diff options
| -rw-r--r-- | arch/arm/mach-omap2/smartreflex.c | 38 | ||||
| -rw-r--r-- | arch/arm/mach-omap2/sr_device.c | 36 | ||||
| -rw-r--r-- | include/linux/power/smartreflex.h | 8 |
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 | ||
| 350 | static u32 sr_retrieve_nvalue(struct omap_sr *sr, u32 efuse_offs) | 350 | static 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 | ||
| 72 | static int __init sr_dev_init(struct omap_hwmod *oh, void *user) | 96 | static 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 | */ |
| 249 | struct omap_sr_nvalue_table { | 251 | struct 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 | /** |
