1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Sophgo SG2042 RP clock Driver
4 *
5 * Copyright (C) 2024 Sophgo Technology Inc.
6 * Copyright (C) 2024 Chen Wang <unicorn_wang@outlook.com>
7 */
8
9 #include <linux/array_size.h>
10 #include <linux/clk-provider.h>
11 #include <linux/platform_device.h>
12
13 #include <dt-bindings/clock/sophgo,sg2042-rpgate.h>
14
15 #include "clk-sg2042.h"
16
17 #define R_SYSGATE_BEGIN 0x0368
18 #define R_RP_RXU_CLK_ENABLE (0x0368 - R_SYSGATE_BEGIN)
19 #define R_MP0_STATUS_REG (0x0380 - R_SYSGATE_BEGIN)
20 #define R_MP0_CONTROL_REG (0x0384 - R_SYSGATE_BEGIN)
21 #define R_MP1_STATUS_REG (0x0388 - R_SYSGATE_BEGIN)
22 #define R_MP1_CONTROL_REG (0x038C - R_SYSGATE_BEGIN)
23 #define R_MP2_STATUS_REG (0x0390 - R_SYSGATE_BEGIN)
24 #define R_MP2_CONTROL_REG (0x0394 - R_SYSGATE_BEGIN)
25 #define R_MP3_STATUS_REG (0x0398 - R_SYSGATE_BEGIN)
26 #define R_MP3_CONTROL_REG (0x039C - R_SYSGATE_BEGIN)
27 #define R_MP4_STATUS_REG (0x03A0 - R_SYSGATE_BEGIN)
28 #define R_MP4_CONTROL_REG (0x03A4 - R_SYSGATE_BEGIN)
29 #define R_MP5_STATUS_REG (0x03A8 - R_SYSGATE_BEGIN)
30 #define R_MP5_CONTROL_REG (0x03AC - R_SYSGATE_BEGIN)
31 #define R_MP6_STATUS_REG (0x03B0 - R_SYSGATE_BEGIN)
32 #define R_MP6_CONTROL_REG (0x03B4 - R_SYSGATE_BEGIN)
33 #define R_MP7_STATUS_REG (0x03B8 - R_SYSGATE_BEGIN)
34 #define R_MP7_CONTROL_REG (0x03BC - R_SYSGATE_BEGIN)
35 #define R_MP8_STATUS_REG (0x03C0 - R_SYSGATE_BEGIN)
36 #define R_MP8_CONTROL_REG (0x03C4 - R_SYSGATE_BEGIN)
37 #define R_MP9_STATUS_REG (0x03C8 - R_SYSGATE_BEGIN)
38 #define R_MP9_CONTROL_REG (0x03CC - R_SYSGATE_BEGIN)
39 #define R_MP10_STATUS_REG (0x03D0 - R_SYSGATE_BEGIN)
40 #define R_MP10_CONTROL_REG (0x03D4 - R_SYSGATE_BEGIN)
41 #define R_MP11_STATUS_REG (0x03D8 - R_SYSGATE_BEGIN)
42 #define R_MP11_CONTROL_REG (0x03DC - R_SYSGATE_BEGIN)
43 #define R_MP12_STATUS_REG (0x03E0 - R_SYSGATE_BEGIN)
44 #define R_MP12_CONTROL_REG (0x03E4 - R_SYSGATE_BEGIN)
45 #define R_MP13_STATUS_REG (0x03E8 - R_SYSGATE_BEGIN)
46 #define R_MP13_CONTROL_REG (0x03EC - R_SYSGATE_BEGIN)
47 #define R_MP14_STATUS_REG (0x03F0 - R_SYSGATE_BEGIN)
48 #define R_MP14_CONTROL_REG (0x03F4 - R_SYSGATE_BEGIN)
49 #define R_MP15_STATUS_REG (0x03F8 - R_SYSGATE_BEGIN)
50 #define R_MP15_CONTROL_REG (0x03FC - R_SYSGATE_BEGIN)
51
52 /**
53 * struct sg2042_rpgate_clock - Gate clock for RP(riscv processors) subsystem
54 * @hw: clk_hw for initialization
55 * @id: used to map clk_onecell_data
56 * @offset_enable: offset of gate enable registers
57 * @bit_idx: which bit in the register controls gating of this clock
58 */
59 struct sg2042_rpgate_clock {
60 struct clk_hw hw;
61
62 unsigned int id;
63
64 u32 offset_enable;
65 u8 bit_idx;
66 };
67
68 /*
69 * Clock initialization macro naming rules:
70 * FW: use CLK_HW_INIT_FW_NAME
71 */
72 #define SG2042_GATE_FW(_id, _name, _parent, _flags, \
73 _r_enable, _bit_idx) { \
74 .hw.init = CLK_HW_INIT_FW_NAME( \
75 _name, \
76 _parent, \
77 NULL, \
78 _flags), \
79 .id = _id, \
80 .offset_enable = _r_enable, \
81 .bit_idx = _bit_idx, \
82 }
83
84 /*
85 * Gate clocks for RP subsystem (including the MP subsystem), which control
86 * registers are defined in SYS_CTRL.
87 */
88 static const struct sg2042_rpgate_clock sg2042_gate_rp[] = {
89 /* downstream of clk_gate_rp_cpu_normal about rxu */
90 SG2042_GATE_FW(GATE_CLK_RXU0, "clk_gate_rxu0", "rpgate",
91 0, R_RP_RXU_CLK_ENABLE, 0),
92 SG2042_GATE_FW(GATE_CLK_RXU1, "clk_gate_rxu1", "rpgate",
93 0, R_RP_RXU_CLK_ENABLE, 1),
94 SG2042_GATE_FW(GATE_CLK_RXU2, "clk_gate_rxu2", "rpgate",
95 0, R_RP_RXU_CLK_ENABLE, 2),
96 SG2042_GATE_FW(GATE_CLK_RXU3, "clk_gate_rxu3", "rpgate",
97 0, R_RP_RXU_CLK_ENABLE, 3),
98 SG2042_GATE_FW(GATE_CLK_RXU4, "clk_gate_rxu4", "rpgate",
99 0, R_RP_RXU_CLK_ENABLE, 4),
100 SG2042_GATE_FW(GATE_CLK_RXU5, "clk_gate_rxu5", "rpgate",
101 0, R_RP_RXU_CLK_ENABLE, 5),
102 SG2042_GATE_FW(GATE_CLK_RXU6, "clk_gate_rxu6", "rpgate",
103 0, R_RP_RXU_CLK_ENABLE, 6),
104 SG2042_GATE_FW(GATE_CLK_RXU7, "clk_gate_rxu7", "rpgate",
105 0, R_RP_RXU_CLK_ENABLE, 7),
106 SG2042_GATE_FW(GATE_CLK_RXU8, "clk_gate_rxu8", "rpgate",
107 0, R_RP_RXU_CLK_ENABLE, 8),
108 SG2042_GATE_FW(GATE_CLK_RXU9, "clk_gate_rxu9", "rpgate",
109 0, R_RP_RXU_CLK_ENABLE, 9),
110 SG2042_GATE_FW(GATE_CLK_RXU10, "clk_gate_rxu10", "rpgate",
111 0, R_RP_RXU_CLK_ENABLE, 10),
112 SG2042_GATE_FW(GATE_CLK_RXU11, "clk_gate_rxu11", "rpgate",
113 0, R_RP_RXU_CLK_ENABLE, 11),
114 SG2042_GATE_FW(GATE_CLK_RXU12, "clk_gate_rxu12", "rpgate",
115 0, R_RP_RXU_CLK_ENABLE, 12),
116 SG2042_GATE_FW(GATE_CLK_RXU13, "clk_gate_rxu13", "rpgate",
117 0, R_RP_RXU_CLK_ENABLE, 13),
118 SG2042_GATE_FW(GATE_CLK_RXU14, "clk_gate_rxu14", "rpgate",
119 0, R_RP_RXU_CLK_ENABLE, 14),
120 SG2042_GATE_FW(GATE_CLK_RXU15, "clk_gate_rxu15", "rpgate",
121 0, R_RP_RXU_CLK_ENABLE, 15),
122 SG2042_GATE_FW(GATE_CLK_RXU16, "clk_gate_rxu16", "rpgate",
123 0, R_RP_RXU_CLK_ENABLE, 16),
124 SG2042_GATE_FW(GATE_CLK_RXU17, "clk_gate_rxu17", "rpgate",
125 0, R_RP_RXU_CLK_ENABLE, 17),
126 SG2042_GATE_FW(GATE_CLK_RXU18, "clk_gate_rxu18", "rpgate",
127 0, R_RP_RXU_CLK_ENABLE, 18),
128 SG2042_GATE_FW(GATE_CLK_RXU19, "clk_gate_rxu19", "rpgate",
129 0, R_RP_RXU_CLK_ENABLE, 19),
130 SG2042_GATE_FW(GATE_CLK_RXU20, "clk_gate_rxu20", "rpgate",
131 0, R_RP_RXU_CLK_ENABLE, 20),
132 SG2042_GATE_FW(GATE_CLK_RXU21, "clk_gate_rxu21", "rpgate",
133 0, R_RP_RXU_CLK_ENABLE, 21),
134 SG2042_GATE_FW(GATE_CLK_RXU22, "clk_gate_rxu22", "rpgate",
135 0, R_RP_RXU_CLK_ENABLE, 22),
136 SG2042_GATE_FW(GATE_CLK_RXU23, "clk_gate_rxu23", "rpgate",
137 0, R_RP_RXU_CLK_ENABLE, 23),
138 SG2042_GATE_FW(GATE_CLK_RXU24, "clk_gate_rxu24", "rpgate",
139 0, R_RP_RXU_CLK_ENABLE, 24),
140 SG2042_GATE_FW(GATE_CLK_RXU25, "clk_gate_rxu25", "rpgate",
141 0, R_RP_RXU_CLK_ENABLE, 25),
142 SG2042_GATE_FW(GATE_CLK_RXU26, "clk_gate_rxu26", "rpgate",
143 0, R_RP_RXU_CLK_ENABLE, 26),
144 SG2042_GATE_FW(GATE_CLK_RXU27, "clk_gate_rxu27", "rpgate",
145 0, R_RP_RXU_CLK_ENABLE, 27),
146 SG2042_GATE_FW(GATE_CLK_RXU28, "clk_gate_rxu28", "rpgate",
147 0, R_RP_RXU_CLK_ENABLE, 28),
148 SG2042_GATE_FW(GATE_CLK_RXU29, "clk_gate_rxu29", "rpgate",
149 0, R_RP_RXU_CLK_ENABLE, 29),
150 SG2042_GATE_FW(GATE_CLK_RXU30, "clk_gate_rxu30", "rpgate",
151 0, R_RP_RXU_CLK_ENABLE, 30),
152 SG2042_GATE_FW(GATE_CLK_RXU31, "clk_gate_rxu31", "rpgate",
153 0, R_RP_RXU_CLK_ENABLE, 31),
154
155 /* downstream of clk_gate_rp_cpu_normal about mp */
156 SG2042_GATE_FW(GATE_CLK_MP0, "clk_gate_mp0", "rpgate",
157 CLK_IS_CRITICAL, R_MP0_CONTROL_REG, 0),
158 SG2042_GATE_FW(GATE_CLK_MP1, "clk_gate_mp1", "rpgate",
159 CLK_IS_CRITICAL, R_MP1_CONTROL_REG, 0),
160 SG2042_GATE_FW(GATE_CLK_MP2, "clk_gate_mp2", "rpgate",
161 CLK_IS_CRITICAL, R_MP2_CONTROL_REG, 0),
162 SG2042_GATE_FW(GATE_CLK_MP3, "clk_gate_mp3", "rpgate",
163 CLK_IS_CRITICAL, R_MP3_CONTROL_REG, 0),
164 SG2042_GATE_FW(GATE_CLK_MP4, "clk_gate_mp4", "rpgate",
165 CLK_IS_CRITICAL, R_MP4_CONTROL_REG, 0),
166 SG2042_GATE_FW(GATE_CLK_MP5, "clk_gate_mp5", "rpgate",
167 CLK_IS_CRITICAL, R_MP5_CONTROL_REG, 0),
168 SG2042_GATE_FW(GATE_CLK_MP6, "clk_gate_mp6", "rpgate",
169 CLK_IS_CRITICAL, R_MP6_CONTROL_REG, 0),
170 SG2042_GATE_FW(GATE_CLK_MP7, "clk_gate_mp7", "rpgate",
171 CLK_IS_CRITICAL, R_MP7_CONTROL_REG, 0),
172 SG2042_GATE_FW(GATE_CLK_MP8, "clk_gate_mp8", "rpgate",
173 CLK_IS_CRITICAL, R_MP8_CONTROL_REG, 0),
174 SG2042_GATE_FW(GATE_CLK_MP9, "clk_gate_mp9", "rpgate",
175 CLK_IS_CRITICAL, R_MP9_CONTROL_REG, 0),
176 SG2042_GATE_FW(GATE_CLK_MP10, "clk_gate_mp10", "rpgate",
177 CLK_IS_CRITICAL, R_MP10_CONTROL_REG, 0),
178 SG2042_GATE_FW(GATE_CLK_MP11, "clk_gate_mp11", "rpgate",
179 CLK_IS_CRITICAL, R_MP11_CONTROL_REG, 0),
180 SG2042_GATE_FW(GATE_CLK_MP12, "clk_gate_mp12", "rpgate",
181 CLK_IS_CRITICAL, R_MP12_CONTROL_REG, 0),
182 SG2042_GATE_FW(GATE_CLK_MP13, "clk_gate_mp13", "rpgate",
183 CLK_IS_CRITICAL, R_MP13_CONTROL_REG, 0),
184 SG2042_GATE_FW(GATE_CLK_MP14, "clk_gate_mp14", "rpgate",
185 CLK_IS_CRITICAL, R_MP14_CONTROL_REG, 0),
186 SG2042_GATE_FW(GATE_CLK_MP15, "clk_gate_mp15", "rpgate",
187 CLK_IS_CRITICAL, R_MP15_CONTROL_REG, 0),
188 };
189
190 static DEFINE_SPINLOCK(sg2042_clk_lock);
191
sg2042_clk_register_rpgates(struct device * dev,struct sg2042_clk_data * clk_data,const struct sg2042_rpgate_clock gate_clks[],int num_gate_clks)192 static int sg2042_clk_register_rpgates(struct device *dev,
193 struct sg2042_clk_data *clk_data,
194 const struct sg2042_rpgate_clock gate_clks[],
195 int num_gate_clks)
196 {
197 const struct sg2042_rpgate_clock *gate;
198 struct clk_hw *hw;
199 int i, ret = 0;
200
201 for (i = 0; i < num_gate_clks; i++) {
202 gate = &gate_clks[i];
203 hw = devm_clk_hw_register_gate_parent_data
204 (dev,
205 gate->hw.init->name,
206 gate->hw.init->parent_data,
207 gate->hw.init->flags,
208 clk_data->iobase + gate->offset_enable,
209 gate->bit_idx,
210 0,
211 &sg2042_clk_lock);
212 if (IS_ERR(hw)) {
213 pr_err("failed to register clock %s\n", gate->hw.init->name);
214 ret = PTR_ERR(hw);
215 break;
216 }
217
218 clk_data->onecell_data.hws[gate->id] = hw;
219 }
220
221 return ret;
222 }
223
sg2042_init_clkdata(struct platform_device * pdev,int num_clks,struct sg2042_clk_data ** pp_clk_data)224 static int sg2042_init_clkdata(struct platform_device *pdev,
225 int num_clks,
226 struct sg2042_clk_data **pp_clk_data)
227 {
228 struct sg2042_clk_data *clk_data;
229
230 clk_data = devm_kzalloc(&pdev->dev,
231 struct_size(clk_data, onecell_data.hws, num_clks),
232 GFP_KERNEL);
233 if (!clk_data)
234 return -ENOMEM;
235
236 clk_data->iobase = devm_platform_ioremap_resource(pdev, 0);
237 if (WARN_ON(IS_ERR(clk_data->iobase)))
238 return PTR_ERR(clk_data->iobase);
239
240 clk_data->onecell_data.num = num_clks;
241
242 *pp_clk_data = clk_data;
243
244 return 0;
245 }
246
sg2042_rpgate_probe(struct platform_device * pdev)247 static int sg2042_rpgate_probe(struct platform_device *pdev)
248 {
249 struct sg2042_clk_data *clk_data = NULL;
250 int num_clks;
251 int ret;
252
253 num_clks = ARRAY_SIZE(sg2042_gate_rp);
254
255 ret = sg2042_init_clkdata(pdev, num_clks, &clk_data);
256 if (ret)
257 goto error_out;
258
259 ret = sg2042_clk_register_rpgates(&pdev->dev, clk_data, sg2042_gate_rp,
260 num_clks);
261 if (ret)
262 goto error_out;
263
264 return devm_of_clk_add_hw_provider(&pdev->dev,
265 of_clk_hw_onecell_get,
266 &clk_data->onecell_data);
267
268 error_out:
269 pr_err("%s failed error number %d\n", __func__, ret);
270 return ret;
271 }
272
273 static const struct of_device_id sg2042_rpgate_match[] = {
274 { .compatible = "sophgo,sg2042-rpgate" },
275 { /* sentinel */ }
276 };
277 MODULE_DEVICE_TABLE(of, sg2042_rpgate_match);
278
279 static struct platform_driver sg2042_rpgate_driver = {
280 .probe = sg2042_rpgate_probe,
281 .driver = {
282 .name = "clk-sophgo-sg2042-rpgate",
283 .of_match_table = sg2042_rpgate_match,
284 .suppress_bind_attrs = true,
285 },
286 };
287 module_platform_driver(sg2042_rpgate_driver);
288
289 MODULE_AUTHOR("Chen Wang");
290 MODULE_DESCRIPTION("Sophgo SG2042 rp subsystem clock driver");
291 MODULE_LICENSE("GPL");
292