• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (c) 2019 BayLibre, SAS
4  * Author: Neil Armstrong <narmstrong@baylibre.com>
5  */
6 
7 #include <common.h>
8 #include <dm.h>
9 #include <power-domain-uclass.h>
10 #include <regmap.h>
11 #include <syscon.h>
12 #include <reset.h>
13 #include <clk.h>
14 #include <dt-bindings/power/meson-g12a-power.h>
15 #include <dt-bindings/power/meson-sm1-power.h>
16 
17 /* AO Offsets */
18 
19 #define AO_RTI_GEN_PWR_SLEEP0		(0x3a << 2)
20 #define AO_RTI_GEN_PWR_ISO0		(0x3b << 2)
21 
22 /* HHI Offsets */
23 
24 #define HHI_MEM_PD_REG0			(0x40 << 2)
25 #define HHI_VPU_MEM_PD_REG0		(0x41 << 2)
26 #define HHI_VPU_MEM_PD_REG1		(0x42 << 2)
27 #define HHI_VPU_MEM_PD_REG3		(0x43 << 2)
28 #define HHI_VPU_MEM_PD_REG4		(0x44 << 2)
29 #define HHI_AUDIO_MEM_PD_REG0		(0x45 << 2)
30 #define HHI_NANOQ_MEM_PD_REG0		(0x46 << 2)
31 #define HHI_NANOQ_MEM_PD_REG1		(0x47 << 2)
32 #define HHI_VPU_MEM_PD_REG2		(0x4d << 2)
33 
34 struct meson_ee_pwrc;
35 struct meson_ee_pwrc_domain;
36 
37 struct meson_ee_pwrc_mem_domain {
38 	unsigned int reg;
39 	unsigned int mask;
40 };
41 
42 struct meson_ee_pwrc_top_domain {
43 	unsigned int sleep_reg;
44 	unsigned int sleep_mask;
45 	unsigned int iso_reg;
46 	unsigned int iso_mask;
47 };
48 
49 struct meson_ee_pwrc_domain_desc {
50 	char *name;
51 	unsigned int reset_names_count;
52 	unsigned int clk_names_count;
53 	struct meson_ee_pwrc_top_domain *top_pd;
54 	unsigned int mem_pd_count;
55 	struct meson_ee_pwrc_mem_domain *mem_pd;
56 	bool (*get_power)(struct power_domain *power_domain);
57 };
58 
59 struct meson_ee_pwrc_domain_data {
60 	unsigned int count;
61 	struct meson_ee_pwrc_domain_desc *domains;
62 };
63 
64 /* TOP Power Domains */
65 
66 static struct meson_ee_pwrc_top_domain g12a_pwrc_vpu = {
67 	.sleep_reg = AO_RTI_GEN_PWR_SLEEP0,
68 	.sleep_mask = BIT(8),
69 	.iso_reg = AO_RTI_GEN_PWR_SLEEP0,
70 	.iso_mask = BIT(9),
71 };
72 
73 #define SM1_EE_PD(__bit)					\
74 	{							\
75 		.sleep_reg = AO_RTI_GEN_PWR_SLEEP0,		\
76 		.sleep_mask = BIT(__bit),			\
77 		.iso_reg = AO_RTI_GEN_PWR_ISO0,			\
78 		.iso_mask = BIT(__bit),				\
79 	}
80 
81 static struct meson_ee_pwrc_top_domain sm1_pwrc_vpu = SM1_EE_PD(8);
82 static struct meson_ee_pwrc_top_domain sm1_pwrc_nna = SM1_EE_PD(16);
83 static struct meson_ee_pwrc_top_domain sm1_pwrc_usb = SM1_EE_PD(17);
84 static struct meson_ee_pwrc_top_domain sm1_pwrc_pci = SM1_EE_PD(18);
85 static struct meson_ee_pwrc_top_domain sm1_pwrc_ge2d = SM1_EE_PD(19);
86 
87 /* Memory PD Domains */
88 
89 #define VPU_MEMPD(__reg)					\
90 	{ __reg, GENMASK(1, 0) },				\
91 	{ __reg, GENMASK(3, 2) },				\
92 	{ __reg, GENMASK(5, 4) },				\
93 	{ __reg, GENMASK(7, 6) },				\
94 	{ __reg, GENMASK(9, 8) },				\
95 	{ __reg, GENMASK(11, 10) },				\
96 	{ __reg, GENMASK(13, 12) },				\
97 	{ __reg, GENMASK(15, 14) },				\
98 	{ __reg, GENMASK(17, 16) },				\
99 	{ __reg, GENMASK(19, 18) },				\
100 	{ __reg, GENMASK(21, 20) },				\
101 	{ __reg, GENMASK(23, 22) },				\
102 	{ __reg, GENMASK(25, 24) },				\
103 	{ __reg, GENMASK(27, 26) },				\
104 	{ __reg, GENMASK(29, 28) },				\
105 	{ __reg, GENMASK(31, 30) }
106 
107 #define VPU_HHI_MEMPD(__reg)					\
108 	{ __reg, BIT(8) },					\
109 	{ __reg, BIT(9) },					\
110 	{ __reg, BIT(10) },					\
111 	{ __reg, BIT(11) },					\
112 	{ __reg, BIT(12) },					\
113 	{ __reg, BIT(13) },					\
114 	{ __reg, BIT(14) },					\
115 	{ __reg, BIT(15) }
116 
117 static struct meson_ee_pwrc_mem_domain g12a_pwrc_mem_vpu[] = {
118 	VPU_MEMPD(HHI_VPU_MEM_PD_REG0),
119 	VPU_MEMPD(HHI_VPU_MEM_PD_REG1),
120 	VPU_MEMPD(HHI_VPU_MEM_PD_REG2),
121 	VPU_HHI_MEMPD(HHI_MEM_PD_REG0),
122 };
123 
124 static struct meson_ee_pwrc_mem_domain g12a_pwrc_mem_eth[] = {
125 	{ HHI_MEM_PD_REG0, GENMASK(3, 2) },
126 };
127 
128 static struct meson_ee_pwrc_mem_domain sm1_pwrc_mem_vpu[] = {
129 	VPU_MEMPD(HHI_VPU_MEM_PD_REG0),
130 	VPU_MEMPD(HHI_VPU_MEM_PD_REG1),
131 	VPU_MEMPD(HHI_VPU_MEM_PD_REG2),
132 	VPU_MEMPD(HHI_VPU_MEM_PD_REG3),
133 	{ HHI_VPU_MEM_PD_REG4, GENMASK(1, 0) },
134 	{ HHI_VPU_MEM_PD_REG4, GENMASK(3, 2) },
135 	{ HHI_VPU_MEM_PD_REG4, GENMASK(5, 4) },
136 	{ HHI_VPU_MEM_PD_REG4, GENMASK(7, 6) },
137 	VPU_HHI_MEMPD(HHI_MEM_PD_REG0),
138 };
139 
140 static struct meson_ee_pwrc_mem_domain sm1_pwrc_mem_nna[] = {
141 	{ HHI_NANOQ_MEM_PD_REG0, 0xff },
142 	{ HHI_NANOQ_MEM_PD_REG1, 0xff },
143 };
144 
145 static struct meson_ee_pwrc_mem_domain sm1_pwrc_mem_usb[] = {
146 	{ HHI_MEM_PD_REG0, GENMASK(31, 30) },
147 };
148 
149 static struct meson_ee_pwrc_mem_domain sm1_pwrc_mem_pcie[] = {
150 	{ HHI_MEM_PD_REG0, GENMASK(29, 26) },
151 };
152 
153 static struct meson_ee_pwrc_mem_domain sm1_pwrc_mem_ge2d[] = {
154 	{ HHI_MEM_PD_REG0, GENMASK(25, 18) },
155 };
156 
157 static struct meson_ee_pwrc_mem_domain sm1_pwrc_mem_audio[] = {
158 	{ HHI_MEM_PD_REG0, GENMASK(5, 4) },
159 	{ HHI_AUDIO_MEM_PD_REG0, GENMASK(1, 0) },
160 	{ HHI_AUDIO_MEM_PD_REG0, GENMASK(3, 2) },
161 	{ HHI_AUDIO_MEM_PD_REG0, GENMASK(5, 4) },
162 	{ HHI_AUDIO_MEM_PD_REG0, GENMASK(7, 6) },
163 	{ HHI_AUDIO_MEM_PD_REG0, GENMASK(13, 12) },
164 	{ HHI_AUDIO_MEM_PD_REG0, GENMASK(15, 14) },
165 	{ HHI_AUDIO_MEM_PD_REG0, GENMASK(17, 16) },
166 	{ HHI_AUDIO_MEM_PD_REG0, GENMASK(19, 18) },
167 	{ HHI_AUDIO_MEM_PD_REG0, GENMASK(21, 20) },
168 	{ HHI_AUDIO_MEM_PD_REG0, GENMASK(23, 22) },
169 	{ HHI_AUDIO_MEM_PD_REG0, GENMASK(25, 24) },
170 	{ HHI_AUDIO_MEM_PD_REG0, GENMASK(27, 26) },
171 };
172 
173 #define VPU_PD(__name, __top_pd, __mem, __get_power, __resets, __clks)	\
174 	{								\
175 		.name = __name,						\
176 		.reset_names_count = __resets,				\
177 		.clk_names_count = __clks,				\
178 		.top_pd = __top_pd,					\
179 		.mem_pd_count = ARRAY_SIZE(__mem),			\
180 		.mem_pd = __mem,					\
181 		.get_power = __get_power,				\
182 	}
183 
184 #define TOP_PD(__name, __top_pd, __mem, __get_power)			\
185 	{								\
186 		.name = __name,						\
187 		.top_pd = __top_pd,					\
188 		.mem_pd_count = ARRAY_SIZE(__mem),			\
189 		.mem_pd = __mem,					\
190 		.get_power = __get_power,				\
191 	}
192 
193 #define MEM_PD(__name, __mem)						\
194 	TOP_PD(__name, NULL, __mem, NULL)
195 
196 static bool pwrc_ee_get_power(struct power_domain *power_domain);
197 
198 static struct meson_ee_pwrc_domain_desc g12a_pwrc_domains[] = {
199 	[PWRC_G12A_VPU_ID]  = VPU_PD("VPU", &g12a_pwrc_vpu, g12a_pwrc_mem_vpu,
200 				     pwrc_ee_get_power, 11, 2),
201 	[PWRC_G12A_ETH_ID] = MEM_PD("ETH", g12a_pwrc_mem_eth),
202 };
203 
204 static struct meson_ee_pwrc_domain_desc sm1_pwrc_domains[] = {
205 	[PWRC_SM1_VPU_ID]  = VPU_PD("VPU", &sm1_pwrc_vpu, sm1_pwrc_mem_vpu,
206 				    pwrc_ee_get_power, 11, 2),
207 	[PWRC_SM1_NNA_ID]  = TOP_PD("NNA", &sm1_pwrc_nna, sm1_pwrc_mem_nna,
208 				    pwrc_ee_get_power),
209 	[PWRC_SM1_USB_ID]  = TOP_PD("USB", &sm1_pwrc_usb, sm1_pwrc_mem_usb,
210 				    pwrc_ee_get_power),
211 	[PWRC_SM1_PCIE_ID] = TOP_PD("PCI", &sm1_pwrc_pci, sm1_pwrc_mem_pcie,
212 				    pwrc_ee_get_power),
213 	[PWRC_SM1_GE2D_ID] = TOP_PD("GE2D", &sm1_pwrc_ge2d, sm1_pwrc_mem_ge2d,
214 				    pwrc_ee_get_power),
215 	[PWRC_SM1_AUDIO_ID] = MEM_PD("AUDIO", sm1_pwrc_mem_audio),
216 	[PWRC_SM1_ETH_ID] = MEM_PD("ETH", g12a_pwrc_mem_eth),
217 };
218 
219 struct meson_ee_pwrc_priv {
220 	struct regmap *regmap_ao;
221 	struct regmap *regmap_hhi;
222 	struct reset_ctl_bulk resets;
223 	struct clk_bulk clks;
224 	const struct meson_ee_pwrc_domain_data *data;
225 };
226 
pwrc_ee_get_power(struct power_domain * power_domain)227 static bool pwrc_ee_get_power(struct power_domain *power_domain)
228 {
229 	struct meson_ee_pwrc_priv *priv = dev_get_priv(power_domain->dev);
230 	struct meson_ee_pwrc_domain_desc *pwrc_domain;
231 	u32 reg;
232 
233 	pwrc_domain = &priv->data->domains[power_domain->id];
234 
235 	regmap_read(priv->regmap_ao,
236 		    pwrc_domain->top_pd->sleep_reg, &reg);
237 
238 	return (reg & pwrc_domain->top_pd->sleep_mask);
239 }
240 
meson_ee_pwrc_request(struct power_domain * power_domain)241 static int meson_ee_pwrc_request(struct power_domain *power_domain)
242 {
243 	return 0;
244 }
245 
meson_ee_pwrc_free(struct power_domain * power_domain)246 static int meson_ee_pwrc_free(struct power_domain *power_domain)
247 {
248 	return 0;
249 }
250 
meson_ee_pwrc_off(struct power_domain * power_domain)251 static int meson_ee_pwrc_off(struct power_domain *power_domain)
252 {
253 	struct meson_ee_pwrc_priv *priv = dev_get_priv(power_domain->dev);
254 	struct meson_ee_pwrc_domain_desc *pwrc_domain;
255 	int i;
256 
257 	pwrc_domain = &priv->data->domains[power_domain->id];
258 
259 	if (pwrc_domain->top_pd)
260 		regmap_update_bits(priv->regmap_ao,
261 				   pwrc_domain->top_pd->sleep_reg,
262 				   pwrc_domain->top_pd->sleep_mask,
263 				   pwrc_domain->top_pd->sleep_mask);
264 	udelay(20);
265 
266 	for (i = 0 ; i < pwrc_domain->mem_pd_count ; ++i)
267 		regmap_update_bits(priv->regmap_hhi,
268 				   pwrc_domain->mem_pd[i].reg,
269 				   pwrc_domain->mem_pd[i].mask,
270 				   pwrc_domain->mem_pd[i].mask);
271 
272 	udelay(20);
273 
274 	if (pwrc_domain->top_pd)
275 		regmap_update_bits(priv->regmap_ao,
276 				   pwrc_domain->top_pd->iso_reg,
277 				   pwrc_domain->top_pd->iso_mask,
278 				   pwrc_domain->top_pd->iso_mask);
279 
280 	if (pwrc_domain->clk_names_count) {
281 		mdelay(20);
282 		clk_disable_bulk(&priv->clks);
283 	}
284 
285 	return 0;
286 }
287 
meson_ee_pwrc_on(struct power_domain * power_domain)288 static int meson_ee_pwrc_on(struct power_domain *power_domain)
289 {
290 	struct meson_ee_pwrc_priv *priv = dev_get_priv(power_domain->dev);
291 	struct meson_ee_pwrc_domain_desc *pwrc_domain;
292 	int i, ret;
293 
294 	pwrc_domain = &priv->data->domains[power_domain->id];
295 
296 	if (pwrc_domain->top_pd)
297 		regmap_update_bits(priv->regmap_ao,
298 				   pwrc_domain->top_pd->sleep_reg,
299 				   pwrc_domain->top_pd->sleep_mask, 0);
300 	udelay(20);
301 
302 	for (i = 0 ; i < pwrc_domain->mem_pd_count ; ++i)
303 		regmap_update_bits(priv->regmap_hhi,
304 				   pwrc_domain->mem_pd[i].reg,
305 				   pwrc_domain->mem_pd[i].mask, 0);
306 
307 	udelay(20);
308 
309 	if (pwrc_domain->reset_names_count) {
310 		ret = reset_assert_bulk(&priv->resets);
311 		if (ret)
312 			return ret;
313 	}
314 
315 	if (pwrc_domain->top_pd)
316 		regmap_update_bits(priv->regmap_ao,
317 				   pwrc_domain->top_pd->iso_reg,
318 				   pwrc_domain->top_pd->iso_mask, 0);
319 
320 	if (pwrc_domain->reset_names_count) {
321 		ret = reset_deassert_bulk(&priv->resets);
322 		if (ret)
323 			return ret;
324 	}
325 
326 	if (pwrc_domain->clk_names_count)
327 		return clk_enable_bulk(&priv->clks);
328 
329 	return 0;
330 }
331 
meson_ee_pwrc_of_xlate(struct power_domain * power_domain,struct ofnode_phandle_args * args)332 static int meson_ee_pwrc_of_xlate(struct power_domain *power_domain,
333 				  struct ofnode_phandle_args *args)
334 {
335 	struct meson_ee_pwrc_priv *priv = dev_get_priv(power_domain->dev);
336 
337 	/* #power-domain-cells is 1 */
338 
339 	if (args->args_count < 1) {
340 		debug("Invalid args_count: %d\n", args->args_count);
341 		return -EINVAL;
342 	}
343 
344 	power_domain->id = args->args[0];
345 
346 	if (power_domain->id >= priv->data->count) {
347 		debug("Invalid domain ID: %lu\n", power_domain->id);
348 		return -EINVAL;
349 	}
350 
351 	return 0;
352 }
353 
354 struct power_domain_ops meson_ee_pwrc_ops = {
355 	.free = meson_ee_pwrc_free,
356 	.off = meson_ee_pwrc_off,
357 	.on = meson_ee_pwrc_on,
358 	.request = meson_ee_pwrc_request,
359 	.of_xlate = meson_ee_pwrc_of_xlate,
360 };
361 
362 static struct meson_ee_pwrc_domain_data meson_ee_g12a_pwrc_data = {
363 	.count = ARRAY_SIZE(g12a_pwrc_domains),
364 	.domains = g12a_pwrc_domains,
365 };
366 
367 static struct meson_ee_pwrc_domain_data meson_ee_sm1_pwrc_data = {
368 	.count = ARRAY_SIZE(sm1_pwrc_domains),
369 	.domains = sm1_pwrc_domains,
370 };
371 
372 static const struct udevice_id meson_ee_pwrc_ids[] = {
373 	{
374 		.compatible = "amlogic,meson-g12a-pwrc",
375 		.data = (unsigned long)&meson_ee_g12a_pwrc_data,
376 	},
377 	{
378 		.compatible = "amlogic,meson-sm1-pwrc",
379 		.data = (unsigned long)&meson_ee_sm1_pwrc_data,
380 	},
381 	{ }
382 };
383 
meson_ee_pwrc_probe(struct udevice * dev)384 static int meson_ee_pwrc_probe(struct udevice *dev)
385 {
386 	struct meson_ee_pwrc_priv *priv = dev_get_priv(dev);
387 	u32 ao_phandle;
388 	ofnode ao_node;
389 	int ret;
390 
391 	priv->data = (void *)dev_get_driver_data(dev);
392 	if (!priv->data)
393 		return -EINVAL;
394 
395 	priv->regmap_hhi = syscon_node_to_regmap(dev_get_parent(dev)->node);
396 	if (IS_ERR(priv->regmap_hhi))
397 		return PTR_ERR(priv->regmap_hhi);
398 
399 	ret = ofnode_read_u32(dev->node, "amlogic,ao-sysctrl",
400 			      &ao_phandle);
401 	if (ret)
402 		return ret;
403 
404 	ao_node = ofnode_get_by_phandle(ao_phandle);
405 	if (!ofnode_valid(ao_node))
406 		return -EINVAL;
407 
408 	priv->regmap_ao = syscon_node_to_regmap(ao_node);
409 	if (IS_ERR(priv->regmap_ao))
410 		return PTR_ERR(priv->regmap_ao);
411 
412 	ret = reset_get_bulk(dev, &priv->resets);
413 	if (ret)
414 		return ret;
415 
416 	ret = clk_get_bulk(dev, &priv->clks);
417 	if (ret)
418 		return ret;
419 
420 	return 0;
421 }
422 
423 U_BOOT_DRIVER(meson_ee_pwrc) = {
424 	.name = "meson_ee_pwrc",
425 	.id = UCLASS_POWER_DOMAIN,
426 	.of_match = meson_ee_pwrc_ids,
427 	.probe = meson_ee_pwrc_probe,
428 	.ops = &meson_ee_pwrc_ops,
429 	.priv_auto_alloc_size = sizeof(struct meson_ee_pwrc_priv),
430 };
431