diff options
Diffstat (limited to 'drivers/clk/ti/divider.c')
-rw-r--r-- | drivers/clk/ti/divider.c | 26 |
1 files changed, 20 insertions, 6 deletions
diff --git a/drivers/clk/ti/divider.c b/drivers/clk/ti/divider.c index 77f93f6d2806..aaa277dd6d99 100644 --- a/drivers/clk/ti/divider.c +++ b/drivers/clk/ti/divider.c | |||
@@ -263,6 +263,8 @@ static int ti_clk_divider_set_rate(struct clk_hw *hw, unsigned long rate, | |||
263 | val |= value << divider->shift; | 263 | val |= value << divider->shift; |
264 | ti_clk_ll_ops->clk_writel(val, ÷r->reg); | 264 | ti_clk_ll_ops->clk_writel(val, ÷r->reg); |
265 | 265 | ||
266 | ti_clk_latch(÷r->reg, divider->latch); | ||
267 | |||
266 | return 0; | 268 | return 0; |
267 | } | 269 | } |
268 | 270 | ||
@@ -276,7 +278,8 @@ static struct clk *_register_divider(struct device *dev, const char *name, | |||
276 | const char *parent_name, | 278 | const char *parent_name, |
277 | unsigned long flags, | 279 | unsigned long flags, |
278 | struct clk_omap_reg *reg, | 280 | struct clk_omap_reg *reg, |
279 | u8 shift, u8 width, u8 clk_divider_flags, | 281 | u8 shift, u8 width, s8 latch, |
282 | u8 clk_divider_flags, | ||
280 | const struct clk_div_table *table) | 283 | const struct clk_div_table *table) |
281 | { | 284 | { |
282 | struct clk_omap_divider *div; | 285 | struct clk_omap_divider *div; |
@@ -305,6 +308,7 @@ static struct clk *_register_divider(struct device *dev, const char *name, | |||
305 | memcpy(&div->reg, reg, sizeof(*reg)); | 308 | memcpy(&div->reg, reg, sizeof(*reg)); |
306 | div->shift = shift; | 309 | div->shift = shift; |
307 | div->width = width; | 310 | div->width = width; |
311 | div->latch = latch; | ||
308 | div->flags = clk_divider_flags; | 312 | div->flags = clk_divider_flags; |
309 | div->hw.init = &init; | 313 | div->hw.init = &init; |
310 | div->table = table; | 314 | div->table = table; |
@@ -420,6 +424,7 @@ struct clk_hw *ti_clk_build_component_div(struct ti_clk_divider *setup) | |||
420 | div->table = _get_div_table_from_setup(setup, &div->width); | 424 | div->table = _get_div_table_from_setup(setup, &div->width); |
421 | 425 | ||
422 | div->shift = setup->bit_shift; | 426 | div->shift = setup->bit_shift; |
427 | div->latch = -EINVAL; | ||
423 | 428 | ||
424 | return &div->hw; | 429 | return &div->hw; |
425 | } | 430 | } |
@@ -452,7 +457,7 @@ struct clk *ti_clk_register_divider(struct ti_clk *setup) | |||
452 | 457 | ||
453 | clk = _register_divider(NULL, setup->name, div->parent, | 458 | clk = _register_divider(NULL, setup->name, div->parent, |
454 | flags, ®, div->bit_shift, | 459 | flags, ®, div->bit_shift, |
455 | width, div_flags, table); | 460 | width, -EINVAL, div_flags, table); |
456 | 461 | ||
457 | if (IS_ERR(clk)) | 462 | if (IS_ERR(clk)) |
458 | kfree(table); | 463 | kfree(table); |
@@ -556,7 +561,7 @@ static int _get_divider_width(struct device_node *node, | |||
556 | 561 | ||
557 | static int __init ti_clk_divider_populate(struct device_node *node, | 562 | static int __init ti_clk_divider_populate(struct device_node *node, |
558 | struct clk_omap_reg *reg, const struct clk_div_table **table, | 563 | struct clk_omap_reg *reg, const struct clk_div_table **table, |
559 | u32 *flags, u8 *div_flags, u8 *width, u8 *shift) | 564 | u32 *flags, u8 *div_flags, u8 *width, u8 *shift, s8 *latch) |
560 | { | 565 | { |
561 | u32 val; | 566 | u32 val; |
562 | int ret; | 567 | int ret; |
@@ -570,6 +575,13 @@ static int __init ti_clk_divider_populate(struct device_node *node, | |||
570 | else | 575 | else |
571 | *shift = 0; | 576 | *shift = 0; |
572 | 577 | ||
578 | if (latch) { | ||
579 | if (!of_property_read_u32(node, "ti,latch-bit", &val)) | ||
580 | *latch = val; | ||
581 | else | ||
582 | *latch = -EINVAL; | ||
583 | } | ||
584 | |||
573 | *flags = 0; | 585 | *flags = 0; |
574 | *div_flags = 0; | 586 | *div_flags = 0; |
575 | 587 | ||
@@ -606,17 +618,18 @@ static void __init of_ti_divider_clk_setup(struct device_node *node) | |||
606 | u8 clk_divider_flags = 0; | 618 | u8 clk_divider_flags = 0; |
607 | u8 width = 0; | 619 | u8 width = 0; |
608 | u8 shift = 0; | 620 | u8 shift = 0; |
621 | s8 latch = -EINVAL; | ||
609 | const struct clk_div_table *table = NULL; | 622 | const struct clk_div_table *table = NULL; |
610 | u32 flags = 0; | 623 | u32 flags = 0; |
611 | 624 | ||
612 | parent_name = of_clk_get_parent_name(node, 0); | 625 | parent_name = of_clk_get_parent_name(node, 0); |
613 | 626 | ||
614 | if (ti_clk_divider_populate(node, ®, &table, &flags, | 627 | if (ti_clk_divider_populate(node, ®, &table, &flags, |
615 | &clk_divider_flags, &width, &shift)) | 628 | &clk_divider_flags, &width, &shift, &latch)) |
616 | goto cleanup; | 629 | goto cleanup; |
617 | 630 | ||
618 | clk = _register_divider(NULL, node->name, parent_name, flags, ®, | 631 | clk = _register_divider(NULL, node->name, parent_name, flags, ®, |
619 | shift, width, clk_divider_flags, table); | 632 | shift, width, latch, clk_divider_flags, table); |
620 | 633 | ||
621 | if (!IS_ERR(clk)) { | 634 | if (!IS_ERR(clk)) { |
622 | of_clk_add_provider(node, of_clk_src_simple_get, clk); | 635 | of_clk_add_provider(node, of_clk_src_simple_get, clk); |
@@ -639,7 +652,8 @@ static void __init of_ti_composite_divider_clk_setup(struct device_node *node) | |||
639 | return; | 652 | return; |
640 | 653 | ||
641 | if (ti_clk_divider_populate(node, &div->reg, &div->table, &val, | 654 | if (ti_clk_divider_populate(node, &div->reg, &div->table, &val, |
642 | &div->flags, &div->width, &div->shift) < 0) | 655 | &div->flags, &div->width, &div->shift, |
656 | NULL) < 0) | ||
643 | goto cleanup; | 657 | goto cleanup; |
644 | 658 | ||
645 | if (!ti_clk_add_component(node, &div->hw, CLK_COMPONENT_TYPE_DIVIDER)) | 659 | if (!ti_clk_add_component(node, &div->hw, CLK_COMPONENT_TYPE_DIVIDER)) |