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

clk: rockchip: add a factor clock type

Add a clock type for fixed factor clocks. This allows us to define fixed
factor clocks where they appear in the clock hierarchy instead of in the
init function.

The additional factor_gate type, finally allows us to model some last
parts of the clock tree correctly.

Signed-off-by: Heiko Stuebner <heiko@sntech.de>

+83
+55
drivers/clk/rockchip/clk.c
··· 265 265 return clk; 266 266 } 267 267 268 + static struct clk *rockchip_clk_register_factor_branch(const char *name, 269 + const char *const *parent_names, u8 num_parents, 270 + void __iomem *base, unsigned int mult, unsigned int div, 271 + int gate_offset, u8 gate_shift, u8 gate_flags, 272 + unsigned long flags, spinlock_t *lock) 273 + { 274 + struct clk *clk; 275 + struct clk_gate *gate = NULL; 276 + struct clk_fixed_factor *fix = NULL; 277 + 278 + /* without gate, register a simple factor clock */ 279 + if (gate_offset == 0) { 280 + return clk_register_fixed_factor(NULL, name, 281 + parent_names[0], flags, mult, 282 + div); 283 + } 284 + 285 + gate = kzalloc(sizeof(*gate), GFP_KERNEL); 286 + if (!gate) 287 + return ERR_PTR(-ENOMEM); 288 + 289 + gate->flags = gate_flags; 290 + gate->reg = base + gate_offset; 291 + gate->bit_idx = gate_shift; 292 + gate->lock = lock; 293 + 294 + fix = kzalloc(sizeof(*fix), GFP_KERNEL); 295 + if (!fix) { 296 + kfree(gate); 297 + return ERR_PTR(-ENOMEM); 298 + } 299 + 300 + fix->mult = mult; 301 + fix->div = div; 302 + 303 + clk = clk_register_composite(NULL, name, parent_names, num_parents, 304 + NULL, NULL, 305 + &fix->hw, &clk_fixed_factor_ops, 306 + &gate->hw, &clk_gate_ops, flags); 307 + if (IS_ERR(clk)) { 308 + kfree(fix); 309 + kfree(gate); 310 + } 311 + 312 + return clk; 313 + } 314 + 268 315 static DEFINE_SPINLOCK(clk_lock); 269 316 static struct clk **clk_table; 270 317 static void __iomem *reg_base; ··· 446 399 list->num_parents, 447 400 reg_base + list->muxdiv_offset, 448 401 list->div_shift, list->div_flags, &clk_lock); 402 + break; 403 + case branch_factor: 404 + clk = rockchip_clk_register_factor_branch( 405 + list->name, list->parent_names, 406 + list->num_parents, reg_base, 407 + list->div_shift, list->div_width, 408 + list->gate_offset, list->gate_shift, 409 + list->gate_flags, flags, &clk_lock); 449 410 break; 450 411 } 451 412
+28
drivers/clk/rockchip/clk.h
··· 254 254 branch_gate, 255 255 branch_mmc, 256 256 branch_inverter, 257 + branch_factor, 257 258 }; 258 259 259 260 struct rockchip_clk_branch { ··· 507 506 .muxdiv_offset = io, \ 508 507 .div_shift = is, \ 509 508 .div_flags = if, \ 509 + } 510 + 511 + #define FACTOR(_id, cname, pname, f, fm, fd) \ 512 + { \ 513 + .id = _id, \ 514 + .branch_type = branch_factor, \ 515 + .name = cname, \ 516 + .parent_names = (const char *[]){ pname }, \ 517 + .num_parents = 1, \ 518 + .flags = f, \ 519 + .div_shift = fm, \ 520 + .div_width = fd, \ 521 + } 522 + 523 + #define FACTOR_GATE(_id, cname, pname, f, fm, fd, go, gb, gf) \ 524 + { \ 525 + .id = _id, \ 526 + .branch_type = branch_factor, \ 527 + .name = cname, \ 528 + .parent_names = (const char *[]){ pname }, \ 529 + .num_parents = 1, \ 530 + .flags = f, \ 531 + .div_shift = fm, \ 532 + .div_width = fd, \ 533 + .gate_offset = go, \ 534 + .gate_shift = gb, \ 535 + .gate_flags = gf, \ 510 536 } 511 537 512 538 void rockchip_clk_init(struct device_node *np, void __iomem *base,