Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

clk: divider: add CLK_DIVIDER_HIWORD_MASK flag

In both Hisilicon & Rockchip Cortex-A9 based chips, they don't use the
paradigm of reading-changing-writing the register contents.
Instead they use a hiword mask to indicate the changed bits.

When b01 should be set as setting divider, it also needs to indicate
the change by setting hiword mask (b11 << 16).

The patch adds divider flag for this usage.

Signed-off-by: Heiko Stuebner <heiko@sntech.de>
Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
Signed-off-by: Mike Turquette <mturquette@linaro.org>

authored by

Haojian Zhuang and committed by
Mike Turquette
d57dfe75 ba492e90

+18 -2
+13 -2
drivers/clk/clk-divider.c
··· 227 227 if (divider->lock) 228 228 spin_lock_irqsave(divider->lock, flags); 229 229 230 - val = readl(divider->reg); 231 - val &= ~(div_mask(divider) << divider->shift); 230 + if (divider->flags & CLK_DIVIDER_HIWORD_MASK) { 231 + val = div_mask(divider) << (divider->shift + 16); 232 + } else { 233 + val = readl(divider->reg); 234 + val &= ~(div_mask(divider) << divider->shift); 235 + } 232 236 val |= value << divider->shift; 233 237 writel(val, divider->reg); 234 238 ··· 258 254 struct clk_divider *div; 259 255 struct clk *clk; 260 256 struct clk_init_data init; 257 + 258 + if (clk_divider_flags & CLK_DIVIDER_HIWORD_MASK) { 259 + if (width + shift > 16) { 260 + pr_warn("divider value exceeds LOWORD field\n"); 261 + return ERR_PTR(-EINVAL); 262 + } 263 + } 261 264 262 265 /* allocate the divider */ 263 266 div = kzalloc(sizeof(struct clk_divider), GFP_KERNEL);
+5
include/linux/clk-provider.h
··· 257 257 * Some hardware implementations gracefully handle this case and allow a 258 258 * zero divisor by not modifying their input clock 259 259 * (divide by one / bypass). 260 + * CLK_DIVIDER_HIWORD_MASK - The divider settings are only in lower 16-bit 261 + * of this register, and mask of divider bits are in higher 16-bit of this 262 + * register. While setting the divider bits, higher 16-bit should also be 263 + * updated to indicate changing divider bits. 260 264 */ 261 265 struct clk_divider { 262 266 struct clk_hw hw; ··· 275 271 #define CLK_DIVIDER_ONE_BASED BIT(0) 276 272 #define CLK_DIVIDER_POWER_OF_TWO BIT(1) 277 273 #define CLK_DIVIDER_ALLOW_ZERO BIT(2) 274 + #define CLK_DIVIDER_HIWORD_MASK BIT(3) 278 275 279 276 extern const struct clk_ops clk_divider_ops; 280 277 struct clk *clk_register_divider(struct device *dev, const char *name,