1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Renesas RCar Gen3 CPG MSSR driver
4  *
5  * Copyright (C) 2018 Marek Vasut <marek.vasut@gmail.com>
6  *
7  * Based on the following driver from Linux kernel:
8  * r8a7796 Clock Pulse Generator / Module Standby and Software Reset
9  *
10  * Copyright (C) 2016 Glider bvba
11  */
12 #include <common.h>
13 #include <clk-uclass.h>
14 #include <dm.h>
15 #include <errno.h>
16 #include <log.h>
17 #include <wait_bit.h>
18 #include <asm/io.h>
19 #include <linux/bitops.h>
20 
21 #include <dt-bindings/clock/renesas-cpg-mssr.h>
22 
23 #include "renesas-cpg-mssr.h"
24 
25 /*
26  * Module Standby and Software Reset register offets.
27  *
28  * If the registers exist, these are valid for SH-Mobile, R-Mobile,
29  * R-Car Gen2, R-Car Gen3, and RZ/G1.
30  * These are NOT valid for R-Car Gen1 and RZ/A1!
31  */
32 
33 /*
34  * Module Stop Status Register offsets
35  */
36 
37 static const u16 mstpsr[] = {
38 	0x030, 0x038, 0x040, 0x048, 0x04C, 0x03C, 0x1C0, 0x1C4,
39 	0x9A0, 0x9A4, 0x9A8, 0x9AC,
40 };
41 
42 #define	MSTPSR(i)	mstpsr[i]
43 
44 
45 /*
46  * System Module Stop Control Register offsets
47  */
48 
49 static const u16 smstpcr[] = {
50 	0x130, 0x134, 0x138, 0x13C, 0x140, 0x144, 0x148, 0x14C,
51 	0x990, 0x994, 0x998, 0x99C,
52 };
53 
54 #define	SMSTPCR(i)	smstpcr[i]
55 
56 
57 /* Realtime Module Stop Control Register offsets */
58 #define RMSTPCR(i)	(smstpcr[i] - 0x20)
59 
60 /* Modem Module Stop Control Register offsets (r8a73a4) */
61 #define MMSTPCR(i)	(smstpcr[i] + 0x20)
62 
63 /* Software Reset Clearing Register offsets */
64 #define	SRSTCLR(i)	(0x940 + (i) * 4)
65 
renesas_clk_is_mod(struct clk * clk)66 bool renesas_clk_is_mod(struct clk *clk)
67 {
68 	return (clk->id >> 16) == CPG_MOD;
69 }
70 
renesas_clk_get_mod(struct clk * clk,struct cpg_mssr_info * info,const struct mssr_mod_clk ** mssr)71 int renesas_clk_get_mod(struct clk *clk, struct cpg_mssr_info *info,
72 			const struct mssr_mod_clk **mssr)
73 {
74 	const unsigned long clkid = clk->id & 0xffff;
75 	int i;
76 
77 	for (i = 0; i < info->mod_clk_size; i++) {
78 		if (info->mod_clk[i].id !=
79 		    (info->mod_clk_base + MOD_CLK_PACK(clkid)))
80 			continue;
81 
82 		*mssr = &info->mod_clk[i];
83 		return 0;
84 	}
85 
86 	return -ENODEV;
87 }
88 
renesas_clk_get_core(struct clk * clk,struct cpg_mssr_info * info,const struct cpg_core_clk ** core)89 int renesas_clk_get_core(struct clk *clk, struct cpg_mssr_info *info,
90 			 const struct cpg_core_clk **core)
91 {
92 	const unsigned long clkid = clk->id & 0xffff;
93 	int i;
94 
95 	for (i = 0; i < info->core_clk_size; i++) {
96 		if (info->core_clk[i].id != clkid)
97 			continue;
98 
99 		*core = &info->core_clk[i];
100 		return 0;
101 	}
102 
103 	return -ENODEV;
104 }
105 
renesas_clk_get_parent(struct clk * clk,struct cpg_mssr_info * info,struct clk * parent)106 int renesas_clk_get_parent(struct clk *clk, struct cpg_mssr_info *info,
107 			   struct clk *parent)
108 {
109 	const struct cpg_core_clk *core;
110 	const struct mssr_mod_clk *mssr;
111 	int ret;
112 
113 	if (renesas_clk_is_mod(clk)) {
114 		ret = renesas_clk_get_mod(clk, info, &mssr);
115 		if (ret)
116 			return ret;
117 
118 		parent->id = mssr->parent;
119 	} else {
120 		ret = renesas_clk_get_core(clk, info, &core);
121 		if (ret)
122 			return ret;
123 
124 		if (core->type == CLK_TYPE_IN)
125 			parent->id = ~0;	/* Top-level clock */
126 		else
127 			parent->id = core->parent;
128 	}
129 
130 	parent->dev = clk->dev;
131 
132 	return 0;
133 }
134 
renesas_clk_endisable(struct clk * clk,void __iomem * base,bool enable)135 int renesas_clk_endisable(struct clk *clk, void __iomem *base, bool enable)
136 {
137 	const unsigned long clkid = clk->id & 0xffff;
138 	const unsigned int reg = clkid / 100;
139 	const unsigned int bit = clkid % 100;
140 	const u32 bitmask = BIT(bit);
141 
142 	if (!renesas_clk_is_mod(clk))
143 		return -EINVAL;
144 
145 	debug("%s[%i] MSTP %lu=%02u/%02u %s\n", __func__, __LINE__,
146 	      clkid, reg, bit, enable ? "ON" : "OFF");
147 
148 	if (enable) {
149 		clrbits_le32(base + SMSTPCR(reg), bitmask);
150 		return wait_for_bit_le32(base + MSTPSR(reg),
151 				    bitmask, 0, 100, 0);
152 	} else {
153 		setbits_le32(base + SMSTPCR(reg), bitmask);
154 		return 0;
155 	}
156 }
157 
renesas_clk_remove(void __iomem * base,struct cpg_mssr_info * info)158 int renesas_clk_remove(void __iomem *base, struct cpg_mssr_info *info)
159 {
160 	unsigned int i;
161 
162 	/* Stop TMU0 */
163 	clrbits_le32(TMU_BASE + TSTR0, TSTR0_STR0);
164 
165 	/* Stop module clock */
166 	for (i = 0; i < info->mstp_table_size; i++) {
167 		clrsetbits_le32(base + SMSTPCR(i),
168 				info->mstp_table[i].sdis,
169 				info->mstp_table[i].sen);
170 		clrsetbits_le32(base + RMSTPCR(i),
171 				info->mstp_table[i].rdis,
172 				info->mstp_table[i].ren);
173 	}
174 
175 	return 0;
176 }
177