1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Clock driver for DA8xx/AM17xx/AM18xx/OMAP-L13x CFGCHIP
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Copyright (C) 2018 David Lechner <david@lechnology.com>
6*4882a593Smuzhiyun */
7*4882a593Smuzhiyun
8*4882a593Smuzhiyun #include <linux/clk-provider.h>
9*4882a593Smuzhiyun #include <linux/clk.h>
10*4882a593Smuzhiyun #include <linux/clkdev.h>
11*4882a593Smuzhiyun #include <linux/init.h>
12*4882a593Smuzhiyun #include <linux/mfd/da8xx-cfgchip.h>
13*4882a593Smuzhiyun #include <linux/mfd/syscon.h>
14*4882a593Smuzhiyun #include <linux/of_device.h>
15*4882a593Smuzhiyun #include <linux/of.h>
16*4882a593Smuzhiyun #include <linux/platform_data/clk-da8xx-cfgchip.h>
17*4882a593Smuzhiyun #include <linux/platform_device.h>
18*4882a593Smuzhiyun #include <linux/regmap.h>
19*4882a593Smuzhiyun #include <linux/slab.h>
20*4882a593Smuzhiyun
21*4882a593Smuzhiyun /* --- Gate clocks --- */
22*4882a593Smuzhiyun
23*4882a593Smuzhiyun #define DA8XX_GATE_CLOCK_IS_DIV4P5 BIT(1)
24*4882a593Smuzhiyun
25*4882a593Smuzhiyun struct da8xx_cfgchip_gate_clk_info {
26*4882a593Smuzhiyun const char *name;
27*4882a593Smuzhiyun u32 cfgchip;
28*4882a593Smuzhiyun u32 bit;
29*4882a593Smuzhiyun u32 flags;
30*4882a593Smuzhiyun };
31*4882a593Smuzhiyun
32*4882a593Smuzhiyun struct da8xx_cfgchip_gate_clk {
33*4882a593Smuzhiyun struct clk_hw hw;
34*4882a593Smuzhiyun struct regmap *regmap;
35*4882a593Smuzhiyun u32 reg;
36*4882a593Smuzhiyun u32 mask;
37*4882a593Smuzhiyun };
38*4882a593Smuzhiyun
39*4882a593Smuzhiyun #define to_da8xx_cfgchip_gate_clk(_hw) \
40*4882a593Smuzhiyun container_of((_hw), struct da8xx_cfgchip_gate_clk, hw)
41*4882a593Smuzhiyun
da8xx_cfgchip_gate_clk_enable(struct clk_hw * hw)42*4882a593Smuzhiyun static int da8xx_cfgchip_gate_clk_enable(struct clk_hw *hw)
43*4882a593Smuzhiyun {
44*4882a593Smuzhiyun struct da8xx_cfgchip_gate_clk *clk = to_da8xx_cfgchip_gate_clk(hw);
45*4882a593Smuzhiyun
46*4882a593Smuzhiyun return regmap_write_bits(clk->regmap, clk->reg, clk->mask, clk->mask);
47*4882a593Smuzhiyun }
48*4882a593Smuzhiyun
da8xx_cfgchip_gate_clk_disable(struct clk_hw * hw)49*4882a593Smuzhiyun static void da8xx_cfgchip_gate_clk_disable(struct clk_hw *hw)
50*4882a593Smuzhiyun {
51*4882a593Smuzhiyun struct da8xx_cfgchip_gate_clk *clk = to_da8xx_cfgchip_gate_clk(hw);
52*4882a593Smuzhiyun
53*4882a593Smuzhiyun regmap_write_bits(clk->regmap, clk->reg, clk->mask, 0);
54*4882a593Smuzhiyun }
55*4882a593Smuzhiyun
da8xx_cfgchip_gate_clk_is_enabled(struct clk_hw * hw)56*4882a593Smuzhiyun static int da8xx_cfgchip_gate_clk_is_enabled(struct clk_hw *hw)
57*4882a593Smuzhiyun {
58*4882a593Smuzhiyun struct da8xx_cfgchip_gate_clk *clk = to_da8xx_cfgchip_gate_clk(hw);
59*4882a593Smuzhiyun unsigned int val;
60*4882a593Smuzhiyun
61*4882a593Smuzhiyun regmap_read(clk->regmap, clk->reg, &val);
62*4882a593Smuzhiyun
63*4882a593Smuzhiyun return !!(val & clk->mask);
64*4882a593Smuzhiyun }
65*4882a593Smuzhiyun
da8xx_cfgchip_div4p5_recalc_rate(struct clk_hw * hw,unsigned long parent_rate)66*4882a593Smuzhiyun static unsigned long da8xx_cfgchip_div4p5_recalc_rate(struct clk_hw *hw,
67*4882a593Smuzhiyun unsigned long parent_rate)
68*4882a593Smuzhiyun {
69*4882a593Smuzhiyun /* this clock divides by 4.5 */
70*4882a593Smuzhiyun return parent_rate * 2 / 9;
71*4882a593Smuzhiyun }
72*4882a593Smuzhiyun
73*4882a593Smuzhiyun static const struct clk_ops da8xx_cfgchip_gate_clk_ops = {
74*4882a593Smuzhiyun .enable = da8xx_cfgchip_gate_clk_enable,
75*4882a593Smuzhiyun .disable = da8xx_cfgchip_gate_clk_disable,
76*4882a593Smuzhiyun .is_enabled = da8xx_cfgchip_gate_clk_is_enabled,
77*4882a593Smuzhiyun };
78*4882a593Smuzhiyun
79*4882a593Smuzhiyun static const struct clk_ops da8xx_cfgchip_div4p5_clk_ops = {
80*4882a593Smuzhiyun .enable = da8xx_cfgchip_gate_clk_enable,
81*4882a593Smuzhiyun .disable = da8xx_cfgchip_gate_clk_disable,
82*4882a593Smuzhiyun .is_enabled = da8xx_cfgchip_gate_clk_is_enabled,
83*4882a593Smuzhiyun .recalc_rate = da8xx_cfgchip_div4p5_recalc_rate,
84*4882a593Smuzhiyun };
85*4882a593Smuzhiyun
86*4882a593Smuzhiyun static struct da8xx_cfgchip_gate_clk * __init
da8xx_cfgchip_gate_clk_register(struct device * dev,const struct da8xx_cfgchip_gate_clk_info * info,struct regmap * regmap)87*4882a593Smuzhiyun da8xx_cfgchip_gate_clk_register(struct device *dev,
88*4882a593Smuzhiyun const struct da8xx_cfgchip_gate_clk_info *info,
89*4882a593Smuzhiyun struct regmap *regmap)
90*4882a593Smuzhiyun {
91*4882a593Smuzhiyun struct clk *parent;
92*4882a593Smuzhiyun const char *parent_name;
93*4882a593Smuzhiyun struct da8xx_cfgchip_gate_clk *gate;
94*4882a593Smuzhiyun struct clk_init_data init;
95*4882a593Smuzhiyun int ret;
96*4882a593Smuzhiyun
97*4882a593Smuzhiyun parent = devm_clk_get(dev, NULL);
98*4882a593Smuzhiyun if (IS_ERR(parent))
99*4882a593Smuzhiyun return ERR_CAST(parent);
100*4882a593Smuzhiyun
101*4882a593Smuzhiyun parent_name = __clk_get_name(parent);
102*4882a593Smuzhiyun
103*4882a593Smuzhiyun gate = devm_kzalloc(dev, sizeof(*gate), GFP_KERNEL);
104*4882a593Smuzhiyun if (!gate)
105*4882a593Smuzhiyun return ERR_PTR(-ENOMEM);
106*4882a593Smuzhiyun
107*4882a593Smuzhiyun init.name = info->name;
108*4882a593Smuzhiyun if (info->flags & DA8XX_GATE_CLOCK_IS_DIV4P5)
109*4882a593Smuzhiyun init.ops = &da8xx_cfgchip_div4p5_clk_ops;
110*4882a593Smuzhiyun else
111*4882a593Smuzhiyun init.ops = &da8xx_cfgchip_gate_clk_ops;
112*4882a593Smuzhiyun init.parent_names = &parent_name;
113*4882a593Smuzhiyun init.num_parents = 1;
114*4882a593Smuzhiyun init.flags = 0;
115*4882a593Smuzhiyun
116*4882a593Smuzhiyun gate->hw.init = &init;
117*4882a593Smuzhiyun gate->regmap = regmap;
118*4882a593Smuzhiyun gate->reg = info->cfgchip;
119*4882a593Smuzhiyun gate->mask = info->bit;
120*4882a593Smuzhiyun
121*4882a593Smuzhiyun ret = devm_clk_hw_register(dev, &gate->hw);
122*4882a593Smuzhiyun if (ret < 0)
123*4882a593Smuzhiyun return ERR_PTR(ret);
124*4882a593Smuzhiyun
125*4882a593Smuzhiyun return gate;
126*4882a593Smuzhiyun }
127*4882a593Smuzhiyun
128*4882a593Smuzhiyun static const struct da8xx_cfgchip_gate_clk_info da8xx_tbclksync_info __initconst = {
129*4882a593Smuzhiyun .name = "ehrpwm_tbclk",
130*4882a593Smuzhiyun .cfgchip = CFGCHIP(1),
131*4882a593Smuzhiyun .bit = CFGCHIP1_TBCLKSYNC,
132*4882a593Smuzhiyun };
133*4882a593Smuzhiyun
da8xx_cfgchip_register_tbclk(struct device * dev,struct regmap * regmap)134*4882a593Smuzhiyun static int __init da8xx_cfgchip_register_tbclk(struct device *dev,
135*4882a593Smuzhiyun struct regmap *regmap)
136*4882a593Smuzhiyun {
137*4882a593Smuzhiyun struct da8xx_cfgchip_gate_clk *gate;
138*4882a593Smuzhiyun
139*4882a593Smuzhiyun gate = da8xx_cfgchip_gate_clk_register(dev, &da8xx_tbclksync_info,
140*4882a593Smuzhiyun regmap);
141*4882a593Smuzhiyun if (IS_ERR(gate))
142*4882a593Smuzhiyun return PTR_ERR(gate);
143*4882a593Smuzhiyun
144*4882a593Smuzhiyun clk_hw_register_clkdev(&gate->hw, "tbclk", "ehrpwm.0");
145*4882a593Smuzhiyun clk_hw_register_clkdev(&gate->hw, "tbclk", "ehrpwm.1");
146*4882a593Smuzhiyun
147*4882a593Smuzhiyun return 0;
148*4882a593Smuzhiyun }
149*4882a593Smuzhiyun
150*4882a593Smuzhiyun static const struct da8xx_cfgchip_gate_clk_info da8xx_div4p5ena_info __initconst = {
151*4882a593Smuzhiyun .name = "div4.5",
152*4882a593Smuzhiyun .cfgchip = CFGCHIP(3),
153*4882a593Smuzhiyun .bit = CFGCHIP3_DIV45PENA,
154*4882a593Smuzhiyun .flags = DA8XX_GATE_CLOCK_IS_DIV4P5,
155*4882a593Smuzhiyun };
156*4882a593Smuzhiyun
da8xx_cfgchip_register_div4p5(struct device * dev,struct regmap * regmap)157*4882a593Smuzhiyun static int __init da8xx_cfgchip_register_div4p5(struct device *dev,
158*4882a593Smuzhiyun struct regmap *regmap)
159*4882a593Smuzhiyun {
160*4882a593Smuzhiyun struct da8xx_cfgchip_gate_clk *gate;
161*4882a593Smuzhiyun
162*4882a593Smuzhiyun gate = da8xx_cfgchip_gate_clk_register(dev, &da8xx_div4p5ena_info, regmap);
163*4882a593Smuzhiyun
164*4882a593Smuzhiyun return PTR_ERR_OR_ZERO(gate);
165*4882a593Smuzhiyun }
166*4882a593Smuzhiyun
167*4882a593Smuzhiyun static int __init
of_da8xx_cfgchip_gate_clk_init(struct device * dev,const struct da8xx_cfgchip_gate_clk_info * info,struct regmap * regmap)168*4882a593Smuzhiyun of_da8xx_cfgchip_gate_clk_init(struct device *dev,
169*4882a593Smuzhiyun const struct da8xx_cfgchip_gate_clk_info *info,
170*4882a593Smuzhiyun struct regmap *regmap)
171*4882a593Smuzhiyun {
172*4882a593Smuzhiyun struct da8xx_cfgchip_gate_clk *gate;
173*4882a593Smuzhiyun
174*4882a593Smuzhiyun gate = da8xx_cfgchip_gate_clk_register(dev, info, regmap);
175*4882a593Smuzhiyun if (IS_ERR(gate))
176*4882a593Smuzhiyun return PTR_ERR(gate);
177*4882a593Smuzhiyun
178*4882a593Smuzhiyun return devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, gate);
179*4882a593Smuzhiyun }
180*4882a593Smuzhiyun
of_da8xx_tbclksync_init(struct device * dev,struct regmap * regmap)181*4882a593Smuzhiyun static int __init of_da8xx_tbclksync_init(struct device *dev,
182*4882a593Smuzhiyun struct regmap *regmap)
183*4882a593Smuzhiyun {
184*4882a593Smuzhiyun return of_da8xx_cfgchip_gate_clk_init(dev, &da8xx_tbclksync_info, regmap);
185*4882a593Smuzhiyun }
186*4882a593Smuzhiyun
of_da8xx_div4p5ena_init(struct device * dev,struct regmap * regmap)187*4882a593Smuzhiyun static int __init of_da8xx_div4p5ena_init(struct device *dev,
188*4882a593Smuzhiyun struct regmap *regmap)
189*4882a593Smuzhiyun {
190*4882a593Smuzhiyun return of_da8xx_cfgchip_gate_clk_init(dev, &da8xx_div4p5ena_info, regmap);
191*4882a593Smuzhiyun }
192*4882a593Smuzhiyun
193*4882a593Smuzhiyun /* --- MUX clocks --- */
194*4882a593Smuzhiyun
195*4882a593Smuzhiyun struct da8xx_cfgchip_mux_clk_info {
196*4882a593Smuzhiyun const char *name;
197*4882a593Smuzhiyun const char *parent0;
198*4882a593Smuzhiyun const char *parent1;
199*4882a593Smuzhiyun u32 cfgchip;
200*4882a593Smuzhiyun u32 bit;
201*4882a593Smuzhiyun };
202*4882a593Smuzhiyun
203*4882a593Smuzhiyun struct da8xx_cfgchip_mux_clk {
204*4882a593Smuzhiyun struct clk_hw hw;
205*4882a593Smuzhiyun struct regmap *regmap;
206*4882a593Smuzhiyun u32 reg;
207*4882a593Smuzhiyun u32 mask;
208*4882a593Smuzhiyun };
209*4882a593Smuzhiyun
210*4882a593Smuzhiyun #define to_da8xx_cfgchip_mux_clk(_hw) \
211*4882a593Smuzhiyun container_of((_hw), struct da8xx_cfgchip_mux_clk, hw)
212*4882a593Smuzhiyun
da8xx_cfgchip_mux_clk_set_parent(struct clk_hw * hw,u8 index)213*4882a593Smuzhiyun static int da8xx_cfgchip_mux_clk_set_parent(struct clk_hw *hw, u8 index)
214*4882a593Smuzhiyun {
215*4882a593Smuzhiyun struct da8xx_cfgchip_mux_clk *clk = to_da8xx_cfgchip_mux_clk(hw);
216*4882a593Smuzhiyun unsigned int val = index ? clk->mask : 0;
217*4882a593Smuzhiyun
218*4882a593Smuzhiyun return regmap_write_bits(clk->regmap, clk->reg, clk->mask, val);
219*4882a593Smuzhiyun }
220*4882a593Smuzhiyun
da8xx_cfgchip_mux_clk_get_parent(struct clk_hw * hw)221*4882a593Smuzhiyun static u8 da8xx_cfgchip_mux_clk_get_parent(struct clk_hw *hw)
222*4882a593Smuzhiyun {
223*4882a593Smuzhiyun struct da8xx_cfgchip_mux_clk *clk = to_da8xx_cfgchip_mux_clk(hw);
224*4882a593Smuzhiyun unsigned int val;
225*4882a593Smuzhiyun
226*4882a593Smuzhiyun regmap_read(clk->regmap, clk->reg, &val);
227*4882a593Smuzhiyun
228*4882a593Smuzhiyun return (val & clk->mask) ? 1 : 0;
229*4882a593Smuzhiyun }
230*4882a593Smuzhiyun
231*4882a593Smuzhiyun static const struct clk_ops da8xx_cfgchip_mux_clk_ops = {
232*4882a593Smuzhiyun .set_parent = da8xx_cfgchip_mux_clk_set_parent,
233*4882a593Smuzhiyun .get_parent = da8xx_cfgchip_mux_clk_get_parent,
234*4882a593Smuzhiyun };
235*4882a593Smuzhiyun
236*4882a593Smuzhiyun static struct da8xx_cfgchip_mux_clk * __init
da8xx_cfgchip_mux_clk_register(struct device * dev,const struct da8xx_cfgchip_mux_clk_info * info,struct regmap * regmap)237*4882a593Smuzhiyun da8xx_cfgchip_mux_clk_register(struct device *dev,
238*4882a593Smuzhiyun const struct da8xx_cfgchip_mux_clk_info *info,
239*4882a593Smuzhiyun struct regmap *regmap)
240*4882a593Smuzhiyun {
241*4882a593Smuzhiyun const char * const parent_names[] = { info->parent0, info->parent1 };
242*4882a593Smuzhiyun struct da8xx_cfgchip_mux_clk *mux;
243*4882a593Smuzhiyun struct clk_init_data init;
244*4882a593Smuzhiyun int ret;
245*4882a593Smuzhiyun
246*4882a593Smuzhiyun mux = devm_kzalloc(dev, sizeof(*mux), GFP_KERNEL);
247*4882a593Smuzhiyun if (!mux)
248*4882a593Smuzhiyun return ERR_PTR(-ENOMEM);
249*4882a593Smuzhiyun
250*4882a593Smuzhiyun init.name = info->name;
251*4882a593Smuzhiyun init.ops = &da8xx_cfgchip_mux_clk_ops;
252*4882a593Smuzhiyun init.parent_names = parent_names;
253*4882a593Smuzhiyun init.num_parents = 2;
254*4882a593Smuzhiyun init.flags = 0;
255*4882a593Smuzhiyun
256*4882a593Smuzhiyun mux->hw.init = &init;
257*4882a593Smuzhiyun mux->regmap = regmap;
258*4882a593Smuzhiyun mux->reg = info->cfgchip;
259*4882a593Smuzhiyun mux->mask = info->bit;
260*4882a593Smuzhiyun
261*4882a593Smuzhiyun ret = devm_clk_hw_register(dev, &mux->hw);
262*4882a593Smuzhiyun if (ret < 0)
263*4882a593Smuzhiyun return ERR_PTR(ret);
264*4882a593Smuzhiyun
265*4882a593Smuzhiyun return mux;
266*4882a593Smuzhiyun }
267*4882a593Smuzhiyun
268*4882a593Smuzhiyun static const struct da8xx_cfgchip_mux_clk_info da850_async1_info __initconst = {
269*4882a593Smuzhiyun .name = "async1",
270*4882a593Smuzhiyun .parent0 = "pll0_sysclk3",
271*4882a593Smuzhiyun .parent1 = "div4.5",
272*4882a593Smuzhiyun .cfgchip = CFGCHIP(3),
273*4882a593Smuzhiyun .bit = CFGCHIP3_EMA_CLKSRC,
274*4882a593Smuzhiyun };
275*4882a593Smuzhiyun
da8xx_cfgchip_register_async1(struct device * dev,struct regmap * regmap)276*4882a593Smuzhiyun static int __init da8xx_cfgchip_register_async1(struct device *dev,
277*4882a593Smuzhiyun struct regmap *regmap)
278*4882a593Smuzhiyun {
279*4882a593Smuzhiyun struct da8xx_cfgchip_mux_clk *mux;
280*4882a593Smuzhiyun
281*4882a593Smuzhiyun mux = da8xx_cfgchip_mux_clk_register(dev, &da850_async1_info, regmap);
282*4882a593Smuzhiyun if (IS_ERR(mux))
283*4882a593Smuzhiyun return PTR_ERR(mux);
284*4882a593Smuzhiyun
285*4882a593Smuzhiyun clk_hw_register_clkdev(&mux->hw, "async1", "da850-psc0");
286*4882a593Smuzhiyun
287*4882a593Smuzhiyun return 0;
288*4882a593Smuzhiyun }
289*4882a593Smuzhiyun
290*4882a593Smuzhiyun static const struct da8xx_cfgchip_mux_clk_info da850_async3_info __initconst = {
291*4882a593Smuzhiyun .name = "async3",
292*4882a593Smuzhiyun .parent0 = "pll0_sysclk2",
293*4882a593Smuzhiyun .parent1 = "pll1_sysclk2",
294*4882a593Smuzhiyun .cfgchip = CFGCHIP(3),
295*4882a593Smuzhiyun .bit = CFGCHIP3_ASYNC3_CLKSRC,
296*4882a593Smuzhiyun };
297*4882a593Smuzhiyun
da850_cfgchip_register_async3(struct device * dev,struct regmap * regmap)298*4882a593Smuzhiyun static int __init da850_cfgchip_register_async3(struct device *dev,
299*4882a593Smuzhiyun struct regmap *regmap)
300*4882a593Smuzhiyun {
301*4882a593Smuzhiyun struct da8xx_cfgchip_mux_clk *mux;
302*4882a593Smuzhiyun struct clk_hw *parent;
303*4882a593Smuzhiyun
304*4882a593Smuzhiyun mux = da8xx_cfgchip_mux_clk_register(dev, &da850_async3_info, regmap);
305*4882a593Smuzhiyun if (IS_ERR(mux))
306*4882a593Smuzhiyun return PTR_ERR(mux);
307*4882a593Smuzhiyun
308*4882a593Smuzhiyun clk_hw_register_clkdev(&mux->hw, "async3", "da850-psc1");
309*4882a593Smuzhiyun
310*4882a593Smuzhiyun /* pll1_sysclk2 is not affected by CPU scaling, so use it for async3 */
311*4882a593Smuzhiyun parent = clk_hw_get_parent_by_index(&mux->hw, 1);
312*4882a593Smuzhiyun if (parent)
313*4882a593Smuzhiyun clk_set_parent(mux->hw.clk, parent->clk);
314*4882a593Smuzhiyun else
315*4882a593Smuzhiyun dev_warn(dev, "Failed to find async3 parent clock\n");
316*4882a593Smuzhiyun
317*4882a593Smuzhiyun return 0;
318*4882a593Smuzhiyun }
319*4882a593Smuzhiyun
320*4882a593Smuzhiyun static int __init
of_da8xx_cfgchip_init_mux_clock(struct device * dev,const struct da8xx_cfgchip_mux_clk_info * info,struct regmap * regmap)321*4882a593Smuzhiyun of_da8xx_cfgchip_init_mux_clock(struct device *dev,
322*4882a593Smuzhiyun const struct da8xx_cfgchip_mux_clk_info *info,
323*4882a593Smuzhiyun struct regmap *regmap)
324*4882a593Smuzhiyun {
325*4882a593Smuzhiyun struct da8xx_cfgchip_mux_clk *mux;
326*4882a593Smuzhiyun
327*4882a593Smuzhiyun mux = da8xx_cfgchip_mux_clk_register(dev, info, regmap);
328*4882a593Smuzhiyun if (IS_ERR(mux))
329*4882a593Smuzhiyun return PTR_ERR(mux);
330*4882a593Smuzhiyun
331*4882a593Smuzhiyun return devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, &mux->hw);
332*4882a593Smuzhiyun }
333*4882a593Smuzhiyun
of_da850_async1_init(struct device * dev,struct regmap * regmap)334*4882a593Smuzhiyun static int __init of_da850_async1_init(struct device *dev, struct regmap *regmap)
335*4882a593Smuzhiyun {
336*4882a593Smuzhiyun return of_da8xx_cfgchip_init_mux_clock(dev, &da850_async1_info, regmap);
337*4882a593Smuzhiyun }
338*4882a593Smuzhiyun
of_da850_async3_init(struct device * dev,struct regmap * regmap)339*4882a593Smuzhiyun static int __init of_da850_async3_init(struct device *dev, struct regmap *regmap)
340*4882a593Smuzhiyun {
341*4882a593Smuzhiyun return of_da8xx_cfgchip_init_mux_clock(dev, &da850_async3_info, regmap);
342*4882a593Smuzhiyun }
343*4882a593Smuzhiyun
344*4882a593Smuzhiyun /* --- USB 2.0 PHY clock --- */
345*4882a593Smuzhiyun
346*4882a593Smuzhiyun struct da8xx_usb0_clk48 {
347*4882a593Smuzhiyun struct clk_hw hw;
348*4882a593Smuzhiyun struct clk *fck;
349*4882a593Smuzhiyun struct regmap *regmap;
350*4882a593Smuzhiyun };
351*4882a593Smuzhiyun
352*4882a593Smuzhiyun #define to_da8xx_usb0_clk48(_hw) \
353*4882a593Smuzhiyun container_of((_hw), struct da8xx_usb0_clk48, hw)
354*4882a593Smuzhiyun
da8xx_usb0_clk48_prepare(struct clk_hw * hw)355*4882a593Smuzhiyun static int da8xx_usb0_clk48_prepare(struct clk_hw *hw)
356*4882a593Smuzhiyun {
357*4882a593Smuzhiyun struct da8xx_usb0_clk48 *usb0 = to_da8xx_usb0_clk48(hw);
358*4882a593Smuzhiyun
359*4882a593Smuzhiyun /* The USB 2.0 PSC clock is only needed temporarily during the USB 2.0
360*4882a593Smuzhiyun * PHY clock enable, but since clk_prepare() can't be called in an
361*4882a593Smuzhiyun * atomic context (i.e. in clk_enable()), we have to prepare it here.
362*4882a593Smuzhiyun */
363*4882a593Smuzhiyun return clk_prepare(usb0->fck);
364*4882a593Smuzhiyun }
365*4882a593Smuzhiyun
da8xx_usb0_clk48_unprepare(struct clk_hw * hw)366*4882a593Smuzhiyun static void da8xx_usb0_clk48_unprepare(struct clk_hw *hw)
367*4882a593Smuzhiyun {
368*4882a593Smuzhiyun struct da8xx_usb0_clk48 *usb0 = to_da8xx_usb0_clk48(hw);
369*4882a593Smuzhiyun
370*4882a593Smuzhiyun clk_unprepare(usb0->fck);
371*4882a593Smuzhiyun }
372*4882a593Smuzhiyun
da8xx_usb0_clk48_enable(struct clk_hw * hw)373*4882a593Smuzhiyun static int da8xx_usb0_clk48_enable(struct clk_hw *hw)
374*4882a593Smuzhiyun {
375*4882a593Smuzhiyun struct da8xx_usb0_clk48 *usb0 = to_da8xx_usb0_clk48(hw);
376*4882a593Smuzhiyun unsigned int mask, val;
377*4882a593Smuzhiyun int ret;
378*4882a593Smuzhiyun
379*4882a593Smuzhiyun /* Locking the USB 2.O PLL requires that the USB 2.O PSC is enabled
380*4882a593Smuzhiyun * temporaily. It can be turned back off once the PLL is locked.
381*4882a593Smuzhiyun */
382*4882a593Smuzhiyun clk_enable(usb0->fck);
383*4882a593Smuzhiyun
384*4882a593Smuzhiyun /* Turn on the USB 2.0 PHY, but just the PLL, and not OTG. The USB 1.1
385*4882a593Smuzhiyun * PHY may use the USB 2.0 PLL clock without USB 2.0 OTG being used.
386*4882a593Smuzhiyun */
387*4882a593Smuzhiyun mask = CFGCHIP2_RESET | CFGCHIP2_PHYPWRDN | CFGCHIP2_PHY_PLLON;
388*4882a593Smuzhiyun val = CFGCHIP2_PHY_PLLON;
389*4882a593Smuzhiyun
390*4882a593Smuzhiyun regmap_write_bits(usb0->regmap, CFGCHIP(2), mask, val);
391*4882a593Smuzhiyun ret = regmap_read_poll_timeout(usb0->regmap, CFGCHIP(2), val,
392*4882a593Smuzhiyun val & CFGCHIP2_PHYCLKGD, 0, 500000);
393*4882a593Smuzhiyun
394*4882a593Smuzhiyun clk_disable(usb0->fck);
395*4882a593Smuzhiyun
396*4882a593Smuzhiyun return ret;
397*4882a593Smuzhiyun }
398*4882a593Smuzhiyun
da8xx_usb0_clk48_disable(struct clk_hw * hw)399*4882a593Smuzhiyun static void da8xx_usb0_clk48_disable(struct clk_hw *hw)
400*4882a593Smuzhiyun {
401*4882a593Smuzhiyun struct da8xx_usb0_clk48 *usb0 = to_da8xx_usb0_clk48(hw);
402*4882a593Smuzhiyun unsigned int val;
403*4882a593Smuzhiyun
404*4882a593Smuzhiyun val = CFGCHIP2_PHYPWRDN;
405*4882a593Smuzhiyun regmap_write_bits(usb0->regmap, CFGCHIP(2), val, val);
406*4882a593Smuzhiyun }
407*4882a593Smuzhiyun
da8xx_usb0_clk48_is_enabled(struct clk_hw * hw)408*4882a593Smuzhiyun static int da8xx_usb0_clk48_is_enabled(struct clk_hw *hw)
409*4882a593Smuzhiyun {
410*4882a593Smuzhiyun struct da8xx_usb0_clk48 *usb0 = to_da8xx_usb0_clk48(hw);
411*4882a593Smuzhiyun unsigned int val;
412*4882a593Smuzhiyun
413*4882a593Smuzhiyun regmap_read(usb0->regmap, CFGCHIP(2), &val);
414*4882a593Smuzhiyun
415*4882a593Smuzhiyun return !!(val & CFGCHIP2_PHYCLKGD);
416*4882a593Smuzhiyun }
417*4882a593Smuzhiyun
da8xx_usb0_clk48_recalc_rate(struct clk_hw * hw,unsigned long parent_rate)418*4882a593Smuzhiyun static unsigned long da8xx_usb0_clk48_recalc_rate(struct clk_hw *hw,
419*4882a593Smuzhiyun unsigned long parent_rate)
420*4882a593Smuzhiyun {
421*4882a593Smuzhiyun struct da8xx_usb0_clk48 *usb0 = to_da8xx_usb0_clk48(hw);
422*4882a593Smuzhiyun unsigned int mask, val;
423*4882a593Smuzhiyun
424*4882a593Smuzhiyun /* The parent clock rate must be one of the following */
425*4882a593Smuzhiyun mask = CFGCHIP2_REFFREQ_MASK;
426*4882a593Smuzhiyun switch (parent_rate) {
427*4882a593Smuzhiyun case 12000000:
428*4882a593Smuzhiyun val = CFGCHIP2_REFFREQ_12MHZ;
429*4882a593Smuzhiyun break;
430*4882a593Smuzhiyun case 13000000:
431*4882a593Smuzhiyun val = CFGCHIP2_REFFREQ_13MHZ;
432*4882a593Smuzhiyun break;
433*4882a593Smuzhiyun case 19200000:
434*4882a593Smuzhiyun val = CFGCHIP2_REFFREQ_19_2MHZ;
435*4882a593Smuzhiyun break;
436*4882a593Smuzhiyun case 20000000:
437*4882a593Smuzhiyun val = CFGCHIP2_REFFREQ_20MHZ;
438*4882a593Smuzhiyun break;
439*4882a593Smuzhiyun case 24000000:
440*4882a593Smuzhiyun val = CFGCHIP2_REFFREQ_24MHZ;
441*4882a593Smuzhiyun break;
442*4882a593Smuzhiyun case 26000000:
443*4882a593Smuzhiyun val = CFGCHIP2_REFFREQ_26MHZ;
444*4882a593Smuzhiyun break;
445*4882a593Smuzhiyun case 38400000:
446*4882a593Smuzhiyun val = CFGCHIP2_REFFREQ_38_4MHZ;
447*4882a593Smuzhiyun break;
448*4882a593Smuzhiyun case 40000000:
449*4882a593Smuzhiyun val = CFGCHIP2_REFFREQ_40MHZ;
450*4882a593Smuzhiyun break;
451*4882a593Smuzhiyun case 48000000:
452*4882a593Smuzhiyun val = CFGCHIP2_REFFREQ_48MHZ;
453*4882a593Smuzhiyun break;
454*4882a593Smuzhiyun default:
455*4882a593Smuzhiyun return 0;
456*4882a593Smuzhiyun }
457*4882a593Smuzhiyun
458*4882a593Smuzhiyun regmap_write_bits(usb0->regmap, CFGCHIP(2), mask, val);
459*4882a593Smuzhiyun
460*4882a593Smuzhiyun /* USB 2.0 PLL always supplies 48MHz */
461*4882a593Smuzhiyun return 48000000;
462*4882a593Smuzhiyun }
463*4882a593Smuzhiyun
da8xx_usb0_clk48_round_rate(struct clk_hw * hw,unsigned long rate,unsigned long * parent_rate)464*4882a593Smuzhiyun static long da8xx_usb0_clk48_round_rate(struct clk_hw *hw, unsigned long rate,
465*4882a593Smuzhiyun unsigned long *parent_rate)
466*4882a593Smuzhiyun {
467*4882a593Smuzhiyun return 48000000;
468*4882a593Smuzhiyun }
469*4882a593Smuzhiyun
da8xx_usb0_clk48_set_parent(struct clk_hw * hw,u8 index)470*4882a593Smuzhiyun static int da8xx_usb0_clk48_set_parent(struct clk_hw *hw, u8 index)
471*4882a593Smuzhiyun {
472*4882a593Smuzhiyun struct da8xx_usb0_clk48 *usb0 = to_da8xx_usb0_clk48(hw);
473*4882a593Smuzhiyun
474*4882a593Smuzhiyun return regmap_write_bits(usb0->regmap, CFGCHIP(2),
475*4882a593Smuzhiyun CFGCHIP2_USB2PHYCLKMUX,
476*4882a593Smuzhiyun index ? CFGCHIP2_USB2PHYCLKMUX : 0);
477*4882a593Smuzhiyun }
478*4882a593Smuzhiyun
da8xx_usb0_clk48_get_parent(struct clk_hw * hw)479*4882a593Smuzhiyun static u8 da8xx_usb0_clk48_get_parent(struct clk_hw *hw)
480*4882a593Smuzhiyun {
481*4882a593Smuzhiyun struct da8xx_usb0_clk48 *usb0 = to_da8xx_usb0_clk48(hw);
482*4882a593Smuzhiyun unsigned int val;
483*4882a593Smuzhiyun
484*4882a593Smuzhiyun regmap_read(usb0->regmap, CFGCHIP(2), &val);
485*4882a593Smuzhiyun
486*4882a593Smuzhiyun return (val & CFGCHIP2_USB2PHYCLKMUX) ? 1 : 0;
487*4882a593Smuzhiyun }
488*4882a593Smuzhiyun
489*4882a593Smuzhiyun static const struct clk_ops da8xx_usb0_clk48_ops = {
490*4882a593Smuzhiyun .prepare = da8xx_usb0_clk48_prepare,
491*4882a593Smuzhiyun .unprepare = da8xx_usb0_clk48_unprepare,
492*4882a593Smuzhiyun .enable = da8xx_usb0_clk48_enable,
493*4882a593Smuzhiyun .disable = da8xx_usb0_clk48_disable,
494*4882a593Smuzhiyun .is_enabled = da8xx_usb0_clk48_is_enabled,
495*4882a593Smuzhiyun .recalc_rate = da8xx_usb0_clk48_recalc_rate,
496*4882a593Smuzhiyun .round_rate = da8xx_usb0_clk48_round_rate,
497*4882a593Smuzhiyun .set_parent = da8xx_usb0_clk48_set_parent,
498*4882a593Smuzhiyun .get_parent = da8xx_usb0_clk48_get_parent,
499*4882a593Smuzhiyun };
500*4882a593Smuzhiyun
501*4882a593Smuzhiyun static struct da8xx_usb0_clk48 *
da8xx_cfgchip_register_usb0_clk48(struct device * dev,struct regmap * regmap)502*4882a593Smuzhiyun da8xx_cfgchip_register_usb0_clk48(struct device *dev,
503*4882a593Smuzhiyun struct regmap *regmap)
504*4882a593Smuzhiyun {
505*4882a593Smuzhiyun const char * const parent_names[] = { "usb_refclkin", "pll0_auxclk" };
506*4882a593Smuzhiyun struct clk *fck_clk;
507*4882a593Smuzhiyun struct da8xx_usb0_clk48 *usb0;
508*4882a593Smuzhiyun struct clk_init_data init;
509*4882a593Smuzhiyun int ret;
510*4882a593Smuzhiyun
511*4882a593Smuzhiyun fck_clk = devm_clk_get(dev, "fck");
512*4882a593Smuzhiyun if (IS_ERR(fck_clk)) {
513*4882a593Smuzhiyun if (PTR_ERR(fck_clk) != -EPROBE_DEFER)
514*4882a593Smuzhiyun dev_err(dev, "Missing fck clock\n");
515*4882a593Smuzhiyun return ERR_CAST(fck_clk);
516*4882a593Smuzhiyun }
517*4882a593Smuzhiyun
518*4882a593Smuzhiyun usb0 = devm_kzalloc(dev, sizeof(*usb0), GFP_KERNEL);
519*4882a593Smuzhiyun if (!usb0)
520*4882a593Smuzhiyun return ERR_PTR(-ENOMEM);
521*4882a593Smuzhiyun
522*4882a593Smuzhiyun init.name = "usb0_clk48";
523*4882a593Smuzhiyun init.ops = &da8xx_usb0_clk48_ops;
524*4882a593Smuzhiyun init.parent_names = parent_names;
525*4882a593Smuzhiyun init.num_parents = 2;
526*4882a593Smuzhiyun
527*4882a593Smuzhiyun usb0->hw.init = &init;
528*4882a593Smuzhiyun usb0->fck = fck_clk;
529*4882a593Smuzhiyun usb0->regmap = regmap;
530*4882a593Smuzhiyun
531*4882a593Smuzhiyun ret = devm_clk_hw_register(dev, &usb0->hw);
532*4882a593Smuzhiyun if (ret < 0)
533*4882a593Smuzhiyun return ERR_PTR(ret);
534*4882a593Smuzhiyun
535*4882a593Smuzhiyun return usb0;
536*4882a593Smuzhiyun }
537*4882a593Smuzhiyun
538*4882a593Smuzhiyun /* --- USB 1.1 PHY clock --- */
539*4882a593Smuzhiyun
540*4882a593Smuzhiyun struct da8xx_usb1_clk48 {
541*4882a593Smuzhiyun struct clk_hw hw;
542*4882a593Smuzhiyun struct regmap *regmap;
543*4882a593Smuzhiyun };
544*4882a593Smuzhiyun
545*4882a593Smuzhiyun #define to_da8xx_usb1_clk48(_hw) \
546*4882a593Smuzhiyun container_of((_hw), struct da8xx_usb1_clk48, hw)
547*4882a593Smuzhiyun
da8xx_usb1_clk48_set_parent(struct clk_hw * hw,u8 index)548*4882a593Smuzhiyun static int da8xx_usb1_clk48_set_parent(struct clk_hw *hw, u8 index)
549*4882a593Smuzhiyun {
550*4882a593Smuzhiyun struct da8xx_usb1_clk48 *usb1 = to_da8xx_usb1_clk48(hw);
551*4882a593Smuzhiyun
552*4882a593Smuzhiyun return regmap_write_bits(usb1->regmap, CFGCHIP(2),
553*4882a593Smuzhiyun CFGCHIP2_USB1PHYCLKMUX,
554*4882a593Smuzhiyun index ? CFGCHIP2_USB1PHYCLKMUX : 0);
555*4882a593Smuzhiyun }
556*4882a593Smuzhiyun
da8xx_usb1_clk48_get_parent(struct clk_hw * hw)557*4882a593Smuzhiyun static u8 da8xx_usb1_clk48_get_parent(struct clk_hw *hw)
558*4882a593Smuzhiyun {
559*4882a593Smuzhiyun struct da8xx_usb1_clk48 *usb1 = to_da8xx_usb1_clk48(hw);
560*4882a593Smuzhiyun unsigned int val;
561*4882a593Smuzhiyun
562*4882a593Smuzhiyun regmap_read(usb1->regmap, CFGCHIP(2), &val);
563*4882a593Smuzhiyun
564*4882a593Smuzhiyun return (val & CFGCHIP2_USB1PHYCLKMUX) ? 1 : 0;
565*4882a593Smuzhiyun }
566*4882a593Smuzhiyun
567*4882a593Smuzhiyun static const struct clk_ops da8xx_usb1_clk48_ops = {
568*4882a593Smuzhiyun .set_parent = da8xx_usb1_clk48_set_parent,
569*4882a593Smuzhiyun .get_parent = da8xx_usb1_clk48_get_parent,
570*4882a593Smuzhiyun };
571*4882a593Smuzhiyun
572*4882a593Smuzhiyun /**
573*4882a593Smuzhiyun * da8xx_cfgchip_register_usb1_clk48 - Register a new USB 1.1 PHY clock
574*4882a593Smuzhiyun * @dev: The device
575*4882a593Smuzhiyun * @regmap: The CFGCHIP regmap
576*4882a593Smuzhiyun */
577*4882a593Smuzhiyun static struct da8xx_usb1_clk48 *
da8xx_cfgchip_register_usb1_clk48(struct device * dev,struct regmap * regmap)578*4882a593Smuzhiyun da8xx_cfgchip_register_usb1_clk48(struct device *dev,
579*4882a593Smuzhiyun struct regmap *regmap)
580*4882a593Smuzhiyun {
581*4882a593Smuzhiyun const char * const parent_names[] = { "usb0_clk48", "usb_refclkin" };
582*4882a593Smuzhiyun struct da8xx_usb1_clk48 *usb1;
583*4882a593Smuzhiyun struct clk_init_data init;
584*4882a593Smuzhiyun int ret;
585*4882a593Smuzhiyun
586*4882a593Smuzhiyun usb1 = devm_kzalloc(dev, sizeof(*usb1), GFP_KERNEL);
587*4882a593Smuzhiyun if (!usb1)
588*4882a593Smuzhiyun return ERR_PTR(-ENOMEM);
589*4882a593Smuzhiyun
590*4882a593Smuzhiyun init.name = "usb1_clk48";
591*4882a593Smuzhiyun init.ops = &da8xx_usb1_clk48_ops;
592*4882a593Smuzhiyun init.parent_names = parent_names;
593*4882a593Smuzhiyun init.num_parents = 2;
594*4882a593Smuzhiyun
595*4882a593Smuzhiyun usb1->hw.init = &init;
596*4882a593Smuzhiyun usb1->regmap = regmap;
597*4882a593Smuzhiyun
598*4882a593Smuzhiyun ret = devm_clk_hw_register(dev, &usb1->hw);
599*4882a593Smuzhiyun if (ret < 0)
600*4882a593Smuzhiyun return ERR_PTR(ret);
601*4882a593Smuzhiyun
602*4882a593Smuzhiyun return usb1;
603*4882a593Smuzhiyun }
604*4882a593Smuzhiyun
da8xx_cfgchip_register_usb_phy_clk(struct device * dev,struct regmap * regmap)605*4882a593Smuzhiyun static int da8xx_cfgchip_register_usb_phy_clk(struct device *dev,
606*4882a593Smuzhiyun struct regmap *regmap)
607*4882a593Smuzhiyun {
608*4882a593Smuzhiyun struct da8xx_usb0_clk48 *usb0;
609*4882a593Smuzhiyun struct da8xx_usb1_clk48 *usb1;
610*4882a593Smuzhiyun struct clk_hw *parent;
611*4882a593Smuzhiyun
612*4882a593Smuzhiyun usb0 = da8xx_cfgchip_register_usb0_clk48(dev, regmap);
613*4882a593Smuzhiyun if (IS_ERR(usb0))
614*4882a593Smuzhiyun return PTR_ERR(usb0);
615*4882a593Smuzhiyun
616*4882a593Smuzhiyun /*
617*4882a593Smuzhiyun * All existing boards use pll0_auxclk as the parent and new boards
618*4882a593Smuzhiyun * should use device tree, so hard-coding the value (1) here.
619*4882a593Smuzhiyun */
620*4882a593Smuzhiyun parent = clk_hw_get_parent_by_index(&usb0->hw, 1);
621*4882a593Smuzhiyun if (parent)
622*4882a593Smuzhiyun clk_set_parent(usb0->hw.clk, parent->clk);
623*4882a593Smuzhiyun else
624*4882a593Smuzhiyun dev_warn(dev, "Failed to find usb0 parent clock\n");
625*4882a593Smuzhiyun
626*4882a593Smuzhiyun usb1 = da8xx_cfgchip_register_usb1_clk48(dev, regmap);
627*4882a593Smuzhiyun if (IS_ERR(usb1))
628*4882a593Smuzhiyun return PTR_ERR(usb1);
629*4882a593Smuzhiyun
630*4882a593Smuzhiyun /*
631*4882a593Smuzhiyun * All existing boards use usb0_clk48 as the parent and new boards
632*4882a593Smuzhiyun * should use device tree, so hard-coding the value (0) here.
633*4882a593Smuzhiyun */
634*4882a593Smuzhiyun parent = clk_hw_get_parent_by_index(&usb1->hw, 0);
635*4882a593Smuzhiyun if (parent)
636*4882a593Smuzhiyun clk_set_parent(usb1->hw.clk, parent->clk);
637*4882a593Smuzhiyun else
638*4882a593Smuzhiyun dev_warn(dev, "Failed to find usb1 parent clock\n");
639*4882a593Smuzhiyun
640*4882a593Smuzhiyun clk_hw_register_clkdev(&usb0->hw, "usb0_clk48", "da8xx-usb-phy");
641*4882a593Smuzhiyun clk_hw_register_clkdev(&usb1->hw, "usb1_clk48", "da8xx-usb-phy");
642*4882a593Smuzhiyun
643*4882a593Smuzhiyun return 0;
644*4882a593Smuzhiyun }
645*4882a593Smuzhiyun
of_da8xx_usb_phy_clk_init(struct device * dev,struct regmap * regmap)646*4882a593Smuzhiyun static int of_da8xx_usb_phy_clk_init(struct device *dev, struct regmap *regmap)
647*4882a593Smuzhiyun {
648*4882a593Smuzhiyun struct clk_hw_onecell_data *clk_data;
649*4882a593Smuzhiyun struct da8xx_usb0_clk48 *usb0;
650*4882a593Smuzhiyun struct da8xx_usb1_clk48 *usb1;
651*4882a593Smuzhiyun
652*4882a593Smuzhiyun clk_data = devm_kzalloc(dev, struct_size(clk_data, hws, 2),
653*4882a593Smuzhiyun GFP_KERNEL);
654*4882a593Smuzhiyun if (!clk_data)
655*4882a593Smuzhiyun return -ENOMEM;
656*4882a593Smuzhiyun
657*4882a593Smuzhiyun clk_data->num = 2;
658*4882a593Smuzhiyun
659*4882a593Smuzhiyun usb0 = da8xx_cfgchip_register_usb0_clk48(dev, regmap);
660*4882a593Smuzhiyun if (IS_ERR(usb0)) {
661*4882a593Smuzhiyun if (PTR_ERR(usb0) == -EPROBE_DEFER)
662*4882a593Smuzhiyun return -EPROBE_DEFER;
663*4882a593Smuzhiyun
664*4882a593Smuzhiyun dev_warn(dev, "Failed to register usb0_clk48 (%ld)\n",
665*4882a593Smuzhiyun PTR_ERR(usb0));
666*4882a593Smuzhiyun
667*4882a593Smuzhiyun clk_data->hws[0] = ERR_PTR(-ENOENT);
668*4882a593Smuzhiyun } else {
669*4882a593Smuzhiyun clk_data->hws[0] = &usb0->hw;
670*4882a593Smuzhiyun }
671*4882a593Smuzhiyun
672*4882a593Smuzhiyun usb1 = da8xx_cfgchip_register_usb1_clk48(dev, regmap);
673*4882a593Smuzhiyun if (IS_ERR(usb1)) {
674*4882a593Smuzhiyun if (PTR_ERR(usb1) == -EPROBE_DEFER)
675*4882a593Smuzhiyun return -EPROBE_DEFER;
676*4882a593Smuzhiyun
677*4882a593Smuzhiyun dev_warn(dev, "Failed to register usb1_clk48 (%ld)\n",
678*4882a593Smuzhiyun PTR_ERR(usb1));
679*4882a593Smuzhiyun
680*4882a593Smuzhiyun clk_data->hws[1] = ERR_PTR(-ENOENT);
681*4882a593Smuzhiyun } else {
682*4882a593Smuzhiyun clk_data->hws[1] = &usb1->hw;
683*4882a593Smuzhiyun }
684*4882a593Smuzhiyun
685*4882a593Smuzhiyun return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, clk_data);
686*4882a593Smuzhiyun }
687*4882a593Smuzhiyun
688*4882a593Smuzhiyun /* --- platform device --- */
689*4882a593Smuzhiyun
690*4882a593Smuzhiyun static const struct of_device_id da8xx_cfgchip_of_match[] = {
691*4882a593Smuzhiyun {
692*4882a593Smuzhiyun .compatible = "ti,da830-tbclksync",
693*4882a593Smuzhiyun .data = of_da8xx_tbclksync_init,
694*4882a593Smuzhiyun },
695*4882a593Smuzhiyun {
696*4882a593Smuzhiyun .compatible = "ti,da830-div4p5ena",
697*4882a593Smuzhiyun .data = of_da8xx_div4p5ena_init,
698*4882a593Smuzhiyun },
699*4882a593Smuzhiyun {
700*4882a593Smuzhiyun .compatible = "ti,da850-async1-clksrc",
701*4882a593Smuzhiyun .data = of_da850_async1_init,
702*4882a593Smuzhiyun },
703*4882a593Smuzhiyun {
704*4882a593Smuzhiyun .compatible = "ti,da850-async3-clksrc",
705*4882a593Smuzhiyun .data = of_da850_async3_init,
706*4882a593Smuzhiyun },
707*4882a593Smuzhiyun {
708*4882a593Smuzhiyun .compatible = "ti,da830-usb-phy-clocks",
709*4882a593Smuzhiyun .data = of_da8xx_usb_phy_clk_init,
710*4882a593Smuzhiyun },
711*4882a593Smuzhiyun { }
712*4882a593Smuzhiyun };
713*4882a593Smuzhiyun
714*4882a593Smuzhiyun static const struct platform_device_id da8xx_cfgchip_id_table[] = {
715*4882a593Smuzhiyun {
716*4882a593Smuzhiyun .name = "da830-tbclksync",
717*4882a593Smuzhiyun .driver_data = (kernel_ulong_t)da8xx_cfgchip_register_tbclk,
718*4882a593Smuzhiyun },
719*4882a593Smuzhiyun {
720*4882a593Smuzhiyun .name = "da830-div4p5ena",
721*4882a593Smuzhiyun .driver_data = (kernel_ulong_t)da8xx_cfgchip_register_div4p5,
722*4882a593Smuzhiyun },
723*4882a593Smuzhiyun {
724*4882a593Smuzhiyun .name = "da850-async1-clksrc",
725*4882a593Smuzhiyun .driver_data = (kernel_ulong_t)da8xx_cfgchip_register_async1,
726*4882a593Smuzhiyun },
727*4882a593Smuzhiyun {
728*4882a593Smuzhiyun .name = "da850-async3-clksrc",
729*4882a593Smuzhiyun .driver_data = (kernel_ulong_t)da850_cfgchip_register_async3,
730*4882a593Smuzhiyun },
731*4882a593Smuzhiyun {
732*4882a593Smuzhiyun .name = "da830-usb-phy-clks",
733*4882a593Smuzhiyun .driver_data = (kernel_ulong_t)da8xx_cfgchip_register_usb_phy_clk,
734*4882a593Smuzhiyun },
735*4882a593Smuzhiyun { }
736*4882a593Smuzhiyun };
737*4882a593Smuzhiyun
738*4882a593Smuzhiyun typedef int (*da8xx_cfgchip_init)(struct device *dev, struct regmap *regmap);
739*4882a593Smuzhiyun
da8xx_cfgchip_probe(struct platform_device * pdev)740*4882a593Smuzhiyun static int da8xx_cfgchip_probe(struct platform_device *pdev)
741*4882a593Smuzhiyun {
742*4882a593Smuzhiyun struct device *dev = &pdev->dev;
743*4882a593Smuzhiyun struct da8xx_cfgchip_clk_platform_data *pdata = dev->platform_data;
744*4882a593Smuzhiyun const struct of_device_id *of_id;
745*4882a593Smuzhiyun da8xx_cfgchip_init clk_init = NULL;
746*4882a593Smuzhiyun struct regmap *regmap = NULL;
747*4882a593Smuzhiyun
748*4882a593Smuzhiyun of_id = of_match_device(da8xx_cfgchip_of_match, dev);
749*4882a593Smuzhiyun if (of_id) {
750*4882a593Smuzhiyun struct device_node *parent;
751*4882a593Smuzhiyun
752*4882a593Smuzhiyun clk_init = of_id->data;
753*4882a593Smuzhiyun parent = of_get_parent(dev->of_node);
754*4882a593Smuzhiyun regmap = syscon_node_to_regmap(parent);
755*4882a593Smuzhiyun of_node_put(parent);
756*4882a593Smuzhiyun } else if (pdev->id_entry && pdata) {
757*4882a593Smuzhiyun clk_init = (void *)pdev->id_entry->driver_data;
758*4882a593Smuzhiyun regmap = pdata->cfgchip;
759*4882a593Smuzhiyun }
760*4882a593Smuzhiyun
761*4882a593Smuzhiyun if (!clk_init) {
762*4882a593Smuzhiyun dev_err(dev, "unable to find driver data\n");
763*4882a593Smuzhiyun return -EINVAL;
764*4882a593Smuzhiyun }
765*4882a593Smuzhiyun
766*4882a593Smuzhiyun if (IS_ERR_OR_NULL(regmap)) {
767*4882a593Smuzhiyun dev_err(dev, "no regmap for CFGCHIP syscon\n");
768*4882a593Smuzhiyun return regmap ? PTR_ERR(regmap) : -ENOENT;
769*4882a593Smuzhiyun }
770*4882a593Smuzhiyun
771*4882a593Smuzhiyun return clk_init(dev, regmap);
772*4882a593Smuzhiyun }
773*4882a593Smuzhiyun
774*4882a593Smuzhiyun static struct platform_driver da8xx_cfgchip_driver = {
775*4882a593Smuzhiyun .probe = da8xx_cfgchip_probe,
776*4882a593Smuzhiyun .driver = {
777*4882a593Smuzhiyun .name = "da8xx-cfgchip-clk",
778*4882a593Smuzhiyun .of_match_table = da8xx_cfgchip_of_match,
779*4882a593Smuzhiyun },
780*4882a593Smuzhiyun .id_table = da8xx_cfgchip_id_table,
781*4882a593Smuzhiyun };
782*4882a593Smuzhiyun
da8xx_cfgchip_driver_init(void)783*4882a593Smuzhiyun static int __init da8xx_cfgchip_driver_init(void)
784*4882a593Smuzhiyun {
785*4882a593Smuzhiyun return platform_driver_register(&da8xx_cfgchip_driver);
786*4882a593Smuzhiyun }
787*4882a593Smuzhiyun
788*4882a593Smuzhiyun /* has to be postcore_initcall because PSC devices depend on the async3 clock */
789*4882a593Smuzhiyun postcore_initcall(da8xx_cfgchip_driver_init);
790