1f9dca0f0SNishanth Menon /* SPDX-License-Identifier: GPL-2.0 */
2b86aeafcSJean Pihet /*
3b86aeafcSJean Pihet  * OMAP Smartreflex Defines and Routines
4b86aeafcSJean Pihet  *
5b86aeafcSJean Pihet  * Author: Thara Gopinath	<[email protected]>
6b86aeafcSJean Pihet  *
7b86aeafcSJean Pihet  * Copyright (C) 2010 Texas Instruments, Inc.
8b86aeafcSJean Pihet  * Thara Gopinath <[email protected]>
9b86aeafcSJean Pihet  *
10b86aeafcSJean Pihet  * Copyright (C) 2008 Nokia Corporation
11b86aeafcSJean Pihet  * Kalle Jokiniemi
12b86aeafcSJean Pihet  *
13b86aeafcSJean Pihet  * Copyright (C) 2007 Texas Instruments, Inc.
14b86aeafcSJean Pihet  * Lesly A M <[email protected]>
15b86aeafcSJean Pihet  */
16b86aeafcSJean Pihet 
17b86aeafcSJean Pihet #ifndef __POWER_SMARTREFLEX_H
18b86aeafcSJean Pihet #define __POWER_SMARTREFLEX_H
19b86aeafcSJean Pihet 
20b86aeafcSJean Pihet #include <linux/types.h>
21b86aeafcSJean Pihet #include <linux/platform_device.h>
2250e4a7d0SJean Pihet #include <linux/delay.h>
232203747cSArnd Bergmann #include <linux/platform_data/voltage-omap.h>
24b86aeafcSJean Pihet 
25b86aeafcSJean Pihet /*
26b86aeafcSJean Pihet  * Different Smartreflex IPs version. The v1 is the 65nm version used in
27b86aeafcSJean Pihet  * OMAP3430. The v2 is the update for the 45nm version of the IP
28b86aeafcSJean Pihet  * used in OMAP3630 and OMAP4430
29b86aeafcSJean Pihet  */
30b86aeafcSJean Pihet #define SR_TYPE_V1	1
31b86aeafcSJean Pihet #define SR_TYPE_V2	2
32b86aeafcSJean Pihet 
33b86aeafcSJean Pihet /* SMART REFLEX REG ADDRESS OFFSET */
34b86aeafcSJean Pihet #define SRCONFIG		0x00
35b86aeafcSJean Pihet #define SRSTATUS		0x04
36b86aeafcSJean Pihet #define SENVAL			0x08
37b86aeafcSJean Pihet #define SENMIN			0x0C
38b86aeafcSJean Pihet #define SENMAX			0x10
39b86aeafcSJean Pihet #define SENAVG			0x14
40b86aeafcSJean Pihet #define AVGWEIGHT		0x18
41b86aeafcSJean Pihet #define NVALUERECIPROCAL	0x1c
42b86aeafcSJean Pihet #define SENERROR_V1		0x20
43b86aeafcSJean Pihet #define ERRCONFIG_V1		0x24
44b86aeafcSJean Pihet #define IRQ_EOI			0x20
45b86aeafcSJean Pihet #define IRQSTATUS_RAW		0x24
46b86aeafcSJean Pihet #define IRQSTATUS		0x28
47b86aeafcSJean Pihet #define IRQENABLE_SET		0x2C
48b86aeafcSJean Pihet #define IRQENABLE_CLR		0x30
49b86aeafcSJean Pihet #define SENERROR_V2		0x34
50b86aeafcSJean Pihet #define ERRCONFIG_V2		0x38
51b86aeafcSJean Pihet 
52b86aeafcSJean Pihet /* Bit/Shift Positions */
53b86aeafcSJean Pihet 
54b86aeafcSJean Pihet /* SRCONFIG */
55b86aeafcSJean Pihet #define SRCONFIG_ACCUMDATA_SHIFT	22
56b86aeafcSJean Pihet #define SRCONFIG_SRCLKLENGTH_SHIFT	12
57b86aeafcSJean Pihet #define SRCONFIG_SENNENABLE_V1_SHIFT	5
58b86aeafcSJean Pihet #define SRCONFIG_SENPENABLE_V1_SHIFT	3
59b86aeafcSJean Pihet #define SRCONFIG_SENNENABLE_V2_SHIFT	1
60b86aeafcSJean Pihet #define SRCONFIG_SENPENABLE_V2_SHIFT	0
61b86aeafcSJean Pihet #define SRCONFIG_CLKCTRL_SHIFT		0
62b86aeafcSJean Pihet 
63b86aeafcSJean Pihet #define SRCONFIG_ACCUMDATA_MASK		(0x3ff << 22)
64b86aeafcSJean Pihet 
65b86aeafcSJean Pihet #define SRCONFIG_SRENABLE		BIT(11)
66b86aeafcSJean Pihet #define SRCONFIG_SENENABLE		BIT(10)
67b86aeafcSJean Pihet #define SRCONFIG_ERRGEN_EN		BIT(9)
68b86aeafcSJean Pihet #define SRCONFIG_MINMAXAVG_EN		BIT(8)
69b86aeafcSJean Pihet #define SRCONFIG_DELAYCTRL		BIT(2)
70b86aeafcSJean Pihet 
71b86aeafcSJean Pihet /* AVGWEIGHT */
72b86aeafcSJean Pihet #define AVGWEIGHT_SENPAVGWEIGHT_SHIFT	2
73b86aeafcSJean Pihet #define AVGWEIGHT_SENNAVGWEIGHT_SHIFT	0
74b86aeafcSJean Pihet 
75b86aeafcSJean Pihet /* NVALUERECIPROCAL */
76b86aeafcSJean Pihet #define NVALUERECIPROCAL_SENPGAIN_SHIFT	20
77b86aeafcSJean Pihet #define NVALUERECIPROCAL_SENNGAIN_SHIFT	16
78b86aeafcSJean Pihet #define NVALUERECIPROCAL_RNSENP_SHIFT	8
79b86aeafcSJean Pihet #define NVALUERECIPROCAL_RNSENN_SHIFT	0
80b86aeafcSJean Pihet 
81b86aeafcSJean Pihet /* ERRCONFIG */
82b86aeafcSJean Pihet #define ERRCONFIG_ERRWEIGHT_SHIFT	16
83b86aeafcSJean Pihet #define ERRCONFIG_ERRMAXLIMIT_SHIFT	8
84b86aeafcSJean Pihet #define ERRCONFIG_ERRMINLIMIT_SHIFT	0
85b86aeafcSJean Pihet 
86b86aeafcSJean Pihet #define SR_ERRWEIGHT_MASK		(0x07 << 16)
87b86aeafcSJean Pihet #define SR_ERRMAXLIMIT_MASK		(0xff << 8)
88b86aeafcSJean Pihet #define SR_ERRMINLIMIT_MASK		(0xff << 0)
89b86aeafcSJean Pihet 
90b86aeafcSJean Pihet #define ERRCONFIG_VPBOUNDINTEN_V1	BIT(31)
91b86aeafcSJean Pihet #define ERRCONFIG_VPBOUNDINTST_V1	BIT(30)
92b86aeafcSJean Pihet #define	ERRCONFIG_MCUACCUMINTEN		BIT(29)
93b86aeafcSJean Pihet #define ERRCONFIG_MCUACCUMINTST		BIT(28)
94b86aeafcSJean Pihet #define	ERRCONFIG_MCUVALIDINTEN		BIT(27)
95b86aeafcSJean Pihet #define ERRCONFIG_MCUVALIDINTST		BIT(26)
96b86aeafcSJean Pihet #define ERRCONFIG_MCUBOUNDINTEN		BIT(25)
97b86aeafcSJean Pihet #define	ERRCONFIG_MCUBOUNDINTST		BIT(24)
98b86aeafcSJean Pihet #define	ERRCONFIG_MCUDISACKINTEN	BIT(23)
99b86aeafcSJean Pihet #define ERRCONFIG_VPBOUNDINTST_V2	BIT(23)
100b86aeafcSJean Pihet #define ERRCONFIG_MCUDISACKINTST	BIT(22)
101b86aeafcSJean Pihet #define ERRCONFIG_VPBOUNDINTEN_V2	BIT(22)
102b86aeafcSJean Pihet 
103b86aeafcSJean Pihet #define ERRCONFIG_STATUS_V1_MASK	(ERRCONFIG_VPBOUNDINTST_V1 | \
104b86aeafcSJean Pihet 					ERRCONFIG_MCUACCUMINTST | \
105b86aeafcSJean Pihet 					ERRCONFIG_MCUVALIDINTST | \
106b86aeafcSJean Pihet 					ERRCONFIG_MCUBOUNDINTST | \
107b86aeafcSJean Pihet 					ERRCONFIG_MCUDISACKINTST)
108b86aeafcSJean Pihet /* IRQSTATUS */
109b86aeafcSJean Pihet #define IRQSTATUS_MCUACCUMINT		BIT(3)
110b86aeafcSJean Pihet #define IRQSTATUS_MCVALIDINT		BIT(2)
111b86aeafcSJean Pihet #define IRQSTATUS_MCBOUNDSINT		BIT(1)
112b86aeafcSJean Pihet #define IRQSTATUS_MCUDISABLEACKINT	BIT(0)
113b86aeafcSJean Pihet 
114b86aeafcSJean Pihet /* IRQENABLE_SET and IRQENABLE_CLEAR */
115b86aeafcSJean Pihet #define IRQENABLE_MCUACCUMINT		BIT(3)
116b86aeafcSJean Pihet #define IRQENABLE_MCUVALIDINT		BIT(2)
117b86aeafcSJean Pihet #define IRQENABLE_MCUBOUNDSINT		BIT(1)
118b86aeafcSJean Pihet #define IRQENABLE_MCUDISABLEACKINT	BIT(0)
119b86aeafcSJean Pihet 
120b86aeafcSJean Pihet /* Common Bit values */
121b86aeafcSJean Pihet 
122b86aeafcSJean Pihet #define SRCLKLENGTH_12MHZ_SYSCLK	0x3c
123b86aeafcSJean Pihet #define SRCLKLENGTH_13MHZ_SYSCLK	0x41
124b86aeafcSJean Pihet #define SRCLKLENGTH_19MHZ_SYSCLK	0x60
125b86aeafcSJean Pihet #define SRCLKLENGTH_26MHZ_SYSCLK	0x82
126b86aeafcSJean Pihet #define SRCLKLENGTH_38MHZ_SYSCLK	0xC0
127b86aeafcSJean Pihet 
128b86aeafcSJean Pihet /*
129b86aeafcSJean Pihet  * 3430 specific values. Maybe these should be passed from board file or
130b86aeafcSJean Pihet  * pmic structures.
131b86aeafcSJean Pihet  */
132b86aeafcSJean Pihet #define OMAP3430_SR_ACCUMDATA		0x1f4
133b86aeafcSJean Pihet 
134b86aeafcSJean Pihet #define OMAP3430_SR1_SENPAVGWEIGHT	0x03
135b86aeafcSJean Pihet #define OMAP3430_SR1_SENNAVGWEIGHT	0x03
136b86aeafcSJean Pihet 
137b86aeafcSJean Pihet #define OMAP3430_SR2_SENPAVGWEIGHT	0x01
138b86aeafcSJean Pihet #define OMAP3430_SR2_SENNAVGWEIGHT	0x01
139b86aeafcSJean Pihet 
140b86aeafcSJean Pihet #define OMAP3430_SR_ERRWEIGHT		0x04
141b86aeafcSJean Pihet #define OMAP3430_SR_ERRMAXLIMIT		0x02
142b86aeafcSJean Pihet 
143d060b405STony Lindgren enum sr_instance {
144d060b405STony Lindgren 	OMAP_SR_MPU,			/* shared with iva on omap3 */
145d060b405STony Lindgren 	OMAP_SR_CORE,
146d060b405STony Lindgren 	OMAP_SR_IVA,
147d060b405STony Lindgren 	OMAP_SR_NR,
148d060b405STony Lindgren };
149d060b405STony Lindgren 
15080821c9cSJean Pihet struct omap_sr {
1518b765d72SJean Pihet 	char				*name;
15280821c9cSJean Pihet 	struct list_head		node;
15380821c9cSJean Pihet 	struct platform_device		*pdev;
15480821c9cSJean Pihet 	struct omap_sr_nvalue_table	*nvalue_table;
15580821c9cSJean Pihet 	struct voltagedomain		*voltdm;
15680821c9cSJean Pihet 	struct dentry			*dbg_dir;
15780821c9cSJean Pihet 	unsigned int			irq;
158*ed4520d6STony Lindgren 	struct clk			*fck;
15980821c9cSJean Pihet 	int				srid;
16080821c9cSJean Pihet 	int				ip_type;
16180821c9cSJean Pihet 	int				nvalue_count;
16280821c9cSJean Pihet 	bool				autocomp_active;
16380821c9cSJean Pihet 	u32				clk_length;
16480821c9cSJean Pihet 	u32				err_weight;
16580821c9cSJean Pihet 	u32				err_minlimit;
16680821c9cSJean Pihet 	u32				err_maxlimit;
16780821c9cSJean Pihet 	u32				accum_data;
16880821c9cSJean Pihet 	u32				senn_avgweight;
16980821c9cSJean Pihet 	u32				senp_avgweight;
17080821c9cSJean Pihet 	u32				senp_mod;
17180821c9cSJean Pihet 	u32				senn_mod;
17280821c9cSJean Pihet 	void __iomem			*base;
173*ed4520d6STony Lindgren 	unsigned long			enabled:1;
17480821c9cSJean Pihet };
17580821c9cSJean Pihet 
176b86aeafcSJean Pihet /**
17750e4a7d0SJean Pihet  * test_cond_timeout - busy-loop, testing a condition
17850e4a7d0SJean Pihet  * @cond: condition to test until it evaluates to true
17950e4a7d0SJean Pihet  * @timeout: maximum number of microseconds in the timeout
18050e4a7d0SJean Pihet  * @index: loop index (integer)
18150e4a7d0SJean Pihet  *
18250e4a7d0SJean Pihet  * Loop waiting for @cond to become true or until at least @timeout
18350e4a7d0SJean Pihet  * microseconds have passed.  To use, define some integer @index in the
18450e4a7d0SJean Pihet  * calling code.  After running, if @index == @timeout, then the loop has
18550e4a7d0SJean Pihet  * timed out.
18650e4a7d0SJean Pihet  *
18750e4a7d0SJean Pihet  * Copied from omap_test_timeout */
18850e4a7d0SJean Pihet #define sr_test_cond_timeout(cond, timeout, index)		\
18950e4a7d0SJean Pihet ({								\
19050e4a7d0SJean Pihet 	for (index = 0; index < timeout; index++) {		\
19150e4a7d0SJean Pihet 		if (cond)					\
19250e4a7d0SJean Pihet 			break;					\
19350e4a7d0SJean Pihet 		udelay(1);					\
19450e4a7d0SJean Pihet 	}							\
19550e4a7d0SJean Pihet })
19650e4a7d0SJean Pihet 
19750e4a7d0SJean Pihet /**
198b86aeafcSJean Pihet  * struct omap_sr_pmic_data - Strucutre to be populated by pmic code to pass
199b86aeafcSJean Pihet  *				pmic specific info to smartreflex driver
200b86aeafcSJean Pihet  *
201b86aeafcSJean Pihet  * @sr_pmic_init:	API to initialize smartreflex on the PMIC side.
202b86aeafcSJean Pihet  */
203b86aeafcSJean Pihet struct omap_sr_pmic_data {
204b86aeafcSJean Pihet 	void (*sr_pmic_init) (void);
205b86aeafcSJean Pihet };
206b86aeafcSJean Pihet 
207b86aeafcSJean Pihet /**
208b86aeafcSJean Pihet  * struct omap_smartreflex_dev_attr - Smartreflex Device attribute.
209b86aeafcSJean Pihet  *
210b86aeafcSJean Pihet  * @sensor_voltdm_name:       Name of voltdomain of SR instance
211b86aeafcSJean Pihet  */
212b86aeafcSJean Pihet struct omap_smartreflex_dev_attr {
213b86aeafcSJean Pihet 	const char      *sensor_voltdm_name;
214b86aeafcSJean Pihet };
215b86aeafcSJean Pihet 
216b86aeafcSJean Pihet /*
217b86aeafcSJean Pihet  * The smart reflex driver supports CLASS1 CLASS2 and CLASS3 SR.
218b86aeafcSJean Pihet  * The smartreflex class driver should pass the class type.
219b86aeafcSJean Pihet  * Should be used to populate the class_type field of the
220b86aeafcSJean Pihet  * omap_smartreflex_class_data structure.
221b86aeafcSJean Pihet  */
222b86aeafcSJean Pihet #define SR_CLASS1	0x1
223b86aeafcSJean Pihet #define SR_CLASS2	0x2
224b86aeafcSJean Pihet #define SR_CLASS3	0x3
225b86aeafcSJean Pihet 
226b86aeafcSJean Pihet /**
227b86aeafcSJean Pihet  * struct omap_sr_class_data - Smartreflex class driver info
228b86aeafcSJean Pihet  *
229b86aeafcSJean Pihet  * @enable:		API to enable a particular class smaartreflex.
230b86aeafcSJean Pihet  * @disable:		API to disable a particular class smartreflex.
231b86aeafcSJean Pihet  * @configure:		API to configure a particular class smartreflex.
232b86aeafcSJean Pihet  * @notify:		API to notify the class driver about an event in SR.
233b86aeafcSJean Pihet  *			Not needed for class3.
234b86aeafcSJean Pihet  * @notify_flags:	specify the events to be notified to the class driver
235b86aeafcSJean Pihet  * @class_type:		specify which smartreflex class.
236b86aeafcSJean Pihet  *			Can be used by the SR driver to take any class
237b86aeafcSJean Pihet  *			based decisions.
238b86aeafcSJean Pihet  */
239b86aeafcSJean Pihet struct omap_sr_class_data {
24080821c9cSJean Pihet 	int (*enable)(struct omap_sr *sr);
24180821c9cSJean Pihet 	int (*disable)(struct omap_sr *sr, int is_volt_reset);
24280821c9cSJean Pihet 	int (*configure)(struct omap_sr *sr);
24380821c9cSJean Pihet 	int (*notify)(struct omap_sr *sr, u32 status);
244b86aeafcSJean Pihet 	u8 notify_flags;
245b86aeafcSJean Pihet 	u8 class_type;
246b86aeafcSJean Pihet };
247b86aeafcSJean Pihet 
248b86aeafcSJean Pihet /**
249b86aeafcSJean Pihet  * struct omap_sr_nvalue_table	- Smartreflex n-target value info
250b86aeafcSJean Pihet  *
251b86aeafcSJean Pihet  * @efuse_offs:	  The offset of the efuse where n-target values are stored.
252b86aeafcSJean Pihet  * @nvalue:	  The n-target value.
2535e7f2e12SJean Pihet  * @errminlimit:  The value of the ERRMINLIMIT bitfield for this n-target
2545e7f2e12SJean Pihet  * @volt_nominal: microvolts DC that the VDD is initially programmed to
255b86aeafcSJean Pihet  */
256b86aeafcSJean Pihet struct omap_sr_nvalue_table {
257b86aeafcSJean Pihet 	u32 efuse_offs;
258b86aeafcSJean Pihet 	u32 nvalue;
2595e7f2e12SJean Pihet 	u32 errminlimit;
2605e7f2e12SJean Pihet 	unsigned long volt_nominal;
261b86aeafcSJean Pihet };
262b86aeafcSJean Pihet 
263b86aeafcSJean Pihet /**
264b86aeafcSJean Pihet  * struct omap_sr_data - Smartreflex platform data.
265b86aeafcSJean Pihet  *
2668b765d72SJean Pihet  * @name:		instance name
267b86aeafcSJean Pihet  * @ip_type:		Smartreflex IP type.
26898aed08eSJean Pihet  * @senp_mod:		SENPENABLE value of the sr CONFIG register
26998aed08eSJean Pihet  * @senn_mod:		SENNENABLE value for sr CONFIG register
27098aed08eSJean Pihet  * @err_weight		ERRWEIGHT value of the sr ERRCONFIG register
27198aed08eSJean Pihet  * @err_maxlimit	ERRMAXLIMIT value of the sr ERRCONFIG register
27298aed08eSJean Pihet  * @accum_data		ACCUMDATA value of the sr CONFIG register
27398aed08eSJean Pihet  * @senn_avgweight	SENNAVGWEIGHT value of the sr AVGWEIGHT register
27498aed08eSJean Pihet  * @senp_avgweight	SENPAVGWEIGHT value of the sr AVGWEIGHT register
275b86aeafcSJean Pihet  * @nvalue_count:	Number of distinct nvalues in the nvalue table
276b86aeafcSJean Pihet  * @nvalue_table:	table containing the  efuse offsets and nvalues
277b86aeafcSJean Pihet  *			corresponding to them.
278b86aeafcSJean Pihet  * @voltdm:		Pointer to the voltage domain associated with the SR
279b86aeafcSJean Pihet  */
280b86aeafcSJean Pihet struct omap_sr_data {
2818b765d72SJean Pihet 	const char			*name;
282b86aeafcSJean Pihet 	int				ip_type;
283b86aeafcSJean Pihet 	u32				senp_mod;
284b86aeafcSJean Pihet 	u32				senn_mod;
28598aed08eSJean Pihet 	u32				err_weight;
28698aed08eSJean Pihet 	u32				err_maxlimit;
28798aed08eSJean Pihet 	u32				accum_data;
28898aed08eSJean Pihet 	u32				senn_avgweight;
28998aed08eSJean Pihet 	u32				senp_avgweight;
290b86aeafcSJean Pihet 	int				nvalue_count;
291b86aeafcSJean Pihet 	struct omap_sr_nvalue_table	*nvalue_table;
292b86aeafcSJean Pihet 	struct voltagedomain		*voltdm;
293b86aeafcSJean Pihet };
294b86aeafcSJean Pihet 
2952079fe6eSBen Dooks 
2962079fe6eSBen Dooks extern struct omap_sr_data omap_sr_pdata[OMAP_SR_NR];
2972079fe6eSBen Dooks 
298d060b405STony Lindgren #ifdef CONFIG_POWER_AVS_OMAP
299d060b405STony Lindgren 
300b86aeafcSJean Pihet /* Smartreflex module enable/disable interface */
301b86aeafcSJean Pihet void omap_sr_enable(struct voltagedomain *voltdm);
302b86aeafcSJean Pihet void omap_sr_disable(struct voltagedomain *voltdm);
303b86aeafcSJean Pihet void omap_sr_disable_reset_volt(struct voltagedomain *voltdm);
304b86aeafcSJean Pihet 
305b86aeafcSJean Pihet /* Smartreflex driver hooks to be called from Smartreflex class driver */
306299066bbSAndrii Tseglytskyi int sr_enable(struct omap_sr *sr, unsigned long volt);
307299066bbSAndrii Tseglytskyi void sr_disable(struct omap_sr *sr);
3083dfc35ffSAndrii Tseglytskyi int sr_configure_errgen(struct omap_sr *sr);
3093dfc35ffSAndrii Tseglytskyi int sr_disable_errgen(struct omap_sr *sr);
3106c805734SAndrii Tseglytskyi int sr_configure_minmax(struct omap_sr *sr);
311b86aeafcSJean Pihet 
312b86aeafcSJean Pihet /* API to register the smartreflex class driver with the smartreflex driver */
313b86aeafcSJean Pihet int sr_register_class(struct omap_sr_class_data *class_data);
314b86aeafcSJean Pihet #else
omap_sr_enable(struct voltagedomain * voltdm)315b86aeafcSJean Pihet static inline void omap_sr_enable(struct voltagedomain *voltdm) {}
omap_sr_disable(struct voltagedomain * voltdm)316b86aeafcSJean Pihet static inline void omap_sr_disable(struct voltagedomain *voltdm) {}
omap_sr_disable_reset_volt(struct voltagedomain * voltdm)317b86aeafcSJean Pihet static inline void omap_sr_disable_reset_volt(
318b86aeafcSJean Pihet 		struct voltagedomain *voltdm) {}
319b86aeafcSJean Pihet #endif
320b86aeafcSJean Pihet #endif
321