OMAP4: Smartreflex framework extensions
[deliverable/linux.git] / arch / arm / mach-omap2 / smartreflex.c
CommitLineData
984aa6db
TG
1/*
2 * OMAP SmartReflex Voltage Control
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#include <linux/interrupt.h>
21#include <linux/clk.h>
22#include <linux/io.h>
23#include <linux/debugfs.h>
24#include <linux/delay.h>
25#include <linux/slab.h>
26#include <linux/pm_runtime.h>
27
28#include <plat/common.h>
29#include <plat/smartreflex.h>
30
31#include "pm.h"
32
33#define SMARTREFLEX_NAME_LEN 16
077fceca 34#define NVALUE_NAME_LEN 40
984aa6db
TG
35#define SR_DISABLE_TIMEOUT 200
36
37struct omap_sr {
38 int srid;
39 int ip_type;
40 int nvalue_count;
41 bool autocomp_active;
42 u32 clk_length;
43 u32 err_weight;
44 u32 err_minlimit;
45 u32 err_maxlimit;
46 u32 accum_data;
47 u32 senn_avgweight;
48 u32 senp_avgweight;
49 u32 senp_mod;
50 u32 senn_mod;
51 unsigned int irq;
52 void __iomem *base;
53 struct platform_device *pdev;
54 struct list_head node;
55 struct omap_sr_nvalue_table *nvalue_table;
56 struct voltagedomain *voltdm;
57};
58
59/* sr_list contains all the instances of smartreflex module */
60static LIST_HEAD(sr_list);
61
62static struct omap_sr_class_data *sr_class;
63static struct omap_sr_pmic_data *sr_pmic_data;
64
65static inline void sr_write_reg(struct omap_sr *sr, unsigned offset, u32 value)
66{
67 __raw_writel(value, (sr->base + offset));
68}
69
70static inline void sr_modify_reg(struct omap_sr *sr, unsigned offset, u32 mask,
71 u32 value)
72{
73 u32 reg_val;
74 u32 errconfig_offs = 0, errconfig_mask = 0;
75
76 reg_val = __raw_readl(sr->base + offset);
77 reg_val &= ~mask;
78
79 /*
80 * Smartreflex error config register is special as it contains
81 * certain status bits which if written a 1 into means a clear
82 * of those bits. So in order to make sure no accidental write of
83 * 1 happens to those status bits, do a clear of them in the read
84 * value. This mean this API doesn't rewrite values in these bits
85 * if they are currently set, but does allow the caller to write
86 * those bits.
87 */
88 if (sr->ip_type == SR_TYPE_V1) {
89 errconfig_offs = ERRCONFIG_V1;
90 errconfig_mask = ERRCONFIG_STATUS_V1_MASK;
91 } else if (sr->ip_type == SR_TYPE_V2) {
92 errconfig_offs = ERRCONFIG_V2;
93 errconfig_mask = ERRCONFIG_VPBOUNDINTST_V2;
94 }
95
96 if (offset == errconfig_offs)
97 reg_val &= ~errconfig_mask;
98
99 reg_val |= value;
100
101 __raw_writel(reg_val, (sr->base + offset));
102}
103
104static inline u32 sr_read_reg(struct omap_sr *sr, unsigned offset)
105{
106 return __raw_readl(sr->base + offset);
107}
108
109static struct omap_sr *_sr_lookup(struct voltagedomain *voltdm)
110{
111 struct omap_sr *sr_info;
112
113 if (!voltdm) {
114 pr_err("%s: Null voltage domain passed!\n", __func__);
115 return ERR_PTR(-EINVAL);
116 }
117
118 list_for_each_entry(sr_info, &sr_list, node) {
119 if (voltdm == sr_info->voltdm)
120 return sr_info;
121 }
122
123 return ERR_PTR(-ENODATA);
124}
125
126static irqreturn_t sr_interrupt(int irq, void *data)
127{
128 struct omap_sr *sr_info = (struct omap_sr *)data;
129 u32 status = 0;
130
131 if (sr_info->ip_type == SR_TYPE_V1) {
132 /* Read the status bits */
133 status = sr_read_reg(sr_info, ERRCONFIG_V1);
134
135 /* Clear them by writing back */
136 sr_write_reg(sr_info, ERRCONFIG_V1, status);
137 } else if (sr_info->ip_type == SR_TYPE_V2) {
138 /* Read the status bits */
139 sr_read_reg(sr_info, IRQSTATUS);
140
141 /* Clear them by writing back */
142 sr_write_reg(sr_info, IRQSTATUS, status);
143 }
144
145 if (sr_class->class_type == SR_CLASS2 && sr_class->notify)
146 sr_class->notify(sr_info->voltdm, status);
147
148 return IRQ_HANDLED;
149}
150
151static void sr_set_clk_length(struct omap_sr *sr)
152{
153 struct clk *sys_ck;
154 u32 sys_clk_speed;
155
b35cecf9
TG
156 if (cpu_is_omap34xx())
157 sys_ck = clk_get(NULL, "sys_ck");
158 else
159 sys_ck = clk_get(NULL, "sys_clkin_ck");
160
984aa6db
TG
161 if (IS_ERR(sys_ck)) {
162 dev_err(&sr->pdev->dev, "%s: unable to get sys clk\n",
163 __func__);
164 return;
165 }
166 sys_clk_speed = clk_get_rate(sys_ck);
167 clk_put(sys_ck);
168
169 switch (sys_clk_speed) {
170 case 12000000:
171 sr->clk_length = SRCLKLENGTH_12MHZ_SYSCLK;
172 break;
173 case 13000000:
174 sr->clk_length = SRCLKLENGTH_13MHZ_SYSCLK;
175 break;
176 case 19200000:
177 sr->clk_length = SRCLKLENGTH_19MHZ_SYSCLK;
178 break;
179 case 26000000:
180 sr->clk_length = SRCLKLENGTH_26MHZ_SYSCLK;
181 break;
182 case 38400000:
183 sr->clk_length = SRCLKLENGTH_38MHZ_SYSCLK;
184 break;
185 default:
186 dev_err(&sr->pdev->dev, "%s: Invalid sysclk value: %d\n",
187 __func__, sys_clk_speed);
188 break;
189 }
190}
191
192static void sr_set_regfields(struct omap_sr *sr)
193{
194 /*
195 * For time being these values are defined in smartreflex.h
196 * and populated during init. May be they can be moved to board
197 * file or pmic specific data structure. In that case these structure
198 * fields will have to be populated using the pdata or pmic structure.
199 */
b35cecf9 200 if (cpu_is_omap34xx() || cpu_is_omap44xx()) {
984aa6db
TG
201 sr->err_weight = OMAP3430_SR_ERRWEIGHT;
202 sr->err_maxlimit = OMAP3430_SR_ERRMAXLIMIT;
203 sr->accum_data = OMAP3430_SR_ACCUMDATA;
204 if (!(strcmp(sr->voltdm->name, "mpu"))) {
205 sr->senn_avgweight = OMAP3430_SR1_SENNAVGWEIGHT;
206 sr->senp_avgweight = OMAP3430_SR1_SENPAVGWEIGHT;
207 } else {
208 sr->senn_avgweight = OMAP3430_SR2_SENNAVGWEIGHT;
209 sr->senp_avgweight = OMAP3430_SR2_SENPAVGWEIGHT;
210 }
211 }
212}
213
214static void sr_start_vddautocomp(struct omap_sr *sr)
215{
216 if (!sr_class || !(sr_class->enable) || !(sr_class->configure)) {
217 dev_warn(&sr->pdev->dev,
218 "%s: smartreflex class driver not registered\n",
219 __func__);
220 return;
221 }
222
223 if (!sr_class->enable(sr->voltdm))
224 sr->autocomp_active = true;
225}
226
227static void sr_stop_vddautocomp(struct omap_sr *sr)
228{
229 if (!sr_class || !(sr_class->disable)) {
230 dev_warn(&sr->pdev->dev,
231 "%s: smartreflex class driver not registered\n",
232 __func__);
233 return;
234 }
235
236 if (sr->autocomp_active) {
237 sr_class->disable(sr->voltdm, 1);
238 sr->autocomp_active = false;
239 }
240}
241
242/*
243 * This function handles the intializations which have to be done
244 * only when both sr device and class driver regiter has
245 * completed. This will be attempted to be called from both sr class
246 * driver register and sr device intializtion API's. Only one call
247 * will ultimately succeed.
248 *
249 * Currenly this function registers interrrupt handler for a particular SR
250 * if smartreflex class driver is already registered and has
251 * requested for interrupts and the SR interrupt line in present.
252 */
253static int sr_late_init(struct omap_sr *sr_info)
254{
255 char *name;
256 struct omap_sr_data *pdata = sr_info->pdev->dev.platform_data;
257 struct resource *mem;
258 int ret = 0;
259
260 if (sr_class->class_type == SR_CLASS2 &&
261 sr_class->notify_flags && sr_info->irq) {
262
263 name = kzalloc(SMARTREFLEX_NAME_LEN + 1, GFP_KERNEL);
264 strcpy(name, "sr_");
265 strcat(name, sr_info->voltdm->name);
266 ret = request_irq(sr_info->irq, sr_interrupt,
267 0, name, (void *)sr_info);
268 if (ret)
269 goto error;
270 }
271
272 if (pdata && pdata->enable_on_init)
273 sr_start_vddautocomp(sr_info);
274
275 return ret;
276
277error:
278 iounmap(sr_info->base);
279 mem = platform_get_resource(sr_info->pdev, IORESOURCE_MEM, 0);
280 release_mem_region(mem->start, resource_size(mem));
281 list_del(&sr_info->node);
282 dev_err(&sr_info->pdev->dev, "%s: ERROR in registering"
283 "interrupt handler. Smartreflex will"
284 "not function as desired\n", __func__);
285 kfree(sr_info);
286 return ret;
287}
288
289static void sr_v1_disable(struct omap_sr *sr)
290{
291 int timeout = 0;
292
293 /* Enable MCUDisableAcknowledge interrupt */
294 sr_modify_reg(sr, ERRCONFIG_V1,
295 ERRCONFIG_MCUDISACKINTEN, ERRCONFIG_MCUDISACKINTEN);
296
297 /* SRCONFIG - disable SR */
298 sr_modify_reg(sr, SRCONFIG, SRCONFIG_SRENABLE, 0x0);
299
300 /* Disable all other SR interrupts and clear the status */
301 sr_modify_reg(sr, ERRCONFIG_V1,
302 (ERRCONFIG_MCUACCUMINTEN | ERRCONFIG_MCUVALIDINTEN |
303 ERRCONFIG_MCUBOUNDINTEN | ERRCONFIG_VPBOUNDINTEN_V1),
304 (ERRCONFIG_MCUACCUMINTST | ERRCONFIG_MCUVALIDINTST |
305 ERRCONFIG_MCUBOUNDINTST |
306 ERRCONFIG_VPBOUNDINTST_V1));
307
308 /*
309 * Wait for SR to be disabled.
310 * wait until ERRCONFIG.MCUDISACKINTST = 1. Typical latency is 1us.
311 */
312 omap_test_timeout((sr_read_reg(sr, ERRCONFIG_V1) &
313 ERRCONFIG_MCUDISACKINTST), SR_DISABLE_TIMEOUT,
314 timeout);
315
316 if (timeout >= SR_DISABLE_TIMEOUT)
317 dev_warn(&sr->pdev->dev, "%s: Smartreflex disable timedout\n",
318 __func__);
319
320 /* Disable MCUDisableAcknowledge interrupt & clear pending interrupt */
321 sr_modify_reg(sr, ERRCONFIG_V1, ERRCONFIG_MCUDISACKINTEN,
322 ERRCONFIG_MCUDISACKINTST);
323}
324
325static void sr_v2_disable(struct omap_sr *sr)
326{
327 int timeout = 0;
328
329 /* Enable MCUDisableAcknowledge interrupt */
330 sr_write_reg(sr, IRQENABLE_SET, IRQENABLE_MCUDISABLEACKINT);
331
332 /* SRCONFIG - disable SR */
333 sr_modify_reg(sr, SRCONFIG, SRCONFIG_SRENABLE, 0x0);
334
335 /* Disable all other SR interrupts and clear the status */
336 sr_modify_reg(sr, ERRCONFIG_V2, ERRCONFIG_VPBOUNDINTEN_V2,
337 ERRCONFIG_VPBOUNDINTST_V2);
338 sr_write_reg(sr, IRQENABLE_CLR, (IRQENABLE_MCUACCUMINT |
339 IRQENABLE_MCUVALIDINT |
340 IRQENABLE_MCUBOUNDSINT));
341 sr_write_reg(sr, IRQSTATUS, (IRQSTATUS_MCUACCUMINT |
342 IRQSTATUS_MCVALIDINT |
343 IRQSTATUS_MCBOUNDSINT));
344
345 /*
346 * Wait for SR to be disabled.
347 * wait until IRQSTATUS.MCUDISACKINTST = 1. Typical latency is 1us.
348 */
349 omap_test_timeout((sr_read_reg(sr, IRQSTATUS) &
350 IRQSTATUS_MCUDISABLEACKINT), SR_DISABLE_TIMEOUT,
351 timeout);
352
353 if (timeout >= SR_DISABLE_TIMEOUT)
354 dev_warn(&sr->pdev->dev, "%s: Smartreflex disable timedout\n",
355 __func__);
356
357 /* Disable MCUDisableAcknowledge interrupt & clear pending interrupt */
358 sr_write_reg(sr, IRQENABLE_CLR, IRQENABLE_MCUDISABLEACKINT);
359 sr_write_reg(sr, IRQSTATUS, IRQSTATUS_MCUDISABLEACKINT);
360}
361
362static u32 sr_retrieve_nvalue(struct omap_sr *sr, u32 efuse_offs)
363{
364 int i;
365
366 if (!sr->nvalue_table) {
367 dev_warn(&sr->pdev->dev, "%s: Missing ntarget value table\n",
368 __func__);
369 return 0;
370 }
371
372 for (i = 0; i < sr->nvalue_count; i++) {
373 if (sr->nvalue_table[i].efuse_offs == efuse_offs)
374 return sr->nvalue_table[i].nvalue;
375 }
376
377 return 0;
378}
379
380/* Public Functions */
381
382/**
383 * sr_configure_errgen() - Configures the smrtreflex to perform AVS using the
384 * error generator module.
385 * @voltdm: VDD pointer to which the SR module to be configured belongs to.
386 *
387 * This API is to be called from the smartreflex class driver to
388 * configure the error generator module inside the smartreflex module.
389 * SR settings if using the ERROR module inside Smartreflex.
390 * SR CLASS 3 by default uses only the ERROR module where as
391 * SR CLASS 2 can choose between ERROR module and MINMAXAVG
392 * module. Returns 0 on success and error value in case of failure.
393 */
394int sr_configure_errgen(struct voltagedomain *voltdm)
395{
396 u32 sr_config, sr_errconfig, errconfig_offs, vpboundint_en;
397 u32 vpboundint_st, senp_en = 0, senn_en = 0;
398 u8 senp_shift, senn_shift;
399 struct omap_sr *sr = _sr_lookup(voltdm);
400
401 if (IS_ERR(sr)) {
402 pr_warning("%s: omap_sr struct for sr_%s not found\n",
403 __func__, voltdm->name);
404 return -EINVAL;
405 }
406
407 if (!sr->clk_length)
408 sr_set_clk_length(sr);
409
410 senp_en = sr->senp_mod;
411 senn_en = sr->senn_mod;
412
413 sr_config = (sr->clk_length << SRCONFIG_SRCLKLENGTH_SHIFT) |
414 SRCONFIG_SENENABLE | SRCONFIG_ERRGEN_EN;
415
416 if (sr->ip_type == SR_TYPE_V1) {
417 sr_config |= SRCONFIG_DELAYCTRL;
418 senn_shift = SRCONFIG_SENNENABLE_V1_SHIFT;
419 senp_shift = SRCONFIG_SENPENABLE_V1_SHIFT;
420 errconfig_offs = ERRCONFIG_V1;
421 vpboundint_en = ERRCONFIG_VPBOUNDINTEN_V1;
422 vpboundint_st = ERRCONFIG_VPBOUNDINTST_V1;
423 } else if (sr->ip_type == SR_TYPE_V2) {
424 senn_shift = SRCONFIG_SENNENABLE_V2_SHIFT;
425 senp_shift = SRCONFIG_SENPENABLE_V2_SHIFT;
426 errconfig_offs = ERRCONFIG_V2;
427 vpboundint_en = ERRCONFIG_VPBOUNDINTEN_V2;
428 vpboundint_st = ERRCONFIG_VPBOUNDINTST_V2;
429 } else {
430 dev_err(&sr->pdev->dev, "%s: Trying to Configure smartreflex"
431 "module without specifying the ip\n", __func__);
432 return -EINVAL;
433 }
434
435 sr_config |= ((senn_en << senn_shift) | (senp_en << senp_shift));
436 sr_write_reg(sr, SRCONFIG, sr_config);
437 sr_errconfig = (sr->err_weight << ERRCONFIG_ERRWEIGHT_SHIFT) |
438 (sr->err_maxlimit << ERRCONFIG_ERRMAXLIMIT_SHIFT) |
439 (sr->err_minlimit << ERRCONFIG_ERRMINLIMIT_SHIFT);
440 sr_modify_reg(sr, errconfig_offs, (SR_ERRWEIGHT_MASK |
441 SR_ERRMAXLIMIT_MASK | SR_ERRMINLIMIT_MASK),
442 sr_errconfig);
443
444 /* Enabling the interrupts if the ERROR module is used */
445 sr_modify_reg(sr, errconfig_offs,
446 vpboundint_en, (vpboundint_en | vpboundint_st));
447
448 return 0;
449}
450
451/**
452 * sr_configure_minmax() - Configures the smrtreflex to perform AVS using the
453 * minmaxavg module.
454 * @voltdm: VDD pointer to which the SR module to be configured belongs to.
455 *
456 * This API is to be called from the smartreflex class driver to
457 * configure the minmaxavg module inside the smartreflex module.
458 * SR settings if using the ERROR module inside Smartreflex.
459 * SR CLASS 3 by default uses only the ERROR module where as
460 * SR CLASS 2 can choose between ERROR module and MINMAXAVG
461 * module. Returns 0 on success and error value in case of failure.
462 */
463int sr_configure_minmax(struct voltagedomain *voltdm)
464{
465 u32 sr_config, sr_avgwt;
466 u32 senp_en = 0, senn_en = 0;
467 u8 senp_shift, senn_shift;
468 struct omap_sr *sr = _sr_lookup(voltdm);
469
470 if (IS_ERR(sr)) {
471 pr_warning("%s: omap_sr struct for sr_%s not found\n",
472 __func__, voltdm->name);
473 return -EINVAL;
474 }
475
476 if (!sr->clk_length)
477 sr_set_clk_length(sr);
478
479 senp_en = sr->senp_mod;
480 senn_en = sr->senn_mod;
481
482 sr_config = (sr->clk_length << SRCONFIG_SRCLKLENGTH_SHIFT) |
483 SRCONFIG_SENENABLE |
484 (sr->accum_data << SRCONFIG_ACCUMDATA_SHIFT);
485
486 if (sr->ip_type == SR_TYPE_V1) {
487 sr_config |= SRCONFIG_DELAYCTRL;
488 senn_shift = SRCONFIG_SENNENABLE_V1_SHIFT;
489 senp_shift = SRCONFIG_SENPENABLE_V1_SHIFT;
490 } else if (sr->ip_type == SR_TYPE_V2) {
491 senn_shift = SRCONFIG_SENNENABLE_V2_SHIFT;
492 senp_shift = SRCONFIG_SENPENABLE_V2_SHIFT;
493 } else {
494 dev_err(&sr->pdev->dev, "%s: Trying to Configure smartreflex"
495 "module without specifying the ip\n", __func__);
496 return -EINVAL;
497 }
498
499 sr_config |= ((senn_en << senn_shift) | (senp_en << senp_shift));
500 sr_write_reg(sr, SRCONFIG, sr_config);
501 sr_avgwt = (sr->senp_avgweight << AVGWEIGHT_SENPAVGWEIGHT_SHIFT) |
502 (sr->senn_avgweight << AVGWEIGHT_SENNAVGWEIGHT_SHIFT);
503 sr_write_reg(sr, AVGWEIGHT, sr_avgwt);
504
505 /*
506 * Enabling the interrupts if MINMAXAVG module is used.
507 * TODO: check if all the interrupts are mandatory
508 */
509 if (sr->ip_type == SR_TYPE_V1) {
510 sr_modify_reg(sr, ERRCONFIG_V1,
511 (ERRCONFIG_MCUACCUMINTEN | ERRCONFIG_MCUVALIDINTEN |
512 ERRCONFIG_MCUBOUNDINTEN),
513 (ERRCONFIG_MCUACCUMINTEN | ERRCONFIG_MCUACCUMINTST |
514 ERRCONFIG_MCUVALIDINTEN | ERRCONFIG_MCUVALIDINTST |
515 ERRCONFIG_MCUBOUNDINTEN | ERRCONFIG_MCUBOUNDINTST));
516 } else if (sr->ip_type == SR_TYPE_V2) {
517 sr_write_reg(sr, IRQSTATUS,
518 IRQSTATUS_MCUACCUMINT | IRQSTATUS_MCVALIDINT |
519 IRQSTATUS_MCBOUNDSINT | IRQSTATUS_MCUDISABLEACKINT);
520 sr_write_reg(sr, IRQENABLE_SET,
521 IRQENABLE_MCUACCUMINT | IRQENABLE_MCUVALIDINT |
522 IRQENABLE_MCUBOUNDSINT | IRQENABLE_MCUDISABLEACKINT);
523 }
524
525 return 0;
526}
527
528/**
529 * sr_enable() - Enables the smartreflex module.
530 * @voltdm: VDD pointer to which the SR module to be configured belongs to.
531 * @volt: The voltage at which the Voltage domain associated with
532 * the smartreflex module is operating at.
533 * This is required only to program the correct Ntarget value.
534 *
535 * This API is to be called from the smartreflex class driver to
536 * enable a smartreflex module. Returns 0 on success. Returns error
537 * value if the voltage passed is wrong or if ntarget value is wrong.
538 */
539int sr_enable(struct voltagedomain *voltdm, unsigned long volt)
540{
541 u32 nvalue_reciprocal;
542 struct omap_volt_data *volt_data;
543 struct omap_sr *sr = _sr_lookup(voltdm);
544 int ret;
545
546 if (IS_ERR(sr)) {
547 pr_warning("%s: omap_sr struct for sr_%s not found\n",
548 __func__, voltdm->name);
549 return -EINVAL;
550 }
551
552 volt_data = omap_voltage_get_voltdata(sr->voltdm, volt);
553
554 if (IS_ERR(volt_data)) {
555 dev_warn(&sr->pdev->dev, "%s: Unable to get voltage table"
556 "for nominal voltage %ld\n", __func__, volt);
557 return -ENODATA;
558 }
559
560 nvalue_reciprocal = sr_retrieve_nvalue(sr, volt_data->sr_efuse_offs);
561
562 if (!nvalue_reciprocal) {
563 dev_warn(&sr->pdev->dev, "%s: NVALUE = 0 at voltage %ld\n",
564 __func__, volt);
565 return -ENODATA;
566 }
567
568 /* errminlimit is opp dependent and hence linked to voltage */
569 sr->err_minlimit = volt_data->sr_errminlimit;
570
571 pm_runtime_get_sync(&sr->pdev->dev);
572
573 /* Check if SR is already enabled. If yes do nothing */
574 if (sr_read_reg(sr, SRCONFIG) & SRCONFIG_SRENABLE)
575 return 0;
576
577 /* Configure SR */
578 ret = sr_class->configure(voltdm);
579 if (ret)
580 return ret;
581
582 sr_write_reg(sr, NVALUERECIPROCAL, nvalue_reciprocal);
583
584 /* SRCONFIG - enable SR */
585 sr_modify_reg(sr, SRCONFIG, SRCONFIG_SRENABLE, SRCONFIG_SRENABLE);
586 return 0;
587}
588
589/**
590 * sr_disable() - Disables the smartreflex module.
591 * @voltdm: VDD pointer to which the SR module to be configured belongs to.
592 *
593 * This API is to be called from the smartreflex class driver to
594 * disable a smartreflex module.
595 */
596void sr_disable(struct voltagedomain *voltdm)
597{
598 struct omap_sr *sr = _sr_lookup(voltdm);
599
600 if (IS_ERR(sr)) {
601 pr_warning("%s: omap_sr struct for sr_%s not found\n",
602 __func__, voltdm->name);
603 return;
604 }
605
606 /* Check if SR clocks are already disabled. If yes do nothing */
607 if (pm_runtime_suspended(&sr->pdev->dev))
608 return;
609
610 /*
611 * Disable SR if only it is indeed enabled. Else just
612 * disable the clocks.
613 */
614 if (sr_read_reg(sr, SRCONFIG) & SRCONFIG_SRENABLE) {
615 if (sr->ip_type == SR_TYPE_V1)
616 sr_v1_disable(sr);
617 else if (sr->ip_type == SR_TYPE_V2)
618 sr_v2_disable(sr);
619 }
620
621 pm_runtime_put_sync(&sr->pdev->dev);
622}
623
624/**
625 * sr_register_class() - API to register a smartreflex class parameters.
626 * @class_data: The structure containing various sr class specific data.
627 *
628 * This API is to be called by the smartreflex class driver to register itself
629 * with the smartreflex driver during init. Returns 0 on success else the
630 * error value.
631 */
632int sr_register_class(struct omap_sr_class_data *class_data)
633{
634 struct omap_sr *sr_info;
635
636 if (!class_data) {
637 pr_warning("%s:, Smartreflex class data passed is NULL\n",
638 __func__);
639 return -EINVAL;
640 }
641
642 if (sr_class) {
643 pr_warning("%s: Smartreflex class driver already registered\n",
644 __func__);
645 return -EBUSY;
646 }
647
648 sr_class = class_data;
649
650 /*
651 * Call into late init to do intializations that require
652 * both sr driver and sr class driver to be initiallized.
653 */
654 list_for_each_entry(sr_info, &sr_list, node)
655 sr_late_init(sr_info);
656
657 return 0;
658}
659
660/**
661 * omap_sr_enable() - API to enable SR clocks and to call into the
662 * registered smartreflex class enable API.
663 * @voltdm: VDD pointer to which the SR module to be configured belongs to.
664 *
665 * This API is to be called from the kernel in order to enable
666 * a particular smartreflex module. This API will do the initial
667 * configurations to turn on the smartreflex module and in turn call
668 * into the registered smartreflex class enable API.
669 */
670void omap_sr_enable(struct voltagedomain *voltdm)
671{
672 struct omap_sr *sr = _sr_lookup(voltdm);
673
674 if (IS_ERR(sr)) {
675 pr_warning("%s: omap_sr struct for sr_%s not found\n",
676 __func__, voltdm->name);
677 return;
678 }
679
680 if (!sr->autocomp_active)
681 return;
682
683 if (!sr_class || !(sr_class->enable) || !(sr_class->configure)) {
684 dev_warn(&sr->pdev->dev, "%s: smartreflex class driver not"
685 "registered\n", __func__);
686 return;
687 }
688
689 sr_class->enable(voltdm);
690}
691
692/**
693 * omap_sr_disable() - API to disable SR without resetting the voltage
694 * processor voltage
695 * @voltdm: VDD pointer to which the SR module to be configured belongs to.
696 *
697 * This API is to be called from the kernel in order to disable
698 * a particular smartreflex module. This API will in turn call
699 * into the registered smartreflex class disable API. This API will tell
700 * the smartreflex class disable not to reset the VP voltage after
701 * disabling smartreflex.
702 */
703void omap_sr_disable(struct voltagedomain *voltdm)
704{
705 struct omap_sr *sr = _sr_lookup(voltdm);
706
707 if (IS_ERR(sr)) {
708 pr_warning("%s: omap_sr struct for sr_%s not found\n",
709 __func__, voltdm->name);
710 return;
711 }
712
713 if (!sr->autocomp_active)
714 return;
715
716 if (!sr_class || !(sr_class->disable)) {
717 dev_warn(&sr->pdev->dev, "%s: smartreflex class driver not"
718 "registered\n", __func__);
719 return;
720 }
721
722 sr_class->disable(voltdm, 0);
723}
724
725/**
726 * omap_sr_disable_reset_volt() - API to disable SR and reset the
727 * voltage processor voltage
728 * @voltdm: VDD pointer to which the SR module to be configured belongs to.
729 *
730 * This API is to be called from the kernel in order to disable
731 * a particular smartreflex module. This API will in turn call
732 * into the registered smartreflex class disable API. This API will tell
733 * the smartreflex class disable to reset the VP voltage after
734 * disabling smartreflex.
735 */
736void omap_sr_disable_reset_volt(struct voltagedomain *voltdm)
737{
738 struct omap_sr *sr = _sr_lookup(voltdm);
739
740 if (IS_ERR(sr)) {
741 pr_warning("%s: omap_sr struct for sr_%s not found\n",
742 __func__, voltdm->name);
743 return;
744 }
745
746 if (!sr->autocomp_active)
747 return;
748
749 if (!sr_class || !(sr_class->disable)) {
750 dev_warn(&sr->pdev->dev, "%s: smartreflex class driver not"
751 "registered\n", __func__);
752 return;
753 }
754
755 sr_class->disable(voltdm, 1);
756}
757
758/**
759 * omap_sr_register_pmic() - API to register pmic specific info.
760 * @pmic_data: The structure containing pmic specific data.
761 *
762 * This API is to be called from the PMIC specific code to register with
763 * smartreflex driver pmic specific info. Currently the only info required
764 * is the smartreflex init on the PMIC side.
765 */
766void omap_sr_register_pmic(struct omap_sr_pmic_data *pmic_data)
767{
768 if (!pmic_data) {
769 pr_warning("%s: Trying to register NULL PMIC data structure"
770 "with smartreflex\n", __func__);
771 return;
772 }
773
774 sr_pmic_data = pmic_data;
775}
776
777/* PM Debug Fs enteries to enable disable smartreflex. */
778static int omap_sr_autocomp_show(void *data, u64 *val)
779{
780 struct omap_sr *sr_info = (struct omap_sr *) data;
781
782 if (!sr_info) {
783 pr_warning("%s: omap_sr struct for sr_%s not found\n",
784 __func__, sr_info->voltdm->name);
785 return -EINVAL;
786 }
787
788 *val = sr_info->autocomp_active;
789
790 return 0;
791}
792
793static int omap_sr_autocomp_store(void *data, u64 val)
794{
795 struct omap_sr *sr_info = (struct omap_sr *) data;
796
797 if (!sr_info) {
798 pr_warning("%s: omap_sr struct for sr_%s not found\n",
799 __func__, sr_info->voltdm->name);
800 return -EINVAL;
801 }
802
803 /* Sanity check */
804 if (val && (val != 1)) {
805 pr_warning("%s: Invalid argument %lld\n", __func__, val);
806 return -EINVAL;
807 }
808
809 if (!val)
810 sr_stop_vddautocomp(sr_info);
811 else
812 sr_start_vddautocomp(sr_info);
813
814 return 0;
815}
816
817DEFINE_SIMPLE_ATTRIBUTE(pm_sr_fops, omap_sr_autocomp_show,
818 omap_sr_autocomp_store, "%llu\n");
819
820static int __init omap_sr_probe(struct platform_device *pdev)
821{
822 struct omap_sr *sr_info = kzalloc(sizeof(struct omap_sr), GFP_KERNEL);
823 struct omap_sr_data *pdata = pdev->dev.platform_data;
824 struct resource *mem, *irq;
077fceca
TG
825 struct dentry *vdd_dbg_dir, *dbg_dir, *nvalue_dir;
826 struct omap_volt_data *volt_data;
827 int i, ret = 0;
984aa6db
TG
828
829 if (!sr_info) {
830 dev_err(&pdev->dev, "%s: unable to allocate sr_info\n",
831 __func__);
832 return -ENOMEM;
833 }
834
835 if (!pdata) {
836 dev_err(&pdev->dev, "%s: platform data missing\n", __func__);
837 return -EINVAL;
838 }
839
840 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
841 if (!mem) {
842 dev_err(&pdev->dev, "%s: no mem resource\n", __func__);
843 ret = -ENODEV;
844 goto err_free_devinfo;
845 }
846
847 irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
848
849 pm_runtime_enable(&pdev->dev);
850
851 sr_info->pdev = pdev;
852 sr_info->srid = pdev->id;
853 sr_info->voltdm = pdata->voltdm;
854 sr_info->nvalue_table = pdata->nvalue_table;
855 sr_info->nvalue_count = pdata->nvalue_count;
856 sr_info->senn_mod = pdata->senn_mod;
857 sr_info->senp_mod = pdata->senp_mod;
858 sr_info->autocomp_active = false;
859 sr_info->ip_type = pdata->ip_type;
860 sr_info->base = ioremap(mem->start, resource_size(mem));
861 if (!sr_info->base) {
862 dev_err(&pdev->dev, "%s: ioremap fail\n", __func__);
863 ret = -ENOMEM;
864 goto err_release_region;
865 }
866
867 if (irq)
868 sr_info->irq = irq->start;
869
870 sr_set_clk_length(sr_info);
871 sr_set_regfields(sr_info);
872
873 list_add(&sr_info->node, &sr_list);
874
875 /*
876 * Call into late init to do intializations that require
877 * both sr driver and sr class driver to be initiallized.
878 */
879 if (sr_class) {
880 ret = sr_late_init(sr_info);
881 if (ret) {
882 pr_warning("%s: Error in SR late init\n", __func__);
883 return ret;
884 }
885 }
886
887 dev_info(&pdev->dev, "%s: SmartReflex driver initialized\n", __func__);
888
889 /*
890 * If the voltage domain debugfs directory is not created, do
891 * not try to create rest of the debugfs entries.
892 */
893 vdd_dbg_dir = omap_voltage_get_dbgdir(sr_info->voltdm);
894 if (!vdd_dbg_dir)
895 return -EINVAL;
896
897 dbg_dir = debugfs_create_dir("smartreflex", vdd_dbg_dir);
898 if (IS_ERR(dbg_dir)) {
899 dev_err(&pdev->dev, "%s: Unable to create debugfs directory\n",
900 __func__);
901 return PTR_ERR(dbg_dir);
902 }
903
904 (void) debugfs_create_file("autocomp", S_IRUGO | S_IWUGO, dbg_dir,
905 (void *)sr_info, &pm_sr_fops);
077fceca
TG
906 (void) debugfs_create_x32("errweight", S_IRUGO, dbg_dir,
907 &sr_info->err_weight);
908 (void) debugfs_create_x32("errmaxlimit", S_IRUGO, dbg_dir,
909 &sr_info->err_maxlimit);
910 (void) debugfs_create_x32("errminlimit", S_IRUGO, dbg_dir,
911 &sr_info->err_minlimit);
912
913 nvalue_dir = debugfs_create_dir("nvalue", dbg_dir);
914 if (IS_ERR(nvalue_dir)) {
915 dev_err(&pdev->dev, "%s: Unable to create debugfs directory"
916 "for n-values\n", __func__);
917 return PTR_ERR(nvalue_dir);
918 }
919
920 omap_voltage_get_volttable(sr_info->voltdm, &volt_data);
921 if (!volt_data) {
922 dev_warn(&pdev->dev, "%s: No Voltage table for the"
923 " corresponding vdd vdd_%s. Cannot create debugfs"
924 "entries for n-values\n",
925 __func__, sr_info->voltdm->name);
926 return -ENODATA;
927 }
928
929 for (i = 0; i < sr_info->nvalue_count; i++) {
930 char *name;
931 char volt_name[32];
932
933 name = kzalloc(NVALUE_NAME_LEN + 1, GFP_KERNEL);
934 if (!name) {
935 dev_err(&pdev->dev, "%s: Unable to allocate memory"
936 " for n-value directory name\n", __func__);
937 return -ENOMEM;
938 }
939
940 strcpy(name, "volt_");
941 sprintf(volt_name, "%d", volt_data[i].volt_nominal);
942 strcat(name, volt_name);
943 (void) debugfs_create_x32(name, S_IRUGO | S_IWUGO, nvalue_dir,
944 &(sr_info->nvalue_table[i].nvalue));
945 }
984aa6db
TG
946
947 return ret;
948
949err_release_region:
950 release_mem_region(mem->start, resource_size(mem));
951err_free_devinfo:
952 kfree(sr_info);
953
954 return ret;
955}
956
957static int __devexit omap_sr_remove(struct platform_device *pdev)
958{
959 struct omap_sr_data *pdata = pdev->dev.platform_data;
960 struct omap_sr *sr_info;
961 struct resource *mem;
962
963 if (!pdata) {
964 dev_err(&pdev->dev, "%s: platform data missing\n", __func__);
965 return -EINVAL;
966 }
967
968 sr_info = _sr_lookup(pdata->voltdm);
969 if (!sr_info) {
970 dev_warn(&pdev->dev, "%s: omap_sr struct not found\n",
971 __func__);
972 return -EINVAL;
973 }
974
975 if (sr_info->autocomp_active)
976 sr_stop_vddautocomp(sr_info);
977
978 list_del(&sr_info->node);
979 iounmap(sr_info->base);
980 kfree(sr_info);
981 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
982 release_mem_region(mem->start, resource_size(mem));
983
984 return 0;
985}
986
987static struct platform_driver smartreflex_driver = {
988 .remove = omap_sr_remove,
989 .driver = {
990 .name = "smartreflex",
991 },
992};
993
994static int __init sr_init(void)
995{
996 int ret = 0;
997
998 /*
999 * sr_init is a late init. If by then a pmic specific API is not
1000 * registered either there is no need for anything to be done on
1001 * the PMIC side or somebody has forgotten to register a PMIC
1002 * handler. Warn for the second condition.
1003 */
1004 if (sr_pmic_data && sr_pmic_data->sr_pmic_init)
1005 sr_pmic_data->sr_pmic_init();
1006 else
1007 pr_warning("%s: No PMIC hook to init smartreflex\n", __func__);
1008
1009 ret = platform_driver_probe(&smartreflex_driver, omap_sr_probe);
1010 if (ret) {
1011 pr_err("%s: platform driver register failed for SR\n",
1012 __func__);
1013 return ret;
1014 }
1015
1016 return 0;
1017}
1018
1019static void __exit sr_exit(void)
1020{
1021 platform_driver_unregister(&smartreflex_driver);
1022}
1023late_initcall(sr_init);
1024module_exit(sr_exit);
1025
1026MODULE_DESCRIPTION("OMAP Smartreflex Driver");
1027MODULE_LICENSE("GPL");
1028MODULE_ALIAS("platform:" DRIVER_NAME);
1029MODULE_AUTHOR("Texas Instruments Inc");
This page took 0.063646 seconds and 5 git commands to generate.