aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJean Pihet <j-pihet@ti.com>2012-04-25 01:49:44 -0400
committerKevin Hilman <khilman@ti.com>2012-05-31 19:03:44 -0400
commit5e7f2e12e4ea14a34fb9b5941d60a4464fc8d40a (patch)
tree0ff1412b37d31fa0c601de90759928b9dbcd7960
parentfa60be6e3f9362bd841e26b9366f0db7b761a042 (diff)
ARM: OMAP2+: SmartReflex: Use per-OPP data structure
The SmartReflex driver incorrectly treats some per-OPP data as data common to all OPPs (e.g., ERRMINLIMIT). Move this data into a per-OPP data structure. Furthermore, in order to make the SmartReflex implementation ready for the move to drivers/, remove the dependency from the SR driver code to the voltage layer by querying the data tables only from the SR device init code. Based on Paul's original code for the SmartReflex driver conversion. Signed-off-by: Jean Pihet <j-pihet@ti.com> Signed-off-by: J Keerthy <j-keerthy@ti.com> Reviewed-by: Kevin Hilman <khilman@ti.com> Signed-off-by: Kevin Hilman <khilman@ti.com>
-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/**