xref: /OK3568_Linux_fs/kernel/drivers/soc/rockchip/rockchip_pvtm.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * Rockchip PVTM support.
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Copyright (c) 2016 Rockchip Electronics Co. Ltd.
6*4882a593Smuzhiyun  * Author: Finley Xiao <finley.xiao@rock-chips.com>
7*4882a593Smuzhiyun  */
8*4882a593Smuzhiyun 
9*4882a593Smuzhiyun #include <linux/clk.h>
10*4882a593Smuzhiyun #include <linux/delay.h>
11*4882a593Smuzhiyun #include <linux/device.h>
12*4882a593Smuzhiyun #include <linux/debugfs.h>
13*4882a593Smuzhiyun #include <linux/io.h>
14*4882a593Smuzhiyun #include <linux/mfd/syscon.h>
15*4882a593Smuzhiyun #include <linux/module.h>
16*4882a593Smuzhiyun #include <linux/of.h>
17*4882a593Smuzhiyun #include <linux/of_clk.h>
18*4882a593Smuzhiyun #include <linux/of_platform.h>
19*4882a593Smuzhiyun #include <linux/platform_device.h>
20*4882a593Smuzhiyun #include <linux/regmap.h>
21*4882a593Smuzhiyun #include <linux/reset.h>
22*4882a593Smuzhiyun #include <linux/slab.h>
23*4882a593Smuzhiyun #include <linux/soc/rockchip/pvtm.h>
24*4882a593Smuzhiyun #include <linux/thermal.h>
25*4882a593Smuzhiyun 
26*4882a593Smuzhiyun #define wr_mask_bit(v, off, mask)	((v) << (off) | (mask) << (16 + off))
27*4882a593Smuzhiyun 
28*4882a593Smuzhiyun #define PVTM(_id, _name, _num_rings, _start, _en, _cal, _done, _freq)	\
29*4882a593Smuzhiyun {					\
30*4882a593Smuzhiyun 	.id = _id,			\
31*4882a593Smuzhiyun 	.name = _name,			\
32*4882a593Smuzhiyun 	.num_rings = _num_rings,	\
33*4882a593Smuzhiyun 	.bit_start = _start,		\
34*4882a593Smuzhiyun 	.bit_en = _en,			\
35*4882a593Smuzhiyun 	.reg_cal = _cal,		\
36*4882a593Smuzhiyun 	.bit_freq_done = _done,		\
37*4882a593Smuzhiyun 	.reg_freq = _freq,		\
38*4882a593Smuzhiyun }
39*4882a593Smuzhiyun 
40*4882a593Smuzhiyun struct rockchip_pvtm;
41*4882a593Smuzhiyun 
42*4882a593Smuzhiyun struct rockchip_pvtm_ops {
43*4882a593Smuzhiyun 	u32 (*get_value)(struct rockchip_pvtm *pvtm, unsigned int ring_sel,
44*4882a593Smuzhiyun 			 unsigned int time_us);
45*4882a593Smuzhiyun 	void (*set_ring_sel)(struct rockchip_pvtm *pvtm, unsigned int ring_sel);
46*4882a593Smuzhiyun };
47*4882a593Smuzhiyun 
48*4882a593Smuzhiyun struct rockchip_pvtm_info {
49*4882a593Smuzhiyun 	u32 reg_cal;
50*4882a593Smuzhiyun 	u32 reg_freq;
51*4882a593Smuzhiyun 	unsigned char id;
52*4882a593Smuzhiyun 	unsigned char *name;
53*4882a593Smuzhiyun 	unsigned int num_rings;
54*4882a593Smuzhiyun 	unsigned int bit_start;
55*4882a593Smuzhiyun 	unsigned int bit_en;
56*4882a593Smuzhiyun 	unsigned int bit_freq_done;
57*4882a593Smuzhiyun };
58*4882a593Smuzhiyun 
59*4882a593Smuzhiyun struct rockchip_pvtm_data {
60*4882a593Smuzhiyun 	u32 con;
61*4882a593Smuzhiyun 	u32 sta;
62*4882a593Smuzhiyun 	unsigned int num_pvtms;
63*4882a593Smuzhiyun 	const struct rockchip_pvtm_info *infos;
64*4882a593Smuzhiyun 	const struct rockchip_pvtm_ops ops;
65*4882a593Smuzhiyun };
66*4882a593Smuzhiyun 
67*4882a593Smuzhiyun struct rockchip_pvtm {
68*4882a593Smuzhiyun 	u32 con;
69*4882a593Smuzhiyun 	u32 sta;
70*4882a593Smuzhiyun 	struct list_head node;
71*4882a593Smuzhiyun 	struct device *dev;
72*4882a593Smuzhiyun 	struct regmap *grf;
73*4882a593Smuzhiyun 	void __iomem *base;
74*4882a593Smuzhiyun 	int num_clks;
75*4882a593Smuzhiyun 	struct clk_bulk_data *clks;
76*4882a593Smuzhiyun 	struct reset_control *rst;
77*4882a593Smuzhiyun 	struct thermal_zone_device *tz;
78*4882a593Smuzhiyun 	const struct rockchip_pvtm_info *info;
79*4882a593Smuzhiyun 	const struct rockchip_pvtm_ops *ops;
80*4882a593Smuzhiyun 	struct dentry *dentry;
81*4882a593Smuzhiyun };
82*4882a593Smuzhiyun 
83*4882a593Smuzhiyun static LIST_HEAD(pvtm_list);
84*4882a593Smuzhiyun 
85*4882a593Smuzhiyun #ifdef CONFIG_DEBUG_FS
86*4882a593Smuzhiyun static struct dentry *rockchip_pvtm_debugfs_root;
87*4882a593Smuzhiyun 
pvtm_value_show(struct seq_file * s,void * data)88*4882a593Smuzhiyun static int pvtm_value_show(struct seq_file *s, void *data)
89*4882a593Smuzhiyun {
90*4882a593Smuzhiyun 	struct rockchip_pvtm *pvtm = (struct rockchip_pvtm *)s->private;
91*4882a593Smuzhiyun 	u32 value;
92*4882a593Smuzhiyun 	int i, ret, cur_temp;
93*4882a593Smuzhiyun 
94*4882a593Smuzhiyun 	if (!pvtm || !pvtm->ops->get_value) {
95*4882a593Smuzhiyun 		seq_puts(s, "unsupported\n");
96*4882a593Smuzhiyun 		return 0;
97*4882a593Smuzhiyun 	}
98*4882a593Smuzhiyun 
99*4882a593Smuzhiyun 	if (pvtm->tz && pvtm->tz->ops && pvtm->tz->ops->get_temp) {
100*4882a593Smuzhiyun 		ret = pvtm->tz->ops->get_temp(pvtm->tz, &cur_temp);
101*4882a593Smuzhiyun 		if (ret)
102*4882a593Smuzhiyun 			dev_err(pvtm->dev, "debug failed to get temp\n");
103*4882a593Smuzhiyun 		else
104*4882a593Smuzhiyun 			seq_printf(s, "temp: %d ", cur_temp);
105*4882a593Smuzhiyun 	}
106*4882a593Smuzhiyun 	seq_puts(s, "pvtm: ");
107*4882a593Smuzhiyun 	for (i = 0; i < pvtm->info->num_rings; i++) {
108*4882a593Smuzhiyun 		value = pvtm->ops->get_value(pvtm, i, 1000);
109*4882a593Smuzhiyun 		seq_printf(s, "%d ", value);
110*4882a593Smuzhiyun 	}
111*4882a593Smuzhiyun 	seq_puts(s, "\n");
112*4882a593Smuzhiyun 
113*4882a593Smuzhiyun 	return 0;
114*4882a593Smuzhiyun }
115*4882a593Smuzhiyun 
pvtm_value_open(struct inode * inode,struct file * file)116*4882a593Smuzhiyun static int pvtm_value_open(struct inode *inode, struct file *file)
117*4882a593Smuzhiyun {
118*4882a593Smuzhiyun 	return single_open(file, pvtm_value_show, inode->i_private);
119*4882a593Smuzhiyun }
120*4882a593Smuzhiyun 
121*4882a593Smuzhiyun static const struct file_operations pvtm_value_fops = {
122*4882a593Smuzhiyun 	.open		= pvtm_value_open,
123*4882a593Smuzhiyun 	.read		= seq_read,
124*4882a593Smuzhiyun 	.llseek		= seq_lseek,
125*4882a593Smuzhiyun 	.release	= single_release,
126*4882a593Smuzhiyun };
127*4882a593Smuzhiyun 
rockchip_pvtm_debugfs_init(void)128*4882a593Smuzhiyun static int rockchip_pvtm_debugfs_init(void)
129*4882a593Smuzhiyun {
130*4882a593Smuzhiyun 	rockchip_pvtm_debugfs_root = debugfs_create_dir("pvtm", NULL);
131*4882a593Smuzhiyun 	if (IS_ERR_OR_NULL(rockchip_pvtm_debugfs_root)) {
132*4882a593Smuzhiyun 		pr_err("Failed to create pvtm debug directory\n");
133*4882a593Smuzhiyun 		rockchip_pvtm_debugfs_root = NULL;
134*4882a593Smuzhiyun 		return -ENOMEM;
135*4882a593Smuzhiyun 	}
136*4882a593Smuzhiyun 
137*4882a593Smuzhiyun 	return 0;
138*4882a593Smuzhiyun }
139*4882a593Smuzhiyun 
rockchip_pvtm_debugfs_exit(void)140*4882a593Smuzhiyun static void rockchip_pvtm_debugfs_exit(void)
141*4882a593Smuzhiyun {
142*4882a593Smuzhiyun 	debugfs_remove_recursive(rockchip_pvtm_debugfs_root);
143*4882a593Smuzhiyun }
144*4882a593Smuzhiyun 
rockchip_pvtm_add_debugfs(struct rockchip_pvtm * pvtm)145*4882a593Smuzhiyun static int rockchip_pvtm_add_debugfs(struct rockchip_pvtm *pvtm)
146*4882a593Smuzhiyun {
147*4882a593Smuzhiyun 	struct dentry *d;
148*4882a593Smuzhiyun 
149*4882a593Smuzhiyun 	if (!rockchip_pvtm_debugfs_root)
150*4882a593Smuzhiyun 		return 0;
151*4882a593Smuzhiyun 
152*4882a593Smuzhiyun 	pvtm->dentry = debugfs_create_dir(pvtm->info->name,
153*4882a593Smuzhiyun 					  rockchip_pvtm_debugfs_root);
154*4882a593Smuzhiyun 	if (!pvtm->dentry) {
155*4882a593Smuzhiyun 		dev_err(pvtm->dev, "failed to create pvtm %s debug dir\n",
156*4882a593Smuzhiyun 			pvtm->info->name);
157*4882a593Smuzhiyun 		return -ENOMEM;
158*4882a593Smuzhiyun 	}
159*4882a593Smuzhiyun 
160*4882a593Smuzhiyun 	d = debugfs_create_file("value", 0444, pvtm->dentry,
161*4882a593Smuzhiyun 				(void *)pvtm, &pvtm_value_fops);
162*4882a593Smuzhiyun 	if (!d) {
163*4882a593Smuzhiyun 		dev_err(pvtm->dev, "failed to pvtm %s value node\n",
164*4882a593Smuzhiyun 			pvtm->info->name);
165*4882a593Smuzhiyun 		debugfs_remove_recursive(pvtm->dentry);
166*4882a593Smuzhiyun 		return -ENOMEM;
167*4882a593Smuzhiyun 	}
168*4882a593Smuzhiyun 
169*4882a593Smuzhiyun 	return 0;
170*4882a593Smuzhiyun }
171*4882a593Smuzhiyun #else
rockchip_pvtm_debugfs_init(void)172*4882a593Smuzhiyun static inline int rockchip_pvtm_debugfs_init(void)
173*4882a593Smuzhiyun {
174*4882a593Smuzhiyun 	return 0;
175*4882a593Smuzhiyun }
176*4882a593Smuzhiyun 
rockchip_pvtm_debugfs_exit(void)177*4882a593Smuzhiyun static inline void rockchip_pvtm_debugfs_exit(void)
178*4882a593Smuzhiyun {
179*4882a593Smuzhiyun }
180*4882a593Smuzhiyun 
rockchip_pvtm_add_debugfs(struct rockchip_pvtm * pvtm)181*4882a593Smuzhiyun static inline int rockchip_pvtm_add_debugfs(struct rockchip_pvtm *pvtm)
182*4882a593Smuzhiyun {
183*4882a593Smuzhiyun 	return 0;
184*4882a593Smuzhiyun }
185*4882a593Smuzhiyun #endif
186*4882a593Smuzhiyun 
rockchip_pvtm_reset(struct rockchip_pvtm * pvtm)187*4882a593Smuzhiyun static int rockchip_pvtm_reset(struct rockchip_pvtm *pvtm)
188*4882a593Smuzhiyun {
189*4882a593Smuzhiyun 	int ret;
190*4882a593Smuzhiyun 
191*4882a593Smuzhiyun 	ret = reset_control_assert(pvtm->rst);
192*4882a593Smuzhiyun 	if (ret) {
193*4882a593Smuzhiyun 		dev_err(pvtm->dev, "failed to assert pvtm %d\n", ret);
194*4882a593Smuzhiyun 		return ret;
195*4882a593Smuzhiyun 	}
196*4882a593Smuzhiyun 
197*4882a593Smuzhiyun 	udelay(2);
198*4882a593Smuzhiyun 
199*4882a593Smuzhiyun 	ret = reset_control_deassert(pvtm->rst);
200*4882a593Smuzhiyun 	if (ret) {
201*4882a593Smuzhiyun 		dev_err(pvtm->dev, "failed to deassert pvtm %d\n", ret);
202*4882a593Smuzhiyun 		return ret;
203*4882a593Smuzhiyun 	}
204*4882a593Smuzhiyun 
205*4882a593Smuzhiyun 	return 0;
206*4882a593Smuzhiyun }
207*4882a593Smuzhiyun 
rockchip_get_pvtm_value(unsigned int id,unsigned int ring_sel,unsigned int time_us)208*4882a593Smuzhiyun u32 rockchip_get_pvtm_value(unsigned int id, unsigned int ring_sel,
209*4882a593Smuzhiyun 			    unsigned int time_us)
210*4882a593Smuzhiyun {
211*4882a593Smuzhiyun 	struct rockchip_pvtm *p, *pvtm = NULL;
212*4882a593Smuzhiyun 
213*4882a593Smuzhiyun 	if (list_empty(&pvtm_list)) {
214*4882a593Smuzhiyun 		pr_err("pvtm list NULL\n");
215*4882a593Smuzhiyun 		return -EINVAL;
216*4882a593Smuzhiyun 	}
217*4882a593Smuzhiyun 
218*4882a593Smuzhiyun 	list_for_each_entry(p, &pvtm_list, node) {
219*4882a593Smuzhiyun 		if (p->info->id == id) {
220*4882a593Smuzhiyun 			pvtm = p;
221*4882a593Smuzhiyun 			break;
222*4882a593Smuzhiyun 		}
223*4882a593Smuzhiyun 	}
224*4882a593Smuzhiyun 
225*4882a593Smuzhiyun 	if (!pvtm) {
226*4882a593Smuzhiyun 		pr_err("invalid pvtm id %d\n", id);
227*4882a593Smuzhiyun 		return -EINVAL;
228*4882a593Smuzhiyun 	}
229*4882a593Smuzhiyun 
230*4882a593Smuzhiyun 	if (ring_sel >= pvtm->info->num_rings) {
231*4882a593Smuzhiyun 		pr_err("invalid pvtm ring %d\n", ring_sel);
232*4882a593Smuzhiyun 		return -EINVAL;
233*4882a593Smuzhiyun 	}
234*4882a593Smuzhiyun 
235*4882a593Smuzhiyun 	return pvtm->ops->get_value(pvtm, ring_sel, time_us);
236*4882a593Smuzhiyun }
237*4882a593Smuzhiyun EXPORT_SYMBOL(rockchip_get_pvtm_value);
238*4882a593Smuzhiyun 
rockchip_pvtm_delay(unsigned int delay)239*4882a593Smuzhiyun static void rockchip_pvtm_delay(unsigned int delay)
240*4882a593Smuzhiyun {
241*4882a593Smuzhiyun 	unsigned int ms = delay / 1000;
242*4882a593Smuzhiyun 	unsigned int us = delay % 1000;
243*4882a593Smuzhiyun 
244*4882a593Smuzhiyun 	if (ms > 0) {
245*4882a593Smuzhiyun 		if (ms < 20)
246*4882a593Smuzhiyun 			us += ms * 1000;
247*4882a593Smuzhiyun 		else
248*4882a593Smuzhiyun 			msleep(ms);
249*4882a593Smuzhiyun 	}
250*4882a593Smuzhiyun 
251*4882a593Smuzhiyun 	if (us >= 10)
252*4882a593Smuzhiyun 		usleep_range(us, us + 100);
253*4882a593Smuzhiyun 	else
254*4882a593Smuzhiyun 		udelay(us);
255*4882a593Smuzhiyun }
256*4882a593Smuzhiyun 
px30_pvtm_set_ring_sel(struct rockchip_pvtm * pvtm,unsigned int ring_sel)257*4882a593Smuzhiyun static void px30_pvtm_set_ring_sel(struct rockchip_pvtm *pvtm,
258*4882a593Smuzhiyun 				   unsigned int ring_sel)
259*4882a593Smuzhiyun {
260*4882a593Smuzhiyun 	unsigned int id = pvtm->info->id;
261*4882a593Smuzhiyun 
262*4882a593Smuzhiyun 	regmap_write(pvtm->grf, pvtm->con,
263*4882a593Smuzhiyun 		     wr_mask_bit(ring_sel, (id * 0x4 + 0x2), 0x3));
264*4882a593Smuzhiyun }
265*4882a593Smuzhiyun 
rk1808_pvtm_set_ring_sel(struct rockchip_pvtm * pvtm,unsigned int ring_sel)266*4882a593Smuzhiyun static void rk1808_pvtm_set_ring_sel(struct rockchip_pvtm *pvtm,
267*4882a593Smuzhiyun 				     unsigned int ring_sel)
268*4882a593Smuzhiyun {
269*4882a593Smuzhiyun 	regmap_write(pvtm->grf, pvtm->con,
270*4882a593Smuzhiyun 		     wr_mask_bit(ring_sel, 0x2, 0x7));
271*4882a593Smuzhiyun }
272*4882a593Smuzhiyun 
rk3399_pvtm_set_ring_sel(struct rockchip_pvtm * pvtm,unsigned int ring_sel)273*4882a593Smuzhiyun static void rk3399_pvtm_set_ring_sel(struct rockchip_pvtm *pvtm,
274*4882a593Smuzhiyun 				     unsigned int ring_sel)
275*4882a593Smuzhiyun {
276*4882a593Smuzhiyun 	unsigned int id = pvtm->info->id;
277*4882a593Smuzhiyun 
278*4882a593Smuzhiyun 	if (id == 1) {
279*4882a593Smuzhiyun 		regmap_write(pvtm->grf, pvtm->con + 0x14,
280*4882a593Smuzhiyun 			     wr_mask_bit(ring_sel >> 0x3, 0, 0x1));
281*4882a593Smuzhiyun 		ring_sel &= 0x3;
282*4882a593Smuzhiyun 	}
283*4882a593Smuzhiyun 	if (id != 4)
284*4882a593Smuzhiyun 		regmap_write(pvtm->grf, pvtm->con,
285*4882a593Smuzhiyun 			     wr_mask_bit(ring_sel, (id * 0x4 + 0x2), 0x3));
286*4882a593Smuzhiyun }
287*4882a593Smuzhiyun 
rockchip_pvtm_get_value(struct rockchip_pvtm * pvtm,unsigned int ring_sel,unsigned int time_us)288*4882a593Smuzhiyun static u32 rockchip_pvtm_get_value(struct rockchip_pvtm *pvtm,
289*4882a593Smuzhiyun 				   unsigned int ring_sel,
290*4882a593Smuzhiyun 				   unsigned int time_us)
291*4882a593Smuzhiyun {
292*4882a593Smuzhiyun 	const struct rockchip_pvtm_info *info = pvtm->info;
293*4882a593Smuzhiyun 	unsigned int clk_cnt, check_cnt = 100;
294*4882a593Smuzhiyun 	u32 sta, val = 0;
295*4882a593Smuzhiyun 	int ret;
296*4882a593Smuzhiyun 
297*4882a593Smuzhiyun 	ret = clk_bulk_prepare_enable(pvtm->num_clks, pvtm->clks);
298*4882a593Smuzhiyun 	if (ret < 0) {
299*4882a593Smuzhiyun 		dev_err(pvtm->dev, "failed to prepare/enable pvtm clks\n");
300*4882a593Smuzhiyun 		return 0;
301*4882a593Smuzhiyun 	}
302*4882a593Smuzhiyun 	ret = rockchip_pvtm_reset(pvtm);
303*4882a593Smuzhiyun 	if (ret) {
304*4882a593Smuzhiyun 		dev_err(pvtm->dev, "failed to reset pvtm\n");
305*4882a593Smuzhiyun 		goto disable_clks;
306*4882a593Smuzhiyun 	}
307*4882a593Smuzhiyun 
308*4882a593Smuzhiyun 	/* if last status is enabled, stop calculating cycles first*/
309*4882a593Smuzhiyun 	regmap_read(pvtm->grf, pvtm->con, &sta);
310*4882a593Smuzhiyun 	if (sta & BIT(info->bit_en))
311*4882a593Smuzhiyun 		regmap_write(pvtm->grf, pvtm->con,
312*4882a593Smuzhiyun 			     wr_mask_bit(0, info->bit_start, 0x1));
313*4882a593Smuzhiyun 
314*4882a593Smuzhiyun 	regmap_write(pvtm->grf, pvtm->con,
315*4882a593Smuzhiyun 		     wr_mask_bit(0x1, info->bit_en, 0x1));
316*4882a593Smuzhiyun 
317*4882a593Smuzhiyun 	if (pvtm->ops->set_ring_sel)
318*4882a593Smuzhiyun 		pvtm->ops->set_ring_sel(pvtm, ring_sel);
319*4882a593Smuzhiyun 
320*4882a593Smuzhiyun 	/* clk = 24 Mhz, T = 1 / 24 us */
321*4882a593Smuzhiyun 	clk_cnt = time_us * 24;
322*4882a593Smuzhiyun 	regmap_write(pvtm->grf, pvtm->con + info->reg_cal, clk_cnt);
323*4882a593Smuzhiyun 
324*4882a593Smuzhiyun 	regmap_write(pvtm->grf, pvtm->con,
325*4882a593Smuzhiyun 		     wr_mask_bit(0x1, info->bit_start, 0x1));
326*4882a593Smuzhiyun 
327*4882a593Smuzhiyun 	rockchip_pvtm_delay(time_us);
328*4882a593Smuzhiyun 
329*4882a593Smuzhiyun 	while (check_cnt) {
330*4882a593Smuzhiyun 		regmap_read(pvtm->grf, pvtm->sta, &sta);
331*4882a593Smuzhiyun 		if (sta & BIT(info->bit_freq_done))
332*4882a593Smuzhiyun 			break;
333*4882a593Smuzhiyun 		udelay(4);
334*4882a593Smuzhiyun 		check_cnt--;
335*4882a593Smuzhiyun 	}
336*4882a593Smuzhiyun 
337*4882a593Smuzhiyun 	if (check_cnt) {
338*4882a593Smuzhiyun 		regmap_read(pvtm->grf, pvtm->sta + info->reg_freq, &val);
339*4882a593Smuzhiyun 	} else {
340*4882a593Smuzhiyun 		dev_err(pvtm->dev, "wait pvtm_done timeout!\n");
341*4882a593Smuzhiyun 		val = 0;
342*4882a593Smuzhiyun 	}
343*4882a593Smuzhiyun 
344*4882a593Smuzhiyun 	regmap_write(pvtm->grf, pvtm->con,
345*4882a593Smuzhiyun 		     wr_mask_bit(0, info->bit_start, 0x1));
346*4882a593Smuzhiyun 
347*4882a593Smuzhiyun 	regmap_write(pvtm->grf, pvtm->con,
348*4882a593Smuzhiyun 		     wr_mask_bit(0, info->bit_en, 0x1));
349*4882a593Smuzhiyun 
350*4882a593Smuzhiyun disable_clks:
351*4882a593Smuzhiyun 	clk_bulk_disable_unprepare(pvtm->num_clks, pvtm->clks);
352*4882a593Smuzhiyun 
353*4882a593Smuzhiyun 	return val;
354*4882a593Smuzhiyun }
355*4882a593Smuzhiyun 
rv1106_core_pvtm_set_ring_sel(struct rockchip_pvtm * pvtm,unsigned int ring_sel)356*4882a593Smuzhiyun static void rv1106_core_pvtm_set_ring_sel(struct rockchip_pvtm *pvtm,
357*4882a593Smuzhiyun 					  unsigned int ring_sel)
358*4882a593Smuzhiyun {
359*4882a593Smuzhiyun 	writel_relaxed(wr_mask_bit(ring_sel + 4, 0x2, 0x7), pvtm->base + pvtm->con);
360*4882a593Smuzhiyun }
361*4882a593Smuzhiyun 
rv1126_pvtm_set_ring_sel(struct rockchip_pvtm * pvtm,unsigned int ring_sel)362*4882a593Smuzhiyun static void rv1126_pvtm_set_ring_sel(struct rockchip_pvtm *pvtm,
363*4882a593Smuzhiyun 				     unsigned int ring_sel)
364*4882a593Smuzhiyun {
365*4882a593Smuzhiyun 	writel_relaxed(wr_mask_bit(ring_sel, 0x2, 0x7), pvtm->base + pvtm->con);
366*4882a593Smuzhiyun }
367*4882a593Smuzhiyun 
rv1126_pvtm_get_value(struct rockchip_pvtm * pvtm,unsigned int ring_sel,unsigned int time_us)368*4882a593Smuzhiyun static u32 rv1126_pvtm_get_value(struct rockchip_pvtm *pvtm,
369*4882a593Smuzhiyun 				 unsigned int ring_sel,
370*4882a593Smuzhiyun 				 unsigned int time_us)
371*4882a593Smuzhiyun {
372*4882a593Smuzhiyun 	const struct rockchip_pvtm_info *info = pvtm->info;
373*4882a593Smuzhiyun 	unsigned int clk_cnt, check_cnt = 100;
374*4882a593Smuzhiyun 	u32 sta, val = 0;
375*4882a593Smuzhiyun 	int ret;
376*4882a593Smuzhiyun 
377*4882a593Smuzhiyun 	ret = clk_bulk_prepare_enable(pvtm->num_clks, pvtm->clks);
378*4882a593Smuzhiyun 	if (ret < 0) {
379*4882a593Smuzhiyun 		dev_err(pvtm->dev, "failed to prepare/enable pvtm clks\n");
380*4882a593Smuzhiyun 		return 0;
381*4882a593Smuzhiyun 	}
382*4882a593Smuzhiyun 	ret = rockchip_pvtm_reset(pvtm);
383*4882a593Smuzhiyun 	if (ret) {
384*4882a593Smuzhiyun 		dev_err(pvtm->dev, "failed to reset pvtm\n");
385*4882a593Smuzhiyun 		goto disable_clks;
386*4882a593Smuzhiyun 	}
387*4882a593Smuzhiyun 
388*4882a593Smuzhiyun 	/* if last status is enabled, stop calculating cycles first*/
389*4882a593Smuzhiyun 	sta = readl_relaxed(pvtm->base + pvtm->con);
390*4882a593Smuzhiyun 	if (sta & BIT(info->bit_en))
391*4882a593Smuzhiyun 		writel_relaxed(wr_mask_bit(0, info->bit_start, 0x1),
392*4882a593Smuzhiyun 			       pvtm->base + pvtm->con);
393*4882a593Smuzhiyun 
394*4882a593Smuzhiyun 	writel_relaxed(wr_mask_bit(0x1, info->bit_en, 0x1),
395*4882a593Smuzhiyun 		       pvtm->base + pvtm->con);
396*4882a593Smuzhiyun 
397*4882a593Smuzhiyun 	if (pvtm->ops->set_ring_sel)
398*4882a593Smuzhiyun 		pvtm->ops->set_ring_sel(pvtm, ring_sel);
399*4882a593Smuzhiyun 
400*4882a593Smuzhiyun 	/* clk = 24 Mhz, T = 1 / 24 us */
401*4882a593Smuzhiyun 	clk_cnt = time_us * 24;
402*4882a593Smuzhiyun 	writel_relaxed(clk_cnt, pvtm->base + pvtm->con + info->reg_cal);
403*4882a593Smuzhiyun 
404*4882a593Smuzhiyun 	writel_relaxed(wr_mask_bit(0x1, info->bit_start, 0x1),
405*4882a593Smuzhiyun 		       pvtm->base + pvtm->con);
406*4882a593Smuzhiyun 
407*4882a593Smuzhiyun 	rockchip_pvtm_delay(time_us);
408*4882a593Smuzhiyun 
409*4882a593Smuzhiyun 	while (check_cnt) {
410*4882a593Smuzhiyun 		sta = readl_relaxed(pvtm->base + pvtm->sta);
411*4882a593Smuzhiyun 		if (sta & BIT(info->bit_freq_done))
412*4882a593Smuzhiyun 			break;
413*4882a593Smuzhiyun 		udelay(4);
414*4882a593Smuzhiyun 		check_cnt--;
415*4882a593Smuzhiyun 	}
416*4882a593Smuzhiyun 
417*4882a593Smuzhiyun 	if (check_cnt) {
418*4882a593Smuzhiyun 		val = readl_relaxed(pvtm->base + pvtm->sta + info->reg_freq);
419*4882a593Smuzhiyun 	} else {
420*4882a593Smuzhiyun 		dev_err(pvtm->dev, "wait pvtm_done timeout!\n");
421*4882a593Smuzhiyun 		val = 0;
422*4882a593Smuzhiyun 	}
423*4882a593Smuzhiyun 
424*4882a593Smuzhiyun 	writel_relaxed(wr_mask_bit(0, info->bit_start, 0x1),
425*4882a593Smuzhiyun 		       pvtm->base + pvtm->con);
426*4882a593Smuzhiyun 	writel_relaxed(wr_mask_bit(0, info->bit_en, 0x1),
427*4882a593Smuzhiyun 		       pvtm->base + pvtm->con);
428*4882a593Smuzhiyun 
429*4882a593Smuzhiyun disable_clks:
430*4882a593Smuzhiyun 	clk_bulk_disable_unprepare(pvtm->num_clks, pvtm->clks);
431*4882a593Smuzhiyun 
432*4882a593Smuzhiyun 	return val;
433*4882a593Smuzhiyun }
434*4882a593Smuzhiyun 
435*4882a593Smuzhiyun static const struct rockchip_pvtm_info px30_pvtm_infos[] = {
436*4882a593Smuzhiyun 	PVTM(0, "core", 3, 0, 1, 0x4, 0, 0x4),
437*4882a593Smuzhiyun };
438*4882a593Smuzhiyun 
439*4882a593Smuzhiyun static const struct rockchip_pvtm_data px30_pvtm = {
440*4882a593Smuzhiyun 	.con = 0x80,
441*4882a593Smuzhiyun 	.sta = 0x88,
442*4882a593Smuzhiyun 	.num_pvtms = ARRAY_SIZE(px30_pvtm_infos),
443*4882a593Smuzhiyun 	.infos = px30_pvtm_infos,
444*4882a593Smuzhiyun 	.ops = {
445*4882a593Smuzhiyun 		.get_value = rockchip_pvtm_get_value,
446*4882a593Smuzhiyun 		.set_ring_sel = px30_pvtm_set_ring_sel,
447*4882a593Smuzhiyun 	},
448*4882a593Smuzhiyun };
449*4882a593Smuzhiyun 
450*4882a593Smuzhiyun static const struct rockchip_pvtm_info px30_pmupvtm_infos[] = {
451*4882a593Smuzhiyun 	PVTM(1, "pmu", 1, 0, 1, 0x4, 0, 0x4),
452*4882a593Smuzhiyun };
453*4882a593Smuzhiyun 
454*4882a593Smuzhiyun static const struct rockchip_pvtm_data px30_pmupvtm = {
455*4882a593Smuzhiyun 	.con = 0x180,
456*4882a593Smuzhiyun 	.sta = 0x190,
457*4882a593Smuzhiyun 	.num_pvtms = ARRAY_SIZE(px30_pmupvtm_infos),
458*4882a593Smuzhiyun 	.infos = px30_pmupvtm_infos,
459*4882a593Smuzhiyun 	.ops =  {
460*4882a593Smuzhiyun 		.get_value = rockchip_pvtm_get_value,
461*4882a593Smuzhiyun 	},
462*4882a593Smuzhiyun };
463*4882a593Smuzhiyun 
464*4882a593Smuzhiyun static const struct rockchip_pvtm_info rk1808_pvtm_infos[] = {
465*4882a593Smuzhiyun 	PVTM(0, "core", 5, 0, 1, 0x4, 0, 0x4),
466*4882a593Smuzhiyun };
467*4882a593Smuzhiyun 
468*4882a593Smuzhiyun static const struct rockchip_pvtm_data rk1808_pvtm = {
469*4882a593Smuzhiyun 	.con = 0x80,
470*4882a593Smuzhiyun 	.sta = 0x88,
471*4882a593Smuzhiyun 	.num_pvtms = ARRAY_SIZE(rk1808_pvtm_infos),
472*4882a593Smuzhiyun 	.infos = rk1808_pvtm_infos,
473*4882a593Smuzhiyun 	.ops = {
474*4882a593Smuzhiyun 		.get_value = rockchip_pvtm_get_value,
475*4882a593Smuzhiyun 		.set_ring_sel = rk1808_pvtm_set_ring_sel,
476*4882a593Smuzhiyun 	},
477*4882a593Smuzhiyun };
478*4882a593Smuzhiyun 
479*4882a593Smuzhiyun static const struct rockchip_pvtm_info rk1808_pmupvtm_infos[] = {
480*4882a593Smuzhiyun 	PVTM(1, "pmu", 1, 0, 1, 0x4, 0, 0x4),
481*4882a593Smuzhiyun };
482*4882a593Smuzhiyun 
483*4882a593Smuzhiyun static const struct rockchip_pvtm_data rk1808_pmupvtm = {
484*4882a593Smuzhiyun 	.con = 0x180,
485*4882a593Smuzhiyun 	.sta = 0x190,
486*4882a593Smuzhiyun 	.num_pvtms = ARRAY_SIZE(rk1808_pmupvtm_infos),
487*4882a593Smuzhiyun 	.infos = rk1808_pmupvtm_infos,
488*4882a593Smuzhiyun 	.ops = {
489*4882a593Smuzhiyun 		.get_value = rockchip_pvtm_get_value,
490*4882a593Smuzhiyun 	},
491*4882a593Smuzhiyun };
492*4882a593Smuzhiyun 
493*4882a593Smuzhiyun static const struct rockchip_pvtm_info rk1808_npupvtm_infos[] = {
494*4882a593Smuzhiyun 	PVTM(2, "npu", 5, 0, 1, 0x4, 0, 0x4),
495*4882a593Smuzhiyun };
496*4882a593Smuzhiyun 
497*4882a593Smuzhiyun static const struct rockchip_pvtm_data rk1808_npupvtm = {
498*4882a593Smuzhiyun 	.con = 0x780,
499*4882a593Smuzhiyun 	.sta = 0x788,
500*4882a593Smuzhiyun 	.num_pvtms = ARRAY_SIZE(rk1808_npupvtm_infos),
501*4882a593Smuzhiyun 	.infos = rk1808_npupvtm_infos,
502*4882a593Smuzhiyun 	.ops = {
503*4882a593Smuzhiyun 		.get_value = rockchip_pvtm_get_value,
504*4882a593Smuzhiyun 		.set_ring_sel = rk1808_pvtm_set_ring_sel,
505*4882a593Smuzhiyun 	},
506*4882a593Smuzhiyun };
507*4882a593Smuzhiyun 
508*4882a593Smuzhiyun static const struct rockchip_pvtm_info rk3288_pvtm_infos[] = {
509*4882a593Smuzhiyun 	PVTM(0, "core", 1, 0, 1, 0x4, 1, 0x4),
510*4882a593Smuzhiyun 	PVTM(1, "gpu", 1, 8, 9, 0x8, 0, 0x8),
511*4882a593Smuzhiyun };
512*4882a593Smuzhiyun 
513*4882a593Smuzhiyun static const struct rockchip_pvtm_data rk3288_pvtm = {
514*4882a593Smuzhiyun 	.con = 0x368,
515*4882a593Smuzhiyun 	.sta = 0x374,
516*4882a593Smuzhiyun 	.num_pvtms = ARRAY_SIZE(rk3288_pvtm_infos),
517*4882a593Smuzhiyun 	.infos = rk3288_pvtm_infos,
518*4882a593Smuzhiyun 	.ops = {
519*4882a593Smuzhiyun 		.get_value = rockchip_pvtm_get_value,
520*4882a593Smuzhiyun 	},
521*4882a593Smuzhiyun };
522*4882a593Smuzhiyun 
523*4882a593Smuzhiyun static const struct rockchip_pvtm_data rk3308_pmupvtm = {
524*4882a593Smuzhiyun 	.con = 0x440,
525*4882a593Smuzhiyun 	.sta = 0x448,
526*4882a593Smuzhiyun 	.num_pvtms = ARRAY_SIZE(px30_pmupvtm_infos),
527*4882a593Smuzhiyun 	.infos = px30_pmupvtm_infos,
528*4882a593Smuzhiyun 	.ops = {
529*4882a593Smuzhiyun 		.get_value = rockchip_pvtm_get_value,
530*4882a593Smuzhiyun 	},
531*4882a593Smuzhiyun };
532*4882a593Smuzhiyun 
533*4882a593Smuzhiyun static const struct rockchip_pvtm_info rk3399_pvtm_infos[] = {
534*4882a593Smuzhiyun 	PVTM(0, "core_l", 4, 0, 1, 0x4, 0, 0x4),
535*4882a593Smuzhiyun 	PVTM(1, "core_b", 6, 4, 5, 0x8, 1, 0x8),
536*4882a593Smuzhiyun 	PVTM(2, "ddr", 4, 8, 9, 0xc, 3, 0x10),
537*4882a593Smuzhiyun 	PVTM(3, "gpu", 4, 12, 13, 0x10, 2, 0xc),
538*4882a593Smuzhiyun };
539*4882a593Smuzhiyun 
540*4882a593Smuzhiyun static const struct rockchip_pvtm_data rk3399_pvtm = {
541*4882a593Smuzhiyun 	.con = 0xe600,
542*4882a593Smuzhiyun 	.sta = 0xe620,
543*4882a593Smuzhiyun 	.num_pvtms = ARRAY_SIZE(rk3399_pvtm_infos),
544*4882a593Smuzhiyun 	.infos = rk3399_pvtm_infos,
545*4882a593Smuzhiyun 	.ops = {
546*4882a593Smuzhiyun 		.get_value = rockchip_pvtm_get_value,
547*4882a593Smuzhiyun 		.set_ring_sel = rk3399_pvtm_set_ring_sel,
548*4882a593Smuzhiyun 	},
549*4882a593Smuzhiyun };
550*4882a593Smuzhiyun 
551*4882a593Smuzhiyun static const struct rockchip_pvtm_info rk3399_pmupvtm_infos[] = {
552*4882a593Smuzhiyun 	PVTM(4, "pmu", 1, 0, 1, 0x4, 0, 0x4),
553*4882a593Smuzhiyun };
554*4882a593Smuzhiyun 
555*4882a593Smuzhiyun static const struct rockchip_pvtm_data rk3399_pmupvtm = {
556*4882a593Smuzhiyun 	.con = 0x240,
557*4882a593Smuzhiyun 	.sta = 0x248,
558*4882a593Smuzhiyun 	.num_pvtms = ARRAY_SIZE(rk3399_pmupvtm_infos),
559*4882a593Smuzhiyun 	.infos = rk3399_pmupvtm_infos,
560*4882a593Smuzhiyun 	.ops = {
561*4882a593Smuzhiyun 		.get_value = rockchip_pvtm_get_value,
562*4882a593Smuzhiyun 	},
563*4882a593Smuzhiyun };
564*4882a593Smuzhiyun 
565*4882a593Smuzhiyun static const struct rockchip_pvtm_info rk3568_corepvtm_infos[] = {
566*4882a593Smuzhiyun 	PVTM(0, "core", 7, 0, 1, 0x4, 0, 0x4),
567*4882a593Smuzhiyun };
568*4882a593Smuzhiyun 
569*4882a593Smuzhiyun static const struct rockchip_pvtm_data rk3568_corepvtm = {
570*4882a593Smuzhiyun 	.con = 0x4,
571*4882a593Smuzhiyun 	.sta = 0x80,
572*4882a593Smuzhiyun 	.num_pvtms = ARRAY_SIZE(rk3568_corepvtm_infos),
573*4882a593Smuzhiyun 	.infos = rk3568_corepvtm_infos,
574*4882a593Smuzhiyun 	.ops = {
575*4882a593Smuzhiyun 		.get_value = rv1126_pvtm_get_value,
576*4882a593Smuzhiyun 		.set_ring_sel = rv1126_pvtm_set_ring_sel,
577*4882a593Smuzhiyun 	},
578*4882a593Smuzhiyun };
579*4882a593Smuzhiyun 
580*4882a593Smuzhiyun static const struct rockchip_pvtm_info rk3568_gpupvtm_infos[] = {
581*4882a593Smuzhiyun 	PVTM(1, "gpu", 7, 0, 1, 0x4, 0, 0x4),
582*4882a593Smuzhiyun };
583*4882a593Smuzhiyun 
584*4882a593Smuzhiyun static const struct rockchip_pvtm_data rk3568_gpupvtm = {
585*4882a593Smuzhiyun 	.con = 0x4,
586*4882a593Smuzhiyun 	.sta = 0x80,
587*4882a593Smuzhiyun 	.num_pvtms = ARRAY_SIZE(rk3568_gpupvtm_infos),
588*4882a593Smuzhiyun 	.infos = rk3568_gpupvtm_infos,
589*4882a593Smuzhiyun 	.ops = {
590*4882a593Smuzhiyun 		.get_value = rv1126_pvtm_get_value,
591*4882a593Smuzhiyun 		.set_ring_sel = rv1126_pvtm_set_ring_sel,
592*4882a593Smuzhiyun 	},
593*4882a593Smuzhiyun };
594*4882a593Smuzhiyun 
595*4882a593Smuzhiyun static const struct rockchip_pvtm_info rk3568_npupvtm_infos[] = {
596*4882a593Smuzhiyun 	PVTM(2, "npu", 7, 0, 1, 0x4, 0, 0x4),
597*4882a593Smuzhiyun };
598*4882a593Smuzhiyun 
599*4882a593Smuzhiyun static const struct rockchip_pvtm_data rk3568_npupvtm = {
600*4882a593Smuzhiyun 	.con = 0x4,
601*4882a593Smuzhiyun 	.sta = 0x80,
602*4882a593Smuzhiyun 	.num_pvtms = ARRAY_SIZE(rk3568_npupvtm_infos),
603*4882a593Smuzhiyun 	.infos = rk3568_npupvtm_infos,
604*4882a593Smuzhiyun 	.ops = {
605*4882a593Smuzhiyun 		.get_value = rv1126_pvtm_get_value,
606*4882a593Smuzhiyun 		.set_ring_sel = rv1126_pvtm_set_ring_sel,
607*4882a593Smuzhiyun 	},
608*4882a593Smuzhiyun };
609*4882a593Smuzhiyun 
610*4882a593Smuzhiyun static const struct rockchip_pvtm_info rk3588_bigcore0_pvtm_infos[] = {
611*4882a593Smuzhiyun 	PVTM(0, "bigcore0", 7, 0, 1, 0x4, 0, 0x4),
612*4882a593Smuzhiyun };
613*4882a593Smuzhiyun 
614*4882a593Smuzhiyun static const struct rockchip_pvtm_data rk3588_bigcore0_pvtm = {
615*4882a593Smuzhiyun 	.con = 0x4,
616*4882a593Smuzhiyun 	.sta = 0x80,
617*4882a593Smuzhiyun 	.num_pvtms = ARRAY_SIZE(rk3588_bigcore0_pvtm_infos),
618*4882a593Smuzhiyun 	.infos = rk3588_bigcore0_pvtm_infos,
619*4882a593Smuzhiyun 	.ops = {
620*4882a593Smuzhiyun 		.get_value = rv1126_pvtm_get_value,
621*4882a593Smuzhiyun 		.set_ring_sel = rv1126_pvtm_set_ring_sel,
622*4882a593Smuzhiyun 	},
623*4882a593Smuzhiyun };
624*4882a593Smuzhiyun 
625*4882a593Smuzhiyun static const struct rockchip_pvtm_info rk3588_bigcore1_pvtm_infos[] = {
626*4882a593Smuzhiyun 	PVTM(1, "bigcore1", 7, 0, 1, 0x4, 0, 0x4),
627*4882a593Smuzhiyun };
628*4882a593Smuzhiyun 
629*4882a593Smuzhiyun static const struct rockchip_pvtm_data rk3588_bigcore1_pvtm = {
630*4882a593Smuzhiyun 	.con = 0x4,
631*4882a593Smuzhiyun 	.sta = 0x80,
632*4882a593Smuzhiyun 	.num_pvtms = ARRAY_SIZE(rk3588_bigcore1_pvtm_infos),
633*4882a593Smuzhiyun 	.infos = rk3588_bigcore1_pvtm_infos,
634*4882a593Smuzhiyun 	.ops = {
635*4882a593Smuzhiyun 		.get_value = rv1126_pvtm_get_value,
636*4882a593Smuzhiyun 		.set_ring_sel = rv1126_pvtm_set_ring_sel,
637*4882a593Smuzhiyun 	},
638*4882a593Smuzhiyun };
639*4882a593Smuzhiyun 
640*4882a593Smuzhiyun static const struct rockchip_pvtm_info rk3588_litcore_pvtm_infos[] = {
641*4882a593Smuzhiyun 	PVTM(2, "litcore", 7, 0, 1, 0x4, 0, 0x4),
642*4882a593Smuzhiyun };
643*4882a593Smuzhiyun 
644*4882a593Smuzhiyun static const struct rockchip_pvtm_data rk3588_litcore_pvtm = {
645*4882a593Smuzhiyun 	.con = 0x4,
646*4882a593Smuzhiyun 	.sta = 0x80,
647*4882a593Smuzhiyun 	.num_pvtms = ARRAY_SIZE(rk3588_litcore_pvtm_infos),
648*4882a593Smuzhiyun 	.infos = rk3588_litcore_pvtm_infos,
649*4882a593Smuzhiyun 	.ops = {
650*4882a593Smuzhiyun 		.get_value = rv1126_pvtm_get_value,
651*4882a593Smuzhiyun 		.set_ring_sel = rv1126_pvtm_set_ring_sel,
652*4882a593Smuzhiyun 	},
653*4882a593Smuzhiyun };
654*4882a593Smuzhiyun 
655*4882a593Smuzhiyun static const struct rockchip_pvtm_info rk3588_npu_pvtm_infos[] = {
656*4882a593Smuzhiyun 	PVTM(3, "npu", 2, 0, 1, 0x4, 0, 0x4),
657*4882a593Smuzhiyun };
658*4882a593Smuzhiyun 
659*4882a593Smuzhiyun static const struct rockchip_pvtm_data rk3588_npu_pvtm = {
660*4882a593Smuzhiyun 	.con = 0x4,
661*4882a593Smuzhiyun 	.sta = 0x80,
662*4882a593Smuzhiyun 	.num_pvtms = ARRAY_SIZE(rk3588_npu_pvtm_infos),
663*4882a593Smuzhiyun 	.infos = rk3588_npu_pvtm_infos,
664*4882a593Smuzhiyun 	.ops = {
665*4882a593Smuzhiyun 		.get_value = rv1126_pvtm_get_value,
666*4882a593Smuzhiyun 		.set_ring_sel = rv1126_pvtm_set_ring_sel,
667*4882a593Smuzhiyun 	},
668*4882a593Smuzhiyun };
669*4882a593Smuzhiyun 
670*4882a593Smuzhiyun static const struct rockchip_pvtm_info rk3588_gpu_pvtm_infos[] = {
671*4882a593Smuzhiyun 	PVTM(4, "gpu", 2, 0, 1, 0x4, 0, 0x4),
672*4882a593Smuzhiyun };
673*4882a593Smuzhiyun 
674*4882a593Smuzhiyun static const struct rockchip_pvtm_data rk3588_gpu_pvtm = {
675*4882a593Smuzhiyun 	.con = 0x4,
676*4882a593Smuzhiyun 	.sta = 0x80,
677*4882a593Smuzhiyun 	.num_pvtms = ARRAY_SIZE(rk3588_gpu_pvtm_infos),
678*4882a593Smuzhiyun 	.infos = rk3588_gpu_pvtm_infos,
679*4882a593Smuzhiyun 	.ops = {
680*4882a593Smuzhiyun 		.get_value = rv1126_pvtm_get_value,
681*4882a593Smuzhiyun 		.set_ring_sel = rv1126_pvtm_set_ring_sel,
682*4882a593Smuzhiyun 	},
683*4882a593Smuzhiyun };
684*4882a593Smuzhiyun 
685*4882a593Smuzhiyun static const struct rockchip_pvtm_info rk3588_pmu_pvtm_infos[] = {
686*4882a593Smuzhiyun 	PVTM(5, "pmu", 1, 0, 1, 0x4, 0, 0x4),
687*4882a593Smuzhiyun };
688*4882a593Smuzhiyun 
689*4882a593Smuzhiyun static const struct rockchip_pvtm_data rk3588_pmu_pvtm = {
690*4882a593Smuzhiyun 	.con = 0x4,
691*4882a593Smuzhiyun 	.sta = 0x80,
692*4882a593Smuzhiyun 	.num_pvtms = ARRAY_SIZE(rk3588_pmu_pvtm_infos),
693*4882a593Smuzhiyun 	.infos = rk3588_pmu_pvtm_infos,
694*4882a593Smuzhiyun 	.ops = {
695*4882a593Smuzhiyun 		.get_value = rv1126_pvtm_get_value,
696*4882a593Smuzhiyun 	},
697*4882a593Smuzhiyun };
698*4882a593Smuzhiyun 
699*4882a593Smuzhiyun static const struct rockchip_pvtm_info rv1106_corepvtm_infos[] = {
700*4882a593Smuzhiyun 	PVTM(0, "core", 2, 0, 1, 0x4, 0, 0x4),
701*4882a593Smuzhiyun };
702*4882a593Smuzhiyun 
703*4882a593Smuzhiyun static const struct rockchip_pvtm_data rv1106_corepvtm = {
704*4882a593Smuzhiyun 	.con = 0x4,
705*4882a593Smuzhiyun 	.sta = 0x80,
706*4882a593Smuzhiyun 	.num_pvtms = ARRAY_SIZE(rv1106_corepvtm_infos),
707*4882a593Smuzhiyun 	.infos = rv1106_corepvtm_infos,
708*4882a593Smuzhiyun 	.ops = {
709*4882a593Smuzhiyun 		.get_value = rv1126_pvtm_get_value,
710*4882a593Smuzhiyun 		.set_ring_sel = rv1106_core_pvtm_set_ring_sel,
711*4882a593Smuzhiyun 	},
712*4882a593Smuzhiyun };
713*4882a593Smuzhiyun 
714*4882a593Smuzhiyun static const struct rockchip_pvtm_info rv1106_pmupvtm_infos[] = {
715*4882a593Smuzhiyun 	PVTM(1, "pmu", 1, 0, 1, 0x4, 0, 0x4),
716*4882a593Smuzhiyun };
717*4882a593Smuzhiyun 
718*4882a593Smuzhiyun static const struct rockchip_pvtm_data rv1106_pmupvtm = {
719*4882a593Smuzhiyun 	.con = 0x4,
720*4882a593Smuzhiyun 	.sta = 0x80,
721*4882a593Smuzhiyun 	.num_pvtms = ARRAY_SIZE(rv1106_pmupvtm_infos),
722*4882a593Smuzhiyun 	.infos = rv1106_pmupvtm_infos,
723*4882a593Smuzhiyun 	.ops = {
724*4882a593Smuzhiyun 		.get_value = rv1126_pvtm_get_value,
725*4882a593Smuzhiyun 	},
726*4882a593Smuzhiyun };
727*4882a593Smuzhiyun 
728*4882a593Smuzhiyun static const struct rockchip_pvtm_info rv1126_cpupvtm_infos[] = {
729*4882a593Smuzhiyun 	PVTM(0, "cpu", 7, 0, 1, 0x4, 0, 0x4),
730*4882a593Smuzhiyun };
731*4882a593Smuzhiyun 
732*4882a593Smuzhiyun static const struct rockchip_pvtm_data rv1126_cpupvtm = {
733*4882a593Smuzhiyun 	.con = 0x4,
734*4882a593Smuzhiyun 	.sta = 0x80,
735*4882a593Smuzhiyun 	.num_pvtms = ARRAY_SIZE(rv1126_cpupvtm_infos),
736*4882a593Smuzhiyun 	.infos = rv1126_cpupvtm_infos,
737*4882a593Smuzhiyun 	.ops = {
738*4882a593Smuzhiyun 		.get_value = rv1126_pvtm_get_value,
739*4882a593Smuzhiyun 		.set_ring_sel = rv1126_pvtm_set_ring_sel,
740*4882a593Smuzhiyun 	},
741*4882a593Smuzhiyun };
742*4882a593Smuzhiyun 
743*4882a593Smuzhiyun static const struct rockchip_pvtm_info rv1126_npupvtm_infos[] = {
744*4882a593Smuzhiyun 	PVTM(1, "npu", 7, 0, 1, 0x4, 0, 0x4),
745*4882a593Smuzhiyun };
746*4882a593Smuzhiyun 
747*4882a593Smuzhiyun static const struct rockchip_pvtm_data rv1126_npupvtm = {
748*4882a593Smuzhiyun 	.con = 0x4,
749*4882a593Smuzhiyun 	.sta = 0x80,
750*4882a593Smuzhiyun 	.num_pvtms = ARRAY_SIZE(rv1126_npupvtm_infos),
751*4882a593Smuzhiyun 	.infos = rv1126_npupvtm_infos,
752*4882a593Smuzhiyun 	.ops = {
753*4882a593Smuzhiyun 		.get_value = rv1126_pvtm_get_value,
754*4882a593Smuzhiyun 		.set_ring_sel = rv1126_pvtm_set_ring_sel,
755*4882a593Smuzhiyun 	},
756*4882a593Smuzhiyun };
757*4882a593Smuzhiyun 
758*4882a593Smuzhiyun static const struct rockchip_pvtm_info rv1126_pmupvtm_infos[] = {
759*4882a593Smuzhiyun 	PVTM(2, "pmu", 1, 0, 1, 0x4, 0, 0x4),
760*4882a593Smuzhiyun };
761*4882a593Smuzhiyun 
762*4882a593Smuzhiyun static const struct rockchip_pvtm_data rv1126_pmupvtm = {
763*4882a593Smuzhiyun 	.con = 0x4,
764*4882a593Smuzhiyun 	.sta = 0x80,
765*4882a593Smuzhiyun 	.num_pvtms = ARRAY_SIZE(rv1126_pmupvtm_infos),
766*4882a593Smuzhiyun 	.infos = rv1126_pmupvtm_infos,
767*4882a593Smuzhiyun 	.ops = {
768*4882a593Smuzhiyun 		.get_value = rv1126_pvtm_get_value,
769*4882a593Smuzhiyun 	},
770*4882a593Smuzhiyun };
771*4882a593Smuzhiyun 
772*4882a593Smuzhiyun static const struct of_device_id rockchip_pvtm_match[] = {
773*4882a593Smuzhiyun #ifdef CONFIG_CPU_PX30
774*4882a593Smuzhiyun 	{
775*4882a593Smuzhiyun 		.compatible = "rockchip,px30-pvtm",
776*4882a593Smuzhiyun 		.data = (void *)&px30_pvtm,
777*4882a593Smuzhiyun 	},
778*4882a593Smuzhiyun 	{
779*4882a593Smuzhiyun 		.compatible = "rockchip,px30-pmu-pvtm",
780*4882a593Smuzhiyun 		.data = (void *)&px30_pmupvtm,
781*4882a593Smuzhiyun 	},
782*4882a593Smuzhiyun #endif
783*4882a593Smuzhiyun #ifdef CONFIG_CPU_RK1808
784*4882a593Smuzhiyun 	{
785*4882a593Smuzhiyun 		.compatible = "rockchip,rk1808-pvtm",
786*4882a593Smuzhiyun 		.data = (void *)&rk1808_pvtm,
787*4882a593Smuzhiyun 	},
788*4882a593Smuzhiyun 	{
789*4882a593Smuzhiyun 		.compatible = "rockchip,rk1808-pmu-pvtm",
790*4882a593Smuzhiyun 		.data = (void *)&rk1808_pmupvtm,
791*4882a593Smuzhiyun 	},
792*4882a593Smuzhiyun 	{
793*4882a593Smuzhiyun 		.compatible = "rockchip,rk1808-npu-pvtm",
794*4882a593Smuzhiyun 		.data = (void *)&rk1808_npupvtm,
795*4882a593Smuzhiyun 	},
796*4882a593Smuzhiyun #endif
797*4882a593Smuzhiyun #ifdef CONFIG_CPU_RK3288
798*4882a593Smuzhiyun 	{
799*4882a593Smuzhiyun 		.compatible = "rockchip,rk3288-pvtm",
800*4882a593Smuzhiyun 		.data = (void *)&rk3288_pvtm,
801*4882a593Smuzhiyun 	},
802*4882a593Smuzhiyun #endif
803*4882a593Smuzhiyun #ifdef CONFIG_CPU_RK3308
804*4882a593Smuzhiyun 	{
805*4882a593Smuzhiyun 		.compatible = "rockchip,rk3308-pvtm",
806*4882a593Smuzhiyun 		.data = (void *)&px30_pvtm,
807*4882a593Smuzhiyun 	},
808*4882a593Smuzhiyun 	{
809*4882a593Smuzhiyun 		.compatible = "rockchip,rk3308-pmu-pvtm",
810*4882a593Smuzhiyun 		.data = (void *)&rk3308_pmupvtm,
811*4882a593Smuzhiyun 	},
812*4882a593Smuzhiyun #endif
813*4882a593Smuzhiyun #ifdef CONFIG_CPU_RK3399
814*4882a593Smuzhiyun 	{
815*4882a593Smuzhiyun 		.compatible = "rockchip,rk3399-pvtm",
816*4882a593Smuzhiyun 		.data = (void *)&rk3399_pvtm,
817*4882a593Smuzhiyun 	},
818*4882a593Smuzhiyun 	{
819*4882a593Smuzhiyun 		.compatible = "rockchip,rk3399-pmu-pvtm",
820*4882a593Smuzhiyun 		.data = (void *)&rk3399_pmupvtm,
821*4882a593Smuzhiyun 	},
822*4882a593Smuzhiyun #endif
823*4882a593Smuzhiyun #ifdef CONFIG_CPU_RK3568
824*4882a593Smuzhiyun 	{
825*4882a593Smuzhiyun 		.compatible = "rockchip,rK3568-core-pvtm",
826*4882a593Smuzhiyun 		.data = (void *)&rk3568_corepvtm,
827*4882a593Smuzhiyun 	},
828*4882a593Smuzhiyun 	{
829*4882a593Smuzhiyun 		.compatible = "rockchip,rk3568-gpu-pvtm",
830*4882a593Smuzhiyun 		.data = (void *)&rk3568_gpupvtm,
831*4882a593Smuzhiyun 	},
832*4882a593Smuzhiyun 	{
833*4882a593Smuzhiyun 		.compatible = "rockchip,rk3568-npu-pvtm",
834*4882a593Smuzhiyun 		.data = (void *)&rk3568_npupvtm,
835*4882a593Smuzhiyun 	},
836*4882a593Smuzhiyun #endif
837*4882a593Smuzhiyun #ifdef CONFIG_CPU_RK3588
838*4882a593Smuzhiyun 	{
839*4882a593Smuzhiyun 		.compatible = "rockchip,rk3588-bigcore0-pvtm",
840*4882a593Smuzhiyun 		.data = (void *)&rk3588_bigcore0_pvtm,
841*4882a593Smuzhiyun 	},
842*4882a593Smuzhiyun 	{
843*4882a593Smuzhiyun 		.compatible = "rockchip,rk3588-bigcore1-pvtm",
844*4882a593Smuzhiyun 		.data = (void *)&rk3588_bigcore1_pvtm,
845*4882a593Smuzhiyun 	},
846*4882a593Smuzhiyun 	{
847*4882a593Smuzhiyun 		.compatible = "rockchip,rk3588-litcore-pvtm",
848*4882a593Smuzhiyun 		.data = (void *)&rk3588_litcore_pvtm,
849*4882a593Smuzhiyun 	},
850*4882a593Smuzhiyun 	{
851*4882a593Smuzhiyun 		.compatible = "rockchip,rk3588-gpu-pvtm",
852*4882a593Smuzhiyun 		.data = (void *)&rk3588_gpu_pvtm,
853*4882a593Smuzhiyun 	},
854*4882a593Smuzhiyun 	{
855*4882a593Smuzhiyun 		.compatible = "rockchip,rk3588-npu-pvtm",
856*4882a593Smuzhiyun 		.data = (void *)&rk3588_npu_pvtm,
857*4882a593Smuzhiyun 	},
858*4882a593Smuzhiyun 	{
859*4882a593Smuzhiyun 		.compatible = "rockchip,rk3588-pmu-pvtm",
860*4882a593Smuzhiyun 		.data = (void *)&rk3588_pmu_pvtm,
861*4882a593Smuzhiyun 	},
862*4882a593Smuzhiyun #endif
863*4882a593Smuzhiyun #ifdef CONFIG_CPU_RV1106
864*4882a593Smuzhiyun 	{
865*4882a593Smuzhiyun 		.compatible = "rockchip,rv1106-core-pvtm",
866*4882a593Smuzhiyun 		.data = (void *)&rv1106_corepvtm,
867*4882a593Smuzhiyun 	},
868*4882a593Smuzhiyun 	{
869*4882a593Smuzhiyun 		.compatible = "rockchip,rv1106-pmu-pvtm",
870*4882a593Smuzhiyun 		.data = (void *)&rv1106_pmupvtm,
871*4882a593Smuzhiyun 	},
872*4882a593Smuzhiyun #endif
873*4882a593Smuzhiyun #ifdef CONFIG_CPU_RV1126
874*4882a593Smuzhiyun 	{
875*4882a593Smuzhiyun 		.compatible = "rockchip,rv1126-cpu-pvtm",
876*4882a593Smuzhiyun 		.data = (void *)&rv1126_cpupvtm,
877*4882a593Smuzhiyun 	},
878*4882a593Smuzhiyun 	{
879*4882a593Smuzhiyun 		.compatible = "rockchip,rv1126-npu-pvtm",
880*4882a593Smuzhiyun 		.data = (void *)&rv1126_npupvtm,
881*4882a593Smuzhiyun 	},
882*4882a593Smuzhiyun 	{
883*4882a593Smuzhiyun 		.compatible = "rockchip,rv1126-pmu-pvtm",
884*4882a593Smuzhiyun 		.data = (void *)&rv1126_pmupvtm,
885*4882a593Smuzhiyun 	},
886*4882a593Smuzhiyun #endif
887*4882a593Smuzhiyun 	{ /* sentinel */ },
888*4882a593Smuzhiyun };
889*4882a593Smuzhiyun MODULE_DEVICE_TABLE(of, rockchip_pvtm_match);
890*4882a593Smuzhiyun 
rockchip_pvtm_get_index(const struct rockchip_pvtm_data * data,u32 ch,u32 * index)891*4882a593Smuzhiyun static int rockchip_pvtm_get_index(const struct rockchip_pvtm_data *data,
892*4882a593Smuzhiyun 				   u32 ch, u32 *index)
893*4882a593Smuzhiyun {
894*4882a593Smuzhiyun 	int i;
895*4882a593Smuzhiyun 
896*4882a593Smuzhiyun 	for (i = 0; i < data->num_pvtms; i++) {
897*4882a593Smuzhiyun 		if (ch == data->infos[i].id) {
898*4882a593Smuzhiyun 			*index = i;
899*4882a593Smuzhiyun 			return 0;
900*4882a593Smuzhiyun 		}
901*4882a593Smuzhiyun 	}
902*4882a593Smuzhiyun 
903*4882a593Smuzhiyun 	return -EINVAL;
904*4882a593Smuzhiyun }
905*4882a593Smuzhiyun 
906*4882a593Smuzhiyun static struct rockchip_pvtm *
rockchip_pvtm_init(struct device * dev,struct device_node * node,const struct rockchip_pvtm_data * data,struct regmap * grf,void __iomem * base)907*4882a593Smuzhiyun rockchip_pvtm_init(struct device *dev, struct device_node *node,
908*4882a593Smuzhiyun 		   const struct rockchip_pvtm_data *data,
909*4882a593Smuzhiyun 		   struct regmap *grf, void __iomem *base)
910*4882a593Smuzhiyun {
911*4882a593Smuzhiyun 	struct rockchip_pvtm *pvtm;
912*4882a593Smuzhiyun 	const char *tz_name;
913*4882a593Smuzhiyun 	u32 id, index;
914*4882a593Smuzhiyun 	int i;
915*4882a593Smuzhiyun 
916*4882a593Smuzhiyun 	if (of_property_read_u32(node, "reg", &id)) {
917*4882a593Smuzhiyun 		dev_err(dev, "%s: failed to retrieve pvtm id\n", node->name);
918*4882a593Smuzhiyun 		return NULL;
919*4882a593Smuzhiyun 	}
920*4882a593Smuzhiyun 	if (rockchip_pvtm_get_index(data, id, &index)) {
921*4882a593Smuzhiyun 		dev_err(dev, "%s: invalid pvtm id %d\n", node->name, id);
922*4882a593Smuzhiyun 		return NULL;
923*4882a593Smuzhiyun 	}
924*4882a593Smuzhiyun 
925*4882a593Smuzhiyun 	pvtm = devm_kzalloc(dev, sizeof(*pvtm), GFP_KERNEL);
926*4882a593Smuzhiyun 	if (!pvtm)
927*4882a593Smuzhiyun 		return NULL;
928*4882a593Smuzhiyun 
929*4882a593Smuzhiyun 	pvtm->dev = dev;
930*4882a593Smuzhiyun 	pvtm->grf = grf;
931*4882a593Smuzhiyun 	pvtm->base = base;
932*4882a593Smuzhiyun 	pvtm->con = data->con;
933*4882a593Smuzhiyun 	pvtm->sta = data->sta;
934*4882a593Smuzhiyun 	pvtm->ops = &data->ops;
935*4882a593Smuzhiyun 	pvtm->info = &data->infos[index];
936*4882a593Smuzhiyun 
937*4882a593Smuzhiyun 	if (!of_property_read_string(node, "thermal-zone", &tz_name)) {
938*4882a593Smuzhiyun 		pvtm->tz = thermal_zone_get_zone_by_name(tz_name);
939*4882a593Smuzhiyun 		if (IS_ERR(pvtm->tz)) {
940*4882a593Smuzhiyun 			dev_err(pvtm->dev, "failed to retrieve pvtm_tz\n");
941*4882a593Smuzhiyun 			pvtm->tz = NULL;
942*4882a593Smuzhiyun 		}
943*4882a593Smuzhiyun 	}
944*4882a593Smuzhiyun 
945*4882a593Smuzhiyun 	pvtm->num_clks = of_clk_get_parent_count(node);
946*4882a593Smuzhiyun 	if (pvtm->num_clks <= 0) {
947*4882a593Smuzhiyun 		dev_err(dev, "%s: does not have clocks\n", node->name);
948*4882a593Smuzhiyun 		goto clk_num_err;
949*4882a593Smuzhiyun 	}
950*4882a593Smuzhiyun 	pvtm->clks = devm_kcalloc(dev, pvtm->num_clks, sizeof(*pvtm->clks),
951*4882a593Smuzhiyun 				  GFP_KERNEL);
952*4882a593Smuzhiyun 	if (!pvtm->clks)
953*4882a593Smuzhiyun 		goto clk_num_err;
954*4882a593Smuzhiyun 	for (i = 0; i < pvtm->num_clks; i++) {
955*4882a593Smuzhiyun 		pvtm->clks[i].clk = of_clk_get(node, i);
956*4882a593Smuzhiyun 		if (IS_ERR(pvtm->clks[i].clk)) {
957*4882a593Smuzhiyun 			dev_err(dev, "%s: failed to get clk at index %d\n",
958*4882a593Smuzhiyun 				node->name, i);
959*4882a593Smuzhiyun 			goto clk_err;
960*4882a593Smuzhiyun 		}
961*4882a593Smuzhiyun 	}
962*4882a593Smuzhiyun 
963*4882a593Smuzhiyun 	pvtm->rst = devm_reset_control_array_get_optional_exclusive(dev);
964*4882a593Smuzhiyun 	if (IS_ERR(pvtm->rst))
965*4882a593Smuzhiyun 		dev_dbg(dev, "%s: failed to get reset\n", node->name);
966*4882a593Smuzhiyun 
967*4882a593Smuzhiyun 	rockchip_pvtm_add_debugfs(pvtm);
968*4882a593Smuzhiyun 
969*4882a593Smuzhiyun 	return pvtm;
970*4882a593Smuzhiyun 
971*4882a593Smuzhiyun clk_err:
972*4882a593Smuzhiyun 	while (--i >= 0)
973*4882a593Smuzhiyun 		clk_put(pvtm->clks[i].clk);
974*4882a593Smuzhiyun 	devm_kfree(dev, pvtm->clks);
975*4882a593Smuzhiyun clk_num_err:
976*4882a593Smuzhiyun 	devm_kfree(dev, pvtm);
977*4882a593Smuzhiyun 
978*4882a593Smuzhiyun 	return NULL;
979*4882a593Smuzhiyun }
980*4882a593Smuzhiyun 
rockchip_pvtm_probe(struct platform_device * pdev)981*4882a593Smuzhiyun static int rockchip_pvtm_probe(struct platform_device *pdev)
982*4882a593Smuzhiyun {
983*4882a593Smuzhiyun 	struct device *dev = &pdev->dev;
984*4882a593Smuzhiyun 	struct device_node *np = pdev->dev.of_node;
985*4882a593Smuzhiyun 	struct device_node *node;
986*4882a593Smuzhiyun 	const struct of_device_id *match;
987*4882a593Smuzhiyun 	struct rockchip_pvtm *pvtm;
988*4882a593Smuzhiyun 	struct regmap *grf = NULL;
989*4882a593Smuzhiyun 	void __iomem *base = NULL;
990*4882a593Smuzhiyun 
991*4882a593Smuzhiyun 	match = of_match_device(dev->driver->of_match_table, dev);
992*4882a593Smuzhiyun 	if (!match || !match->data) {
993*4882a593Smuzhiyun 		dev_err(dev, "missing pvtm data\n");
994*4882a593Smuzhiyun 		return -EINVAL;
995*4882a593Smuzhiyun 	}
996*4882a593Smuzhiyun 
997*4882a593Smuzhiyun 	if (dev->parent && dev->parent->of_node) {
998*4882a593Smuzhiyun 		grf = syscon_node_to_regmap(dev->parent->of_node);
999*4882a593Smuzhiyun 		if (IS_ERR(grf))
1000*4882a593Smuzhiyun 			return PTR_ERR(grf);
1001*4882a593Smuzhiyun 	} else {
1002*4882a593Smuzhiyun 		base = devm_platform_ioremap_resource(pdev, 0);
1003*4882a593Smuzhiyun 		if (IS_ERR(base))
1004*4882a593Smuzhiyun 			return PTR_ERR(base);
1005*4882a593Smuzhiyun 	}
1006*4882a593Smuzhiyun 
1007*4882a593Smuzhiyun 	for_each_available_child_of_node(np, node) {
1008*4882a593Smuzhiyun 		pvtm = rockchip_pvtm_init(dev, node, match->data, grf, base);
1009*4882a593Smuzhiyun 		if (!pvtm) {
1010*4882a593Smuzhiyun 			dev_err(dev, "failed to handle node %s\n",
1011*4882a593Smuzhiyun 				node->full_name);
1012*4882a593Smuzhiyun 			continue;
1013*4882a593Smuzhiyun 		}
1014*4882a593Smuzhiyun 		list_add(&pvtm->node, &pvtm_list);
1015*4882a593Smuzhiyun 		dev_info(dev, "%s probed\n", node->full_name);
1016*4882a593Smuzhiyun 	}
1017*4882a593Smuzhiyun 
1018*4882a593Smuzhiyun 	return 0;
1019*4882a593Smuzhiyun }
1020*4882a593Smuzhiyun 
1021*4882a593Smuzhiyun static struct platform_driver rockchip_pvtm_driver = {
1022*4882a593Smuzhiyun 	.probe = rockchip_pvtm_probe,
1023*4882a593Smuzhiyun 	.driver = {
1024*4882a593Smuzhiyun 		.name  = "rockchip-pvtm",
1025*4882a593Smuzhiyun 		.of_match_table = rockchip_pvtm_match,
1026*4882a593Smuzhiyun 	},
1027*4882a593Smuzhiyun };
1028*4882a593Smuzhiyun 
rockchip_pvtm_module_init(void)1029*4882a593Smuzhiyun static int __init rockchip_pvtm_module_init(void)
1030*4882a593Smuzhiyun {
1031*4882a593Smuzhiyun 	rockchip_pvtm_debugfs_init();
1032*4882a593Smuzhiyun 
1033*4882a593Smuzhiyun 	return platform_driver_register(&rockchip_pvtm_driver);
1034*4882a593Smuzhiyun }
1035*4882a593Smuzhiyun module_init(rockchip_pvtm_module_init);
1036*4882a593Smuzhiyun 
rockchip_pvtm_module_exit(void)1037*4882a593Smuzhiyun static void __exit rockchip_pvtm_module_exit(void)
1038*4882a593Smuzhiyun {
1039*4882a593Smuzhiyun 	rockchip_pvtm_debugfs_exit();
1040*4882a593Smuzhiyun 	platform_driver_unregister(&rockchip_pvtm_driver);
1041*4882a593Smuzhiyun }
1042*4882a593Smuzhiyun module_exit(rockchip_pvtm_module_exit);
1043*4882a593Smuzhiyun 
1044*4882a593Smuzhiyun MODULE_DESCRIPTION("Rockchip PVTM driver");
1045*4882a593Smuzhiyun MODULE_AUTHOR("Finley Xiao <finley.xiao@rock-chips.com>");
1046*4882a593Smuzhiyun MODULE_LICENSE("GPL v2");
1047