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

clk: ti: Improve clksel clock bit parsing for reg property

Because of legacy reasons, the TI clksel composite clocks can have
overlapping reg properties, and use a custom ti,bit-shift property.

For the clksel clocks we can start using of the standard reg property
instead of the custom ti,bit-shift property.

To do this, let's add a ti_clk_get_legacy_bit_shift() helper, and make
ti_clk_get_reg_addr() populate the clock bit offset.

This makes it possible to update the devicetree files to use the reg
property one clock at a time.

Acked-by: Stephen Boyd <sboyd@kernel.org>
Signed-off-by: Tony Lindgren <tony@atomide.com>

+63 -33
+3 -8
drivers/clk/ti/apll.c
··· 376 376 } 377 377 clk_hw->fixed_rate = val; 378 378 379 - if (of_property_read_u32(node, "ti,bit-shift", &val)) { 380 - pr_err("%pOFn missing bit-shift\n", node); 381 - goto cleanup; 382 - } 383 - 384 - clk_hw->enable_bit = val; 385 - ad->enable_mask = 0x3 << val; 386 - ad->autoidle_mask = 0x3 << val; 379 + clk_hw->enable_bit = ti_clk_get_legacy_bit_shift(node); 380 + ad->enable_mask = 0x3 << clk_hw->enable_bit; 381 + ad->autoidle_mask = 0x3 << clk_hw->enable_bit; 387 382 388 383 if (of_property_read_u32(node, "ti,idlest-shift", &val)) { 389 384 pr_err("%pOFn missing idlest-shift\n", node);
+50 -7
drivers/clk/ti/clk.c
··· 16 16 #include <linux/of.h> 17 17 #include <linux/of_address.h> 18 18 #include <linux/list.h> 19 + #include <linux/minmax.h> 19 20 #include <linux/regmap.h> 20 21 #include <linux/string_helpers.h> 21 22 #include <linux/memblock.h> ··· 308 307 int ti_clk_get_reg_addr(struct device_node *node, int index, 309 308 struct clk_omap_reg *reg) 310 309 { 311 - u32 val; 312 - int i; 310 + u32 clksel_addr, val; 311 + bool is_clksel = false; 312 + int i, err; 313 313 314 314 for (i = 0; i < CLK_MAX_MEMMAPS; i++) { 315 315 if (clocks_node_ptr[i] == node->parent) ··· 326 324 327 325 reg->index = i; 328 326 329 - if (of_property_read_u32_index(node, "reg", index, &val)) { 330 - if (of_property_read_u32_index(node->parent, "reg", 331 - index, &val)) { 332 - pr_err("%pOFn or parent must have reg[%d]!\n", 333 - node, index); 327 + if (of_device_is_compatible(node->parent, "ti,clksel")) { 328 + err = of_property_read_u32_index(node->parent, "reg", index, &clksel_addr); 329 + if (err) { 330 + pr_err("%pOFn parent clksel must have reg[%d]!\n", node, index); 334 331 return -EINVAL; 335 332 } 333 + is_clksel = true; 336 334 } 337 335 336 + err = of_property_read_u32_index(node, "reg", index, &val); 337 + if (err && is_clksel) { 338 + /* Legacy clksel with no reg and a possible ti,bit-shift property */ 339 + reg->offset = clksel_addr; 340 + reg->bit = ti_clk_get_legacy_bit_shift(node); 341 + reg->ptr = NULL; 342 + 343 + return 0; 344 + } 345 + 346 + /* Updated clksel clock with a proper reg property */ 347 + if (is_clksel) { 348 + reg->offset = clksel_addr; 349 + reg->bit = val; 350 + reg->ptr = NULL; 351 + return 0; 352 + } 353 + 354 + /* Other clocks that may or may not have ti,bit-shift property */ 338 355 reg->offset = val; 356 + reg->bit = ti_clk_get_legacy_bit_shift(node); 339 357 reg->ptr = NULL; 358 + 359 + return 0; 360 + } 361 + 362 + /** 363 + * ti_clk_get_legacy_bit_shift - get bit shift for a clock register 364 + * @node: device node for the clock 365 + * 366 + * Gets the clock register bit shift using the legacy ti,bit-shift 367 + * property. Only needed for legacy clock, and can be eventually 368 + * dropped once all the composite clocks use a clksel node with a 369 + * proper reg property. 370 + */ 371 + int ti_clk_get_legacy_bit_shift(struct device_node *node) 372 + { 373 + int err; 374 + u32 val; 375 + 376 + err = of_property_read_u32(node, "ti,bit-shift", &val); 377 + if (!err && in_range(val, 0, 32)) 378 + return val; 340 379 341 380 return 0; 342 381 }
+1
drivers/clk/ti/clock.h
··· 216 216 217 217 int ti_clk_get_reg_addr(struct device_node *node, int index, 218 218 struct clk_omap_reg *reg); 219 + int ti_clk_get_legacy_bit_shift(struct device_node *node); 219 220 void ti_dt_clocks_register(struct ti_dt_clk *oclks); 220 221 int ti_clk_retry_init(struct device_node *node, void *user, 221 222 ti_of_clk_init_cb_t func);
+1 -4
drivers/clk/ti/divider.c
··· 477 477 if (ret) 478 478 return ret; 479 479 480 - if (!of_property_read_u32(node, "ti,bit-shift", &val)) 481 - div->shift = val; 482 - else 483 - div->shift = 0; 480 + div->shift = div->reg.bit; 484 481 485 482 if (!of_property_read_u32(node, "ti,latch-bit", &val)) 486 483 div->latch = val;
+2 -7
drivers/clk/ti/gate.c
··· 132 132 struct clk_omap_reg reg; 133 133 const char *name; 134 134 u8 enable_bit = 0; 135 - u32 val; 136 135 u32 flags = 0; 137 136 u8 clk_gate_flags = 0; 138 137 ··· 139 140 if (ti_clk_get_reg_addr(node, 0, &reg)) 140 141 return; 141 142 142 - if (!of_property_read_u32(node, "ti,bit-shift", &val)) 143 - enable_bit = val; 143 + enable_bit = reg.bit; 144 144 } 145 145 146 146 if (of_clk_get_parent_count(node) != 1) { ··· 168 170 const struct clk_hw_omap_ops *hw_ops) 169 171 { 170 172 struct clk_hw_omap *gate; 171 - u32 val = 0; 172 173 173 174 gate = kzalloc(sizeof(*gate), GFP_KERNEL); 174 175 if (!gate) ··· 176 179 if (ti_clk_get_reg_addr(node, 0, &gate->enable_reg)) 177 180 goto cleanup; 178 181 179 - of_property_read_u32(node, "ti,bit-shift", &val); 180 - 181 - gate->enable_bit = val; 182 + gate->enable_bit = gate->enable_reg.bit; 182 183 gate->ops = hw_ops; 183 184 184 185 if (!ti_clk_add_component(node, &gate->hw, CLK_COMPONENT_TYPE_GATE))
+1 -3
drivers/clk/ti/interface.c
··· 66 66 struct clk_omap_reg reg; 67 67 u8 enable_bit = 0; 68 68 const char *name; 69 - u32 val; 70 69 71 70 if (ti_clk_get_reg_addr(node, 0, &reg)) 72 71 return; 73 72 74 - if (!of_property_read_u32(node, "ti,bit-shift", &val)) 75 - enable_bit = val; 73 + enable_bit = reg.bit; 76 74 77 75 parent_name = of_clk_get_parent_name(node, 0); 78 76 if (!parent_name) {
+2 -4
drivers/clk/ti/mux.c
··· 189 189 if (ti_clk_get_reg_addr(node, 0, &reg)) 190 190 goto cleanup; 191 191 192 - of_property_read_u32(node, "ti,bit-shift", &shift); 192 + shift = reg.bit; 193 193 194 194 of_property_read_u32(node, "ti,latch-bit", &latch); 195 195 ··· 252 252 { 253 253 struct clk_omap_mux *mux; 254 254 unsigned int num_parents; 255 - u32 val; 256 255 257 256 mux = kzalloc(sizeof(*mux), GFP_KERNEL); 258 257 if (!mux) ··· 260 261 if (ti_clk_get_reg_addr(node, 0, &mux->reg)) 261 262 goto cleanup; 262 263 263 - if (!of_property_read_u32(node, "ti,bit-shift", &val)) 264 - mux->shift = val; 264 + mux->shift = mux->reg.bit; 265 265 266 266 if (of_property_read_bool(node, "ti,index-starts-at-one")) 267 267 mux->flags |= CLK_MUX_INDEX_ONE;
+3
include/linux/clk/ti.h
··· 13 13 /** 14 14 * struct clk_omap_reg - OMAP register declaration 15 15 * @offset: offset from the master IP module base address 16 + * @bit: register bit offset 16 17 * @index: index of the master IP module 18 + * @flags: flags 17 19 */ 18 20 struct clk_omap_reg { 19 21 void __iomem *ptr; 20 22 u16 offset; 23 + u8 bit; 21 24 u8 index; 22 25 u8 flags; 23 26 };