1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * Rockchip Generic power domain support.
4 *
5 * Copyright (c) 2015 ROCKCHIP, Co. Ltd.
6 */
7
8#include <linux/io.h>
9#include <linux/iopoll.h>
10#include <linux/err.h>
11#include <linux/pm_clock.h>
12#include <linux/pm_domain.h>
13#include <linux/of_address.h>
14#include <linux/of_clk.h>
15#include <linux/of_platform.h>
16#include <linux/clk.h>
17#include <linux/regmap.h>
18#include <linux/mfd/syscon.h>
19#include <dt-bindings/power/px30-power.h>
20#include <dt-bindings/power/rk3036-power.h>
21#include <dt-bindings/power/rk3066-power.h>
22#include <dt-bindings/power/rk3128-power.h>
23#include <dt-bindings/power/rk3188-power.h>
24#include <dt-bindings/power/rk3228-power.h>
25#include <dt-bindings/power/rk3288-power.h>
26#include <dt-bindings/power/rk3328-power.h>
27#include <dt-bindings/power/rk3366-power.h>
28#include <dt-bindings/power/rk3368-power.h>
29#include <dt-bindings/power/rk3399-power.h>
30
31struct rockchip_domain_info {
32	int pwr_mask;
33	int status_mask;
34	int req_mask;
35	int idle_mask;
36	int ack_mask;
37	bool active_wakeup;
38	int pwr_w_mask;
39	int req_w_mask;
40};
41
42struct rockchip_pmu_info {
43	u32 pwr_offset;
44	u32 status_offset;
45	u32 req_offset;
46	u32 idle_offset;
47	u32 ack_offset;
48
49	u32 core_pwrcnt_offset;
50	u32 gpu_pwrcnt_offset;
51
52	unsigned int core_power_transition_time;
53	unsigned int gpu_power_transition_time;
54
55	int num_domains;
56	const struct rockchip_domain_info *domain_info;
57};
58
59#define MAX_QOS_REGS_NUM	5
60#define QOS_PRIORITY		0x08
61#define QOS_MODE		0x0c
62#define QOS_BANDWIDTH		0x10
63#define QOS_SATURATION		0x14
64#define QOS_EXTCONTROL		0x18
65
66struct rockchip_pm_domain {
67	struct generic_pm_domain genpd;
68	const struct rockchip_domain_info *info;
69	struct rockchip_pmu *pmu;
70	int num_qos;
71	struct regmap **qos_regmap;
72	u32 *qos_save_regs[MAX_QOS_REGS_NUM];
73	int num_clks;
74	struct clk_bulk_data *clks;
75};
76
77struct rockchip_pmu {
78	struct device *dev;
79	struct regmap *regmap;
80	const struct rockchip_pmu_info *info;
81	struct mutex mutex; /* mutex lock for pmu */
82	struct genpd_onecell_data genpd_data;
83	struct generic_pm_domain *domains[];
84};
85
86#define to_rockchip_pd(gpd) container_of(gpd, struct rockchip_pm_domain, genpd)
87
88#define DOMAIN(pwr, status, req, idle, ack, wakeup)	\
89{							\
90	.pwr_mask = (pwr),				\
91	.status_mask = (status),			\
92	.req_mask = (req),				\
93	.idle_mask = (idle),				\
94	.ack_mask = (ack),				\
95	.active_wakeup = (wakeup),			\
96}
97
98#define DOMAIN_M(pwr, status, req, idle, ack, wakeup)	\
99{							\
100	.pwr_w_mask = (pwr) << 16,			\
101	.pwr_mask = (pwr),				\
102	.status_mask = (status),			\
103	.req_w_mask = (req) << 16,			\
104	.req_mask = (req),				\
105	.idle_mask = (idle),				\
106	.ack_mask = (ack),				\
107	.active_wakeup = wakeup,			\
108}
109
110#define DOMAIN_RK3036(req, ack, idle, wakeup)		\
111{							\
112	.req_mask = (req),				\
113	.req_w_mask = (req) << 16,			\
114	.ack_mask = (ack),				\
115	.idle_mask = (idle),				\
116	.active_wakeup = wakeup,			\
117}
118
119#define DOMAIN_PX30(pwr, status, req, wakeup)		\
120	DOMAIN_M(pwr, status, req, (req) << 16, req, wakeup)
121
122#define DOMAIN_RK3288(pwr, status, req, wakeup)		\
123	DOMAIN(pwr, status, req, req, (req) << 16, wakeup)
124
125#define DOMAIN_RK3328(pwr, status, req, wakeup)		\
126	DOMAIN_M(pwr, pwr, req, (req) << 10, req, wakeup)
127
128#define DOMAIN_RK3368(pwr, status, req, wakeup)		\
129	DOMAIN(pwr, status, req, (req) << 16, req, wakeup)
130
131#define DOMAIN_RK3399(pwr, status, req, wakeup)		\
132	DOMAIN(pwr, status, req, req, req, wakeup)
133
134static bool rockchip_pmu_domain_is_idle(struct rockchip_pm_domain *pd)
135{
136	struct rockchip_pmu *pmu = pd->pmu;
137	const struct rockchip_domain_info *pd_info = pd->info;
138	unsigned int val;
139
140	regmap_read(pmu->regmap, pmu->info->idle_offset, &val);
141	return (val & pd_info->idle_mask) == pd_info->idle_mask;
142}
143
144static unsigned int rockchip_pmu_read_ack(struct rockchip_pmu *pmu)
145{
146	unsigned int val;
147
148	regmap_read(pmu->regmap, pmu->info->ack_offset, &val);
149	return val;
150}
151
152static int rockchip_pmu_set_idle_request(struct rockchip_pm_domain *pd,
153					 bool idle)
154{
155	const struct rockchip_domain_info *pd_info = pd->info;
156	struct generic_pm_domain *genpd = &pd->genpd;
157	struct rockchip_pmu *pmu = pd->pmu;
158	unsigned int target_ack;
159	unsigned int val;
160	bool is_idle;
161	int ret;
162
163	if (pd_info->req_mask == 0)
164		return 0;
165	else if (pd_info->req_w_mask)
166		regmap_write(pmu->regmap, pmu->info->req_offset,
167			     idle ? (pd_info->req_mask | pd_info->req_w_mask) :
168			     pd_info->req_w_mask);
169	else
170		regmap_update_bits(pmu->regmap, pmu->info->req_offset,
171				   pd_info->req_mask, idle ? -1U : 0);
172
173	dsb(sy);
174
175	/* Wait util idle_ack = 1 */
176	target_ack = idle ? pd_info->ack_mask : 0;
177	ret = readx_poll_timeout_atomic(rockchip_pmu_read_ack, pmu, val,
178					(val & pd_info->ack_mask) == target_ack,
179					0, 10000);
180	if (ret) {
181		dev_err(pmu->dev,
182			"failed to get ack on domain '%s', val=0x%x\n",
183			genpd->name, val);
184		return ret;
185	}
186
187	ret = readx_poll_timeout_atomic(rockchip_pmu_domain_is_idle, pd,
188					is_idle, is_idle == idle, 0, 10000);
189	if (ret) {
190		dev_err(pmu->dev,
191			"failed to set idle on domain '%s', val=%d\n",
192			genpd->name, is_idle);
193		return ret;
194	}
195
196	return 0;
197}
198
199static int rockchip_pmu_save_qos(struct rockchip_pm_domain *pd)
200{
201	int i;
202
203	for (i = 0; i < pd->num_qos; i++) {
204		regmap_read(pd->qos_regmap[i],
205			    QOS_PRIORITY,
206			    &pd->qos_save_regs[0][i]);
207		regmap_read(pd->qos_regmap[i],
208			    QOS_MODE,
209			    &pd->qos_save_regs[1][i]);
210		regmap_read(pd->qos_regmap[i],
211			    QOS_BANDWIDTH,
212			    &pd->qos_save_regs[2][i]);
213		regmap_read(pd->qos_regmap[i],
214			    QOS_SATURATION,
215			    &pd->qos_save_regs[3][i]);
216		regmap_read(pd->qos_regmap[i],
217			    QOS_EXTCONTROL,
218			    &pd->qos_save_regs[4][i]);
219	}
220	return 0;
221}
222
223static int rockchip_pmu_restore_qos(struct rockchip_pm_domain *pd)
224{
225	int i;
226
227	for (i = 0; i < pd->num_qos; i++) {
228		regmap_write(pd->qos_regmap[i],
229			     QOS_PRIORITY,
230			     pd->qos_save_regs[0][i]);
231		regmap_write(pd->qos_regmap[i],
232			     QOS_MODE,
233			     pd->qos_save_regs[1][i]);
234		regmap_write(pd->qos_regmap[i],
235			     QOS_BANDWIDTH,
236			     pd->qos_save_regs[2][i]);
237		regmap_write(pd->qos_regmap[i],
238			     QOS_SATURATION,
239			     pd->qos_save_regs[3][i]);
240		regmap_write(pd->qos_regmap[i],
241			     QOS_EXTCONTROL,
242			     pd->qos_save_regs[4][i]);
243	}
244
245	return 0;
246}
247
248static bool rockchip_pmu_domain_is_on(struct rockchip_pm_domain *pd)
249{
250	struct rockchip_pmu *pmu = pd->pmu;
251	unsigned int val;
252
253	/* check idle status for idle-only domains */
254	if (pd->info->status_mask == 0)
255		return !rockchip_pmu_domain_is_idle(pd);
256
257	regmap_read(pmu->regmap, pmu->info->status_offset, &val);
258
259	/* 1'b0: power on, 1'b1: power off */
260	return !(val & pd->info->status_mask);
261}
262
263static void rockchip_do_pmu_set_power_domain(struct rockchip_pm_domain *pd,
264					     bool on)
265{
266	struct rockchip_pmu *pmu = pd->pmu;
267	struct generic_pm_domain *genpd = &pd->genpd;
268	bool is_on;
269
270	if (pd->info->pwr_mask == 0)
271		return;
272	else if (pd->info->pwr_w_mask)
273		regmap_write(pmu->regmap, pmu->info->pwr_offset,
274			     on ? pd->info->pwr_w_mask :
275			     (pd->info->pwr_mask | pd->info->pwr_w_mask));
276	else
277		regmap_update_bits(pmu->regmap, pmu->info->pwr_offset,
278				   pd->info->pwr_mask, on ? 0 : -1U);
279
280	dsb(sy);
281
282	if (readx_poll_timeout_atomic(rockchip_pmu_domain_is_on, pd, is_on,
283				      is_on == on, 0, 10000)) {
284		dev_err(pmu->dev,
285			"failed to set domain '%s', val=%d\n",
286			genpd->name, is_on);
287		return;
288	}
289}
290
291static int rockchip_pd_power(struct rockchip_pm_domain *pd, bool power_on)
292{
293	struct rockchip_pmu *pmu = pd->pmu;
294	int ret;
295
296	mutex_lock(&pmu->mutex);
297
298	if (rockchip_pmu_domain_is_on(pd) != power_on) {
299		ret = clk_bulk_enable(pd->num_clks, pd->clks);
300		if (ret < 0) {
301			dev_err(pmu->dev, "failed to enable clocks\n");
302			mutex_unlock(&pmu->mutex);
303			return ret;
304		}
305
306		if (!power_on) {
307			rockchip_pmu_save_qos(pd);
308
309			/* if powering down, idle request to NIU first */
310			rockchip_pmu_set_idle_request(pd, true);
311		}
312
313		rockchip_do_pmu_set_power_domain(pd, power_on);
314
315		if (power_on) {
316			/* if powering up, leave idle mode */
317			rockchip_pmu_set_idle_request(pd, false);
318
319			rockchip_pmu_restore_qos(pd);
320		}
321
322		clk_bulk_disable(pd->num_clks, pd->clks);
323	}
324
325	mutex_unlock(&pmu->mutex);
326	return 0;
327}
328
329static int rockchip_pd_power_on(struct generic_pm_domain *domain)
330{
331	struct rockchip_pm_domain *pd = to_rockchip_pd(domain);
332
333	return rockchip_pd_power(pd, true);
334}
335
336static int rockchip_pd_power_off(struct generic_pm_domain *domain)
337{
338	struct rockchip_pm_domain *pd = to_rockchip_pd(domain);
339
340	return rockchip_pd_power(pd, false);
341}
342
343static int rockchip_pd_attach_dev(struct generic_pm_domain *genpd,
344				  struct device *dev)
345{
346	struct clk *clk;
347	int i;
348	int error;
349
350	dev_dbg(dev, "attaching to power domain '%s'\n", genpd->name);
351
352	error = pm_clk_create(dev);
353	if (error) {
354		dev_err(dev, "pm_clk_create failed %d\n", error);
355		return error;
356	}
357
358	i = 0;
359	while ((clk = of_clk_get(dev->of_node, i++)) && !IS_ERR(clk)) {
360		dev_dbg(dev, "adding clock '%pC' to list of PM clocks\n", clk);
361		error = pm_clk_add_clk(dev, clk);
362		if (error) {
363			dev_err(dev, "pm_clk_add_clk failed %d\n", error);
364			clk_put(clk);
365			pm_clk_destroy(dev);
366			return error;
367		}
368	}
369
370	return 0;
371}
372
373static void rockchip_pd_detach_dev(struct generic_pm_domain *genpd,
374				   struct device *dev)
375{
376	dev_dbg(dev, "detaching from power domain '%s'\n", genpd->name);
377
378	pm_clk_destroy(dev);
379}
380
381static int rockchip_pm_add_one_domain(struct rockchip_pmu *pmu,
382				      struct device_node *node)
383{
384	const struct rockchip_domain_info *pd_info;
385	struct rockchip_pm_domain *pd;
386	struct device_node *qos_node;
387	int i, j;
388	u32 id;
389	int error;
390
391	error = of_property_read_u32(node, "reg", &id);
392	if (error) {
393		dev_err(pmu->dev,
394			"%pOFn: failed to retrieve domain id (reg): %d\n",
395			node, error);
396		return -EINVAL;
397	}
398
399	if (id >= pmu->info->num_domains) {
400		dev_err(pmu->dev, "%pOFn: invalid domain id %d\n",
401			node, id);
402		return -EINVAL;
403	}
404
405	pd_info = &pmu->info->domain_info[id];
406	if (!pd_info) {
407		dev_err(pmu->dev, "%pOFn: undefined domain id %d\n",
408			node, id);
409		return -EINVAL;
410	}
411
412	pd = devm_kzalloc(pmu->dev, sizeof(*pd), GFP_KERNEL);
413	if (!pd)
414		return -ENOMEM;
415
416	pd->info = pd_info;
417	pd->pmu = pmu;
418
419	pd->num_clks = of_clk_get_parent_count(node);
420	if (pd->num_clks > 0) {
421		pd->clks = devm_kcalloc(pmu->dev, pd->num_clks,
422					sizeof(*pd->clks), GFP_KERNEL);
423		if (!pd->clks)
424			return -ENOMEM;
425	} else {
426		dev_dbg(pmu->dev, "%pOFn: doesn't have clocks: %d\n",
427			node, pd->num_clks);
428		pd->num_clks = 0;
429	}
430
431	for (i = 0; i < pd->num_clks; i++) {
432		pd->clks[i].clk = of_clk_get(node, i);
433		if (IS_ERR(pd->clks[i].clk)) {
434			error = PTR_ERR(pd->clks[i].clk);
435			dev_err(pmu->dev,
436				"%pOFn: failed to get clk at index %d: %d\n",
437				node, i, error);
438			return error;
439		}
440	}
441
442	error = clk_bulk_prepare(pd->num_clks, pd->clks);
443	if (error)
444		goto err_put_clocks;
445
446	pd->num_qos = of_count_phandle_with_args(node, "pm_qos",
447						 NULL);
448
449	if (pd->num_qos > 0) {
450		pd->qos_regmap = devm_kcalloc(pmu->dev, pd->num_qos,
451					      sizeof(*pd->qos_regmap),
452					      GFP_KERNEL);
453		if (!pd->qos_regmap) {
454			error = -ENOMEM;
455			goto err_unprepare_clocks;
456		}
457
458		for (j = 0; j < MAX_QOS_REGS_NUM; j++) {
459			pd->qos_save_regs[j] = devm_kcalloc(pmu->dev,
460							    pd->num_qos,
461							    sizeof(u32),
462							    GFP_KERNEL);
463			if (!pd->qos_save_regs[j]) {
464				error = -ENOMEM;
465				goto err_unprepare_clocks;
466			}
467		}
468
469		for (j = 0; j < pd->num_qos; j++) {
470			qos_node = of_parse_phandle(node, "pm_qos", j);
471			if (!qos_node) {
472				error = -ENODEV;
473				goto err_unprepare_clocks;
474			}
475			pd->qos_regmap[j] = syscon_node_to_regmap(qos_node);
476			if (IS_ERR(pd->qos_regmap[j])) {
477				error = -ENODEV;
478				of_node_put(qos_node);
479				goto err_unprepare_clocks;
480			}
481			of_node_put(qos_node);
482		}
483	}
484
485	error = rockchip_pd_power(pd, true);
486	if (error) {
487		dev_err(pmu->dev,
488			"failed to power on domain '%pOFn': %d\n",
489			node, error);
490		goto err_unprepare_clocks;
491	}
492
493	pd->genpd.name = node->name;
494	pd->genpd.power_off = rockchip_pd_power_off;
495	pd->genpd.power_on = rockchip_pd_power_on;
496	pd->genpd.attach_dev = rockchip_pd_attach_dev;
497	pd->genpd.detach_dev = rockchip_pd_detach_dev;
498	pd->genpd.flags = GENPD_FLAG_PM_CLK;
499	if (pd_info->active_wakeup)
500		pd->genpd.flags |= GENPD_FLAG_ACTIVE_WAKEUP;
501	pm_genpd_init(&pd->genpd, NULL, false);
502
503	pmu->genpd_data.domains[id] = &pd->genpd;
504	return 0;
505
506err_unprepare_clocks:
507	clk_bulk_unprepare(pd->num_clks, pd->clks);
508err_put_clocks:
509	clk_bulk_put(pd->num_clks, pd->clks);
510	return error;
511}
512
513static void rockchip_pm_remove_one_domain(struct rockchip_pm_domain *pd)
514{
515	int ret;
516
517	/*
518	 * We're in the error cleanup already, so we only complain,
519	 * but won't emit another error on top of the original one.
520	 */
521	ret = pm_genpd_remove(&pd->genpd);
522	if (ret < 0)
523		dev_err(pd->pmu->dev, "failed to remove domain '%s' : %d - state may be inconsistent\n",
524			pd->genpd.name, ret);
525
526	clk_bulk_unprepare(pd->num_clks, pd->clks);
527	clk_bulk_put(pd->num_clks, pd->clks);
528
529	/* protect the zeroing of pm->num_clks */
530	mutex_lock(&pd->pmu->mutex);
531	pd->num_clks = 0;
532	mutex_unlock(&pd->pmu->mutex);
533
534	/* devm will free our memory */
535}
536
537static void rockchip_pm_domain_cleanup(struct rockchip_pmu *pmu)
538{
539	struct generic_pm_domain *genpd;
540	struct rockchip_pm_domain *pd;
541	int i;
542
543	for (i = 0; i < pmu->genpd_data.num_domains; i++) {
544		genpd = pmu->genpd_data.domains[i];
545		if (genpd) {
546			pd = to_rockchip_pd(genpd);
547			rockchip_pm_remove_one_domain(pd);
548		}
549	}
550
551	/* devm will free our memory */
552}
553
554static void rockchip_configure_pd_cnt(struct rockchip_pmu *pmu,
555				      u32 domain_reg_offset,
556				      unsigned int count)
557{
558	/* First configure domain power down transition count ... */
559	regmap_write(pmu->regmap, domain_reg_offset, count);
560	/* ... and then power up count. */
561	regmap_write(pmu->regmap, domain_reg_offset + 4, count);
562}
563
564static int rockchip_pm_add_subdomain(struct rockchip_pmu *pmu,
565				     struct device_node *parent)
566{
567	struct device_node *np;
568	struct generic_pm_domain *child_domain, *parent_domain;
569	int error;
570
571	for_each_child_of_node(parent, np) {
572		u32 idx;
573
574		error = of_property_read_u32(parent, "reg", &idx);
575		if (error) {
576			dev_err(pmu->dev,
577				"%pOFn: failed to retrieve domain id (reg): %d\n",
578				parent, error);
579			goto err_out;
580		}
581		parent_domain = pmu->genpd_data.domains[idx];
582
583		error = rockchip_pm_add_one_domain(pmu, np);
584		if (error) {
585			dev_err(pmu->dev, "failed to handle node %pOFn: %d\n",
586				np, error);
587			goto err_out;
588		}
589
590		error = of_property_read_u32(np, "reg", &idx);
591		if (error) {
592			dev_err(pmu->dev,
593				"%pOFn: failed to retrieve domain id (reg): %d\n",
594				np, error);
595			goto err_out;
596		}
597		child_domain = pmu->genpd_data.domains[idx];
598
599		error = pm_genpd_add_subdomain(parent_domain, child_domain);
600		if (error) {
601			dev_err(pmu->dev, "%s failed to add subdomain %s: %d\n",
602				parent_domain->name, child_domain->name, error);
603			goto err_out;
604		} else {
605			dev_dbg(pmu->dev, "%s add subdomain: %s\n",
606				parent_domain->name, child_domain->name);
607		}
608
609		rockchip_pm_add_subdomain(pmu, np);
610	}
611
612	return 0;
613
614err_out:
615	of_node_put(np);
616	return error;
617}
618
619static int rockchip_pm_domain_probe(struct platform_device *pdev)
620{
621	struct device *dev = &pdev->dev;
622	struct device_node *np = dev->of_node;
623	struct device_node *node;
624	struct device *parent;
625	struct rockchip_pmu *pmu;
626	const struct of_device_id *match;
627	const struct rockchip_pmu_info *pmu_info;
628	int error;
629
630	if (!np) {
631		dev_err(dev, "device tree node not found\n");
632		return -ENODEV;
633	}
634
635	match = of_match_device(dev->driver->of_match_table, dev);
636	if (!match || !match->data) {
637		dev_err(dev, "missing pmu data\n");
638		return -EINVAL;
639	}
640
641	pmu_info = match->data;
642
643	pmu = devm_kzalloc(dev,
644			   struct_size(pmu, domains, pmu_info->num_domains),
645			   GFP_KERNEL);
646	if (!pmu)
647		return -ENOMEM;
648
649	pmu->dev = &pdev->dev;
650	mutex_init(&pmu->mutex);
651
652	pmu->info = pmu_info;
653
654	pmu->genpd_data.domains = pmu->domains;
655	pmu->genpd_data.num_domains = pmu_info->num_domains;
656
657	parent = dev->parent;
658	if (!parent) {
659		dev_err(dev, "no parent for syscon devices\n");
660		return -ENODEV;
661	}
662
663	pmu->regmap = syscon_node_to_regmap(parent->of_node);
664	if (IS_ERR(pmu->regmap)) {
665		dev_err(dev, "no regmap available\n");
666		return PTR_ERR(pmu->regmap);
667	}
668
669	/*
670	 * Configure power up and down transition delays for CORE
671	 * and GPU domains.
672	 */
673	if (pmu_info->core_power_transition_time)
674		rockchip_configure_pd_cnt(pmu, pmu_info->core_pwrcnt_offset,
675					pmu_info->core_power_transition_time);
676	if (pmu_info->gpu_pwrcnt_offset)
677		rockchip_configure_pd_cnt(pmu, pmu_info->gpu_pwrcnt_offset,
678					pmu_info->gpu_power_transition_time);
679
680	error = -ENODEV;
681
682	for_each_available_child_of_node(np, node) {
683		error = rockchip_pm_add_one_domain(pmu, node);
684		if (error) {
685			dev_err(dev, "failed to handle node %pOFn: %d\n",
686				node, error);
687			of_node_put(node);
688			goto err_out;
689		}
690
691		error = rockchip_pm_add_subdomain(pmu, node);
692		if (error < 0) {
693			dev_err(dev, "failed to handle subdomain node %pOFn: %d\n",
694				node, error);
695			of_node_put(node);
696			goto err_out;
697		}
698	}
699
700	if (error) {
701		dev_dbg(dev, "no power domains defined\n");
702		goto err_out;
703	}
704
705	error = of_genpd_add_provider_onecell(np, &pmu->genpd_data);
706	if (error) {
707		dev_err(dev, "failed to add provider: %d\n", error);
708		goto err_out;
709	}
710
711	return 0;
712
713err_out:
714	rockchip_pm_domain_cleanup(pmu);
715	return error;
716}
717
718static const struct rockchip_domain_info px30_pm_domains[] = {
719	[PX30_PD_USB]		= DOMAIN_PX30(BIT(5),  BIT(5),  BIT(10), false),
720	[PX30_PD_SDCARD]	= DOMAIN_PX30(BIT(8),  BIT(8),  BIT(9),  false),
721	[PX30_PD_GMAC]		= DOMAIN_PX30(BIT(10), BIT(10), BIT(6),  false),
722	[PX30_PD_MMC_NAND]	= DOMAIN_PX30(BIT(11), BIT(11), BIT(5),  false),
723	[PX30_PD_VPU]		= DOMAIN_PX30(BIT(12), BIT(12), BIT(14), false),
724	[PX30_PD_VO]		= DOMAIN_PX30(BIT(13), BIT(13), BIT(7),  false),
725	[PX30_PD_VI]		= DOMAIN_PX30(BIT(14), BIT(14), BIT(8),  false),
726	[PX30_PD_GPU]		= DOMAIN_PX30(BIT(15), BIT(15), BIT(2),  false),
727};
728
729static const struct rockchip_domain_info rk3036_pm_domains[] = {
730	[RK3036_PD_MSCH]	= DOMAIN_RK3036(BIT(14), BIT(23), BIT(30), true),
731	[RK3036_PD_CORE]	= DOMAIN_RK3036(BIT(13), BIT(17), BIT(24), false),
732	[RK3036_PD_PERI]	= DOMAIN_RK3036(BIT(12), BIT(18), BIT(25), false),
733	[RK3036_PD_VIO]		= DOMAIN_RK3036(BIT(11), BIT(19), BIT(26), false),
734	[RK3036_PD_VPU]		= DOMAIN_RK3036(BIT(10), BIT(20), BIT(27), false),
735	[RK3036_PD_GPU]		= DOMAIN_RK3036(BIT(9),  BIT(21), BIT(28), false),
736	[RK3036_PD_SYS]		= DOMAIN_RK3036(BIT(8),  BIT(22), BIT(29), false),
737};
738
739static const struct rockchip_domain_info rk3066_pm_domains[] = {
740	[RK3066_PD_GPU]		= DOMAIN(BIT(9), BIT(9), BIT(3), BIT(24), BIT(29), false),
741	[RK3066_PD_VIDEO]	= DOMAIN(BIT(8), BIT(8), BIT(4), BIT(23), BIT(28), false),
742	[RK3066_PD_VIO]		= DOMAIN(BIT(7), BIT(7), BIT(5), BIT(22), BIT(27), false),
743	[RK3066_PD_PERI]	= DOMAIN(BIT(6), BIT(6), BIT(2), BIT(25), BIT(30), false),
744	[RK3066_PD_CPU]		= DOMAIN(0,      BIT(5), BIT(1), BIT(26), BIT(31), false),
745};
746
747static const struct rockchip_domain_info rk3128_pm_domains[] = {
748	[RK3128_PD_CORE]	= DOMAIN_RK3288(BIT(0), BIT(0), BIT(4), false),
749	[RK3128_PD_MSCH]	= DOMAIN_RK3288(0,      0,      BIT(6), true),
750	[RK3128_PD_VIO]		= DOMAIN_RK3288(BIT(3), BIT(3), BIT(2), false),
751	[RK3128_PD_VIDEO]	= DOMAIN_RK3288(BIT(2), BIT(2), BIT(1), false),
752	[RK3128_PD_GPU]		= DOMAIN_RK3288(BIT(1), BIT(1), BIT(3), false),
753};
754
755static const struct rockchip_domain_info rk3188_pm_domains[] = {
756	[RK3188_PD_GPU]		= DOMAIN(BIT(9), BIT(9), BIT(3), BIT(24), BIT(29), false),
757	[RK3188_PD_VIDEO]	= DOMAIN(BIT(8), BIT(8), BIT(4), BIT(23), BIT(28), false),
758	[RK3188_PD_VIO]		= DOMAIN(BIT(7), BIT(7), BIT(5), BIT(22), BIT(27), false),
759	[RK3188_PD_PERI]	= DOMAIN(BIT(6), BIT(6), BIT(2), BIT(25), BIT(30), false),
760	[RK3188_PD_CPU]		= DOMAIN(BIT(5), BIT(5), BIT(1), BIT(26), BIT(31), false),
761};
762
763static const struct rockchip_domain_info rk3228_pm_domains[] = {
764	[RK3228_PD_CORE]	= DOMAIN_RK3036(BIT(0),  BIT(0),  BIT(16), true),
765	[RK3228_PD_MSCH]	= DOMAIN_RK3036(BIT(1),  BIT(1),  BIT(17), true),
766	[RK3228_PD_BUS]		= DOMAIN_RK3036(BIT(2),  BIT(2),  BIT(18), true),
767	[RK3228_PD_SYS]		= DOMAIN_RK3036(BIT(3),  BIT(3),  BIT(19), true),
768	[RK3228_PD_VIO]		= DOMAIN_RK3036(BIT(4),  BIT(4),  BIT(20), false),
769	[RK3228_PD_VOP]		= DOMAIN_RK3036(BIT(5),  BIT(5),  BIT(21), false),
770	[RK3228_PD_VPU]		= DOMAIN_RK3036(BIT(6),  BIT(6),  BIT(22), false),
771	[RK3228_PD_RKVDEC]	= DOMAIN_RK3036(BIT(7),  BIT(7),  BIT(23), false),
772	[RK3228_PD_GPU]		= DOMAIN_RK3036(BIT(8),  BIT(8),  BIT(24), false),
773	[RK3228_PD_PERI]	= DOMAIN_RK3036(BIT(9),  BIT(9),  BIT(25), true),
774	[RK3228_PD_GMAC]	= DOMAIN_RK3036(BIT(10), BIT(10), BIT(26), false),
775};
776
777static const struct rockchip_domain_info rk3288_pm_domains[] = {
778	[RK3288_PD_VIO]		= DOMAIN_RK3288(BIT(7),  BIT(7),  BIT(4), false),
779	[RK3288_PD_HEVC]	= DOMAIN_RK3288(BIT(14), BIT(10), BIT(9), false),
780	[RK3288_PD_VIDEO]	= DOMAIN_RK3288(BIT(8),  BIT(8),  BIT(3), false),
781	[RK3288_PD_GPU]		= DOMAIN_RK3288(BIT(9),  BIT(9),  BIT(2), false),
782};
783
784static const struct rockchip_domain_info rk3328_pm_domains[] = {
785	[RK3328_PD_CORE]	= DOMAIN_RK3328(0, BIT(0), BIT(0), false),
786	[RK3328_PD_GPU]		= DOMAIN_RK3328(0, BIT(1), BIT(1), false),
787	[RK3328_PD_BUS]		= DOMAIN_RK3328(0, BIT(2), BIT(2), true),
788	[RK3328_PD_MSCH]	= DOMAIN_RK3328(0, BIT(3), BIT(3), true),
789	[RK3328_PD_PERI]	= DOMAIN_RK3328(0, BIT(4), BIT(4), true),
790	[RK3328_PD_VIDEO]	= DOMAIN_RK3328(0, BIT(5), BIT(5), false),
791	[RK3328_PD_HEVC]	= DOMAIN_RK3328(0, BIT(6), BIT(6), false),
792	[RK3328_PD_VIO]		= DOMAIN_RK3328(0, BIT(8), BIT(8), false),
793	[RK3328_PD_VPU]		= DOMAIN_RK3328(0, BIT(9), BIT(9), false),
794};
795
796static const struct rockchip_domain_info rk3366_pm_domains[] = {
797	[RK3366_PD_PERI]	= DOMAIN_RK3368(BIT(10), BIT(10), BIT(6), true),
798	[RK3366_PD_VIO]		= DOMAIN_RK3368(BIT(14), BIT(14), BIT(8), false),
799	[RK3366_PD_VIDEO]	= DOMAIN_RK3368(BIT(13), BIT(13), BIT(7), false),
800	[RK3366_PD_RKVDEC]	= DOMAIN_RK3368(BIT(11), BIT(11), BIT(7), false),
801	[RK3366_PD_WIFIBT]	= DOMAIN_RK3368(BIT(8),  BIT(8),  BIT(9), false),
802	[RK3366_PD_VPU]		= DOMAIN_RK3368(BIT(12), BIT(12), BIT(7), false),
803	[RK3366_PD_GPU]		= DOMAIN_RK3368(BIT(15), BIT(15), BIT(2), false),
804};
805
806static const struct rockchip_domain_info rk3368_pm_domains[] = {
807	[RK3368_PD_PERI]	= DOMAIN_RK3368(BIT(13), BIT(12), BIT(6), true),
808	[RK3368_PD_VIO]		= DOMAIN_RK3368(BIT(15), BIT(14), BIT(8), false),
809	[RK3368_PD_VIDEO]	= DOMAIN_RK3368(BIT(14), BIT(13), BIT(7), false),
810	[RK3368_PD_GPU_0]	= DOMAIN_RK3368(BIT(16), BIT(15), BIT(2), false),
811	[RK3368_PD_GPU_1]	= DOMAIN_RK3368(BIT(17), BIT(16), BIT(2), false),
812};
813
814static const struct rockchip_domain_info rk3399_pm_domains[] = {
815	[RK3399_PD_TCPD0]	= DOMAIN_RK3399(BIT(8),  BIT(8),  0,	   false),
816	[RK3399_PD_TCPD1]	= DOMAIN_RK3399(BIT(9),  BIT(9),  0,	   false),
817	[RK3399_PD_CCI]		= DOMAIN_RK3399(BIT(10), BIT(10), 0,	   true),
818	[RK3399_PD_CCI0]	= DOMAIN_RK3399(0,	 0,	  BIT(15), true),
819	[RK3399_PD_CCI1]	= DOMAIN_RK3399(0,	 0,	  BIT(16), true),
820	[RK3399_PD_PERILP]	= DOMAIN_RK3399(BIT(11), BIT(11), BIT(1),  true),
821	[RK3399_PD_PERIHP]	= DOMAIN_RK3399(BIT(12), BIT(12), BIT(2),  true),
822	[RK3399_PD_CENTER]	= DOMAIN_RK3399(BIT(13), BIT(13), BIT(14), true),
823	[RK3399_PD_VIO]		= DOMAIN_RK3399(BIT(14), BIT(14), BIT(17), false),
824	[RK3399_PD_GPU]		= DOMAIN_RK3399(BIT(15), BIT(15), BIT(0),  false),
825	[RK3399_PD_VCODEC]	= DOMAIN_RK3399(BIT(16), BIT(16), BIT(3),  false),
826	[RK3399_PD_VDU]		= DOMAIN_RK3399(BIT(17), BIT(17), BIT(4),  false),
827	[RK3399_PD_RGA]		= DOMAIN_RK3399(BIT(18), BIT(18), BIT(5),  false),
828	[RK3399_PD_IEP]		= DOMAIN_RK3399(BIT(19), BIT(19), BIT(6),  false),
829	[RK3399_PD_VO]		= DOMAIN_RK3399(BIT(20), BIT(20), 0,	   false),
830	[RK3399_PD_VOPB]	= DOMAIN_RK3399(0,	 0,	  BIT(7),  false),
831	[RK3399_PD_VOPL]	= DOMAIN_RK3399(0, 	 0,	  BIT(8),  false),
832	[RK3399_PD_ISP0]	= DOMAIN_RK3399(BIT(22), BIT(22), BIT(9),  false),
833	[RK3399_PD_ISP1]	= DOMAIN_RK3399(BIT(23), BIT(23), BIT(10), false),
834	[RK3399_PD_HDCP]	= DOMAIN_RK3399(BIT(24), BIT(24), BIT(11), false),
835	[RK3399_PD_GMAC]	= DOMAIN_RK3399(BIT(25), BIT(25), BIT(23), true),
836	[RK3399_PD_EMMC]	= DOMAIN_RK3399(BIT(26), BIT(26), BIT(24), true),
837	[RK3399_PD_USB3]	= DOMAIN_RK3399(BIT(27), BIT(27), BIT(12), true),
838	[RK3399_PD_EDP]		= DOMAIN_RK3399(BIT(28), BIT(28), BIT(22), false),
839	[RK3399_PD_GIC]		= DOMAIN_RK3399(BIT(29), BIT(29), BIT(27), true),
840	[RK3399_PD_SD]		= DOMAIN_RK3399(BIT(30), BIT(30), BIT(28), true),
841	[RK3399_PD_SDIOAUDIO]	= DOMAIN_RK3399(BIT(31), BIT(31), BIT(29), true),
842};
843
844static const struct rockchip_pmu_info px30_pmu = {
845	.pwr_offset = 0x18,
846	.status_offset = 0x20,
847	.req_offset = 0x64,
848	.idle_offset = 0x6c,
849	.ack_offset = 0x6c,
850
851	.num_domains = ARRAY_SIZE(px30_pm_domains),
852	.domain_info = px30_pm_domains,
853};
854
855static const struct rockchip_pmu_info rk3036_pmu = {
856	.req_offset = 0x148,
857	.idle_offset = 0x14c,
858	.ack_offset = 0x14c,
859
860	.num_domains = ARRAY_SIZE(rk3036_pm_domains),
861	.domain_info = rk3036_pm_domains,
862};
863
864static const struct rockchip_pmu_info rk3066_pmu = {
865	.pwr_offset = 0x08,
866	.status_offset = 0x0c,
867	.req_offset = 0x38, /* PMU_MISC_CON1 */
868	.idle_offset = 0x0c,
869	.ack_offset = 0x0c,
870
871	.num_domains = ARRAY_SIZE(rk3066_pm_domains),
872	.domain_info = rk3066_pm_domains,
873};
874
875static const struct rockchip_pmu_info rk3128_pmu = {
876	.pwr_offset = 0x04,
877	.status_offset = 0x08,
878	.req_offset = 0x0c,
879	.idle_offset = 0x10,
880	.ack_offset = 0x10,
881
882	.num_domains = ARRAY_SIZE(rk3128_pm_domains),
883	.domain_info = rk3128_pm_domains,
884};
885
886static const struct rockchip_pmu_info rk3188_pmu = {
887	.pwr_offset = 0x08,
888	.status_offset = 0x0c,
889	.req_offset = 0x38, /* PMU_MISC_CON1 */
890	.idle_offset = 0x0c,
891	.ack_offset = 0x0c,
892
893	.num_domains = ARRAY_SIZE(rk3188_pm_domains),
894	.domain_info = rk3188_pm_domains,
895};
896
897static const struct rockchip_pmu_info rk3228_pmu = {
898	.req_offset = 0x40c,
899	.idle_offset = 0x488,
900	.ack_offset = 0x488,
901
902	.num_domains = ARRAY_SIZE(rk3228_pm_domains),
903	.domain_info = rk3228_pm_domains,
904};
905
906static const struct rockchip_pmu_info rk3288_pmu = {
907	.pwr_offset = 0x08,
908	.status_offset = 0x0c,
909	.req_offset = 0x10,
910	.idle_offset = 0x14,
911	.ack_offset = 0x14,
912
913	.core_pwrcnt_offset = 0x34,
914	.gpu_pwrcnt_offset = 0x3c,
915
916	.core_power_transition_time = 24, /* 1us */
917	.gpu_power_transition_time = 24, /* 1us */
918
919	.num_domains = ARRAY_SIZE(rk3288_pm_domains),
920	.domain_info = rk3288_pm_domains,
921};
922
923static const struct rockchip_pmu_info rk3328_pmu = {
924	.req_offset = 0x414,
925	.idle_offset = 0x484,
926	.ack_offset = 0x484,
927
928	.num_domains = ARRAY_SIZE(rk3328_pm_domains),
929	.domain_info = rk3328_pm_domains,
930};
931
932static const struct rockchip_pmu_info rk3366_pmu = {
933	.pwr_offset = 0x0c,
934	.status_offset = 0x10,
935	.req_offset = 0x3c,
936	.idle_offset = 0x40,
937	.ack_offset = 0x40,
938
939	.core_pwrcnt_offset = 0x48,
940	.gpu_pwrcnt_offset = 0x50,
941
942	.core_power_transition_time = 24,
943	.gpu_power_transition_time = 24,
944
945	.num_domains = ARRAY_SIZE(rk3366_pm_domains),
946	.domain_info = rk3366_pm_domains,
947};
948
949static const struct rockchip_pmu_info rk3368_pmu = {
950	.pwr_offset = 0x0c,
951	.status_offset = 0x10,
952	.req_offset = 0x3c,
953	.idle_offset = 0x40,
954	.ack_offset = 0x40,
955
956	.core_pwrcnt_offset = 0x48,
957	.gpu_pwrcnt_offset = 0x50,
958
959	.core_power_transition_time = 24,
960	.gpu_power_transition_time = 24,
961
962	.num_domains = ARRAY_SIZE(rk3368_pm_domains),
963	.domain_info = rk3368_pm_domains,
964};
965
966static const struct rockchip_pmu_info rk3399_pmu = {
967	.pwr_offset = 0x14,
968	.status_offset = 0x18,
969	.req_offset = 0x60,
970	.idle_offset = 0x64,
971	.ack_offset = 0x68,
972
973	/* ARM Trusted Firmware manages power transition times */
974
975	.num_domains = ARRAY_SIZE(rk3399_pm_domains),
976	.domain_info = rk3399_pm_domains,
977};
978
979static const struct of_device_id rockchip_pm_domain_dt_match[] = {
980	{
981		.compatible = "rockchip,px30-power-controller",
982		.data = (void *)&px30_pmu,
983	},
984	{
985		.compatible = "rockchip,rk3036-power-controller",
986		.data = (void *)&rk3036_pmu,
987	},
988	{
989		.compatible = "rockchip,rk3066-power-controller",
990		.data = (void *)&rk3066_pmu,
991	},
992	{
993		.compatible = "rockchip,rk3128-power-controller",
994		.data = (void *)&rk3128_pmu,
995	},
996	{
997		.compatible = "rockchip,rk3188-power-controller",
998		.data = (void *)&rk3188_pmu,
999	},
1000	{
1001		.compatible = "rockchip,rk3228-power-controller",
1002		.data = (void *)&rk3228_pmu,
1003	},
1004	{
1005		.compatible = "rockchip,rk3288-power-controller",
1006		.data = (void *)&rk3288_pmu,
1007	},
1008	{
1009		.compatible = "rockchip,rk3328-power-controller",
1010		.data = (void *)&rk3328_pmu,
1011	},
1012	{
1013		.compatible = "rockchip,rk3366-power-controller",
1014		.data = (void *)&rk3366_pmu,
1015	},
1016	{
1017		.compatible = "rockchip,rk3368-power-controller",
1018		.data = (void *)&rk3368_pmu,
1019	},
1020	{
1021		.compatible = "rockchip,rk3399-power-controller",
1022		.data = (void *)&rk3399_pmu,
1023	},
1024	{ /* sentinel */ },
1025};
1026
1027static struct platform_driver rockchip_pm_domain_driver = {
1028	.probe = rockchip_pm_domain_probe,
1029	.driver = {
1030		.name   = "rockchip-pm-domain",
1031		.of_match_table = rockchip_pm_domain_dt_match,
1032		/*
1033		 * We can't forcibly eject devices form power domain,
1034		 * so we can't really remove power domains once they
1035		 * were added.
1036		 */
1037		.suppress_bind_attrs = true,
1038	},
1039};
1040
1041static int __init rockchip_pm_domain_drv_register(void)
1042{
1043	return platform_driver_register(&rockchip_pm_domain_driver);
1044}
1045postcore_initcall(rockchip_pm_domain_drv_register);
1046