xref: /OK3568_Linux_fs/kernel/drivers/clk/renesas/renesas-cpg-mssr.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * Renesas Clock Pulse Generator / Module Standby and Software Reset
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Copyright (C) 2015 Glider bvba
6*4882a593Smuzhiyun  *
7*4882a593Smuzhiyun  * Based on clk-mstp.c, clk-rcar-gen2.c, and clk-rcar-gen3.c
8*4882a593Smuzhiyun  *
9*4882a593Smuzhiyun  * Copyright (C) 2013 Ideas On Board SPRL
10*4882a593Smuzhiyun  * Copyright (C) 2015 Renesas Electronics Corp.
11*4882a593Smuzhiyun  */
12*4882a593Smuzhiyun 
13*4882a593Smuzhiyun #include <linux/clk.h>
14*4882a593Smuzhiyun #include <linux/clk-provider.h>
15*4882a593Smuzhiyun #include <linux/clk/renesas.h>
16*4882a593Smuzhiyun #include <linux/delay.h>
17*4882a593Smuzhiyun #include <linux/device.h>
18*4882a593Smuzhiyun #include <linux/init.h>
19*4882a593Smuzhiyun #include <linux/io.h>
20*4882a593Smuzhiyun #include <linux/mod_devicetable.h>
21*4882a593Smuzhiyun #include <linux/module.h>
22*4882a593Smuzhiyun #include <linux/of_address.h>
23*4882a593Smuzhiyun #include <linux/of_device.h>
24*4882a593Smuzhiyun #include <linux/platform_device.h>
25*4882a593Smuzhiyun #include <linux/pm_clock.h>
26*4882a593Smuzhiyun #include <linux/pm_domain.h>
27*4882a593Smuzhiyun #include <linux/psci.h>
28*4882a593Smuzhiyun #include <linux/reset-controller.h>
29*4882a593Smuzhiyun #include <linux/slab.h>
30*4882a593Smuzhiyun 
31*4882a593Smuzhiyun #include <dt-bindings/clock/renesas-cpg-mssr.h>
32*4882a593Smuzhiyun 
33*4882a593Smuzhiyun #include "renesas-cpg-mssr.h"
34*4882a593Smuzhiyun #include "clk-div6.h"
35*4882a593Smuzhiyun 
36*4882a593Smuzhiyun #ifdef DEBUG
37*4882a593Smuzhiyun #define WARN_DEBUG(x)	WARN_ON(x)
38*4882a593Smuzhiyun #else
39*4882a593Smuzhiyun #define WARN_DEBUG(x)	do { } while (0)
40*4882a593Smuzhiyun #endif
41*4882a593Smuzhiyun 
42*4882a593Smuzhiyun 
43*4882a593Smuzhiyun /*
44*4882a593Smuzhiyun  * Module Standby and Software Reset register offets.
45*4882a593Smuzhiyun  *
46*4882a593Smuzhiyun  * If the registers exist, these are valid for SH-Mobile, R-Mobile,
47*4882a593Smuzhiyun  * R-Car Gen2, R-Car Gen3, and RZ/G1.
48*4882a593Smuzhiyun  * These are NOT valid for R-Car Gen1 and RZ/A1!
49*4882a593Smuzhiyun  */
50*4882a593Smuzhiyun 
51*4882a593Smuzhiyun /*
52*4882a593Smuzhiyun  * Module Stop Status Register offsets
53*4882a593Smuzhiyun  */
54*4882a593Smuzhiyun 
55*4882a593Smuzhiyun static const u16 mstpsr[] = {
56*4882a593Smuzhiyun 	0x030, 0x038, 0x040, 0x048, 0x04C, 0x03C, 0x1C0, 0x1C4,
57*4882a593Smuzhiyun 	0x9A0, 0x9A4, 0x9A8, 0x9AC,
58*4882a593Smuzhiyun };
59*4882a593Smuzhiyun 
60*4882a593Smuzhiyun static const u16 mstpsr_for_v3u[] = {
61*4882a593Smuzhiyun 	0x2E00, 0x2E04, 0x2E08, 0x2E0C, 0x2E10, 0x2E14, 0x2E18, 0x2E1C,
62*4882a593Smuzhiyun 	0x2E20, 0x2E24, 0x2E28, 0x2E2C, 0x2E30, 0x2E34, 0x2E38,
63*4882a593Smuzhiyun };
64*4882a593Smuzhiyun 
65*4882a593Smuzhiyun /*
66*4882a593Smuzhiyun  * System Module Stop Control Register offsets
67*4882a593Smuzhiyun  */
68*4882a593Smuzhiyun 
69*4882a593Smuzhiyun static const u16 smstpcr[] = {
70*4882a593Smuzhiyun 	0x130, 0x134, 0x138, 0x13C, 0x140, 0x144, 0x148, 0x14C,
71*4882a593Smuzhiyun 	0x990, 0x994, 0x998, 0x99C,
72*4882a593Smuzhiyun };
73*4882a593Smuzhiyun 
74*4882a593Smuzhiyun static const u16 mstpcr_for_v3u[] = {
75*4882a593Smuzhiyun 	0x2D00, 0x2D04, 0x2D08, 0x2D0C, 0x2D10, 0x2D14, 0x2D18, 0x2D1C,
76*4882a593Smuzhiyun 	0x2D20, 0x2D24, 0x2D28, 0x2D2C, 0x2D30, 0x2D34, 0x2D38,
77*4882a593Smuzhiyun };
78*4882a593Smuzhiyun 
79*4882a593Smuzhiyun /*
80*4882a593Smuzhiyun  * Standby Control Register offsets (RZ/A)
81*4882a593Smuzhiyun  * Base address is FRQCR register
82*4882a593Smuzhiyun  */
83*4882a593Smuzhiyun 
84*4882a593Smuzhiyun static const u16 stbcr[] = {
85*4882a593Smuzhiyun 	0xFFFF/*dummy*/, 0x010, 0x014, 0x410, 0x414, 0x418, 0x41C, 0x420,
86*4882a593Smuzhiyun 	0x424, 0x428, 0x42C,
87*4882a593Smuzhiyun };
88*4882a593Smuzhiyun 
89*4882a593Smuzhiyun /*
90*4882a593Smuzhiyun  * Software Reset Register offsets
91*4882a593Smuzhiyun  */
92*4882a593Smuzhiyun 
93*4882a593Smuzhiyun static const u16 srcr[] = {
94*4882a593Smuzhiyun 	0x0A0, 0x0A8, 0x0B0, 0x0B8, 0x0BC, 0x0C4, 0x1C8, 0x1CC,
95*4882a593Smuzhiyun 	0x920, 0x924, 0x928, 0x92C,
96*4882a593Smuzhiyun };
97*4882a593Smuzhiyun 
98*4882a593Smuzhiyun static const u16 srcr_for_v3u[] = {
99*4882a593Smuzhiyun 	0x2C00, 0x2C04, 0x2C08, 0x2C0C, 0x2C10, 0x2C14, 0x2C18, 0x2C1C,
100*4882a593Smuzhiyun 	0x2C20, 0x2C24, 0x2C28, 0x2C2C, 0x2C30, 0x2C34, 0x2C38,
101*4882a593Smuzhiyun };
102*4882a593Smuzhiyun 
103*4882a593Smuzhiyun /* Realtime Module Stop Control Register offsets */
104*4882a593Smuzhiyun #define RMSTPCR(i)	(smstpcr[i] - 0x20)
105*4882a593Smuzhiyun 
106*4882a593Smuzhiyun /* Modem Module Stop Control Register offsets (r8a73a4) */
107*4882a593Smuzhiyun #define MMSTPCR(i)	(smstpcr[i] + 0x20)
108*4882a593Smuzhiyun 
109*4882a593Smuzhiyun /* Software Reset Clearing Register offsets */
110*4882a593Smuzhiyun 
111*4882a593Smuzhiyun static const u16 srstclr[] = {
112*4882a593Smuzhiyun 	0x940, 0x944, 0x948, 0x94C, 0x950, 0x954, 0x958, 0x95C,
113*4882a593Smuzhiyun 	0x960, 0x964, 0x968, 0x96C,
114*4882a593Smuzhiyun };
115*4882a593Smuzhiyun 
116*4882a593Smuzhiyun static const u16 srstclr_for_v3u[] = {
117*4882a593Smuzhiyun 	0x2C80, 0x2C84, 0x2C88, 0x2C8C, 0x2C90, 0x2C94, 0x2C98, 0x2C9C,
118*4882a593Smuzhiyun 	0x2CA0, 0x2CA4, 0x2CA8, 0x2CAC, 0x2CB0, 0x2CB4, 0x2CB8,
119*4882a593Smuzhiyun };
120*4882a593Smuzhiyun 
121*4882a593Smuzhiyun /**
122*4882a593Smuzhiyun  * Clock Pulse Generator / Module Standby and Software Reset Private Data
123*4882a593Smuzhiyun  *
124*4882a593Smuzhiyun  * @rcdev: Optional reset controller entity
125*4882a593Smuzhiyun  * @dev: CPG/MSSR device
126*4882a593Smuzhiyun  * @base: CPG/MSSR register block base address
127*4882a593Smuzhiyun  * @reg_layout: CPG/MSSR register layout
128*4882a593Smuzhiyun  * @rmw_lock: protects RMW register accesses
129*4882a593Smuzhiyun  * @np: Device node in DT for this CPG/MSSR module
130*4882a593Smuzhiyun  * @num_core_clks: Number of Core Clocks in clks[]
131*4882a593Smuzhiyun  * @num_mod_clks: Number of Module Clocks in clks[]
132*4882a593Smuzhiyun  * @last_dt_core_clk: ID of the last Core Clock exported to DT
133*4882a593Smuzhiyun  * @notifiers: Notifier chain to save/restore clock state for system resume
134*4882a593Smuzhiyun  * @status_regs: Pointer to status registers array
135*4882a593Smuzhiyun  * @control_regs: Pointer to control registers array
136*4882a593Smuzhiyun  * @reset_regs: Pointer to reset registers array
137*4882a593Smuzhiyun  * @reset_clear_regs:  Pointer to reset clearing registers array
138*4882a593Smuzhiyun  * @smstpcr_saved[].mask: Mask of SMSTPCR[] bits under our control
139*4882a593Smuzhiyun  * @smstpcr_saved[].val: Saved values of SMSTPCR[]
140*4882a593Smuzhiyun  * @clks: Array containing all Core and Module Clocks
141*4882a593Smuzhiyun  */
142*4882a593Smuzhiyun struct cpg_mssr_priv {
143*4882a593Smuzhiyun #ifdef CONFIG_RESET_CONTROLLER
144*4882a593Smuzhiyun 	struct reset_controller_dev rcdev;
145*4882a593Smuzhiyun #endif
146*4882a593Smuzhiyun 	struct device *dev;
147*4882a593Smuzhiyun 	void __iomem *base;
148*4882a593Smuzhiyun 	enum clk_reg_layout reg_layout;
149*4882a593Smuzhiyun 	spinlock_t rmw_lock;
150*4882a593Smuzhiyun 	struct device_node *np;
151*4882a593Smuzhiyun 
152*4882a593Smuzhiyun 	unsigned int num_core_clks;
153*4882a593Smuzhiyun 	unsigned int num_mod_clks;
154*4882a593Smuzhiyun 	unsigned int last_dt_core_clk;
155*4882a593Smuzhiyun 
156*4882a593Smuzhiyun 	struct raw_notifier_head notifiers;
157*4882a593Smuzhiyun 	const u16 *status_regs;
158*4882a593Smuzhiyun 	const u16 *control_regs;
159*4882a593Smuzhiyun 	const u16 *reset_regs;
160*4882a593Smuzhiyun 	const u16 *reset_clear_regs;
161*4882a593Smuzhiyun 	struct {
162*4882a593Smuzhiyun 		u32 mask;
163*4882a593Smuzhiyun 		u32 val;
164*4882a593Smuzhiyun 	} smstpcr_saved[ARRAY_SIZE(mstpsr_for_v3u)];
165*4882a593Smuzhiyun 
166*4882a593Smuzhiyun 	struct clk *clks[];
167*4882a593Smuzhiyun };
168*4882a593Smuzhiyun 
169*4882a593Smuzhiyun static struct cpg_mssr_priv *cpg_mssr_priv;
170*4882a593Smuzhiyun 
171*4882a593Smuzhiyun /**
172*4882a593Smuzhiyun  * struct mstp_clock - MSTP gating clock
173*4882a593Smuzhiyun  * @hw: handle between common and hardware-specific interfaces
174*4882a593Smuzhiyun  * @index: MSTP clock number
175*4882a593Smuzhiyun  * @priv: CPG/MSSR private data
176*4882a593Smuzhiyun  */
177*4882a593Smuzhiyun struct mstp_clock {
178*4882a593Smuzhiyun 	struct clk_hw hw;
179*4882a593Smuzhiyun 	u32 index;
180*4882a593Smuzhiyun 	struct cpg_mssr_priv *priv;
181*4882a593Smuzhiyun };
182*4882a593Smuzhiyun 
183*4882a593Smuzhiyun #define to_mstp_clock(_hw) container_of(_hw, struct mstp_clock, hw)
184*4882a593Smuzhiyun 
cpg_mstp_clock_endisable(struct clk_hw * hw,bool enable)185*4882a593Smuzhiyun static int cpg_mstp_clock_endisable(struct clk_hw *hw, bool enable)
186*4882a593Smuzhiyun {
187*4882a593Smuzhiyun 	struct mstp_clock *clock = to_mstp_clock(hw);
188*4882a593Smuzhiyun 	struct cpg_mssr_priv *priv = clock->priv;
189*4882a593Smuzhiyun 	unsigned int reg = clock->index / 32;
190*4882a593Smuzhiyun 	unsigned int bit = clock->index % 32;
191*4882a593Smuzhiyun 	struct device *dev = priv->dev;
192*4882a593Smuzhiyun 	u32 bitmask = BIT(bit);
193*4882a593Smuzhiyun 	unsigned long flags;
194*4882a593Smuzhiyun 	unsigned int i;
195*4882a593Smuzhiyun 	u32 value;
196*4882a593Smuzhiyun 
197*4882a593Smuzhiyun 	dev_dbg(dev, "MSTP %u%02u/%pC %s\n", reg, bit, hw->clk,
198*4882a593Smuzhiyun 		enable ? "ON" : "OFF");
199*4882a593Smuzhiyun 	spin_lock_irqsave(&priv->rmw_lock, flags);
200*4882a593Smuzhiyun 
201*4882a593Smuzhiyun 	if (priv->reg_layout == CLK_REG_LAYOUT_RZ_A) {
202*4882a593Smuzhiyun 		value = readb(priv->base + priv->control_regs[reg]);
203*4882a593Smuzhiyun 		if (enable)
204*4882a593Smuzhiyun 			value &= ~bitmask;
205*4882a593Smuzhiyun 		else
206*4882a593Smuzhiyun 			value |= bitmask;
207*4882a593Smuzhiyun 		writeb(value, priv->base + priv->control_regs[reg]);
208*4882a593Smuzhiyun 
209*4882a593Smuzhiyun 		/* dummy read to ensure write has completed */
210*4882a593Smuzhiyun 		readb(priv->base + priv->control_regs[reg]);
211*4882a593Smuzhiyun 		barrier_data(priv->base + priv->control_regs[reg]);
212*4882a593Smuzhiyun 	} else {
213*4882a593Smuzhiyun 		value = readl(priv->base + priv->control_regs[reg]);
214*4882a593Smuzhiyun 		if (enable)
215*4882a593Smuzhiyun 			value &= ~bitmask;
216*4882a593Smuzhiyun 		else
217*4882a593Smuzhiyun 			value |= bitmask;
218*4882a593Smuzhiyun 		writel(value, priv->base + priv->control_regs[reg]);
219*4882a593Smuzhiyun 	}
220*4882a593Smuzhiyun 
221*4882a593Smuzhiyun 	spin_unlock_irqrestore(&priv->rmw_lock, flags);
222*4882a593Smuzhiyun 
223*4882a593Smuzhiyun 	if (!enable || priv->reg_layout == CLK_REG_LAYOUT_RZ_A)
224*4882a593Smuzhiyun 		return 0;
225*4882a593Smuzhiyun 
226*4882a593Smuzhiyun 	for (i = 1000; i > 0; --i) {
227*4882a593Smuzhiyun 		if (!(readl(priv->base + priv->status_regs[reg]) & bitmask))
228*4882a593Smuzhiyun 			break;
229*4882a593Smuzhiyun 		cpu_relax();
230*4882a593Smuzhiyun 	}
231*4882a593Smuzhiyun 
232*4882a593Smuzhiyun 	if (!i) {
233*4882a593Smuzhiyun 		dev_err(dev, "Failed to enable SMSTP %p[%d]\n",
234*4882a593Smuzhiyun 			priv->base + priv->control_regs[reg], bit);
235*4882a593Smuzhiyun 		return -ETIMEDOUT;
236*4882a593Smuzhiyun 	}
237*4882a593Smuzhiyun 
238*4882a593Smuzhiyun 	return 0;
239*4882a593Smuzhiyun }
240*4882a593Smuzhiyun 
cpg_mstp_clock_enable(struct clk_hw * hw)241*4882a593Smuzhiyun static int cpg_mstp_clock_enable(struct clk_hw *hw)
242*4882a593Smuzhiyun {
243*4882a593Smuzhiyun 	return cpg_mstp_clock_endisable(hw, true);
244*4882a593Smuzhiyun }
245*4882a593Smuzhiyun 
cpg_mstp_clock_disable(struct clk_hw * hw)246*4882a593Smuzhiyun static void cpg_mstp_clock_disable(struct clk_hw *hw)
247*4882a593Smuzhiyun {
248*4882a593Smuzhiyun 	cpg_mstp_clock_endisable(hw, false);
249*4882a593Smuzhiyun }
250*4882a593Smuzhiyun 
cpg_mstp_clock_is_enabled(struct clk_hw * hw)251*4882a593Smuzhiyun static int cpg_mstp_clock_is_enabled(struct clk_hw *hw)
252*4882a593Smuzhiyun {
253*4882a593Smuzhiyun 	struct mstp_clock *clock = to_mstp_clock(hw);
254*4882a593Smuzhiyun 	struct cpg_mssr_priv *priv = clock->priv;
255*4882a593Smuzhiyun 	u32 value;
256*4882a593Smuzhiyun 
257*4882a593Smuzhiyun 	if (priv->reg_layout == CLK_REG_LAYOUT_RZ_A)
258*4882a593Smuzhiyun 		value = readb(priv->base + priv->control_regs[clock->index / 32]);
259*4882a593Smuzhiyun 	else
260*4882a593Smuzhiyun 		value = readl(priv->base + priv->status_regs[clock->index / 32]);
261*4882a593Smuzhiyun 
262*4882a593Smuzhiyun 	return !(value & BIT(clock->index % 32));
263*4882a593Smuzhiyun }
264*4882a593Smuzhiyun 
265*4882a593Smuzhiyun static const struct clk_ops cpg_mstp_clock_ops = {
266*4882a593Smuzhiyun 	.enable = cpg_mstp_clock_enable,
267*4882a593Smuzhiyun 	.disable = cpg_mstp_clock_disable,
268*4882a593Smuzhiyun 	.is_enabled = cpg_mstp_clock_is_enabled,
269*4882a593Smuzhiyun };
270*4882a593Smuzhiyun 
271*4882a593Smuzhiyun static
cpg_mssr_clk_src_twocell_get(struct of_phandle_args * clkspec,void * data)272*4882a593Smuzhiyun struct clk *cpg_mssr_clk_src_twocell_get(struct of_phandle_args *clkspec,
273*4882a593Smuzhiyun 					 void *data)
274*4882a593Smuzhiyun {
275*4882a593Smuzhiyun 	unsigned int clkidx = clkspec->args[1];
276*4882a593Smuzhiyun 	struct cpg_mssr_priv *priv = data;
277*4882a593Smuzhiyun 	struct device *dev = priv->dev;
278*4882a593Smuzhiyun 	unsigned int idx;
279*4882a593Smuzhiyun 	const char *type;
280*4882a593Smuzhiyun 	struct clk *clk;
281*4882a593Smuzhiyun 	int range_check;
282*4882a593Smuzhiyun 
283*4882a593Smuzhiyun 	switch (clkspec->args[0]) {
284*4882a593Smuzhiyun 	case CPG_CORE:
285*4882a593Smuzhiyun 		type = "core";
286*4882a593Smuzhiyun 		if (clkidx > priv->last_dt_core_clk) {
287*4882a593Smuzhiyun 			dev_err(dev, "Invalid %s clock index %u\n", type,
288*4882a593Smuzhiyun 			       clkidx);
289*4882a593Smuzhiyun 			return ERR_PTR(-EINVAL);
290*4882a593Smuzhiyun 		}
291*4882a593Smuzhiyun 		clk = priv->clks[clkidx];
292*4882a593Smuzhiyun 		break;
293*4882a593Smuzhiyun 
294*4882a593Smuzhiyun 	case CPG_MOD:
295*4882a593Smuzhiyun 		type = "module";
296*4882a593Smuzhiyun 		if (priv->reg_layout == CLK_REG_LAYOUT_RZ_A) {
297*4882a593Smuzhiyun 			idx = MOD_CLK_PACK_10(clkidx);
298*4882a593Smuzhiyun 			range_check = 7 - (clkidx % 10);
299*4882a593Smuzhiyun 		} else {
300*4882a593Smuzhiyun 			idx = MOD_CLK_PACK(clkidx);
301*4882a593Smuzhiyun 			range_check = 31 - (clkidx % 100);
302*4882a593Smuzhiyun 		}
303*4882a593Smuzhiyun 		if (range_check < 0 || idx >= priv->num_mod_clks) {
304*4882a593Smuzhiyun 			dev_err(dev, "Invalid %s clock index %u\n", type,
305*4882a593Smuzhiyun 				clkidx);
306*4882a593Smuzhiyun 			return ERR_PTR(-EINVAL);
307*4882a593Smuzhiyun 		}
308*4882a593Smuzhiyun 		clk = priv->clks[priv->num_core_clks + idx];
309*4882a593Smuzhiyun 		break;
310*4882a593Smuzhiyun 
311*4882a593Smuzhiyun 	default:
312*4882a593Smuzhiyun 		dev_err(dev, "Invalid CPG clock type %u\n", clkspec->args[0]);
313*4882a593Smuzhiyun 		return ERR_PTR(-EINVAL);
314*4882a593Smuzhiyun 	}
315*4882a593Smuzhiyun 
316*4882a593Smuzhiyun 	if (IS_ERR(clk))
317*4882a593Smuzhiyun 		dev_err(dev, "Cannot get %s clock %u: %ld", type, clkidx,
318*4882a593Smuzhiyun 		       PTR_ERR(clk));
319*4882a593Smuzhiyun 	else
320*4882a593Smuzhiyun 		dev_dbg(dev, "clock (%u, %u) is %pC at %lu Hz\n",
321*4882a593Smuzhiyun 			clkspec->args[0], clkspec->args[1], clk,
322*4882a593Smuzhiyun 			clk_get_rate(clk));
323*4882a593Smuzhiyun 	return clk;
324*4882a593Smuzhiyun }
325*4882a593Smuzhiyun 
cpg_mssr_register_core_clk(const struct cpg_core_clk * core,const struct cpg_mssr_info * info,struct cpg_mssr_priv * priv)326*4882a593Smuzhiyun static void __init cpg_mssr_register_core_clk(const struct cpg_core_clk *core,
327*4882a593Smuzhiyun 					      const struct cpg_mssr_info *info,
328*4882a593Smuzhiyun 					      struct cpg_mssr_priv *priv)
329*4882a593Smuzhiyun {
330*4882a593Smuzhiyun 	struct clk *clk = ERR_PTR(-ENOTSUPP), *parent;
331*4882a593Smuzhiyun 	struct device *dev = priv->dev;
332*4882a593Smuzhiyun 	unsigned int id = core->id, div = core->div;
333*4882a593Smuzhiyun 	const char *parent_name;
334*4882a593Smuzhiyun 
335*4882a593Smuzhiyun 	WARN_DEBUG(id >= priv->num_core_clks);
336*4882a593Smuzhiyun 	WARN_DEBUG(PTR_ERR(priv->clks[id]) != -ENOENT);
337*4882a593Smuzhiyun 
338*4882a593Smuzhiyun 	if (!core->name) {
339*4882a593Smuzhiyun 		/* Skip NULLified clock */
340*4882a593Smuzhiyun 		return;
341*4882a593Smuzhiyun 	}
342*4882a593Smuzhiyun 
343*4882a593Smuzhiyun 	switch (core->type) {
344*4882a593Smuzhiyun 	case CLK_TYPE_IN:
345*4882a593Smuzhiyun 		clk = of_clk_get_by_name(priv->np, core->name);
346*4882a593Smuzhiyun 		break;
347*4882a593Smuzhiyun 
348*4882a593Smuzhiyun 	case CLK_TYPE_FF:
349*4882a593Smuzhiyun 	case CLK_TYPE_DIV6P1:
350*4882a593Smuzhiyun 	case CLK_TYPE_DIV6_RO:
351*4882a593Smuzhiyun 		WARN_DEBUG(core->parent >= priv->num_core_clks);
352*4882a593Smuzhiyun 		parent = priv->clks[core->parent];
353*4882a593Smuzhiyun 		if (IS_ERR(parent)) {
354*4882a593Smuzhiyun 			clk = parent;
355*4882a593Smuzhiyun 			goto fail;
356*4882a593Smuzhiyun 		}
357*4882a593Smuzhiyun 
358*4882a593Smuzhiyun 		parent_name = __clk_get_name(parent);
359*4882a593Smuzhiyun 
360*4882a593Smuzhiyun 		if (core->type == CLK_TYPE_DIV6_RO)
361*4882a593Smuzhiyun 			/* Multiply with the DIV6 register value */
362*4882a593Smuzhiyun 			div *= (readl(priv->base + core->offset) & 0x3f) + 1;
363*4882a593Smuzhiyun 
364*4882a593Smuzhiyun 		if (core->type == CLK_TYPE_DIV6P1) {
365*4882a593Smuzhiyun 			clk = cpg_div6_register(core->name, 1, &parent_name,
366*4882a593Smuzhiyun 						priv->base + core->offset,
367*4882a593Smuzhiyun 						&priv->notifiers);
368*4882a593Smuzhiyun 		} else {
369*4882a593Smuzhiyun 			clk = clk_register_fixed_factor(NULL, core->name,
370*4882a593Smuzhiyun 							parent_name, 0,
371*4882a593Smuzhiyun 							core->mult, div);
372*4882a593Smuzhiyun 		}
373*4882a593Smuzhiyun 		break;
374*4882a593Smuzhiyun 
375*4882a593Smuzhiyun 	case CLK_TYPE_FR:
376*4882a593Smuzhiyun 		clk = clk_register_fixed_rate(NULL, core->name, NULL, 0,
377*4882a593Smuzhiyun 					      core->mult);
378*4882a593Smuzhiyun 		break;
379*4882a593Smuzhiyun 
380*4882a593Smuzhiyun 	default:
381*4882a593Smuzhiyun 		if (info->cpg_clk_register)
382*4882a593Smuzhiyun 			clk = info->cpg_clk_register(dev, core, info,
383*4882a593Smuzhiyun 						     priv->clks, priv->base,
384*4882a593Smuzhiyun 						     &priv->notifiers);
385*4882a593Smuzhiyun 		else
386*4882a593Smuzhiyun 			dev_err(dev, "%s has unsupported core clock type %u\n",
387*4882a593Smuzhiyun 				core->name, core->type);
388*4882a593Smuzhiyun 		break;
389*4882a593Smuzhiyun 	}
390*4882a593Smuzhiyun 
391*4882a593Smuzhiyun 	if (IS_ERR_OR_NULL(clk))
392*4882a593Smuzhiyun 		goto fail;
393*4882a593Smuzhiyun 
394*4882a593Smuzhiyun 	dev_dbg(dev, "Core clock %pC at %lu Hz\n", clk, clk_get_rate(clk));
395*4882a593Smuzhiyun 	priv->clks[id] = clk;
396*4882a593Smuzhiyun 	return;
397*4882a593Smuzhiyun 
398*4882a593Smuzhiyun fail:
399*4882a593Smuzhiyun 	dev_err(dev, "Failed to register %s clock %s: %ld\n", "core",
400*4882a593Smuzhiyun 		core->name, PTR_ERR(clk));
401*4882a593Smuzhiyun }
402*4882a593Smuzhiyun 
cpg_mssr_register_mod_clk(const struct mssr_mod_clk * mod,const struct cpg_mssr_info * info,struct cpg_mssr_priv * priv)403*4882a593Smuzhiyun static void __init cpg_mssr_register_mod_clk(const struct mssr_mod_clk *mod,
404*4882a593Smuzhiyun 					     const struct cpg_mssr_info *info,
405*4882a593Smuzhiyun 					     struct cpg_mssr_priv *priv)
406*4882a593Smuzhiyun {
407*4882a593Smuzhiyun 	struct mstp_clock *clock = NULL;
408*4882a593Smuzhiyun 	struct device *dev = priv->dev;
409*4882a593Smuzhiyun 	unsigned int id = mod->id;
410*4882a593Smuzhiyun 	struct clk_init_data init;
411*4882a593Smuzhiyun 	struct clk *parent, *clk;
412*4882a593Smuzhiyun 	const char *parent_name;
413*4882a593Smuzhiyun 	unsigned int i;
414*4882a593Smuzhiyun 
415*4882a593Smuzhiyun 	WARN_DEBUG(id < priv->num_core_clks);
416*4882a593Smuzhiyun 	WARN_DEBUG(id >= priv->num_core_clks + priv->num_mod_clks);
417*4882a593Smuzhiyun 	WARN_DEBUG(mod->parent >= priv->num_core_clks + priv->num_mod_clks);
418*4882a593Smuzhiyun 	WARN_DEBUG(PTR_ERR(priv->clks[id]) != -ENOENT);
419*4882a593Smuzhiyun 
420*4882a593Smuzhiyun 	if (!mod->name) {
421*4882a593Smuzhiyun 		/* Skip NULLified clock */
422*4882a593Smuzhiyun 		return;
423*4882a593Smuzhiyun 	}
424*4882a593Smuzhiyun 
425*4882a593Smuzhiyun 	parent = priv->clks[mod->parent];
426*4882a593Smuzhiyun 	if (IS_ERR(parent)) {
427*4882a593Smuzhiyun 		clk = parent;
428*4882a593Smuzhiyun 		goto fail;
429*4882a593Smuzhiyun 	}
430*4882a593Smuzhiyun 
431*4882a593Smuzhiyun 	clock = kzalloc(sizeof(*clock), GFP_KERNEL);
432*4882a593Smuzhiyun 	if (!clock) {
433*4882a593Smuzhiyun 		clk = ERR_PTR(-ENOMEM);
434*4882a593Smuzhiyun 		goto fail;
435*4882a593Smuzhiyun 	}
436*4882a593Smuzhiyun 
437*4882a593Smuzhiyun 	init.name = mod->name;
438*4882a593Smuzhiyun 	init.ops = &cpg_mstp_clock_ops;
439*4882a593Smuzhiyun 	init.flags = CLK_SET_RATE_PARENT;
440*4882a593Smuzhiyun 	parent_name = __clk_get_name(parent);
441*4882a593Smuzhiyun 	init.parent_names = &parent_name;
442*4882a593Smuzhiyun 	init.num_parents = 1;
443*4882a593Smuzhiyun 
444*4882a593Smuzhiyun 	clock->index = id - priv->num_core_clks;
445*4882a593Smuzhiyun 	clock->priv = priv;
446*4882a593Smuzhiyun 	clock->hw.init = &init;
447*4882a593Smuzhiyun 
448*4882a593Smuzhiyun 	for (i = 0; i < info->num_crit_mod_clks; i++)
449*4882a593Smuzhiyun 		if (id == info->crit_mod_clks[i] &&
450*4882a593Smuzhiyun 		    cpg_mstp_clock_is_enabled(&clock->hw)) {
451*4882a593Smuzhiyun 			dev_dbg(dev, "MSTP %s setting CLK_IS_CRITICAL\n",
452*4882a593Smuzhiyun 				mod->name);
453*4882a593Smuzhiyun 			init.flags |= CLK_IS_CRITICAL;
454*4882a593Smuzhiyun 			break;
455*4882a593Smuzhiyun 		}
456*4882a593Smuzhiyun 
457*4882a593Smuzhiyun 	clk = clk_register(NULL, &clock->hw);
458*4882a593Smuzhiyun 	if (IS_ERR(clk))
459*4882a593Smuzhiyun 		goto fail;
460*4882a593Smuzhiyun 
461*4882a593Smuzhiyun 	dev_dbg(dev, "Module clock %pC at %lu Hz\n", clk, clk_get_rate(clk));
462*4882a593Smuzhiyun 	priv->clks[id] = clk;
463*4882a593Smuzhiyun 	priv->smstpcr_saved[clock->index / 32].mask |= BIT(clock->index % 32);
464*4882a593Smuzhiyun 	return;
465*4882a593Smuzhiyun 
466*4882a593Smuzhiyun fail:
467*4882a593Smuzhiyun 	dev_err(dev, "Failed to register %s clock %s: %ld\n", "module",
468*4882a593Smuzhiyun 		mod->name, PTR_ERR(clk));
469*4882a593Smuzhiyun 	kfree(clock);
470*4882a593Smuzhiyun }
471*4882a593Smuzhiyun 
472*4882a593Smuzhiyun struct cpg_mssr_clk_domain {
473*4882a593Smuzhiyun 	struct generic_pm_domain genpd;
474*4882a593Smuzhiyun 	unsigned int num_core_pm_clks;
475*4882a593Smuzhiyun 	unsigned int core_pm_clks[];
476*4882a593Smuzhiyun };
477*4882a593Smuzhiyun 
478*4882a593Smuzhiyun static struct cpg_mssr_clk_domain *cpg_mssr_clk_domain;
479*4882a593Smuzhiyun 
cpg_mssr_is_pm_clk(const struct of_phandle_args * clkspec,struct cpg_mssr_clk_domain * pd)480*4882a593Smuzhiyun static bool cpg_mssr_is_pm_clk(const struct of_phandle_args *clkspec,
481*4882a593Smuzhiyun 			       struct cpg_mssr_clk_domain *pd)
482*4882a593Smuzhiyun {
483*4882a593Smuzhiyun 	unsigned int i;
484*4882a593Smuzhiyun 
485*4882a593Smuzhiyun 	if (clkspec->np != pd->genpd.dev.of_node || clkspec->args_count != 2)
486*4882a593Smuzhiyun 		return false;
487*4882a593Smuzhiyun 
488*4882a593Smuzhiyun 	switch (clkspec->args[0]) {
489*4882a593Smuzhiyun 	case CPG_CORE:
490*4882a593Smuzhiyun 		for (i = 0; i < pd->num_core_pm_clks; i++)
491*4882a593Smuzhiyun 			if (clkspec->args[1] == pd->core_pm_clks[i])
492*4882a593Smuzhiyun 				return true;
493*4882a593Smuzhiyun 		return false;
494*4882a593Smuzhiyun 
495*4882a593Smuzhiyun 	case CPG_MOD:
496*4882a593Smuzhiyun 		return true;
497*4882a593Smuzhiyun 
498*4882a593Smuzhiyun 	default:
499*4882a593Smuzhiyun 		return false;
500*4882a593Smuzhiyun 	}
501*4882a593Smuzhiyun }
502*4882a593Smuzhiyun 
cpg_mssr_attach_dev(struct generic_pm_domain * unused,struct device * dev)503*4882a593Smuzhiyun int cpg_mssr_attach_dev(struct generic_pm_domain *unused, struct device *dev)
504*4882a593Smuzhiyun {
505*4882a593Smuzhiyun 	struct cpg_mssr_clk_domain *pd = cpg_mssr_clk_domain;
506*4882a593Smuzhiyun 	struct device_node *np = dev->of_node;
507*4882a593Smuzhiyun 	struct of_phandle_args clkspec;
508*4882a593Smuzhiyun 	struct clk *clk;
509*4882a593Smuzhiyun 	int i = 0;
510*4882a593Smuzhiyun 	int error;
511*4882a593Smuzhiyun 
512*4882a593Smuzhiyun 	if (!pd) {
513*4882a593Smuzhiyun 		dev_dbg(dev, "CPG/MSSR clock domain not yet available\n");
514*4882a593Smuzhiyun 		return -EPROBE_DEFER;
515*4882a593Smuzhiyun 	}
516*4882a593Smuzhiyun 
517*4882a593Smuzhiyun 	while (!of_parse_phandle_with_args(np, "clocks", "#clock-cells", i,
518*4882a593Smuzhiyun 					   &clkspec)) {
519*4882a593Smuzhiyun 		if (cpg_mssr_is_pm_clk(&clkspec, pd))
520*4882a593Smuzhiyun 			goto found;
521*4882a593Smuzhiyun 
522*4882a593Smuzhiyun 		of_node_put(clkspec.np);
523*4882a593Smuzhiyun 		i++;
524*4882a593Smuzhiyun 	}
525*4882a593Smuzhiyun 
526*4882a593Smuzhiyun 	return 0;
527*4882a593Smuzhiyun 
528*4882a593Smuzhiyun found:
529*4882a593Smuzhiyun 	clk = of_clk_get_from_provider(&clkspec);
530*4882a593Smuzhiyun 	of_node_put(clkspec.np);
531*4882a593Smuzhiyun 
532*4882a593Smuzhiyun 	if (IS_ERR(clk))
533*4882a593Smuzhiyun 		return PTR_ERR(clk);
534*4882a593Smuzhiyun 
535*4882a593Smuzhiyun 	error = pm_clk_create(dev);
536*4882a593Smuzhiyun 	if (error)
537*4882a593Smuzhiyun 		goto fail_put;
538*4882a593Smuzhiyun 
539*4882a593Smuzhiyun 	error = pm_clk_add_clk(dev, clk);
540*4882a593Smuzhiyun 	if (error)
541*4882a593Smuzhiyun 		goto fail_destroy;
542*4882a593Smuzhiyun 
543*4882a593Smuzhiyun 	return 0;
544*4882a593Smuzhiyun 
545*4882a593Smuzhiyun fail_destroy:
546*4882a593Smuzhiyun 	pm_clk_destroy(dev);
547*4882a593Smuzhiyun fail_put:
548*4882a593Smuzhiyun 	clk_put(clk);
549*4882a593Smuzhiyun 	return error;
550*4882a593Smuzhiyun }
551*4882a593Smuzhiyun 
cpg_mssr_detach_dev(struct generic_pm_domain * unused,struct device * dev)552*4882a593Smuzhiyun void cpg_mssr_detach_dev(struct generic_pm_domain *unused, struct device *dev)
553*4882a593Smuzhiyun {
554*4882a593Smuzhiyun 	if (!pm_clk_no_clocks(dev))
555*4882a593Smuzhiyun 		pm_clk_destroy(dev);
556*4882a593Smuzhiyun }
557*4882a593Smuzhiyun 
cpg_mssr_add_clk_domain(struct device * dev,const unsigned int * core_pm_clks,unsigned int num_core_pm_clks)558*4882a593Smuzhiyun static int __init cpg_mssr_add_clk_domain(struct device *dev,
559*4882a593Smuzhiyun 					  const unsigned int *core_pm_clks,
560*4882a593Smuzhiyun 					  unsigned int num_core_pm_clks)
561*4882a593Smuzhiyun {
562*4882a593Smuzhiyun 	struct device_node *np = dev->of_node;
563*4882a593Smuzhiyun 	struct generic_pm_domain *genpd;
564*4882a593Smuzhiyun 	struct cpg_mssr_clk_domain *pd;
565*4882a593Smuzhiyun 	size_t pm_size = num_core_pm_clks * sizeof(core_pm_clks[0]);
566*4882a593Smuzhiyun 
567*4882a593Smuzhiyun 	pd = devm_kzalloc(dev, sizeof(*pd) + pm_size, GFP_KERNEL);
568*4882a593Smuzhiyun 	if (!pd)
569*4882a593Smuzhiyun 		return -ENOMEM;
570*4882a593Smuzhiyun 
571*4882a593Smuzhiyun 	pd->num_core_pm_clks = num_core_pm_clks;
572*4882a593Smuzhiyun 	memcpy(pd->core_pm_clks, core_pm_clks, pm_size);
573*4882a593Smuzhiyun 
574*4882a593Smuzhiyun 	genpd = &pd->genpd;
575*4882a593Smuzhiyun 	genpd->name = np->name;
576*4882a593Smuzhiyun 	genpd->flags = GENPD_FLAG_PM_CLK | GENPD_FLAG_ALWAYS_ON |
577*4882a593Smuzhiyun 		       GENPD_FLAG_ACTIVE_WAKEUP;
578*4882a593Smuzhiyun 	genpd->attach_dev = cpg_mssr_attach_dev;
579*4882a593Smuzhiyun 	genpd->detach_dev = cpg_mssr_detach_dev;
580*4882a593Smuzhiyun 	pm_genpd_init(genpd, &pm_domain_always_on_gov, false);
581*4882a593Smuzhiyun 	cpg_mssr_clk_domain = pd;
582*4882a593Smuzhiyun 
583*4882a593Smuzhiyun 	of_genpd_add_provider_simple(np, genpd);
584*4882a593Smuzhiyun 	return 0;
585*4882a593Smuzhiyun }
586*4882a593Smuzhiyun 
587*4882a593Smuzhiyun #ifdef CONFIG_RESET_CONTROLLER
588*4882a593Smuzhiyun 
589*4882a593Smuzhiyun #define rcdev_to_priv(x)	container_of(x, struct cpg_mssr_priv, rcdev)
590*4882a593Smuzhiyun 
cpg_mssr_reset(struct reset_controller_dev * rcdev,unsigned long id)591*4882a593Smuzhiyun static int cpg_mssr_reset(struct reset_controller_dev *rcdev,
592*4882a593Smuzhiyun 			  unsigned long id)
593*4882a593Smuzhiyun {
594*4882a593Smuzhiyun 	struct cpg_mssr_priv *priv = rcdev_to_priv(rcdev);
595*4882a593Smuzhiyun 	unsigned int reg = id / 32;
596*4882a593Smuzhiyun 	unsigned int bit = id % 32;
597*4882a593Smuzhiyun 	u32 bitmask = BIT(bit);
598*4882a593Smuzhiyun 
599*4882a593Smuzhiyun 	dev_dbg(priv->dev, "reset %u%02u\n", reg, bit);
600*4882a593Smuzhiyun 
601*4882a593Smuzhiyun 	/* Reset module */
602*4882a593Smuzhiyun 	writel(bitmask, priv->base + priv->reset_regs[reg]);
603*4882a593Smuzhiyun 
604*4882a593Smuzhiyun 	/* Wait for at least one cycle of the RCLK clock (@ ca. 32 kHz) */
605*4882a593Smuzhiyun 	udelay(35);
606*4882a593Smuzhiyun 
607*4882a593Smuzhiyun 	/* Release module from reset state */
608*4882a593Smuzhiyun 	writel(bitmask, priv->base + priv->reset_clear_regs[reg]);
609*4882a593Smuzhiyun 
610*4882a593Smuzhiyun 	return 0;
611*4882a593Smuzhiyun }
612*4882a593Smuzhiyun 
cpg_mssr_assert(struct reset_controller_dev * rcdev,unsigned long id)613*4882a593Smuzhiyun static int cpg_mssr_assert(struct reset_controller_dev *rcdev, unsigned long id)
614*4882a593Smuzhiyun {
615*4882a593Smuzhiyun 	struct cpg_mssr_priv *priv = rcdev_to_priv(rcdev);
616*4882a593Smuzhiyun 	unsigned int reg = id / 32;
617*4882a593Smuzhiyun 	unsigned int bit = id % 32;
618*4882a593Smuzhiyun 	u32 bitmask = BIT(bit);
619*4882a593Smuzhiyun 
620*4882a593Smuzhiyun 	dev_dbg(priv->dev, "assert %u%02u\n", reg, bit);
621*4882a593Smuzhiyun 
622*4882a593Smuzhiyun 	writel(bitmask, priv->base + priv->reset_regs[reg]);
623*4882a593Smuzhiyun 	return 0;
624*4882a593Smuzhiyun }
625*4882a593Smuzhiyun 
cpg_mssr_deassert(struct reset_controller_dev * rcdev,unsigned long id)626*4882a593Smuzhiyun static int cpg_mssr_deassert(struct reset_controller_dev *rcdev,
627*4882a593Smuzhiyun 			     unsigned long id)
628*4882a593Smuzhiyun {
629*4882a593Smuzhiyun 	struct cpg_mssr_priv *priv = rcdev_to_priv(rcdev);
630*4882a593Smuzhiyun 	unsigned int reg = id / 32;
631*4882a593Smuzhiyun 	unsigned int bit = id % 32;
632*4882a593Smuzhiyun 	u32 bitmask = BIT(bit);
633*4882a593Smuzhiyun 
634*4882a593Smuzhiyun 	dev_dbg(priv->dev, "deassert %u%02u\n", reg, bit);
635*4882a593Smuzhiyun 
636*4882a593Smuzhiyun 	writel(bitmask, priv->base + priv->reset_clear_regs[reg]);
637*4882a593Smuzhiyun 	return 0;
638*4882a593Smuzhiyun }
639*4882a593Smuzhiyun 
cpg_mssr_status(struct reset_controller_dev * rcdev,unsigned long id)640*4882a593Smuzhiyun static int cpg_mssr_status(struct reset_controller_dev *rcdev,
641*4882a593Smuzhiyun 			   unsigned long id)
642*4882a593Smuzhiyun {
643*4882a593Smuzhiyun 	struct cpg_mssr_priv *priv = rcdev_to_priv(rcdev);
644*4882a593Smuzhiyun 	unsigned int reg = id / 32;
645*4882a593Smuzhiyun 	unsigned int bit = id % 32;
646*4882a593Smuzhiyun 	u32 bitmask = BIT(bit);
647*4882a593Smuzhiyun 
648*4882a593Smuzhiyun 	return !!(readl(priv->base + priv->reset_regs[reg]) & bitmask);
649*4882a593Smuzhiyun }
650*4882a593Smuzhiyun 
651*4882a593Smuzhiyun static const struct reset_control_ops cpg_mssr_reset_ops = {
652*4882a593Smuzhiyun 	.reset = cpg_mssr_reset,
653*4882a593Smuzhiyun 	.assert = cpg_mssr_assert,
654*4882a593Smuzhiyun 	.deassert = cpg_mssr_deassert,
655*4882a593Smuzhiyun 	.status = cpg_mssr_status,
656*4882a593Smuzhiyun };
657*4882a593Smuzhiyun 
cpg_mssr_reset_xlate(struct reset_controller_dev * rcdev,const struct of_phandle_args * reset_spec)658*4882a593Smuzhiyun static int cpg_mssr_reset_xlate(struct reset_controller_dev *rcdev,
659*4882a593Smuzhiyun 				const struct of_phandle_args *reset_spec)
660*4882a593Smuzhiyun {
661*4882a593Smuzhiyun 	struct cpg_mssr_priv *priv = rcdev_to_priv(rcdev);
662*4882a593Smuzhiyun 	unsigned int unpacked = reset_spec->args[0];
663*4882a593Smuzhiyun 	unsigned int idx = MOD_CLK_PACK(unpacked);
664*4882a593Smuzhiyun 
665*4882a593Smuzhiyun 	if (unpacked % 100 > 31 || idx >= rcdev->nr_resets) {
666*4882a593Smuzhiyun 		dev_err(priv->dev, "Invalid reset index %u\n", unpacked);
667*4882a593Smuzhiyun 		return -EINVAL;
668*4882a593Smuzhiyun 	}
669*4882a593Smuzhiyun 
670*4882a593Smuzhiyun 	return idx;
671*4882a593Smuzhiyun }
672*4882a593Smuzhiyun 
cpg_mssr_reset_controller_register(struct cpg_mssr_priv * priv)673*4882a593Smuzhiyun static int cpg_mssr_reset_controller_register(struct cpg_mssr_priv *priv)
674*4882a593Smuzhiyun {
675*4882a593Smuzhiyun 	priv->rcdev.ops = &cpg_mssr_reset_ops;
676*4882a593Smuzhiyun 	priv->rcdev.of_node = priv->dev->of_node;
677*4882a593Smuzhiyun 	priv->rcdev.of_reset_n_cells = 1;
678*4882a593Smuzhiyun 	priv->rcdev.of_xlate = cpg_mssr_reset_xlate;
679*4882a593Smuzhiyun 	priv->rcdev.nr_resets = priv->num_mod_clks;
680*4882a593Smuzhiyun 	return devm_reset_controller_register(priv->dev, &priv->rcdev);
681*4882a593Smuzhiyun }
682*4882a593Smuzhiyun 
683*4882a593Smuzhiyun #else /* !CONFIG_RESET_CONTROLLER */
cpg_mssr_reset_controller_register(struct cpg_mssr_priv * priv)684*4882a593Smuzhiyun static inline int cpg_mssr_reset_controller_register(struct cpg_mssr_priv *priv)
685*4882a593Smuzhiyun {
686*4882a593Smuzhiyun 	return 0;
687*4882a593Smuzhiyun }
688*4882a593Smuzhiyun #endif /* !CONFIG_RESET_CONTROLLER */
689*4882a593Smuzhiyun 
690*4882a593Smuzhiyun 
691*4882a593Smuzhiyun static const struct of_device_id cpg_mssr_match[] = {
692*4882a593Smuzhiyun #ifdef CONFIG_CLK_R7S9210
693*4882a593Smuzhiyun 	{
694*4882a593Smuzhiyun 		.compatible = "renesas,r7s9210-cpg-mssr",
695*4882a593Smuzhiyun 		.data = &r7s9210_cpg_mssr_info,
696*4882a593Smuzhiyun 	},
697*4882a593Smuzhiyun #endif
698*4882a593Smuzhiyun #ifdef CONFIG_CLK_R8A7742
699*4882a593Smuzhiyun 	{
700*4882a593Smuzhiyun 		.compatible = "renesas,r8a7742-cpg-mssr",
701*4882a593Smuzhiyun 		.data = &r8a7742_cpg_mssr_info,
702*4882a593Smuzhiyun 	},
703*4882a593Smuzhiyun #endif
704*4882a593Smuzhiyun #ifdef CONFIG_CLK_R8A7743
705*4882a593Smuzhiyun 	{
706*4882a593Smuzhiyun 		.compatible = "renesas,r8a7743-cpg-mssr",
707*4882a593Smuzhiyun 		.data = &r8a7743_cpg_mssr_info,
708*4882a593Smuzhiyun 	},
709*4882a593Smuzhiyun 	/* RZ/G1N is (almost) identical to RZ/G1M w.r.t. clocks. */
710*4882a593Smuzhiyun 	{
711*4882a593Smuzhiyun 		.compatible = "renesas,r8a7744-cpg-mssr",
712*4882a593Smuzhiyun 		.data = &r8a7743_cpg_mssr_info,
713*4882a593Smuzhiyun 	},
714*4882a593Smuzhiyun #endif
715*4882a593Smuzhiyun #ifdef CONFIG_CLK_R8A7745
716*4882a593Smuzhiyun 	{
717*4882a593Smuzhiyun 		.compatible = "renesas,r8a7745-cpg-mssr",
718*4882a593Smuzhiyun 		.data = &r8a7745_cpg_mssr_info,
719*4882a593Smuzhiyun 	},
720*4882a593Smuzhiyun #endif
721*4882a593Smuzhiyun #ifdef CONFIG_CLK_R8A77470
722*4882a593Smuzhiyun 	{
723*4882a593Smuzhiyun 		.compatible = "renesas,r8a77470-cpg-mssr",
724*4882a593Smuzhiyun 		.data = &r8a77470_cpg_mssr_info,
725*4882a593Smuzhiyun 	},
726*4882a593Smuzhiyun #endif
727*4882a593Smuzhiyun #ifdef CONFIG_CLK_R8A774A1
728*4882a593Smuzhiyun 	{
729*4882a593Smuzhiyun 		.compatible = "renesas,r8a774a1-cpg-mssr",
730*4882a593Smuzhiyun 		.data = &r8a774a1_cpg_mssr_info,
731*4882a593Smuzhiyun 	},
732*4882a593Smuzhiyun #endif
733*4882a593Smuzhiyun #ifdef CONFIG_CLK_R8A774B1
734*4882a593Smuzhiyun 	{
735*4882a593Smuzhiyun 		.compatible = "renesas,r8a774b1-cpg-mssr",
736*4882a593Smuzhiyun 		.data = &r8a774b1_cpg_mssr_info,
737*4882a593Smuzhiyun 	},
738*4882a593Smuzhiyun #endif
739*4882a593Smuzhiyun #ifdef CONFIG_CLK_R8A774C0
740*4882a593Smuzhiyun 	{
741*4882a593Smuzhiyun 		.compatible = "renesas,r8a774c0-cpg-mssr",
742*4882a593Smuzhiyun 		.data = &r8a774c0_cpg_mssr_info,
743*4882a593Smuzhiyun 	},
744*4882a593Smuzhiyun #endif
745*4882a593Smuzhiyun #ifdef CONFIG_CLK_R8A774E1
746*4882a593Smuzhiyun 	{
747*4882a593Smuzhiyun 		.compatible = "renesas,r8a774e1-cpg-mssr",
748*4882a593Smuzhiyun 		.data = &r8a774e1_cpg_mssr_info,
749*4882a593Smuzhiyun 	},
750*4882a593Smuzhiyun #endif
751*4882a593Smuzhiyun #ifdef CONFIG_CLK_R8A7790
752*4882a593Smuzhiyun 	{
753*4882a593Smuzhiyun 		.compatible = "renesas,r8a7790-cpg-mssr",
754*4882a593Smuzhiyun 		.data = &r8a7790_cpg_mssr_info,
755*4882a593Smuzhiyun 	},
756*4882a593Smuzhiyun #endif
757*4882a593Smuzhiyun #ifdef CONFIG_CLK_R8A7791
758*4882a593Smuzhiyun 	{
759*4882a593Smuzhiyun 		.compatible = "renesas,r8a7791-cpg-mssr",
760*4882a593Smuzhiyun 		.data = &r8a7791_cpg_mssr_info,
761*4882a593Smuzhiyun 	},
762*4882a593Smuzhiyun 	/* R-Car M2-N is (almost) identical to R-Car M2-W w.r.t. clocks. */
763*4882a593Smuzhiyun 	{
764*4882a593Smuzhiyun 		.compatible = "renesas,r8a7793-cpg-mssr",
765*4882a593Smuzhiyun 		.data = &r8a7791_cpg_mssr_info,
766*4882a593Smuzhiyun 	},
767*4882a593Smuzhiyun #endif
768*4882a593Smuzhiyun #ifdef CONFIG_CLK_R8A7792
769*4882a593Smuzhiyun 	{
770*4882a593Smuzhiyun 		.compatible = "renesas,r8a7792-cpg-mssr",
771*4882a593Smuzhiyun 		.data = &r8a7792_cpg_mssr_info,
772*4882a593Smuzhiyun 	},
773*4882a593Smuzhiyun #endif
774*4882a593Smuzhiyun #ifdef CONFIG_CLK_R8A7794
775*4882a593Smuzhiyun 	{
776*4882a593Smuzhiyun 		.compatible = "renesas,r8a7794-cpg-mssr",
777*4882a593Smuzhiyun 		.data = &r8a7794_cpg_mssr_info,
778*4882a593Smuzhiyun 	},
779*4882a593Smuzhiyun #endif
780*4882a593Smuzhiyun #ifdef CONFIG_CLK_R8A7795
781*4882a593Smuzhiyun 	{
782*4882a593Smuzhiyun 		.compatible = "renesas,r8a7795-cpg-mssr",
783*4882a593Smuzhiyun 		.data = &r8a7795_cpg_mssr_info,
784*4882a593Smuzhiyun 	},
785*4882a593Smuzhiyun #endif
786*4882a593Smuzhiyun #ifdef CONFIG_CLK_R8A77960
787*4882a593Smuzhiyun 	{
788*4882a593Smuzhiyun 		.compatible = "renesas,r8a7796-cpg-mssr",
789*4882a593Smuzhiyun 		.data = &r8a7796_cpg_mssr_info,
790*4882a593Smuzhiyun 	},
791*4882a593Smuzhiyun #endif
792*4882a593Smuzhiyun #ifdef CONFIG_CLK_R8A77961
793*4882a593Smuzhiyun 	{
794*4882a593Smuzhiyun 		.compatible = "renesas,r8a77961-cpg-mssr",
795*4882a593Smuzhiyun 		.data = &r8a7796_cpg_mssr_info,
796*4882a593Smuzhiyun 	},
797*4882a593Smuzhiyun #endif
798*4882a593Smuzhiyun #ifdef CONFIG_CLK_R8A77965
799*4882a593Smuzhiyun 	{
800*4882a593Smuzhiyun 		.compatible = "renesas,r8a77965-cpg-mssr",
801*4882a593Smuzhiyun 		.data = &r8a77965_cpg_mssr_info,
802*4882a593Smuzhiyun 	},
803*4882a593Smuzhiyun #endif
804*4882a593Smuzhiyun #ifdef CONFIG_CLK_R8A77970
805*4882a593Smuzhiyun 	{
806*4882a593Smuzhiyun 		.compatible = "renesas,r8a77970-cpg-mssr",
807*4882a593Smuzhiyun 		.data = &r8a77970_cpg_mssr_info,
808*4882a593Smuzhiyun 	},
809*4882a593Smuzhiyun #endif
810*4882a593Smuzhiyun #ifdef CONFIG_CLK_R8A77980
811*4882a593Smuzhiyun 	{
812*4882a593Smuzhiyun 		.compatible = "renesas,r8a77980-cpg-mssr",
813*4882a593Smuzhiyun 		.data = &r8a77980_cpg_mssr_info,
814*4882a593Smuzhiyun 	},
815*4882a593Smuzhiyun #endif
816*4882a593Smuzhiyun #ifdef CONFIG_CLK_R8A77990
817*4882a593Smuzhiyun 	{
818*4882a593Smuzhiyun 		.compatible = "renesas,r8a77990-cpg-mssr",
819*4882a593Smuzhiyun 		.data = &r8a77990_cpg_mssr_info,
820*4882a593Smuzhiyun 	},
821*4882a593Smuzhiyun #endif
822*4882a593Smuzhiyun #ifdef CONFIG_CLK_R8A77995
823*4882a593Smuzhiyun 	{
824*4882a593Smuzhiyun 		.compatible = "renesas,r8a77995-cpg-mssr",
825*4882a593Smuzhiyun 		.data = &r8a77995_cpg_mssr_info,
826*4882a593Smuzhiyun 	},
827*4882a593Smuzhiyun #endif
828*4882a593Smuzhiyun #ifdef CONFIG_CLK_R8A779A0
829*4882a593Smuzhiyun 	{
830*4882a593Smuzhiyun 		.compatible = "renesas,r8a779a0-cpg-mssr",
831*4882a593Smuzhiyun 		.data = &r8a779a0_cpg_mssr_info,
832*4882a593Smuzhiyun 	},
833*4882a593Smuzhiyun #endif
834*4882a593Smuzhiyun 	{ /* sentinel */ }
835*4882a593Smuzhiyun };
836*4882a593Smuzhiyun 
cpg_mssr_del_clk_provider(void * data)837*4882a593Smuzhiyun static void cpg_mssr_del_clk_provider(void *data)
838*4882a593Smuzhiyun {
839*4882a593Smuzhiyun 	of_clk_del_provider(data);
840*4882a593Smuzhiyun }
841*4882a593Smuzhiyun 
842*4882a593Smuzhiyun #if defined(CONFIG_PM_SLEEP) && defined(CONFIG_ARM_PSCI_FW)
cpg_mssr_suspend_noirq(struct device * dev)843*4882a593Smuzhiyun static int cpg_mssr_suspend_noirq(struct device *dev)
844*4882a593Smuzhiyun {
845*4882a593Smuzhiyun 	struct cpg_mssr_priv *priv = dev_get_drvdata(dev);
846*4882a593Smuzhiyun 	unsigned int reg;
847*4882a593Smuzhiyun 
848*4882a593Smuzhiyun 	/* This is the best we can do to check for the presence of PSCI */
849*4882a593Smuzhiyun 	if (!psci_ops.cpu_suspend)
850*4882a593Smuzhiyun 		return 0;
851*4882a593Smuzhiyun 
852*4882a593Smuzhiyun 	/* Save module registers with bits under our control */
853*4882a593Smuzhiyun 	for (reg = 0; reg < ARRAY_SIZE(priv->smstpcr_saved); reg++) {
854*4882a593Smuzhiyun 		if (priv->smstpcr_saved[reg].mask)
855*4882a593Smuzhiyun 			priv->smstpcr_saved[reg].val =
856*4882a593Smuzhiyun 				priv->reg_layout == CLK_REG_LAYOUT_RZ_A ?
857*4882a593Smuzhiyun 				readb(priv->base + priv->control_regs[reg]) :
858*4882a593Smuzhiyun 				readl(priv->base + priv->control_regs[reg]);
859*4882a593Smuzhiyun 	}
860*4882a593Smuzhiyun 
861*4882a593Smuzhiyun 	/* Save core clocks */
862*4882a593Smuzhiyun 	raw_notifier_call_chain(&priv->notifiers, PM_EVENT_SUSPEND, NULL);
863*4882a593Smuzhiyun 
864*4882a593Smuzhiyun 	return 0;
865*4882a593Smuzhiyun }
866*4882a593Smuzhiyun 
cpg_mssr_resume_noirq(struct device * dev)867*4882a593Smuzhiyun static int cpg_mssr_resume_noirq(struct device *dev)
868*4882a593Smuzhiyun {
869*4882a593Smuzhiyun 	struct cpg_mssr_priv *priv = dev_get_drvdata(dev);
870*4882a593Smuzhiyun 	unsigned int reg, i;
871*4882a593Smuzhiyun 	u32 mask, oldval, newval;
872*4882a593Smuzhiyun 
873*4882a593Smuzhiyun 	/* This is the best we can do to check for the presence of PSCI */
874*4882a593Smuzhiyun 	if (!psci_ops.cpu_suspend)
875*4882a593Smuzhiyun 		return 0;
876*4882a593Smuzhiyun 
877*4882a593Smuzhiyun 	/* Restore core clocks */
878*4882a593Smuzhiyun 	raw_notifier_call_chain(&priv->notifiers, PM_EVENT_RESUME, NULL);
879*4882a593Smuzhiyun 
880*4882a593Smuzhiyun 	/* Restore module clocks */
881*4882a593Smuzhiyun 	for (reg = 0; reg < ARRAY_SIZE(priv->smstpcr_saved); reg++) {
882*4882a593Smuzhiyun 		mask = priv->smstpcr_saved[reg].mask;
883*4882a593Smuzhiyun 		if (!mask)
884*4882a593Smuzhiyun 			continue;
885*4882a593Smuzhiyun 
886*4882a593Smuzhiyun 		if (priv->reg_layout == CLK_REG_LAYOUT_RZ_A)
887*4882a593Smuzhiyun 			oldval = readb(priv->base + priv->control_regs[reg]);
888*4882a593Smuzhiyun 		else
889*4882a593Smuzhiyun 			oldval = readl(priv->base + priv->control_regs[reg]);
890*4882a593Smuzhiyun 		newval = oldval & ~mask;
891*4882a593Smuzhiyun 		newval |= priv->smstpcr_saved[reg].val & mask;
892*4882a593Smuzhiyun 		if (newval == oldval)
893*4882a593Smuzhiyun 			continue;
894*4882a593Smuzhiyun 
895*4882a593Smuzhiyun 		if (priv->reg_layout == CLK_REG_LAYOUT_RZ_A) {
896*4882a593Smuzhiyun 			writeb(newval, priv->base + priv->control_regs[reg]);
897*4882a593Smuzhiyun 			/* dummy read to ensure write has completed */
898*4882a593Smuzhiyun 			readb(priv->base + priv->control_regs[reg]);
899*4882a593Smuzhiyun 			barrier_data(priv->base + priv->control_regs[reg]);
900*4882a593Smuzhiyun 			continue;
901*4882a593Smuzhiyun 		} else
902*4882a593Smuzhiyun 			writel(newval, priv->base + priv->control_regs[reg]);
903*4882a593Smuzhiyun 
904*4882a593Smuzhiyun 		/* Wait until enabled clocks are really enabled */
905*4882a593Smuzhiyun 		mask &= ~priv->smstpcr_saved[reg].val;
906*4882a593Smuzhiyun 		if (!mask)
907*4882a593Smuzhiyun 			continue;
908*4882a593Smuzhiyun 
909*4882a593Smuzhiyun 		for (i = 1000; i > 0; --i) {
910*4882a593Smuzhiyun 			oldval = readl(priv->base + priv->status_regs[reg]);
911*4882a593Smuzhiyun 			if (!(oldval & mask))
912*4882a593Smuzhiyun 				break;
913*4882a593Smuzhiyun 			cpu_relax();
914*4882a593Smuzhiyun 		}
915*4882a593Smuzhiyun 
916*4882a593Smuzhiyun 		if (!i)
917*4882a593Smuzhiyun 			dev_warn(dev, "Failed to enable %s%u[0x%x]\n",
918*4882a593Smuzhiyun 				 priv->reg_layout == CLK_REG_LAYOUT_RZ_A ?
919*4882a593Smuzhiyun 				 "STB" : "SMSTP", reg, oldval & mask);
920*4882a593Smuzhiyun 	}
921*4882a593Smuzhiyun 
922*4882a593Smuzhiyun 	return 0;
923*4882a593Smuzhiyun }
924*4882a593Smuzhiyun 
925*4882a593Smuzhiyun static const struct dev_pm_ops cpg_mssr_pm = {
926*4882a593Smuzhiyun 	SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(cpg_mssr_suspend_noirq,
927*4882a593Smuzhiyun 				      cpg_mssr_resume_noirq)
928*4882a593Smuzhiyun };
929*4882a593Smuzhiyun #define DEV_PM_OPS	&cpg_mssr_pm
930*4882a593Smuzhiyun #else
931*4882a593Smuzhiyun #define DEV_PM_OPS	NULL
932*4882a593Smuzhiyun #endif /* CONFIG_PM_SLEEP && CONFIG_ARM_PSCI_FW */
933*4882a593Smuzhiyun 
cpg_mssr_common_init(struct device * dev,struct device_node * np,const struct cpg_mssr_info * info)934*4882a593Smuzhiyun static int __init cpg_mssr_common_init(struct device *dev,
935*4882a593Smuzhiyun 				       struct device_node *np,
936*4882a593Smuzhiyun 				       const struct cpg_mssr_info *info)
937*4882a593Smuzhiyun {
938*4882a593Smuzhiyun 	struct cpg_mssr_priv *priv;
939*4882a593Smuzhiyun 	unsigned int nclks, i;
940*4882a593Smuzhiyun 	int error;
941*4882a593Smuzhiyun 
942*4882a593Smuzhiyun 	if (info->init) {
943*4882a593Smuzhiyun 		error = info->init(dev);
944*4882a593Smuzhiyun 		if (error)
945*4882a593Smuzhiyun 			return error;
946*4882a593Smuzhiyun 	}
947*4882a593Smuzhiyun 
948*4882a593Smuzhiyun 	nclks = info->num_total_core_clks + info->num_hw_mod_clks;
949*4882a593Smuzhiyun 	priv = kzalloc(struct_size(priv, clks, nclks), GFP_KERNEL);
950*4882a593Smuzhiyun 	if (!priv)
951*4882a593Smuzhiyun 		return -ENOMEM;
952*4882a593Smuzhiyun 
953*4882a593Smuzhiyun 	priv->np = np;
954*4882a593Smuzhiyun 	priv->dev = dev;
955*4882a593Smuzhiyun 	spin_lock_init(&priv->rmw_lock);
956*4882a593Smuzhiyun 
957*4882a593Smuzhiyun 	priv->base = of_iomap(np, 0);
958*4882a593Smuzhiyun 	if (!priv->base) {
959*4882a593Smuzhiyun 		error = -ENOMEM;
960*4882a593Smuzhiyun 		goto out_err;
961*4882a593Smuzhiyun 	}
962*4882a593Smuzhiyun 
963*4882a593Smuzhiyun 	cpg_mssr_priv = priv;
964*4882a593Smuzhiyun 	priv->num_core_clks = info->num_total_core_clks;
965*4882a593Smuzhiyun 	priv->num_mod_clks = info->num_hw_mod_clks;
966*4882a593Smuzhiyun 	priv->last_dt_core_clk = info->last_dt_core_clk;
967*4882a593Smuzhiyun 	RAW_INIT_NOTIFIER_HEAD(&priv->notifiers);
968*4882a593Smuzhiyun 	priv->reg_layout = info->reg_layout;
969*4882a593Smuzhiyun 	if (priv->reg_layout == CLK_REG_LAYOUT_RCAR_GEN2_AND_GEN3) {
970*4882a593Smuzhiyun 		priv->status_regs = mstpsr;
971*4882a593Smuzhiyun 		priv->control_regs = smstpcr;
972*4882a593Smuzhiyun 		priv->reset_regs = srcr;
973*4882a593Smuzhiyun 		priv->reset_clear_regs = srstclr;
974*4882a593Smuzhiyun 	} else if (priv->reg_layout == CLK_REG_LAYOUT_RZ_A) {
975*4882a593Smuzhiyun 		priv->control_regs = stbcr;
976*4882a593Smuzhiyun 	} else if (priv->reg_layout == CLK_REG_LAYOUT_RCAR_V3U) {
977*4882a593Smuzhiyun 		priv->status_regs = mstpsr_for_v3u;
978*4882a593Smuzhiyun 		priv->control_regs = mstpcr_for_v3u;
979*4882a593Smuzhiyun 		priv->reset_regs = srcr_for_v3u;
980*4882a593Smuzhiyun 		priv->reset_clear_regs = srstclr_for_v3u;
981*4882a593Smuzhiyun 	} else {
982*4882a593Smuzhiyun 		error = -EINVAL;
983*4882a593Smuzhiyun 		goto out_err;
984*4882a593Smuzhiyun 	}
985*4882a593Smuzhiyun 
986*4882a593Smuzhiyun 	for (i = 0; i < nclks; i++)
987*4882a593Smuzhiyun 		priv->clks[i] = ERR_PTR(-ENOENT);
988*4882a593Smuzhiyun 
989*4882a593Smuzhiyun 	error = of_clk_add_provider(np, cpg_mssr_clk_src_twocell_get, priv);
990*4882a593Smuzhiyun 	if (error)
991*4882a593Smuzhiyun 		goto out_err;
992*4882a593Smuzhiyun 
993*4882a593Smuzhiyun 	return 0;
994*4882a593Smuzhiyun 
995*4882a593Smuzhiyun out_err:
996*4882a593Smuzhiyun 	if (priv->base)
997*4882a593Smuzhiyun 		iounmap(priv->base);
998*4882a593Smuzhiyun 	kfree(priv);
999*4882a593Smuzhiyun 
1000*4882a593Smuzhiyun 	return error;
1001*4882a593Smuzhiyun }
1002*4882a593Smuzhiyun 
cpg_mssr_early_init(struct device_node * np,const struct cpg_mssr_info * info)1003*4882a593Smuzhiyun void __init cpg_mssr_early_init(struct device_node *np,
1004*4882a593Smuzhiyun 				const struct cpg_mssr_info *info)
1005*4882a593Smuzhiyun {
1006*4882a593Smuzhiyun 	int error;
1007*4882a593Smuzhiyun 	int i;
1008*4882a593Smuzhiyun 
1009*4882a593Smuzhiyun 	error = cpg_mssr_common_init(NULL, np, info);
1010*4882a593Smuzhiyun 	if (error)
1011*4882a593Smuzhiyun 		return;
1012*4882a593Smuzhiyun 
1013*4882a593Smuzhiyun 	for (i = 0; i < info->num_early_core_clks; i++)
1014*4882a593Smuzhiyun 		cpg_mssr_register_core_clk(&info->early_core_clks[i], info,
1015*4882a593Smuzhiyun 					   cpg_mssr_priv);
1016*4882a593Smuzhiyun 
1017*4882a593Smuzhiyun 	for (i = 0; i < info->num_early_mod_clks; i++)
1018*4882a593Smuzhiyun 		cpg_mssr_register_mod_clk(&info->early_mod_clks[i], info,
1019*4882a593Smuzhiyun 					  cpg_mssr_priv);
1020*4882a593Smuzhiyun 
1021*4882a593Smuzhiyun }
1022*4882a593Smuzhiyun 
cpg_mssr_probe(struct platform_device * pdev)1023*4882a593Smuzhiyun static int __init cpg_mssr_probe(struct platform_device *pdev)
1024*4882a593Smuzhiyun {
1025*4882a593Smuzhiyun 	struct device *dev = &pdev->dev;
1026*4882a593Smuzhiyun 	struct device_node *np = dev->of_node;
1027*4882a593Smuzhiyun 	const struct cpg_mssr_info *info;
1028*4882a593Smuzhiyun 	struct cpg_mssr_priv *priv;
1029*4882a593Smuzhiyun 	unsigned int i;
1030*4882a593Smuzhiyun 	int error;
1031*4882a593Smuzhiyun 
1032*4882a593Smuzhiyun 	info = of_device_get_match_data(dev);
1033*4882a593Smuzhiyun 
1034*4882a593Smuzhiyun 	if (!cpg_mssr_priv) {
1035*4882a593Smuzhiyun 		error = cpg_mssr_common_init(dev, dev->of_node, info);
1036*4882a593Smuzhiyun 		if (error)
1037*4882a593Smuzhiyun 			return error;
1038*4882a593Smuzhiyun 	}
1039*4882a593Smuzhiyun 
1040*4882a593Smuzhiyun 	priv = cpg_mssr_priv;
1041*4882a593Smuzhiyun 	priv->dev = dev;
1042*4882a593Smuzhiyun 	dev_set_drvdata(dev, priv);
1043*4882a593Smuzhiyun 
1044*4882a593Smuzhiyun 	for (i = 0; i < info->num_core_clks; i++)
1045*4882a593Smuzhiyun 		cpg_mssr_register_core_clk(&info->core_clks[i], info, priv);
1046*4882a593Smuzhiyun 
1047*4882a593Smuzhiyun 	for (i = 0; i < info->num_mod_clks; i++)
1048*4882a593Smuzhiyun 		cpg_mssr_register_mod_clk(&info->mod_clks[i], info, priv);
1049*4882a593Smuzhiyun 
1050*4882a593Smuzhiyun 	error = devm_add_action_or_reset(dev,
1051*4882a593Smuzhiyun 					 cpg_mssr_del_clk_provider,
1052*4882a593Smuzhiyun 					 np);
1053*4882a593Smuzhiyun 	if (error)
1054*4882a593Smuzhiyun 		return error;
1055*4882a593Smuzhiyun 
1056*4882a593Smuzhiyun 	error = cpg_mssr_add_clk_domain(dev, info->core_pm_clks,
1057*4882a593Smuzhiyun 					info->num_core_pm_clks);
1058*4882a593Smuzhiyun 	if (error)
1059*4882a593Smuzhiyun 		return error;
1060*4882a593Smuzhiyun 
1061*4882a593Smuzhiyun 	/* Reset Controller not supported for Standby Control SoCs */
1062*4882a593Smuzhiyun 	if (priv->reg_layout == CLK_REG_LAYOUT_RZ_A)
1063*4882a593Smuzhiyun 		return 0;
1064*4882a593Smuzhiyun 
1065*4882a593Smuzhiyun 	error = cpg_mssr_reset_controller_register(priv);
1066*4882a593Smuzhiyun 	if (error)
1067*4882a593Smuzhiyun 		return error;
1068*4882a593Smuzhiyun 
1069*4882a593Smuzhiyun 	return 0;
1070*4882a593Smuzhiyun }
1071*4882a593Smuzhiyun 
1072*4882a593Smuzhiyun static struct platform_driver cpg_mssr_driver = {
1073*4882a593Smuzhiyun 	.driver		= {
1074*4882a593Smuzhiyun 		.name	= "renesas-cpg-mssr",
1075*4882a593Smuzhiyun 		.of_match_table = cpg_mssr_match,
1076*4882a593Smuzhiyun 		.pm = DEV_PM_OPS,
1077*4882a593Smuzhiyun 	},
1078*4882a593Smuzhiyun };
1079*4882a593Smuzhiyun 
cpg_mssr_init(void)1080*4882a593Smuzhiyun static int __init cpg_mssr_init(void)
1081*4882a593Smuzhiyun {
1082*4882a593Smuzhiyun 	return platform_driver_probe(&cpg_mssr_driver, cpg_mssr_probe);
1083*4882a593Smuzhiyun }
1084*4882a593Smuzhiyun 
1085*4882a593Smuzhiyun subsys_initcall(cpg_mssr_init);
1086*4882a593Smuzhiyun 
cpg_core_nullify_range(struct cpg_core_clk * core_clks,unsigned int num_core_clks,unsigned int first_clk,unsigned int last_clk)1087*4882a593Smuzhiyun void __init cpg_core_nullify_range(struct cpg_core_clk *core_clks,
1088*4882a593Smuzhiyun 				   unsigned int num_core_clks,
1089*4882a593Smuzhiyun 				   unsigned int first_clk,
1090*4882a593Smuzhiyun 				   unsigned int last_clk)
1091*4882a593Smuzhiyun {
1092*4882a593Smuzhiyun 	unsigned int i;
1093*4882a593Smuzhiyun 
1094*4882a593Smuzhiyun 	for (i = 0; i < num_core_clks; i++)
1095*4882a593Smuzhiyun 		if (core_clks[i].id >= first_clk &&
1096*4882a593Smuzhiyun 		    core_clks[i].id <= last_clk)
1097*4882a593Smuzhiyun 			core_clks[i].name = NULL;
1098*4882a593Smuzhiyun }
1099*4882a593Smuzhiyun 
mssr_mod_nullify(struct mssr_mod_clk * mod_clks,unsigned int num_mod_clks,const unsigned int * clks,unsigned int n)1100*4882a593Smuzhiyun void __init mssr_mod_nullify(struct mssr_mod_clk *mod_clks,
1101*4882a593Smuzhiyun 			     unsigned int num_mod_clks,
1102*4882a593Smuzhiyun 			     const unsigned int *clks, unsigned int n)
1103*4882a593Smuzhiyun {
1104*4882a593Smuzhiyun 	unsigned int i, j;
1105*4882a593Smuzhiyun 
1106*4882a593Smuzhiyun 	for (i = 0, j = 0; i < num_mod_clks && j < n; i++)
1107*4882a593Smuzhiyun 		if (mod_clks[i].id == clks[j]) {
1108*4882a593Smuzhiyun 			mod_clks[i].name = NULL;
1109*4882a593Smuzhiyun 			j++;
1110*4882a593Smuzhiyun 		}
1111*4882a593Smuzhiyun }
1112*4882a593Smuzhiyun 
mssr_mod_reparent(struct mssr_mod_clk * mod_clks,unsigned int num_mod_clks,const struct mssr_mod_reparent * clks,unsigned int n)1113*4882a593Smuzhiyun void __init mssr_mod_reparent(struct mssr_mod_clk *mod_clks,
1114*4882a593Smuzhiyun 			      unsigned int num_mod_clks,
1115*4882a593Smuzhiyun 			      const struct mssr_mod_reparent *clks,
1116*4882a593Smuzhiyun 			      unsigned int n)
1117*4882a593Smuzhiyun {
1118*4882a593Smuzhiyun 	unsigned int i, j;
1119*4882a593Smuzhiyun 
1120*4882a593Smuzhiyun 	for (i = 0, j = 0; i < num_mod_clks && j < n; i++)
1121*4882a593Smuzhiyun 		if (mod_clks[i].id == clks[j].clk) {
1122*4882a593Smuzhiyun 			mod_clks[i].parent = clks[j].parent;
1123*4882a593Smuzhiyun 			j++;
1124*4882a593Smuzhiyun 		}
1125*4882a593Smuzhiyun }
1126*4882a593Smuzhiyun 
1127*4882a593Smuzhiyun MODULE_DESCRIPTION("Renesas CPG/MSSR Driver");
1128*4882a593Smuzhiyun MODULE_LICENSE("GPL v2");
1129