diff options
author | Jerome Brunet <jbrunet@baylibre.com> | 2018-02-12 09:58:41 -0500 |
---|---|---|
committer | Neil Armstrong <narmstrong@baylibre.com> | 2018-03-13 05:04:02 -0400 |
commit | 88a4e1283681e0f07048b2bd867cc81fbbae57cc (patch) | |
tree | 55ded77d44c335f5399ed35c2bb1f2cb24dafd16 | |
parent | c763e61ae8cbc9424e95b23a4d4ad5d2d7a71dcd (diff) |
clk: meson: migrate the audio divider clock to clk_regmap
Rework meson audio divider driver to use clk_regmap and move gxbb
clock using meson_clk_audio_divider to clk_regmap.
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
-rw-r--r-- | drivers/clk/meson/clk-audio-divider.c | 63 | ||||
-rw-r--r-- | drivers/clk/meson/clkc.h | 5 | ||||
-rw-r--r-- | drivers/clk/meson/gxbb.c | 30 |
3 files changed, 30 insertions, 68 deletions
diff --git a/drivers/clk/meson/clk-audio-divider.c b/drivers/clk/meson/clk-audio-divider.c index 6c07db06642d..f7ab5b1db342 100644 --- a/drivers/clk/meson/clk-audio-divider.c +++ b/drivers/clk/meson/clk-audio-divider.c | |||
@@ -28,8 +28,11 @@ | |||
28 | #include <linux/clk-provider.h> | 28 | #include <linux/clk-provider.h> |
29 | #include "clkc.h" | 29 | #include "clkc.h" |
30 | 30 | ||
31 | #define to_meson_clk_audio_divider(_hw) container_of(_hw, \ | 31 | static inline struct meson_clk_audio_div_data * |
32 | struct meson_clk_audio_divider, hw) | 32 | meson_clk_audio_div_data(struct clk_regmap *clk) |
33 | { | ||
34 | return (struct meson_clk_audio_div_data *)clk->data; | ||
35 | } | ||
33 | 36 | ||
34 | static int _div_round(unsigned long parent_rate, unsigned long rate, | 37 | static int _div_round(unsigned long parent_rate, unsigned long rate, |
35 | unsigned long flags) | 38 | unsigned long flags) |
@@ -45,15 +48,9 @@ static int _get_val(unsigned long parent_rate, unsigned long rate) | |||
45 | return DIV_ROUND_UP_ULL((u64)parent_rate, rate) - 1; | 48 | return DIV_ROUND_UP_ULL((u64)parent_rate, rate) - 1; |
46 | } | 49 | } |
47 | 50 | ||
48 | static int _valid_divider(struct clk_hw *hw, int divider) | 51 | static int _valid_divider(unsigned int width, int divider) |
49 | { | 52 | { |
50 | struct meson_clk_audio_divider *adiv = | 53 | int max_divider = 1 << width; |
51 | to_meson_clk_audio_divider(hw); | ||
52 | int max_divider; | ||
53 | u8 width; | ||
54 | |||
55 | width = adiv->div.width; | ||
56 | max_divider = 1 << width; | ||
57 | 54 | ||
58 | return clamp(divider, 1, max_divider); | 55 | return clamp(divider, 1, max_divider); |
59 | } | 56 | } |
@@ -61,14 +58,11 @@ static int _valid_divider(struct clk_hw *hw, int divider) | |||
61 | static unsigned long audio_divider_recalc_rate(struct clk_hw *hw, | 58 | static unsigned long audio_divider_recalc_rate(struct clk_hw *hw, |
62 | unsigned long parent_rate) | 59 | unsigned long parent_rate) |
63 | { | 60 | { |
64 | struct meson_clk_audio_divider *adiv = | 61 | struct clk_regmap *clk = to_clk_regmap(hw); |
65 | to_meson_clk_audio_divider(hw); | 62 | struct meson_clk_audio_div_data *adiv = meson_clk_audio_div_data(clk); |
66 | struct parm *p; | 63 | unsigned long divider; |
67 | unsigned long reg, divider; | ||
68 | 64 | ||
69 | p = &adiv->div; | 65 | divider = meson_parm_read(clk->map, &adiv->div); |
70 | reg = readl(adiv->base + p->reg_off); | ||
71 | divider = PARM_GET(p->width, p->shift, reg) + 1; | ||
72 | 66 | ||
73 | return DIV_ROUND_UP_ULL((u64)parent_rate, divider); | 67 | return DIV_ROUND_UP_ULL((u64)parent_rate, divider); |
74 | } | 68 | } |
@@ -77,14 +71,14 @@ static long audio_divider_round_rate(struct clk_hw *hw, | |||
77 | unsigned long rate, | 71 | unsigned long rate, |
78 | unsigned long *parent_rate) | 72 | unsigned long *parent_rate) |
79 | { | 73 | { |
80 | struct meson_clk_audio_divider *adiv = | 74 | struct clk_regmap *clk = to_clk_regmap(hw); |
81 | to_meson_clk_audio_divider(hw); | 75 | struct meson_clk_audio_div_data *adiv = meson_clk_audio_div_data(clk); |
82 | unsigned long max_prate; | 76 | unsigned long max_prate; |
83 | int divider; | 77 | int divider; |
84 | 78 | ||
85 | if (!(clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT)) { | 79 | if (!(clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT)) { |
86 | divider = _div_round(*parent_rate, rate, adiv->flags); | 80 | divider = _div_round(*parent_rate, rate, adiv->flags); |
87 | divider = _valid_divider(hw, divider); | 81 | divider = _valid_divider(adiv->div.width, divider); |
88 | return DIV_ROUND_UP_ULL((u64)*parent_rate, divider); | 82 | return DIV_ROUND_UP_ULL((u64)*parent_rate, divider); |
89 | } | 83 | } |
90 | 84 | ||
@@ -93,7 +87,7 @@ static long audio_divider_round_rate(struct clk_hw *hw, | |||
93 | 87 | ||
94 | /* Get the corresponding rounded down divider */ | 88 | /* Get the corresponding rounded down divider */ |
95 | divider = max_prate / rate; | 89 | divider = max_prate / rate; |
96 | divider = _valid_divider(hw, divider); | 90 | divider = _valid_divider(adiv->div.width, divider); |
97 | 91 | ||
98 | /* Get actual rate of the parent */ | 92 | /* Get actual rate of the parent */ |
99 | *parent_rate = clk_hw_round_rate(clk_hw_get_parent(hw), | 93 | *parent_rate = clk_hw_round_rate(clk_hw_get_parent(hw), |
@@ -106,28 +100,11 @@ static int audio_divider_set_rate(struct clk_hw *hw, | |||
106 | unsigned long rate, | 100 | unsigned long rate, |
107 | unsigned long parent_rate) | 101 | unsigned long parent_rate) |
108 | { | 102 | { |
109 | struct meson_clk_audio_divider *adiv = | 103 | struct clk_regmap *clk = to_clk_regmap(hw); |
110 | to_meson_clk_audio_divider(hw); | 104 | struct meson_clk_audio_div_data *adiv = meson_clk_audio_div_data(clk); |
111 | struct parm *p; | 105 | int val = _get_val(parent_rate, rate); |
112 | unsigned long reg, flags = 0; | 106 | |
113 | int val; | 107 | meson_parm_write(clk->map, &adiv->div, val); |
114 | |||
115 | val = _get_val(parent_rate, rate); | ||
116 | |||
117 | if (adiv->lock) | ||
118 | spin_lock_irqsave(adiv->lock, flags); | ||
119 | else | ||
120 | __acquire(adiv->lock); | ||
121 | |||
122 | p = &adiv->div; | ||
123 | reg = readl(adiv->base + p->reg_off); | ||
124 | reg = PARM_SET(p->width, p->shift, reg, val); | ||
125 | writel(reg, adiv->base + p->reg_off); | ||
126 | |||
127 | if (adiv->lock) | ||
128 | spin_unlock_irqrestore(adiv->lock, flags); | ||
129 | else | ||
130 | __release(adiv->lock); | ||
131 | 108 | ||
132 | return 0; | 109 | return 0; |
133 | } | 110 | } |
diff --git a/drivers/clk/meson/clkc.h b/drivers/clk/meson/clkc.h index 08a1ebfc65dc..a4a526cbca4c 100644 --- a/drivers/clk/meson/clkc.h +++ b/drivers/clk/meson/clkc.h | |||
@@ -142,12 +142,9 @@ struct meson_clk_mpll_data { | |||
142 | spinlock_t *lock; | 142 | spinlock_t *lock; |
143 | }; | 143 | }; |
144 | 144 | ||
145 | struct meson_clk_audio_divider { | 145 | struct meson_clk_audio_div_data { |
146 | struct clk_hw hw; | ||
147 | void __iomem *base; | ||
148 | struct parm div; | 146 | struct parm div; |
149 | u8 flags; | 147 | u8 flags; |
150 | spinlock_t *lock; | ||
151 | }; | 148 | }; |
152 | 149 | ||
153 | #define MESON_GATE(_name, _reg, _bit) \ | 150 | #define MESON_GATE(_name, _reg, _bit) \ |
diff --git a/drivers/clk/meson/gxbb.c b/drivers/clk/meson/gxbb.c index d2724a7ce9e7..196557f11608 100644 --- a/drivers/clk/meson/gxbb.c +++ b/drivers/clk/meson/gxbb.c | |||
@@ -826,14 +826,15 @@ static struct clk_regmap gxbb_cts_amclk_sel = { | |||
826 | }, | 826 | }, |
827 | }; | 827 | }; |
828 | 828 | ||
829 | static struct meson_clk_audio_divider gxbb_cts_amclk_div = { | 829 | static struct clk_regmap gxbb_cts_amclk_div = { |
830 | .div = { | 830 | .data = &(struct meson_clk_audio_div_data){ |
831 | .reg_off = HHI_AUD_CLK_CNTL, | 831 | .div = { |
832 | .shift = 0, | 832 | .reg_off = HHI_AUD_CLK_CNTL, |
833 | .width = 8, | 833 | .shift = 0, |
834 | .width = 8, | ||
835 | }, | ||
836 | .flags = CLK_DIVIDER_ROUND_CLOSEST, | ||
834 | }, | 837 | }, |
835 | .flags = CLK_DIVIDER_ROUND_CLOSEST, | ||
836 | .lock = &meson_clk_lock, | ||
837 | .hw.init = &(struct clk_init_data){ | 838 | .hw.init = &(struct clk_init_data){ |
838 | .name = "cts_amclk_div", | 839 | .name = "cts_amclk_div", |
839 | .ops = &meson_clk_audio_divider_ops, | 840 | .ops = &meson_clk_audio_divider_ops, |
@@ -1777,10 +1778,6 @@ static struct meson_clk_pll *const gxl_clk_plls[] = { | |||
1777 | &gxl_gp0_pll, | 1778 | &gxl_gp0_pll, |
1778 | }; | 1779 | }; |
1779 | 1780 | ||
1780 | static struct meson_clk_audio_divider *const gxbb_audio_dividers[] = { | ||
1781 | &gxbb_cts_amclk_div, | ||
1782 | }; | ||
1783 | |||
1784 | static struct clk_regmap *const gx_clk_regmaps[] = { | 1781 | static struct clk_regmap *const gx_clk_regmaps[] = { |
1785 | &gxbb_clk81, | 1782 | &gxbb_clk81, |
1786 | &gxbb_ddr, | 1783 | &gxbb_ddr, |
@@ -1912,29 +1909,24 @@ static struct clk_regmap *const gx_clk_regmaps[] = { | |||
1912 | &gxbb_mpll0, | 1909 | &gxbb_mpll0, |
1913 | &gxbb_mpll1, | 1910 | &gxbb_mpll1, |
1914 | &gxbb_mpll2, | 1911 | &gxbb_mpll2, |
1912 | &gxbb_cts_amclk_div, | ||
1915 | }; | 1913 | }; |
1916 | 1914 | ||
1917 | struct clkc_data { | 1915 | struct clkc_data { |
1918 | struct meson_clk_pll *const *clk_plls; | 1916 | struct meson_clk_pll *const *clk_plls; |
1919 | unsigned int clk_plls_count; | 1917 | unsigned int clk_plls_count; |
1920 | struct meson_clk_audio_divider *const *clk_audio_dividers; | ||
1921 | unsigned int clk_audio_dividers_count; | ||
1922 | struct clk_hw_onecell_data *hw_onecell_data; | 1918 | struct clk_hw_onecell_data *hw_onecell_data; |
1923 | }; | 1919 | }; |
1924 | 1920 | ||
1925 | static const struct clkc_data gxbb_clkc_data = { | 1921 | static const struct clkc_data gxbb_clkc_data = { |
1926 | .clk_plls = gxbb_clk_plls, | 1922 | .clk_plls = gxbb_clk_plls, |
1927 | .clk_plls_count = ARRAY_SIZE(gxbb_clk_plls), | 1923 | .clk_plls_count = ARRAY_SIZE(gxbb_clk_plls), |
1928 | .clk_audio_dividers = gxbb_audio_dividers, | ||
1929 | .clk_audio_dividers_count = ARRAY_SIZE(gxbb_audio_dividers), | ||
1930 | .hw_onecell_data = &gxbb_hw_onecell_data, | 1924 | .hw_onecell_data = &gxbb_hw_onecell_data, |
1931 | }; | 1925 | }; |
1932 | 1926 | ||
1933 | static const struct clkc_data gxl_clkc_data = { | 1927 | static const struct clkc_data gxl_clkc_data = { |
1934 | .clk_plls = gxl_clk_plls, | 1928 | .clk_plls = gxl_clk_plls, |
1935 | .clk_plls_count = ARRAY_SIZE(gxl_clk_plls), | 1929 | .clk_plls_count = ARRAY_SIZE(gxl_clk_plls), |
1936 | .clk_audio_dividers = gxbb_audio_dividers, | ||
1937 | .clk_audio_dividers_count = ARRAY_SIZE(gxbb_audio_dividers), | ||
1938 | .hw_onecell_data = &gxl_hw_onecell_data, | 1930 | .hw_onecell_data = &gxl_hw_onecell_data, |
1939 | }; | 1931 | }; |
1940 | 1932 | ||
@@ -1981,10 +1973,6 @@ static int gxbb_clkc_probe(struct platform_device *pdev) | |||
1981 | for (i = 0; i < clkc_data->clk_plls_count; i++) | 1973 | for (i = 0; i < clkc_data->clk_plls_count; i++) |
1982 | clkc_data->clk_plls[i]->base = clk_base; | 1974 | clkc_data->clk_plls[i]->base = clk_base; |
1983 | 1975 | ||
1984 | /* Populate base address for the audio dividers */ | ||
1985 | for (i = 0; i < clkc_data->clk_audio_dividers_count; i++) | ||
1986 | clkc_data->clk_audio_dividers[i]->base = clk_base; | ||
1987 | |||
1988 | /* Populate regmap for the common regmap backed clocks */ | 1976 | /* Populate regmap for the common regmap backed clocks */ |
1989 | for (i = 0; i < ARRAY_SIZE(gx_clk_regmaps); i++) | 1977 | for (i = 0; i < ARRAY_SIZE(gx_clk_regmaps); i++) |
1990 | gx_clk_regmaps[i]->map = map; | 1978 | gx_clk_regmaps[i]->map = map; |