xref: /openbmc/linux/drivers/pmdomain/qcom/cpr.c (revision e2ad626f)
1*e2ad626fSUlf Hansson // SPDX-License-Identifier: GPL-2.0
2*e2ad626fSUlf Hansson /*
3*e2ad626fSUlf Hansson  * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
4*e2ad626fSUlf Hansson  * Copyright (c) 2019, Linaro Limited
5*e2ad626fSUlf Hansson  */
6*e2ad626fSUlf Hansson 
7*e2ad626fSUlf Hansson #include <linux/module.h>
8*e2ad626fSUlf Hansson #include <linux/err.h>
9*e2ad626fSUlf Hansson #include <linux/debugfs.h>
10*e2ad626fSUlf Hansson #include <linux/string.h>
11*e2ad626fSUlf Hansson #include <linux/kernel.h>
12*e2ad626fSUlf Hansson #include <linux/list.h>
13*e2ad626fSUlf Hansson #include <linux/init.h>
14*e2ad626fSUlf Hansson #include <linux/io.h>
15*e2ad626fSUlf Hansson #include <linux/bitops.h>
16*e2ad626fSUlf Hansson #include <linux/slab.h>
17*e2ad626fSUlf Hansson #include <linux/of.h>
18*e2ad626fSUlf Hansson #include <linux/platform_device.h>
19*e2ad626fSUlf Hansson #include <linux/pm_domain.h>
20*e2ad626fSUlf Hansson #include <linux/pm_opp.h>
21*e2ad626fSUlf Hansson #include <linux/interrupt.h>
22*e2ad626fSUlf Hansson #include <linux/regmap.h>
23*e2ad626fSUlf Hansson #include <linux/mfd/syscon.h>
24*e2ad626fSUlf Hansson #include <linux/regulator/consumer.h>
25*e2ad626fSUlf Hansson #include <linux/clk.h>
26*e2ad626fSUlf Hansson #include <linux/nvmem-consumer.h>
27*e2ad626fSUlf Hansson 
28*e2ad626fSUlf Hansson /* Register Offsets for RB-CPR and Bit Definitions */
29*e2ad626fSUlf Hansson 
30*e2ad626fSUlf Hansson /* RBCPR Version Register */
31*e2ad626fSUlf Hansson #define REG_RBCPR_VERSION		0
32*e2ad626fSUlf Hansson #define RBCPR_VER_2			0x02
33*e2ad626fSUlf Hansson #define FLAGS_IGNORE_1ST_IRQ_STATUS	BIT(0)
34*e2ad626fSUlf Hansson 
35*e2ad626fSUlf Hansson /* RBCPR Gate Count and Target Registers */
36*e2ad626fSUlf Hansson #define REG_RBCPR_GCNT_TARGET(n)	(0x60 + 4 * (n))
37*e2ad626fSUlf Hansson 
38*e2ad626fSUlf Hansson #define RBCPR_GCNT_TARGET_TARGET_SHIFT	0
39*e2ad626fSUlf Hansson #define RBCPR_GCNT_TARGET_TARGET_MASK	GENMASK(11, 0)
40*e2ad626fSUlf Hansson #define RBCPR_GCNT_TARGET_GCNT_SHIFT	12
41*e2ad626fSUlf Hansson #define RBCPR_GCNT_TARGET_GCNT_MASK	GENMASK(9, 0)
42*e2ad626fSUlf Hansson 
43*e2ad626fSUlf Hansson /* RBCPR Timer Control */
44*e2ad626fSUlf Hansson #define REG_RBCPR_TIMER_INTERVAL	0x44
45*e2ad626fSUlf Hansson #define REG_RBIF_TIMER_ADJUST		0x4c
46*e2ad626fSUlf Hansson 
47*e2ad626fSUlf Hansson #define RBIF_TIMER_ADJ_CONS_UP_MASK	GENMASK(3, 0)
48*e2ad626fSUlf Hansson #define RBIF_TIMER_ADJ_CONS_UP_SHIFT	0
49*e2ad626fSUlf Hansson #define RBIF_TIMER_ADJ_CONS_DOWN_MASK	GENMASK(3, 0)
50*e2ad626fSUlf Hansson #define RBIF_TIMER_ADJ_CONS_DOWN_SHIFT	4
51*e2ad626fSUlf Hansson #define RBIF_TIMER_ADJ_CLAMP_INT_MASK	GENMASK(7, 0)
52*e2ad626fSUlf Hansson #define RBIF_TIMER_ADJ_CLAMP_INT_SHIFT	8
53*e2ad626fSUlf Hansson 
54*e2ad626fSUlf Hansson /* RBCPR Config Register */
55*e2ad626fSUlf Hansson #define REG_RBIF_LIMIT			0x48
56*e2ad626fSUlf Hansson #define RBIF_LIMIT_CEILING_MASK		GENMASK(5, 0)
57*e2ad626fSUlf Hansson #define RBIF_LIMIT_CEILING_SHIFT	6
58*e2ad626fSUlf Hansson #define RBIF_LIMIT_FLOOR_BITS		6
59*e2ad626fSUlf Hansson #define RBIF_LIMIT_FLOOR_MASK		GENMASK(5, 0)
60*e2ad626fSUlf Hansson 
61*e2ad626fSUlf Hansson #define RBIF_LIMIT_CEILING_DEFAULT	RBIF_LIMIT_CEILING_MASK
62*e2ad626fSUlf Hansson #define RBIF_LIMIT_FLOOR_DEFAULT	0
63*e2ad626fSUlf Hansson 
64*e2ad626fSUlf Hansson #define REG_RBIF_SW_VLEVEL		0x94
65*e2ad626fSUlf Hansson #define RBIF_SW_VLEVEL_DEFAULT		0x20
66*e2ad626fSUlf Hansson 
67*e2ad626fSUlf Hansson #define REG_RBCPR_STEP_QUOT		0x80
68*e2ad626fSUlf Hansson #define RBCPR_STEP_QUOT_STEPQUOT_MASK	GENMASK(7, 0)
69*e2ad626fSUlf Hansson #define RBCPR_STEP_QUOT_IDLE_CLK_MASK	GENMASK(3, 0)
70*e2ad626fSUlf Hansson #define RBCPR_STEP_QUOT_IDLE_CLK_SHIFT	8
71*e2ad626fSUlf Hansson 
72*e2ad626fSUlf Hansson /* RBCPR Control Register */
73*e2ad626fSUlf Hansson #define REG_RBCPR_CTL			0x90
74*e2ad626fSUlf Hansson 
75*e2ad626fSUlf Hansson #define RBCPR_CTL_LOOP_EN			BIT(0)
76*e2ad626fSUlf Hansson #define RBCPR_CTL_TIMER_EN			BIT(3)
77*e2ad626fSUlf Hansson #define RBCPR_CTL_SW_AUTO_CONT_ACK_EN		BIT(5)
78*e2ad626fSUlf Hansson #define RBCPR_CTL_SW_AUTO_CONT_NACK_DN_EN	BIT(6)
79*e2ad626fSUlf Hansson #define RBCPR_CTL_COUNT_MODE			BIT(10)
80*e2ad626fSUlf Hansson #define RBCPR_CTL_UP_THRESHOLD_MASK	GENMASK(3, 0)
81*e2ad626fSUlf Hansson #define RBCPR_CTL_UP_THRESHOLD_SHIFT	24
82*e2ad626fSUlf Hansson #define RBCPR_CTL_DN_THRESHOLD_MASK	GENMASK(3, 0)
83*e2ad626fSUlf Hansson #define RBCPR_CTL_DN_THRESHOLD_SHIFT	28
84*e2ad626fSUlf Hansson 
85*e2ad626fSUlf Hansson /* RBCPR Ack/Nack Response */
86*e2ad626fSUlf Hansson #define REG_RBIF_CONT_ACK_CMD		0x98
87*e2ad626fSUlf Hansson #define REG_RBIF_CONT_NACK_CMD		0x9c
88*e2ad626fSUlf Hansson 
89*e2ad626fSUlf Hansson /* RBCPR Result status Register */
90*e2ad626fSUlf Hansson #define REG_RBCPR_RESULT_0		0xa0
91*e2ad626fSUlf Hansson 
92*e2ad626fSUlf Hansson #define RBCPR_RESULT0_BUSY_SHIFT	19
93*e2ad626fSUlf Hansson #define RBCPR_RESULT0_BUSY_MASK		BIT(RBCPR_RESULT0_BUSY_SHIFT)
94*e2ad626fSUlf Hansson #define RBCPR_RESULT0_ERROR_LT0_SHIFT	18
95*e2ad626fSUlf Hansson #define RBCPR_RESULT0_ERROR_SHIFT	6
96*e2ad626fSUlf Hansson #define RBCPR_RESULT0_ERROR_MASK	GENMASK(11, 0)
97*e2ad626fSUlf Hansson #define RBCPR_RESULT0_ERROR_STEPS_SHIFT	2
98*e2ad626fSUlf Hansson #define RBCPR_RESULT0_ERROR_STEPS_MASK	GENMASK(3, 0)
99*e2ad626fSUlf Hansson #define RBCPR_RESULT0_STEP_UP_SHIFT	1
100*e2ad626fSUlf Hansson 
101*e2ad626fSUlf Hansson /* RBCPR Interrupt Control Register */
102*e2ad626fSUlf Hansson #define REG_RBIF_IRQ_EN(n)		(0x100 + 4 * (n))
103*e2ad626fSUlf Hansson #define REG_RBIF_IRQ_CLEAR		0x110
104*e2ad626fSUlf Hansson #define REG_RBIF_IRQ_STATUS		0x114
105*e2ad626fSUlf Hansson 
106*e2ad626fSUlf Hansson #define CPR_INT_DONE		BIT(0)
107*e2ad626fSUlf Hansson #define CPR_INT_MIN		BIT(1)
108*e2ad626fSUlf Hansson #define CPR_INT_DOWN		BIT(2)
109*e2ad626fSUlf Hansson #define CPR_INT_MID		BIT(3)
110*e2ad626fSUlf Hansson #define CPR_INT_UP		BIT(4)
111*e2ad626fSUlf Hansson #define CPR_INT_MAX		BIT(5)
112*e2ad626fSUlf Hansson #define CPR_INT_CLAMP		BIT(6)
113*e2ad626fSUlf Hansson #define CPR_INT_ALL	(CPR_INT_DONE | CPR_INT_MIN | CPR_INT_DOWN | \
114*e2ad626fSUlf Hansson 			CPR_INT_MID | CPR_INT_UP | CPR_INT_MAX | CPR_INT_CLAMP)
115*e2ad626fSUlf Hansson #define CPR_INT_DEFAULT	(CPR_INT_UP | CPR_INT_DOWN)
116*e2ad626fSUlf Hansson 
117*e2ad626fSUlf Hansson #define CPR_NUM_RING_OSC	8
118*e2ad626fSUlf Hansson 
119*e2ad626fSUlf Hansson /* CPR eFuse parameters */
120*e2ad626fSUlf Hansson #define CPR_FUSE_TARGET_QUOT_BITS_MASK	GENMASK(11, 0)
121*e2ad626fSUlf Hansson 
122*e2ad626fSUlf Hansson #define CPR_FUSE_MIN_QUOT_DIFF		50
123*e2ad626fSUlf Hansson 
124*e2ad626fSUlf Hansson #define FUSE_REVISION_UNKNOWN		(-1)
125*e2ad626fSUlf Hansson 
126*e2ad626fSUlf Hansson enum voltage_change_dir {
127*e2ad626fSUlf Hansson 	NO_CHANGE,
128*e2ad626fSUlf Hansson 	DOWN,
129*e2ad626fSUlf Hansson 	UP,
130*e2ad626fSUlf Hansson };
131*e2ad626fSUlf Hansson 
132*e2ad626fSUlf Hansson struct cpr_fuse {
133*e2ad626fSUlf Hansson 	char *ring_osc;
134*e2ad626fSUlf Hansson 	char *init_voltage;
135*e2ad626fSUlf Hansson 	char *quotient;
136*e2ad626fSUlf Hansson 	char *quotient_offset;
137*e2ad626fSUlf Hansson };
138*e2ad626fSUlf Hansson 
139*e2ad626fSUlf Hansson struct fuse_corner_data {
140*e2ad626fSUlf Hansson 	int ref_uV;
141*e2ad626fSUlf Hansson 	int max_uV;
142*e2ad626fSUlf Hansson 	int min_uV;
143*e2ad626fSUlf Hansson 	int max_volt_scale;
144*e2ad626fSUlf Hansson 	int max_quot_scale;
145*e2ad626fSUlf Hansson 	/* fuse quot */
146*e2ad626fSUlf Hansson 	int quot_offset;
147*e2ad626fSUlf Hansson 	int quot_scale;
148*e2ad626fSUlf Hansson 	int quot_adjust;
149*e2ad626fSUlf Hansson 	/* fuse quot_offset */
150*e2ad626fSUlf Hansson 	int quot_offset_scale;
151*e2ad626fSUlf Hansson 	int quot_offset_adjust;
152*e2ad626fSUlf Hansson };
153*e2ad626fSUlf Hansson 
154*e2ad626fSUlf Hansson struct cpr_fuses {
155*e2ad626fSUlf Hansson 	int init_voltage_step;
156*e2ad626fSUlf Hansson 	int init_voltage_width;
157*e2ad626fSUlf Hansson 	struct fuse_corner_data *fuse_corner_data;
158*e2ad626fSUlf Hansson };
159*e2ad626fSUlf Hansson 
160*e2ad626fSUlf Hansson struct corner_data {
161*e2ad626fSUlf Hansson 	unsigned int fuse_corner;
162*e2ad626fSUlf Hansson 	unsigned long freq;
163*e2ad626fSUlf Hansson };
164*e2ad626fSUlf Hansson 
165*e2ad626fSUlf Hansson struct cpr_desc {
166*e2ad626fSUlf Hansson 	unsigned int num_fuse_corners;
167*e2ad626fSUlf Hansson 	int min_diff_quot;
168*e2ad626fSUlf Hansson 	int *step_quot;
169*e2ad626fSUlf Hansson 
170*e2ad626fSUlf Hansson 	unsigned int		timer_delay_us;
171*e2ad626fSUlf Hansson 	unsigned int		timer_cons_up;
172*e2ad626fSUlf Hansson 	unsigned int		timer_cons_down;
173*e2ad626fSUlf Hansson 	unsigned int		up_threshold;
174*e2ad626fSUlf Hansson 	unsigned int		down_threshold;
175*e2ad626fSUlf Hansson 	unsigned int		idle_clocks;
176*e2ad626fSUlf Hansson 	unsigned int		gcnt_us;
177*e2ad626fSUlf Hansson 	unsigned int		vdd_apc_step_up_limit;
178*e2ad626fSUlf Hansson 	unsigned int		vdd_apc_step_down_limit;
179*e2ad626fSUlf Hansson 	unsigned int		clamp_timer_interval;
180*e2ad626fSUlf Hansson 
181*e2ad626fSUlf Hansson 	struct cpr_fuses cpr_fuses;
182*e2ad626fSUlf Hansson 	bool reduce_to_fuse_uV;
183*e2ad626fSUlf Hansson 	bool reduce_to_corner_uV;
184*e2ad626fSUlf Hansson };
185*e2ad626fSUlf Hansson 
186*e2ad626fSUlf Hansson struct acc_desc {
187*e2ad626fSUlf Hansson 	unsigned int	enable_reg;
188*e2ad626fSUlf Hansson 	u32		enable_mask;
189*e2ad626fSUlf Hansson 
190*e2ad626fSUlf Hansson 	struct reg_sequence	*config;
191*e2ad626fSUlf Hansson 	struct reg_sequence	*settings;
192*e2ad626fSUlf Hansson 	int			num_regs_per_fuse;
193*e2ad626fSUlf Hansson };
194*e2ad626fSUlf Hansson 
195*e2ad626fSUlf Hansson struct cpr_acc_desc {
196*e2ad626fSUlf Hansson 	const struct cpr_desc *cpr_desc;
197*e2ad626fSUlf Hansson 	const struct acc_desc *acc_desc;
198*e2ad626fSUlf Hansson };
199*e2ad626fSUlf Hansson 
200*e2ad626fSUlf Hansson struct fuse_corner {
201*e2ad626fSUlf Hansson 	int min_uV;
202*e2ad626fSUlf Hansson 	int max_uV;
203*e2ad626fSUlf Hansson 	int uV;
204*e2ad626fSUlf Hansson 	int quot;
205*e2ad626fSUlf Hansson 	int step_quot;
206*e2ad626fSUlf Hansson 	const struct reg_sequence *accs;
207*e2ad626fSUlf Hansson 	int num_accs;
208*e2ad626fSUlf Hansson 	unsigned long max_freq;
209*e2ad626fSUlf Hansson 	u8 ring_osc_idx;
210*e2ad626fSUlf Hansson };
211*e2ad626fSUlf Hansson 
212*e2ad626fSUlf Hansson struct corner {
213*e2ad626fSUlf Hansson 	int min_uV;
214*e2ad626fSUlf Hansson 	int max_uV;
215*e2ad626fSUlf Hansson 	int uV;
216*e2ad626fSUlf Hansson 	int last_uV;
217*e2ad626fSUlf Hansson 	int quot_adjust;
218*e2ad626fSUlf Hansson 	u32 save_ctl;
219*e2ad626fSUlf Hansson 	u32 save_irq;
220*e2ad626fSUlf Hansson 	unsigned long freq;
221*e2ad626fSUlf Hansson 	struct fuse_corner *fuse_corner;
222*e2ad626fSUlf Hansson };
223*e2ad626fSUlf Hansson 
224*e2ad626fSUlf Hansson struct cpr_drv {
225*e2ad626fSUlf Hansson 	unsigned int		num_corners;
226*e2ad626fSUlf Hansson 	unsigned int		ref_clk_khz;
227*e2ad626fSUlf Hansson 
228*e2ad626fSUlf Hansson 	struct generic_pm_domain pd;
229*e2ad626fSUlf Hansson 	struct device		*dev;
230*e2ad626fSUlf Hansson 	struct device		*attached_cpu_dev;
231*e2ad626fSUlf Hansson 	struct mutex		lock;
232*e2ad626fSUlf Hansson 	void __iomem		*base;
233*e2ad626fSUlf Hansson 	struct corner		*corner;
234*e2ad626fSUlf Hansson 	struct regulator	*vdd_apc;
235*e2ad626fSUlf Hansson 	struct clk		*cpu_clk;
236*e2ad626fSUlf Hansson 	struct regmap		*tcsr;
237*e2ad626fSUlf Hansson 	bool			loop_disabled;
238*e2ad626fSUlf Hansson 	u32			gcnt;
239*e2ad626fSUlf Hansson 	unsigned long		flags;
240*e2ad626fSUlf Hansson 
241*e2ad626fSUlf Hansson 	struct fuse_corner	*fuse_corners;
242*e2ad626fSUlf Hansson 	struct corner		*corners;
243*e2ad626fSUlf Hansson 
244*e2ad626fSUlf Hansson 	const struct cpr_desc *desc;
245*e2ad626fSUlf Hansson 	const struct acc_desc *acc_desc;
246*e2ad626fSUlf Hansson 	const struct cpr_fuse *cpr_fuses;
247*e2ad626fSUlf Hansson 
248*e2ad626fSUlf Hansson 	struct dentry *debugfs;
249*e2ad626fSUlf Hansson };
250*e2ad626fSUlf Hansson 
cpr_is_allowed(struct cpr_drv * drv)251*e2ad626fSUlf Hansson static bool cpr_is_allowed(struct cpr_drv *drv)
252*e2ad626fSUlf Hansson {
253*e2ad626fSUlf Hansson 	return !drv->loop_disabled;
254*e2ad626fSUlf Hansson }
255*e2ad626fSUlf Hansson 
cpr_write(struct cpr_drv * drv,u32 offset,u32 value)256*e2ad626fSUlf Hansson static void cpr_write(struct cpr_drv *drv, u32 offset, u32 value)
257*e2ad626fSUlf Hansson {
258*e2ad626fSUlf Hansson 	writel_relaxed(value, drv->base + offset);
259*e2ad626fSUlf Hansson }
260*e2ad626fSUlf Hansson 
cpr_read(struct cpr_drv * drv,u32 offset)261*e2ad626fSUlf Hansson static u32 cpr_read(struct cpr_drv *drv, u32 offset)
262*e2ad626fSUlf Hansson {
263*e2ad626fSUlf Hansson 	return readl_relaxed(drv->base + offset);
264*e2ad626fSUlf Hansson }
265*e2ad626fSUlf Hansson 
266*e2ad626fSUlf Hansson static void
cpr_masked_write(struct cpr_drv * drv,u32 offset,u32 mask,u32 value)267*e2ad626fSUlf Hansson cpr_masked_write(struct cpr_drv *drv, u32 offset, u32 mask, u32 value)
268*e2ad626fSUlf Hansson {
269*e2ad626fSUlf Hansson 	u32 val;
270*e2ad626fSUlf Hansson 
271*e2ad626fSUlf Hansson 	val = readl_relaxed(drv->base + offset);
272*e2ad626fSUlf Hansson 	val &= ~mask;
273*e2ad626fSUlf Hansson 	val |= value & mask;
274*e2ad626fSUlf Hansson 	writel_relaxed(val, drv->base + offset);
275*e2ad626fSUlf Hansson }
276*e2ad626fSUlf Hansson 
cpr_irq_clr(struct cpr_drv * drv)277*e2ad626fSUlf Hansson static void cpr_irq_clr(struct cpr_drv *drv)
278*e2ad626fSUlf Hansson {
279*e2ad626fSUlf Hansson 	cpr_write(drv, REG_RBIF_IRQ_CLEAR, CPR_INT_ALL);
280*e2ad626fSUlf Hansson }
281*e2ad626fSUlf Hansson 
cpr_irq_clr_nack(struct cpr_drv * drv)282*e2ad626fSUlf Hansson static void cpr_irq_clr_nack(struct cpr_drv *drv)
283*e2ad626fSUlf Hansson {
284*e2ad626fSUlf Hansson 	cpr_irq_clr(drv);
285*e2ad626fSUlf Hansson 	cpr_write(drv, REG_RBIF_CONT_NACK_CMD, 1);
286*e2ad626fSUlf Hansson }
287*e2ad626fSUlf Hansson 
cpr_irq_clr_ack(struct cpr_drv * drv)288*e2ad626fSUlf Hansson static void cpr_irq_clr_ack(struct cpr_drv *drv)
289*e2ad626fSUlf Hansson {
290*e2ad626fSUlf Hansson 	cpr_irq_clr(drv);
291*e2ad626fSUlf Hansson 	cpr_write(drv, REG_RBIF_CONT_ACK_CMD, 1);
292*e2ad626fSUlf Hansson }
293*e2ad626fSUlf Hansson 
cpr_irq_set(struct cpr_drv * drv,u32 int_bits)294*e2ad626fSUlf Hansson static void cpr_irq_set(struct cpr_drv *drv, u32 int_bits)
295*e2ad626fSUlf Hansson {
296*e2ad626fSUlf Hansson 	cpr_write(drv, REG_RBIF_IRQ_EN(0), int_bits);
297*e2ad626fSUlf Hansson }
298*e2ad626fSUlf Hansson 
cpr_ctl_modify(struct cpr_drv * drv,u32 mask,u32 value)299*e2ad626fSUlf Hansson static void cpr_ctl_modify(struct cpr_drv *drv, u32 mask, u32 value)
300*e2ad626fSUlf Hansson {
301*e2ad626fSUlf Hansson 	cpr_masked_write(drv, REG_RBCPR_CTL, mask, value);
302*e2ad626fSUlf Hansson }
303*e2ad626fSUlf Hansson 
cpr_ctl_enable(struct cpr_drv * drv,struct corner * corner)304*e2ad626fSUlf Hansson static void cpr_ctl_enable(struct cpr_drv *drv, struct corner *corner)
305*e2ad626fSUlf Hansson {
306*e2ad626fSUlf Hansson 	u32 val, mask;
307*e2ad626fSUlf Hansson 	const struct cpr_desc *desc = drv->desc;
308*e2ad626fSUlf Hansson 
309*e2ad626fSUlf Hansson 	/* Program Consecutive Up & Down */
310*e2ad626fSUlf Hansson 	val = desc->timer_cons_down << RBIF_TIMER_ADJ_CONS_DOWN_SHIFT;
311*e2ad626fSUlf Hansson 	val |= desc->timer_cons_up << RBIF_TIMER_ADJ_CONS_UP_SHIFT;
312*e2ad626fSUlf Hansson 	mask = RBIF_TIMER_ADJ_CONS_UP_MASK | RBIF_TIMER_ADJ_CONS_DOWN_MASK;
313*e2ad626fSUlf Hansson 	cpr_masked_write(drv, REG_RBIF_TIMER_ADJUST, mask, val);
314*e2ad626fSUlf Hansson 	cpr_masked_write(drv, REG_RBCPR_CTL,
315*e2ad626fSUlf Hansson 			 RBCPR_CTL_SW_AUTO_CONT_NACK_DN_EN |
316*e2ad626fSUlf Hansson 			 RBCPR_CTL_SW_AUTO_CONT_ACK_EN,
317*e2ad626fSUlf Hansson 			 corner->save_ctl);
318*e2ad626fSUlf Hansson 	cpr_irq_set(drv, corner->save_irq);
319*e2ad626fSUlf Hansson 
320*e2ad626fSUlf Hansson 	if (cpr_is_allowed(drv) && corner->max_uV > corner->min_uV)
321*e2ad626fSUlf Hansson 		val = RBCPR_CTL_LOOP_EN;
322*e2ad626fSUlf Hansson 	else
323*e2ad626fSUlf Hansson 		val = 0;
324*e2ad626fSUlf Hansson 	cpr_ctl_modify(drv, RBCPR_CTL_LOOP_EN, val);
325*e2ad626fSUlf Hansson }
326*e2ad626fSUlf Hansson 
cpr_ctl_disable(struct cpr_drv * drv)327*e2ad626fSUlf Hansson static void cpr_ctl_disable(struct cpr_drv *drv)
328*e2ad626fSUlf Hansson {
329*e2ad626fSUlf Hansson 	cpr_irq_set(drv, 0);
330*e2ad626fSUlf Hansson 	cpr_ctl_modify(drv, RBCPR_CTL_SW_AUTO_CONT_NACK_DN_EN |
331*e2ad626fSUlf Hansson 		       RBCPR_CTL_SW_AUTO_CONT_ACK_EN, 0);
332*e2ad626fSUlf Hansson 	cpr_masked_write(drv, REG_RBIF_TIMER_ADJUST,
333*e2ad626fSUlf Hansson 			 RBIF_TIMER_ADJ_CONS_UP_MASK |
334*e2ad626fSUlf Hansson 			 RBIF_TIMER_ADJ_CONS_DOWN_MASK, 0);
335*e2ad626fSUlf Hansson 	cpr_irq_clr(drv);
336*e2ad626fSUlf Hansson 	cpr_write(drv, REG_RBIF_CONT_ACK_CMD, 1);
337*e2ad626fSUlf Hansson 	cpr_write(drv, REG_RBIF_CONT_NACK_CMD, 1);
338*e2ad626fSUlf Hansson 	cpr_ctl_modify(drv, RBCPR_CTL_LOOP_EN, 0);
339*e2ad626fSUlf Hansson }
340*e2ad626fSUlf Hansson 
cpr_ctl_is_enabled(struct cpr_drv * drv)341*e2ad626fSUlf Hansson static bool cpr_ctl_is_enabled(struct cpr_drv *drv)
342*e2ad626fSUlf Hansson {
343*e2ad626fSUlf Hansson 	u32 reg_val;
344*e2ad626fSUlf Hansson 
345*e2ad626fSUlf Hansson 	reg_val = cpr_read(drv, REG_RBCPR_CTL);
346*e2ad626fSUlf Hansson 	return reg_val & RBCPR_CTL_LOOP_EN;
347*e2ad626fSUlf Hansson }
348*e2ad626fSUlf Hansson 
cpr_ctl_is_busy(struct cpr_drv * drv)349*e2ad626fSUlf Hansson static bool cpr_ctl_is_busy(struct cpr_drv *drv)
350*e2ad626fSUlf Hansson {
351*e2ad626fSUlf Hansson 	u32 reg_val;
352*e2ad626fSUlf Hansson 
353*e2ad626fSUlf Hansson 	reg_val = cpr_read(drv, REG_RBCPR_RESULT_0);
354*e2ad626fSUlf Hansson 	return reg_val & RBCPR_RESULT0_BUSY_MASK;
355*e2ad626fSUlf Hansson }
356*e2ad626fSUlf Hansson 
cpr_corner_save(struct cpr_drv * drv,struct corner * corner)357*e2ad626fSUlf Hansson static void cpr_corner_save(struct cpr_drv *drv, struct corner *corner)
358*e2ad626fSUlf Hansson {
359*e2ad626fSUlf Hansson 	corner->save_ctl = cpr_read(drv, REG_RBCPR_CTL);
360*e2ad626fSUlf Hansson 	corner->save_irq = cpr_read(drv, REG_RBIF_IRQ_EN(0));
361*e2ad626fSUlf Hansson }
362*e2ad626fSUlf Hansson 
cpr_corner_restore(struct cpr_drv * drv,struct corner * corner)363*e2ad626fSUlf Hansson static void cpr_corner_restore(struct cpr_drv *drv, struct corner *corner)
364*e2ad626fSUlf Hansson {
365*e2ad626fSUlf Hansson 	u32 gcnt, ctl, irq, ro_sel, step_quot;
366*e2ad626fSUlf Hansson 	struct fuse_corner *fuse = corner->fuse_corner;
367*e2ad626fSUlf Hansson 	const struct cpr_desc *desc = drv->desc;
368*e2ad626fSUlf Hansson 	int i;
369*e2ad626fSUlf Hansson 
370*e2ad626fSUlf Hansson 	ro_sel = fuse->ring_osc_idx;
371*e2ad626fSUlf Hansson 	gcnt = drv->gcnt;
372*e2ad626fSUlf Hansson 	gcnt |= fuse->quot - corner->quot_adjust;
373*e2ad626fSUlf Hansson 
374*e2ad626fSUlf Hansson 	/* Program the step quotient and idle clocks */
375*e2ad626fSUlf Hansson 	step_quot = desc->idle_clocks << RBCPR_STEP_QUOT_IDLE_CLK_SHIFT;
376*e2ad626fSUlf Hansson 	step_quot |= fuse->step_quot & RBCPR_STEP_QUOT_STEPQUOT_MASK;
377*e2ad626fSUlf Hansson 	cpr_write(drv, REG_RBCPR_STEP_QUOT, step_quot);
378*e2ad626fSUlf Hansson 
379*e2ad626fSUlf Hansson 	/* Clear the target quotient value and gate count of all ROs */
380*e2ad626fSUlf Hansson 	for (i = 0; i < CPR_NUM_RING_OSC; i++)
381*e2ad626fSUlf Hansson 		cpr_write(drv, REG_RBCPR_GCNT_TARGET(i), 0);
382*e2ad626fSUlf Hansson 
383*e2ad626fSUlf Hansson 	cpr_write(drv, REG_RBCPR_GCNT_TARGET(ro_sel), gcnt);
384*e2ad626fSUlf Hansson 	ctl = corner->save_ctl;
385*e2ad626fSUlf Hansson 	cpr_write(drv, REG_RBCPR_CTL, ctl);
386*e2ad626fSUlf Hansson 	irq = corner->save_irq;
387*e2ad626fSUlf Hansson 	cpr_irq_set(drv, irq);
388*e2ad626fSUlf Hansson 	dev_dbg(drv->dev, "gcnt = %#08x, ctl = %#08x, irq = %#08x\n", gcnt,
389*e2ad626fSUlf Hansson 		ctl, irq);
390*e2ad626fSUlf Hansson }
391*e2ad626fSUlf Hansson 
cpr_set_acc(struct regmap * tcsr,struct fuse_corner * f,struct fuse_corner * end)392*e2ad626fSUlf Hansson static void cpr_set_acc(struct regmap *tcsr, struct fuse_corner *f,
393*e2ad626fSUlf Hansson 			struct fuse_corner *end)
394*e2ad626fSUlf Hansson {
395*e2ad626fSUlf Hansson 	if (f == end)
396*e2ad626fSUlf Hansson 		return;
397*e2ad626fSUlf Hansson 
398*e2ad626fSUlf Hansson 	if (f < end) {
399*e2ad626fSUlf Hansson 		for (f += 1; f <= end; f++)
400*e2ad626fSUlf Hansson 			regmap_multi_reg_write(tcsr, f->accs, f->num_accs);
401*e2ad626fSUlf Hansson 	} else {
402*e2ad626fSUlf Hansson 		for (f -= 1; f >= end; f--)
403*e2ad626fSUlf Hansson 			regmap_multi_reg_write(tcsr, f->accs, f->num_accs);
404*e2ad626fSUlf Hansson 	}
405*e2ad626fSUlf Hansson }
406*e2ad626fSUlf Hansson 
cpr_pre_voltage(struct cpr_drv * drv,struct fuse_corner * fuse_corner,enum voltage_change_dir dir)407*e2ad626fSUlf Hansson static int cpr_pre_voltage(struct cpr_drv *drv,
408*e2ad626fSUlf Hansson 			   struct fuse_corner *fuse_corner,
409*e2ad626fSUlf Hansson 			   enum voltage_change_dir dir)
410*e2ad626fSUlf Hansson {
411*e2ad626fSUlf Hansson 	struct fuse_corner *prev_fuse_corner = drv->corner->fuse_corner;
412*e2ad626fSUlf Hansson 
413*e2ad626fSUlf Hansson 	if (drv->tcsr && dir == DOWN)
414*e2ad626fSUlf Hansson 		cpr_set_acc(drv->tcsr, prev_fuse_corner, fuse_corner);
415*e2ad626fSUlf Hansson 
416*e2ad626fSUlf Hansson 	return 0;
417*e2ad626fSUlf Hansson }
418*e2ad626fSUlf Hansson 
cpr_post_voltage(struct cpr_drv * drv,struct fuse_corner * fuse_corner,enum voltage_change_dir dir)419*e2ad626fSUlf Hansson static int cpr_post_voltage(struct cpr_drv *drv,
420*e2ad626fSUlf Hansson 			    struct fuse_corner *fuse_corner,
421*e2ad626fSUlf Hansson 			    enum voltage_change_dir dir)
422*e2ad626fSUlf Hansson {
423*e2ad626fSUlf Hansson 	struct fuse_corner *prev_fuse_corner = drv->corner->fuse_corner;
424*e2ad626fSUlf Hansson 
425*e2ad626fSUlf Hansson 	if (drv->tcsr && dir == UP)
426*e2ad626fSUlf Hansson 		cpr_set_acc(drv->tcsr, prev_fuse_corner, fuse_corner);
427*e2ad626fSUlf Hansson 
428*e2ad626fSUlf Hansson 	return 0;
429*e2ad626fSUlf Hansson }
430*e2ad626fSUlf Hansson 
cpr_scale_voltage(struct cpr_drv * drv,struct corner * corner,int new_uV,enum voltage_change_dir dir)431*e2ad626fSUlf Hansson static int cpr_scale_voltage(struct cpr_drv *drv, struct corner *corner,
432*e2ad626fSUlf Hansson 			     int new_uV, enum voltage_change_dir dir)
433*e2ad626fSUlf Hansson {
434*e2ad626fSUlf Hansson 	int ret;
435*e2ad626fSUlf Hansson 	struct fuse_corner *fuse_corner = corner->fuse_corner;
436*e2ad626fSUlf Hansson 
437*e2ad626fSUlf Hansson 	ret = cpr_pre_voltage(drv, fuse_corner, dir);
438*e2ad626fSUlf Hansson 	if (ret)
439*e2ad626fSUlf Hansson 		return ret;
440*e2ad626fSUlf Hansson 
441*e2ad626fSUlf Hansson 	ret = regulator_set_voltage(drv->vdd_apc, new_uV, new_uV);
442*e2ad626fSUlf Hansson 	if (ret) {
443*e2ad626fSUlf Hansson 		dev_err_ratelimited(drv->dev, "failed to set apc voltage %d\n",
444*e2ad626fSUlf Hansson 				    new_uV);
445*e2ad626fSUlf Hansson 		return ret;
446*e2ad626fSUlf Hansson 	}
447*e2ad626fSUlf Hansson 
448*e2ad626fSUlf Hansson 	ret = cpr_post_voltage(drv, fuse_corner, dir);
449*e2ad626fSUlf Hansson 	if (ret)
450*e2ad626fSUlf Hansson 		return ret;
451*e2ad626fSUlf Hansson 
452*e2ad626fSUlf Hansson 	return 0;
453*e2ad626fSUlf Hansson }
454*e2ad626fSUlf Hansson 
cpr_get_cur_perf_state(struct cpr_drv * drv)455*e2ad626fSUlf Hansson static unsigned int cpr_get_cur_perf_state(struct cpr_drv *drv)
456*e2ad626fSUlf Hansson {
457*e2ad626fSUlf Hansson 	return drv->corner ? drv->corner - drv->corners + 1 : 0;
458*e2ad626fSUlf Hansson }
459*e2ad626fSUlf Hansson 
cpr_scale(struct cpr_drv * drv,enum voltage_change_dir dir)460*e2ad626fSUlf Hansson static int cpr_scale(struct cpr_drv *drv, enum voltage_change_dir dir)
461*e2ad626fSUlf Hansson {
462*e2ad626fSUlf Hansson 	u32 val, error_steps, reg_mask;
463*e2ad626fSUlf Hansson 	int last_uV, new_uV, step_uV, ret;
464*e2ad626fSUlf Hansson 	struct corner *corner;
465*e2ad626fSUlf Hansson 	const struct cpr_desc *desc = drv->desc;
466*e2ad626fSUlf Hansson 
467*e2ad626fSUlf Hansson 	if (dir != UP && dir != DOWN)
468*e2ad626fSUlf Hansson 		return 0;
469*e2ad626fSUlf Hansson 
470*e2ad626fSUlf Hansson 	step_uV = regulator_get_linear_step(drv->vdd_apc);
471*e2ad626fSUlf Hansson 	if (!step_uV)
472*e2ad626fSUlf Hansson 		return -EINVAL;
473*e2ad626fSUlf Hansson 
474*e2ad626fSUlf Hansson 	corner = drv->corner;
475*e2ad626fSUlf Hansson 
476*e2ad626fSUlf Hansson 	val = cpr_read(drv, REG_RBCPR_RESULT_0);
477*e2ad626fSUlf Hansson 
478*e2ad626fSUlf Hansson 	error_steps = val >> RBCPR_RESULT0_ERROR_STEPS_SHIFT;
479*e2ad626fSUlf Hansson 	error_steps &= RBCPR_RESULT0_ERROR_STEPS_MASK;
480*e2ad626fSUlf Hansson 	last_uV = corner->last_uV;
481*e2ad626fSUlf Hansson 
482*e2ad626fSUlf Hansson 	if (dir == UP) {
483*e2ad626fSUlf Hansson 		if (desc->clamp_timer_interval &&
484*e2ad626fSUlf Hansson 		    error_steps < desc->up_threshold) {
485*e2ad626fSUlf Hansson 			/*
486*e2ad626fSUlf Hansson 			 * Handle the case where another measurement started
487*e2ad626fSUlf Hansson 			 * after the interrupt was triggered due to a core
488*e2ad626fSUlf Hansson 			 * exiting from power collapse.
489*e2ad626fSUlf Hansson 			 */
490*e2ad626fSUlf Hansson 			error_steps = max(desc->up_threshold,
491*e2ad626fSUlf Hansson 					  desc->vdd_apc_step_up_limit);
492*e2ad626fSUlf Hansson 		}
493*e2ad626fSUlf Hansson 
494*e2ad626fSUlf Hansson 		if (last_uV >= corner->max_uV) {
495*e2ad626fSUlf Hansson 			cpr_irq_clr_nack(drv);
496*e2ad626fSUlf Hansson 
497*e2ad626fSUlf Hansson 			/* Maximize the UP threshold */
498*e2ad626fSUlf Hansson 			reg_mask = RBCPR_CTL_UP_THRESHOLD_MASK;
499*e2ad626fSUlf Hansson 			reg_mask <<= RBCPR_CTL_UP_THRESHOLD_SHIFT;
500*e2ad626fSUlf Hansson 			val = reg_mask;
501*e2ad626fSUlf Hansson 			cpr_ctl_modify(drv, reg_mask, val);
502*e2ad626fSUlf Hansson 
503*e2ad626fSUlf Hansson 			/* Disable UP interrupt */
504*e2ad626fSUlf Hansson 			cpr_irq_set(drv, CPR_INT_DEFAULT & ~CPR_INT_UP);
505*e2ad626fSUlf Hansson 
506*e2ad626fSUlf Hansson 			return 0;
507*e2ad626fSUlf Hansson 		}
508*e2ad626fSUlf Hansson 
509*e2ad626fSUlf Hansson 		if (error_steps > desc->vdd_apc_step_up_limit)
510*e2ad626fSUlf Hansson 			error_steps = desc->vdd_apc_step_up_limit;
511*e2ad626fSUlf Hansson 
512*e2ad626fSUlf Hansson 		/* Calculate new voltage */
513*e2ad626fSUlf Hansson 		new_uV = last_uV + error_steps * step_uV;
514*e2ad626fSUlf Hansson 		new_uV = min(new_uV, corner->max_uV);
515*e2ad626fSUlf Hansson 
516*e2ad626fSUlf Hansson 		dev_dbg(drv->dev,
517*e2ad626fSUlf Hansson 			"UP: -> new_uV: %d last_uV: %d perf state: %u\n",
518*e2ad626fSUlf Hansson 			new_uV, last_uV, cpr_get_cur_perf_state(drv));
519*e2ad626fSUlf Hansson 	} else {
520*e2ad626fSUlf Hansson 		if (desc->clamp_timer_interval &&
521*e2ad626fSUlf Hansson 		    error_steps < desc->down_threshold) {
522*e2ad626fSUlf Hansson 			/*
523*e2ad626fSUlf Hansson 			 * Handle the case where another measurement started
524*e2ad626fSUlf Hansson 			 * after the interrupt was triggered due to a core
525*e2ad626fSUlf Hansson 			 * exiting from power collapse.
526*e2ad626fSUlf Hansson 			 */
527*e2ad626fSUlf Hansson 			error_steps = max(desc->down_threshold,
528*e2ad626fSUlf Hansson 					  desc->vdd_apc_step_down_limit);
529*e2ad626fSUlf Hansson 		}
530*e2ad626fSUlf Hansson 
531*e2ad626fSUlf Hansson 		if (last_uV <= corner->min_uV) {
532*e2ad626fSUlf Hansson 			cpr_irq_clr_nack(drv);
533*e2ad626fSUlf Hansson 
534*e2ad626fSUlf Hansson 			/* Enable auto nack down */
535*e2ad626fSUlf Hansson 			reg_mask = RBCPR_CTL_SW_AUTO_CONT_NACK_DN_EN;
536*e2ad626fSUlf Hansson 			val = RBCPR_CTL_SW_AUTO_CONT_NACK_DN_EN;
537*e2ad626fSUlf Hansson 
538*e2ad626fSUlf Hansson 			cpr_ctl_modify(drv, reg_mask, val);
539*e2ad626fSUlf Hansson 
540*e2ad626fSUlf Hansson 			/* Disable DOWN interrupt */
541*e2ad626fSUlf Hansson 			cpr_irq_set(drv, CPR_INT_DEFAULT & ~CPR_INT_DOWN);
542*e2ad626fSUlf Hansson 
543*e2ad626fSUlf Hansson 			return 0;
544*e2ad626fSUlf Hansson 		}
545*e2ad626fSUlf Hansson 
546*e2ad626fSUlf Hansson 		if (error_steps > desc->vdd_apc_step_down_limit)
547*e2ad626fSUlf Hansson 			error_steps = desc->vdd_apc_step_down_limit;
548*e2ad626fSUlf Hansson 
549*e2ad626fSUlf Hansson 		/* Calculate new voltage */
550*e2ad626fSUlf Hansson 		new_uV = last_uV - error_steps * step_uV;
551*e2ad626fSUlf Hansson 		new_uV = max(new_uV, corner->min_uV);
552*e2ad626fSUlf Hansson 
553*e2ad626fSUlf Hansson 		dev_dbg(drv->dev,
554*e2ad626fSUlf Hansson 			"DOWN: -> new_uV: %d last_uV: %d perf state: %u\n",
555*e2ad626fSUlf Hansson 			new_uV, last_uV, cpr_get_cur_perf_state(drv));
556*e2ad626fSUlf Hansson 	}
557*e2ad626fSUlf Hansson 
558*e2ad626fSUlf Hansson 	ret = cpr_scale_voltage(drv, corner, new_uV, dir);
559*e2ad626fSUlf Hansson 	if (ret) {
560*e2ad626fSUlf Hansson 		cpr_irq_clr_nack(drv);
561*e2ad626fSUlf Hansson 		return ret;
562*e2ad626fSUlf Hansson 	}
563*e2ad626fSUlf Hansson 	drv->corner->last_uV = new_uV;
564*e2ad626fSUlf Hansson 
565*e2ad626fSUlf Hansson 	if (dir == UP) {
566*e2ad626fSUlf Hansson 		/* Disable auto nack down */
567*e2ad626fSUlf Hansson 		reg_mask = RBCPR_CTL_SW_AUTO_CONT_NACK_DN_EN;
568*e2ad626fSUlf Hansson 		val = 0;
569*e2ad626fSUlf Hansson 	} else {
570*e2ad626fSUlf Hansson 		/* Restore default threshold for UP */
571*e2ad626fSUlf Hansson 		reg_mask = RBCPR_CTL_UP_THRESHOLD_MASK;
572*e2ad626fSUlf Hansson 		reg_mask <<= RBCPR_CTL_UP_THRESHOLD_SHIFT;
573*e2ad626fSUlf Hansson 		val = desc->up_threshold;
574*e2ad626fSUlf Hansson 		val <<= RBCPR_CTL_UP_THRESHOLD_SHIFT;
575*e2ad626fSUlf Hansson 	}
576*e2ad626fSUlf Hansson 
577*e2ad626fSUlf Hansson 	cpr_ctl_modify(drv, reg_mask, val);
578*e2ad626fSUlf Hansson 
579*e2ad626fSUlf Hansson 	/* Re-enable default interrupts */
580*e2ad626fSUlf Hansson 	cpr_irq_set(drv, CPR_INT_DEFAULT);
581*e2ad626fSUlf Hansson 
582*e2ad626fSUlf Hansson 	/* Ack */
583*e2ad626fSUlf Hansson 	cpr_irq_clr_ack(drv);
584*e2ad626fSUlf Hansson 
585*e2ad626fSUlf Hansson 	return 0;
586*e2ad626fSUlf Hansson }
587*e2ad626fSUlf Hansson 
cpr_irq_handler(int irq,void * dev)588*e2ad626fSUlf Hansson static irqreturn_t cpr_irq_handler(int irq, void *dev)
589*e2ad626fSUlf Hansson {
590*e2ad626fSUlf Hansson 	struct cpr_drv *drv = dev;
591*e2ad626fSUlf Hansson 	const struct cpr_desc *desc = drv->desc;
592*e2ad626fSUlf Hansson 	irqreturn_t ret = IRQ_HANDLED;
593*e2ad626fSUlf Hansson 	u32 val;
594*e2ad626fSUlf Hansson 
595*e2ad626fSUlf Hansson 	mutex_lock(&drv->lock);
596*e2ad626fSUlf Hansson 
597*e2ad626fSUlf Hansson 	val = cpr_read(drv, REG_RBIF_IRQ_STATUS);
598*e2ad626fSUlf Hansson 	if (drv->flags & FLAGS_IGNORE_1ST_IRQ_STATUS)
599*e2ad626fSUlf Hansson 		val = cpr_read(drv, REG_RBIF_IRQ_STATUS);
600*e2ad626fSUlf Hansson 
601*e2ad626fSUlf Hansson 	dev_dbg(drv->dev, "IRQ_STATUS = %#02x\n", val);
602*e2ad626fSUlf Hansson 
603*e2ad626fSUlf Hansson 	if (!cpr_ctl_is_enabled(drv)) {
604*e2ad626fSUlf Hansson 		dev_dbg(drv->dev, "CPR is disabled\n");
605*e2ad626fSUlf Hansson 		ret = IRQ_NONE;
606*e2ad626fSUlf Hansson 	} else if (cpr_ctl_is_busy(drv) && !desc->clamp_timer_interval) {
607*e2ad626fSUlf Hansson 		dev_dbg(drv->dev, "CPR measurement is not ready\n");
608*e2ad626fSUlf Hansson 	} else if (!cpr_is_allowed(drv)) {
609*e2ad626fSUlf Hansson 		val = cpr_read(drv, REG_RBCPR_CTL);
610*e2ad626fSUlf Hansson 		dev_err_ratelimited(drv->dev,
611*e2ad626fSUlf Hansson 				    "Interrupt broken? RBCPR_CTL = %#02x\n",
612*e2ad626fSUlf Hansson 				    val);
613*e2ad626fSUlf Hansson 		ret = IRQ_NONE;
614*e2ad626fSUlf Hansson 	} else {
615*e2ad626fSUlf Hansson 		/*
616*e2ad626fSUlf Hansson 		 * Following sequence of handling is as per each IRQ's
617*e2ad626fSUlf Hansson 		 * priority
618*e2ad626fSUlf Hansson 		 */
619*e2ad626fSUlf Hansson 		if (val & CPR_INT_UP) {
620*e2ad626fSUlf Hansson 			cpr_scale(drv, UP);
621*e2ad626fSUlf Hansson 		} else if (val & CPR_INT_DOWN) {
622*e2ad626fSUlf Hansson 			cpr_scale(drv, DOWN);
623*e2ad626fSUlf Hansson 		} else if (val & CPR_INT_MIN) {
624*e2ad626fSUlf Hansson 			cpr_irq_clr_nack(drv);
625*e2ad626fSUlf Hansson 		} else if (val & CPR_INT_MAX) {
626*e2ad626fSUlf Hansson 			cpr_irq_clr_nack(drv);
627*e2ad626fSUlf Hansson 		} else if (val & CPR_INT_MID) {
628*e2ad626fSUlf Hansson 			/* RBCPR_CTL_SW_AUTO_CONT_ACK_EN is enabled */
629*e2ad626fSUlf Hansson 			dev_dbg(drv->dev, "IRQ occurred for Mid Flag\n");
630*e2ad626fSUlf Hansson 		} else {
631*e2ad626fSUlf Hansson 			dev_dbg(drv->dev,
632*e2ad626fSUlf Hansson 				"IRQ occurred for unknown flag (%#08x)\n", val);
633*e2ad626fSUlf Hansson 		}
634*e2ad626fSUlf Hansson 
635*e2ad626fSUlf Hansson 		/* Save register values for the corner */
636*e2ad626fSUlf Hansson 		cpr_corner_save(drv, drv->corner);
637*e2ad626fSUlf Hansson 	}
638*e2ad626fSUlf Hansson 
639*e2ad626fSUlf Hansson 	mutex_unlock(&drv->lock);
640*e2ad626fSUlf Hansson 
641*e2ad626fSUlf Hansson 	return ret;
642*e2ad626fSUlf Hansson }
643*e2ad626fSUlf Hansson 
cpr_enable(struct cpr_drv * drv)644*e2ad626fSUlf Hansson static int cpr_enable(struct cpr_drv *drv)
645*e2ad626fSUlf Hansson {
646*e2ad626fSUlf Hansson 	int ret;
647*e2ad626fSUlf Hansson 
648*e2ad626fSUlf Hansson 	ret = regulator_enable(drv->vdd_apc);
649*e2ad626fSUlf Hansson 	if (ret)
650*e2ad626fSUlf Hansson 		return ret;
651*e2ad626fSUlf Hansson 
652*e2ad626fSUlf Hansson 	mutex_lock(&drv->lock);
653*e2ad626fSUlf Hansson 
654*e2ad626fSUlf Hansson 	if (cpr_is_allowed(drv) && drv->corner) {
655*e2ad626fSUlf Hansson 		cpr_irq_clr(drv);
656*e2ad626fSUlf Hansson 		cpr_corner_restore(drv, drv->corner);
657*e2ad626fSUlf Hansson 		cpr_ctl_enable(drv, drv->corner);
658*e2ad626fSUlf Hansson 	}
659*e2ad626fSUlf Hansson 
660*e2ad626fSUlf Hansson 	mutex_unlock(&drv->lock);
661*e2ad626fSUlf Hansson 
662*e2ad626fSUlf Hansson 	return 0;
663*e2ad626fSUlf Hansson }
664*e2ad626fSUlf Hansson 
cpr_disable(struct cpr_drv * drv)665*e2ad626fSUlf Hansson static int cpr_disable(struct cpr_drv *drv)
666*e2ad626fSUlf Hansson {
667*e2ad626fSUlf Hansson 	mutex_lock(&drv->lock);
668*e2ad626fSUlf Hansson 
669*e2ad626fSUlf Hansson 	if (cpr_is_allowed(drv)) {
670*e2ad626fSUlf Hansson 		cpr_ctl_disable(drv);
671*e2ad626fSUlf Hansson 		cpr_irq_clr(drv);
672*e2ad626fSUlf Hansson 	}
673*e2ad626fSUlf Hansson 
674*e2ad626fSUlf Hansson 	mutex_unlock(&drv->lock);
675*e2ad626fSUlf Hansson 
676*e2ad626fSUlf Hansson 	return regulator_disable(drv->vdd_apc);
677*e2ad626fSUlf Hansson }
678*e2ad626fSUlf Hansson 
cpr_config(struct cpr_drv * drv)679*e2ad626fSUlf Hansson static int cpr_config(struct cpr_drv *drv)
680*e2ad626fSUlf Hansson {
681*e2ad626fSUlf Hansson 	int i;
682*e2ad626fSUlf Hansson 	u32 val, gcnt;
683*e2ad626fSUlf Hansson 	struct corner *corner;
684*e2ad626fSUlf Hansson 	const struct cpr_desc *desc = drv->desc;
685*e2ad626fSUlf Hansson 
686*e2ad626fSUlf Hansson 	/* Disable interrupt and CPR */
687*e2ad626fSUlf Hansson 	cpr_write(drv, REG_RBIF_IRQ_EN(0), 0);
688*e2ad626fSUlf Hansson 	cpr_write(drv, REG_RBCPR_CTL, 0);
689*e2ad626fSUlf Hansson 
690*e2ad626fSUlf Hansson 	/* Program the default HW ceiling, floor and vlevel */
691*e2ad626fSUlf Hansson 	val = (RBIF_LIMIT_CEILING_DEFAULT & RBIF_LIMIT_CEILING_MASK)
692*e2ad626fSUlf Hansson 		<< RBIF_LIMIT_CEILING_SHIFT;
693*e2ad626fSUlf Hansson 	val |= RBIF_LIMIT_FLOOR_DEFAULT & RBIF_LIMIT_FLOOR_MASK;
694*e2ad626fSUlf Hansson 	cpr_write(drv, REG_RBIF_LIMIT, val);
695*e2ad626fSUlf Hansson 	cpr_write(drv, REG_RBIF_SW_VLEVEL, RBIF_SW_VLEVEL_DEFAULT);
696*e2ad626fSUlf Hansson 
697*e2ad626fSUlf Hansson 	/*
698*e2ad626fSUlf Hansson 	 * Clear the target quotient value and gate count of all
699*e2ad626fSUlf Hansson 	 * ring oscillators
700*e2ad626fSUlf Hansson 	 */
701*e2ad626fSUlf Hansson 	for (i = 0; i < CPR_NUM_RING_OSC; i++)
702*e2ad626fSUlf Hansson 		cpr_write(drv, REG_RBCPR_GCNT_TARGET(i), 0);
703*e2ad626fSUlf Hansson 
704*e2ad626fSUlf Hansson 	/* Init and save gcnt */
705*e2ad626fSUlf Hansson 	gcnt = (drv->ref_clk_khz * desc->gcnt_us) / 1000;
706*e2ad626fSUlf Hansson 	gcnt = gcnt & RBCPR_GCNT_TARGET_GCNT_MASK;
707*e2ad626fSUlf Hansson 	gcnt <<= RBCPR_GCNT_TARGET_GCNT_SHIFT;
708*e2ad626fSUlf Hansson 	drv->gcnt = gcnt;
709*e2ad626fSUlf Hansson 
710*e2ad626fSUlf Hansson 	/* Program the delay count for the timer */
711*e2ad626fSUlf Hansson 	val = (drv->ref_clk_khz * desc->timer_delay_us) / 1000;
712*e2ad626fSUlf Hansson 	cpr_write(drv, REG_RBCPR_TIMER_INTERVAL, val);
713*e2ad626fSUlf Hansson 	dev_dbg(drv->dev, "Timer count: %#0x (for %d us)\n", val,
714*e2ad626fSUlf Hansson 		desc->timer_delay_us);
715*e2ad626fSUlf Hansson 
716*e2ad626fSUlf Hansson 	/* Program Consecutive Up & Down */
717*e2ad626fSUlf Hansson 	val = desc->timer_cons_down << RBIF_TIMER_ADJ_CONS_DOWN_SHIFT;
718*e2ad626fSUlf Hansson 	val |= desc->timer_cons_up << RBIF_TIMER_ADJ_CONS_UP_SHIFT;
719*e2ad626fSUlf Hansson 	val |= desc->clamp_timer_interval << RBIF_TIMER_ADJ_CLAMP_INT_SHIFT;
720*e2ad626fSUlf Hansson 	cpr_write(drv, REG_RBIF_TIMER_ADJUST, val);
721*e2ad626fSUlf Hansson 
722*e2ad626fSUlf Hansson 	/* Program the control register */
723*e2ad626fSUlf Hansson 	val = desc->up_threshold << RBCPR_CTL_UP_THRESHOLD_SHIFT;
724*e2ad626fSUlf Hansson 	val |= desc->down_threshold << RBCPR_CTL_DN_THRESHOLD_SHIFT;
725*e2ad626fSUlf Hansson 	val |= RBCPR_CTL_TIMER_EN | RBCPR_CTL_COUNT_MODE;
726*e2ad626fSUlf Hansson 	val |= RBCPR_CTL_SW_AUTO_CONT_ACK_EN;
727*e2ad626fSUlf Hansson 	cpr_write(drv, REG_RBCPR_CTL, val);
728*e2ad626fSUlf Hansson 
729*e2ad626fSUlf Hansson 	for (i = 0; i < drv->num_corners; i++) {
730*e2ad626fSUlf Hansson 		corner = &drv->corners[i];
731*e2ad626fSUlf Hansson 		corner->save_ctl = val;
732*e2ad626fSUlf Hansson 		corner->save_irq = CPR_INT_DEFAULT;
733*e2ad626fSUlf Hansson 	}
734*e2ad626fSUlf Hansson 
735*e2ad626fSUlf Hansson 	cpr_irq_set(drv, CPR_INT_DEFAULT);
736*e2ad626fSUlf Hansson 
737*e2ad626fSUlf Hansson 	val = cpr_read(drv, REG_RBCPR_VERSION);
738*e2ad626fSUlf Hansson 	if (val <= RBCPR_VER_2)
739*e2ad626fSUlf Hansson 		drv->flags |= FLAGS_IGNORE_1ST_IRQ_STATUS;
740*e2ad626fSUlf Hansson 
741*e2ad626fSUlf Hansson 	return 0;
742*e2ad626fSUlf Hansson }
743*e2ad626fSUlf Hansson 
cpr_set_performance_state(struct generic_pm_domain * domain,unsigned int state)744*e2ad626fSUlf Hansson static int cpr_set_performance_state(struct generic_pm_domain *domain,
745*e2ad626fSUlf Hansson 				     unsigned int state)
746*e2ad626fSUlf Hansson {
747*e2ad626fSUlf Hansson 	struct cpr_drv *drv = container_of(domain, struct cpr_drv, pd);
748*e2ad626fSUlf Hansson 	struct corner *corner, *end;
749*e2ad626fSUlf Hansson 	enum voltage_change_dir dir;
750*e2ad626fSUlf Hansson 	int ret = 0, new_uV;
751*e2ad626fSUlf Hansson 
752*e2ad626fSUlf Hansson 	mutex_lock(&drv->lock);
753*e2ad626fSUlf Hansson 
754*e2ad626fSUlf Hansson 	dev_dbg(drv->dev, "%s: setting perf state: %u (prev state: %u)\n",
755*e2ad626fSUlf Hansson 		__func__, state, cpr_get_cur_perf_state(drv));
756*e2ad626fSUlf Hansson 
757*e2ad626fSUlf Hansson 	/*
758*e2ad626fSUlf Hansson 	 * Determine new corner we're going to.
759*e2ad626fSUlf Hansson 	 * Remove one since lowest performance state is 1.
760*e2ad626fSUlf Hansson 	 */
761*e2ad626fSUlf Hansson 	corner = drv->corners + state - 1;
762*e2ad626fSUlf Hansson 	end = &drv->corners[drv->num_corners - 1];
763*e2ad626fSUlf Hansson 	if (corner > end || corner < drv->corners) {
764*e2ad626fSUlf Hansson 		ret = -EINVAL;
765*e2ad626fSUlf Hansson 		goto unlock;
766*e2ad626fSUlf Hansson 	}
767*e2ad626fSUlf Hansson 
768*e2ad626fSUlf Hansson 	/* Determine direction */
769*e2ad626fSUlf Hansson 	if (drv->corner > corner)
770*e2ad626fSUlf Hansson 		dir = DOWN;
771*e2ad626fSUlf Hansson 	else if (drv->corner < corner)
772*e2ad626fSUlf Hansson 		dir = UP;
773*e2ad626fSUlf Hansson 	else
774*e2ad626fSUlf Hansson 		dir = NO_CHANGE;
775*e2ad626fSUlf Hansson 
776*e2ad626fSUlf Hansson 	if (cpr_is_allowed(drv))
777*e2ad626fSUlf Hansson 		new_uV = corner->last_uV;
778*e2ad626fSUlf Hansson 	else
779*e2ad626fSUlf Hansson 		new_uV = corner->uV;
780*e2ad626fSUlf Hansson 
781*e2ad626fSUlf Hansson 	if (cpr_is_allowed(drv))
782*e2ad626fSUlf Hansson 		cpr_ctl_disable(drv);
783*e2ad626fSUlf Hansson 
784*e2ad626fSUlf Hansson 	ret = cpr_scale_voltage(drv, corner, new_uV, dir);
785*e2ad626fSUlf Hansson 	if (ret)
786*e2ad626fSUlf Hansson 		goto unlock;
787*e2ad626fSUlf Hansson 
788*e2ad626fSUlf Hansson 	if (cpr_is_allowed(drv)) {
789*e2ad626fSUlf Hansson 		cpr_irq_clr(drv);
790*e2ad626fSUlf Hansson 		if (drv->corner != corner)
791*e2ad626fSUlf Hansson 			cpr_corner_restore(drv, corner);
792*e2ad626fSUlf Hansson 		cpr_ctl_enable(drv, corner);
793*e2ad626fSUlf Hansson 	}
794*e2ad626fSUlf Hansson 
795*e2ad626fSUlf Hansson 	drv->corner = corner;
796*e2ad626fSUlf Hansson 
797*e2ad626fSUlf Hansson unlock:
798*e2ad626fSUlf Hansson 	mutex_unlock(&drv->lock);
799*e2ad626fSUlf Hansson 
800*e2ad626fSUlf Hansson 	return ret;
801*e2ad626fSUlf Hansson }
802*e2ad626fSUlf Hansson 
803*e2ad626fSUlf Hansson static int
cpr_populate_ring_osc_idx(struct cpr_drv * drv)804*e2ad626fSUlf Hansson cpr_populate_ring_osc_idx(struct cpr_drv *drv)
805*e2ad626fSUlf Hansson {
806*e2ad626fSUlf Hansson 	struct fuse_corner *fuse = drv->fuse_corners;
807*e2ad626fSUlf Hansson 	struct fuse_corner *end = fuse + drv->desc->num_fuse_corners;
808*e2ad626fSUlf Hansson 	const struct cpr_fuse *fuses = drv->cpr_fuses;
809*e2ad626fSUlf Hansson 	u32 data;
810*e2ad626fSUlf Hansson 	int ret;
811*e2ad626fSUlf Hansson 
812*e2ad626fSUlf Hansson 	for (; fuse < end; fuse++, fuses++) {
813*e2ad626fSUlf Hansson 		ret = nvmem_cell_read_variable_le_u32(drv->dev, fuses->ring_osc, &data);
814*e2ad626fSUlf Hansson 		if (ret)
815*e2ad626fSUlf Hansson 			return ret;
816*e2ad626fSUlf Hansson 		fuse->ring_osc_idx = data;
817*e2ad626fSUlf Hansson 	}
818*e2ad626fSUlf Hansson 
819*e2ad626fSUlf Hansson 	return 0;
820*e2ad626fSUlf Hansson }
821*e2ad626fSUlf Hansson 
cpr_read_fuse_uV(const struct cpr_desc * desc,const struct fuse_corner_data * fdata,const char * init_v_efuse,int step_volt,struct cpr_drv * drv)822*e2ad626fSUlf Hansson static int cpr_read_fuse_uV(const struct cpr_desc *desc,
823*e2ad626fSUlf Hansson 			    const struct fuse_corner_data *fdata,
824*e2ad626fSUlf Hansson 			    const char *init_v_efuse,
825*e2ad626fSUlf Hansson 			    int step_volt,
826*e2ad626fSUlf Hansson 			    struct cpr_drv *drv)
827*e2ad626fSUlf Hansson {
828*e2ad626fSUlf Hansson 	int step_size_uV, steps, uV;
829*e2ad626fSUlf Hansson 	u32 bits = 0;
830*e2ad626fSUlf Hansson 	int ret;
831*e2ad626fSUlf Hansson 
832*e2ad626fSUlf Hansson 	ret = nvmem_cell_read_variable_le_u32(drv->dev, init_v_efuse, &bits);
833*e2ad626fSUlf Hansson 	if (ret)
834*e2ad626fSUlf Hansson 		return ret;
835*e2ad626fSUlf Hansson 
836*e2ad626fSUlf Hansson 	steps = bits & ~BIT(desc->cpr_fuses.init_voltage_width - 1);
837*e2ad626fSUlf Hansson 	/* Not two's complement.. instead highest bit is sign bit */
838*e2ad626fSUlf Hansson 	if (bits & BIT(desc->cpr_fuses.init_voltage_width - 1))
839*e2ad626fSUlf Hansson 		steps = -steps;
840*e2ad626fSUlf Hansson 
841*e2ad626fSUlf Hansson 	step_size_uV = desc->cpr_fuses.init_voltage_step;
842*e2ad626fSUlf Hansson 
843*e2ad626fSUlf Hansson 	uV = fdata->ref_uV + steps * step_size_uV;
844*e2ad626fSUlf Hansson 	return DIV_ROUND_UP(uV, step_volt) * step_volt;
845*e2ad626fSUlf Hansson }
846*e2ad626fSUlf Hansson 
cpr_fuse_corner_init(struct cpr_drv * drv)847*e2ad626fSUlf Hansson static int cpr_fuse_corner_init(struct cpr_drv *drv)
848*e2ad626fSUlf Hansson {
849*e2ad626fSUlf Hansson 	const struct cpr_desc *desc = drv->desc;
850*e2ad626fSUlf Hansson 	const struct cpr_fuse *fuses = drv->cpr_fuses;
851*e2ad626fSUlf Hansson 	const struct acc_desc *acc_desc = drv->acc_desc;
852*e2ad626fSUlf Hansson 	int i;
853*e2ad626fSUlf Hansson 	unsigned int step_volt;
854*e2ad626fSUlf Hansson 	struct fuse_corner_data *fdata;
855*e2ad626fSUlf Hansson 	struct fuse_corner *fuse, *end;
856*e2ad626fSUlf Hansson 	int uV;
857*e2ad626fSUlf Hansson 	const struct reg_sequence *accs;
858*e2ad626fSUlf Hansson 	int ret;
859*e2ad626fSUlf Hansson 
860*e2ad626fSUlf Hansson 	accs = acc_desc->settings;
861*e2ad626fSUlf Hansson 
862*e2ad626fSUlf Hansson 	step_volt = regulator_get_linear_step(drv->vdd_apc);
863*e2ad626fSUlf Hansson 	if (!step_volt)
864*e2ad626fSUlf Hansson 		return -EINVAL;
865*e2ad626fSUlf Hansson 
866*e2ad626fSUlf Hansson 	/* Populate fuse_corner members */
867*e2ad626fSUlf Hansson 	fuse = drv->fuse_corners;
868*e2ad626fSUlf Hansson 	end = &fuse[desc->num_fuse_corners - 1];
869*e2ad626fSUlf Hansson 	fdata = desc->cpr_fuses.fuse_corner_data;
870*e2ad626fSUlf Hansson 
871*e2ad626fSUlf Hansson 	for (i = 0; fuse <= end; fuse++, fuses++, i++, fdata++) {
872*e2ad626fSUlf Hansson 		/*
873*e2ad626fSUlf Hansson 		 * Update SoC voltages: platforms might choose a different
874*e2ad626fSUlf Hansson 		 * regulators than the one used to characterize the algorithms
875*e2ad626fSUlf Hansson 		 * (ie, init_voltage_step).
876*e2ad626fSUlf Hansson 		 */
877*e2ad626fSUlf Hansson 		fdata->min_uV = roundup(fdata->min_uV, step_volt);
878*e2ad626fSUlf Hansson 		fdata->max_uV = roundup(fdata->max_uV, step_volt);
879*e2ad626fSUlf Hansson 
880*e2ad626fSUlf Hansson 		/* Populate uV */
881*e2ad626fSUlf Hansson 		uV = cpr_read_fuse_uV(desc, fdata, fuses->init_voltage,
882*e2ad626fSUlf Hansson 				      step_volt, drv);
883*e2ad626fSUlf Hansson 		if (uV < 0)
884*e2ad626fSUlf Hansson 			return uV;
885*e2ad626fSUlf Hansson 
886*e2ad626fSUlf Hansson 		fuse->min_uV = fdata->min_uV;
887*e2ad626fSUlf Hansson 		fuse->max_uV = fdata->max_uV;
888*e2ad626fSUlf Hansson 		fuse->uV = clamp(uV, fuse->min_uV, fuse->max_uV);
889*e2ad626fSUlf Hansson 
890*e2ad626fSUlf Hansson 		if (fuse == end) {
891*e2ad626fSUlf Hansson 			/*
892*e2ad626fSUlf Hansson 			 * Allow the highest fuse corner's PVS voltage to
893*e2ad626fSUlf Hansson 			 * define the ceiling voltage for that corner in order
894*e2ad626fSUlf Hansson 			 * to support SoC's in which variable ceiling values
895*e2ad626fSUlf Hansson 			 * are required.
896*e2ad626fSUlf Hansson 			 */
897*e2ad626fSUlf Hansson 			end->max_uV = max(end->max_uV, end->uV);
898*e2ad626fSUlf Hansson 		}
899*e2ad626fSUlf Hansson 
900*e2ad626fSUlf Hansson 		/* Populate target quotient by scaling */
901*e2ad626fSUlf Hansson 		ret = nvmem_cell_read_variable_le_u32(drv->dev, fuses->quotient, &fuse->quot);
902*e2ad626fSUlf Hansson 		if (ret)
903*e2ad626fSUlf Hansson 			return ret;
904*e2ad626fSUlf Hansson 
905*e2ad626fSUlf Hansson 		fuse->quot *= fdata->quot_scale;
906*e2ad626fSUlf Hansson 		fuse->quot += fdata->quot_offset;
907*e2ad626fSUlf Hansson 		fuse->quot += fdata->quot_adjust;
908*e2ad626fSUlf Hansson 		fuse->step_quot = desc->step_quot[fuse->ring_osc_idx];
909*e2ad626fSUlf Hansson 
910*e2ad626fSUlf Hansson 		/* Populate acc settings */
911*e2ad626fSUlf Hansson 		fuse->accs = accs;
912*e2ad626fSUlf Hansson 		fuse->num_accs = acc_desc->num_regs_per_fuse;
913*e2ad626fSUlf Hansson 		accs += acc_desc->num_regs_per_fuse;
914*e2ad626fSUlf Hansson 	}
915*e2ad626fSUlf Hansson 
916*e2ad626fSUlf Hansson 	/*
917*e2ad626fSUlf Hansson 	 * Restrict all fuse corner PVS voltages based upon per corner
918*e2ad626fSUlf Hansson 	 * ceiling and floor voltages.
919*e2ad626fSUlf Hansson 	 */
920*e2ad626fSUlf Hansson 	for (fuse = drv->fuse_corners, i = 0; fuse <= end; fuse++, i++) {
921*e2ad626fSUlf Hansson 		if (fuse->uV > fuse->max_uV)
922*e2ad626fSUlf Hansson 			fuse->uV = fuse->max_uV;
923*e2ad626fSUlf Hansson 		else if (fuse->uV < fuse->min_uV)
924*e2ad626fSUlf Hansson 			fuse->uV = fuse->min_uV;
925*e2ad626fSUlf Hansson 
926*e2ad626fSUlf Hansson 		ret = regulator_is_supported_voltage(drv->vdd_apc,
927*e2ad626fSUlf Hansson 						     fuse->min_uV,
928*e2ad626fSUlf Hansson 						     fuse->min_uV);
929*e2ad626fSUlf Hansson 		if (!ret) {
930*e2ad626fSUlf Hansson 			dev_err(drv->dev,
931*e2ad626fSUlf Hansson 				"min uV: %d (fuse corner: %d) not supported by regulator\n",
932*e2ad626fSUlf Hansson 				fuse->min_uV, i);
933*e2ad626fSUlf Hansson 			return -EINVAL;
934*e2ad626fSUlf Hansson 		}
935*e2ad626fSUlf Hansson 
936*e2ad626fSUlf Hansson 		ret = regulator_is_supported_voltage(drv->vdd_apc,
937*e2ad626fSUlf Hansson 						     fuse->max_uV,
938*e2ad626fSUlf Hansson 						     fuse->max_uV);
939*e2ad626fSUlf Hansson 		if (!ret) {
940*e2ad626fSUlf Hansson 			dev_err(drv->dev,
941*e2ad626fSUlf Hansson 				"max uV: %d (fuse corner: %d) not supported by regulator\n",
942*e2ad626fSUlf Hansson 				fuse->max_uV, i);
943*e2ad626fSUlf Hansson 			return -EINVAL;
944*e2ad626fSUlf Hansson 		}
945*e2ad626fSUlf Hansson 
946*e2ad626fSUlf Hansson 		dev_dbg(drv->dev,
947*e2ad626fSUlf Hansson 			"fuse corner %d: [%d %d %d] RO%hhu quot %d squot %d\n",
948*e2ad626fSUlf Hansson 			i, fuse->min_uV, fuse->uV, fuse->max_uV,
949*e2ad626fSUlf Hansson 			fuse->ring_osc_idx, fuse->quot, fuse->step_quot);
950*e2ad626fSUlf Hansson 	}
951*e2ad626fSUlf Hansson 
952*e2ad626fSUlf Hansson 	return 0;
953*e2ad626fSUlf Hansson }
954*e2ad626fSUlf Hansson 
cpr_calculate_scaling(const char * quot_offset,struct cpr_drv * drv,const struct fuse_corner_data * fdata,const struct corner * corner)955*e2ad626fSUlf Hansson static int cpr_calculate_scaling(const char *quot_offset,
956*e2ad626fSUlf Hansson 				 struct cpr_drv *drv,
957*e2ad626fSUlf Hansson 				 const struct fuse_corner_data *fdata,
958*e2ad626fSUlf Hansson 				 const struct corner *corner)
959*e2ad626fSUlf Hansson {
960*e2ad626fSUlf Hansson 	u32 quot_diff = 0;
961*e2ad626fSUlf Hansson 	unsigned long freq_diff;
962*e2ad626fSUlf Hansson 	int scaling;
963*e2ad626fSUlf Hansson 	const struct fuse_corner *fuse, *prev_fuse;
964*e2ad626fSUlf Hansson 	int ret;
965*e2ad626fSUlf Hansson 
966*e2ad626fSUlf Hansson 	fuse = corner->fuse_corner;
967*e2ad626fSUlf Hansson 	prev_fuse = fuse - 1;
968*e2ad626fSUlf Hansson 
969*e2ad626fSUlf Hansson 	if (quot_offset) {
970*e2ad626fSUlf Hansson 		ret = nvmem_cell_read_variable_le_u32(drv->dev, quot_offset, &quot_diff);
971*e2ad626fSUlf Hansson 		if (ret)
972*e2ad626fSUlf Hansson 			return ret;
973*e2ad626fSUlf Hansson 
974*e2ad626fSUlf Hansson 		quot_diff *= fdata->quot_offset_scale;
975*e2ad626fSUlf Hansson 		quot_diff += fdata->quot_offset_adjust;
976*e2ad626fSUlf Hansson 	} else {
977*e2ad626fSUlf Hansson 		quot_diff = fuse->quot - prev_fuse->quot;
978*e2ad626fSUlf Hansson 	}
979*e2ad626fSUlf Hansson 
980*e2ad626fSUlf Hansson 	freq_diff = fuse->max_freq - prev_fuse->max_freq;
981*e2ad626fSUlf Hansson 	freq_diff /= 1000000; /* Convert to MHz */
982*e2ad626fSUlf Hansson 	scaling = 1000 * quot_diff / freq_diff;
983*e2ad626fSUlf Hansson 	return min(scaling, fdata->max_quot_scale);
984*e2ad626fSUlf Hansson }
985*e2ad626fSUlf Hansson 
cpr_interpolate(const struct corner * corner,int step_volt,const struct fuse_corner_data * fdata)986*e2ad626fSUlf Hansson static int cpr_interpolate(const struct corner *corner, int step_volt,
987*e2ad626fSUlf Hansson 			   const struct fuse_corner_data *fdata)
988*e2ad626fSUlf Hansson {
989*e2ad626fSUlf Hansson 	unsigned long f_high, f_low, f_diff;
990*e2ad626fSUlf Hansson 	int uV_high, uV_low, uV;
991*e2ad626fSUlf Hansson 	u64 temp, temp_limit;
992*e2ad626fSUlf Hansson 	const struct fuse_corner *fuse, *prev_fuse;
993*e2ad626fSUlf Hansson 
994*e2ad626fSUlf Hansson 	fuse = corner->fuse_corner;
995*e2ad626fSUlf Hansson 	prev_fuse = fuse - 1;
996*e2ad626fSUlf Hansson 
997*e2ad626fSUlf Hansson 	f_high = fuse->max_freq;
998*e2ad626fSUlf Hansson 	f_low = prev_fuse->max_freq;
999*e2ad626fSUlf Hansson 	uV_high = fuse->uV;
1000*e2ad626fSUlf Hansson 	uV_low = prev_fuse->uV;
1001*e2ad626fSUlf Hansson 	f_diff = fuse->max_freq - corner->freq;
1002*e2ad626fSUlf Hansson 
1003*e2ad626fSUlf Hansson 	/*
1004*e2ad626fSUlf Hansson 	 * Don't interpolate in the wrong direction. This could happen
1005*e2ad626fSUlf Hansson 	 * if the adjusted fuse voltage overlaps with the previous fuse's
1006*e2ad626fSUlf Hansson 	 * adjusted voltage.
1007*e2ad626fSUlf Hansson 	 */
1008*e2ad626fSUlf Hansson 	if (f_high <= f_low || uV_high <= uV_low || f_high <= corner->freq)
1009*e2ad626fSUlf Hansson 		return corner->uV;
1010*e2ad626fSUlf Hansson 
1011*e2ad626fSUlf Hansson 	temp = f_diff * (uV_high - uV_low);
1012*e2ad626fSUlf Hansson 	temp = div64_ul(temp, f_high - f_low);
1013*e2ad626fSUlf Hansson 
1014*e2ad626fSUlf Hansson 	/*
1015*e2ad626fSUlf Hansson 	 * max_volt_scale has units of uV/MHz while freq values
1016*e2ad626fSUlf Hansson 	 * have units of Hz.  Divide by 1000000 to convert to.
1017*e2ad626fSUlf Hansson 	 */
1018*e2ad626fSUlf Hansson 	temp_limit = f_diff * fdata->max_volt_scale;
1019*e2ad626fSUlf Hansson 	do_div(temp_limit, 1000000);
1020*e2ad626fSUlf Hansson 
1021*e2ad626fSUlf Hansson 	uV = uV_high - min(temp, temp_limit);
1022*e2ad626fSUlf Hansson 	return roundup(uV, step_volt);
1023*e2ad626fSUlf Hansson }
1024*e2ad626fSUlf Hansson 
cpr_get_fuse_corner(struct dev_pm_opp * opp)1025*e2ad626fSUlf Hansson static unsigned int cpr_get_fuse_corner(struct dev_pm_opp *opp)
1026*e2ad626fSUlf Hansson {
1027*e2ad626fSUlf Hansson 	struct device_node *np;
1028*e2ad626fSUlf Hansson 	unsigned int fuse_corner = 0;
1029*e2ad626fSUlf Hansson 
1030*e2ad626fSUlf Hansson 	np = dev_pm_opp_get_of_node(opp);
1031*e2ad626fSUlf Hansson 	if (of_property_read_u32(np, "qcom,opp-fuse-level", &fuse_corner))
1032*e2ad626fSUlf Hansson 		pr_err("%s: missing 'qcom,opp-fuse-level' property\n",
1033*e2ad626fSUlf Hansson 		       __func__);
1034*e2ad626fSUlf Hansson 
1035*e2ad626fSUlf Hansson 	of_node_put(np);
1036*e2ad626fSUlf Hansson 
1037*e2ad626fSUlf Hansson 	return fuse_corner;
1038*e2ad626fSUlf Hansson }
1039*e2ad626fSUlf Hansson 
cpr_get_opp_hz_for_req(struct dev_pm_opp * ref,struct device * cpu_dev)1040*e2ad626fSUlf Hansson static unsigned long cpr_get_opp_hz_for_req(struct dev_pm_opp *ref,
1041*e2ad626fSUlf Hansson 					    struct device *cpu_dev)
1042*e2ad626fSUlf Hansson {
1043*e2ad626fSUlf Hansson 	u64 rate = 0;
1044*e2ad626fSUlf Hansson 	struct device_node *ref_np;
1045*e2ad626fSUlf Hansson 	struct device_node *desc_np;
1046*e2ad626fSUlf Hansson 	struct device_node *child_np = NULL;
1047*e2ad626fSUlf Hansson 	struct device_node *child_req_np = NULL;
1048*e2ad626fSUlf Hansson 
1049*e2ad626fSUlf Hansson 	desc_np = dev_pm_opp_of_get_opp_desc_node(cpu_dev);
1050*e2ad626fSUlf Hansson 	if (!desc_np)
1051*e2ad626fSUlf Hansson 		return 0;
1052*e2ad626fSUlf Hansson 
1053*e2ad626fSUlf Hansson 	ref_np = dev_pm_opp_get_of_node(ref);
1054*e2ad626fSUlf Hansson 	if (!ref_np)
1055*e2ad626fSUlf Hansson 		goto out_ref;
1056*e2ad626fSUlf Hansson 
1057*e2ad626fSUlf Hansson 	do {
1058*e2ad626fSUlf Hansson 		of_node_put(child_req_np);
1059*e2ad626fSUlf Hansson 		child_np = of_get_next_available_child(desc_np, child_np);
1060*e2ad626fSUlf Hansson 		child_req_np = of_parse_phandle(child_np, "required-opps", 0);
1061*e2ad626fSUlf Hansson 	} while (child_np && child_req_np != ref_np);
1062*e2ad626fSUlf Hansson 
1063*e2ad626fSUlf Hansson 	if (child_np && child_req_np == ref_np)
1064*e2ad626fSUlf Hansson 		of_property_read_u64(child_np, "opp-hz", &rate);
1065*e2ad626fSUlf Hansson 
1066*e2ad626fSUlf Hansson 	of_node_put(child_req_np);
1067*e2ad626fSUlf Hansson 	of_node_put(child_np);
1068*e2ad626fSUlf Hansson 	of_node_put(ref_np);
1069*e2ad626fSUlf Hansson out_ref:
1070*e2ad626fSUlf Hansson 	of_node_put(desc_np);
1071*e2ad626fSUlf Hansson 
1072*e2ad626fSUlf Hansson 	return (unsigned long) rate;
1073*e2ad626fSUlf Hansson }
1074*e2ad626fSUlf Hansson 
cpr_corner_init(struct cpr_drv * drv)1075*e2ad626fSUlf Hansson static int cpr_corner_init(struct cpr_drv *drv)
1076*e2ad626fSUlf Hansson {
1077*e2ad626fSUlf Hansson 	const struct cpr_desc *desc = drv->desc;
1078*e2ad626fSUlf Hansson 	const struct cpr_fuse *fuses = drv->cpr_fuses;
1079*e2ad626fSUlf Hansson 	int i, level, scaling = 0;
1080*e2ad626fSUlf Hansson 	unsigned int fnum, fc;
1081*e2ad626fSUlf Hansson 	const char *quot_offset;
1082*e2ad626fSUlf Hansson 	struct fuse_corner *fuse, *prev_fuse;
1083*e2ad626fSUlf Hansson 	struct corner *corner, *end;
1084*e2ad626fSUlf Hansson 	struct corner_data *cdata;
1085*e2ad626fSUlf Hansson 	const struct fuse_corner_data *fdata;
1086*e2ad626fSUlf Hansson 	bool apply_scaling;
1087*e2ad626fSUlf Hansson 	unsigned long freq_diff, freq_diff_mhz;
1088*e2ad626fSUlf Hansson 	unsigned long freq;
1089*e2ad626fSUlf Hansson 	int step_volt = regulator_get_linear_step(drv->vdd_apc);
1090*e2ad626fSUlf Hansson 	struct dev_pm_opp *opp;
1091*e2ad626fSUlf Hansson 
1092*e2ad626fSUlf Hansson 	if (!step_volt)
1093*e2ad626fSUlf Hansson 		return -EINVAL;
1094*e2ad626fSUlf Hansson 
1095*e2ad626fSUlf Hansson 	corner = drv->corners;
1096*e2ad626fSUlf Hansson 	end = &corner[drv->num_corners - 1];
1097*e2ad626fSUlf Hansson 
1098*e2ad626fSUlf Hansson 	cdata = devm_kcalloc(drv->dev, drv->num_corners,
1099*e2ad626fSUlf Hansson 			     sizeof(struct corner_data),
1100*e2ad626fSUlf Hansson 			     GFP_KERNEL);
1101*e2ad626fSUlf Hansson 	if (!cdata)
1102*e2ad626fSUlf Hansson 		return -ENOMEM;
1103*e2ad626fSUlf Hansson 
1104*e2ad626fSUlf Hansson 	/*
1105*e2ad626fSUlf Hansson 	 * Store maximum frequency for each fuse corner based on the frequency
1106*e2ad626fSUlf Hansson 	 * plan
1107*e2ad626fSUlf Hansson 	 */
1108*e2ad626fSUlf Hansson 	for (level = 1; level <= drv->num_corners; level++) {
1109*e2ad626fSUlf Hansson 		opp = dev_pm_opp_find_level_exact(&drv->pd.dev, level);
1110*e2ad626fSUlf Hansson 		if (IS_ERR(opp))
1111*e2ad626fSUlf Hansson 			return -EINVAL;
1112*e2ad626fSUlf Hansson 		fc = cpr_get_fuse_corner(opp);
1113*e2ad626fSUlf Hansson 		if (!fc) {
1114*e2ad626fSUlf Hansson 			dev_pm_opp_put(opp);
1115*e2ad626fSUlf Hansson 			return -EINVAL;
1116*e2ad626fSUlf Hansson 		}
1117*e2ad626fSUlf Hansson 		fnum = fc - 1;
1118*e2ad626fSUlf Hansson 		freq = cpr_get_opp_hz_for_req(opp, drv->attached_cpu_dev);
1119*e2ad626fSUlf Hansson 		if (!freq) {
1120*e2ad626fSUlf Hansson 			dev_pm_opp_put(opp);
1121*e2ad626fSUlf Hansson 			return -EINVAL;
1122*e2ad626fSUlf Hansson 		}
1123*e2ad626fSUlf Hansson 		cdata[level - 1].fuse_corner = fnum;
1124*e2ad626fSUlf Hansson 		cdata[level - 1].freq = freq;
1125*e2ad626fSUlf Hansson 
1126*e2ad626fSUlf Hansson 		fuse = &drv->fuse_corners[fnum];
1127*e2ad626fSUlf Hansson 		dev_dbg(drv->dev, "freq: %lu level: %u fuse level: %u\n",
1128*e2ad626fSUlf Hansson 			freq, dev_pm_opp_get_level(opp) - 1, fnum);
1129*e2ad626fSUlf Hansson 		if (freq > fuse->max_freq)
1130*e2ad626fSUlf Hansson 			fuse->max_freq = freq;
1131*e2ad626fSUlf Hansson 		dev_pm_opp_put(opp);
1132*e2ad626fSUlf Hansson 	}
1133*e2ad626fSUlf Hansson 
1134*e2ad626fSUlf Hansson 	/*
1135*e2ad626fSUlf Hansson 	 * Get the quotient adjustment scaling factor, according to:
1136*e2ad626fSUlf Hansson 	 *
1137*e2ad626fSUlf Hansson 	 * scaling = min(1000 * (QUOT(corner_N) - QUOT(corner_N-1))
1138*e2ad626fSUlf Hansson 	 *		/ (freq(corner_N) - freq(corner_N-1)), max_factor)
1139*e2ad626fSUlf Hansson 	 *
1140*e2ad626fSUlf Hansson 	 * QUOT(corner_N):	quotient read from fuse for fuse corner N
1141*e2ad626fSUlf Hansson 	 * QUOT(corner_N-1):	quotient read from fuse for fuse corner (N - 1)
1142*e2ad626fSUlf Hansson 	 * freq(corner_N):	max frequency in MHz supported by fuse corner N
1143*e2ad626fSUlf Hansson 	 * freq(corner_N-1):	max frequency in MHz supported by fuse corner
1144*e2ad626fSUlf Hansson 	 *			 (N - 1)
1145*e2ad626fSUlf Hansson 	 *
1146*e2ad626fSUlf Hansson 	 * Then walk through the corners mapped to each fuse corner
1147*e2ad626fSUlf Hansson 	 * and calculate the quotient adjustment for each one using the
1148*e2ad626fSUlf Hansson 	 * following formula:
1149*e2ad626fSUlf Hansson 	 *
1150*e2ad626fSUlf Hansson 	 * quot_adjust = (freq_max - freq_corner) * scaling / 1000
1151*e2ad626fSUlf Hansson 	 *
1152*e2ad626fSUlf Hansson 	 * freq_max: max frequency in MHz supported by the fuse corner
1153*e2ad626fSUlf Hansson 	 * freq_corner: frequency in MHz corresponding to the corner
1154*e2ad626fSUlf Hansson 	 * scaling: calculated from above equation
1155*e2ad626fSUlf Hansson 	 *
1156*e2ad626fSUlf Hansson 	 *
1157*e2ad626fSUlf Hansson 	 *     +                           +
1158*e2ad626fSUlf Hansson 	 *     |                         v |
1159*e2ad626fSUlf Hansson 	 *   q |           f c           o |           f c
1160*e2ad626fSUlf Hansson 	 *   u |         c               l |         c
1161*e2ad626fSUlf Hansson 	 *   o |       f                 t |       f
1162*e2ad626fSUlf Hansson 	 *   t |     c                   a |     c
1163*e2ad626fSUlf Hansson 	 *     | c f                     g | c f
1164*e2ad626fSUlf Hansson 	 *     |                         e |
1165*e2ad626fSUlf Hansson 	 *     +---------------            +----------------
1166*e2ad626fSUlf Hansson 	 *       0 1 2 3 4 5 6               0 1 2 3 4 5 6
1167*e2ad626fSUlf Hansson 	 *          corner                      corner
1168*e2ad626fSUlf Hansson 	 *
1169*e2ad626fSUlf Hansson 	 *    c = corner
1170*e2ad626fSUlf Hansson 	 *    f = fuse corner
1171*e2ad626fSUlf Hansson 	 *
1172*e2ad626fSUlf Hansson 	 */
1173*e2ad626fSUlf Hansson 	for (apply_scaling = false, i = 0; corner <= end; corner++, i++) {
1174*e2ad626fSUlf Hansson 		fnum = cdata[i].fuse_corner;
1175*e2ad626fSUlf Hansson 		fdata = &desc->cpr_fuses.fuse_corner_data[fnum];
1176*e2ad626fSUlf Hansson 		quot_offset = fuses[fnum].quotient_offset;
1177*e2ad626fSUlf Hansson 		fuse = &drv->fuse_corners[fnum];
1178*e2ad626fSUlf Hansson 		if (fnum)
1179*e2ad626fSUlf Hansson 			prev_fuse = &drv->fuse_corners[fnum - 1];
1180*e2ad626fSUlf Hansson 		else
1181*e2ad626fSUlf Hansson 			prev_fuse = NULL;
1182*e2ad626fSUlf Hansson 
1183*e2ad626fSUlf Hansson 		corner->fuse_corner = fuse;
1184*e2ad626fSUlf Hansson 		corner->freq = cdata[i].freq;
1185*e2ad626fSUlf Hansson 		corner->uV = fuse->uV;
1186*e2ad626fSUlf Hansson 
1187*e2ad626fSUlf Hansson 		if (prev_fuse && cdata[i - 1].freq == prev_fuse->max_freq) {
1188*e2ad626fSUlf Hansson 			scaling = cpr_calculate_scaling(quot_offset, drv,
1189*e2ad626fSUlf Hansson 							fdata, corner);
1190*e2ad626fSUlf Hansson 			if (scaling < 0)
1191*e2ad626fSUlf Hansson 				return scaling;
1192*e2ad626fSUlf Hansson 
1193*e2ad626fSUlf Hansson 			apply_scaling = true;
1194*e2ad626fSUlf Hansson 		} else if (corner->freq == fuse->max_freq) {
1195*e2ad626fSUlf Hansson 			/* This is a fuse corner; don't scale anything */
1196*e2ad626fSUlf Hansson 			apply_scaling = false;
1197*e2ad626fSUlf Hansson 		}
1198*e2ad626fSUlf Hansson 
1199*e2ad626fSUlf Hansson 		if (apply_scaling) {
1200*e2ad626fSUlf Hansson 			freq_diff = fuse->max_freq - corner->freq;
1201*e2ad626fSUlf Hansson 			freq_diff_mhz = freq_diff / 1000000;
1202*e2ad626fSUlf Hansson 			corner->quot_adjust = scaling * freq_diff_mhz / 1000;
1203*e2ad626fSUlf Hansson 
1204*e2ad626fSUlf Hansson 			corner->uV = cpr_interpolate(corner, step_volt, fdata);
1205*e2ad626fSUlf Hansson 		}
1206*e2ad626fSUlf Hansson 
1207*e2ad626fSUlf Hansson 		corner->max_uV = fuse->max_uV;
1208*e2ad626fSUlf Hansson 		corner->min_uV = fuse->min_uV;
1209*e2ad626fSUlf Hansson 		corner->uV = clamp(corner->uV, corner->min_uV, corner->max_uV);
1210*e2ad626fSUlf Hansson 		corner->last_uV = corner->uV;
1211*e2ad626fSUlf Hansson 
1212*e2ad626fSUlf Hansson 		/* Reduce the ceiling voltage if needed */
1213*e2ad626fSUlf Hansson 		if (desc->reduce_to_corner_uV && corner->uV < corner->max_uV)
1214*e2ad626fSUlf Hansson 			corner->max_uV = corner->uV;
1215*e2ad626fSUlf Hansson 		else if (desc->reduce_to_fuse_uV && fuse->uV < corner->max_uV)
1216*e2ad626fSUlf Hansson 			corner->max_uV = max(corner->min_uV, fuse->uV);
1217*e2ad626fSUlf Hansson 
1218*e2ad626fSUlf Hansson 		dev_dbg(drv->dev, "corner %d: [%d %d %d] quot %d\n", i,
1219*e2ad626fSUlf Hansson 			corner->min_uV, corner->uV, corner->max_uV,
1220*e2ad626fSUlf Hansson 			fuse->quot - corner->quot_adjust);
1221*e2ad626fSUlf Hansson 	}
1222*e2ad626fSUlf Hansson 
1223*e2ad626fSUlf Hansson 	return 0;
1224*e2ad626fSUlf Hansson }
1225*e2ad626fSUlf Hansson 
cpr_get_fuses(struct cpr_drv * drv)1226*e2ad626fSUlf Hansson static const struct cpr_fuse *cpr_get_fuses(struct cpr_drv *drv)
1227*e2ad626fSUlf Hansson {
1228*e2ad626fSUlf Hansson 	const struct cpr_desc *desc = drv->desc;
1229*e2ad626fSUlf Hansson 	struct cpr_fuse *fuses;
1230*e2ad626fSUlf Hansson 	int i;
1231*e2ad626fSUlf Hansson 
1232*e2ad626fSUlf Hansson 	fuses = devm_kcalloc(drv->dev, desc->num_fuse_corners,
1233*e2ad626fSUlf Hansson 			     sizeof(struct cpr_fuse),
1234*e2ad626fSUlf Hansson 			     GFP_KERNEL);
1235*e2ad626fSUlf Hansson 	if (!fuses)
1236*e2ad626fSUlf Hansson 		return ERR_PTR(-ENOMEM);
1237*e2ad626fSUlf Hansson 
1238*e2ad626fSUlf Hansson 	for (i = 0; i < desc->num_fuse_corners; i++) {
1239*e2ad626fSUlf Hansson 		char tbuf[32];
1240*e2ad626fSUlf Hansson 
1241*e2ad626fSUlf Hansson 		snprintf(tbuf, 32, "cpr_ring_osc%d", i + 1);
1242*e2ad626fSUlf Hansson 		fuses[i].ring_osc = devm_kstrdup(drv->dev, tbuf, GFP_KERNEL);
1243*e2ad626fSUlf Hansson 		if (!fuses[i].ring_osc)
1244*e2ad626fSUlf Hansson 			return ERR_PTR(-ENOMEM);
1245*e2ad626fSUlf Hansson 
1246*e2ad626fSUlf Hansson 		snprintf(tbuf, 32, "cpr_init_voltage%d", i + 1);
1247*e2ad626fSUlf Hansson 		fuses[i].init_voltage = devm_kstrdup(drv->dev, tbuf,
1248*e2ad626fSUlf Hansson 						     GFP_KERNEL);
1249*e2ad626fSUlf Hansson 		if (!fuses[i].init_voltage)
1250*e2ad626fSUlf Hansson 			return ERR_PTR(-ENOMEM);
1251*e2ad626fSUlf Hansson 
1252*e2ad626fSUlf Hansson 		snprintf(tbuf, 32, "cpr_quotient%d", i + 1);
1253*e2ad626fSUlf Hansson 		fuses[i].quotient = devm_kstrdup(drv->dev, tbuf, GFP_KERNEL);
1254*e2ad626fSUlf Hansson 		if (!fuses[i].quotient)
1255*e2ad626fSUlf Hansson 			return ERR_PTR(-ENOMEM);
1256*e2ad626fSUlf Hansson 
1257*e2ad626fSUlf Hansson 		snprintf(tbuf, 32, "cpr_quotient_offset%d", i + 1);
1258*e2ad626fSUlf Hansson 		fuses[i].quotient_offset = devm_kstrdup(drv->dev, tbuf,
1259*e2ad626fSUlf Hansson 							GFP_KERNEL);
1260*e2ad626fSUlf Hansson 		if (!fuses[i].quotient_offset)
1261*e2ad626fSUlf Hansson 			return ERR_PTR(-ENOMEM);
1262*e2ad626fSUlf Hansson 	}
1263*e2ad626fSUlf Hansson 
1264*e2ad626fSUlf Hansson 	return fuses;
1265*e2ad626fSUlf Hansson }
1266*e2ad626fSUlf Hansson 
cpr_set_loop_allowed(struct cpr_drv * drv)1267*e2ad626fSUlf Hansson static void cpr_set_loop_allowed(struct cpr_drv *drv)
1268*e2ad626fSUlf Hansson {
1269*e2ad626fSUlf Hansson 	drv->loop_disabled = false;
1270*e2ad626fSUlf Hansson }
1271*e2ad626fSUlf Hansson 
cpr_init_parameters(struct cpr_drv * drv)1272*e2ad626fSUlf Hansson static int cpr_init_parameters(struct cpr_drv *drv)
1273*e2ad626fSUlf Hansson {
1274*e2ad626fSUlf Hansson 	const struct cpr_desc *desc = drv->desc;
1275*e2ad626fSUlf Hansson 	struct clk *clk;
1276*e2ad626fSUlf Hansson 
1277*e2ad626fSUlf Hansson 	clk = clk_get(drv->dev, "ref");
1278*e2ad626fSUlf Hansson 	if (IS_ERR(clk))
1279*e2ad626fSUlf Hansson 		return PTR_ERR(clk);
1280*e2ad626fSUlf Hansson 
1281*e2ad626fSUlf Hansson 	drv->ref_clk_khz = clk_get_rate(clk) / 1000;
1282*e2ad626fSUlf Hansson 	clk_put(clk);
1283*e2ad626fSUlf Hansson 
1284*e2ad626fSUlf Hansson 	if (desc->timer_cons_up > RBIF_TIMER_ADJ_CONS_UP_MASK ||
1285*e2ad626fSUlf Hansson 	    desc->timer_cons_down > RBIF_TIMER_ADJ_CONS_DOWN_MASK ||
1286*e2ad626fSUlf Hansson 	    desc->up_threshold > RBCPR_CTL_UP_THRESHOLD_MASK ||
1287*e2ad626fSUlf Hansson 	    desc->down_threshold > RBCPR_CTL_DN_THRESHOLD_MASK ||
1288*e2ad626fSUlf Hansson 	    desc->idle_clocks > RBCPR_STEP_QUOT_IDLE_CLK_MASK ||
1289*e2ad626fSUlf Hansson 	    desc->clamp_timer_interval > RBIF_TIMER_ADJ_CLAMP_INT_MASK)
1290*e2ad626fSUlf Hansson 		return -EINVAL;
1291*e2ad626fSUlf Hansson 
1292*e2ad626fSUlf Hansson 	dev_dbg(drv->dev, "up threshold = %u, down threshold = %u\n",
1293*e2ad626fSUlf Hansson 		desc->up_threshold, desc->down_threshold);
1294*e2ad626fSUlf Hansson 
1295*e2ad626fSUlf Hansson 	return 0;
1296*e2ad626fSUlf Hansson }
1297*e2ad626fSUlf Hansson 
cpr_find_initial_corner(struct cpr_drv * drv)1298*e2ad626fSUlf Hansson static int cpr_find_initial_corner(struct cpr_drv *drv)
1299*e2ad626fSUlf Hansson {
1300*e2ad626fSUlf Hansson 	unsigned long rate;
1301*e2ad626fSUlf Hansson 	const struct corner *end;
1302*e2ad626fSUlf Hansson 	struct corner *iter;
1303*e2ad626fSUlf Hansson 	unsigned int i = 0;
1304*e2ad626fSUlf Hansson 
1305*e2ad626fSUlf Hansson 	if (!drv->cpu_clk) {
1306*e2ad626fSUlf Hansson 		dev_err(drv->dev, "cannot get rate from NULL clk\n");
1307*e2ad626fSUlf Hansson 		return -EINVAL;
1308*e2ad626fSUlf Hansson 	}
1309*e2ad626fSUlf Hansson 
1310*e2ad626fSUlf Hansson 	end = &drv->corners[drv->num_corners - 1];
1311*e2ad626fSUlf Hansson 	rate = clk_get_rate(drv->cpu_clk);
1312*e2ad626fSUlf Hansson 
1313*e2ad626fSUlf Hansson 	/*
1314*e2ad626fSUlf Hansson 	 * Some bootloaders set a CPU clock frequency that is not defined
1315*e2ad626fSUlf Hansson 	 * in the OPP table. When running at an unlisted frequency,
1316*e2ad626fSUlf Hansson 	 * cpufreq_online() will change to the OPP which has the lowest
1317*e2ad626fSUlf Hansson 	 * frequency, at or above the unlisted frequency.
1318*e2ad626fSUlf Hansson 	 * Since cpufreq_online() always "rounds up" in the case of an
1319*e2ad626fSUlf Hansson 	 * unlisted frequency, this function always "rounds down" in case
1320*e2ad626fSUlf Hansson 	 * of an unlisted frequency. That way, when cpufreq_online()
1321*e2ad626fSUlf Hansson 	 * triggers the first ever call to cpr_set_performance_state(),
1322*e2ad626fSUlf Hansson 	 * it will correctly determine the direction as UP.
1323*e2ad626fSUlf Hansson 	 */
1324*e2ad626fSUlf Hansson 	for (iter = drv->corners; iter <= end; iter++) {
1325*e2ad626fSUlf Hansson 		if (iter->freq > rate)
1326*e2ad626fSUlf Hansson 			break;
1327*e2ad626fSUlf Hansson 		i++;
1328*e2ad626fSUlf Hansson 		if (iter->freq == rate) {
1329*e2ad626fSUlf Hansson 			drv->corner = iter;
1330*e2ad626fSUlf Hansson 			break;
1331*e2ad626fSUlf Hansson 		}
1332*e2ad626fSUlf Hansson 		if (iter->freq < rate)
1333*e2ad626fSUlf Hansson 			drv->corner = iter;
1334*e2ad626fSUlf Hansson 	}
1335*e2ad626fSUlf Hansson 
1336*e2ad626fSUlf Hansson 	if (!drv->corner) {
1337*e2ad626fSUlf Hansson 		dev_err(drv->dev, "boot up corner not found\n");
1338*e2ad626fSUlf Hansson 		return -EINVAL;
1339*e2ad626fSUlf Hansson 	}
1340*e2ad626fSUlf Hansson 
1341*e2ad626fSUlf Hansson 	dev_dbg(drv->dev, "boot up perf state: %u\n", i);
1342*e2ad626fSUlf Hansson 
1343*e2ad626fSUlf Hansson 	return 0;
1344*e2ad626fSUlf Hansson }
1345*e2ad626fSUlf Hansson 
1346*e2ad626fSUlf Hansson static const struct cpr_desc qcs404_cpr_desc = {
1347*e2ad626fSUlf Hansson 	.num_fuse_corners = 3,
1348*e2ad626fSUlf Hansson 	.min_diff_quot = CPR_FUSE_MIN_QUOT_DIFF,
1349*e2ad626fSUlf Hansson 	.step_quot = (int []){ 25, 25, 25, },
1350*e2ad626fSUlf Hansson 	.timer_delay_us = 5000,
1351*e2ad626fSUlf Hansson 	.timer_cons_up = 0,
1352*e2ad626fSUlf Hansson 	.timer_cons_down = 2,
1353*e2ad626fSUlf Hansson 	.up_threshold = 1,
1354*e2ad626fSUlf Hansson 	.down_threshold = 3,
1355*e2ad626fSUlf Hansson 	.idle_clocks = 15,
1356*e2ad626fSUlf Hansson 	.gcnt_us = 1,
1357*e2ad626fSUlf Hansson 	.vdd_apc_step_up_limit = 1,
1358*e2ad626fSUlf Hansson 	.vdd_apc_step_down_limit = 1,
1359*e2ad626fSUlf Hansson 	.cpr_fuses = {
1360*e2ad626fSUlf Hansson 		.init_voltage_step = 8000,
1361*e2ad626fSUlf Hansson 		.init_voltage_width = 6,
1362*e2ad626fSUlf Hansson 		.fuse_corner_data = (struct fuse_corner_data[]){
1363*e2ad626fSUlf Hansson 			/* fuse corner 0 */
1364*e2ad626fSUlf Hansson 			{
1365*e2ad626fSUlf Hansson 				.ref_uV = 1224000,
1366*e2ad626fSUlf Hansson 				.max_uV = 1224000,
1367*e2ad626fSUlf Hansson 				.min_uV = 1048000,
1368*e2ad626fSUlf Hansson 				.max_volt_scale = 0,
1369*e2ad626fSUlf Hansson 				.max_quot_scale = 0,
1370*e2ad626fSUlf Hansson 				.quot_offset = 0,
1371*e2ad626fSUlf Hansson 				.quot_scale = 1,
1372*e2ad626fSUlf Hansson 				.quot_adjust = 0,
1373*e2ad626fSUlf Hansson 				.quot_offset_scale = 5,
1374*e2ad626fSUlf Hansson 				.quot_offset_adjust = 0,
1375*e2ad626fSUlf Hansson 			},
1376*e2ad626fSUlf Hansson 			/* fuse corner 1 */
1377*e2ad626fSUlf Hansson 			{
1378*e2ad626fSUlf Hansson 				.ref_uV = 1288000,
1379*e2ad626fSUlf Hansson 				.max_uV = 1288000,
1380*e2ad626fSUlf Hansson 				.min_uV = 1048000,
1381*e2ad626fSUlf Hansson 				.max_volt_scale = 2000,
1382*e2ad626fSUlf Hansson 				.max_quot_scale = 1400,
1383*e2ad626fSUlf Hansson 				.quot_offset = 0,
1384*e2ad626fSUlf Hansson 				.quot_scale = 1,
1385*e2ad626fSUlf Hansson 				.quot_adjust = -20,
1386*e2ad626fSUlf Hansson 				.quot_offset_scale = 5,
1387*e2ad626fSUlf Hansson 				.quot_offset_adjust = 0,
1388*e2ad626fSUlf Hansson 			},
1389*e2ad626fSUlf Hansson 			/* fuse corner 2 */
1390*e2ad626fSUlf Hansson 			{
1391*e2ad626fSUlf Hansson 				.ref_uV = 1352000,
1392*e2ad626fSUlf Hansson 				.max_uV = 1384000,
1393*e2ad626fSUlf Hansson 				.min_uV = 1088000,
1394*e2ad626fSUlf Hansson 				.max_volt_scale = 2000,
1395*e2ad626fSUlf Hansson 				.max_quot_scale = 1400,
1396*e2ad626fSUlf Hansson 				.quot_offset = 0,
1397*e2ad626fSUlf Hansson 				.quot_scale = 1,
1398*e2ad626fSUlf Hansson 				.quot_adjust = 0,
1399*e2ad626fSUlf Hansson 				.quot_offset_scale = 5,
1400*e2ad626fSUlf Hansson 				.quot_offset_adjust = 0,
1401*e2ad626fSUlf Hansson 			},
1402*e2ad626fSUlf Hansson 		},
1403*e2ad626fSUlf Hansson 	},
1404*e2ad626fSUlf Hansson };
1405*e2ad626fSUlf Hansson 
1406*e2ad626fSUlf Hansson static const struct acc_desc qcs404_acc_desc = {
1407*e2ad626fSUlf Hansson 	.settings = (struct reg_sequence[]){
1408*e2ad626fSUlf Hansson 		{ 0xb120, 0x1041040 },
1409*e2ad626fSUlf Hansson 		{ 0xb124, 0x41 },
1410*e2ad626fSUlf Hansson 		{ 0xb120, 0x0 },
1411*e2ad626fSUlf Hansson 		{ 0xb124, 0x0 },
1412*e2ad626fSUlf Hansson 		{ 0xb120, 0x0 },
1413*e2ad626fSUlf Hansson 		{ 0xb124, 0x0 },
1414*e2ad626fSUlf Hansson 	},
1415*e2ad626fSUlf Hansson 	.config = (struct reg_sequence[]){
1416*e2ad626fSUlf Hansson 		{ 0xb138, 0xff },
1417*e2ad626fSUlf Hansson 		{ 0xb130, 0x5555 },
1418*e2ad626fSUlf Hansson 	},
1419*e2ad626fSUlf Hansson 	.num_regs_per_fuse = 2,
1420*e2ad626fSUlf Hansson };
1421*e2ad626fSUlf Hansson 
1422*e2ad626fSUlf Hansson static const struct cpr_acc_desc qcs404_cpr_acc_desc = {
1423*e2ad626fSUlf Hansson 	.cpr_desc = &qcs404_cpr_desc,
1424*e2ad626fSUlf Hansson 	.acc_desc = &qcs404_acc_desc,
1425*e2ad626fSUlf Hansson };
1426*e2ad626fSUlf Hansson 
cpr_get_performance_state(struct generic_pm_domain * genpd,struct dev_pm_opp * opp)1427*e2ad626fSUlf Hansson static unsigned int cpr_get_performance_state(struct generic_pm_domain *genpd,
1428*e2ad626fSUlf Hansson 					      struct dev_pm_opp *opp)
1429*e2ad626fSUlf Hansson {
1430*e2ad626fSUlf Hansson 	return dev_pm_opp_get_level(opp);
1431*e2ad626fSUlf Hansson }
1432*e2ad626fSUlf Hansson 
cpr_power_off(struct generic_pm_domain * domain)1433*e2ad626fSUlf Hansson static int cpr_power_off(struct generic_pm_domain *domain)
1434*e2ad626fSUlf Hansson {
1435*e2ad626fSUlf Hansson 	struct cpr_drv *drv = container_of(domain, struct cpr_drv, pd);
1436*e2ad626fSUlf Hansson 
1437*e2ad626fSUlf Hansson 	return cpr_disable(drv);
1438*e2ad626fSUlf Hansson }
1439*e2ad626fSUlf Hansson 
cpr_power_on(struct generic_pm_domain * domain)1440*e2ad626fSUlf Hansson static int cpr_power_on(struct generic_pm_domain *domain)
1441*e2ad626fSUlf Hansson {
1442*e2ad626fSUlf Hansson 	struct cpr_drv *drv = container_of(domain, struct cpr_drv, pd);
1443*e2ad626fSUlf Hansson 
1444*e2ad626fSUlf Hansson 	return cpr_enable(drv);
1445*e2ad626fSUlf Hansson }
1446*e2ad626fSUlf Hansson 
cpr_pd_attach_dev(struct generic_pm_domain * domain,struct device * dev)1447*e2ad626fSUlf Hansson static int cpr_pd_attach_dev(struct generic_pm_domain *domain,
1448*e2ad626fSUlf Hansson 			     struct device *dev)
1449*e2ad626fSUlf Hansson {
1450*e2ad626fSUlf Hansson 	struct cpr_drv *drv = container_of(domain, struct cpr_drv, pd);
1451*e2ad626fSUlf Hansson 	const struct acc_desc *acc_desc = drv->acc_desc;
1452*e2ad626fSUlf Hansson 	int ret = 0;
1453*e2ad626fSUlf Hansson 
1454*e2ad626fSUlf Hansson 	mutex_lock(&drv->lock);
1455*e2ad626fSUlf Hansson 
1456*e2ad626fSUlf Hansson 	dev_dbg(drv->dev, "attach callback for: %s\n", dev_name(dev));
1457*e2ad626fSUlf Hansson 
1458*e2ad626fSUlf Hansson 	/*
1459*e2ad626fSUlf Hansson 	 * This driver only supports scaling voltage for a CPU cluster
1460*e2ad626fSUlf Hansson 	 * where all CPUs in the cluster share a single regulator.
1461*e2ad626fSUlf Hansson 	 * Therefore, save the struct device pointer only for the first
1462*e2ad626fSUlf Hansson 	 * CPU device that gets attached. There is no need to do any
1463*e2ad626fSUlf Hansson 	 * additional initialization when further CPUs get attached.
1464*e2ad626fSUlf Hansson 	 */
1465*e2ad626fSUlf Hansson 	if (drv->attached_cpu_dev)
1466*e2ad626fSUlf Hansson 		goto unlock;
1467*e2ad626fSUlf Hansson 
1468*e2ad626fSUlf Hansson 	/*
1469*e2ad626fSUlf Hansson 	 * cpr_scale_voltage() requires the direction (if we are changing
1470*e2ad626fSUlf Hansson 	 * to a higher or lower OPP). The first time
1471*e2ad626fSUlf Hansson 	 * cpr_set_performance_state() is called, there is no previous
1472*e2ad626fSUlf Hansson 	 * performance state defined. Therefore, we call
1473*e2ad626fSUlf Hansson 	 * cpr_find_initial_corner() that gets the CPU clock frequency
1474*e2ad626fSUlf Hansson 	 * set by the bootloader, so that we can determine the direction
1475*e2ad626fSUlf Hansson 	 * the first time cpr_set_performance_state() is called.
1476*e2ad626fSUlf Hansson 	 */
1477*e2ad626fSUlf Hansson 	drv->cpu_clk = devm_clk_get(dev, NULL);
1478*e2ad626fSUlf Hansson 	if (IS_ERR(drv->cpu_clk)) {
1479*e2ad626fSUlf Hansson 		ret = PTR_ERR(drv->cpu_clk);
1480*e2ad626fSUlf Hansson 		if (ret != -EPROBE_DEFER)
1481*e2ad626fSUlf Hansson 			dev_err(drv->dev, "could not get cpu clk: %d\n", ret);
1482*e2ad626fSUlf Hansson 		goto unlock;
1483*e2ad626fSUlf Hansson 	}
1484*e2ad626fSUlf Hansson 	drv->attached_cpu_dev = dev;
1485*e2ad626fSUlf Hansson 
1486*e2ad626fSUlf Hansson 	dev_dbg(drv->dev, "using cpu clk from: %s\n",
1487*e2ad626fSUlf Hansson 		dev_name(drv->attached_cpu_dev));
1488*e2ad626fSUlf Hansson 
1489*e2ad626fSUlf Hansson 	/*
1490*e2ad626fSUlf Hansson 	 * Everything related to (virtual) corners has to be initialized
1491*e2ad626fSUlf Hansson 	 * here, when attaching to the power domain, since we need to know
1492*e2ad626fSUlf Hansson 	 * the maximum frequency for each fuse corner, and this is only
1493*e2ad626fSUlf Hansson 	 * available after the cpufreq driver has attached to us.
1494*e2ad626fSUlf Hansson 	 * The reason for this is that we need to know the highest
1495*e2ad626fSUlf Hansson 	 * frequency associated with each fuse corner.
1496*e2ad626fSUlf Hansson 	 */
1497*e2ad626fSUlf Hansson 	ret = dev_pm_opp_get_opp_count(&drv->pd.dev);
1498*e2ad626fSUlf Hansson 	if (ret < 0) {
1499*e2ad626fSUlf Hansson 		dev_err(drv->dev, "could not get OPP count\n");
1500*e2ad626fSUlf Hansson 		goto unlock;
1501*e2ad626fSUlf Hansson 	}
1502*e2ad626fSUlf Hansson 	drv->num_corners = ret;
1503*e2ad626fSUlf Hansson 
1504*e2ad626fSUlf Hansson 	if (drv->num_corners < 2) {
1505*e2ad626fSUlf Hansson 		dev_err(drv->dev, "need at least 2 OPPs to use CPR\n");
1506*e2ad626fSUlf Hansson 		ret = -EINVAL;
1507*e2ad626fSUlf Hansson 		goto unlock;
1508*e2ad626fSUlf Hansson 	}
1509*e2ad626fSUlf Hansson 
1510*e2ad626fSUlf Hansson 	drv->corners = devm_kcalloc(drv->dev, drv->num_corners,
1511*e2ad626fSUlf Hansson 				    sizeof(*drv->corners),
1512*e2ad626fSUlf Hansson 				    GFP_KERNEL);
1513*e2ad626fSUlf Hansson 	if (!drv->corners) {
1514*e2ad626fSUlf Hansson 		ret = -ENOMEM;
1515*e2ad626fSUlf Hansson 		goto unlock;
1516*e2ad626fSUlf Hansson 	}
1517*e2ad626fSUlf Hansson 
1518*e2ad626fSUlf Hansson 	ret = cpr_corner_init(drv);
1519*e2ad626fSUlf Hansson 	if (ret)
1520*e2ad626fSUlf Hansson 		goto unlock;
1521*e2ad626fSUlf Hansson 
1522*e2ad626fSUlf Hansson 	cpr_set_loop_allowed(drv);
1523*e2ad626fSUlf Hansson 
1524*e2ad626fSUlf Hansson 	ret = cpr_init_parameters(drv);
1525*e2ad626fSUlf Hansson 	if (ret)
1526*e2ad626fSUlf Hansson 		goto unlock;
1527*e2ad626fSUlf Hansson 
1528*e2ad626fSUlf Hansson 	/* Configure CPR HW but keep it disabled */
1529*e2ad626fSUlf Hansson 	ret = cpr_config(drv);
1530*e2ad626fSUlf Hansson 	if (ret)
1531*e2ad626fSUlf Hansson 		goto unlock;
1532*e2ad626fSUlf Hansson 
1533*e2ad626fSUlf Hansson 	ret = cpr_find_initial_corner(drv);
1534*e2ad626fSUlf Hansson 	if (ret)
1535*e2ad626fSUlf Hansson 		goto unlock;
1536*e2ad626fSUlf Hansson 
1537*e2ad626fSUlf Hansson 	if (acc_desc->config)
1538*e2ad626fSUlf Hansson 		regmap_multi_reg_write(drv->tcsr, acc_desc->config,
1539*e2ad626fSUlf Hansson 				       acc_desc->num_regs_per_fuse);
1540*e2ad626fSUlf Hansson 
1541*e2ad626fSUlf Hansson 	/* Enable ACC if required */
1542*e2ad626fSUlf Hansson 	if (acc_desc->enable_mask)
1543*e2ad626fSUlf Hansson 		regmap_update_bits(drv->tcsr, acc_desc->enable_reg,
1544*e2ad626fSUlf Hansson 				   acc_desc->enable_mask,
1545*e2ad626fSUlf Hansson 				   acc_desc->enable_mask);
1546*e2ad626fSUlf Hansson 
1547*e2ad626fSUlf Hansson 	dev_info(drv->dev, "driver initialized with %u OPPs\n",
1548*e2ad626fSUlf Hansson 		 drv->num_corners);
1549*e2ad626fSUlf Hansson 
1550*e2ad626fSUlf Hansson unlock:
1551*e2ad626fSUlf Hansson 	mutex_unlock(&drv->lock);
1552*e2ad626fSUlf Hansson 
1553*e2ad626fSUlf Hansson 	return ret;
1554*e2ad626fSUlf Hansson }
1555*e2ad626fSUlf Hansson 
cpr_debug_info_show(struct seq_file * s,void * unused)1556*e2ad626fSUlf Hansson static int cpr_debug_info_show(struct seq_file *s, void *unused)
1557*e2ad626fSUlf Hansson {
1558*e2ad626fSUlf Hansson 	u32 gcnt, ro_sel, ctl, irq_status, reg, error_steps;
1559*e2ad626fSUlf Hansson 	u32 step_dn, step_up, error, error_lt0, busy;
1560*e2ad626fSUlf Hansson 	struct cpr_drv *drv = s->private;
1561*e2ad626fSUlf Hansson 	struct fuse_corner *fuse_corner;
1562*e2ad626fSUlf Hansson 	struct corner *corner;
1563*e2ad626fSUlf Hansson 
1564*e2ad626fSUlf Hansson 	corner = drv->corner;
1565*e2ad626fSUlf Hansson 	fuse_corner = corner->fuse_corner;
1566*e2ad626fSUlf Hansson 
1567*e2ad626fSUlf Hansson 	seq_printf(s, "corner, current_volt = %d uV\n",
1568*e2ad626fSUlf Hansson 		       corner->last_uV);
1569*e2ad626fSUlf Hansson 
1570*e2ad626fSUlf Hansson 	ro_sel = fuse_corner->ring_osc_idx;
1571*e2ad626fSUlf Hansson 	gcnt = cpr_read(drv, REG_RBCPR_GCNT_TARGET(ro_sel));
1572*e2ad626fSUlf Hansson 	seq_printf(s, "rbcpr_gcnt_target (%u) = %#02X\n", ro_sel, gcnt);
1573*e2ad626fSUlf Hansson 
1574*e2ad626fSUlf Hansson 	ctl = cpr_read(drv, REG_RBCPR_CTL);
1575*e2ad626fSUlf Hansson 	seq_printf(s, "rbcpr_ctl = %#02X\n", ctl);
1576*e2ad626fSUlf Hansson 
1577*e2ad626fSUlf Hansson 	irq_status = cpr_read(drv, REG_RBIF_IRQ_STATUS);
1578*e2ad626fSUlf Hansson 	seq_printf(s, "rbcpr_irq_status = %#02X\n", irq_status);
1579*e2ad626fSUlf Hansson 
1580*e2ad626fSUlf Hansson 	reg = cpr_read(drv, REG_RBCPR_RESULT_0);
1581*e2ad626fSUlf Hansson 	seq_printf(s, "rbcpr_result_0 = %#02X\n", reg);
1582*e2ad626fSUlf Hansson 
1583*e2ad626fSUlf Hansson 	step_dn = reg & 0x01;
1584*e2ad626fSUlf Hansson 	step_up = (reg >> RBCPR_RESULT0_STEP_UP_SHIFT) & 0x01;
1585*e2ad626fSUlf Hansson 	seq_printf(s, "  [step_dn = %u", step_dn);
1586*e2ad626fSUlf Hansson 
1587*e2ad626fSUlf Hansson 	seq_printf(s, ", step_up = %u", step_up);
1588*e2ad626fSUlf Hansson 
1589*e2ad626fSUlf Hansson 	error_steps = (reg >> RBCPR_RESULT0_ERROR_STEPS_SHIFT)
1590*e2ad626fSUlf Hansson 				& RBCPR_RESULT0_ERROR_STEPS_MASK;
1591*e2ad626fSUlf Hansson 	seq_printf(s, ", error_steps = %u", error_steps);
1592*e2ad626fSUlf Hansson 
1593*e2ad626fSUlf Hansson 	error = (reg >> RBCPR_RESULT0_ERROR_SHIFT) & RBCPR_RESULT0_ERROR_MASK;
1594*e2ad626fSUlf Hansson 	seq_printf(s, ", error = %u", error);
1595*e2ad626fSUlf Hansson 
1596*e2ad626fSUlf Hansson 	error_lt0 = (reg >> RBCPR_RESULT0_ERROR_LT0_SHIFT) & 0x01;
1597*e2ad626fSUlf Hansson 	seq_printf(s, ", error_lt_0 = %u", error_lt0);
1598*e2ad626fSUlf Hansson 
1599*e2ad626fSUlf Hansson 	busy = (reg >> RBCPR_RESULT0_BUSY_SHIFT) & 0x01;
1600*e2ad626fSUlf Hansson 	seq_printf(s, ", busy = %u]\n", busy);
1601*e2ad626fSUlf Hansson 
1602*e2ad626fSUlf Hansson 	return 0;
1603*e2ad626fSUlf Hansson }
1604*e2ad626fSUlf Hansson DEFINE_SHOW_ATTRIBUTE(cpr_debug_info);
1605*e2ad626fSUlf Hansson 
cpr_debugfs_init(struct cpr_drv * drv)1606*e2ad626fSUlf Hansson static void cpr_debugfs_init(struct cpr_drv *drv)
1607*e2ad626fSUlf Hansson {
1608*e2ad626fSUlf Hansson 	drv->debugfs = debugfs_create_dir("qcom_cpr", NULL);
1609*e2ad626fSUlf Hansson 
1610*e2ad626fSUlf Hansson 	debugfs_create_file("debug_info", 0444, drv->debugfs,
1611*e2ad626fSUlf Hansson 			    drv, &cpr_debug_info_fops);
1612*e2ad626fSUlf Hansson }
1613*e2ad626fSUlf Hansson 
cpr_probe(struct platform_device * pdev)1614*e2ad626fSUlf Hansson static int cpr_probe(struct platform_device *pdev)
1615*e2ad626fSUlf Hansson {
1616*e2ad626fSUlf Hansson 	struct device *dev = &pdev->dev;
1617*e2ad626fSUlf Hansson 	struct cpr_drv *drv;
1618*e2ad626fSUlf Hansson 	int irq, ret;
1619*e2ad626fSUlf Hansson 	const struct cpr_acc_desc *data;
1620*e2ad626fSUlf Hansson 	struct device_node *np;
1621*e2ad626fSUlf Hansson 	u32 cpr_rev = FUSE_REVISION_UNKNOWN;
1622*e2ad626fSUlf Hansson 
1623*e2ad626fSUlf Hansson 	data = of_device_get_match_data(dev);
1624*e2ad626fSUlf Hansson 	if (!data || !data->cpr_desc || !data->acc_desc)
1625*e2ad626fSUlf Hansson 		return -EINVAL;
1626*e2ad626fSUlf Hansson 
1627*e2ad626fSUlf Hansson 	drv = devm_kzalloc(dev, sizeof(*drv), GFP_KERNEL);
1628*e2ad626fSUlf Hansson 	if (!drv)
1629*e2ad626fSUlf Hansson 		return -ENOMEM;
1630*e2ad626fSUlf Hansson 	drv->dev = dev;
1631*e2ad626fSUlf Hansson 	drv->desc = data->cpr_desc;
1632*e2ad626fSUlf Hansson 	drv->acc_desc = data->acc_desc;
1633*e2ad626fSUlf Hansson 
1634*e2ad626fSUlf Hansson 	drv->fuse_corners = devm_kcalloc(dev, drv->desc->num_fuse_corners,
1635*e2ad626fSUlf Hansson 					 sizeof(*drv->fuse_corners),
1636*e2ad626fSUlf Hansson 					 GFP_KERNEL);
1637*e2ad626fSUlf Hansson 	if (!drv->fuse_corners)
1638*e2ad626fSUlf Hansson 		return -ENOMEM;
1639*e2ad626fSUlf Hansson 
1640*e2ad626fSUlf Hansson 	np = of_parse_phandle(dev->of_node, "acc-syscon", 0);
1641*e2ad626fSUlf Hansson 	if (!np)
1642*e2ad626fSUlf Hansson 		return -ENODEV;
1643*e2ad626fSUlf Hansson 
1644*e2ad626fSUlf Hansson 	drv->tcsr = syscon_node_to_regmap(np);
1645*e2ad626fSUlf Hansson 	of_node_put(np);
1646*e2ad626fSUlf Hansson 	if (IS_ERR(drv->tcsr))
1647*e2ad626fSUlf Hansson 		return PTR_ERR(drv->tcsr);
1648*e2ad626fSUlf Hansson 
1649*e2ad626fSUlf Hansson 	drv->base = devm_platform_ioremap_resource(pdev, 0);
1650*e2ad626fSUlf Hansson 	if (IS_ERR(drv->base))
1651*e2ad626fSUlf Hansson 		return PTR_ERR(drv->base);
1652*e2ad626fSUlf Hansson 
1653*e2ad626fSUlf Hansson 	irq = platform_get_irq(pdev, 0);
1654*e2ad626fSUlf Hansson 	if (irq < 0)
1655*e2ad626fSUlf Hansson 		return -EINVAL;
1656*e2ad626fSUlf Hansson 
1657*e2ad626fSUlf Hansson 	drv->vdd_apc = devm_regulator_get(dev, "vdd-apc");
1658*e2ad626fSUlf Hansson 	if (IS_ERR(drv->vdd_apc))
1659*e2ad626fSUlf Hansson 		return PTR_ERR(drv->vdd_apc);
1660*e2ad626fSUlf Hansson 
1661*e2ad626fSUlf Hansson 	/*
1662*e2ad626fSUlf Hansson 	 * Initialize fuse corners, since it simply depends
1663*e2ad626fSUlf Hansson 	 * on data in efuses.
1664*e2ad626fSUlf Hansson 	 * Everything related to (virtual) corners has to be
1665*e2ad626fSUlf Hansson 	 * initialized after attaching to the power domain,
1666*e2ad626fSUlf Hansson 	 * since it depends on the CPU's OPP table.
1667*e2ad626fSUlf Hansson 	 */
1668*e2ad626fSUlf Hansson 	ret = nvmem_cell_read_variable_le_u32(dev, "cpr_fuse_revision", &cpr_rev);
1669*e2ad626fSUlf Hansson 	if (ret)
1670*e2ad626fSUlf Hansson 		return ret;
1671*e2ad626fSUlf Hansson 
1672*e2ad626fSUlf Hansson 	drv->cpr_fuses = cpr_get_fuses(drv);
1673*e2ad626fSUlf Hansson 	if (IS_ERR(drv->cpr_fuses))
1674*e2ad626fSUlf Hansson 		return PTR_ERR(drv->cpr_fuses);
1675*e2ad626fSUlf Hansson 
1676*e2ad626fSUlf Hansson 	ret = cpr_populate_ring_osc_idx(drv);
1677*e2ad626fSUlf Hansson 	if (ret)
1678*e2ad626fSUlf Hansson 		return ret;
1679*e2ad626fSUlf Hansson 
1680*e2ad626fSUlf Hansson 	ret = cpr_fuse_corner_init(drv);
1681*e2ad626fSUlf Hansson 	if (ret)
1682*e2ad626fSUlf Hansson 		return ret;
1683*e2ad626fSUlf Hansson 
1684*e2ad626fSUlf Hansson 	mutex_init(&drv->lock);
1685*e2ad626fSUlf Hansson 
1686*e2ad626fSUlf Hansson 	ret = devm_request_threaded_irq(dev, irq, NULL,
1687*e2ad626fSUlf Hansson 					cpr_irq_handler,
1688*e2ad626fSUlf Hansson 					IRQF_ONESHOT | IRQF_TRIGGER_RISING,
1689*e2ad626fSUlf Hansson 					"cpr", drv);
1690*e2ad626fSUlf Hansson 	if (ret)
1691*e2ad626fSUlf Hansson 		return ret;
1692*e2ad626fSUlf Hansson 
1693*e2ad626fSUlf Hansson 	drv->pd.name = devm_kstrdup_const(dev, dev->of_node->full_name,
1694*e2ad626fSUlf Hansson 					  GFP_KERNEL);
1695*e2ad626fSUlf Hansson 	if (!drv->pd.name)
1696*e2ad626fSUlf Hansson 		return -EINVAL;
1697*e2ad626fSUlf Hansson 
1698*e2ad626fSUlf Hansson 	drv->pd.power_off = cpr_power_off;
1699*e2ad626fSUlf Hansson 	drv->pd.power_on = cpr_power_on;
1700*e2ad626fSUlf Hansson 	drv->pd.set_performance_state = cpr_set_performance_state;
1701*e2ad626fSUlf Hansson 	drv->pd.opp_to_performance_state = cpr_get_performance_state;
1702*e2ad626fSUlf Hansson 	drv->pd.attach_dev = cpr_pd_attach_dev;
1703*e2ad626fSUlf Hansson 
1704*e2ad626fSUlf Hansson 	ret = pm_genpd_init(&drv->pd, NULL, true);
1705*e2ad626fSUlf Hansson 	if (ret)
1706*e2ad626fSUlf Hansson 		return ret;
1707*e2ad626fSUlf Hansson 
1708*e2ad626fSUlf Hansson 	ret = of_genpd_add_provider_simple(dev->of_node, &drv->pd);
1709*e2ad626fSUlf Hansson 	if (ret)
1710*e2ad626fSUlf Hansson 		goto err_remove_genpd;
1711*e2ad626fSUlf Hansson 
1712*e2ad626fSUlf Hansson 	platform_set_drvdata(pdev, drv);
1713*e2ad626fSUlf Hansson 	cpr_debugfs_init(drv);
1714*e2ad626fSUlf Hansson 
1715*e2ad626fSUlf Hansson 	return 0;
1716*e2ad626fSUlf Hansson 
1717*e2ad626fSUlf Hansson err_remove_genpd:
1718*e2ad626fSUlf Hansson 	pm_genpd_remove(&drv->pd);
1719*e2ad626fSUlf Hansson 	return ret;
1720*e2ad626fSUlf Hansson }
1721*e2ad626fSUlf Hansson 
cpr_remove(struct platform_device * pdev)1722*e2ad626fSUlf Hansson static int cpr_remove(struct platform_device *pdev)
1723*e2ad626fSUlf Hansson {
1724*e2ad626fSUlf Hansson 	struct cpr_drv *drv = platform_get_drvdata(pdev);
1725*e2ad626fSUlf Hansson 
1726*e2ad626fSUlf Hansson 	if (cpr_is_allowed(drv)) {
1727*e2ad626fSUlf Hansson 		cpr_ctl_disable(drv);
1728*e2ad626fSUlf Hansson 		cpr_irq_set(drv, 0);
1729*e2ad626fSUlf Hansson 	}
1730*e2ad626fSUlf Hansson 
1731*e2ad626fSUlf Hansson 	of_genpd_del_provider(pdev->dev.of_node);
1732*e2ad626fSUlf Hansson 	pm_genpd_remove(&drv->pd);
1733*e2ad626fSUlf Hansson 
1734*e2ad626fSUlf Hansson 	debugfs_remove_recursive(drv->debugfs);
1735*e2ad626fSUlf Hansson 
1736*e2ad626fSUlf Hansson 	return 0;
1737*e2ad626fSUlf Hansson }
1738*e2ad626fSUlf Hansson 
1739*e2ad626fSUlf Hansson static const struct of_device_id cpr_match_table[] = {
1740*e2ad626fSUlf Hansson 	{ .compatible = "qcom,qcs404-cpr", .data = &qcs404_cpr_acc_desc },
1741*e2ad626fSUlf Hansson 	{ }
1742*e2ad626fSUlf Hansson };
1743*e2ad626fSUlf Hansson MODULE_DEVICE_TABLE(of, cpr_match_table);
1744*e2ad626fSUlf Hansson 
1745*e2ad626fSUlf Hansson static struct platform_driver cpr_driver = {
1746*e2ad626fSUlf Hansson 	.probe		= cpr_probe,
1747*e2ad626fSUlf Hansson 	.remove		= cpr_remove,
1748*e2ad626fSUlf Hansson 	.driver		= {
1749*e2ad626fSUlf Hansson 		.name	= "qcom-cpr",
1750*e2ad626fSUlf Hansson 		.of_match_table = cpr_match_table,
1751*e2ad626fSUlf Hansson 	},
1752*e2ad626fSUlf Hansson };
1753*e2ad626fSUlf Hansson module_platform_driver(cpr_driver);
1754*e2ad626fSUlf Hansson 
1755*e2ad626fSUlf Hansson MODULE_DESCRIPTION("Core Power Reduction (CPR) driver");
1756*e2ad626fSUlf Hansson MODULE_LICENSE("GPL v2");
1757