1/*
2 * OMAP Smartreflex Defines and Routines
3 *
4 * Author: Thara Gopinath	<thara@ti.com>
5 *
6 * Copyright (C) 2010 Texas Instruments, Inc.
7 * Thara Gopinath <thara@ti.com>
8 *
9 * Copyright (C) 2008 Nokia Corporation
10 * Kalle Jokiniemi
11 *
12 * Copyright (C) 2007 Texas Instruments, Inc.
13 * Lesly A M <x0080970@ti.com>
14 *
15 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License version 2 as
17 * published by the Free Software Foundation.
18 */
19
20#ifndef __POWER_SMARTREFLEX_H
21#define __POWER_SMARTREFLEX_H
22
23#include <linux/types.h>
24#include <linux/platform_device.h>
25#include <linux/delay.h>
26#include <linux/platform_data/voltage-omap.h>
27
28/*
29 * Different Smartreflex IPs version. The v1 is the 65nm version used in
30 * OMAP3430. The v2 is the update for the 45nm version of the IP
31 * used in OMAP3630 and OMAP4430
32 */
33#define SR_TYPE_V1	1
34#define SR_TYPE_V2	2
35
36/* SMART REFLEX REG ADDRESS OFFSET */
37#define SRCONFIG		0x00
38#define SRSTATUS		0x04
39#define SENVAL			0x08
40#define SENMIN			0x0C
41#define SENMAX			0x10
42#define SENAVG			0x14
43#define AVGWEIGHT		0x18
44#define NVALUERECIPROCAL	0x1c
45#define SENERROR_V1		0x20
46#define ERRCONFIG_V1		0x24
47#define IRQ_EOI			0x20
48#define IRQSTATUS_RAW		0x24
49#define IRQSTATUS		0x28
50#define IRQENABLE_SET		0x2C
51#define IRQENABLE_CLR		0x30
52#define SENERROR_V2		0x34
53#define ERRCONFIG_V2		0x38
54
55/* Bit/Shift Positions */
56
57/* SRCONFIG */
58#define SRCONFIG_ACCUMDATA_SHIFT	22
59#define SRCONFIG_SRCLKLENGTH_SHIFT	12
60#define SRCONFIG_SENNENABLE_V1_SHIFT	5
61#define SRCONFIG_SENPENABLE_V1_SHIFT	3
62#define SRCONFIG_SENNENABLE_V2_SHIFT	1
63#define SRCONFIG_SENPENABLE_V2_SHIFT	0
64#define SRCONFIG_CLKCTRL_SHIFT		0
65
66#define SRCONFIG_ACCUMDATA_MASK		(0x3ff << 22)
67
68#define SRCONFIG_SRENABLE		BIT(11)
69#define SRCONFIG_SENENABLE		BIT(10)
70#define SRCONFIG_ERRGEN_EN		BIT(9)
71#define SRCONFIG_MINMAXAVG_EN		BIT(8)
72#define SRCONFIG_DELAYCTRL		BIT(2)
73
74/* AVGWEIGHT */
75#define AVGWEIGHT_SENPAVGWEIGHT_SHIFT	2
76#define AVGWEIGHT_SENNAVGWEIGHT_SHIFT	0
77
78/* NVALUERECIPROCAL */
79#define NVALUERECIPROCAL_SENPGAIN_SHIFT	20
80#define NVALUERECIPROCAL_SENNGAIN_SHIFT	16
81#define NVALUERECIPROCAL_RNSENP_SHIFT	8
82#define NVALUERECIPROCAL_RNSENN_SHIFT	0
83
84/* ERRCONFIG */
85#define ERRCONFIG_ERRWEIGHT_SHIFT	16
86#define ERRCONFIG_ERRMAXLIMIT_SHIFT	8
87#define ERRCONFIG_ERRMINLIMIT_SHIFT	0
88
89#define SR_ERRWEIGHT_MASK		(0x07 << 16)
90#define SR_ERRMAXLIMIT_MASK		(0xff << 8)
91#define SR_ERRMINLIMIT_MASK		(0xff << 0)
92
93#define ERRCONFIG_VPBOUNDINTEN_V1	BIT(31)
94#define ERRCONFIG_VPBOUNDINTST_V1	BIT(30)
95#define	ERRCONFIG_MCUACCUMINTEN		BIT(29)
96#define ERRCONFIG_MCUACCUMINTST		BIT(28)
97#define	ERRCONFIG_MCUVALIDINTEN		BIT(27)
98#define ERRCONFIG_MCUVALIDINTST		BIT(26)
99#define ERRCONFIG_MCUBOUNDINTEN		BIT(25)
100#define	ERRCONFIG_MCUBOUNDINTST		BIT(24)
101#define	ERRCONFIG_MCUDISACKINTEN	BIT(23)
102#define ERRCONFIG_VPBOUNDINTST_V2	BIT(23)
103#define ERRCONFIG_MCUDISACKINTST	BIT(22)
104#define ERRCONFIG_VPBOUNDINTEN_V2	BIT(22)
105
106#define ERRCONFIG_STATUS_V1_MASK	(ERRCONFIG_VPBOUNDINTST_V1 | \
107					ERRCONFIG_MCUACCUMINTST | \
108					ERRCONFIG_MCUVALIDINTST | \
109					ERRCONFIG_MCUBOUNDINTST | \
110					ERRCONFIG_MCUDISACKINTST)
111/* IRQSTATUS */
112#define IRQSTATUS_MCUACCUMINT		BIT(3)
113#define IRQSTATUS_MCVALIDINT		BIT(2)
114#define IRQSTATUS_MCBOUNDSINT		BIT(1)
115#define IRQSTATUS_MCUDISABLEACKINT	BIT(0)
116
117/* IRQENABLE_SET and IRQENABLE_CLEAR */
118#define IRQENABLE_MCUACCUMINT		BIT(3)
119#define IRQENABLE_MCUVALIDINT		BIT(2)
120#define IRQENABLE_MCUBOUNDSINT		BIT(1)
121#define IRQENABLE_MCUDISABLEACKINT	BIT(0)
122
123/* Common Bit values */
124
125#define SRCLKLENGTH_12MHZ_SYSCLK	0x3c
126#define SRCLKLENGTH_13MHZ_SYSCLK	0x41
127#define SRCLKLENGTH_19MHZ_SYSCLK	0x60
128#define SRCLKLENGTH_26MHZ_SYSCLK	0x82
129#define SRCLKLENGTH_38MHZ_SYSCLK	0xC0
130
131/*
132 * 3430 specific values. Maybe these should be passed from board file or
133 * pmic structures.
134 */
135#define OMAP3430_SR_ACCUMDATA		0x1f4
136
137#define OMAP3430_SR1_SENPAVGWEIGHT	0x03
138#define OMAP3430_SR1_SENNAVGWEIGHT	0x03
139
140#define OMAP3430_SR2_SENPAVGWEIGHT	0x01
141#define OMAP3430_SR2_SENNAVGWEIGHT	0x01
142
143#define OMAP3430_SR_ERRWEIGHT		0x04
144#define OMAP3430_SR_ERRMAXLIMIT		0x02
145
146struct omap_sr {
147	char				*name;
148	struct list_head		node;
149	struct platform_device		*pdev;
150	struct omap_sr_nvalue_table	*nvalue_table;
151	struct voltagedomain		*voltdm;
152	struct dentry			*dbg_dir;
153	unsigned int			irq;
154	int				srid;
155	int				ip_type;
156	int				nvalue_count;
157	bool				autocomp_active;
158	u32				clk_length;
159	u32				err_weight;
160	u32				err_minlimit;
161	u32				err_maxlimit;
162	u32				accum_data;
163	u32				senn_avgweight;
164	u32				senp_avgweight;
165	u32				senp_mod;
166	u32				senn_mod;
167	void __iomem			*base;
168};
169
170/**
171 * test_cond_timeout - busy-loop, testing a condition
172 * @cond: condition to test until it evaluates to true
173 * @timeout: maximum number of microseconds in the timeout
174 * @index: loop index (integer)
175 *
176 * Loop waiting for @cond to become true or until at least @timeout
177 * microseconds have passed.  To use, define some integer @index in the
178 * calling code.  After running, if @index == @timeout, then the loop has
179 * timed out.
180 *
181 * Copied from omap_test_timeout */
182#define sr_test_cond_timeout(cond, timeout, index)		\
183({								\
184	for (index = 0; index < timeout; index++) {		\
185		if (cond)					\
186			break;					\
187		udelay(1);					\
188	}							\
189})
190
191/**
192 * struct omap_sr_pmic_data - Strucutre to be populated by pmic code to pass
193 *				pmic specific info to smartreflex driver
194 *
195 * @sr_pmic_init:	API to initialize smartreflex on the PMIC side.
196 */
197struct omap_sr_pmic_data {
198	void (*sr_pmic_init) (void);
199};
200
201/**
202 * struct omap_smartreflex_dev_attr - Smartreflex Device attribute.
203 *
204 * @sensor_voltdm_name:       Name of voltdomain of SR instance
205 */
206struct omap_smartreflex_dev_attr {
207	const char      *sensor_voltdm_name;
208};
209
210#ifdef CONFIG_POWER_AVS_OMAP
211/*
212 * The smart reflex driver supports CLASS1 CLASS2 and CLASS3 SR.
213 * The smartreflex class driver should pass the class type.
214 * Should be used to populate the class_type field of the
215 * omap_smartreflex_class_data structure.
216 */
217#define SR_CLASS1	0x1
218#define SR_CLASS2	0x2
219#define SR_CLASS3	0x3
220
221/**
222 * struct omap_sr_class_data - Smartreflex class driver info
223 *
224 * @enable:		API to enable a particular class smaartreflex.
225 * @disable:		API to disable a particular class smartreflex.
226 * @configure:		API to configure a particular class smartreflex.
227 * @notify:		API to notify the class driver about an event in SR.
228 *			Not needed for class3.
229 * @notify_flags:	specify the events to be notified to the class driver
230 * @class_type:		specify which smartreflex class.
231 *			Can be used by the SR driver to take any class
232 *			based decisions.
233 */
234struct omap_sr_class_data {
235	int (*enable)(struct omap_sr *sr);
236	int (*disable)(struct omap_sr *sr, int is_volt_reset);
237	int (*configure)(struct omap_sr *sr);
238	int (*notify)(struct omap_sr *sr, u32 status);
239	u8 notify_flags;
240	u8 class_type;
241};
242
243/**
244 * struct omap_sr_nvalue_table	- Smartreflex n-target value info
245 *
246 * @efuse_offs:	  The offset of the efuse where n-target values are stored.
247 * @nvalue:	  The n-target value.
248 * @errminlimit:  The value of the ERRMINLIMIT bitfield for this n-target
249 * @volt_nominal: microvolts DC that the VDD is initially programmed to
250 */
251struct omap_sr_nvalue_table {
252	u32 efuse_offs;
253	u32 nvalue;
254	u32 errminlimit;
255	unsigned long volt_nominal;
256};
257
258/**
259 * struct omap_sr_data - Smartreflex platform data.
260 *
261 * @name:		instance name
262 * @ip_type:		Smartreflex IP type.
263 * @senp_mod:		SENPENABLE value of the sr CONFIG register
264 * @senn_mod:		SENNENABLE value for sr CONFIG register
265 * @err_weight		ERRWEIGHT value of the sr ERRCONFIG register
266 * @err_maxlimit	ERRMAXLIMIT value of the sr ERRCONFIG register
267 * @accum_data		ACCUMDATA value of the sr CONFIG register
268 * @senn_avgweight	SENNAVGWEIGHT value of the sr AVGWEIGHT register
269 * @senp_avgweight	SENPAVGWEIGHT value of the sr AVGWEIGHT register
270 * @nvalue_count:	Number of distinct nvalues in the nvalue table
271 * @enable_on_init:	whether this sr module needs to enabled at
272 *			boot up or not.
273 * @nvalue_table:	table containing the  efuse offsets and nvalues
274 *			corresponding to them.
275 * @voltdm:		Pointer to the voltage domain associated with the SR
276 */
277struct omap_sr_data {
278	const char			*name;
279	int				ip_type;
280	u32				senp_mod;
281	u32				senn_mod;
282	u32				err_weight;
283	u32				err_maxlimit;
284	u32				accum_data;
285	u32				senn_avgweight;
286	u32				senp_avgweight;
287	int				nvalue_count;
288	bool				enable_on_init;
289	struct omap_sr_nvalue_table	*nvalue_table;
290	struct voltagedomain		*voltdm;
291};
292
293/* Smartreflex module enable/disable interface */
294void omap_sr_enable(struct voltagedomain *voltdm);
295void omap_sr_disable(struct voltagedomain *voltdm);
296void omap_sr_disable_reset_volt(struct voltagedomain *voltdm);
297
298/* API to register the pmic specific data with the smartreflex driver. */
299void omap_sr_register_pmic(struct omap_sr_pmic_data *pmic_data);
300
301/* Smartreflex driver hooks to be called from Smartreflex class driver */
302int sr_enable(struct omap_sr *sr, unsigned long volt);
303void sr_disable(struct omap_sr *sr);
304int sr_configure_errgen(struct omap_sr *sr);
305int sr_disable_errgen(struct omap_sr *sr);
306int sr_configure_minmax(struct omap_sr *sr);
307
308/* API to register the smartreflex class driver with the smartreflex driver */
309int sr_register_class(struct omap_sr_class_data *class_data);
310#else
311static inline void omap_sr_enable(struct voltagedomain *voltdm) {}
312static inline void omap_sr_disable(struct voltagedomain *voltdm) {}
313static inline void omap_sr_disable_reset_volt(
314		struct voltagedomain *voltdm) {}
315static inline void omap_sr_register_pmic(
316		struct omap_sr_pmic_data *pmic_data) {}
317#endif
318#endif
319