Linux driver: clock control
1. bulk control
sample code:
#define MAX_CLK_SOURCES 3
static struct clk_bulk_data clks[MAX_CLK_SOURCES] = {
{"g1_clk",NULL}, {"g2_pclk", NULL}, {"g3_clk", NULL}
};
static struct reset_control *rst_ctrls = NULL;
static void _enable_clock(void)
{
unsigned long flags;
if(is_clk_on)
return;
spin_lock_irqsave(&clk_lock, flags);
do {
// clock
if( 0 != devm_clk_bulk_get(device, MAX_CLK_SOURCES, clks)){
pr_err("enable_clock: devm_clk_bulk_get failed!\n");
break;
}
if ( 0 != clk_bulk_prepare(MAX_CLK_SOURCES, clks)) {
pr_err("enable_clock: clk_bulk_enable error!\n");
break;
}
if( 0 != clk_bulk_enable(MAX_CLK_SOURCES, clks)) {
pr_err("enable_clock: clk_bulk_enable error!\n");
break;
}
// reset
rst_ctrls = devm_reset_control_array_get(device, true, true);
if (PTR_ERR(rst_ctrls) == -EPROBE_DEFER) {
pr_err("enable_clock: devm_reset_control_array_get error!\n");
break;
}
if (0 != reset_control_deassert(rst_ctrls)) {
pr_err("enable_clock: devm_reset_control_array_get error!\n");
break;
}
udelay(1);
is_clk_on = 1;
pr_info(" _enable_clock\n");
}while(0);
spin_unlock_irqrestore(&clk_lock, flags);
}
static void _disable_clock(unsigned long value)
{
if (is_clk_on) {
unsigned long flags;
spin_lock_irqsave(&clk_lock, flags);
// clock
clk_bulk_disable(MAX_CLK_SOURCES, clks);
clk_bulk_unprepare(MAX_CLK_SOURCES, clks);
clk_bulk_put(MAX_CLK_SOURCES, clks);
// reset
if (!IS_ERR(rst_ctrls)) {
reset_control_assert(rst_ctrls);
}
is_clk_on = 0;
spin_unlock_irqrestore(&clk_lock, flags);
pr_info("disable_clock\n");
}
}