unsigned int div_num;
unsigned int div_min;
unsigned int div_max;
+ unsigned int cur_div_idx;
};
/* SDn divider
static int cpg_sd_clock_enable(struct clk_hw *hw)
{
struct sd_clock *clock = to_sd_clock(hw);
- u32 val, sd_fc;
- unsigned int i;
-
- val = readl(clock->reg);
-
- sd_fc = val & CPG_SD_FC_MASK;
- for (i = 0; i < clock->div_num; i++)
- if (sd_fc == (clock->div_table[i].val & CPG_SD_FC_MASK))
- break;
-
- if (i >= clock->div_num)
- return -EINVAL;
+ u32 val = readl(clock->reg);
val &= ~(CPG_SD_STP_MASK);
- val |= clock->div_table[i].val & CPG_SD_STP_MASK;
+ val |= clock->div_table[clock->cur_div_idx].val & CPG_SD_STP_MASK;
writel(val, clock->reg);
unsigned long parent_rate)
{
struct sd_clock *clock = to_sd_clock(hw);
- u32 val, sd_fc;
- unsigned int i;
-
- val = readl(clock->reg);
-
- sd_fc = val & CPG_SD_FC_MASK;
- for (i = 0; i < clock->div_num; i++)
- if (sd_fc == (clock->div_table[i].val & CPG_SD_FC_MASK))
- break;
-
- if (i >= clock->div_num)
- return -EINVAL;
- return DIV_ROUND_CLOSEST(parent_rate, clock->div_table[i].div);
+ return DIV_ROUND_CLOSEST(parent_rate,
+ clock->div_table[clock->cur_div_idx].div);
}
static unsigned int cpg_sd_clock_calc_div(struct sd_clock *clock,
if (i >= clock->div_num)
return -EINVAL;
+ clock->cur_div_idx = i;
+
val = readl(clock->reg);
val &= ~(CPG_SD_STP_MASK | CPG_SD_FC_MASK);
val |= clock->div_table[i].val & (CPG_SD_STP_MASK | CPG_SD_FC_MASK);
struct sd_clock *clock;
struct clk *clk;
unsigned int i;
+ u32 sd_fc;
clock = kzalloc(sizeof(*clock), GFP_KERNEL);
if (!clock)
clock->div_table = cpg_sd_div_table;
clock->div_num = ARRAY_SIZE(cpg_sd_div_table);
+ sd_fc = readl(clock->reg) & CPG_SD_FC_MASK;
+ for (i = 0; i < clock->div_num; i++)
+ if (sd_fc == (clock->div_table[i].val & CPG_SD_FC_MASK))
+ break;
+
+ if (WARN_ON(i >= clock->div_num)) {
+ kfree(clock);
+ return ERR_PTR(-EINVAL);
+ }
+
+ clock->cur_div_idx = i;
+
clock->div_max = clock->div_table[0].div;
clock->div_min = clock->div_max;
for (i = 1; i < clock->div_num; i++) {