aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/mach-omap2/smartreflex.c38
-rw-r--r--arch/arm/mach-omap2/sr_device.c36
-rw-r--r--include/linux/power/smartreflex.h8
3 files changed, 54 insertions, 28 deletions
diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c
index acef08d837cc..20075de13868 100644
--- a/arch/arm/mach-omap2/smartreflex.c
+++ b/arch/arm/mach-omap2/smartreflex.c
@@ -347,22 +347,23 @@ static void sr_v2_disable(struct omap_sr *sr)
347 sr_write_reg(sr, IRQSTATUS, IRQSTATUS_MCUDISABLEACKINT); 347 sr_write_reg(sr, IRQSTATUS, IRQSTATUS_MCUDISABLEACKINT);
348} 348}
349 349
350static u32 sr_retrieve_nvalue(struct omap_sr *sr, u32 efuse_offs) 350static struct omap_sr_nvalue_table *sr_retrieve_nvalue_row(
351 struct omap_sr *sr, u32 efuse_offs)
351{ 352{
352 int i; 353 int i;
353 354
354 if (!sr->nvalue_table) { 355 if (!sr->nvalue_table) {
355 dev_warn(&sr->pdev->dev, "%s: Missing ntarget value table\n", 356 dev_warn(&sr->pdev->dev, "%s: Missing ntarget value table\n",
356 __func__); 357 __func__);
357 return 0; 358 return NULL;
358 } 359 }
359 360
360 for (i = 0; i < sr->nvalue_count; i++) { 361 for (i = 0; i < sr->nvalue_count; i++) {
361 if (sr->nvalue_table[i].efuse_offs == efuse_offs) 362 if (sr->nvalue_table[i].efuse_offs == efuse_offs)
362 return sr->nvalue_table[i].nvalue; 363 return &sr->nvalue_table[i];
363 } 364 }
364 365
365 return 0; 366 return NULL;
366} 367}
367 368
368/* Public Functions */ 369/* Public Functions */
@@ -586,7 +587,7 @@ int sr_enable(struct voltagedomain *voltdm, unsigned long volt)
586{ 587{
587 struct omap_volt_data *volt_data; 588 struct omap_volt_data *volt_data;
588 struct omap_sr *sr = _sr_lookup(voltdm); 589 struct omap_sr *sr = _sr_lookup(voltdm);
589 u32 nvalue_reciprocal; 590 struct omap_sr_nvalue_table *nvalue_row;
590 int ret; 591 int ret;
591 592
592 if (IS_ERR(sr)) { 593 if (IS_ERR(sr)) {
@@ -602,16 +603,16 @@ int sr_enable(struct voltagedomain *voltdm, unsigned long volt)
602 return PTR_ERR(volt_data); 603 return PTR_ERR(volt_data);
603 } 604 }
604 605
605 nvalue_reciprocal = sr_retrieve_nvalue(sr, volt_data->sr_efuse_offs); 606 nvalue_row = sr_retrieve_nvalue_row(sr, volt_data->sr_efuse_offs);
606 607
607 if (!nvalue_reciprocal) { 608 if (!nvalue_row) {
608 dev_warn(&sr->pdev->dev, "%s: NVALUE = 0 at voltage %ld\n", 609 dev_warn(&sr->pdev->dev, "%s: failure getting SR data for this voltage %ld\n",
609 __func__, volt); 610 __func__, volt);
610 return -ENODATA; 611 return -ENODATA;
611 } 612 }
612 613
613 /* errminlimit is opp dependent and hence linked to voltage */ 614 /* errminlimit is opp dependent and hence linked to voltage */
614 sr->err_minlimit = volt_data->sr_errminlimit; 615 sr->err_minlimit = nvalue_row->errminlimit;
615 616
616 pm_runtime_get_sync(&sr->pdev->dev); 617 pm_runtime_get_sync(&sr->pdev->dev);
617 618
@@ -624,7 +625,7 @@ int sr_enable(struct voltagedomain *voltdm, unsigned long volt)
624 if (ret) 625 if (ret)
625 return ret; 626 return ret;
626 627
627 sr_write_reg(sr, NVALUERECIPROCAL, nvalue_reciprocal); 628 sr_write_reg(sr, NVALUERECIPROCAL, nvalue_row->nvalue);
628 629
629 /* SRCONFIG - enable SR */ 630 /* SRCONFIG - enable SR */
630 sr_modify_reg(sr, SRCONFIG, SRCONFIG_SRENABLE, SRCONFIG_SRENABLE); 631 sr_modify_reg(sr, SRCONFIG, SRCONFIG_SRENABLE, SRCONFIG_SRENABLE);
@@ -872,7 +873,6 @@ static int __init omap_sr_probe(struct platform_device *pdev)
872 struct omap_sr_data *pdata = pdev->dev.platform_data; 873 struct omap_sr_data *pdata = pdev->dev.platform_data;
873 struct resource *mem, *irq; 874 struct resource *mem, *irq;
874 struct dentry *nvalue_dir; 875 struct dentry *nvalue_dir;
875 struct omap_volt_data *volt_data;
876 int i, ret = 0; 876 int i, ret = 0;
877 877
878 sr_info = kzalloc(sizeof(struct omap_sr), GFP_KERNEL); 878 sr_info = kzalloc(sizeof(struct omap_sr), GFP_KERNEL);
@@ -990,12 +990,10 @@ static int __init omap_sr_probe(struct platform_device *pdev)
990 goto err_debugfs; 990 goto err_debugfs;
991 } 991 }
992 992
993 omap_voltage_get_volttable(sr_info->voltdm, &volt_data); 993 if (sr_info->nvalue_count == 0 || !sr_info->nvalue_table) {
994 if (!volt_data) { 994 dev_warn(&pdev->dev, "%s: %s: No Voltage table for the corresponding vdd. Cannot create debugfs entries for n-values\n",
995 dev_warn(&pdev->dev, "%s: %s: No Voltage table for the" 995 __func__, sr_info->name);
996 " corresponding vdd. Cannot create debugfs" 996
997 "entries for n-values\n",
998 __func__, sr_info->name);
999 ret = -ENODATA; 997 ret = -ENODATA;
1000 goto err_debugfs; 998 goto err_debugfs;
1001 } 999 }
@@ -1003,8 +1001,8 @@ static int __init omap_sr_probe(struct platform_device *pdev)
1003 for (i = 0; i < sr_info->nvalue_count; i++) { 1001 for (i = 0; i < sr_info->nvalue_count; i++) {
1004 char name[NVALUE_NAME_LEN + 1]; 1002 char name[NVALUE_NAME_LEN + 1];
1005 1003
1006 snprintf(name, sizeof(name), "volt_%d", 1004 snprintf(name, sizeof(name), "volt_%lu",
1007 volt_data[i].volt_nominal); 1005 sr_info->nvalue_table[i].volt_nominal);
1008 (void) debugfs_create_x32(name, S_IRUGO | S_IWUSR, nvalue_dir, 1006 (void) debugfs_create_x32(name, S_IRUGO | S_IWUSR, nvalue_dir,
1009 &(sr_info->nvalue_table[i].nvalue)); 1007 &(sr_info->nvalue_table[i].nvalue));
1010 } 1008 }
diff --git a/arch/arm/mach-omap2/sr_device.c b/arch/arm/mach-omap2/sr_device.c
index e081174f28af..e107e3915a8a 100644
--- a/arch/arm/mach-omap2/sr_device.c
+++ b/arch/arm/mach-omap2/sr_device.c
@@ -36,7 +36,10 @@ static void __init sr_set_nvalues(struct omap_volt_data *volt_data,
36 struct omap_sr_data *sr_data) 36 struct omap_sr_data *sr_data)
37{ 37{
38 struct omap_sr_nvalue_table *nvalue_table; 38 struct omap_sr_nvalue_table *nvalue_table;
39 int i, count = 0; 39 int i, j, count = 0;
40
41 sr_data->nvalue_count = 0;
42 sr_data->nvalue_table = NULL;
40 43
41 while (volt_data[count].volt_nominal) 44 while (volt_data[count].volt_nominal)
42 count++; 45 count++;
@@ -44,8 +47,14 @@ static void __init sr_set_nvalues(struct omap_volt_data *volt_data,
44 nvalue_table = kzalloc(sizeof(struct omap_sr_nvalue_table)*count, 47 nvalue_table = kzalloc(sizeof(struct omap_sr_nvalue_table)*count,
45 GFP_KERNEL); 48 GFP_KERNEL);
46 49
47 for (i = 0; i < count; i++) { 50 if (!nvalue_table) {
51 pr_err("OMAP: SmartReflex: cannot allocate memory for n-value table\n");
52 return;
53 }
54
55 for (i = 0, j = 0; i < count; i++) {
48 u32 v; 56 u32 v;
57
49 /* 58 /*
50 * In OMAP4 the efuse registers are 24 bit aligned. 59 * In OMAP4 the efuse registers are 24 bit aligned.
51 * A __raw_readl will fail for non-32 bit aligned address 60 * A __raw_readl will fail for non-32 bit aligned address
@@ -58,15 +67,30 @@ static void __init sr_set_nvalues(struct omap_volt_data *volt_data,
58 omap_ctrl_readb(offset + 1) << 8 | 67 omap_ctrl_readb(offset + 1) << 8 |
59 omap_ctrl_readb(offset + 2) << 16; 68 omap_ctrl_readb(offset + 2) << 16;
60 } else { 69 } else {
61 v = omap_ctrl_readl(volt_data[i].sr_efuse_offs); 70 v = omap_ctrl_readl(volt_data[i].sr_efuse_offs);
62 } 71 }
63 72
64 nvalue_table[i].efuse_offs = volt_data[i].sr_efuse_offs; 73 /*
65 nvalue_table[i].nvalue = v; 74 * Many OMAP SoCs don't have the eFuse values set.
75 * For example, pretty much all OMAP3xxx before
76 * ES3.something.
77 *
78 * XXX There needs to be some way for board files or
79 * userspace to add these in.
80 */
81 if (v == 0)
82 continue;
83
84 nvalue_table[j].nvalue = v;
85 nvalue_table[j].efuse_offs = volt_data[i].sr_efuse_offs;
86 nvalue_table[j].errminlimit = volt_data[i].sr_errminlimit;
87 nvalue_table[j].volt_nominal = volt_data[i].volt_nominal;
88
89 j++;
66 } 90 }
67 91
68 sr_data->nvalue_table = nvalue_table; 92 sr_data->nvalue_table = nvalue_table;
69 sr_data->nvalue_count = count; 93 sr_data->nvalue_count = j;
70} 94}
71 95
72static int __init sr_dev_init(struct omap_hwmod *oh, void *user) 96static int __init sr_dev_init(struct omap_hwmod *oh, void *user)
diff --git a/include/linux/power/smartreflex.h b/include/linux/power/smartreflex.h
index 78b795ea2709..222f90183712 100644
--- a/include/linux/power/smartreflex.h
+++ b/include/linux/power/smartreflex.h
@@ -243,12 +243,16 @@ struct omap_sr_class_data {
243/** 243/**
244 * struct omap_sr_nvalue_table - Smartreflex n-target value info 244 * struct omap_sr_nvalue_table - Smartreflex n-target value info
245 * 245 *
246 * @efuse_offs: The offset of the efuse where n-target values are stored. 246 * @efuse_offs: The offset of the efuse where n-target values are stored.
247 * @nvalue: The n-target value. 247 * @nvalue: The n-target value.
248 * @errminlimit: The value of the ERRMINLIMIT bitfield for this n-target
249 * @volt_nominal: microvolts DC that the VDD is initially programmed to
248 */ 250 */
249struct omap_sr_nvalue_table { 251struct omap_sr_nvalue_table {
250 u32 efuse_offs; 252 u32 efuse_offs;
251 u32 nvalue; 253 u32 nvalue;
254 u32 errminlimit;
255 unsigned long volt_nominal;
252}; 256};
253 257
254/** 258/**