[glsdk/meta-ti-glsdk.git] / recipes-kernel / linux / linux-am335x-psp-3.2 / 0001-am33xx-Add-SmartReflex-support.patch
1 From 35ae6b61d349e5b4efd1c6337a0d1e23b6e86899 Mon Sep 17 00:00:00 2001
2 From: Greg Guyotte <gguyotte@ti.com>
3 Date: Thu, 7 Jun 2012 18:05:31 -0500
4 Subject: [PATCH] am33xx: Add SmartReflex support.
6 This patch introduces SmartReflex support to AM33XX devices. The
7 purpose of SmartReflex is to optimize (lower) voltage based upon
8 silicon process and temperature.
10 The SmartReflex driver requires the silicon to be programmed with
11 "nTarget" EFUSE values. If the values are not present (as with
12 pre-RTP samples), the driver will simply fail to load and kernel
13 boot will continue normally.
15 The SR driver logs several items in the debugfs at /debug/smartreflex.
16 To disable SmartReflex, use the command 'echo 0 > /debug/smartreflex/autocomp'.
17 The node /debug/smartreflex/smartreflex0 gives information about
18 the CORE voltage domain, and /smartreflex1 is related to the MPU voltage
19 domain.
21 To determine the effectiveness of SmartReflex, you can compare the
22 initial voltage with the current voltage for a given OPP. For example,
23 'cat /debug/smartreflex/smartreflex1/current_voltage' gives the current
24 MPU voltage. Comparing that with 'cat /debug/smartreflex/smartreflex1/
25 initial_voltage' will show you the voltage drop associated with SR
26 operation.
28 Signed-off-by: Greg Guyotte <gguyotte@ti.com>
29 ---
30 arch/arm/mach-omap2/Makefile | 1 +
31 arch/arm/mach-omap2/am33xx-smartreflex-class2.c | 1055 ++++++++++++++++++++
32 arch/arm/mach-omap2/board-am335xevm.c | 7 +
33 arch/arm/mach-omap2/devices.c | 269 +++++
34 arch/arm/mach-omap2/include/mach/board-am335xevm.h | 1 +
35 arch/arm/plat-omap/Kconfig | 21 +
36 arch/arm/plat-omap/include/plat/am33xx.h | 3 +
37 arch/arm/plat-omap/include/plat/smartreflex.h | 431 ++++++++
38 drivers/regulator/core.c | 4 +
39 include/linux/regulator/driver.h | 2 +-
40 include/linux/regulator/machine.h | 3 +-
41 11 files changed, 1795 insertions(+), 2 deletions(-)
42 create mode 100644 arch/arm/mach-omap2/am33xx-smartreflex-class2.c
43 create mode 100644 arch/arm/plat-omap/include/plat/smartreflex.h
45 diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
46 index f275e74..c01b62d 100644
47 --- a/arch/arm/mach-omap2/Makefile
48 +++ b/arch/arm/mach-omap2/Makefile
49 @@ -73,6 +73,7 @@ obj-$(CONFIG_SOC_OMAPAM33XX) += cpuidle33xx.o pm33xx.o \
50 obj-$(CONFIG_PM_DEBUG) += pm-debug.o
51 obj-$(CONFIG_OMAP_SMARTREFLEX) += sr_device.o smartreflex.o
52 obj-$(CONFIG_OMAP_SMARTREFLEX_CLASS3) += smartreflex-class3.o
53 +obj-$(CONFIG_AM33XX_SMARTREFLEX) += am33xx-smartreflex-class2.o
55 AFLAGS_sleep24xx.o :=-Wa,-march=armv6
56 AFLAGS_sleep34xx.o :=-Wa,-march=armv7-a$(plus_sec)
57 diff --git a/arch/arm/mach-omap2/am33xx-smartreflex-class2.c b/arch/arm/mach-omap2/am33xx-smartreflex-class2.c
58 new file mode 100644
59 index 0000000..66f98b7
60 --- /dev/null
61 +++ b/arch/arm/mach-omap2/am33xx-smartreflex-class2.c
62 @@ -0,0 +1,1055 @@
63 +/*
64 + * SmartReflex Voltage Control driver
65 + *
66 + * Copyright (C) 2012 Texas Instruments, Inc. - http://www.ti.com/
67 + * Author: Greg Guyotte <gguyotte@ti.com> (modified for AM33xx)
68 + *
69 + * Copyright (C) 2011 Texas Instruments, Inc. - http://www.ti.com/
70 + * Author: AnilKumar Ch <anilkumar@ti.com>
71 + *
72 + * This program is free software; you can redistribute it and/or
73 + * modify it under the terms of the GNU General Public License as
74 + * published by the Free Software Foundation version 2.
75 + *
76 + * This program is distributed "as is" WITHOUT ANY WARRANTY of any
77 + * kind, whether express or implied; without even the implied warranty
78 + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
79 + * GNU General Public License for more details.
80 + */
81 +
82 +#include <linux/kernel.h>
83 +#include <linux/init.h>
84 +#include <linux/module.h>
85 +#include <linux/interrupt.h>
86 +#include <linux/clk.h>
87 +#include <linux/io.h>
88 +#include <linux/debugfs.h>
89 +#include <linux/slab.h>
90 +#include <linux/regulator/consumer.h>
91 +#include <linux/cpufreq.h>
92 +#include <linux/opp.h>
93 +
94 +#include <plat/common.h>
95 +#include <plat/smartreflex.h>
96 +
97 +#include "control.h"
98 +#include "voltage.h"
99 +
100 +#define CLK_NAME_LEN 40
101 +
102 +static inline void sr_write_reg(struct am33xx_sr *sr, int offset, u32 value,
103 + u32 srid)
104 +{
105 + writel(value, sr->sen[srid].base + offset);
106 +}
107 +
108 +static inline void sr_modify_reg(struct am33xx_sr *sr, int offset, u32 mask,
109 + u32 value, u32 srid)
110 +{
111 + u32 reg_val;
112 +
113 + reg_val = readl(sr->sen[srid].base + offset);
114 + reg_val &= ~mask;
115 + reg_val |= (value&mask);
116 +
117 + writel(reg_val, sr->sen[srid].base + offset);
118 +}
119 +
120 +static inline u32 sr_read_reg(struct am33xx_sr *sr, int offset, u32 srid)
121 +{
122 + return readl(sr->sen[srid].base + offset);
123 +}
124 +
125 +static void cal_reciprocal(u32 sensor, u32 *sengain, u32 *rnsen) {
126 + u32 gn, rn, mul;
127 +
128 + for (gn = 0; gn < GAIN_MAXLIMIT; gn++) {
129 + mul = 1 << (gn + 8);
130 + rn = mul / sensor;
131 + if (rn < R_MAXLIMIT) {
132 + *sengain = gn;
133 + *rnsen = rn;
134 + }
135 + }
136 +}
137 +
138 +static u32 cal_test_nvalue(u32 sennval, u32 senpval) {
139 + u32 senpgain=0, senngain=0;
140 + u32 rnsenp=0, rnsenn=0;
141 +
142 + /* Calculating the gain and reciprocal of the SenN and SenP values */
143 + cal_reciprocal(senpval, &senpgain, &rnsenp);
144 + cal_reciprocal(sennval, &senngain, &rnsenn);
145 +
146 + return (senpgain << NVALUERECIPROCAL_SENPGAIN_SHIFT) |
147 + (senngain << NVALUERECIPROCAL_SENNGAIN_SHIFT) |
148 + (rnsenp << NVALUERECIPROCAL_RNSENP_SHIFT) |
149 + (rnsenn << NVALUERECIPROCAL_RNSENN_SHIFT);
150 +}
151 +
152 +static unsigned int sr_adjust_efuse_nvalue(unsigned int opp_no,
153 + unsigned int orig_opp_nvalue,
154 + unsigned int mv_delta) {
155 + unsigned int new_opp_nvalue;
156 + unsigned int senp_gain, senn_gain, rnsenp, rnsenn, pnt_delta, nnt_delta;
157 + unsigned int new_senn, new_senp, senn, senp;
158 +
159 + /* calculate SenN and SenP from the efuse value */
160 + senp_gain = ((orig_opp_nvalue >> 20) & 0xf);
161 + senn_gain = ((orig_opp_nvalue >> 16) & 0xf);
162 + rnsenp = ((orig_opp_nvalue >> 8) & 0xff);
163 + rnsenn = (orig_opp_nvalue & 0xff);
164 +
165 + senp = ((1<<(senp_gain+8))/(rnsenp));
166 + senn = ((1<<(senn_gain+8))/(rnsenn));
167 +
168 + /* calculate the voltage delta */
169 + pnt_delta = (26 * mv_delta)/10;
170 + nnt_delta = (3 * mv_delta);
171 +
172 + /* now lets add the voltage delta to the sensor values */
173 + new_senn = senn + nnt_delta;
174 + new_senp = senp + pnt_delta;
175 +
176 + new_opp_nvalue = cal_test_nvalue(new_senn, new_senp);
177 +
178 + printk("Compensating OPP%d for %dmV Orig nvalue:0x%x New nvalue:0x%x \n",
179 + opp_no, mv_delta, orig_opp_nvalue, new_opp_nvalue);
180 +
181 + return new_opp_nvalue;
182 +}
183 +
184 +/* irq_sr_reenable - Re-enable SR interrupts (triggered by delayed work queue)
185 + * @work: pointer to work_struct embedded in am33xx_sr_sensor struct
186 + *
187 + * While servicing the IRQ, this function is added to the delayed work queue.
188 + * This gives time for the voltage change to settle before we re-enable
189 + * the interrupt.
190 + */
191 +static void irq_sr_reenable(struct work_struct *work)
192 +{
193 + u32 srid;
194 + struct am33xx_sr_sensor *sens;
195 + struct am33xx_sr *sr;
196 +
197 + sens = container_of((void *)work, struct am33xx_sr_sensor,
198 + work_reenable);
199 +
200 + srid = sens->sr_id;
201 +
202 + sr = container_of((void *)sens, struct am33xx_sr, sen[srid]);
203 +
204 + dev_dbg(&sr->pdev->dev, "%s: SR %d\n", __func__, srid);
205 +
206 + /* Must clear IRQ status */
207 + sens->irq_status = 0;
208 +
209 + /* Re-enable the interrupt */
210 + sr_modify_reg(sr, IRQENABLE_SET, IRQENABLE_MCUBOUNDSINT,
211 + IRQENABLE_MCUBOUNDSINT, srid);
212 +
213 + /* Restart the module after voltage set */
214 + sr_modify_reg(sr, SRCONFIG, SRCONFIG_SRENABLE,
215 + SRCONFIG_SRENABLE, srid);
216 +}
217 +
218 +/* get_errvolt - get error voltage from SR error register
219 + * @sr: contains SR driver data
220 + * @srid: contains the srid, indicates which SR moduel lswe are using
221 + *
222 + * Read the error from SENSOR error register and then convert
223 + * to voltage delta, return value is the voltage delta in micro
224 + * volt.
225 + */
226 +static int get_errvolt(struct am33xx_sr *sr, s32 srid)
227 +{
228 + struct am33xx_sr_sensor *sens;
229 + int senerror_reg;
230 + s32 uvoltage;
231 + s8 terror;
232 +
233 + sens = &sr->sen[srid];
234 +
235 + senerror_reg = sr_read_reg(sr, SENERROR_V2, srid);
236 + senerror_reg = (senerror_reg & 0x0000FF00);
237 + terror = (s8)(senerror_reg >> 8);
238 +
239 + /* math defined in SR functional spec */
240 + uvoltage = ((terror) * sr->uvoltage_step_size) >> 7;
241 + uvoltage = uvoltage * sens->opp_data[sens->curr_opp].e2v_gain;
242 +
243 + return uvoltage;
244 +}
245 +
246 +/* set_voltage - Schedule task for setting the voltage
247 + * @work: pointer to the work structure
248 + *
249 + * Voltage is set based on previous voltage and calculated
250 + * voltage error.
251 + *
252 + * Generic voltage regulator set voltage is used for changing
253 + * the voltage to new value. Could potentially use voltdm_scale
254 + * but at time of testing voltdm was not populated with volt_data.
255 + *
256 + * Disabling the module before changing the voltage, this is
257 + * needed for not generating interrupt during voltage change,
258 + * enabling after voltage change. This will also take care of
259 + * resetting the SR registers.
260 + */
261 +static void set_voltage(struct work_struct *work)
262 +{
263 + struct am33xx_sr *sr;
264 + int prev_volt, new_volt, i, ret;
265 + s32 delta_v;
266 +
267 + sr = container_of((void *)work, struct am33xx_sr, work);
268 +
269 + for (i = 0; i < sr->no_of_sens; i++) {
270 + if (sr->sen[i].irq_status != 1)
271 + continue;
272 +
273 + /* Get the current voltage from PMIC */
274 + prev_volt = regulator_get_voltage(sr->sen[i].reg);
275 +
276 + if (prev_volt < 0) {
277 + dev_err(&sr->pdev->dev,
278 + "%s: SR %d: regulator_get_voltage error %d\n",
279 + __func__, i, prev_volt);
280 +
281 + goto reenable;
282 + }
283 +
284 + delta_v = get_errvolt(sr, i);
285 + new_volt = prev_volt + delta_v;
286 +
287 + /* this is the primary output for debugging SR activity */
288 + dev_dbg(&sr->pdev->dev,
289 + "%s: SR %d: prev volt=%d, delta_v=%d, req_volt=%d\n",
290 + __func__, i, prev_volt, delta_v, new_volt);
291 +
292 + /* Clear the counter, SR module disable */
293 + sr_modify_reg(sr, SRCONFIG, SRCONFIG_SRENABLE,
294 + ~SRCONFIG_SRENABLE, i);
295 +
296 + if (delta_v != 0) {
297 + ret = regulator_set_voltage(sr->sen[i].reg, new_volt,
298 + new_volt + sr->uvoltage_step_size);
299 +
300 + if (ret < 0)
301 + dev_err(&sr->pdev->dev,
302 + "%s: regulator_set_voltage failed! (err %d)\n",
303 + __func__, ret);
304 + }
305 +reenable:
306 + /* allow time for voltage to settle before re-enabling SR
307 + module and interrupt */
308 + schedule_delayed_work(&sr->sen[i].work_reenable,
309 + msecs_to_jiffies(sr->irq_delay));
310 + }
311 +}
312 +
313 +/* sr_class2_irq - sr irq handling
314 + * @irq: Number of the irq serviced
315 + * @data: data contains the SR driver structure
316 + *
317 + * Smartreflex IRQ handling for class2 IP, once the IRQ handler
318 + * is here then disable the interrupt and re-enable after some
319 + * time. This is the work around for handling both interrupts,
320 + * while one got satisfied with the voltage change but not the
321 + * other. The same logic helps the case where PMIC cannot set
322 + * the exact voltage requested by SR IP
323 + *
324 + * Schedule work only if both interrupts are serviced
325 + *
326 + * Note that same irq handler is used for both the interrupts,
327 + * needed for decision making for voltage change
328 + */
329 +static irqreturn_t sr_class2_irq(int irq, void *data)
330 +{
331 + u32 srid;
332 + struct am33xx_sr *sr;
333 + struct am33xx_sr_sensor *sr_sensor = (struct am33xx_sr_sensor *)data;
334 +
335 + srid = sr_sensor->sr_id;
336 +
337 + sr = container_of(data, struct am33xx_sr, sen[srid]);
338 +
339 + sr->sen[srid].irq_status = 1;
340 +
341 + /* Clear MCUBounds Interrupt */
342 + sr_modify_reg(sr, IRQSTATUS, IRQSTATUS_MCBOUNDSINT,
343 + IRQSTATUS_MCBOUNDSINT, srid);
344 +
345 + /* Disable the interrupt and re-enable in set_voltage() */
346 + sr_modify_reg(sr, IRQENABLE_CLR, IRQENABLE_MCUBOUNDSINT,
347 + IRQENABLE_MCUBOUNDSINT, srid);
348 +
349 + /* Causes set_voltage() to get called at a later time. Set_voltage()
350 + will check the irq_status flags to determine which SR needs to
351 + be serviced. This was previously done with schedule_work, but
352 + I observed a crash in set_voltage() when changing OPPs on weak
353 + silicon, which may have been related to insufficient voltage
354 + settling time for OPP change. This additional delay avoids the
355 + crash. */
356 + schedule_delayed_work(&sr->work,
357 + msecs_to_jiffies(250));
358 +
359 + return IRQ_HANDLED;
360 +}
361 +
362 +static int sr_clk_enable(struct am33xx_sr *sr, u32 srid)
363 +{
364 + if (clk_enable(sr->sen[srid].fck) != 0) {
365 + dev_err(&sr->pdev->dev, "%s: Could not enable sr_fck\n",
366 + __func__);
367 + return -EINVAL;
368 + }
369 +
370 + return 0;
371 +}
372 +
373 +static int sr_clk_disable(struct am33xx_sr *sr, u32 srid)
374 +{
375 + clk_disable(sr->sen[srid].fck);
376 +
377 + return 0;
378 +}
379 +
380 +static inline int sr_set_nvalues(struct am33xx_sr *sr, u32 srid)
381 +{
382 + int i;
383 + struct am33xx_sr_sensor *sens = &sr->sen[srid];
384 +
385 + for (i = 0; i < sens->no_of_opps; i++) {
386 + /* Read nTarget value form EFUSE register*/
387 + sens->opp_data[i].nvalue = readl(AM33XX_CTRL_REGADDR
388 + (sens->opp_data[i].efuse_offs)) & 0xFFFFFF;
389 +
390 + /* validate nTarget value */
391 + if (sens->opp_data[i].nvalue == 0)
392 + return -EINVAL;
393 +
394 + /* adjust nTarget based on margin in mv */
395 + sens->opp_data[i].adj_nvalue = sr_adjust_efuse_nvalue(i,
396 + sens->opp_data[i].nvalue,
397 + sens->opp_data[i].margin);
398 +
399 + dev_dbg(&sr->pdev->dev,
400 + "NValueReciprocal value (from efuse) = %08x\n",
401 + sens->opp_data[i].nvalue);
402 +
403 + dev_dbg(&sr->pdev->dev,
404 + "Adjusted NValueReciprocal value = %08x\n",
405 + sens->opp_data[i].adj_nvalue);
406 + }
407 + return 0;
408 +}
409 +
410 +/* sr_configure - Configure SR module to work in Error generator mode
411 + * @sr: contains SR driver data
412 + * @srid: contains the srid, specify whether it is CORE or MPU
413 + *
414 + * Configure the corresponding values to SR module registers for
415 + * operating SR module in Error Generator mode.
416 + */
417 +static void sr_configure(struct am33xx_sr *sr, u32 srid)
418 +{
419 + struct am33xx_sr_sensor *sens = &sr->sen[srid];
420 +
421 + /* Configuring the SR module with clock length, enabling the
422 + * error generator, enable SR module, enable individual N and P
423 + * sensors
424 + */
425 + sr_write_reg(sr, SRCONFIG, (SRCLKLENGTH_125MHZ_SYSCLK |
426 + SRCONFIG_SENENABLE | SRCONFIG_ERRGEN_EN |
427 + (sens->senn_en << SRCONFIG_SENNENABLE_V2_SHIFT) |
428 + (sens->senp_en << SRCONFIG_SENPENABLE_V2_SHIFT)),
429 + srid);
430 +
431 + /* Configuring the Error Generator */
432 + sr_modify_reg(sr, ERRCONFIG_V2, (SR_ERRWEIGHT_MASK |
433 + SR_ERRMAXLIMIT_MASK | SR_ERRMINLIMIT_MASK),
434 + ((sens->opp_data[sens->curr_opp].err_weight <<
435 + ERRCONFIG_ERRWEIGHT_SHIFT) |
436 + (sens->opp_data[sens->curr_opp].err_maxlimit <<
437 + ERRCONFIG_ERRMAXLIMIT_SHIFT) |
438 + (sens->opp_data[sens->curr_opp].err_minlimit <<
439 + ERRCONFIG_ERRMINLIMIT_SHIFT)),
440 + srid);
441 +}
442 +
443 +/* sr_enable - Enable SR module
444 + * @sr: contains SR driver data
445 + * @srid: contains the srid, specify whether it is CORE or MPU
446 + *
447 + * Enable SR module by writing nTarget values to corresponding SR
448 + * NVALUERECIPROCAL register, enable the interrupt and enable SR
449 + */
450 +static void sr_enable(struct am33xx_sr *sr, u32 srid)
451 +{
452 + struct am33xx_sr_sensor *sens;
453 +
454 + sens = &sr->sen[srid];
455 +
456 + /* Check if SR is already enabled. If yes do nothing */
457 + if (sr_read_reg(sr, SRCONFIG, srid) & SRCONFIG_SRENABLE)
458 + return;
459 +
460 + if (sens->opp_data[sens->curr_opp].nvalue == 0)
461 + dev_err(&sr->pdev->dev,
462 + "%s: OPP doesn't support SmartReflex\n", __func__);
463 +
464 + /* Writing the nReciprocal value to the register */
465 + sr_write_reg(sr, NVALUERECIPROCAL,
466 + sens->opp_data[sens->curr_opp].adj_nvalue, srid);
467 +
468 + /* Enable the interrupt */
469 + sr_modify_reg(sr, IRQENABLE_SET, IRQENABLE_MCUBOUNDSINT,
470 + IRQENABLE_MCUBOUNDSINT, srid);
471 +
472 + /* SRCONFIG - enable SR */
473 + sr_modify_reg(sr, SRCONFIG, SRCONFIG_SRENABLE,
474 + SRCONFIG_SRENABLE, srid);
475 +}
476 +
477 +/* sr_disable - Disable SR module
478 + * @sr: contains SR driver data
479 + * @srid: contains the srid, specify whether it is CORE or MPU
480 + *
481 + * Disable SR module by disabling the interrupt and Smartreflex module
482 + */
483 +static void sr_disable(struct am33xx_sr *sr, u32 srid)
484 +{
485 + /* Disable the interrupt */
486 + sr_modify_reg(sr, IRQENABLE_CLR, IRQENABLE_MCUBOUNDSINT,
487 + IRQENABLE_MCUBOUNDSINT, srid);
488 +
489 + /* SRCONFIG - disable SR */
490 + sr_modify_reg(sr, SRCONFIG, SRCONFIG_SRENABLE,
491 + ~SRCONFIG_SRENABLE, srid);
492 +}
493 +
494 +/* sr_start_vddautocomp - Start VDD auto compensation
495 + * @sr: contains SR driver data
496 + *
497 + * This is the starting point for AVS enable from user space.
498 + * Also used to re-enable SR after OPP change.
499 + */
500 +static void sr_start_vddautocomp(struct am33xx_sr *sr)
501 +{
502 + int i;
503 +
504 + if ((sr->sen[SR_CORE].opp_data[0].nvalue == 0) ||
505 + (sr->sen[SR_MPU].opp_data[0].nvalue == 0)) {
506 + dev_err(&sr->pdev->dev, "SR module not enabled, nTarget"
507 + " values are not found\n");
508 + return;
509 + }
510 +
511 + if (sr->autocomp_active == 1) {
512 + dev_warn(&sr->pdev->dev, "SR VDD autocomp already active\n");
513 + return;
514 + }
515 +
516 + for (i = 0; i < sr->no_of_sens; i++) {
517 + /* Read current regulator value and voltage */
518 + sr->sen[i].init_volt_mv = regulator_get_voltage(sr->sen[i].reg);
519 +
520 + dev_dbg(&sr->pdev->dev, "%s: regulator %d, init_volt = %d\n",
521 + __func__, i, sr->sen[i].init_volt_mv);
522 +
523 + if (sr_clk_enable(sr, i))
524 + return;
525 + sr_configure(sr, i);
526 + sr_enable(sr, i);
527 + }
528 +
529 + sr->autocomp_active = 1;
530 +}
531 +
532 +/* sr_stop_vddautocomp - Stop VDD auto compensation
533 + * @sr: contains SR driver data
534 + *
535 + * This is the ending point during SR disable from user space.
536 + * Also used to disable SR after OPP change.
537 + */
538 +static void sr_stop_vddautocomp(struct am33xx_sr *sr)
539 +{
540 + int i;
541 +
542 + if (sr->autocomp_active == 0) {
543 + dev_warn(&sr->pdev->dev, "SR VDD autocomp is not active\n");
544 + return;
545 + }
546 +
547 + /* cancel bottom half interrupt handlers that haven't run yet */
548 + cancel_delayed_work_sync(&sr->work);
549 +
550 + for (i = 0; i < sr->no_of_sens; i++) {
551 + /* cancel any outstanding SR IRQ re-enables on work queue */
552 + cancel_delayed_work_sync(&sr->sen[i].work_reenable);
553 + sr_disable(sr, i);
554 + sr_clk_disable(sr, i);
555 + }
556 +
557 + sr->autocomp_active = 0;
558 +}
559 +
560 +/* am33xx_sr_autocomp_show - Store user input value and stop SR
561 + * @data: contains SR driver data
562 + * @val: pointer to store autocomp_active status
563 + *
564 + * This is the Debug Fs enteries to show whether SR is enabled
565 + * or disabled
566 + */
567 +static int am33xx_sr_autocomp_show(void *data, u64 *val)
568 +{
569 + struct am33xx_sr *sr_info = (struct am33xx_sr *) data;
570 +
571 + *val = (u64) sr_info->autocomp_active;
572 +
573 + return 0;
574 +}
575 +
576 +static int am33xx_sr_margin_show(void *data, u64 *val)
577 +{
578 + struct am33xx_sr_opp_data *sr_opp_data = (struct am33xx_sr_opp_data *)data;
579 +
580 + *val = (u64) sr_opp_data->margin;
581 +
582 + return 0;
583 +}
584 +
585 +static int am33xx_sr_margin_update(void *data, u64 val)
586 +{
587 + struct am33xx_sr_opp_data *sr_opp_data =
588 + (struct am33xx_sr_opp_data *)data;
589 + struct am33xx_sr_sensor *sr_sensor;
590 + struct am33xx_sr *sr_info;
591 +
592 + /* work back to the sr_info pointer */
593 + sr_sensor = container_of((void *)sr_opp_data, struct am33xx_sr_sensor,
594 + opp_data[sr_opp_data->opp_id]);
595 +
596 + sr_info = container_of((void *)sr_sensor, struct am33xx_sr,
597 + sen[sr_sensor->sr_id]);
598 +
599 + /* store the value of margin */
600 + sr_opp_data->margin = (s32)val;
601 +
602 + dev_warn(&sr_info->pdev->dev, "%s: new margin=%d, srid=%d, opp=%d\n",
603 + __func__, sr_opp_data->margin, sr_sensor->sr_id,
604 + sr_opp_data->opp_id);
605 +
606 + /* updata ntarget values based upon new margin */
607 + if (sr_set_nvalues(sr_info, sr_sensor->sr_id) == -EINVAL)
608 + dev_err(&sr_info->pdev->dev,
609 + "%s: Zero NValue read from EFUSE\n", __func__);
610 +
611 + /* restart SmartReflex to adapt to new values */
612 + sr_stop_vddautocomp(sr_info);
613 + sr_start_vddautocomp(sr_info);
614 +
615 + return 0;
616 +}
617 +
618 +/* am33xx_sr_autocomp_store - Store user input and start SR
619 + * @data: contains SR driver data
620 + * @val: contains the value pased by user
621 + *
622 + * This is the Debug Fs enteries to store user input and
623 + * enable smartreflex.
624 + */
625 +static int am33xx_sr_autocomp_store(void *data, u64 val)
626 +{
627 + struct am33xx_sr *sr_info = (struct am33xx_sr *) data;
628 +
629 + /* Sanity check */
630 + if (val && (val != 1)) {
631 + dev_warn(&sr_info->pdev->dev, "%s: Invalid argument %llu\n",
632 + __func__, val);
633 + return -EINVAL;
634 + }
635 +
636 + if (!val) {
637 + sr_info->disabled_by_user = 1;
638 + sr_stop_vddautocomp(sr_info);
639 + }
640 + else {
641 + sr_info->disabled_by_user = 0;
642 + sr_start_vddautocomp(sr_info);
643 + }
644 +
645 + return 0;
646 +}
647 +
648 +DEFINE_SIMPLE_ATTRIBUTE(sr_fops, am33xx_sr_autocomp_show,
649 + am33xx_sr_autocomp_store, "%llu\n");
650 +
651 +/* sr_curr_volt_show - Show current voltage value
652 + * @data: contains SR driver data
653 + * @val: pointer to store current voltage value
654 + *
655 + * Read the current voltage value and display the same on console
656 + * This is used in debugfs entries
657 + */
658 +static int am33xx_sr_curr_volt_show(void *data, u64 *val)
659 +{
660 + struct am33xx_sr_sensor *sr_sensor = (struct am33xx_sr_sensor *) data;
661 +
662 + *val = (u64) regulator_get_voltage(sr_sensor->reg);
663 +
664 + return 0;
665 +}
666 +
667 +DEFINE_SIMPLE_ATTRIBUTE(curr_volt_fops, am33xx_sr_curr_volt_show,
668 + NULL, "%llu\n");
669 +
670 +DEFINE_SIMPLE_ATTRIBUTE(margin_fops, am33xx_sr_margin_show,
671 + am33xx_sr_margin_update, "%llu\n");
672 +
673 +#ifdef CONFIG_DEBUG_FS
674 +/* sr_debugfs_entries - Create debugfs entries
675 + * @sr_info: contains SR driver data
676 + *
677 + * Create debugfs entries, which is exposed to user for knowing
678 + * the current status. Some of the parameters can change during
679 + * run time
680 + */
681 +static int sr_debugfs_entries(struct am33xx_sr *sr_info)
682 +{
683 + struct am33xx_sr_sensor *sens;
684 + struct dentry *dbg_dir, *sen_dir, *opp_dir;
685 + int i, j;
686 +
687 + dbg_dir = debugfs_create_dir("smartreflex", NULL);
688 + if (IS_ERR(dbg_dir)) {
689 + dev_err(&sr_info->pdev->dev, "%s: Unable to create debugfs"
690 + " directory\n", __func__);
691 + return PTR_ERR(dbg_dir);
692 + }
693 +
694 + (void) debugfs_create_file("autocomp", S_IRUGO | S_IWUGO, dbg_dir,
695 + (void *)sr_info, &sr_fops);
696 + (void) debugfs_create_u32("interrupt_delay", S_IRUGO | S_IWUGO,
697 + dbg_dir, &sr_info->irq_delay);
698 +
699 + for (i = 0; i < sr_info->no_of_sens; i++) {
700 + sens = &sr_info->sen[i];
701 + sen_dir = debugfs_create_dir(sens->name, dbg_dir);
702 + if (IS_ERR(sen_dir)) {
703 + dev_err(&sr_info->pdev->dev, "%s: Unable to create"
704 + " debugfs directory\n", __func__);
705 + return PTR_ERR(sen_dir);
706 + }
707 +
708 + (void)debugfs_create_u32("initial_voltage", S_IRUGO, sen_dir,
709 + &sens->init_volt_mv);
710 + (void)debugfs_create_file("current_voltage", S_IRUGO, sen_dir,
711 + (void *)sens, &curr_volt_fops);
712 +
713 + for (j = 0; j < sr_info->sen[i].no_of_opps; j++) {
714 + char tmp[20];
715 +
716 + sprintf(&tmp[0], "opp%d", j);
717 + opp_dir = debugfs_create_dir(tmp, sen_dir);
718 + if (IS_ERR(opp_dir)) {
719 + dev_err(&sr_info->pdev->dev,
720 + "%s: Unable to create debugfs directory\n",
721 + __func__);
722 + return PTR_ERR(opp_dir);
723 + }
724 +
725 + (void)debugfs_create_file("margin", S_IRUGO | S_IWUGO,
726 + opp_dir, (void *)&sens->opp_data[j],
727 + &margin_fops);
728 + (void)debugfs_create_x32("err2voltgain",
729 + S_IRUGO | S_IWUGO,
730 + opp_dir,
731 + &sens->opp_data[j].e2v_gain);
732 + (void)debugfs_create_x32("nvalue", S_IRUGO,
733 + opp_dir,
734 + &sens->opp_data[j].nvalue);
735 + (void)debugfs_create_x32("adj_nvalue", S_IRUGO,
736 + opp_dir,
737 + &sens->opp_data[j].adj_nvalue);
738 + }
739 + }
740 + return 0;
741 +}
742 +#else
743 +static int sr_debugfs_entries(struct am33xx_sr *sr_info)
744 +{
745 + return 0;
746 +}
747 +#endif
748 +
749 +#ifdef CONFIG_CPU_FREQ
750 +
751 +/* Find and return current OPP. This should change to use system APIs,
752 + but voltdm is not currently populated, and opp APIs are also not working. */
753 +static int get_current_opp(struct am33xx_sr *sr, u32 srid, u32 freq) {
754 + int i;
755 +
756 + for (i = 0; i < sr->sen[srid].no_of_opps; i++) {
757 + if (sr->sen[srid].opp_data[i].frequency == freq)
758 + return i;
759 + }
760 +
761 + return -EINVAL;
762 +}
763 +
764 +static int am33xx_sr_cpufreq_transition(struct notifier_block *nb,
765 + unsigned long val, void *data)
766 +{
767 + struct am33xx_sr *sr;
768 + struct cpufreq_freqs *cpu;
769 +
770 + sr = container_of(nb, struct am33xx_sr, freq_transition);
771 +
772 + /* We are required to disable SR while OPP change is occurring */
773 + if (val == CPUFREQ_PRECHANGE) {
774 + dev_dbg(&sr->pdev->dev, "%s: prechange\n", __func__);
775 + sr_stop_vddautocomp(sr);
776 + } else if (val == CPUFREQ_POSTCHANGE) {
777 + cpu = (struct cpufreq_freqs *)data;
778 + dev_dbg(&sr->pdev->dev,
779 + "%s: postchange, cpu=%d, old=%d, new=%d\n",
780 + __func__, cpu->cpu, cpu->old, cpu->new);
781 +
782 + /* update current OPP */
783 + sr->sen[SR_MPU].curr_opp = get_current_opp(sr, SR_MPU,
784 + cpu->new*1000);
785 + if (sr->sen[SR_MPU].curr_opp == -EINVAL) {
786 + dev_err(&sr->pdev->dev, "%s: cannot determine opp\n",
787 + __func__);
788 + return -EINVAL;
789 + }
790 +
791 + dev_dbg(&sr->pdev->dev, "%s: postchange, new opp=%d\n",
792 + __func__, sr->sen[SR_MPU].curr_opp);
793 +
794 + /* this handles the case when the user has disabled SR via
795 + debugfs, therefore we do not want to enable SR */
796 + if (sr->disabled_by_user == 0)
797 + sr_start_vddautocomp(sr);
798 + }
799 +
800 + return 0;
801 +}
802 +
803 +static inline int am33xx_sr_cpufreq_register(struct am33xx_sr *sr)
804 +{
805 + sr->freq_transition.notifier_call = am33xx_sr_cpufreq_transition;
806 +
807 + return cpufreq_register_notifier(&sr->freq_transition,
808 + CPUFREQ_TRANSITION_NOTIFIER);
809 +}
810 +
811 +static inline void am33xx_sr_cpufreq_deregister(struct am33xx_sr *sr)
812 +{
813 + cpufreq_unregister_notifier(&sr->freq_transition,
814 + CPUFREQ_TRANSITION_NOTIFIER);
815 +}
816 +
817 +#endif
818 +
819 +static int __init am33xx_sr_probe(struct platform_device *pdev)
820 +{
821 + struct am33xx_sr *sr_info;
822 + struct am33xx_sr_platform_data *pdata;
823 + struct resource *res[MAX_SENSORS];
824 + int irq;
825 + int ret;
826 + int i,j;
827 +
828 + sr_info = kzalloc(sizeof(struct am33xx_sr), GFP_KERNEL);
829 + if (!sr_info) {
830 + dev_err(&pdev->dev, "%s: unable to allocate sr_info\n",
831 + __func__);
832 + return -ENOMEM;
833 + }
834 +
835 + pdata = pdev->dev.platform_data;
836 + if (!pdata) {
837 + dev_err(&pdev->dev, "%s: platform data missing\n", __func__);
838 + ret = -EINVAL;
839 + goto err_free_sr_info;
840 + }
841 +
842 + sr_info->pdev = pdev;
843 + sr_info->sen[SR_CORE].name = "smartreflex0";
844 + sr_info->sen[SR_MPU].name = "smartreflex1";
845 + sr_info->ip_type = pdata->ip_type;
846 + sr_info->irq_delay = pdata->irq_delay;
847 + sr_info->no_of_sens = pdata->no_of_sens;
848 + sr_info->no_of_vds = pdata->no_of_vds;
849 + sr_info->uvoltage_step_size = pdata->vstep_size_uv;
850 + sr_info->autocomp_active = false;
851 + sr_info->disabled_by_user = false;
852 +
853 + for (i = 0; i < sr_info->no_of_sens; i++) {
854 + u32 curr_freq=0;
855 +
856 + sr_info->sen[i].reg_name = pdata->vd_name[i];
857 +
858 + /* this should be determined from voltdm or opp layer, but
859 + those approaches are not working */
860 + sr_info->sen[i].no_of_opps = pdata->sr_sdata[i].no_of_opps;
861 + sr_info->sen[i].sr_id = i;
862 +
863 + /* Reading per OPP Values */
864 + for (j = 0; j < sr_info->sen[i].no_of_opps; j++) {
865 + sr_info->sen[i].opp_data[j].efuse_offs =
866 + pdata->sr_sdata[i].sr_opp_data[j].efuse_offs;
867 + sr_info->sen[i].opp_data[j].e2v_gain =
868 + pdata->sr_sdata[i].sr_opp_data[j].e2v_gain;
869 + sr_info->sen[i].opp_data[j].err_weight =
870 + pdata->sr_sdata[i].sr_opp_data[j].err_weight;
871 + sr_info->sen[i].opp_data[j].err_minlimit =
872 + pdata->sr_sdata[i].sr_opp_data[j].err_minlimit;
873 + sr_info->sen[i].opp_data[j].err_maxlimit =
874 + pdata->sr_sdata[i].sr_opp_data[j].err_maxlimit;
875 + sr_info->sen[i].opp_data[j].margin =
876 + pdata->sr_sdata[i].sr_opp_data[j].margin;
877 + sr_info->sen[i].opp_data[j].nominal_volt =
878 + pdata->sr_sdata[i].sr_opp_data[j].nominal_volt;
879 + sr_info->sen[i].opp_data[j].frequency =
880 + pdata->sr_sdata[i].sr_opp_data[j].frequency;
881 + sr_info->sen[i].opp_data[j].opp_id = j;
882 + }
883 +
884 + if (i == SR_MPU) {
885 + /* hardcoded CPU NR */
886 + curr_freq = cpufreq_get(0);
887 +
888 + /* update current OPP */
889 + sr_info->sen[i].curr_opp = get_current_opp(sr_info, i,
890 + curr_freq*1000);
891 + if (sr_info->sen[i].curr_opp == -EINVAL) {
892 + dev_err(&sr_info->pdev->dev,
893 + "%s: cannot determine opp\n",__func__);
894 + ret = -EINVAL;
895 + goto err_free_sr_info;
896 + }
897 + } else {
898 + sr_info->sen[i].curr_opp =
899 + pdata->sr_sdata[i].default_opp;
900 + }
901 +
902 + dev_dbg(&pdev->dev,
903 + "%s: SR%d, curr_opp=%d, no_of_opps=%d, step_size=%d\n",
904 + __func__, i, sr_info->sen[i].curr_opp,
905 + sr_info->sen[i].no_of_opps,
906 + sr_info->uvoltage_step_size);
907 +
908 + ret = sr_set_nvalues(sr_info, i);
909 + if (ret == -EINVAL) {
910 + dev_err(&sr_info->pdev->dev,
911 + "%s: Zero NValue read from EFUSE\n", __func__);
912 + goto err_free_sr_info;
913 + }
914 +
915 + INIT_DELAYED_WORK(&sr_info->sen[i].work_reenable,
916 + irq_sr_reenable);
917 +
918 + sr_info->res_name[i] = kzalloc(CLK_NAME_LEN + 1, GFP_KERNEL);
919 +
920 + /* resources */
921 + res[i] = platform_get_resource_byname(pdev, IORESOURCE_MEM,
922 + sr_info->sen[i].name);
923 + if (!res[i]) {
924 + dev_err(&pdev->dev, "%s: no mem resource\n", __func__);
925 + ret = -ENOENT;
926 + goto err_free_mem;
927 + }
928 +
929 + irq = platform_get_irq_byname(pdev, sr_info->sen[i].name);
930 + if (irq < 0) {
931 + dev_err(&pdev->dev, "Can't get interrupt resource\n");
932 + ret = irq;
933 + goto err_free_mem;
934 + }
935 + sr_info->sen[i].irq = irq;
936 +
937 + res[i] = request_mem_region(res[i]->start,
938 + resource_size(res[i]), pdev->name);
939 + if (!res[i]) {
940 + dev_err(&pdev->dev, "can't request mem region\n");
941 + ret = -EBUSY;
942 + goto err_free_mem;
943 + }
944 +
945 + sr_info->sen[i].base = ioremap(res[i]->start,
946 + resource_size(res[i]));
947 + if (!sr_info->sen[i].base) {
948 + dev_err(&pdev->dev, "%s: ioremap fail\n", __func__);
949 + ret = -ENOMEM;
950 + goto err_release_mem;
951 + }
952 +
953 + strcat(sr_info->res_name[i], sr_info->sen[i].name);
954 + strcat(sr_info->res_name[i], "_fck");
955 +
956 + sr_info->sen[i].fck = clk_get(NULL, sr_info->res_name[i]);
957 + if (IS_ERR(sr_info->sen[i].fck)) {
958 + dev_err(&pdev->dev, "%s: Could not get sr fck\n",
959 + __func__);
960 + ret = PTR_ERR(sr_info->sen[i].fck);
961 + goto err_unmap;
962 + }
963 +
964 + ret = request_irq(sr_info->sen[i].irq, sr_class2_irq,
965 + IRQF_DISABLED, sr_info->sen[i].name,
966 + (void *)&sr_info->sen[i]);
967 + if (ret) {
968 + dev_err(&pdev->dev, "%s: Could not install SR ISR\n",
969 + __func__);
970 + goto err_put_clock;
971 + }
972 +
973 + sr_info->sen[i].senn_en = pdata->sr_sdata[i].senn_mod;
974 + sr_info->sen[i].senp_en = pdata->sr_sdata[i].senp_mod;
975 +
976 + sr_info->sen[i].reg =
977 + regulator_get(NULL, sr_info->sen[i].reg_name);
978 + if (IS_ERR(sr_info->sen[i].reg)) {
979 + ret = -EINVAL;
980 + goto err_free_irq;
981 + }
982 +
983 + /* Read current regulator value and voltage */
984 + sr_info->sen[i].init_volt_mv =
985 + regulator_get_voltage(sr_info->sen[i].reg);
986 +
987 + dev_dbg(&pdev->dev, "%s: regulator %d, init_volt = %d\n",
988 + __func__, i, sr_info->sen[i].init_volt_mv);
989 + } /* for() */
990 +
991 + /* set_voltage() will be used as the bottom half IRQ handler */
992 + INIT_DELAYED_WORK(&sr_info->work, set_voltage);
993 +
994 +#ifdef CONFIG_CPU_FREQ
995 + ret = am33xx_sr_cpufreq_register(sr_info);
996 + if (ret) {
997 + dev_err(&pdev->dev, "failed to register cpufreq\n");
998 + goto err_reg_put;
999 + }
1000 +#endif
1001 +
1002 + /* debugfs entries */
1003 + ret = sr_debugfs_entries(sr_info);
1004 + if (ret)
1005 + dev_warn(&pdev->dev, "%s: Debugfs entries are not created\n",
1006 + __func__);
1007 +
1008 + platform_set_drvdata(pdev, sr_info);
1009 +
1010 + dev_info(&pdev->dev, "%s: Driver initialized\n", __func__);
1011 +
1012 + /* disabled_by_user used to ensure SR doesn't come on via CPUFREQ
1013 + scaling if user has disabled SR via debugfs on enable_on_init */
1014 + if (pdata->enable_on_init)
1015 + sr_start_vddautocomp(sr_info);
1016 + else
1017 + sr_info->disabled_by_user = 1;
1018 +
1019 + return ret;
1020 +
1021 +#ifdef CONFIG_CPU_FREQ
1022 + am33xx_sr_cpufreq_deregister(sr_info);
1023 +#endif
1024 +
1025 +err_reg_put:
1026 + i--; /* back up i by one to walk back through the for loop */
1027 + regulator_put(sr_info->sen[i].reg);
1028 +err_free_irq:
1029 + free_irq(sr_info->sen[i].irq, (void *)sr_info);
1030 +err_put_clock:
1031 + clk_put(sr_info->sen[i].fck);
1032 +err_unmap:
1033 + iounmap(sr_info->sen[i].base);
1034 +err_release_mem:
1035 + release_mem_region(res[i]->start, resource_size(res[i]));
1036 +err_free_mem:
1037 + kfree(sr_info->res_name[i]);
1038 + /* unwind back through the for loop */
1039 + if (i != 0) {
1040 + goto err_reg_put;
1041 + }
1042 +
1043 +err_free_sr_info:
1044 + kfree(sr_info);
1045 + return ret;
1046 +}
1047 +
1048 +static int __devexit am33xx_sr_remove(struct platform_device *pdev)
1049 +{
1050 + struct am33xx_sr *sr_info;
1051 + struct resource *res[MAX_SENSORS];
1052 + int irq;
1053 + int i;
1054 +
1055 + sr_info = dev_get_drvdata(&pdev->dev);
1056 + if (!sr_info) {
1057 + dev_err(&pdev->dev, "%s: sr_info missing\n", __func__);
1058 + return -EINVAL;
1059 + }
1060 +
1061 + if (sr_info->autocomp_active)
1062 + sr_stop_vddautocomp(sr_info);
1063 +
1064 +#ifdef CONFIG_CPU_FREQ
1065 + am33xx_sr_cpufreq_deregister(sr_info);
1066 +#endif
1067 +
1068 + for (i = 0; i < sr_info->no_of_sens; i++) {
1069 + regulator_put(sr_info->sen[i].reg);
1070 + irq = platform_get_irq_byname(pdev, sr_info->sen[i].name);
1071 + free_irq(irq, (void *)sr_info);
1072 + clk_put(sr_info->sen[i].fck);
1073 + iounmap(sr_info->sen[i].base);
1074 + res[i] = platform_get_resource_byname(pdev,
1075 + IORESOURCE_MEM, sr_info->sen[i].name);
1076 + release_mem_region(res[i]->start, resource_size(res[i]));
1077 + kfree(sr_info->res_name[i]);
1078 + }
1079 +
1080 + kfree(sr_info);
1081 +
1082 + dev_info(&pdev->dev, "%s: SR has been removed\n", __func__);
1083 + return 0;
1084 +}
1085 +
1086 +static struct platform_driver smartreflex_driver = {
1087 + .driver = {
1088 + .name = "smartreflex",
1089 + .owner = THIS_MODULE,
1090 + },
1091 + .remove = am33xx_sr_remove,
1092 +};
1093 +
1094 +static int __init sr_init(void)
1095 +{
1096 + int ret;
1097 +
1098 + ret = platform_driver_probe(&smartreflex_driver, am33xx_sr_probe);
1099 + if (ret) {
1100 + pr_err("%s: platform driver register failed\n", __func__);
1101 + return ret;
1102 + }
1103 +
1104 + return 0;
1105 +}
1106 +
1107 +static void __exit sr_exit(void)
1108 +{
1109 + platform_driver_unregister(&smartreflex_driver);
1110 +}
1111 +late_initcall(sr_init);
1112 +module_exit(sr_exit);
1113 +
1114 +MODULE_DESCRIPTION("AM33XX Smartreflex Class2 Driver");
1115 +MODULE_LICENSE("GPL");
1116 +MODULE_ALIAS("platform:" DRIVER_NAME);
1117 +MODULE_AUTHOR("Texas Instruments Inc");
1118 diff --git a/arch/arm/mach-omap2/board-am335xevm.c b/arch/arm/mach-omap2/board-am335xevm.c
1119 index 0bcadd7..6e1c026 100644
1120 --- a/arch/arm/mach-omap2/board-am335xevm.c
1121 +++ b/arch/arm/mach-omap2/board-am335xevm.c
1122 @@ -1410,6 +1410,7 @@ static struct regulator_init_data tps65217_regulator_data[] = {
1123 .num_consumer_supplies = ARRAY_SIZE(tps65217_dcdc2_consumers),
1124 .consumer_supplies = tps65217_dcdc2_consumers,
1125 .driver_data = &dcdc2_ramp_delay,
1126 + .ignore_check_consumers = 1,
1127 },
1129 /* dcdc3 */
1130 @@ -1424,6 +1425,7 @@ static struct regulator_init_data tps65217_regulator_data[] = {
1131 },
1132 .num_consumer_supplies = ARRAY_SIZE(tps65217_dcdc3_consumers),
1133 .consumer_supplies = tps65217_dcdc3_consumers,
1134 + .ignore_check_consumers = 1,
1135 },
1137 /* ldo1 */
1138 @@ -2214,6 +2216,9 @@ static void am335x_evm_setup(struct memory_accessor *mem_acc, void *context)
1139 goto out;
1140 }
1142 + /* SmartReflex also requires board information. */
1143 + am33xx_sr_init();
1144 +
1145 return;
1147 out:
1148 @@ -2265,6 +2270,7 @@ static struct regulator_init_data am335x_vdd1 = {
1149 },
1150 .num_consumer_supplies = ARRAY_SIZE(am335x_vdd1_supply),
1151 .consumer_supplies = am335x_vdd1_supply,
1152 + .ignore_check_consumers = 1,
1153 };
1155 static struct regulator_consumer_supply am335x_vdd2_supply[] = {
1156 @@ -2281,6 +2287,7 @@ static struct regulator_init_data am335x_vdd2 = {
1157 },
1158 .num_consumer_supplies = ARRAY_SIZE(am335x_vdd2_supply),
1159 .consumer_supplies = am335x_vdd2_supply,
1160 + .ignore_check_consumers = 1,
1161 };
1163 static struct tps65910_board am335x_tps65910_info = {
1164 diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c
1165 index 6113654..ebf0d9e 100644
1166 --- a/arch/arm/mach-omap2/devices.c
1167 +++ b/arch/arm/mach-omap2/devices.c
1168 @@ -52,6 +52,7 @@
1169 #include <plat/config_pwm.h>
1170 #include <plat/cpu.h>
1171 #include <plat/gpmc.h>
1172 +#include <plat/smartreflex.h>
1173 #include <plat/am33xx.h>
1175 /* LCD controller similar DA8xx */
1176 @@ -60,10 +61,28 @@
1177 #include "mux.h"
1178 #include "control.h"
1179 #include "devices.h"
1180 +#include "omap_opp_data.h"
1182 #define L3_MODULES_MAX_LEN 12
1183 #define L3_MODULES 3
1185 +static unsigned int am33xx_evmid;
1186 +
1187 +/*
1188 + * am33xx_evmid_fillup - set up board evmid
1189 + * @evmid - evm id which needs to be configured
1190 + *
1191 + * This function is called to configure board evm id.
1192 + * IA Motor Control EVM needs special setting of MAC PHY Id.
1193 + * This function is called when IA Motor Control EVM is detected
1194 + * during boot-up.
1195 + */
1196 +void am33xx_evmid_fillup(unsigned int evmid)
1197 +{
1198 + am33xx_evmid = evmid;
1199 + return;
1200 +}
1201 +
1202 static int __init omap3_l3_init(void)
1203 {
1204 int l;
1205 @@ -1226,6 +1245,256 @@ static struct platform_device am335x_sgx = {
1207 #endif
1209 +#ifdef CONFIG_AM33XX_SMARTREFLEX
1210 +
1211 +/* smartreflex platform data */
1212 +
1213 +/* The values below are based upon silicon characterization data.
1214 + * Each OPP and sensor combination potentially has different values.
1215 + * The values of ERR2VOLT_GAIN and ERR_MIN_LIMIT also change based on
1216 + * the PMIC step size. Values have been given to cover the AM335 EVM
1217 + * (12.5mV step) and the Beaglebone (25mV step). If the step
1218 + * size changes, you should update these values, and don't forget to
1219 + * change the step size in the platform data structure, am33xx_sr_pdata.
1220 + */
1221 +
1222 +#define AM33XX_SR0_OPP50_CNTRL_OFFSET 0x07B8
1223 +#define AM33XX_SR0_OPP50_EVM_ERR2VOLT_GAIN 0xC
1224 +#define AM33XX_SR0_OPP50_EVM_ERR_MIN_LIMIT 0xF5
1225 +#define AM33XX_SR0_OPP50_BB_ERR2VOLT_GAIN 0x6
1226 +#define AM33XX_SR0_OPP50_BB_ERR_MIN_LIMIT 0xEA
1227 +#define AM33XX_SR0_OPP50_ERR_MAX_LIMIT 0x2
1228 +#define AM33XX_SR0_OPP50_ERR_WEIGHT 0x4
1229 +#define AM33XX_SR0_OPP50_MARGIN 0
1230 +
1231 +#define AM33XX_SR0_OPP100_CNTRL_OFFSET 0x07BC
1232 +#define AM33XX_SR0_OPP100_EVM_ERR2VOLT_GAIN 0x12
1233 +#define AM33XX_SR0_OPP100_EVM_ERR_MIN_LIMIT 0xF8
1234 +#define AM33XX_SR0_OPP100_BB_ERR2VOLT_GAIN 0x9
1235 +#define AM33XX_SR0_OPP100_BB_ERR_MIN_LIMIT 0xF1
1236 +#define AM33XX_SR0_OPP100_ERR_MAX_LIMIT 0x2
1237 +#define AM33XX_SR0_OPP100_ERR_WEIGHT 0x4
1238 +#define AM33XX_SR0_OPP100_MARGIN 0
1239 +
1240 +#define AM33XX_SR1_OPP50_CNTRL_OFFSET 0x0770
1241 +#define AM33XX_SR1_OPP50_EVM_ERR2VOLT_GAIN 0x5
1242 +#define AM33XX_SR1_OPP50_EVM_ERR_MIN_LIMIT 0xE6
1243 +#define AM33XX_SR1_OPP50_BB_ERR2VOLT_GAIN 0x2
1244 +#define AM33XX_SR1_OPP50_BB_ERR_MIN_LIMIT 0xC0
1245 +#define AM33XX_SR1_OPP50_ERR_MAX_LIMIT 0x2
1246 +#define AM33XX_SR1_OPP50_ERR_WEIGHT 0x4
1247 +#define AM33XX_SR1_OPP50_MARGIN 0
1248 +
1249 +#define AM33XX_SR1_OPP100_CNTRL_OFFSET 0x0774
1250 +#define AM33XX_SR1_OPP100_EVM_ERR2VOLT_GAIN 0x8
1251 +#define AM33XX_SR1_OPP100_EVM_ERR_MIN_LIMIT 0xF0
1252 +#define AM33XX_SR1_OPP100_BB_ERR2VOLT_GAIN 0x4
1253 +#define AM33XX_SR1_OPP100_BB_ERR_MIN_LIMIT 0xDF
1254 +#define AM33XX_SR1_OPP100_ERR_MAX_LIMIT 0x2
1255 +#define AM33XX_SR1_OPP100_ERR_WEIGHT 0x4
1256 +#define AM33XX_SR1_OPP100_MARGIN 0
1257 +
1258 +#define AM33XX_SR1_OPP120_CNTRL_OFFSET 0x0778
1259 +#define AM33XX_SR1_OPP120_EVM_ERR2VOLT_GAIN 0xB
1260 +#define AM33XX_SR1_OPP120_EVM_ERR_MIN_LIMIT 0xF4
1261 +#define AM33XX_SR1_OPP120_BB_ERR2VOLT_GAIN 0x5
1262 +#define AM33XX_SR1_OPP120_BB_ERR_MIN_LIMIT 0xE6
1263 +#define AM33XX_SR1_OPP120_ERR_MAX_LIMIT 0x2
1264 +#define AM33XX_SR1_OPP120_ERR_WEIGHT 0x4
1265 +#define AM33XX_SR1_OPP120_MARGIN 0
1266 +
1267 +#define AM33XX_SR1_OPPTURBO_CNTRL_OFFSET 0x077C
1268 +#define AM33XX_SR1_OPPTURBO_EVM_ERR2VOLT_GAIN 0xC
1269 +#define AM33XX_SR1_OPPTURBO_EVM_ERR_MIN_LIMIT 0xF5
1270 +#define AM33XX_SR1_OPPTURBO_BB_ERR2VOLT_GAIN 0x6
1271 +#define AM33XX_SR1_OPPTURBO_BB_ERR_MIN_LIMIT 0xEA
1272 +#define AM33XX_SR1_OPPTURBO_ERR_MAX_LIMIT 0x2
1273 +#define AM33XX_SR1_OPPTURBO_ERR_WEIGHT 0x4
1274 +#define AM33XX_SR1_OPPTURBO_MARGIN 0
1275 +
1276 +/* the voltages and frequencies should probably be defined in opp3xxx_data.c.
1277 + Once SR is integrated to the mainline driver, and voltdm is working
1278 + correctly in AM335x, these can be removed. */
1279 +#define AM33XX_VDD_MPU_OPP50_UV 950000
1280 +#define AM33XX_VDD_MPU_OPP100_UV 1100000
1281 +#define AM33XX_VDD_MPU_OPP120_UV 1200000
1282 +#define AM33XX_VDD_MPU_OPPTURBO_UV 1260000
1283 +#define AM33XX_VDD_CORE_OPP50_UV 950000
1284 +#define AM33XX_VDD_CORE_OPP100_UV 1100000
1285 +
1286 +#define AM33XX_VDD_MPU_OPP50_FREQ 275000000
1287 +#define AM33XX_VDD_MPU_OPP100_FREQ 500000000
1288 +#define AM33XX_VDD_MPU_OPP120_FREQ 600000000
1289 +#define AM33XX_VDD_MPU_OPPTURBO_FREQ 720000000
1290 +
1291 +static struct am33xx_sr_opp_data sr1_opp_data[] = {
1292 + {
1293 + .efuse_offs = AM33XX_SR1_OPP50_CNTRL_OFFSET,
1294 + .e2v_gain = AM33XX_SR1_OPP50_EVM_ERR2VOLT_GAIN,
1295 + .err_minlimit = AM33XX_SR1_OPP50_EVM_ERR_MIN_LIMIT,
1296 + .err_maxlimit = AM33XX_SR1_OPP50_ERR_MAX_LIMIT,
1297 + .err_weight = AM33XX_SR1_OPP50_ERR_WEIGHT,
1298 + .margin = AM33XX_SR1_OPP50_MARGIN,
1299 + .nominal_volt = AM33XX_VDD_MPU_OPP50_UV,
1300 + .frequency = AM33XX_VDD_MPU_OPP50_FREQ,
1301 + },
1302 + {
1303 + .efuse_offs = AM33XX_SR1_OPP100_CNTRL_OFFSET,
1304 + .e2v_gain = AM33XX_SR1_OPP100_EVM_ERR2VOLT_GAIN,
1305 + .err_minlimit = AM33XX_SR1_OPP100_EVM_ERR_MIN_LIMIT,
1306 + .err_maxlimit = AM33XX_SR1_OPP100_ERR_MAX_LIMIT,
1307 + .err_weight = AM33XX_SR1_OPP100_ERR_WEIGHT,
1308 + .margin = AM33XX_SR1_OPP100_MARGIN,
1309 + .nominal_volt = AM33XX_VDD_MPU_OPP100_UV,
1310 + .frequency = AM33XX_VDD_MPU_OPP100_FREQ,
1311 + },
1312 + {
1313 + .efuse_offs = AM33XX_SR1_OPP120_CNTRL_OFFSET,
1314 + .e2v_gain = AM33XX_SR1_OPP120_EVM_ERR2VOLT_GAIN,
1315 + .err_minlimit = AM33XX_SR1_OPP120_EVM_ERR_MIN_LIMIT,
1316 + .err_maxlimit = AM33XX_SR1_OPP120_ERR_MAX_LIMIT,
1317 + .err_weight = AM33XX_SR1_OPP120_ERR_WEIGHT,
1318 + .margin = AM33XX_SR1_OPP120_MARGIN,
1319 + .nominal_volt = AM33XX_VDD_MPU_OPP120_UV,
1320 + .frequency = AM33XX_VDD_MPU_OPP120_FREQ,
1321 + },
1322 + {
1323 + .efuse_offs = AM33XX_SR1_OPPTURBO_CNTRL_OFFSET,
1324 + .e2v_gain = AM33XX_SR1_OPPTURBO_EVM_ERR2VOLT_GAIN,
1325 + .err_minlimit = AM33XX_SR1_OPPTURBO_EVM_ERR_MIN_LIMIT,
1326 + .err_maxlimit = AM33XX_SR1_OPPTURBO_ERR_MAX_LIMIT,
1327 + .err_weight = AM33XX_SR1_OPPTURBO_ERR_WEIGHT,
1328 + .margin = AM33XX_SR1_OPPTURBO_MARGIN,
1329 + .nominal_volt = AM33XX_VDD_MPU_OPPTURBO_UV,
1330 + .frequency = AM33XX_VDD_MPU_OPPTURBO_FREQ,
1331 + },
1332 +};
1333 +
1334 +static struct am33xx_sr_opp_data sr0_opp_data[] = {
1335 + {
1336 + .efuse_offs = AM33XX_SR0_OPP50_CNTRL_OFFSET,
1337 + .e2v_gain = AM33XX_SR0_OPP50_EVM_ERR2VOLT_GAIN,
1338 + .err_minlimit = AM33XX_SR0_OPP50_EVM_ERR_MIN_LIMIT,
1339 + .err_maxlimit = AM33XX_SR0_OPP50_ERR_MAX_LIMIT,
1340 + .err_weight = AM33XX_SR0_OPP50_ERR_WEIGHT,
1341 + .margin = AM33XX_SR0_OPP50_MARGIN,
1342 + .nominal_volt = AM33XX_VDD_CORE_OPP50_UV,
1343 + },
1344 + {
1345 + .efuse_offs = AM33XX_SR0_OPP100_CNTRL_OFFSET,
1346 + .e2v_gain = AM33XX_SR0_OPP100_EVM_ERR2VOLT_GAIN,
1347 + .err_minlimit = AM33XX_SR0_OPP100_EVM_ERR_MIN_LIMIT,
1348 + .err_maxlimit = AM33XX_SR0_OPP100_ERR_MAX_LIMIT,
1349 + .err_weight = AM33XX_SR0_OPP100_ERR_WEIGHT,
1350 + .margin = AM33XX_SR0_OPP100_MARGIN,
1351 + .nominal_volt = AM33XX_VDD_CORE_OPP100_UV,
1352 + },
1353 +};
1354 +
1355 +static struct am33xx_sr_sdata sr_sensor_data[] = {
1356 + {
1357 + .sr_opp_data = sr0_opp_data,
1358 + /* note that OPP50 is NOT used in Linux kernel for AM335x */
1359 + .no_of_opps = 0x2,
1360 + .default_opp = 0x1,
1361 + .senn_mod = 0x1,
1362 + .senp_mod = 0x1,
1363 + },
1364 + {
1365 + .sr_opp_data = sr1_opp_data,
1366 + /* the opp data below should be determined
1367 + dynamically during SR probe */
1368 + .no_of_opps = 0x4,
1369 + .default_opp = 0x3,
1370 + .senn_mod = 0x1,
1371 + .senp_mod = 0x1,
1372 + },
1373 +};
1374 +
1375 +static struct am33xx_sr_platform_data am33xx_sr_pdata = {
1376 + .vd_name[0] = "vdd_core",
1377 + .vd_name[1] = "vdd_mpu",
1378 + .ip_type = 2,
1379 + .irq_delay = 1000,
1380 + .no_of_vds = 2,
1381 + .no_of_sens = ARRAY_SIZE(sr_sensor_data),
1382 + .vstep_size_uv = 12500,
1383 + .enable_on_init = true,
1384 + .sr_sdata = sr_sensor_data,
1385 +};
1386 +
1387 +static struct resource am33xx_sr_resources[] = {
1388 + {
1389 + .name = "smartreflex0",
1390 + .start = AM33XX_SR0_BASE,
1391 + .end = AM33XX_SR0_BASE + SZ_4K - 1,
1392 + .flags = IORESOURCE_MEM,
1393 + },
1394 + {
1395 + .name = "smartreflex0",
1396 + .start = AM33XX_IRQ_SMARTREFLEX0,
1397 + .end = AM33XX_IRQ_SMARTREFLEX0,
1398 + .flags = IORESOURCE_IRQ,
1399 + },
1400 + {
1401 + .name = "smartreflex1",
1402 + .start = AM33XX_SR1_BASE,
1403 + .end = AM33XX_SR1_BASE + SZ_4K - 1,
1404 + .flags = IORESOURCE_MEM,
1405 + },
1406 + {
1407 + .name = "smartreflex1",
1408 + .start = AM33XX_IRQ_SMARTREFLEX1,
1409 + .end = AM33XX_IRQ_SMARTREFLEX1,
1410 + .flags = IORESOURCE_IRQ,
1411 + },
1412 +};
1413 +
1414 +/* VCORE for SR regulator init */
1415 +static struct platform_device am33xx_sr_device = {
1416 + .name = "smartreflex",
1417 + .id = -1,
1418 + .num_resources = ARRAY_SIZE(am33xx_sr_resources),
1419 + .resource = am33xx_sr_resources,
1420 + .dev = {
1421 + .platform_data = &am33xx_sr_pdata,
1422 + },
1423 +};
1424 +
1425 +void __init am33xx_sr_init(void)
1426 +{
1427 + /* For beaglebone, update voltage step size and related parameters
1428 + appropriately. All other AM33XX platforms are good with the
1429 + structure defaults as initialized above. */
1430 + if ((am33xx_evmid == BEAGLE_BONE_OLD) ||
1431 + (am33xx_evmid == BEAGLE_BONE_A3)) {
1432 + printk(KERN_ERR "address of pdata = %08x\n", (u32)&am33xx_sr_pdata);
1433 + am33xx_sr_pdata.vstep_size_uv = 25000;
1434 + /* CORE */
1435 + sr0_opp_data[0].e2v_gain = AM33XX_SR0_OPP50_BB_ERR2VOLT_GAIN;
1436 + sr0_opp_data[0].err_minlimit = AM33XX_SR0_OPP50_BB_ERR_MIN_LIMIT;
1437 + sr0_opp_data[1].e2v_gain = AM33XX_SR0_OPP100_BB_ERR2VOLT_GAIN;
1438 + sr0_opp_data[1].err_minlimit = AM33XX_SR0_OPP100_BB_ERR_MIN_LIMIT;
1439 + /* MPU */
1440 + sr1_opp_data[0].e2v_gain = AM33XX_SR1_OPP50_BB_ERR2VOLT_GAIN;
1441 + sr1_opp_data[0].err_minlimit = AM33XX_SR1_OPP50_BB_ERR_MIN_LIMIT;
1442 + sr1_opp_data[1].e2v_gain = AM33XX_SR1_OPP100_BB_ERR2VOLT_GAIN;
1443 + sr1_opp_data[1].err_minlimit = AM33XX_SR1_OPP100_BB_ERR_MIN_LIMIT;
1444 + sr1_opp_data[2].e2v_gain = AM33XX_SR1_OPP120_BB_ERR2VOLT_GAIN;
1445 + sr1_opp_data[2].err_minlimit = AM33XX_SR1_OPP120_BB_ERR_MIN_LIMIT;
1446 + sr1_opp_data[3].e2v_gain = AM33XX_SR1_OPPTURBO_BB_ERR2VOLT_GAIN;
1447 + sr1_opp_data[3].err_minlimit = AM33XX_SR1_OPPTURBO_BB_ERR_MIN_LIMIT;
1448 + }
1449 +
1450 + if (platform_device_register(&am33xx_sr_device))
1451 + printk(KERN_ERR "failed to register am33xx_sr device\n");
1452 + else
1453 + printk(KERN_INFO "registered am33xx_sr device\n");
1454 +}
1455 +#else
1456 +inline void am33xx_sr_init(void) {}
1457 +#endif
1458 +
1459 /*-------------------------------------------------------------------------*/
1461 static int __init omap2_init_devices(void)
1462 diff --git a/arch/arm/mach-omap2/include/mach/board-am335xevm.h b/arch/arm/mach-omap2/include/mach/board-am335xevm.h
1463 index 1d24495..85a8df0 100644
1464 --- a/arch/arm/mach-omap2/include/mach/board-am335xevm.h
1465 +++ b/arch/arm/mach-omap2/include/mach/board-am335xevm.h
1466 @@ -41,6 +41,7 @@
1467 void am335x_evm_set_id(unsigned int evmid);
1468 int am335x_evm_get_id(void);
1469 void am33xx_cpsw_macidfillup(char *eeprommacid0, char *eeprommacid1);
1470 +void am33xx_sr_init(void);
1471 void am33xx_d_can_init(unsigned int instance);
1473 #endif
1474 diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig
1475 index 734009a..33f17f2 100644
1476 --- a/arch/arm/plat-omap/Kconfig
1477 +++ b/arch/arm/plat-omap/Kconfig
1478 @@ -43,6 +43,27 @@ config OMAP_DEBUG_LEDS
1479 depends on OMAP_DEBUG_DEVICES
1480 default y if LEDS_CLASS
1482 +config AM33XX_SMARTREFLEX
1483 + bool "AM33XX SmartReflex support"
1484 + depends on (SOC_OMAPAM33XX) && PM
1485 + help
1486 + Say Y if you want to enable SmartReflex.
1487 +
1488 + SmartReflex can perform continuous dynamic voltage
1489 + scaling around the nominal operating point voltage
1490 + according to silicon characteristics and operating
1491 + conditions. Enabling SmartReflex reduces active power
1492 + consumption.
1493 +
1494 + Please note, that by default SmartReflex is enabled.
1495 + To disable the automatic voltage compensation for
1496 + vdd mpu and vdd core from user space, user must
1497 + write 1 to /debug/smartreflex/autocomp.
1498 +
1499 + Optionally autocompensation can be disabled in the kernel
1500 + by default during system init via the enable_on_init flag
1501 + which an be passed as platform data to the smartreflex driver.
1502 +
1503 config OMAP_SMARTREFLEX
1504 bool "SmartReflex support"
1505 depends on (ARCH_OMAP3 || ARCH_OMAP4) && PM
1506 diff --git a/arch/arm/plat-omap/include/plat/am33xx.h b/arch/arm/plat-omap/include/plat/am33xx.h
1507 index 32522df..a628b1f 100644
1508 --- a/arch/arm/plat-omap/include/plat/am33xx.h
1509 +++ b/arch/arm/plat-omap/include/plat/am33xx.h
1510 @@ -43,6 +43,9 @@
1511 #define AM33XX_TSC_BASE 0x44E0D000
1512 #define AM33XX_RTC_BASE 0x44E3E000
1514 +#define AM33XX_SR0_BASE 0x44E37000
1515 +#define AM33XX_SR1_BASE 0x44E39000
1516 +
1517 #define AM33XX_ASP0_BASE 0x48038000
1518 #define AM33XX_ASP1_BASE 0x4803C000
1520 diff --git a/arch/arm/plat-omap/include/plat/smartreflex.h b/arch/arm/plat-omap/include/plat/smartreflex.h
1521 new file mode 100644
1522 index 0000000..36338f7
1523 --- /dev/null
1524 +++ b/arch/arm/plat-omap/include/plat/smartreflex.h
1525 @@ -0,0 +1,431 @@
1526 +/*
1527 + * OMAP Smartreflex Defines and Routines
1528 + *
1529 + * Author: Thara Gopinath <thara@ti.com>
1530 + *
1531 + * Copyright (C) 2010 Texas Instruments, Inc.
1532 + * Thara Gopinath <thara@ti.com>
1533 + *
1534 + * Copyright (C) 2008 Nokia Corporation
1535 + * Kalle Jokiniemi
1536 + *
1537 + * Copyright (C) 2007 Texas Instruments, Inc.
1538 + * Lesly A M <x0080970@ti.com>
1539 + *
1540 + * This program is free software; you can redistribute it and/or modify
1541 + * it under the terms of the GNU General Public License version 2 as
1542 + * published by the Free Software Foundation.
1543 + */
1544 +
1545 +#ifndef __ASM_ARM_OMAP_SMARTREFLEX_H
1546 +#define __ASM_ARM_OMAP_SMARTREFLEX_H
1547 +
1548 +#include <linux/platform_device.h>
1549 +#include <plat/voltage.h>
1550 +
1551 +/*
1552 + * Different Smartreflex IPs version. The v1 is the 65nm version used in
1553 + * OMAP3430. The v2 is the update for the 45nm version of the IP
1554 + * used in OMAP3630 and OMAP4430
1555 + */
1556 +#define SR_TYPE_V1 1
1557 +#define SR_TYPE_V2 2
1558 +
1559 +/* SMART REFLEX REG ADDRESS OFFSET */
1560 +#define SRCONFIG 0x00
1561 +#define SRSTATUS 0x04
1562 +#define SENVAL 0x08
1563 +#define SENMIN 0x0C
1564 +#define SENMAX 0x10
1565 +#define SENAVG 0x14
1566 +#define AVGWEIGHT 0x18
1567 +#define NVALUERECIPROCAL 0x1c
1568 +#define SENERROR_V1 0x20
1569 +#define ERRCONFIG_V1 0x24
1570 +#define IRQ_EOI 0x20
1571 +#define IRQSTATUS_RAW 0x24
1572 +#define IRQSTATUS 0x28
1573 +#define IRQENABLE_SET 0x2C
1574 +#define IRQENABLE_CLR 0x30
1575 +#define SENERROR_V2 0x34
1576 +#define ERRCONFIG_V2 0x38
1577 +
1578 +/* Bit/Shift Positions */
1579 +
1580 +/* SRCONFIG */
1581 +#define SRCONFIG_ACCUMDATA_SHIFT 22
1582 +#define SRCONFIG_SRCLKLENGTH_SHIFT 12
1583 +#define SRCONFIG_SENNENABLE_V1_SHIFT 5
1584 +#define SRCONFIG_SENPENABLE_V1_SHIFT 3
1585 +#define SRCONFIG_SENNENABLE_V2_SHIFT 1
1586 +#define SRCONFIG_SENPENABLE_V2_SHIFT 0
1587 +#define SRCONFIG_CLKCTRL_SHIFT 0
1588 +
1589 +#define SRCONFIG_ACCUMDATA_MASK (0x3ff << 22)
1590 +
1591 +#define SRCONFIG_SRENABLE BIT(11)
1592 +#define SRCONFIG_SENENABLE BIT(10)
1593 +#define SRCONFIG_ERRGEN_EN BIT(9)
1594 +#define SRCONFIG_MINMAXAVG_EN BIT(8)
1595 +#define SRCONFIG_DELAYCTRL BIT(2)
1596 +
1597 +/* AVGWEIGHT */
1598 +#define AVGWEIGHT_SENPAVGWEIGHT_SHIFT 2
1599 +#define AVGWEIGHT_SENNAVGWEIGHT_SHIFT 0
1600 +
1601 +/* NVALUERECIPROCAL */
1602 +#define NVALUERECIPROCAL_SENPGAIN_SHIFT 20
1603 +#define NVALUERECIPROCAL_SENNGAIN_SHIFT 16
1604 +#define NVALUERECIPROCAL_RNSENP_SHIFT 8
1605 +#define NVALUERECIPROCAL_RNSENN_SHIFT 0
1606 +
1607 +/* ERRCONFIG */
1608 +#define ERRCONFIG_ERRWEIGHT_SHIFT 16
1609 +#define ERRCONFIG_ERRMAXLIMIT_SHIFT 8
1610 +#define ERRCONFIG_ERRMINLIMIT_SHIFT 0
1611 +
1612 +#define SR_ERRWEIGHT_MASK (0x07 << 16)
1613 +#define SR_ERRMAXLIMIT_MASK (0xff << 8)
1614 +#define SR_ERRMINLIMIT_MASK (0xff << 0)
1615 +
1616 +#define ERRCONFIG_VPBOUNDINTEN_V1 BIT(31)
1617 +#define ERRCONFIG_VPBOUNDINTST_V1 BIT(30)
1618 +#define ERRCONFIG_MCUACCUMINTEN BIT(29)
1619 +#define ERRCONFIG_MCUACCUMINTST BIT(28)
1620 +#define ERRCONFIG_MCUVALIDINTEN BIT(27)
1621 +#define ERRCONFIG_MCUVALIDINTST BIT(26)
1622 +#define ERRCONFIG_MCUBOUNDINTEN BIT(25)
1623 +#define ERRCONFIG_MCUBOUNDINTST BIT(24)
1624 +#define ERRCONFIG_MCUDISACKINTEN BIT(23)
1625 +#define ERRCONFIG_VPBOUNDINTST_V2 BIT(23)
1626 +#define ERRCONFIG_MCUDISACKINTST BIT(22)
1627 +#define ERRCONFIG_VPBOUNDINTEN_V2 BIT(22)
1628 +
1629 +#define ERRCONFIG_STATUS_V1_MASK (ERRCONFIG_VPBOUNDINTST_V1 | \
1630 + ERRCONFIG_MCUACCUMINTST | \
1631 + ERRCONFIG_MCUVALIDINTST | \
1632 + ERRCONFIG_MCUBOUNDINTST | \
1633 + ERRCONFIG_MCUDISACKINTST)
1634 +/* IRQSTATUS */
1635 +#define IRQSTATUS_MCUACCUMINT BIT(3)
1636 +#define IRQSTATUS_MCVALIDINT BIT(2)
1637 +#define IRQSTATUS_MCBOUNDSINT BIT(1)
1638 +#define IRQSTATUS_MCUDISABLEACKINT BIT(0)
1639 +
1640 +/* IRQENABLE_SET and IRQENABLE_CLEAR */
1641 +#define IRQENABLE_MCUACCUMINT BIT(3)
1642 +#define IRQENABLE_MCUVALIDINT BIT(2)
1643 +#define IRQENABLE_MCUBOUNDSINT BIT(1)
1644 +#define IRQENABLE_MCUDISABLEACKINT BIT(0)
1645 +
1646 +/* Common Bit values */
1647 +
1648 +#define SRCLKLENGTH_12MHZ_SYSCLK 0x3c
1649 +#define SRCLKLENGTH_13MHZ_SYSCLK 0x41
1650 +#define SRCLKLENGTH_19MHZ_SYSCLK 0x60
1651 +#define SRCLKLENGTH_26MHZ_SYSCLK 0x82
1652 +#define SRCLKLENGTH_38MHZ_SYSCLK 0xC0
1653 +
1654 +/*
1655 + * 3430 specific values. Maybe these should be passed from board file or
1656 + * pmic structures.
1657 + */
1658 +#define OMAP3430_SR_ACCUMDATA 0x1f4
1659 +
1660 +#define OMAP3430_SR1_SENPAVGWEIGHT 0x03
1661 +#define OMAP3430_SR1_SENNAVGWEIGHT 0x03
1662 +
1663 +#define OMAP3430_SR2_SENPAVGWEIGHT 0x01
1664 +#define OMAP3430_SR2_SENNAVGWEIGHT 0x01
1665 +
1666 +#define OMAP3430_SR_ERRWEIGHT 0x04
1667 +#define OMAP3430_SR_ERRMAXLIMIT 0x02
1668 +
1669 +/**
1670 + * struct omap_sr_pmic_data - Strucutre to be populated by pmic code to pass
1671 + * pmic specific info to smartreflex driver
1672 + *
1673 + * @sr_pmic_init: API to initialize smartreflex on the PMIC side.
1674 + */
1675 +struct omap_sr_pmic_data {
1676 + void (*sr_pmic_init) (void);
1677 +};
1678 +
1679 +#ifdef CONFIG_OMAP_SMARTREFLEX
1680 +/*
1681 + * The smart reflex driver supports CLASS1 CLASS2 and CLASS3 SR.
1682 + * The smartreflex class driver should pass the class type.
1683 + * Should be used to populate the class_type field of the
1684 + * omap_smartreflex_class_data structure.
1685 + */
1686 +#define SR_CLASS1 0x1
1687 +#define SR_CLASS2 0x2
1688 +#define SR_CLASS3 0x3
1689 +
1690 +/**
1691 + * struct omap_sr_class_data - Smartreflex class driver info
1692 + *
1693 + * @enable: API to enable a particular class smaartreflex.
1694 + * @disable: API to disable a particular class smartreflex.
1695 + * @configure: API to configure a particular class smartreflex.
1696 + * @notify: API to notify the class driver about an event in SR.
1697 + * Not needed for class3.
1698 + * @notify_flags: specify the events to be notified to the class driver
1699 + * @class_type: specify which smartreflex class.
1700 + * Can be used by the SR driver to take any class
1701 + * based decisions.
1702 + */
1703 +struct omap_sr_class_data {
1704 + int (*enable)(struct voltagedomain *voltdm);
1705 + int (*disable)(struct voltagedomain *voltdm, int is_volt_reset);
1706 + int (*configure)(struct voltagedomain *voltdm);
1707 + int (*notify)(struct voltagedomain *voltdm, u32 status);
1708 + u8 notify_flags;
1709 + u8 class_type;
1710 +};
1711 +
1712 +/**
1713 + * struct omap_sr_nvalue_table - Smartreflex n-target value info
1714 + *
1715 + * @efuse_offs: The offset of the efuse where n-target values are stored.
1716 + * @nvalue: The n-target value.
1717 + */
1718 +struct omap_sr_nvalue_table {
1719 + u32 efuse_offs;
1720 + u32 nvalue;
1721 +};
1722 +
1723 +/**
1724 + * struct omap_sr_data - Smartreflex platform data.
1725 + *
1726 + * @ip_type: Smartreflex IP type.
1727 + * @senp_mod: SENPENABLE value for the sr
1728 + * @senn_mod: SENNENABLE value for sr
1729 + * @nvalue_count: Number of distinct nvalues in the nvalue table
1730 + * @enable_on_init: whether this sr module needs to enabled at
1731 + * boot up or not.
1732 + * @nvalue_table: table containing the efuse offsets and nvalues
1733 + * corresponding to them.
1734 + * @voltdm: Pointer to the voltage domain associated with the SR
1735 + */
1736 +struct omap_sr_data {
1737 + int ip_type;
1738 + u32 senp_mod;
1739 + u32 senn_mod;
1740 + int nvalue_count;
1741 + bool enable_on_init;
1742 + struct omap_sr_nvalue_table *nvalue_table;
1743 + struct voltagedomain *voltdm;
1744 +};
1745 +
1746 +/* Smartreflex module enable/disable interface */
1747 +void omap_sr_enable(struct voltagedomain *voltdm);
1748 +void omap_sr_disable(struct voltagedomain *voltdm);
1749 +void omap_sr_disable_reset_volt(struct voltagedomain *voltdm);
1750 +
1751 +/* API to register the pmic specific data with the smartreflex driver. */
1752 +void omap_sr_register_pmic(struct omap_sr_pmic_data *pmic_data);
1753 +
1754 +/* Smartreflex driver hooks to be called from Smartreflex class driver */
1755 +int sr_enable(struct voltagedomain *voltdm, unsigned long volt);
1756 +void sr_disable(struct voltagedomain *voltdm);
1757 +int sr_configure_errgen(struct voltagedomain *voltdm);
1758 +int sr_configure_minmax(struct voltagedomain *voltdm);
1759 +
1760 +/* API to register the smartreflex class driver with the smartreflex driver */
1761 +int sr_register_class(struct omap_sr_class_data *class_data);
1762 +#else
1763 +
1764 +#ifdef CONFIG_AM33XX_SMARTREFLEX
1765 +
1766 +#define SR_CORE (0)
1767 +#define SR_MPU (1)
1768 +#define SRCLKLENGTH_125MHZ_SYSCLK (0x78 << 12)
1769 +#define GAIN_MAXLIMIT (16)
1770 +#define R_MAXLIMIT (256)
1771 +#define MAX_SENSORS 2
1772 +/* GG: eventually this should be determined at runtime */
1773 +#define AM33XX_OPP_COUNT 4
1774 +
1775 +/**
1776 + * struct am33xx_sr_opp_data - Smartreflex data per OPP
1777 + * @efuse_offs: The offset of the efuse where n-target values are
1778 + * stored.
1779 + * @nvalue: NTarget as stored in EFUSE.
1780 + * @adj_nvalue: Adjusted NTarget (adjusted by margin)
1781 + * @e2v_gain: Error to voltage gain for changing the percentage
1782 + * error into voltage delta
1783 + * @err_weight: Average sensor error weight
1784 + * @err_minlimit: Minimum error limit of the sensor
1785 + * @err_maxlimit: Maximum error limit of the sensor
1786 + * @margin: Voltage margin to apply
1787 + * @nominal_volt: Nominal voltage for this OPP
1788 + * @frequency: Defined frequency for this OPP (in KHz)
1789 + */
1790 +struct am33xx_sr_opp_data {
1791 + u32 efuse_offs;
1792 + u32 nvalue;
1793 + u32 adj_nvalue;
1794 + s32 e2v_gain;
1795 + u32 err_weight;
1796 + u32 err_minlimit;
1797 + u32 err_maxlimit;
1798 + s32 margin;
1799 + u32 nominal_volt; /* nominal_volt and frequency may be removed
1800 + once am33xx voltdm layer works */
1801 + u32 frequency;
1802 + u32 opp_id;
1803 +};
1804 +
1805 +/**
1806 + * struct am33xx_sr_sdata - Smartreflex sensors data
1807 + * @sr_opp_data: Pointer to data structure containing per OPP data
1808 + * for this SR module.
1809 + * @no_of_opps: Number of OPP's supported for this sensor -
1810 + * determined dynamically when possible.
1811 + * @default_opp: Defines the opp to use on startup if OPP is fixed
1812 + * or cannot be determined dynamically.
1813 + * @senn_mod: Enable bit for N sensor
1814 + * @senp_mod: Enable bit for P sensor
1815 + */
1816 +struct am33xx_sr_sdata {
1817 + struct am33xx_sr_opp_data *sr_opp_data;
1818 + u32 no_of_opps;
1819 + u32 default_opp;
1820 + u32 senn_mod;
1821 + u32 senp_mod;
1822 +};
1823 +
1824 +struct am33xx_sr_sensor {
1825 + u32 sr_id;
1826 + u32 irq;
1827 + u32 irq_status;
1828 + u32 senn_en;
1829 + u32 senp_en;
1830 + char *name;
1831 + char *reg_name;
1832 + void __iomem *base;
1833 + int init_volt_mv;
1834 + int curr_opp;
1835 + u32 no_of_opps;
1836 + struct delayed_work work_reenable;
1837 + struct regulator *reg;
1838 + struct am33xx_sr_opp_data opp_data[AM33XX_OPP_COUNT];
1839 + struct clk *fck;
1840 + struct voltagedomain *voltdm;
1841 + struct omap_volt_data *volt_data;
1842 +};
1843 +
1844 +struct am33xx_sr {
1845 + u32 autocomp_active;
1846 + u32 sens_per_vd;
1847 + u32 no_of_sens;
1848 + u32 no_of_vds;
1849 + u32 ip_type;
1850 + u32 irq_delay;
1851 + u32 disabled_by_user;
1852 + int uvoltage_step_size;
1853 + char *res_name[MAX_SENSORS];
1854 +#ifdef CONFIG_CPU_FREQ
1855 + struct notifier_block freq_transition;
1856 +#endif
1857 + /*struct work_struct work;*/
1858 + struct delayed_work work;
1859 + struct sr_platform_data *sr_data;
1860 + struct am33xx_sr_sensor sen[MAX_SENSORS];
1861 + struct platform_device *pdev;
1862 +};
1863 +
1864 +/**
1865 + * struct am33xx_sr_platform_data - Smartreflex platform data.
1866 + * @sr_sdata: SR per sensor details, contains the efuse off-sets,
1867 + * error to voltage gain factor, minimum error limits
1868 + * @vd_name: Name of the voltage domain.
1869 + * @ip_type: Smartreflex IP type, class1 or class2 or class3.
1870 + * @irq_delay: Amount of time required for changed voltage to settle.
1871 + * @no_of_vds: Number of voltage domains to which SR applicable
1872 + * @no_of_sens: Number of SR sensors used to monitor the device
1873 + * performance, temp etc...
1874 + * @vstep_size_uv: PMIC voltage step size in micro volts
1875 + * @enable_on_init: whether this sr module needs to enabled at
1876 + * boot up or not.
1877 + */
1878 +struct am33xx_sr_platform_data {
1879 + struct am33xx_sr_sdata *sr_sdata;
1880 + char *vd_name[2];
1881 + u32 ip_type;
1882 + u32 irq_delay;
1883 + u32 no_of_vds;
1884 + u32 no_of_sens;
1885 + u32 vstep_size_uv;
1886 + bool enable_on_init;
1887 +};
1888 +
1889 +#endif /*CONFIG_AM33XX_SMARTREFLEX*/
1890 +
1891 +#ifdef CONFIG_TI816X_SMARTREFLEX
1892 +
1893 +#define SRHVT 0
1894 +#define SRSVT 1
1895 +
1896 +/* SRClk = 100KHz */
1897 +#define SRCLKLENGTH_125MHZ_SYSCLK (0x271 << 12)
1898 +
1899 +/**
1900 + * struct ti816x_sr_sdata - Smartreflex sensors data
1901 + * @efuse_offs: The offset of the efuse where n-target values are
1902 + * stored.
1903 + * @e2v_gain: Error to voltage gain for changing the percentage
1904 + * error into voltage delta
1905 + * @err_weight: Average sensor error weight
1906 + * @err_minlimit: Minimum error limit of the sensor
1907 + * @err_maxlimit: Maximum error limit of the sensor
1908 + * @senn_mod: Enable bit for N sensor
1909 + * @senp_mod: Enable bit for P sensor
1910 + */
1911 +struct ti816x_sr_sdata {
1912 + u32 efuse_offs;
1913 + u32 e2v_gain;
1914 + u32 err_weight;
1915 + u32 err_minlimit;
1916 + u32 err_maxlimit;
1917 + u32 senn_mod;
1918 + u32 senp_mod;
1919 +};
1920 +
1921 +/**
1922 + * struct ti816x_sr_platform_data - Smartreflex platform data.
1923 + * @sr_sdata: SR per sensor details, contains the efuse off-sets,
1924 + * error to voltage gain factor, minimum error limits
1925 + * @vd_name: Name of the voltage domain.
1926 + * @ip_type: Smartreflex IP type, class1 or class2 or class3.
1927 + * @irq_delay: Time delay between disable and re-enable the
1928 + * interrupts, in msec
1929 + * @no_of_vds: Number of voltage domains to which SR applicable
1930 + * @no_of_sens: Number of SR sensors used to monitor the device
1931 + * performance, temp etc...
1932 + * @vstep_size_uv: PMIC voltage step size in micro volts
1933 + * @enable_on_init: whether this sr module needs to enabled at
1934 + * boot up or not.
1935 + */
1936 +struct ti816x_sr_platform_data {
1937 + struct ti816x_sr_sdata *sr_sdata;
1938 + char *vd_name;
1939 + u32 ip_type;
1940 + u32 irq_delay;
1941 + u32 no_of_vds;
1942 + u32 no_of_sens;
1943 + u32 vstep_size_uv;
1944 + bool enable_on_init;
1945 +};
1946 +
1947 +#endif /* CONFIG_TI816X_SMARTREFLEX */
1948 +
1949 +static inline void omap_sr_enable(struct voltagedomain *voltdm) {}
1950 +static inline void omap_sr_disable(struct voltagedomain *voltdm) {}
1951 +static inline void omap_sr_disable_reset_volt(
1952 + struct voltagedomain *voltdm) {}
1953 +static inline void omap_sr_register_pmic(
1954 + struct omap_sr_pmic_data *pmic_data) {}
1955 +#endif
1956 +#endif
1957 diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
1958 index 00706c6..382ce2d 100644
1959 --- a/drivers/regulator/core.c
1960 +++ b/drivers/regulator/core.c
1961 @@ -169,6 +169,9 @@ static int regulator_check_consumers(struct regulator_dev *rdev,
1962 {
1963 struct regulator *regulator;
1965 + if (rdev->ignore_check_consumers)
1966 + return 0;
1967 +
1968 list_for_each_entry(regulator, &rdev->consumer_list, list) {
1969 /*
1970 * Assume consumers that didn't say anything are OK
1971 @@ -2688,6 +2691,7 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc,
1972 rdev->reg_data = driver_data;
1973 rdev->owner = regulator_desc->owner;
1974 rdev->desc = regulator_desc;
1975 + rdev->ignore_check_consumers = init_data->ignore_check_consumers;
1976 INIT_LIST_HEAD(&rdev->consumer_list);
1977 INIT_LIST_HEAD(&rdev->list);
1978 BLOCKING_INIT_NOTIFIER_HEAD(&rdev->notifier);
1979 diff --git a/include/linux/regulator/driver.h b/include/linux/regulator/driver.h
1980 index 52c89ae..6176167 100644
1981 --- a/include/linux/regulator/driver.h
1982 +++ b/include/linux/regulator/driver.h
1983 @@ -204,7 +204,7 @@ struct regulator_dev {
1984 int deferred_disables;
1986 void *reg_data; /* regulator_dev data */
1987 -
1988 + int ignore_check_consumers;
1989 #ifdef CONFIG_DEBUG_FS
1990 struct dentry *debugfs;
1991 #endif
1992 diff --git a/include/linux/regulator/machine.h b/include/linux/regulator/machine.h
1993 index f3f13fd..0de52a3 100644
1994 --- a/include/linux/regulator/machine.h
1995 +++ b/include/linux/regulator/machine.h
1996 @@ -169,7 +169,7 @@ struct regulator_consumer_supply {
1997 * be usable.
1998 * @num_consumer_supplies: Number of consumer device supplies.
1999 * @consumer_supplies: Consumer device supply configuration.
2000 - *
2001 + * @ignore_check_consumers: If != 0, regulator_check_consumers() is disabled.
2002 * @regulator_init: Callback invoked when the regulator has been registered.
2003 * @driver_data: Data passed to regulator_init.
2004 */
2005 @@ -181,6 +181,7 @@ struct regulator_init_data {
2006 int num_consumer_supplies;
2007 struct regulator_consumer_supply *consumer_supplies;
2009 + int ignore_check_consumers;
2010 /* optional regulator machine specific init */
2011 int (*regulator_init)(void *driver_data);
2012 void *driver_data; /* core does not touch this */
2013 --
2014 1.7.0.4