diff options
Diffstat (limited to 'drivers/clk/bcm/clk-kona.c')
-rw-r--r-- | drivers/clk/bcm/clk-kona.c | 64 |
1 files changed, 33 insertions, 31 deletions
diff --git a/drivers/clk/bcm/clk-kona.c b/drivers/clk/bcm/clk-kona.c index e3d339e08309..db11a87449f2 100644 --- a/drivers/clk/bcm/clk-kona.c +++ b/drivers/clk/bcm/clk-kona.c | |||
@@ -61,7 +61,7 @@ u64 do_div_round_closest(u64 dividend, unsigned long divisor) | |||
61 | /* Convert a divider into the scaled divisor value it represents. */ | 61 | /* Convert a divider into the scaled divisor value it represents. */ |
62 | static inline u64 scaled_div_value(struct bcm_clk_div *div, u32 reg_div) | 62 | static inline u64 scaled_div_value(struct bcm_clk_div *div, u32 reg_div) |
63 | { | 63 | { |
64 | return (u64)reg_div + ((u64)1 << div->frac_width); | 64 | return (u64)reg_div + ((u64)1 << div->u.s.frac_width); |
65 | } | 65 | } |
66 | 66 | ||
67 | /* | 67 | /* |
@@ -77,7 +77,7 @@ u64 scaled_div_build(struct bcm_clk_div *div, u32 div_value, u32 billionths) | |||
77 | BUG_ON(billionths >= BILLION); | 77 | BUG_ON(billionths >= BILLION); |
78 | 78 | ||
79 | combined = (u64)div_value * BILLION + billionths; | 79 | combined = (u64)div_value * BILLION + billionths; |
80 | combined <<= div->frac_width; | 80 | combined <<= div->u.s.frac_width; |
81 | 81 | ||
82 | return do_div_round_closest(combined, BILLION); | 82 | return do_div_round_closest(combined, BILLION); |
83 | } | 83 | } |
@@ -87,7 +87,7 @@ static inline u64 | |||
87 | scaled_div_min(struct bcm_clk_div *div) | 87 | scaled_div_min(struct bcm_clk_div *div) |
88 | { | 88 | { |
89 | if (divider_is_fixed(div)) | 89 | if (divider_is_fixed(div)) |
90 | return (u64)div->fixed; | 90 | return (u64)div->u.fixed; |
91 | 91 | ||
92 | return scaled_div_value(div, 0); | 92 | return scaled_div_value(div, 0); |
93 | } | 93 | } |
@@ -98,9 +98,9 @@ u64 scaled_div_max(struct bcm_clk_div *div) | |||
98 | u32 reg_div; | 98 | u32 reg_div; |
99 | 99 | ||
100 | if (divider_is_fixed(div)) | 100 | if (divider_is_fixed(div)) |
101 | return (u64)div->fixed; | 101 | return (u64)div->u.fixed; |
102 | 102 | ||
103 | reg_div = ((u32)1 << div->width) - 1; | 103 | reg_div = ((u32)1 << div->u.s.width) - 1; |
104 | 104 | ||
105 | return scaled_div_value(div, reg_div); | 105 | return scaled_div_value(div, reg_div); |
106 | } | 106 | } |
@@ -115,7 +115,7 @@ divider(struct bcm_clk_div *div, u64 scaled_div) | |||
115 | BUG_ON(scaled_div < scaled_div_min(div)); | 115 | BUG_ON(scaled_div < scaled_div_min(div)); |
116 | BUG_ON(scaled_div > scaled_div_max(div)); | 116 | BUG_ON(scaled_div > scaled_div_max(div)); |
117 | 117 | ||
118 | return (u32)(scaled_div - ((u64)1 << div->frac_width)); | 118 | return (u32)(scaled_div - ((u64)1 << div->u.s.frac_width)); |
119 | } | 119 | } |
120 | 120 | ||
121 | /* Return a rate scaled for use when dividing by a scaled divisor. */ | 121 | /* Return a rate scaled for use when dividing by a scaled divisor. */ |
@@ -125,7 +125,7 @@ scale_rate(struct bcm_clk_div *div, u32 rate) | |||
125 | if (divider_is_fixed(div)) | 125 | if (divider_is_fixed(div)) |
126 | return (u64)rate; | 126 | return (u64)rate; |
127 | 127 | ||
128 | return (u64)rate << div->frac_width; | 128 | return (u64)rate << div->u.s.frac_width; |
129 | } | 129 | } |
130 | 130 | ||
131 | /* CCU access */ | 131 | /* CCU access */ |
@@ -398,14 +398,14 @@ static u64 divider_read_scaled(struct ccu_data *ccu, struct bcm_clk_div *div) | |||
398 | u32 reg_div; | 398 | u32 reg_div; |
399 | 399 | ||
400 | if (divider_is_fixed(div)) | 400 | if (divider_is_fixed(div)) |
401 | return (u64)div->fixed; | 401 | return (u64)div->u.fixed; |
402 | 402 | ||
403 | flags = ccu_lock(ccu); | 403 | flags = ccu_lock(ccu); |
404 | reg_val = __ccu_read(ccu, div->offset); | 404 | reg_val = __ccu_read(ccu, div->u.s.offset); |
405 | ccu_unlock(ccu, flags); | 405 | ccu_unlock(ccu, flags); |
406 | 406 | ||
407 | /* Extract the full divider field from the register value */ | 407 | /* Extract the full divider field from the register value */ |
408 | reg_div = bitfield_extract(reg_val, div->shift, div->width); | 408 | reg_div = bitfield_extract(reg_val, div->u.s.shift, div->u.s.width); |
409 | 409 | ||
410 | /* Return the scaled divisor value it represents */ | 410 | /* Return the scaled divisor value it represents */ |
411 | return scaled_div_value(div, reg_div); | 411 | return scaled_div_value(div, reg_div); |
@@ -433,16 +433,17 @@ static int __div_commit(struct ccu_data *ccu, struct bcm_clk_gate *gate, | |||
433 | * state was defined in the device tree, we just find out | 433 | * state was defined in the device tree, we just find out |
434 | * what its current value is rather than updating it. | 434 | * what its current value is rather than updating it. |
435 | */ | 435 | */ |
436 | if (div->scaled_div == BAD_SCALED_DIV_VALUE) { | 436 | if (div->u.s.scaled_div == BAD_SCALED_DIV_VALUE) { |
437 | reg_val = __ccu_read(ccu, div->offset); | 437 | reg_val = __ccu_read(ccu, div->u.s.offset); |
438 | reg_div = bitfield_extract(reg_val, div->shift, div->width); | 438 | reg_div = bitfield_extract(reg_val, div->u.s.shift, |
439 | div->scaled_div = scaled_div_value(div, reg_div); | 439 | div->u.s.width); |
440 | div->u.s.scaled_div = scaled_div_value(div, reg_div); | ||
440 | 441 | ||
441 | return 0; | 442 | return 0; |
442 | } | 443 | } |
443 | 444 | ||
444 | /* Convert the scaled divisor to the value we need to record */ | 445 | /* Convert the scaled divisor to the value we need to record */ |
445 | reg_div = divider(div, div->scaled_div); | 446 | reg_div = divider(div, div->u.s.scaled_div); |
446 | 447 | ||
447 | /* Clock needs to be enabled before changing the rate */ | 448 | /* Clock needs to be enabled before changing the rate */ |
448 | enabled = __is_clk_gate_enabled(ccu, gate); | 449 | enabled = __is_clk_gate_enabled(ccu, gate); |
@@ -452,9 +453,10 @@ static int __div_commit(struct ccu_data *ccu, struct bcm_clk_gate *gate, | |||
452 | } | 453 | } |
453 | 454 | ||
454 | /* Replace the divider value and record the result */ | 455 | /* Replace the divider value and record the result */ |
455 | reg_val = __ccu_read(ccu, div->offset); | 456 | reg_val = __ccu_read(ccu, div->u.s.offset); |
456 | reg_val = bitfield_replace(reg_val, div->shift, div->width, reg_div); | 457 | reg_val = bitfield_replace(reg_val, div->u.s.shift, div->u.s.width, |
457 | __ccu_write(ccu, div->offset, reg_val); | 458 | reg_div); |
459 | __ccu_write(ccu, div->u.s.offset, reg_val); | ||
458 | 460 | ||
459 | /* If the trigger fails we still want to disable the gate */ | 461 | /* If the trigger fails we still want to disable the gate */ |
460 | if (!__clk_trigger(ccu, trig)) | 462 | if (!__clk_trigger(ccu, trig)) |
@@ -490,11 +492,11 @@ static int divider_write(struct ccu_data *ccu, struct bcm_clk_gate *gate, | |||
490 | 492 | ||
491 | BUG_ON(divider_is_fixed(div)); | 493 | BUG_ON(divider_is_fixed(div)); |
492 | 494 | ||
493 | previous = div->scaled_div; | 495 | previous = div->u.s.scaled_div; |
494 | if (previous == scaled_div) | 496 | if (previous == scaled_div) |
495 | return 0; /* No change */ | 497 | return 0; /* No change */ |
496 | 498 | ||
497 | div->scaled_div = scaled_div; | 499 | div->u.s.scaled_div = scaled_div; |
498 | 500 | ||
499 | flags = ccu_lock(ccu); | 501 | flags = ccu_lock(ccu); |
500 | __ccu_write_enable(ccu); | 502 | __ccu_write_enable(ccu); |
@@ -505,7 +507,7 @@ static int divider_write(struct ccu_data *ccu, struct bcm_clk_gate *gate, | |||
505 | ccu_unlock(ccu, flags); | 507 | ccu_unlock(ccu, flags); |
506 | 508 | ||
507 | if (ret) | 509 | if (ret) |
508 | div->scaled_div = previous; /* Revert the change */ | 510 | div->u.s.scaled_div = previous; /* Revert the change */ |
509 | 511 | ||
510 | return ret; | 512 | return ret; |
511 | 513 | ||
@@ -802,7 +804,7 @@ static int selector_write(struct ccu_data *ccu, struct bcm_clk_gate *gate, | |||
802 | static int kona_peri_clk_enable(struct clk_hw *hw) | 804 | static int kona_peri_clk_enable(struct clk_hw *hw) |
803 | { | 805 | { |
804 | struct kona_clk *bcm_clk = to_kona_clk(hw); | 806 | struct kona_clk *bcm_clk = to_kona_clk(hw); |
805 | struct bcm_clk_gate *gate = &bcm_clk->peri->gate; | 807 | struct bcm_clk_gate *gate = &bcm_clk->u.peri->gate; |
806 | 808 | ||
807 | return clk_gate(bcm_clk->ccu, bcm_clk->name, gate, true); | 809 | return clk_gate(bcm_clk->ccu, bcm_clk->name, gate, true); |
808 | } | 810 | } |
@@ -810,7 +812,7 @@ static int kona_peri_clk_enable(struct clk_hw *hw) | |||
810 | static void kona_peri_clk_disable(struct clk_hw *hw) | 812 | static void kona_peri_clk_disable(struct clk_hw *hw) |
811 | { | 813 | { |
812 | struct kona_clk *bcm_clk = to_kona_clk(hw); | 814 | struct kona_clk *bcm_clk = to_kona_clk(hw); |
813 | struct bcm_clk_gate *gate = &bcm_clk->peri->gate; | 815 | struct bcm_clk_gate *gate = &bcm_clk->u.peri->gate; |
814 | 816 | ||
815 | (void)clk_gate(bcm_clk->ccu, bcm_clk->name, gate, false); | 817 | (void)clk_gate(bcm_clk->ccu, bcm_clk->name, gate, false); |
816 | } | 818 | } |
@@ -818,7 +820,7 @@ static void kona_peri_clk_disable(struct clk_hw *hw) | |||
818 | static int kona_peri_clk_is_enabled(struct clk_hw *hw) | 820 | static int kona_peri_clk_is_enabled(struct clk_hw *hw) |
819 | { | 821 | { |
820 | struct kona_clk *bcm_clk = to_kona_clk(hw); | 822 | struct kona_clk *bcm_clk = to_kona_clk(hw); |
821 | struct bcm_clk_gate *gate = &bcm_clk->peri->gate; | 823 | struct bcm_clk_gate *gate = &bcm_clk->u.peri->gate; |
822 | 824 | ||
823 | return is_clk_gate_enabled(bcm_clk->ccu, gate) ? 1 : 0; | 825 | return is_clk_gate_enabled(bcm_clk->ccu, gate) ? 1 : 0; |
824 | } | 826 | } |
@@ -827,7 +829,7 @@ static unsigned long kona_peri_clk_recalc_rate(struct clk_hw *hw, | |||
827 | unsigned long parent_rate) | 829 | unsigned long parent_rate) |
828 | { | 830 | { |
829 | struct kona_clk *bcm_clk = to_kona_clk(hw); | 831 | struct kona_clk *bcm_clk = to_kona_clk(hw); |
830 | struct peri_clk_data *data = bcm_clk->peri; | 832 | struct peri_clk_data *data = bcm_clk->u.peri; |
831 | 833 | ||
832 | return clk_recalc_rate(bcm_clk->ccu, &data->div, &data->pre_div, | 834 | return clk_recalc_rate(bcm_clk->ccu, &data->div, &data->pre_div, |
833 | parent_rate); | 835 | parent_rate); |
@@ -837,20 +839,20 @@ static long kona_peri_clk_round_rate(struct clk_hw *hw, unsigned long rate, | |||
837 | unsigned long *parent_rate) | 839 | unsigned long *parent_rate) |
838 | { | 840 | { |
839 | struct kona_clk *bcm_clk = to_kona_clk(hw); | 841 | struct kona_clk *bcm_clk = to_kona_clk(hw); |
840 | struct bcm_clk_div *div = &bcm_clk->peri->div; | 842 | struct bcm_clk_div *div = &bcm_clk->u.peri->div; |
841 | 843 | ||
842 | if (!divider_exists(div)) | 844 | if (!divider_exists(div)) |
843 | return __clk_get_rate(hw->clk); | 845 | return __clk_get_rate(hw->clk); |
844 | 846 | ||
845 | /* Quietly avoid a zero rate */ | 847 | /* Quietly avoid a zero rate */ |
846 | return round_rate(bcm_clk->ccu, div, &bcm_clk->peri->pre_div, | 848 | return round_rate(bcm_clk->ccu, div, &bcm_clk->u.peri->pre_div, |
847 | rate ? rate : 1, *parent_rate, NULL); | 849 | rate ? rate : 1, *parent_rate, NULL); |
848 | } | 850 | } |
849 | 851 | ||
850 | static int kona_peri_clk_set_parent(struct clk_hw *hw, u8 index) | 852 | static int kona_peri_clk_set_parent(struct clk_hw *hw, u8 index) |
851 | { | 853 | { |
852 | struct kona_clk *bcm_clk = to_kona_clk(hw); | 854 | struct kona_clk *bcm_clk = to_kona_clk(hw); |
853 | struct peri_clk_data *data = bcm_clk->peri; | 855 | struct peri_clk_data *data = bcm_clk->u.peri; |
854 | struct bcm_clk_sel *sel = &data->sel; | 856 | struct bcm_clk_sel *sel = &data->sel; |
855 | struct bcm_clk_trig *trig; | 857 | struct bcm_clk_trig *trig; |
856 | int ret; | 858 | int ret; |
@@ -884,7 +886,7 @@ static int kona_peri_clk_set_parent(struct clk_hw *hw, u8 index) | |||
884 | static u8 kona_peri_clk_get_parent(struct clk_hw *hw) | 886 | static u8 kona_peri_clk_get_parent(struct clk_hw *hw) |
885 | { | 887 | { |
886 | struct kona_clk *bcm_clk = to_kona_clk(hw); | 888 | struct kona_clk *bcm_clk = to_kona_clk(hw); |
887 | struct peri_clk_data *data = bcm_clk->peri; | 889 | struct peri_clk_data *data = bcm_clk->u.peri; |
888 | u8 index; | 890 | u8 index; |
889 | 891 | ||
890 | index = selector_read_index(bcm_clk->ccu, &data->sel); | 892 | index = selector_read_index(bcm_clk->ccu, &data->sel); |
@@ -897,7 +899,7 @@ static int kona_peri_clk_set_rate(struct clk_hw *hw, unsigned long rate, | |||
897 | unsigned long parent_rate) | 899 | unsigned long parent_rate) |
898 | { | 900 | { |
899 | struct kona_clk *bcm_clk = to_kona_clk(hw); | 901 | struct kona_clk *bcm_clk = to_kona_clk(hw); |
900 | struct peri_clk_data *data = bcm_clk->peri; | 902 | struct peri_clk_data *data = bcm_clk->u.peri; |
901 | struct bcm_clk_div *div = &data->div; | 903 | struct bcm_clk_div *div = &data->div; |
902 | u64 scaled_div = 0; | 904 | u64 scaled_div = 0; |
903 | int ret; | 905 | int ret; |
@@ -958,7 +960,7 @@ struct clk_ops kona_peri_clk_ops = { | |||
958 | static bool __peri_clk_init(struct kona_clk *bcm_clk) | 960 | static bool __peri_clk_init(struct kona_clk *bcm_clk) |
959 | { | 961 | { |
960 | struct ccu_data *ccu = bcm_clk->ccu; | 962 | struct ccu_data *ccu = bcm_clk->ccu; |
961 | struct peri_clk_data *peri = bcm_clk->peri; | 963 | struct peri_clk_data *peri = bcm_clk->u.peri; |
962 | const char *name = bcm_clk->name; | 964 | const char *name = bcm_clk->name; |
963 | struct bcm_clk_trig *trig; | 965 | struct bcm_clk_trig *trig; |
964 | 966 | ||