OMAP3+: PM: introduce SR class 1.5
Subsystems (5)
v3 cover OMAP3+: PM: introduce SR class 1.5
Hi,
This series intends to introduce SmartReflex AVS Class 1.5 support which is now the recommended AVS class for usage in OMAP3630, OMAP4 and potentially in later generation of silicon as well. Smartreflex class 1.5 is a software controlled hardware calibration mechanism designed to improve DVFS latencies and system performance as well as helping bring in additional benefits to the system from h/w perspective. The corresponding patch has details on this class and the implementation as well.
The series eventually results in OMAP343x based platforms using class 3 and OMAP3630, OMAP4 platforms using class 1.5 automatically without modifications or additions to board files.
The series contains a bunch of bugfixes and improvements needed to introduce SmartReflex AVS class 1.5.
This series is Based on:
a) k.org 2.6.38-rc7 (b2.6.38-rc7)
b) The pm-core branch Kevin Hilman's tree: (pm-base-v3)
http://git.kernel.org/?p=linux/kernel/git/khilman/linux-omap-pm.git;a=summary
Some good fixes needed are here (optional):
c) sr-fixes: (sr-baseline-v3)
https://patchwork.kernel.org/patch/611991/ https://patchwork.kernel.org/patch/611951/ https://patchwork.kernel.org/patch/611961/ https://patchwork.kernel.org/patch/611971/
This series is also available at:
git://gitorious.org/linux-omap-nm-sr/linux-omap-sr.git Branch: sr-1.5-v3
Changes in v3 since v2:
* On request from OMAP PM maintainer, the series is now rebased to pm-core of linux-omap-pm tree
http://git.kernel.org/?p=linux/kernel/git/khilman/linux-omap-pm.git;a=summary
Ref: http://marc.info/?l=linux-omap&m=129911240208955&w=2
the voltage files and structures have been reorganized in pm-core, so the same code looks a little different now.
* Changes throughout the series for typos, spell corrections, using uppercase for abbreviations
* Updated commit message for patches 3, 6, 9 and 15
* Dropped patch http://marc.info/?t=129906354500012&r=1&w=2
* Added patch 2 in the series for pm-core branch (build warning)
* Included a squashed series from Jaarko(patch 9):
http://marc.info/?l=linux-omap&m=129908137900427&w=2
This was rebased to pm-core+ my series
* patch 10 changed x ^ y check to x != y to basically get the same behavior but a little more readable without thinking bitops ;)
* patch 12 - changed class_init/deinit to start/stop APIs
v2: http://marc.info/?l=linux-omap&m=129906334611444&w=2
v1: http://marc.info/?l=linux-omap&m=129811693118173&w=2
Jarkko Nikula (1):
OMAP3+: SR: Reuse sr_[start|stop]_vddautocomp functions
Nishanth Menon (18):
OMAP3: hwmod: add SmartReflex IRQs
OMAP3+: voltage: fix build warning
OMAP3+: voltage: remove initial voltage OMAP3+: voltage: remove spurious pr_notice for debugfs OMAP3+: voltage: use IS_ERR_OR_NULL
OMAP3+: voltage: use volt_data pointer instead values OMAP3+: voltage: add transdone APIs
OMAP3+: SR: make notify independent of class OMAP3+: SR: disable interrupt by default OMAP3+: SR: enable/disable SR only on need OMAP3+: SR: fix cosmetic indentation
OMAP3+: SR: introduce class start,stop and priv data OMAP3+: SR: introduce notifiers flags
OMAP3+: SR: introduce notifier_control OMAP3+: SR: disable spamming interrupts OMAP3+: SR: make enable path use volt_data pointer OMAP3630+: SR: add support for class 1.5
OMAP3430: SR: class3: restrict CPU to run on
arch/arm/mach-omap2/Makefile | 1 + arch/arm/mach-omap2/omap_hwmod_3xxx_data.c | 17 + arch/arm/mach-omap2/pm.c | 3 +- arch/arm/mach-omap2/smartreflex-class1p5.c | 582 ++++++++++++++++++++++++++++ arch/arm/mach-omap2/smartreflex-class3.c | 21 +- arch/arm/mach-omap2/smartreflex.c | 288 +++++++++++---- arch/arm/mach-omap2/smartreflex.h | 39 ++- arch/arm/mach-omap2/voltage.c | 241 +++++++++--- arch/arm/mach-omap2/voltage.h | 40 ++- arch/arm/plat-omap/Kconfig | 17 + 10 files changed, 1106 insertions(+), 143 deletions(-) create mode 100644 arch/arm/mach-omap2/smartreflex-class1p5.c
Testing performed:
Testing with sr-1.5-v3 - http://pastebin.mozilla.org/1117880
- enable disable in domain combinations, test the new debugfs entries etc..
- platforms: SDP3430(OMAP3430), SDP3630(OMAP3630), PandaBoard(OMAP4430)
Testing with dvfs-test-v2 (not v3)
The DVFS series no longer applies on pm-core with the cleanups that have taken place. I have been unable to test the latest series with it yet.
V2 of the series was tested with:
http://pastebin.mozilla.org/1117872
- transitions from all opps to all other opps,sr enabled, disable
- platforms: SDP3430(OMAP3430), SDP3630(OMAP3630) (further note: dvfs series does'nt support OMAP4 yet)
Regards,
Nishanth Menon
PATCH v3 1/19 OMAP3: hwmod: add SmartReflex IRQs
OMAP3 SmartReflex IRQs in hwmod structures with the same naming as present in OMAP4. Without these IRQs being registered, SmartReflex driver will be unable to get the IRQ numbers to handle notifications
--- arch/arm/mach-omap2/omap_hwmod_3xxx_data.c | 17 +++++++++++++++++ 1 files changed, 17 insertions(+), 0 deletions(-)
arch/arm/mach-omap2/omap_hwmod_3xxx_data.c +17 -0
@@ -378,6 +378,15 @@ static struct omap_hwmod_ocp_if omap3_l4_core__i2c3 = { .user = OCP_USER_MPU | OCP_USER_SDMA, }; + +static struct omap_hwmod_irq_info omap3_smartreflex_mpu_irqs[] = { + {.name ="sr1_irq" , .irq =18 }, +}; + +static struct omap_hwmod_irq_info omap3_smartreflex_core_irqs[] = { + {.name ="sr2_irq" , .irq =19 }, +}; +/* L4 CORE -> SR1 interface */ static struct omap_hwmod_addr_space omap3_sr1_addr_space[] = { {
@@ -2925,6 +2934,8 @@ static struct omap_hwmod omap34xx_sr1_hwmod = { .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES2 | CHIP_IS_OMAP3430ES3_0 | CHIP_IS_OMAP3430ES3_1), + .mpu_irqs = omap3_smartreflex_mpu_irqs, + .mpu_irqs_cnt = ARRAY_SIZE(omap3_smartreflex_mpu_irqs), .flags = HWMOD_SET_DEFAULT_CLOCKACT, };
@@ -2945,6 +2956,8 @@ static struct omap_hwmod omap36xx_sr1_hwmod = { .slaves = omap3_sr1_slaves, .slaves_cnt = ARRAY_SIZE(omap3_sr1_slaves), .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3630ES1), + .mpu_irqs = omap3_smartreflex_mpu_irqs, + .mpu_irqs_cnt = ARRAY_SIZE(omap3_smartreflex_mpu_irqs), };/* SR2 */
@@ -2971,6 +2984,8 @@ static struct omap_hwmod omap34xx_sr2_hwmod = { .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES2 | CHIP_IS_OMAP3430ES3_0 | CHIP_IS_OMAP3430ES3_1), + .mpu_irqs = omap3_smartreflex_core_irqs, + .mpu_irqs_cnt = ARRAY_SIZE(omap3_smartreflex_core_irqs), .flags = HWMOD_SET_DEFAULT_CLOCKACT, };
@@ -2991,6 +3006,8 @@ static struct omap_hwmod omap36xx_sr2_hwmod = { .slaves = omap3_sr2_slaves, .slaves_cnt = ARRAY_SIZE(omap3_sr2_slaves), .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3630ES1), + .mpu_irqs = omap3_smartreflex_core_irqs, + .mpu_irqs_cnt = ARRAY_SIZE(omap3_smartreflex_core_irqs), };/*
Signature · 1 line
1.7.1
PATCH v3 1/19 OMAP3: hwmod: add SmartReflex IRQs
Hi Nishanth,
Quoted 15 lines · Nishanth Menon
OMAP3 SmartReflex IRQs in hwmod structures with the same naming as present in OMAP4. Without these IRQs being registered, SmartReflex driver will be unable to get the IRQ numbers to handle notifications
Signed-off-by Nishanth Menon <[email protected]>--- arch/arm/mach-omap2/omap_hwmod_3xxx_data.c | 17 +++++++++++++++++ 1 files changed, 17 insertions(+), 0 deletions(-)arch/arm/mach-omap2/omap_hwmod_3xxx_data.c +0
-0@@ -378,6 +378,15 @@ static struct omap_hwmod_ocp_if omap3_l4_core__i2c3 = { .user = OCP_USER_MPU | OCP_USER_SDMA,
arch/arm/mach-omap2/omap_hwmod_3xxx_data.c static struct omap_hwmod_ocp_if omap3_l4_core__i2c3 = { · line 388
Quoted 10 lines
arch/arm/mach-omap2/omap_hwmod_3xxx_data.c +8
-0}; + +static struct omap_hwmod_irq_info omap3_smartreflex_mpu_irqs[] = { + {.name ="sr1_irq" , .irq =18 }, +}; + +static struct omap_hwmod_irq_info omap3_smartreflex_core_irqs[] = { + {.name ="sr2_irq" , .irq =19 }, +};
The name here doesn't seem to be needed.
Kevin
Quoted 39 lines
arch/arm/mach-omap2/omap_hwmod_3xxx_data.c +8
-0/* L4 CORE -> SR1 interface */ static struct omap_hwmod_addr_space omap3_sr1_addr_space[] = { {@@ -2925,6 +2934,8 @@ static struct omap_hwmod omap34xx_sr1_hwmod = { .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES2 | CHIP_IS_OMAP3430ES3_0 | CHIP_IS_OMAP3430ES3_1), + .mpu_irqs = omap3_smartreflex_mpu_irqs, + .mpu_irqs_cnt = ARRAY_SIZE(omap3_smartreflex_mpu_irqs), .flags = HWMOD_SET_DEFAULT_CLOCKACT, };@@ -2945,6 +2956,8 @@ static struct omap_hwmod omap36xx_sr1_hwmod = { .slaves = omap3_sr1_slaves, .slaves_cnt = ARRAY_SIZE(omap3_sr1_slaves), .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3630ES1), + .mpu_irqs = omap3_smartreflex_mpu_irqs, + .mpu_irqs_cnt = ARRAY_SIZE(omap3_smartreflex_mpu_irqs), };/* SR2 */ @@ -2971,6 +2984,8 @@ static struct omap_hwmod omap34xx_sr2_hwmod = { .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES2 | CHIP_IS_OMAP3430ES3_0 | CHIP_IS_OMAP3430ES3_1), + .mpu_irqs = omap3_smartreflex_core_irqs, + .mpu_irqs_cnt = ARRAY_SIZE(omap3_smartreflex_core_irqs), .flags = HWMOD_SET_DEFAULT_CLOCKACT, };@@ -2991,6 +3006,8 @@ static struct omap_hwmod omap36xx_sr2_hwmod = { .slaves = omap3_sr2_slaves, .slaves_cnt = ARRAY_SIZE(omap3_sr2_slaves), .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3630ES1), + .mpu_irqs = omap3_smartreflex_core_irqs, + .mpu_irqs_cnt = ARRAY_SIZE(omap3_smartreflex_core_irqs), };/*
PATCH v3 1/19 OMAP3: hwmod: add SmartReflex IRQs
In reply to Nishanth MenonHi,
Quoted 5 lines · Nishanth Menon
OMAP3 SmartReflex IRQs in hwmod structures with the same naming as present in OMAP4. Without these IRQs being registered, SmartReflex driver will be unable to get the IRQ numbers to handle notifications
Signed-off-by Nishanth Menon <[email protected]>
FWIW:
According to 36xx TRM page 383, the IRQ numbers are correct.
Quoted 67 lines
--- arch/arm/mach-omap2/omap_hwmod_3xxx_data.c | 17 +++++++++++++++++ 1 files changed, 17 insertions(+), 0 deletions(-)arch/arm/mach-omap2/omap_hwmod_3xxx_data.c +17
-0@@ -378,6 +378,15 @@ static struct omap_hwmod_ocp_if omap3_l4_core__i2c3 = { .user = OCP_USER_MPU | OCP_USER_SDMA, }; + +static struct omap_hwmod_irq_info omap3_smartreflex_mpu_irqs[] = { + {.name ="sr1_irq" , .irq =18 }, +}; + +static struct omap_hwmod_irq_info omap3_smartreflex_core_irqs[] = { + {.name ="sr2_irq" , .irq =19 }, +}; +/* L4 CORE -> SR1 interface */ static struct omap_hwmod_addr_space omap3_sr1_addr_space[] = { {@@ -2925,6 +2934,8 @@ static struct omap_hwmod omap34xx_sr1_hwmod = { .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES2 | CHIP_IS_OMAP3430ES3_0 | CHIP_IS_OMAP3430ES3_1), + .mpu_irqs = omap3_smartreflex_mpu_irqs, + .mpu_irqs_cnt = ARRAY_SIZE(omap3_smartreflex_mpu_irqs), .flags = HWMOD_SET_DEFAULT_CLOCKACT, };@@ -2945,6 +2956,8 @@ static struct omap_hwmod omap36xx_sr1_hwmod = { .slaves = omap3_sr1_slaves, .slaves_cnt = ARRAY_SIZE(omap3_sr1_slaves), .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3630ES1), + .mpu_irqs = omap3_smartreflex_mpu_irqs, + .mpu_irqs_cnt = ARRAY_SIZE(omap3_smartreflex_mpu_irqs), };/* SR2 */ @@ -2971,6 +2984,8 @@ static struct omap_hwmod omap34xx_sr2_hwmod = { .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES2 | CHIP_IS_OMAP3430ES3_0 | CHIP_IS_OMAP3430ES3_1), + .mpu_irqs = omap3_smartreflex_core_irqs, + .mpu_irqs_cnt = ARRAY_SIZE(omap3_smartreflex_core_irqs), .flags = HWMOD_SET_DEFAULT_CLOCKACT, };@@ -2991,6 +3006,8 @@ static struct omap_hwmod omap36xx_sr2_hwmod = { .slaves = omap3_sr2_slaves, .slaves_cnt = ARRAY_SIZE(omap3_sr2_slaves), .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3630ES1), + .mpu_irqs = omap3_smartreflex_core_irqs, + .mpu_irqs_cnt = ARRAY_SIZE(omap3_smartreflex_core_irqs), };/* Signature · 6 lines
1.7.1 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo at vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Signature · 8 lines
balbi -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 490 bytes Desc: Digital signature URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20110726/b8a7a704/attachment-0001.sig>
PATCH v3 2/19 OMAP3+: voltage: fix build warning
In reply to Nishanth MenonHandle the case for a future SoC where sys_ck_name might be
uninitialized. Fixes the build warning:arch/arm/mach-omap2/voltage.c: In function 'omap_voltage_late_init':arch/arm/mach-omap2/voltage.c:86:8: warning: 'sys_ck_name' may be used uninitialized in this function
--- arch/arm/mach-omap2/voltage.c | 8 ++++++-- 1 files changed, 6 insertions(+), 2 deletions(-)
arch/arm/mach-omap2/voltage.c +6 -2
@@ -91,10 +91,14 @@ static int __init _config_common_vdd_data(struct omap_vdd_info *vdd)* XXX Clockfw should handle this, or this should be in a * struct record */ -if (cpu_is_omap24xx () ||cpu_is_omap34xx ()) +if (cpu_is_omap24xx () ||cpu_is_omap34xx ()) { sys_ck_name ="sys_ck" ; -else if (cpu_is_omap44xx ()) + }else if (cpu_is_omap44xx ()) { sys_ck_name ="sys_clkin_ck" ; + }else { +pr_err ("%s: Unsupported OMAP\n" , __func__); +return -EINVAL ; + }/* * Sys clk rate is require to calculate vp timeout value and
Signature · 1 line
1.7.1
PATCH v3 2/19 OMAP3+: voltage: fix build warning
Quoted 6 lines · Nishanth Menon
Handle the case for a future SoC where
sys_ck_namemight be
uninitialized. Fixes the build warning:arch/arm/mach-omap2/voltage.c: In function 'omap_voltage_late_init':arch/arm/mach-omap2/voltage.c:86:8: warning: 'sys_ck_name' may be used uninitialized in this functionSigned-off-by Nishanth Menon <[email protected]>
This one seems to be already fixed in l-o commit:
commit c0718df4d666cc5fd8837ac93c82995a17bfdbf5
Author: Paul Walmsley <[email protected]> Date: Thu Mar 10 22:17:45 2011 -0700
OMAP2+: voltage: reorganize, split code from data
Kevin
Quoted 25 lines
--- arch/arm/mach-omap2/voltage.c | 8 ++++++-- 1 files changed, 6 insertions(+), 2 deletions(-)arch/arm/mach-omap2/voltage.c +6
-2@@ -91,10 +91,14 @@ static int __init _config_common_vdd_data(struct omap_vdd_info *vdd)* XXX Clockfw should handle this, or this should be in a * struct record */ -if (cpu_is_omap24xx () ||cpu_is_omap34xx ()) +if (cpu_is_omap24xx () ||cpu_is_omap34xx ()) { sys_ck_name ="sys_ck" ; -else if (cpu_is_omap44xx ()) + }else if (cpu_is_omap44xx ()) { sys_ck_name ="sys_clkin_ck" ; + }else { +pr_err ("%s: Unsupported OMAP\n" , __func__); +return -EINVAL ; + }/* * Sys clk rate is require to calculate vp timeout value and
PATCH v3 2/19 OMAP3+: voltage: fix build warning
In reply to Nishanth MenonQuoted 6 lines · Nishanth Menon
Handle the case for a future SoC where
sys_ck_namemight be
uninitialized. Fixes the build warning:arch/arm/mach-omap2/voltage.c: In function 'omap_voltage_late_init':arch/arm/mach-omap2/voltage.c:86:8: warning: 'sys_ck_name' may be used uninitialized in this functionSigned-off-by Nishanth Menon <[email protected]>
FWIW:
Quoted 32 lines
--- arch/arm/mach-omap2/voltage.c | 8 ++++++-- 1 files changed, 6 insertions(+), 2 deletions(-)arch/arm/mach-omap2/voltage.c +6
-2@@ -91,10 +91,14 @@ static int __init _config_common_vdd_data(struct omap_vdd_info *vdd)* XXX Clockfw should handle this, or this should be in a * struct record */ -if (cpu_is_omap24xx () ||cpu_is_omap34xx ()) +if (cpu_is_omap24xx () ||cpu_is_omap34xx ()) { sys_ck_name ="sys_ck" ; -else if (cpu_is_omap44xx ()) + }else if (cpu_is_omap44xx ()) { sys_ck_name ="sys_clkin_ck" ; + }else { +pr_err ("%s: Unsupported OMAP\n" , __func__); +return -EINVAL ; + }/* * Sys clk rate is require to calculate vp timeout value and Signature · 6 lines
1.7.1 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo at vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Signature · 8 lines
balbi -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 490 bytes Desc: Digital signature URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20110726/7b6b64ce/attachment.sig>
PATCH v3 3/19 OMAP3+: voltage: remove initial voltage
In reply to Nishanth MenonBlindly setting a 1.2V setting in the initial structure may not even match the default voltages stored in the voltage table which are supported for the domain. For example, OMAP3430 core domain does not use 1.2V and ends up generating a warning on the first transition.
Further, since omap2_set_init_voltage is called as part of the pm framework's initialization sequence to configure the voltage required for the current OPP, the call does(and has to) setup the system voltage(curr_volt as a result) using the right mechanisms appropriate for the system at that point of time. This also overrides initialization we are currently doing in voltage.c making it redundant. So, remove the wrong and redundant initialization.
--- arch/arm/mach-omap2/voltage.c | 1 - 1 files changed, 0 insertions(+), 1 deletions(-)
arch/arm/mach-omap2/voltage.c +0 -1
@@ -116,7 +116,6 @@ static int __init _config_common_vdd_data(struct omap_vdd_info *vdd) sys_clk_speed /=1000 ;/* Generic voltage parameters */ - vdd->curr_volt =1200000 ; vdd->volt_scale = vp_forceupdate_scale_voltage; vdd->vp_enabled = false;
Signature · 1 line
1.7.1
PATCH v3 3/19 OMAP3+: voltage: remove initial voltage
Hello.
Quoted 1 line · Nishanth Menon
Blindly setting a 1.2V setting
Hm, seems tautological...
Quoted 13 lines
in the initial structure may not even
match the default voltages stored in the voltage table which are supported for the domain. For example, OMAP3430 core domain does not use 1.2V and ends up generating a warning on the first transition.Further, since
omap2_set_init_voltageis called as part of the pm framework's initialization sequence to configure the voltage required for the current OPP, the call does(and has to) setup the systemvoltage(curr_volt as a result)using the right mechanisms appropriate for the system at that point of time. This also overrides initialization we are currently doing involtage.cmaking it redundant. So, remove the wrong and redundant initialization.
Quoted 1 line
Signed-off-by Nishanth Menon<[email protected]>
WBR, Sergei
PATCH v3 3/19 OMAP3+: voltage: remove initial voltage
Sergei Shtylyov wrote, on 03/06/2011 07:07 PM:
Quoted 4 lines
Quoted 2 lines
Blindly setting a 1.2V setting
Hm, seems tautological...
As a non native English speaker, I would like to understand how we could improve this. I suppose you mean "Blindly setting 1.2V" is better here. Am i correct?
Quoted 4 lines
Quoted 4 lines
in the initial structure may not even
match the default voltages stored in the voltage table which are supported for the domain. For example, OMAP3430 core domain does not use 1.2V and ends up generating a warning on the first transition.
[..]
Signature · 2 lines
Regards, Nishanth Menon
PATCH v3 3/19 OMAP3+: voltage: remove initial voltage
Hello.
Quoted 7 lines · Nishanth Menon
Quoted 3 lines
Quoted 1 line
Blindly setting a 1.2V setting
Hm, seems tautological...
As a non native English speaker, I would like to understand how we could improve this. I suppose you mean "Blindly setting 1.2V" is better here. Am i correct?
Yes.
WBR, Sergei
PATCH v3 3/19 OMAP3+: voltage: remove initial voltage
Quoted 6 lines · Sergei Shtylyov
Hello.
Quoted 1 line · Nishanth Menon
Quoted 1 line
Quoted 1 line
Blindly setting a 1.2V setting
Quoted 7 lines
Quoted 5 lines
Quoted 1 line
Hm, seems tautological...
As a non native English speaker, I would like to understand how we could improve this. I suppose you mean "Blindly setting 1.2V" is better here. Am i correct?
Yes.
OK, here is the update as per the suggestion:
Regards,
Nishanth Menon
From: Nishanth Menon <[email protected]>
Date: Tue, 15 Feb 2011 09:37:18 +0530
Subject: [PATCH V4 3/19] OMAP3+: voltage: remove initial voltage
Blindly setting 1.2V in the initial structure may not even match the default voltages stored in the voltage table which are supported for the domain. For example, OMAP3430 core domain does not use 1.2V and ends up generating a warning on the first transition.
Further, since omap2_set_init_voltage is called as part of the pm framework's initialization sequence to configure the voltage required for the current OPP, the call does(and has to) setup the system voltage(curr_volt as a result) using the right mechanisms appropriate for the system at that point of time. This also overrides initialization we are currently doing in voltage.c making it redundant. So, remove the wrong and redundant initialization.
--- arch/arm/mach-omap2/voltage.c | 1 - 1 files changed, 0 insertions(+), 1 deletions(-)
arch/arm/mach-omap2/voltage.c +0 -1
@@ -116,7 +116,6 @@ static int __init _config_common_vdd_data(struct omap_vdd_info *vdd) sys_clk_speed /=1000 ;/* Generic voltage parameters */ - vdd->curr_volt =1200000 ; vdd->volt_scale = vp_forceupdate_scale_voltage; vdd->vp_enabled = false;
Signature · 1 line
1.7.1
PATCH v3 3/19 OMAP3+: voltage: remove initial voltage
Quoted 34 lines · Nishanth Menon
Quoted 6 lines · Sergei Shtylyov
Hello.
Quoted 1 line · Nishanth Menon
Quoted 1 line
Quoted 1 line
Blindly setting a 1.2V setting
Quoted 7 lines
Quoted 5 lines
Quoted 1 line
Hm, seems tautological...
As a non native English speaker, I would like to understand how we could improve this. I suppose you mean "Blindly setting 1.2V" is better here. Am i correct?
Yes.
OK, here is the update as per the suggestion:
Regards,
Nishanth Menon
From: Nishanth Menon <[email protected]>
Date: Tue, 15 Feb 2011 09:37:18 +0530
Subject: [PATCH V4 3/19] OMAP3+: voltage: remove initial voltageBlindly setting 1.2V in the initial structure may not even match the default voltages stored in the voltage table which are supported for the domain. For example, OMAP3430 core domain does not use 1.2V and ends up generating a warning on the first transition.
Further, since
omap2_set_init_voltageis called as part of the pm framework's initialization sequence to configure the voltage required for the current OPP, the call does(and has to) setup the systemvoltage(curr_volt as a result)using the right mechanisms appropriate for the system at that point of time. This also overrides initialization we are currently doing involtage.cmaking it redundant. So, remove the wrong and redundant initialization.
Quoted 1 line
Signed-off-by Nishanth Menon <[email protected]>
FWIW:
Quoted 23 lines
--- arch/arm/mach-omap2/voltage.c | 1 - 1 files changed, 0 insertions(+), 1 deletions(-)arch/arm/mach-omap2/voltage.c +0
-1@@ -116,7 +116,6 @@ static int __init _config_common_vdd_data(struct omap_vdd_info *vdd) sys_clk_speed /=1000 ;/* Generic voltage parameters */ - vdd->curr_volt =1200000 ; vdd->volt_scale = vp_forceupdate_scale_voltage; vdd->vp_enabled = false;Signature · 6 lines
1.7.1 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo at vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Signature · 8 lines
balbi -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 490 bytes Desc: Digital signature URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20110726/44d6beb9/attachment.sig>
PATCH v3 3/19 OMAP3+: voltage: remove initial voltage
In reply to Nishanth MenonQuoted 13 lines · Nishanth Menon
Blindly setting a 1.2V setting in the initial structure may not even match the default voltages stored in the voltage table which are supported for the domain. For example, OMAP3430 core domain does not use 1.2V and ends up generating a warning on the first transition.
Further, since
omap2_set_init_voltageis called as part of the pm framework's initialization sequence to configure the voltage required for the current OPP, the call does(and has to) setup the systemvoltage(curr_volt as a result)using the right mechanisms appropriate for the system at that point of time. This also overrides initialization we are currently doing involtage.cmaking it redundant. So, remove the wrong and redundant initialization.
Quoted 1 line
Signed-off-by Nishanth Menon <[email protected]>
Thanks queuing for 2.6.39 fixes (branch: for_2.6.39/pm-fixes)
Note: Nishanth, I queued the one with updated changelog from the tarball you sent.)
Kevin
Quoted 15 lines
--- arch/arm/mach-omap2/voltage.c | 1 - 1 files changed, 0 insertions(+), 1 deletions(-)arch/arm/mach-omap2/voltage.c +0
-1@@ -116,7 +116,6 @@ static int __init _config_common_vdd_data(struct omap_vdd_info *vdd) sys_clk_speed /=1000 ;/* Generic voltage parameters */ - vdd->curr_volt =1200000 ; vdd->volt_scale = vp_forceupdate_scale_voltage; vdd->vp_enabled = false;
PATCH v3 4/19 OMAP3+: voltage: remove spurious pr_notice for debugfs
In reply to Nishanth Menoncat of debugfs entry for vp_volt provides voltage. The additional pr_notice is just spam on console and provides no additional information.
--- arch/arm/mach-omap2/voltage.c | 1 - 1 files changed, 0 insertions(+), 1 deletions(-)
arch/arm/mach-omap2/voltage.c +0 -1
@@ -150,7 +150,6 @@ static int vp_volt_debug_get(void *data, u64 *val) } vsel = vdd->read_reg (prm_mod_offs, vdd->vp_data->voltage); -pr_notice ("curr_vsel = %x\n" , vsel);if (!vdd->pmic_info->vsel_to_uv) { pr_warning("PMIC function to convert vsel to voltage"
Signature · 1 line
1.7.1
PATCH v3 4/19 OMAP3+: voltage: remove spurious pr_notice for debugfs
Quoted 4 lines · Nishanth Menon
cat of debugfs entry for
vp_voltprovides voltage. The additionalpr_noticeis just spam on console and provides no additional information.Signed-off-by Nishanth Menon <[email protected]>
Thanks, queueing for 2.6.39-rc fixes cycle.
Kevin
Quoted 16 lines
--- arch/arm/mach-omap2/voltage.c | 1 - 1 files changed, 0 insertions(+), 1 deletions(-)arch/arm/mach-omap2/voltage.c +0
-1@@ -150,7 +150,6 @@ static int vp_volt_debug_get(void *data, u64 *val) } vsel = vdd->read_reg (prm_mod_offs, vdd->vp_data->voltage); -pr_notice ("curr_vsel = %x\n" , vsel);if (!vdd->pmic_info->vsel_to_uv) { pr_warning("PMIC function to convert vsel to voltage"
PATCH v3 4/19 OMAP3+: voltage: remove spurious pr_notice for debugfs
In reply to Nishanth MenonQuoted 4 lines · Nishanth Menon
cat of debugfs entry for
vp_voltprovides voltage. The additionalpr_noticeis just spam on console and provides no additional information.Signed-off-by Nishanth Menon <[email protected]>
FWIW:
Quoted 23 lines
--- arch/arm/mach-omap2/voltage.c | 1 - 1 files changed, 0 insertions(+), 1 deletions(-)arch/arm/mach-omap2/voltage.c +0
-1@@ -150,7 +150,6 @@ static int vp_volt_debug_get(void *data, u64 *val) } vsel = vdd->read_reg (prm_mod_offs, vdd->vp_data->voltage); -pr_notice ("curr_vsel = %x\n" , vsel);if (!vdd->pmic_info->vsel_to_uv) { pr_warning("PMIC function to convert vsel to voltage"Signature · 6 lines
1.7.1 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo at vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Signature · 8 lines
balbi -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 490 bytes Desc: Digital signature URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20110726/3e8b2b6e/attachment.sig>
PATCH v3 5/19 OMAP3+: voltage: use IS_ERR_OR_NULL
In reply to Nishanth MenonUse IS_ERR_OR_NULL macro instead of !xyz || IS_ERR(xyz) usage.
--- arch/arm/mach-omap2/voltage.c | 22 +++++++++++----------- 1 files changed, 11 insertions(+), 11 deletions(-)
arch/arm/mach-omap2/voltage.c +11 -11
@@ -682,7 +682,7 @@ unsigned long omap_voltage_get_nom_volt(struct voltagedomain *voltdm) {struct omap_vdd_info *vdd; -if (!voltdm ||IS_ERR (voltdm)) { +if (IS_ERR_OR_NULL (voltdm)) {pr_warning ("%s: VDD specified does not exist!\n" , __func__);return 0 ; }
@@ -703,7 +703,7 @@ unsigned long omap_vp_get_curr_volt(struct voltagedomain *voltdm)struct omap_vdd_info *vdd;u8 curr_vsel; -if (!voltdm ||IS_ERR (voltdm)) { +if (IS_ERR_OR_NULL (voltdm)) {pr_warning ("%s: VDD specified does not exist!\n" , __func__);return 0 ; }
@@ -738,7 +738,7 @@ void omap_vp_enable(struct voltagedomain *voltdm)struct omap_vdd_info *vdd;u32 vpconfig; -if (!voltdm ||IS_ERR (voltdm)) { +if (IS_ERR_OR_NULL (voltdm)) {pr_warning ("%s: VDD specified does not exist!\n" , __func__);return ; }
@@ -776,7 +776,7 @@ void omap_vp_disable(struct voltagedomain *voltdm)u32 vpconfig;int timeout; -if (!voltdm ||IS_ERR (voltdm)) { +if (IS_ERR_OR_NULL (voltdm)) {pr_warning ("%s: VDD specified does not exist!\n" , __func__);return ; }
@@ -829,7 +829,7 @@ int omap_voltage_scale_vdd(struct voltagedomain *voltdm, {struct omap_vdd_info *vdd; -if (!voltdm ||IS_ERR (voltdm)) { +if (IS_ERR_OR_NULL (voltdm)) {pr_warning ("%s: VDD specified does not exist!\n" , __func__);return -EINVAL ; }
@@ -858,7 +858,7 @@ void omap_voltage_reset(struct voltagedomain *voltdm) {unsigned long target_uvdc; -if (!voltdm ||IS_ERR (voltdm)) { +if (IS_ERR_OR_NULL (voltdm)) {pr_warning ("%s: VDD specified does not exist!\n" , __func__);return ; }
@@ -890,7 +890,7 @@ void omap_voltage_get_volttable(struct voltagedomain *voltdm, {struct omap_vdd_info *vdd; -if (!voltdm ||IS_ERR (voltdm)) { +if (IS_ERR_OR_NULL (voltdm)) {pr_warning ("%s: VDD specified does not exist!\n" , __func__);return ; }
@@ -921,7 +921,7 @@ struct omap_volt_data *omap_voltage_get_voltdata(struct voltagedomain *voltdm,struct omap_vdd_info *vdd;int i; -if (!voltdm ||IS_ERR (voltdm)) { +if (IS_ERR_OR_NULL (voltdm)) {pr_warning ("%s: VDD specified does not exist!\n" , __func__);return ERR_PTR (-EINVAL ); }
@@ -959,7 +959,7 @@ int omap_voltage_register_pmic(struct voltagedomain *voltdm, {struct omap_vdd_info *vdd; -if (!voltdm ||IS_ERR (voltdm)) { +if (IS_ERR_OR_NULL (voltdm)) {pr_warning ("%s: VDD specified does not exist!\n" , __func__);return -EINVAL ; }
@@ -986,7 +986,7 @@ struct dentry *omap_voltage_get_dbgdir(struct voltagedomain *voltdm) {struct omap_vdd_info *vdd; -if (!voltdm ||IS_ERR (voltdm)) { +if (IS_ERR_OR_NULL (voltdm)) {pr_warning ("%s: VDD specified does not exist!\n" , __func__);return NULL ; }
@@ -1011,7 +1011,7 @@ void omap_change_voltscale_method(struct voltagedomain *voltdm, {struct omap_vdd_info *vdd; -if (!voltdm ||IS_ERR (voltdm)) { +if (IS_ERR_OR_NULL (voltdm)) {pr_warning ("%s: VDD specified does not exist!\n" , __func__);return ; }
Signature · 1 line
1.7.1
PATCH v3 5/19 OMAP3+: voltage: use IS_ERR_OR_NULL
Hi Nishanth,
Quoted 12 lines · Nishanth Menon
Use
IS_ERR_OR_NULLmacro instead of !xyz ||IS_ERR(xyz)usage.Signed-off-by Nishanth Menon <[email protected]>---
?arch/arm/mach-omap2/voltage.c | ? 22 +++++++++++----------- ?1 files changed, 11 insertions(+), 11 deletions(-)arch/arm/mach-omap2/voltage.c +0
-0
arch/arm/mach-omap2/voltage.c unsigned long omap_voltage_get_nom_volt(struct voltagedomain *voltdm) · line 685
Quoted 5 lines
arch/arm/mach-omap2/voltage.c +1
-1@@ -682,7 +682,7 @@ unsigned long omap_voltage_get_nom_volt(struct voltagedomain *voltdm) ?{ ? ? ? ?struct omap_vdd_info *vdd; - ? ? ? if (!voltdm || IS_ERR(voltdm)) { + ? ? ? if (IS_ERR_OR_NULL(voltdm)) {
I have one comment here. voltdm is received as parameter and it's already checked by IS_ERR(). Is there any specific reason for that? IS_ERR() doesn't suppose to be a macro to check if the pointer is valid or not, but to know if there's an invalid value with error code in the pointer value. It's useful when you have a function which returns a pointer but it can return an error code when it fails. Please, note that IS_ERR() won't detect invalid pointers which does not represent an error code, so it's not correct to rely on it for this purpose.
IMO, instead of change to IS_ERR_OR_NULL(), you could only remove IS_ERR(). The same apply for the other cases.
Kind regards,
David Cohen
Quoted 101 lines
arch/arm/mach-omap2/voltage.c +10
-11? ? ? ? ? ? ? ?pr_warning("%s: VDD specified does not exist!\n", __func__); ? ? ? ? ? ? ? ?return 0; ? ? ? ?}@@ -703,7 +703,7 @@ unsigned long omap_vp_get_curr_volt(struct voltagedomain *voltdm) ? ? ? ?struct omap_vdd_info *vdd; ? ? ? ?u8 curr_vsel; - ? ? ? if (!voltdm || IS_ERR(voltdm)) { + ? ? ? if (IS_ERR_OR_NULL(voltdm)) { ? ? ? ? ? ? ? ?pr_warning("%s: VDD specified does not exist!\n", __func__); ? ? ? ? ? ? ? ?return 0; ? ? ? ?}@@ -738,7 +738,7 @@ void omap_vp_enable(struct voltagedomain *voltdm) ? ? ? ?struct omap_vdd_info *vdd; ? ? ? ?u32 vpconfig; - ? ? ? if (!voltdm || IS_ERR(voltdm)) { + ? ? ? if (IS_ERR_OR_NULL(voltdm)) { ? ? ? ? ? ? ? ?pr_warning("%s: VDD specified does not exist!\n", __func__); ? ? ? ? ? ? ? ?return; ? ? ? ?}@@ -776,7 +776,7 @@ void omap_vp_disable(struct voltagedomain *voltdm) ? ? ? ?u32 vpconfig; ? ? ? ?int timeout; - ? ? ? if (!voltdm || IS_ERR(voltdm)) { + ? ? ? if (IS_ERR_OR_NULL(voltdm)) { ? ? ? ? ? ? ? ?pr_warning("%s: VDD specified does not exist!\n", __func__); ? ? ? ? ? ? ? ?return; ? ? ? ?}@@ -829,7 +829,7 @@ int omap_voltage_scale_vdd(struct voltagedomain *voltdm, ?{ ? ? ? ?struct omap_vdd_info *vdd; - ? ? ? if (!voltdm || IS_ERR(voltdm)) { + ? ? ? if (IS_ERR_OR_NULL(voltdm)) { ? ? ? ? ? ? ? ?pr_warning("%s: VDD specified does not exist!\n", __func__); ? ? ? ? ? ? ? ?return -EINVAL; ? ? ? ?}@@ -858,7 +858,7 @@ void omap_voltage_reset(struct voltagedomain *voltdm) ?{ ? ? ? ?unsigned long target_uvdc; - ? ? ? if (!voltdm || IS_ERR(voltdm)) { + ? ? ? if (IS_ERR_OR_NULL(voltdm)) { ? ? ? ? ? ? ? ?pr_warning("%s: VDD specified does not exist!\n", __func__); ? ? ? ? ? ? ? ?return; ? ? ? ?}@@ -890,7 +890,7 @@ void omap_voltage_get_volttable(struct voltagedomain *voltdm, ?{ ? ? ? ?struct omap_vdd_info *vdd; - ? ? ? if (!voltdm || IS_ERR(voltdm)) { + ? ? ? if (IS_ERR_OR_NULL(voltdm)) { ? ? ? ? ? ? ? ?pr_warning("%s: VDD specified does not exist!\n", __func__); ? ? ? ? ? ? ? ?return; ? ? ? ?}@@ -921,7 +921,7 @@ struct omap_volt_data *omap_voltage_get_voltdata(struct voltagedomain *voltdm, ? ? ? ?struct omap_vdd_info *vdd; ? ? ? ?int i; - ? ? ? if (!voltdm || IS_ERR(voltdm)) { + ? ? ? if (IS_ERR_OR_NULL(voltdm)) { ? ? ? ? ? ? ? ?pr_warning("%s: VDD specified does not exist!\n", __func__); ? ? ? ? ? ? ? ?return ERR_PTR(-EINVAL); ? ? ? ?}@@ -959,7 +959,7 @@ int omap_voltage_register_pmic(struct voltagedomain *voltdm, ?{ ? ? ? ?struct omap_vdd_info *vdd; - ? ? ? if (!voltdm || IS_ERR(voltdm)) { + ? ? ? if (IS_ERR_OR_NULL(voltdm)) { ? ? ? ? ? ? ? ?pr_warning("%s: VDD specified does not exist!\n", __func__); ? ? ? ? ? ? ? ?return -EINVAL; ? ? ? ?}@@ -986,7 +986,7 @@ struct dentry *omap_voltage_get_dbgdir(struct voltagedomain *voltdm) ?{ ? ? ? ?struct omap_vdd_info *vdd; - ? ? ? if (!voltdm || IS_ERR(voltdm)) { + ? ? ? if (IS_ERR_OR_NULL(voltdm)) { ? ? ? ? ? ? ? ?pr_warning("%s: VDD specified does not exist!\n", __func__); ? ? ? ? ? ? ? ?return NULL; ? ? ? ?}@@ -1011,7 +1011,7 @@ void omap_change_voltscale_method(struct voltagedomain *voltdm, ?{ ? ? ? ?struct omap_vdd_info *vdd; - ? ? ? if (!voltdm || IS_ERR(voltdm)) { + ? ? ? if (IS_ERR_OR_NULL(voltdm)) { ? ? ? ? ? ? ? ?pr_warning("%s: VDD specified does not exist!\n", __func__); ? ? ? ? ? ? ? ?return; ? ? ? ?} --1.7.1
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo at vger.kernel.org
More majordomo info at ?http://vger.kernel.org/majordomo-info.html
PATCH v3 5/19 OMAP3+: voltage: use IS_ERR_OR_NULL
David Cohen wrote, on 03/05/2011 11:06 PM:
[..]
Quoted 8 lines
Quoted 8 lines
arch/arm/mach-omap2/voltage.c +0
-0@@ -682,7 +682,7 @@ unsigned long omap_voltage_get_nom_volt(struct voltagedomain *voltdm) {struct omap_vdd_info *vdd;
Quoted 5 lines
arch/arm/mach-omap2/voltage.c unsigned long omap_voltage_get_nom_volt(struct voltagedomain *voltdm) · line 685
Quoted 2 lines
arch/arm/mach-omap2/voltage.c +1
-1-if (!voltdm ||IS_ERR (voltdm)) { +if (IS_ERR_OR_NULL (voltdm)) {I have one comment here. voltdm is received as parameter and it's already checked by
IS_ERR(). Is there any specific reason for that?
yes:
1. omap_voltage_domain_lookup can return ERR_PTR() in certain conditions
2. the !voltdm is coz of the usage of these APIs from external to voltage.c (sr, pm, dvfs etc) - it is possible (and has happend) when mistakes have been made and NULL pointers passed as voltdm.
Quoted 9 lines
IS_ERR()doesn't suppose to be a macro to check if the pointer is valid or not, but to know if there's an invalid value with error code in the pointer value. It's useful when you have a function which returns a pointer but it can return an error code when it fails. Please, note thatIS_ERR()won't detect invalid pointers which does not represent an error code, so it's not correct to rely on it for this purpose.
IMO, instead of change toIS_ERR_OR_NULL(), you could only removeIS_ERR(). The same apply for the other cases.
no, I am not convinced with your argument.
omap_voltage_get_nom_volt(omap_voltage_domain_lookup("me")); IS_ERR is useful in this case. If I were to remove vdata, PTR_ERR(something)== vdata and vdata !=NULL and it will try to dereference and crash.
my_dumb_func(){
struct voltagedomain *vdata = NULL;
if (cpu_is_omap3630()_) {
vdata = omap_voltage_domain_lookup("mpu")
}
/* forgot to add other cpu types or a else case */
/* do other things */
me_volt=omap_voltage_get_nom_volt(vdata);
/* do things with me_volt */
}Sorry, but i think the check, even if seems superfluous is sane IMHO. even if the above code worked on 3630, it'd fail on o4/3430 without the check, it can even crash. and given that we've all seen our fair share of developers who develop for one platform without consideration that the rest of the world uses others as well... I do feel cases like above example might infact be a reality.
[...]
Signature · 2 lines
Regards, Nishanth Menon
PATCH v3 5/19 OMAP3+: voltage: use IS_ERR_OR_NULL
Quoted 11 lines · Nishanth Menon
my_dumb_func(){
struct voltagedomain *vdata = NULL;
if (cpu_is_omap3630()_) {
vdata = omap_voltage_domain_lookup("mpu")
}
/* forgot to add other cpu types or a else case */
/* do other things */
me_volt=omap_voltage_get_nom_volt(vdata);
/* do things with me_volt */
}Quoted 6 lines
Sorry, but i think the check, even if seems superfluous is sane IMHO. even if the above code worked on 3630, it'd fail on o4/3430 without the check, it can even crash. and given that we've all seen our fair share of developers who develop for one platform without consideration that the rest of the world uses others as well... I do feel cases like above example might infact be a reality.
But normal practice is to check the return value from functions before it's used. So:
my_dumb_func(){
struct voltagedomain *vdata = NULL;
if (cpu_is_omap3630()) {
vdata = omap_voltage_domain_lookup("mpu")
}
/* forgot to add other cpu types or a else case */+ if (!vdata)
+ return some error;
/* do other things */ me_volt=omap_voltage_get_nom_volt(vdata); /* do things with me_volt */
}
is the right way to deal with this. Pushing the primary error checking down into sub-functions is stupid - where does it stop? Do you check me_volt for errors? Do you get functions which use me_volt to check for errors from that too?
It's a silly idea. Put the primary error checking in the function which gets the return value. Don't bury it in sub-functions.
PATCH v3 5/19 OMAP3+: voltage: use IS_ERR_OR_NULL
Russell King - ARM Linux wrote, on 03/06/2011 01:48 PM:
Quoted 37 lines · Nishanth Menon
Quoted 11 lines
my_dumb_func(){ struct voltagedomain *vdata = NULL; if (cpu_is_omap3630()_) { vdata = omap_voltage_domain_lookup("mpu") } /* forgot to add other cpu types or a else case */ /* do other things */ me_volt=omap_voltage_get_nom_volt(vdata); /* do things with me_volt */ }Quoted 6 lines
Sorry, but i think the check, even if seems superfluous is sane IMHO. even if the above code worked on 3630, it'd fail on o4/3430 without the check, it can even crash. and given that we've all seen our fair share of developers who develop for one platform without consideration that the rest of the world uses others as well... I do feel cases like above example might infact be a reality.
But normal practice is to check the return value from functions before it's used. So:
my_dumb_func(){ struct voltagedomain *vdata = NULL; if (cpu_is_omap3630()) { vdata = omap_voltage_domain_lookup("mpu") } /* forgot to add other cpu types or a else case */(quoted diff) +2
-0+ if (!vdata) + return some error;/* do other things */ me_volt=omap_voltage_get_nom_volt(vdata); /* do things with me_volt */}
Quoted 7 lines
is the right way to deal with this. Pushing the primary error checking down into sub-functions is stupid - where does it stop? Do you check
me_voltfor errors? Do you get functions which useme_voltto check for errors from that too?It's a silly idea. Put the primary error checking in the function which gets the return value. Don't bury it in sub-functions.
I agree with you on this - sub functions esp static ones should able to trust the parameters passed to it by callers. for the moment, I suggest we drop this patch from this series - it has no functional impact to the overall goal which I was attempting to achieve. Cleanups of the voltage, smartreflex layers are an ongoing activity currently and should be takenup as part of it.
Signature · 2 lines
Regards, Nishanth Menon
PATCH v3 5/19 OMAP3+: voltage: use IS_ERR_OR_NULL
In reply to Nishanth MenonQuoted 3 lines · Nishanth Menon
Use
IS_ERR_OR_NULLmacro instead of !xyz ||IS_ERR(xyz)usage.Signed-off-by Nishanth Menon <[email protected]>
FWIW:
Quoted 114 lines
--- arch/arm/mach-omap2/voltage.c | 22 +++++++++++----------- 1 files changed, 11 insertions(+), 11 deletions(-)arch/arm/mach-omap2/voltage.c +11
-11@@ -682,7 +682,7 @@ unsigned long omap_voltage_get_nom_volt(struct voltagedomain *voltdm) {struct omap_vdd_info *vdd; -if (!voltdm ||IS_ERR (voltdm)) { +if (IS_ERR_OR_NULL (voltdm)) {pr_warning ("%s: VDD specified does not exist!\n" , __func__);return 0 ; }@@ -703,7 +703,7 @@ unsigned long omap_vp_get_curr_volt(struct voltagedomain *voltdm)struct omap_vdd_info *vdd;u8 curr_vsel; -if (!voltdm ||IS_ERR (voltdm)) { +if (IS_ERR_OR_NULL (voltdm)) {pr_warning ("%s: VDD specified does not exist!\n" , __func__);return 0 ; }@@ -738,7 +738,7 @@ void omap_vp_enable(struct voltagedomain *voltdm)struct omap_vdd_info *vdd;u32 vpconfig; -if (!voltdm ||IS_ERR (voltdm)) { +if (IS_ERR_OR_NULL (voltdm)) {pr_warning ("%s: VDD specified does not exist!\n" , __func__);return ; }@@ -776,7 +776,7 @@ void omap_vp_disable(struct voltagedomain *voltdm)u32 vpconfig;int timeout; -if (!voltdm ||IS_ERR (voltdm)) { +if (IS_ERR_OR_NULL (voltdm)) {pr_warning ("%s: VDD specified does not exist!\n" , __func__);return ; }@@ -829,7 +829,7 @@ int omap_voltage_scale_vdd(struct voltagedomain *voltdm, {struct omap_vdd_info *vdd; -if (!voltdm ||IS_ERR (voltdm)) { +if (IS_ERR_OR_NULL (voltdm)) {pr_warning ("%s: VDD specified does not exist!\n" , __func__);return -EINVAL ; }@@ -858,7 +858,7 @@ void omap_voltage_reset(struct voltagedomain *voltdm) {unsigned long target_uvdc; -if (!voltdm ||IS_ERR (voltdm)) { +if (IS_ERR_OR_NULL (voltdm)) {pr_warning ("%s: VDD specified does not exist!\n" , __func__);return ; }@@ -890,7 +890,7 @@ void omap_voltage_get_volttable(struct voltagedomain *voltdm, {struct omap_vdd_info *vdd; -if (!voltdm ||IS_ERR (voltdm)) { +if (IS_ERR_OR_NULL (voltdm)) {pr_warning ("%s: VDD specified does not exist!\n" , __func__);return ; }@@ -921,7 +921,7 @@ struct omap_volt_data *omap_voltage_get_voltdata(struct voltagedomain *voltdm,struct omap_vdd_info *vdd;int i; -if (!voltdm ||IS_ERR (voltdm)) { +if (IS_ERR_OR_NULL (voltdm)) {pr_warning ("%s: VDD specified does not exist!\n" , __func__);return ERR_PTR (-EINVAL ); }@@ -959,7 +959,7 @@ int omap_voltage_register_pmic(struct voltagedomain *voltdm, {struct omap_vdd_info *vdd; -if (!voltdm ||IS_ERR (voltdm)) { +if (IS_ERR_OR_NULL (voltdm)) {pr_warning ("%s: VDD specified does not exist!\n" , __func__);return -EINVAL ; }@@ -986,7 +986,7 @@ struct dentry *omap_voltage_get_dbgdir(struct voltagedomain *voltdm) {struct omap_vdd_info *vdd; -if (!voltdm ||IS_ERR (voltdm)) { +if (IS_ERR_OR_NULL (voltdm)) {pr_warning ("%s: VDD specified does not exist!\n" , __func__);return NULL ; }@@ -1011,7 +1011,7 @@ void omap_change_voltscale_method(struct voltagedomain *voltdm, {struct omap_vdd_info *vdd; -if (!voltdm ||IS_ERR (voltdm)) { +if (IS_ERR_OR_NULL (voltdm)) {pr_warning ("%s: VDD specified does not exist!\n" , __func__);return ; }Signature · 6 lines
1.7.1 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo at vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Signature · 8 lines
balbi -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 490 bytes Desc: Digital signature URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20110726/52f5acaa/attachment.sig>
PATCH v3 6/19 OMAP3+: voltage: use volt_data pointer instead values
In reply to Nishanth MenonVoltage values can get confusing in meaning with various SmartReflex classes being active. Depending on the class used, the actual voltage selected might be a variant. For example:
With SmartReflex AVS class 3:
a) If we don't have SR enabled, we will go to volt_nominal.
b) If have SR enabled, we go to volt_nominal, then enable SR and expect it to adjust voltage. We don't really care about the resultant voltage.
Essentially, when we ask voltage layer to scale to voltage x for OPP y, it always means x is the nominal voltage for OPP y.
Now, once we introduce SmartReflex AVS class 1.5:
a) If you are booting for the first time OR if you never enabled SR before, we always go to volt_nominal.
b) If you enable SR and the OPP is calibrated, we will not enable SR again when that OPP is accessed anymore, but when we set voltage for an OPP, the voltage achieved will be volt_calibrated.
c) If recalibration timeout triggers or SR is disabled after a calibration, the calibrated values are not valid anymore, at this point, setting the voltage will mean volt_dynamic_nominal.
So, depending on which state the system is at, voltage for that OPP we are setting has not 1 single value anymore, but 3 possible valid values.
For upper layers(DVFS/cpufreq OMAP SoC layers) to use voltage values, it will need to know which type of voltage AVS strategy is being used and the corresponding system state from voltage layer perspective. This would replicate the role of voltage layer, SmartReflex AVS in the upper layers and make the corresponding implementations complex.
Since each voltage domain contains a set of volt_data structs representing a voltage point that is supported for that domain, volt_data is a more accurate representation of the voltage point we are interested in going to, and the actual translation of this voltage point to the voltage value is done inside the voltage layer. Doing this allows the users of the voltage layer to be blissfully ignorant of any complexity of the underneath layers and simplify the implementation of dependent layers.
--- arch/arm/mach-omap2/pm.c | 3 +- arch/arm/mach-omap2/smartreflex-class3.c | 3 +- arch/arm/mach-omap2/voltage.c | 75 +++++++++++++++++------------- arch/arm/mach-omap2/voltage.h | 17 +++++-- 4 files changed, 59 insertions(+), 39 deletions(-)
arch/arm/mach-omap2/pm.c +2 -1
@@ -209,7 +209,8 @@ static int __init omap2_set_init_voltage(char *vdd_name, char *clk_name, goto exit; } -omap_voltage_scale_vdd (voltdm, bootup_volt); +omap_voltage_scale_vdd (voltdm, +omap_voltage_get_voltdata (voltdm, bootup_volt));return 0 ; exit:
arch/arm/mach-omap2/smartreflex-class3.c +2 -1
@@ -15,7 +15,8 @@static int sr_class3_enable (struct voltagedomain *voltdm) { -unsigned long volt =omap_voltage_get_nom_volt (voltdm); +unsigned long volt =omap_get_operation_voltage ( +omap_voltage_get_nom_volt (voltdm));if (!volt) { pr_warning("%s: Curr voltage unknown. Cannot enable sr_%s\n",
arch/arm/mach-omap2/voltage.c +42 -33
171 lines not on this page · raw message
arch/arm/mach-omap2/voltage.h +13 -4
@@ -131,25 +131,25 @@ struct omap_vdd_info {const struct omap_vfsm_instance_data *vfsm;struct voltagedomain voltdm;struct dentry *debug_dir; -u32 curr_volt; +struct omap_volt_data *curr_volt;bool vp_enabled;u32 (*read_reg) (u16 mod,u8 offset);void (*write_reg) (u32 val,u16 mod,u8 offset);int (*volt_scale) (struct omap_vdd_info *vdd, -unsigned long target_volt); +struct omap_volt_data *target_volt); };unsigned long omap_vp_get_curr_volt (struct voltagedomain *voltdm);void omap_vp_enable (struct voltagedomain *voltdm);void omap_vp_disable (struct voltagedomain *voltdm);int omap_voltage_scale_vdd (struct voltagedomain *voltdm, -unsigned long target_volt); +struct omap_volt_data *target_volt);void omap_voltage_reset (struct voltagedomain *voltdm);void omap_voltage_get_volttable (struct voltagedomain *voltdm,struct omap_volt_data **volt_data);struct omap_volt_data *omap_voltage_get_voltdata (struct voltagedomain *voltdm,unsigned long volt); -unsigned long omap_voltage_get_nom_volt (struct voltagedomain *voltdm); +struct omap_volt_data *omap_voltage_get_nom_volt (struct voltagedomain *voltdm);struct dentry *omap_voltage_get_dbgdir (struct voltagedomain *voltdm); int __init omap_voltage_early_init(s16 prm_mod, s16 prm_irqst_mod, struct omap_vdd_info *omap_vdd_array[],
@@ -181,4 +181,13 @@ static inline struct voltagedomain *omap_voltage_domain_lookup(char *name) }#endif +/* convert volt data to the voltage for the voltage data */ +static inline unsigned long omap_get_operation_voltage ( +struct omap_volt_data *vdata) +{ +if (IS_ERR_OR_NULL (vdata)) +return 0 ; +return vdata->volt_nominal; +} +#endif
Signature · 1 line
1.7.1
PATCH v3 6/19 OMAP3+: voltage: use volt_data pointer instead values
Quoted 38 lines · Nishanth Menon
Voltage values can get confusing in meaning with various SmartReflex classes being active. Depending on the class used, the actual voltage selected might be a variant. For example:
With SmartReflex AVS class 3:
a) If we don't have SR enabled, we will go tovolt_nominal.
b) If have SR enabled, we go tovolt_nominal, then enable SR and expect it to adjust voltage. We don't really care about the resultant voltage.
Essentially, when we ask voltage layer to scale to voltage x for OPP y, it always means x is the nominal voltage for OPP y.Now, once we introduce SmartReflex AVS class 1.5:
a) If you are booting for the first time OR if you never enabled SR before, we always go tovolt_nominal.
b) If you enable SR and the OPP is calibrated, we will not enable SR again when that OPP is accessed anymore, but when we set voltage for an OPP, the voltage achieved will bevolt_calibrated.
c) If recalibration timeout triggers or SR is disabled after a calibration, the calibrated values are not valid anymore, at this point, setting the voltage will meanvolt_dynamic_nominal.
So, depending on which state the system is at, voltage for that OPP we are setting has not 1 single value anymore, but 3 possible valid values.For upper layers(DVFS/cpufreq OMAP SoC layers) to use voltage values, it will need to know which type of voltage AVS strategy is being used and the corresponding system state from voltage layer perspective. This would replicate the role of voltage layer, SmartReflex AVS in the upper layers and make the corresponding implementations complex.
Since each voltage domain contains a set of
volt_datastructs representing a voltage point that is supported for that domain,volt_datais a more accurate representation of the voltage point we are interested in going to, and the actual translation of this voltage point to the voltage value is done inside the voltage layer. Doing this allows the users of the voltage layer to be blissfully ignorant of any complexity of the underneath layers and simplify the implementation of dependent layers.
Quoted 1 line
Signed-off-by Nishanth Menon <[email protected]>
Mostly coding style and/or readability comments below...
Quoted 12 lines
--- arch/arm/mach-omap2/pm.c | 3 +- arch/arm/mach-omap2/smartreflex-class3.c | 3 +- arch/arm/mach-omap2/voltage.c | 75 +++++++++++++++++------------- arch/arm/mach-omap2/voltage.h | 17 +++++-- 4 files changed, 59 insertions(+), 39 deletions(-)arch/arm/mach-omap2/pm.c +0
-0
arch/arm/mach-omap2/pm.c static int __init omap2_set_init_voltage(char *vdd_name, char *clk_name, · line 213
Quoted 6 lines
arch/arm/mach-omap2/pm.c +2
-1@@ -209,7 +209,8 @@ static int __init omap2_set_init_voltage(char *vdd_name, char *clk_name, goto exit; } -omap_voltage_scale_vdd (voltdm, bootup_volt); +omap_voltage_scale_vdd (voltdm, +omap_voltage_get_voltdata (voltdm, bootup_volt));
coding style: to avoid wrapping (which IMO affects readabiliyt), assign volt_data to it's own variable then pass it to scale_vdd.
Quoted 8 lines
arch/arm/mach-omap2/pm.c +0
-0return 0 ; exit:arch/arm/mach-omap2/smartreflex-class3.c +0
-0
arch/arm/mach-omap2/smartreflex-class3.c line 19
Quoted 6 lines
arch/arm/mach-omap2/smartreflex-class3.c +2
-1@@ -15,7 +15,8 @@static int sr_class3_enable (struct voltagedomain *voltdm) { -unsigned long volt =omap_voltage_get_nom_volt (voltdm); +unsigned long volt =omap_get_operation_voltage ( +omap_voltage_get_nom_volt (voltdm));
readability/wrapping
Also, the name of the new function doesn't follow the naming convention of the rest of the voltage layer: e.g. omap_voltage_...
Quoted 38 lines
arch/arm/mach-omap2/smartreflex-class3.c +0
-0if (!volt) { pr_warning("%s: Curr voltage unknown. Cannot enable sr_%s\n",arch/arm/mach-omap2/voltage.c +9
-2@@ -58,7 +58,7 @@ static struct dentry *voltage_dir;/* Init function pointers */ static int vp_forceupdate_scale_voltage (struct omap_vdd_info *vdd, -unsigned long target_volt); +struct omap_volt_data *target_volt);static u32 omap3_voltage_read_reg (u16 mod,u8 offset) {@@ -164,13 +164,20 @@ static int vp_volt_debug_get(void *data, u64 *val)static int nom_volt_debug_get (void *data,u64 *val) {struct omap_vdd_info *vdd = (struct omap_vdd_info *) data; +struct omap_volt_data *volt_data;if (!vdd) {pr_warning ("Wrong paramater passed\n" );return -EINVAL ; } - *val =omap_voltage_get_nom_volt (&vdd->voltdm); + volt_data =omap_voltage_get_nom_volt (&vdd->voltdm); +if (IS_ERR_OR_NULL (volt_data)) { +pr_warning ("%s: No voltage/domain?\n" , __func__); +return -ENODEV ; + } + + *val = volt_data->volt_nominal;return 0 ; }
arch/arm/mach-omap2/voltage.c static void vp_latch_vsel(struct omap_vdd_info *vdd) · line 195
Quoted 6 lines
arch/arm/mach-omap2/voltage.c +2
-1@@ -184,7 +191,8 @@ static void vp_latch_vsel(struct omap_vdd_info *vdd)unsigned long uvdc;char vsel; - uvdc =omap_voltage_get_nom_volt (&vdd->voltdm); + uvdc =omap_get_operation_voltage ( +omap_voltage_get_nom_volt (&vdd->voltdm));
wrapping
Quoted 7 lines
arch/arm/mach-omap2/voltage.c +0
-0if (!uvdc) {pr_warning ("%s: unable to find current voltage for vdd_%s\n" , __func__, vdd->voltdm.name);@@ -302,13 +310,19 @@ static void __init vdd_debugfs_init(struct omap_vdd_info *vdd)/* Voltage scale and accessory APIs */ static int _pre_volt_scale(struct omap_vdd_info *vdd,
arch/arm/mach-omap2/voltage.c static void __init vdd_debugfs_init(struct omap_vdd_info *vdd) · line 320
Quoted 10 lines
arch/arm/mach-omap2/voltage.c +3
-2- unsigned long target_volt, u8 *target_vsel, u8 *current_vsel) + struct omap_volt_data *target_volt, u8 *target_vsel, + u8 *current_vsel) { - struct omap_volt_data *volt_data; const struct omap_vc_common_data *vc_common;const struct omap_vp_common_data *vp_common;u32 vc_cmdval, vp_errgain_val; + if (IS_ERR_OR_NULL(target_volt) || IS_ERR_OR_NULL(vdd) ||
Checking for NULL on arguments passed in is fine, but not sure the error check here makes any sense.
Quoted 10 lines
arch/arm/mach-omap2/voltage.c +5
-0+ !target_vsel || !current_vsel) { +pr_err ("%s: invalid parms!\n" , __func__); +return -EINVAL ; + } + vc_common = vdd->vc_data->vc_common; vp_common = vdd->vp_data->vp_common;@@ -332,12 +346,8 @@ static int _pre_volt_scale(struct omap_vdd_info *vdd,return -EINVAL ;
arch/arm/mach-omap2/voltage.c static int _pre_volt_scale(struct omap_vdd_info *vdd, · line 350
Quoted 10 lines
arch/arm/mach-omap2/voltage.c +2
-6} -/* Get volt_data corresponding to target_volt */ - volt_data =omap_voltage_get_voltdata (&vdd->voltdm, target_volt); -if (IS_ERR (volt_data)) - volt_data =NULL ; - - *target_vsel = vdd->pmic_info->uv_to_vsel (target_volt); + *target_vsel = vdd->pmic_info->uv_to_vsel ( +omap_get_operation_voltage (target_volt));
wrapping
Quoted 83 lines
arch/arm/mach-omap2/voltage.c +16
-18*current_vsel = vdd->read_reg (prm_mod_offs, vdd->vp_data->voltage);/* Setting the ON voltage to the new target voltage */ @@ -347,22 +357,21 @@ static int _pre_volt_scale(struct omap_vdd_info *vdd, vdd->write_reg (vc_cmdval, prm_mod_offs, vdd->vc_data->cmdval_reg);/* Setting vp errorgain based on the voltage */ -if (volt_data) { - vp_errgain_val = vdd->read_reg (prm_mod_offs, - vdd->vp_data->vpconfig); - vdd->vp_rt_data.vpconfig_errorgain = volt_data->vp_errgain; - vp_errgain_val &= ~vp_common->vpconfig_errorgain_mask; - vp_errgain_val |= vdd->vp_rt_data.vpconfig_errorgain << - vp_common->vpconfig_errorgain_shift; - vdd->write_reg (vp_errgain_val, prm_mod_offs, - vdd->vp_data->vpconfig); - } + vp_errgain_val = vdd->read_reg (prm_mod_offs, + vdd->vp_data->vpconfig); + vdd->vp_rt_data.vpconfig_errorgain = target_volt->vp_errgain; + vp_errgain_val &= ~vp_common->vpconfig_errorgain_mask; + vp_errgain_val |= vdd->vp_rt_data.vpconfig_errorgain << + vp_common->vpconfig_errorgain_shift; + vdd->write_reg (vp_errgain_val, prm_mod_offs, + vdd->vp_data->vpconfig);return 0 ; }static void _post_volt_scale (struct omap_vdd_info *vdd, -unsigned long target_volt,u8 target_vsel,u8 current_vsel) +struct omap_volt_data *target_volt,u8 target_vsel, +u8 current_vsel) {u32 smps_steps =0 , smps_delay =0 ;@@ -377,7 +386,7 @@ static void _post_volt_scale(struct omap_vdd_info *vdd,/* vc_bypass_scale_voltage - VC bypass method of voltage scaling */ static int vc_bypass_scale_voltage (struct omap_vdd_info *vdd, -unsigned long target_volt) +struct omap_volt_data *target_volt) {u32 loop_cnt =0 , retries_cnt =0 ;u32 vc_valid, vc_bypass_val_reg, vc_bypass_value;@@ -429,7 +438,7 @@ static int vc_bypass_scale_voltage(struct omap_vdd_info *vdd,/* VP force update method of voltage scaling */ static int vp_forceupdate_scale_voltage (struct omap_vdd_info *vdd, -unsigned long target_volt) +struct omap_volt_data *target_volt) {u32 vpconfig;u8 target_vsel, current_vsel, prm_irqst_reg;@@ -675,16 +684,15 @@ ovdc_out:* omap_voltage_get_nom_volt() - Gets the current non-auto-compensated voltage * @voltdm: pointer to the VDD for which current voltage info is needed * -* API to get the current non-auto-compensated voltage for a VDD. -* Returns 0 in case of error else returns the current voltage for the VDD. +* API to get the current voltage data pointer for a VDD. */ -unsigned long omap_voltage_get_nom_volt (struct voltagedomain *voltdm) +struct omap_volt_data *omap_voltage_get_nom_volt (struct voltagedomain *voltdm) {struct omap_vdd_info *vdd;if (IS_ERR_OR_NULL (voltdm)) {pr_warning ("%s: VDD specified does not exist!\n" , __func__); -return 0 ; +return ERR_PTR (-ENODATA ); } vdd = container_of(voltdm, struct omap_vdd_info, voltdm);@@ -819,18 +827,19 @@ void omap_vp_disable(struct voltagedomain *voltdm)* omap_voltage_scale_vdd() - API to scale voltage of a particular * voltage domain. * @voltdm: pointer to the VDD which is to be scaled. -* @target_volt: The target voltage of the voltage domain +* @target_volt: The target voltage data for the voltage domain * * This API should be called by the kernel to do the voltage scaling * for a particular voltage domain during dvfs or any other situation.
arch/arm/mach-omap2/voltage.c void omap_vp_disable(struct voltagedomain *voltdm) · line 840
Quoted 10 lines
arch/arm/mach-omap2/voltage.c +2
-3*/ int omap_voltage_scale_vdd (struct voltagedomain *voltdm, -unsigned long target_volt) +struct omap_volt_data *target_volt) {struct omap_vdd_info *vdd; -if (IS_ERR_OR_NULL (voltdm)) { -pr_warning ("%s: VDD specified does not exist!\n" , __func__); +if (IS_ERR_OR_NULL (voltdm) ||IS_ERR_OR_NULL (target_volt)) {
checking for NULL should suffice
Quoted 49 lines
arch/arm/mach-omap2/voltage.c +3
-1+pr_warning ("%s: Bad Params vdm=%p tv=%p!\n" , __func__, + voltdm, target_volt);return -EINVAL ; }@@ -856,7 +865,7 @@ int omap_voltage_scale_vdd(struct voltagedomain *voltdm,*/ void omap_voltage_reset (struct voltagedomain *voltdm) { -unsigned long target_uvdc; +struct omap_volt_data *target_uvdc;if (IS_ERR_OR_NULL (voltdm)) {pr_warning ("%s: VDD specified does not exist!\n" , __func__);arch/arm/mach-omap2/voltage.h +4
-4@@ -131,25 +131,25 @@ struct omap_vdd_info {const struct omap_vfsm_instance_data *vfsm;struct voltagedomain voltdm;struct dentry *debug_dir; -u32 curr_volt; +struct omap_volt_data *curr_volt;bool vp_enabled;u32 (*read_reg) (u16 mod,u8 offset);void (*write_reg) (u32 val,u16 mod,u8 offset);int (*volt_scale) (struct omap_vdd_info *vdd, -unsigned long target_volt); +struct omap_volt_data *target_volt); };unsigned long omap_vp_get_curr_volt (struct voltagedomain *voltdm);void omap_vp_enable (struct voltagedomain *voltdm);void omap_vp_disable (struct voltagedomain *voltdm);int omap_voltage_scale_vdd (struct voltagedomain *voltdm, -unsigned long target_volt); +struct omap_volt_data *target_volt);void omap_voltage_reset (struct voltagedomain *voltdm);void omap_voltage_get_volttable (struct voltagedomain *voltdm,struct omap_volt_data **volt_data);struct omap_volt_data *omap_voltage_get_voltdata (struct voltagedomain *voltdm,unsigned long volt); -unsigned long omap_voltage_get_nom_volt (struct voltagedomain *voltdm); +struct omap_volt_data *omap_voltage_get_nom_volt (struct voltagedomain *voltdm);struct dentry *omap_voltage_get_dbgdir (struct voltagedomain *voltdm); int __init omap_voltage_early_init(s16 prm_mod, s16 prm_irqst_mod, struct omap_vdd_info *omap_vdd_array[],
arch/arm/mach-omap2/voltage.h static inline struct voltagedomain *omap_voltage_domain_lookup(char *name) · line 188
Quoted 8 lines
arch/arm/mach-omap2/voltage.h +5
-0@@ -181,4 +181,13 @@ static inline struct voltagedomain *omap_voltage_domain_lookup(char *name) }#endif +/* convert volt data to the voltage for the voltage data */ +static inline unsigned long omap_get_operation_voltage ( +struct omap_volt_data *vdata) +{ +if (IS_ERR_OR_NULL (vdata))
checking for NULL chould suffice
arch/arm/mach-omap2/voltage.h static inline struct voltagedomain *omap_voltage_domain_lookup(char *name) · line 193
Quoted 5 lines
arch/arm/mach-omap2/voltage.h +4
-0+return 0 ; + return vdata->volt_nominal; +} +#endif
Also, this function name should follow the naming convention of the rest of the voltage layer.
Kevin
PATCH v3 7/19 OMAP3+: voltage: add transdone APIs
In reply to Nishanth MenonTransdone event in Voltage processor gives us fine grained status on the current status of the voltage communication with the PMIC. Unfortunately, IRQ generation by VP is based on the start of the transmission to VC from VP, not at the end (or the completion of the voltage setting). Hence any users of voltage layer who need to know fine grained information such as confirmation if the voltage is actually send to PMIC, needs to depend on this status.
--- arch/arm/mach-omap2/voltage.c | 57 +++++++++++++++++++++++++++++++++++------ arch/arm/mach-omap2/voltage.h | 2 + 2 files changed, 51 insertions(+), 8 deletions(-)
arch/arm/mach-omap2/voltage.c +49 -8
@@ -455,10 +455,8 @@ static int vp_forceupdate_scale_voltage(struct omap_vdd_info *vdd,* is <3us */ while (timeout++ <VP_TRANXDONE_TIMEOUT ) { - vdd->write_reg (vdd->vp_data->prm_irqst_data->tranxdone_status, - prm_irqst_ocp_mod_offs, prm_irqst_reg); -if (!(vdd->read_reg (prm_irqst_ocp_mod_offs, prm_irqst_reg) & - vdd->vp_data->prm_irqst_data->tranxdone_status)) +omap_vp_clear_transdone (&vdd->voltdm); +if (!omap_vp_is_transdone (&vdd->voltdm))break ;udelay (1 ); }
@@ -506,10 +504,8 @@ static int vp_forceupdate_scale_voltage(struct omap_vdd_info *vdd,*/ timeout =0 ;while (timeout++ <VP_TRANXDONE_TIMEOUT ) { - vdd->write_reg (vdd->vp_data->prm_irqst_data->tranxdone_status, - prm_irqst_ocp_mod_offs, prm_irqst_reg); -if (!(vdd->read_reg (prm_irqst_ocp_mod_offs, prm_irqst_reg) & - vdd->vp_data->prm_irqst_data->tranxdone_status)) +omap_vp_clear_transdone (&vdd->voltdm); +if (!omap_vp_is_transdone (&vdd->voltdm))break ;udelay (1 ); }
@@ -824,6 +820,51 @@ void omap_vp_disable(struct voltagedomain *voltdm) }/** +* omap_vp_is_transdone() - is voltage transfer done on vp? +* @voltdm: pointer to the VDD which is to be scaled. +* +* VP's transdone bit is the only way to ensure that the transfer +* of the voltage value has actually been send over to the PMIC +* This is hence useful for all users of voltage domain to precisely +* identify once the PMIC voltage has been set by the voltage processor +*/ +bool omap_vp_is_transdone (struct voltagedomain *voltdm) +{ +struct omap_vdd_info *vdd; + +if (IS_ERR_OR_NULL (voltdm)) { +pr_warning ("%s: Bad Params vdm=%p\n" , __func__, voltdm); +return false; + } + + vdd = container_of(voltdm, struct omap_vdd_info, voltdm); +return (vdd->read_reg (prm_irqst_ocp_mod_offs, + vdd->vp_data->prm_irqst_data->prm_irqst_reg) & + vdd->vp_data->prm_irqst_data->tranxdone_status) ? true : false; +} + +/** +* omap_vp_clear_transdone() - clear voltage transfer done status on vp +* @voltdm: pointer to the VDD which is to be scaled. +*/ +bool omap_vp_clear_transdone (struct voltagedomain *voltdm) +{ +struct omap_vdd_info *vdd; + +if (IS_ERR_OR_NULL (voltdm)) { +pr_warning ("%s: Bad Params vdm=%p\n" , __func__, voltdm); +return false; + } + + vdd = container_of(voltdm, struct omap_vdd_info, voltdm); + vdd->write_reg (vdd->vp_data->prm_irqst_data->tranxdone_status, + prm_irqst_ocp_mod_offs, + vdd->vp_data->prm_irqst_data->prm_irqst_reg); + +return true; +} + +/** * omap_voltage_scale_vdd() - API to scale voltage of a particular * voltage domain. * @voltdm: pointer to the VDD which is to be scaled.
arch/arm/mach-omap2/voltage.h +2 -0
@@ -150,6 +150,8 @@ void omap_voltage_get_volttable(struct voltagedomain *voltdm,struct omap_volt_data *omap_voltage_get_voltdata (struct voltagedomain *voltdm,unsigned long volt);struct omap_volt_data *omap_voltage_get_nom_volt (struct voltagedomain *voltdm); +bool omap_vp_is_transdone (struct voltagedomain *voltdm); +bool omap_vp_clear_transdone (struct voltagedomain *voltdm);struct dentry *omap_voltage_get_dbgdir (struct voltagedomain *voltdm); int __init omap_voltage_early_init(s16 prm_mod, s16 prm_irqst_mod, struct omap_vdd_info *omap_vdd_array[],
Signature · 1 line
1.7.1
PATCH v3 7/19 OMAP3+: voltage: add transdone APIs
Quoted 1 line · Nishanth Menon
Transdone event in Voltage processor gives us fine grained status on
s/Transdone/Transaction done/
Quoted 6 lines
the current status of the voltage communication with the PMIC. Unfortunately, IRQ generation by VP is based on the start of the transmission to VC from VP, not at the end (or the completion of the voltage setting). Hence any users of voltage layer who need to know fine grained information such as confirmation if the voltage is actually send to PMIC, needs to depend on this status.
This changelog explains why we need to check the transaction done bit, but the patch doesn't add this feature, it just creates a new API for an existing feature.
To minimize confusion, the changelog should be more clear that it is just generalizing an existing feature by creating an API for it. It currently makes it sound like it is changing current behavior.
Quoted 43 lines
Signed-off-by Nishanth Menon <[email protected]>--- arch/arm/mach-omap2/voltage.c | 57 +++++++++++++++++++++++++++++++++++------ arch/arm/mach-omap2/voltage.h | 2 + 2 files changed, 51 insertions(+), 8 deletions(-)arch/arm/mach-omap2/voltage.c +7
-8@@ -455,10 +455,8 @@ static int vp_forceupdate_scale_voltage(struct omap_vdd_info *vdd,* is <3us */ while (timeout++ <VP_TRANXDONE_TIMEOUT ) { - vdd->write_reg (vdd->vp_data->prm_irqst_data->tranxdone_status, - prm_irqst_ocp_mod_offs, prm_irqst_reg); -if (!(vdd->read_reg (prm_irqst_ocp_mod_offs, prm_irqst_reg) & - vdd->vp_data->prm_irqst_data->tranxdone_status)) +omap_vp_clear_transdone (&vdd->voltdm); +if (!omap_vp_is_transdone (&vdd->voltdm))break ;udelay (1 ); }@@ -506,10 +504,8 @@ static int vp_forceupdate_scale_voltage(struct omap_vdd_info *vdd,*/ timeout =0 ;while (timeout++ <VP_TRANXDONE_TIMEOUT ) { - vdd->write_reg (vdd->vp_data->prm_irqst_data->tranxdone_status, - prm_irqst_ocp_mod_offs, prm_irqst_reg); -if (!(vdd->read_reg (prm_irqst_ocp_mod_offs, prm_irqst_reg) & - vdd->vp_data->prm_irqst_data->tranxdone_status)) +omap_vp_clear_transdone (&vdd->voltdm); +if (!omap_vp_is_transdone (&vdd->voltdm))break ;udelay (1 ); }@@ -824,6 +820,51 @@ void omap_vp_disable(struct voltagedomain *voltdm) }/** +* omap_vp_is_transdone() - is voltage transfer done on vp? +* @voltdm: pointer to the VDD which is to be scaled. +*
arch/arm/mach-omap2/voltage.c void omap_vp_disable(struct voltagedomain *voltdm) · line 835
Quoted 10 lines
arch/arm/mach-omap2/voltage.c +10
-0+* VP's transdone bit is the only way to ensure that the transfer +* of the voltage value has actually been send over to the PMIC +* This is hence useful for all users of voltage domain to precisely +* identify once the PMIC voltage has been set by the voltage processor +*/ +bool omap_vp_is_transdone (struct voltagedomain *voltdm) +{ +struct omap_vdd_info *vdd; + +if (IS_ERR_OR_NULL (voltdm)) {
As with some of the other patches, checking for error on input
parameters doesn't make much sense. Checking for NULL should suffice.
Quoted 9 lines
arch/arm/mach-omap2/voltage.c +9
-0+pr_warning ("%s: Bad Params vdm=%p\n" , __func__, voltdm); +return false; + } + + vdd = container_of(voltdm, struct omap_vdd_info, voltdm); +return (vdd->read_reg (prm_irqst_ocp_mod_offs, + vdd->vp_data->prm_irqst_data->prm_irqst_reg) & + vdd->vp_data->prm_irqst_data->tranxdone_status) ? true : false; +}
arch/arm/mach-omap2/voltage.c void omap_vp_disable(struct voltagedomain *voltdm) · line 854
Quoted 10 lines
arch/arm/mach-omap2/voltage.c +10
-0+ +/** +* omap_vp_clear_transdone() - clear voltage transfer done status on vp +* @voltdm: pointer to the VDD which is to be scaled. +*/ +bool omap_vp_clear_transdone (struct voltagedomain *voltdm) +{ +struct omap_vdd_info *vdd; + +if (IS_ERR_OR_NULL (voltdm)) {
ditto
Quoted 21 lines
arch/arm/mach-omap2/voltage.c +13
-0+pr_warning ("%s: Bad Params vdm=%p\n" , __func__, voltdm); +return false; + } + + vdd = container_of(voltdm, struct omap_vdd_info, voltdm); + vdd->write_reg (vdd->vp_data->prm_irqst_data->tranxdone_status, + prm_irqst_ocp_mod_offs, + vdd->vp_data->prm_irqst_data->prm_irqst_reg); + +return true; +} + +/** * omap_voltage_scale_vdd() - API to scale voltage of a particular * voltage domain. * @voltdm: pointer to the VDD which is to be scaled. arch/arm/mach-omap2/voltage.h +0
-0
arch/arm/mach-omap2/voltage.h void omap_voltage_get_volttable(struct voltagedomain *voltdm, · line 157
Quoted 8 lines
arch/arm/mach-omap2/voltage.h +2
-0@@ -150,6 +150,8 @@ void omap_voltage_get_volttable(struct voltagedomain *voltdm,struct omap_volt_data *omap_voltage_get_voltdata (struct voltagedomain *voltdm,unsigned long volt);struct omap_volt_data *omap_voltage_get_nom_volt (struct voltagedomain *voltdm); +bool omap_vp_is_transdone (struct voltagedomain *voltdm); +bool omap_vp_clear_transdone (struct voltagedomain *voltdm);struct dentry *omap_voltage_get_dbgdir (struct voltagedomain *voltdm); int __init omap_voltage_early_init(s16 prm_mod, s16 prm_irqst_mod, struct omap_vdd_info *omap_vdd_array[],
Kevin
PATCH v3 8/19 OMAP3+: SR: make notify independent of class
In reply to Nishanth MenonInterrupt notification mechanism of SmartReflex can be used by the choice of implementation of the class driver. For example, Class 2 and Class 1.5 of SmartReflex can both use the interrupt notification to identify the transition of voltage or other events.
Hence, the actual class does not matter for notifier. Let the class driver's handling decide how it should be used. SmartReflex driver should provide just the primitives.
--- arch/arm/mach-omap2/smartreflex.c | 6 ++---- 1 files changed, 2 insertions(+), 4 deletions(-)
arch/arm/mach-omap2/smartreflex.c +2 -4
@@ -142,7 +142,7 @@ static irqreturn_t sr_interrupt(int irq, void *data)sr_write_reg (sr_info,IRQSTATUS , status); } -if (sr_class->class_type ==SR_CLASS2 && sr_class->notify) +if (sr_class->notify) sr_class->notify (sr_info->voltdm, status);return IRQ_HANDLED ;
@@ -257,9 +257,7 @@ static int sr_late_init(struct omap_sr *sr_info)struct resource *mem;int ret =0 ; -if (sr_class->class_type ==SR_CLASS2 && - sr_class->notify_flags && sr_info->irq) { - +if (sr_class->notify && sr_class->notify_flags && sr_info->irq) { name =kasprintf (GFP_KERNEL ,"sr_%s" , sr_info->voltdm->name);if (name ==NULL ) { ret = -ENOMEM ;
Signature · 1 line
1.7.1
PATCH v3 8/19 OMAP3+: SR: make notify independent of class
Quoted 10 lines · Nishanth Menon
Interrupt notification mechanism of SmartReflex can be used by the choice of implementation of the class driver. For example, Class 2 and Class 1.5 of SmartReflex can both use the interrupt notification to identify the transition of voltage or other events.
Hence, the actual class does not matter for notifier. Let the class driver's handling decide how it should be used. SmartReflex driver should provide just the primitives.
Signed-off-by Nishanth Menon <[email protected]>
Thanks, queuing for 2.6.40 (branch: for_2.6.40/pm-misc)
Kevin
Quoted 28 lines
--- arch/arm/mach-omap2/smartreflex.c | 6 ++---- 1 files changed, 2 insertions(+), 4 deletions(-)arch/arm/mach-omap2/smartreflex.c +2
-4@@ -142,7 +142,7 @@ static irqreturn_t sr_interrupt(int irq, void *data)sr_write_reg (sr_info,IRQSTATUS , status); } -if (sr_class->class_type ==SR_CLASS2 && sr_class->notify) +if (sr_class->notify) sr_class->notify (sr_info->voltdm, status);return IRQ_HANDLED ;@@ -257,9 +257,7 @@ static int sr_late_init(struct omap_sr *sr_info)struct resource *mem;int ret =0 ; -if (sr_class->class_type ==SR_CLASS2 && - sr_class->notify_flags && sr_info->irq) { - +if (sr_class->notify && sr_class->notify_flags && sr_info->irq) { name =kasprintf (GFP_KERNEL ,"sr_%s" , sr_info->voltdm->name);if (name ==NULL ) { ret = -ENOMEM ;
PATCH v3 9/19 OMAP3+: SR: disable interrupt by default
In reply to Nishanth MenonWe will enable and disable interrupt on a need basis in the class driver. We need to keep the IRQ disabled by default else the forceupdate or vcbypass events could trigger events that we don't need/expect to handle.
This is a preparation for SmartReflex AVS class drivers such as class 2 and class 1.5 which would need to use interrupts. Existing SmartReflex AVS class 3 driver does not require to use interrupts and is not impacted by this change.
--- arch/arm/mach-omap2/smartreflex.c | 1 + 1 files changed, 1 insertions(+), 0 deletions(-)
arch/arm/mach-omap2/smartreflex.c +1 -0
@@ -267,6 +267,7 @@ static int sr_late_init(struct omap_sr *sr_info) 0, name, (void *)sr_info);if (ret) goto error; +disable_irq (sr_info->irq); }if (pdata && pdata->enable_on_init)
Signature · 1 line
1.7.1
PATCH v3 9/19 OMAP3+: SR: disable interrupt by default
Quoted 11 lines · Nishanth Menon
We will enable and disable interrupt on a need basis in the class driver. We need to keep the IRQ disabled by default else the forceupdate or vcbypass events could trigger events that we don't need/expect to handle.
This is a preparation for SmartReflex AVS class drivers such as class 2 and class 1.5 which would need to use interrupts. Existing SmartReflex AVS class 3 driver does not require to use interrupts and is not impacted by this change.
Signed-off-by Nishanth Menon <[email protected]>
Thanks, queueing for 2.6.40
Kevin
Quoted 16 lines
--- arch/arm/mach-omap2/smartreflex.c | 1 + 1 files changed, 1 insertions(+), 0 deletions(-)arch/arm/mach-omap2/smartreflex.c +1
-0@@ -267,6 +267,7 @@ static int sr_late_init(struct omap_sr *sr_info) 0, name, (void *)sr_info);if (ret) goto error; +disable_irq (sr_info->irq); }if (pdata && pdata->enable_on_init)
PATCH v3 10/19 OMAP3+: SR: enable/disable SR only on need
In reply to Nishanth MenonSince we already know the state of the autocomp enablement, we can see if the requested state is different from the current state and enable/disable SR only on the need basis.
--- arch/arm/mach-omap2/smartreflex.c | 11 +++++++---- 1 files changed, 7 insertions(+), 4 deletions(-)
arch/arm/mach-omap2/smartreflex.c +7 -4
@@ -806,10 +806,13 @@ static int omap_sr_autocomp_store(void *data, u64 val)return -EINVAL ; } -if (!val) -sr_stop_vddautocomp (sr_info); -else -sr_start_vddautocomp (sr_info); +/* control enable/disable only if there is a delta in value */ +if (sr_info->autocomp_active != val) { +if (!val) +sr_stop_vddautocomp (sr_info); +else +sr_start_vddautocomp (sr_info); + }return 0 ; }
Signature · 1 line
1.7.1
PATCH v3 10/19 OMAP3+: SR: enable/disable SR only on need
Quoted 5 lines · Nishanth Menon
Since we already know the state of the autocomp enablement, we can see if the requested state is different from the current state and enable/disable SR only on the need basis.
Signed-off-by Nishanth Menon <[email protected]>
Thanks, queuing for 2.6.40.
Kevin
Quoted 26 lines
--- arch/arm/mach-omap2/smartreflex.c | 11 +++++++---- 1 files changed, 7 insertions(+), 4 deletions(-)arch/arm/mach-omap2/smartreflex.c +7
-4@@ -806,10 +806,13 @@ static int omap_sr_autocomp_store(void *data, u64 val)return -EINVAL ; } -if (!val) -sr_stop_vddautocomp (sr_info); -else -sr_start_vddautocomp (sr_info); +/* control enable/disable only if there is a delta in value */ +if (sr_info->autocomp_active != val) { +if (!val) +sr_stop_vddautocomp (sr_info); +else +sr_start_vddautocomp (sr_info); + }return 0 ; }
PATCH v3 11/19 OMAP3+: SR: fix cosmetic indentation
In reply to Nishanth MenonError label case seems to have a 2 tab indentation when just 1 is necessary.
--- arch/arm/mach-omap2/smartreflex.c | 20 ++++++++++---------- 1 files changed, 10 insertions(+), 10 deletions(-)
arch/arm/mach-omap2/smartreflex.c +10 -10
@@ -276,16 +276,16 @@ static int sr_late_init(struct omap_sr *sr_info)return ret; error: -iounmap (sr_info->base); - mem =platform_get_resource (sr_info->pdev,IORESOURCE_MEM ,0 ); -release_mem_region (mem->start,resource_size (mem)); -list_del (&sr_info->node); -dev_err (&sr_info->pdev->dev,"%s: ERROR in registering" -"interrupt handler. Smartreflex will" -"not function as desired\n" , __func__); -kfree (name); -kfree (sr_info); -return ret; +iounmap (sr_info->base); + mem =platform_get_resource (sr_info->pdev,IORESOURCE_MEM ,0 ); +release_mem_region (mem->start,resource_size (mem)); +list_del (&sr_info->node); +dev_err (&sr_info->pdev->dev,"%s: ERROR in registering" +"interrupt handler. Smartreflex will" +"not function as desired\n" , __func__); +kfree (name); +kfree (sr_info); +return ret; }static void sr_v1_disable (struct omap_sr *sr)
Signature · 1 line
1.7.1
PATCH v3 11/19 OMAP3+: SR: fix cosmetic indentation
Quoted 4 lines · Nishanth Menon
Error label case seems to have a 2 tab indentation when just 1 is necessary.
Signed-off-by Nishanth Menon <[email protected]>
Thanks, queuing for 2.6.40.
Kevin
Quoted 35 lines
--- arch/arm/mach-omap2/smartreflex.c | 20 ++++++++++---------- 1 files changed, 10 insertions(+), 10 deletions(-)arch/arm/mach-omap2/smartreflex.c +10
-10@@ -276,16 +276,16 @@ static int sr_late_init(struct omap_sr *sr_info)return ret; error: -iounmap (sr_info->base); - mem =platform_get_resource (sr_info->pdev,IORESOURCE_MEM ,0 ); -release_mem_region (mem->start,resource_size (mem)); -list_del (&sr_info->node); -dev_err (&sr_info->pdev->dev,"%s: ERROR in registering" -"interrupt handler. Smartreflex will" -"not function as desired\n" , __func__); -kfree (name); -kfree (sr_info); -return ret; +iounmap (sr_info->base); + mem =platform_get_resource (sr_info->pdev,IORESOURCE_MEM ,0 ); +release_mem_region (mem->start,resource_size (mem)); +list_del (&sr_info->node); +dev_err (&sr_info->pdev->dev,"%s: ERROR in registering" +"interrupt handler. Smartreflex will" +"not function as desired\n" , __func__); +kfree (name); +kfree (sr_info); +return ret; }static void sr_v1_disable (struct omap_sr *sr)
PATCH v3 11/19 OMAP3+: SR: fix cosmetic indentation
Hi,
Quoted 3 lines · Kevin Hilman
Thanks, queuing for 2.6.40.
[...]
Quoted 13 lines
Quoted 13 lines
arch/arm/mach-omap2/smartreflex.c +2
-10-iounmap (sr_info->base); - mem =platform_get_resource (sr_info->pdev,IORESOURCE_MEM ,0 ); -release_mem_region (mem->start,resource_size (mem)); -list_del (&sr_info->node); -dev_err (&sr_info->pdev->dev,"%s: ERROR in registering" -"interrupt handler. Smartreflex will" -"not function as desired\n" , __func__); -kfree (name); -kfree (sr_info); -return ret; +iounmap (sr_info->base); + mem =platform_get_resource (sr_info->pdev,IORESOURCE_MEM ,0 );
Quoted 8 lines
arch/arm/mach-omap2/smartreflex.c static int sr_late_init(struct omap_sr *sr_info) · line 288
Quoted 8 lines
arch/arm/mach-omap2/smartreflex.c +8
-0+release_mem_region (mem->start,resource_size (mem)); +list_del (&sr_info->node); +dev_err (&sr_info->pdev->dev,"%s: ERROR in registering" +"interrupt handler. Smartreflex will" +"not function as desired\n" , __func__); +kfree (name); +kfree (sr_info); +return ret;
Just FYI, this code is partly broken and probably need to be fixed in .39.
Some of those resources are also freed by omap_sr_probe() when sr_late_init() fails and that cannot be correct.
A.
PATCH v3 11/19 OMAP3+: SR: fix cosmetic indentation
Quoted 22 lines · Aaro Koskinen
Hi,
Quoted 3 lines · Kevin Hilman
Thanks, queuing for 2.6.40.
[...]
Quoted 15 lines
Quoted 15 lines
arch/arm/mach-omap2/smartreflex.c +4
-10-iounmap (sr_info->base); - mem =platform_get_resource (sr_info->pdev,IORESOURCE_MEM ,0 ); -release_mem_region (mem->start,resource_size (mem)); -list_del (&sr_info->node); -dev_err (&sr_info->pdev->dev,"%s: ERROR in registering" -"interrupt handler. Smartreflex will" -"not function as desired\n" , __func__); -kfree (name); -kfree (sr_info); -return ret; +iounmap (sr_info->base); + mem =platform_get_resource (sr_info->pdev,IORESOURCE_MEM ,0 ); +release_mem_region (mem->start,resource_size (mem)); +list_del (&sr_info->node);
Quoted 8 lines
Quoted 6 lines
arch/arm/mach-omap2/smartreflex.c static int sr_late_init(struct omap_sr *sr_info) · line 288
Quoted 6 lines
arch/arm/mach-omap2/smartreflex.c +6
-0+dev_err (&sr_info->pdev->dev,"%s: ERROR in registering" +"interrupt handler. Smartreflex will" +"not function as desired\n" , __func__); +kfree (name); +kfree (sr_info); +return ret;Just FYI, this code is partly broken and probably need to be fixed in .39.
OK
Quoted 2 lines
Some of those resources are also freed by
omap_sr_probe()whensr_late_init()fails and that cannot be correct.
Got a patch around to fix that? Sounds like something we should get into the .39-rc cycle.
Kevin
PATCH v3 12/19 OMAP3+: SR: introduce class start, stop and priv data
In reply to Nishanth MenonCertain class drivers such as class 1.5 drivers, will need specific notification that they have to be started up or stopped independent of smart reflex operation. They also may need private data to be used for operations of their own, provide the same.
This allows the class driver to initialize it's internal data structures on a need basis in preparation for the specific domain's autocomp usage. The resultant operation is as follows:
when autocomp is set to 1 -> class drivers' start is called The existing enable/disable is still used as before by the SmartReflex core driver to enable disable the class operation.
When autocomp is set to 0 -> class drivers' stop is called, signaling the end of usage for that domain.
--- arch/arm/mach-omap2/smartreflex.c | 14 ++++++++++++++ arch/arm/mach-omap2/smartreflex.h | 6 ++++++ 2 files changed, 20 insertions(+), 0 deletions(-)
arch/arm/mach-omap2/smartreflex.c +14 -0
@@ -220,6 +220,13 @@ static void sr_start_vddautocomp(struct omap_sr *sr)return ; } +if (sr_class->start && + sr_class->start (sr->voltdm, sr_class->class_priv_data)) { +dev_err (&sr->pdev->dev, +"%s: SRClass initialization failed\n" , __func__); +return ; + } +if (!sr_class->enable (sr->voltdm)) sr->autocomp_active = true; }
@@ -235,6 +242,13 @@ static void sr_stop_vddautocomp(struct omap_sr *sr)if (sr->autocomp_active) { sr_class->disable (sr->voltdm,1 ); +if (sr_class->stop && + sr_class->stop (sr->voltdm, + sr_class->class_priv_data)) { +dev_err (&sr->pdev->dev, +"%s: SR[%d]Class deinitialization failed\n" , + __func__, sr->srid); + } sr->autocomp_active = false; } }
arch/arm/mach-omap2/smartreflex.h +6 -0
@@ -168,6 +168,8 @@ struct omap_sr_pmic_data {* * @enable: API to enable a particular class smaartreflex. * @disable: API to disable a particular class smartreflex. +* @start: API to do class specific initialization (optional) +* @stop: API to do class specific deinitialization (optional) * @configure: API to configure a particular class smartreflex. * @notify: API to notify the class driver about an event in SR. * Not needed for class3.
@@ -175,14 +177,18 @@ struct omap_sr_pmic_data {* @class_type: specify which smartreflex class. * Can be used by the SR driver to take any class * based decisions. +* @class_priv_data: Class specific private data (optional) */ struct omap_sr_class_data {int (*enable)(struct voltagedomain *voltdm);int (*disable)(struct voltagedomain *voltdm,int is_volt_reset); +int (*start)(struct voltagedomain *voltdm,void *class_priv_data); +int (*stop)(struct voltagedomain *voltdm,void *class_priv_data);int (*configure)(struct voltagedomain *voltdm);int (*notify)(struct voltagedomain *voltdm,u32 status);u8 notify_flags;u8 class_type; +void *class_priv_data; };/**
Signature · 1 line
1.7.1
PATCH v3 12/19 OMAP3+: SR: introduce class start, stop and priv data
Quoted 13 lines · Nishanth Menon
Certain class drivers such as class 1.5 drivers, will need specific notification that they have to be started up or stopped independent of smart reflex operation. They also may need private data to be used for operations of their own, provide the same.
This allows the class driver to initialize it's internal data structures on a need basis in preparation for the specific domain's autocomp usage. The resultant operation is as follows:
when autocomp is set to 1 -> class drivers' start is called The existing enable/disable is still used as before by the SmartReflex core driver to enable disable the class operation.
When autocomp is set to 0 -> class drivers' stop is called, signaling the end of usage for that domain.
Quoted 1 line
Signed-off-by Nishanth Menon <[email protected]>
Please also fixup the comments and printks to use the start/stop terminology instead of the init/deinit terminology.
Thanks,
Kevin
Quoted 69 lines
--- arch/arm/mach-omap2/smartreflex.c | 14 ++++++++++++++ arch/arm/mach-omap2/smartreflex.h | 6 ++++++ 2 files changed, 20 insertions(+), 0 deletions(-)arch/arm/mach-omap2/smartreflex.c +14
-0@@ -220,6 +220,13 @@ static void sr_start_vddautocomp(struct omap_sr *sr)return ; } +if (sr_class->start && + sr_class->start (sr->voltdm, sr_class->class_priv_data)) { +dev_err (&sr->pdev->dev, +"%s: SRClass initialization failed\n" , __func__); +return ; + } +if (!sr_class->enable (sr->voltdm)) sr->autocomp_active = true; }@@ -235,6 +242,13 @@ static void sr_stop_vddautocomp(struct omap_sr *sr)if (sr->autocomp_active) { sr_class->disable (sr->voltdm,1 ); +if (sr_class->stop && + sr_class->stop (sr->voltdm, + sr_class->class_priv_data)) { +dev_err (&sr->pdev->dev, +"%s: SR[%d]Class deinitialization failed\n" , + __func__, sr->srid); + } sr->autocomp_active = false; } }arch/arm/mach-omap2/smartreflex.h +6
-0@@ -168,6 +168,8 @@ struct omap_sr_pmic_data {* * @enable: API to enable a particular class smaartreflex. * @disable: API to disable a particular class smartreflex. +* @start: API to do class specific initialization (optional) +* @stop: API to do class specific deinitialization (optional) * @configure: API to configure a particular class smartreflex. * @notify: API to notify the class driver about an event in SR. * Not needed for class3. @@ -175,14 +177,18 @@ struct omap_sr_pmic_data {* @class_type: specify which smartreflex class. * Can be used by the SR driver to take any class * based decisions. +* @class_priv_data: Class specific private data (optional) */ struct omap_sr_class_data {int (*enable)(struct voltagedomain *voltdm);int (*disable)(struct voltagedomain *voltdm,int is_volt_reset); +int (*start)(struct voltagedomain *voltdm,void *class_priv_data); +int (*stop)(struct voltagedomain *voltdm,void *class_priv_data);int (*configure)(struct voltagedomain *voltdm);int (*notify)(struct voltagedomain *voltdm,u32 status);u8 notify_flags;u8 class_type; +void *class_priv_data; };/**
PATCH v3 13/19 OMAP3+: SR: Reuse sr_[start|stop]_vddautocomp functions
In reply to Nishanth MenonFrom: Jarkko Nikula <[email protected]>
sr_start_vddautocomp and sr_stop_autocomp functions can be reused from omap_sr_enable, omap_sr_disable and omap_sr_disable_reset_volt and by adding one additional argument sr_stop_autocomp. This allows us to have a single point where SR enable and disable operations are controlled from.
[nm at ti.com: synced it up with class start/stop as well. autocomp flag
should only be disabled when SR is disabled for that domain]
---
Side note: Jarkko has'nt seen this rev as I just finished the rebase and tested but adding his signed-off anyways as he is primary contributor to the idea and the patch.
arch/arm/mach-omap2/smartreflex.c | 66 +++++++++++++------------------------ 1 files changed, 23 insertions(+), 43 deletions(-)
arch/arm/mach-omap2/smartreflex.c +23 -43
@@ -211,8 +211,12 @@ static void sr_set_regfields(struct omap_sr *sr) } } -static void sr_start_vddautocomp (struct omap_sr *sr) +static void sr_start_vddautocomp (struct omap_sr *sr,bool class_start) { +int r; +if (sr->autocomp_active) +return ; +if (!sr_class || !(sr_class->enable) || !(sr_class->configure)) { dev_warn(&sr->pdev->dev, "%s: smartreflex class driver not registered\n",
@@ -220,19 +224,24 @@ static void sr_start_vddautocomp(struct omap_sr *sr)return ; } -if (sr_class->start && +if (class_start && sr_class->start && sr_class->start (sr->voltdm, sr_class->class_priv_data)) {dev_err (&sr->pdev->dev,"%s: SRClass initialization failed\n" , __func__);return ; } -if (!sr_class->enable (sr->voltdm)) + r = sr_class->enable (sr->voltdm); +if (!r && class_start) sr->autocomp_active = true; } -static void sr_stop_vddautocomp (struct omap_sr *sr) +static void sr_stop_vddautocomp (struct omap_sr *sr,bool class_stop, +int is_volt_reset) { +if (!sr->autocomp_active) +return ; +if (!sr_class || !(sr_class->disable)) { dev_warn(&sr->pdev->dev, "%s: smartreflex class driver not registered\n",
@@ -240,15 +249,13 @@ static void sr_stop_vddautocomp(struct omap_sr *sr)return ; } -if (sr->autocomp_active) { - sr_class->disable (sr->voltdm,1 ); + sr_class->disable (sr->voltdm, is_volt_reset); +if (class_stop) {if (sr_class->stop && - sr_class->stop (sr->voltdm, - sr_class->class_priv_data)) { + sr_class->stop (sr->voltdm, sr_class->class_priv_data))dev_err (&sr->pdev->dev,"%s: SR[%d]Class deinitialization failed\n" , __func__, sr->srid); - } sr->autocomp_active = false; } }
@@ -285,7 +292,7 @@ static int sr_late_init(struct omap_sr *sr_info) }if (pdata && pdata->enable_on_init) -sr_start_vddautocomp (sr_info); +sr_start_vddautocomp (sr_info, true);return ret;
@@ -693,16 +700,7 @@ void omap_sr_enable(struct voltagedomain *voltdm)return ; } -if (!sr->autocomp_active) -return ; - -if (!sr_class || !(sr_class->enable) || !(sr_class->configure)) { -dev_warn (&sr->pdev->dev,"%s: smartreflex class driver not" -"registered\n" , __func__); -return ; - } - - sr_class->enable (voltdm); +sr_start_vddautocomp (sr, false); }/**
@@ -726,16 +724,7 @@ void omap_sr_disable(struct voltagedomain *voltdm)return ; } -if (!sr->autocomp_active) -return ; - -if (!sr_class || !(sr_class->disable)) { -dev_warn (&sr->pdev->dev,"%s: smartreflex class driver not" -"registered\n" , __func__); -return ; - } - - sr_class->disable (voltdm,0 ); +sr_stop_vddautocomp (sr, false,0 ); }/**
@@ -759,16 +748,7 @@ void omap_sr_disable_reset_volt(struct voltagedomain *voltdm)return ; } -if (!sr->autocomp_active) -return ; - -if (!sr_class || !(sr_class->disable)) { -dev_warn (&sr->pdev->dev,"%s: smartreflex class driver not" -"registered\n" , __func__); -return ; - } - - sr_class->disable (voltdm,1 ); +sr_stop_vddautocomp (sr, false,1 ); }/**
@@ -823,9 +803,9 @@ static int omap_sr_autocomp_store(void *data, u64 val)/* control enable/disable only if there is a delta in value */ if (sr_info->autocomp_active != val) {if (!val) -sr_stop_vddautocomp (sr_info); +sr_stop_vddautocomp (sr_info, true,1 );else -sr_start_vddautocomp (sr_info); +sr_start_vddautocomp (sr_info, true); }return 0 ;
@@ -987,7 +967,7 @@ static int __devexit omap_sr_remove(struct platform_device *pdev) }if (sr_info->autocomp_active) -sr_stop_vddautocomp (sr_info); +sr_stop_vddautocomp (sr_info, true,1 );list_del (&sr_info->node);iounmap (sr_info->base);
Signature · 1 line
1.7.1
PATCH v3 13/19 OMAP3+: SR: Reuse sr_[start|stop]_vddautocomp functions
Quoted 7 lines · On Sat, 5 Mar 2011 20:59:16 +0530 Nishanth Menon <[email protected]> wrote:
From: Jarkko Nikula <[email protected]>
sr_start_vddautocompandsr_stop_autocompfunctions can be reused fromomap_sr_enable,omap_sr_disableandomap_sr_disable_reset_voltand by adding one additional argumentsr_stop_autocomp. This allows us to have a single point where SR enable and disable operations are controlled from.
Quoted 9 lines
[nm at ti.com: synced it up with class start/stop as well. autocomp flag
should only be disabled when SR is disabled for that domain]Signed-off-by Nishanth Menon <[email protected]>Signed-off-by Jarkko Nikula <[email protected]>---
Side note: Jarkko has'nt seen this rev as I just finished the rebase and tested but adding his signed-off anyways as he is primary contributor to the idea and the patch.
This version looks good to me. We agreed with Nishant that squashing my trivial patches with Nishant's set makes the most sense.
Signature · 1 line
Jarkko
PATCH v3 13/19 OMAP3+: SR: Reuse sr_[start|stop]_vddautocomp functions
In reply to Nishanth MenonQuoted 7 lines · Nishanth Menon
From: Jarkko Nikula <[email protected]>
sr_start_vddautocompandsr_stop_autocompfunctions can be reused fromomap_sr_enable,omap_sr_disableandomap_sr_disable_reset_voltand by adding one additional argumentsr_stop_autocomp. This allows us to have a single point where SR enable and disable operations are controlled from.
Quoted 8 lines
[nm at ti.com: synced it up with class start/stop as well. autocomp flag
should only be disabled when SR is disabled for that domain]Signed-off-by Nishanth Menon <[email protected]>Signed-off-by Jarkko Nikula <[email protected]>---
Side note: Jarkko has'nt seen this rev as I just finished the rebase and tested but adding his signed-off anyways as he is primary contributor to the idea and the patch.
This one looks fine, but will wait to apply it since it depends on the previous one which needs some minor fixups.
Kevin
Quoted 152 lines
arch/arm/mach-omap2/smartreflex.c | 66 +++++++++++++------------------------ 1 files changed, 23 insertions(+), 43 deletions(-)arch/arm/mach-omap2/smartreflex.c +23
-43@@ -211,8 +211,12 @@ static void sr_set_regfields(struct omap_sr *sr) } } -static void sr_start_vddautocomp (struct omap_sr *sr) +static void sr_start_vddautocomp (struct omap_sr *sr,bool class_start) { +int r; +if (sr->autocomp_active) +return ; +if (!sr_class || !(sr_class->enable) || !(sr_class->configure)) { dev_warn(&sr->pdev->dev, "%s: smartreflex class driver not registered\n",@@ -220,19 +224,24 @@ static void sr_start_vddautocomp(struct omap_sr *sr)return ; } -if (sr_class->start && +if (class_start && sr_class->start && sr_class->start (sr->voltdm, sr_class->class_priv_data)) {dev_err (&sr->pdev->dev,"%s: SRClass initialization failed\n" , __func__);return ; } -if (!sr_class->enable (sr->voltdm)) + r = sr_class->enable (sr->voltdm); +if (!r && class_start) sr->autocomp_active = true; } -static void sr_stop_vddautocomp (struct omap_sr *sr) +static void sr_stop_vddautocomp (struct omap_sr *sr,bool class_stop, +int is_volt_reset) { +if (!sr->autocomp_active) +return ; +if (!sr_class || !(sr_class->disable)) { dev_warn(&sr->pdev->dev, "%s: smartreflex class driver not registered\n",@@ -240,15 +249,13 @@ static void sr_stop_vddautocomp(struct omap_sr *sr)return ; } -if (sr->autocomp_active) { - sr_class->disable (sr->voltdm,1 ); + sr_class->disable (sr->voltdm, is_volt_reset); +if (class_stop) {if (sr_class->stop && - sr_class->stop (sr->voltdm, - sr_class->class_priv_data)) { + sr_class->stop (sr->voltdm, sr_class->class_priv_data))dev_err (&sr->pdev->dev,"%s: SR[%d]Class deinitialization failed\n" , __func__, sr->srid); - } sr->autocomp_active = false; } }@@ -285,7 +292,7 @@ static int sr_late_init(struct omap_sr *sr_info) }if (pdata && pdata->enable_on_init) -sr_start_vddautocomp (sr_info); +sr_start_vddautocomp (sr_info, true);return ret;@@ -693,16 +700,7 @@ void omap_sr_enable(struct voltagedomain *voltdm)return ; } -if (!sr->autocomp_active) -return ; - -if (!sr_class || !(sr_class->enable) || !(sr_class->configure)) { -dev_warn (&sr->pdev->dev,"%s: smartreflex class driver not" -"registered\n" , __func__); -return ; - } - - sr_class->enable (voltdm); +sr_start_vddautocomp (sr, false); }/** @@ -726,16 +724,7 @@ void omap_sr_disable(struct voltagedomain *voltdm)return ; } -if (!sr->autocomp_active) -return ; - -if (!sr_class || !(sr_class->disable)) { -dev_warn (&sr->pdev->dev,"%s: smartreflex class driver not" -"registered\n" , __func__); -return ; - } - - sr_class->disable (voltdm,0 ); +sr_stop_vddautocomp (sr, false,0 ); }/** @@ -759,16 +748,7 @@ void omap_sr_disable_reset_volt(struct voltagedomain *voltdm)return ; } -if (!sr->autocomp_active) -return ; - -if (!sr_class || !(sr_class->disable)) { -dev_warn (&sr->pdev->dev,"%s: smartreflex class driver not" -"registered\n" , __func__); -return ; - } - - sr_class->disable (voltdm,1 ); +sr_stop_vddautocomp (sr, false,1 ); }/** @@ -823,9 +803,9 @@ static int omap_sr_autocomp_store(void *data, u64 val)/* control enable/disable only if there is a delta in value */ if (sr_info->autocomp_active != val) {if (!val) -sr_stop_vddautocomp (sr_info); +sr_stop_vddautocomp (sr_info, true,1 );else -sr_start_vddautocomp (sr_info); +sr_start_vddautocomp (sr_info, true); }return 0 ;@@ -987,7 +967,7 @@ static int __devexit omap_sr_remove(struct platform_device *pdev) }if (sr_info->autocomp_active) -sr_stop_vddautocomp (sr_info); +sr_stop_vddautocomp (sr_info, true,1 );list_del (&sr_info->node);iounmap (sr_info->base);
PATCH v3 14/19 OMAP3+: SR: introduce notifiers flags
In reply to Nishanth MenonSmartReflex IP V1 and V2 have different registers and offsets. Currently, we pass the status as is to the class driver. However, since we don't pass the version of the underlying SR hardware to the Class driver, it will not be unable to make consistent sense of the status bits coming over to it.
A class driver should be able to function without dependency on the exact IP version it is actually running on. We hence introduce our own translation in software level for a generic notification flag.
As part of this change, we will now call the notifier iff we get a match with the notifier flags that the class driver requested.
--- arch/arm/mach-omap2/smartreflex.c | 73 +++++++++++++++++++++++++++++++++++-- arch/arm/mach-omap2/smartreflex.h | 6 +++ 2 files changed, 76 insertions(+), 3 deletions(-)
arch/arm/mach-omap2/smartreflex.c +70 -3
@@ -123,27 +123,94 @@ static struct omap_sr *_sr_lookup(struct voltagedomain *voltdm)return ERR_PTR (-ENODATA ); } +static inline u32 notifier_to_irqen_v1 (u8 notify_flags) +{ +u32 val; + val = (notify_flags &SR_NOTIFY_MCUACCUM ) ? +ERRCONFIG_MCUACCUMINTEN :0 ; + val |= (notify_flags &SR_NOTIFY_MCUVALID ) ? +ERRCONFIG_MCUVALIDINTEN :0 ; + val |= (notify_flags &SR_NOTIFY_MCUBOUND ) ? +ERRCONFIG_MCUBOUNDINTEN :0 ; + val |= (notify_flags &SR_NOTIFY_MCUDISACK ) ? +ERRCONFIG_MCUDISACKINTEN :0 ; +return val; +} + +static inline u32 notifier_to_irqen_v2 (u8 notify_flags) +{ +u32 val; + val = (notify_flags &SR_NOTIFY_MCUACCUM ) ? +IRQENABLE_MCUACCUMINT :0 ; + val |= (notify_flags &SR_NOTIFY_MCUVALID ) ? +IRQENABLE_MCUVALIDINT :0 ; + val |= (notify_flags &SR_NOTIFY_MCUBOUND ) ? +IRQENABLE_MCUBOUNDSINT :0 ; + val |= (notify_flags &SR_NOTIFY_MCUDISACK ) ? +IRQENABLE_MCUDISABLEACKINT :0 ; +return val; +} + +static inline u8 irqstat_to_notifier_v1 (u32 status) +{ +u8 val; + val = (status &ERRCONFIG_MCUACCUMINTST ) ? +SR_NOTIFY_MCUACCUM :0 ; + val |= (status &ERRCONFIG_MCUVALIDINTEN ) ? +SR_NOTIFY_MCUVALID :0 ; + val |= (status &ERRCONFIG_MCUBOUNDINTEN ) ? +SR_NOTIFY_MCUBOUND :0 ; + val |= (status &ERRCONFIG_MCUDISACKINTEN ) ? +SR_NOTIFY_MCUDISACK :0 ; +return val; +} + +static inline u8 irqstat_to_notifier_v2 (u32 status) +{ +u8 val; + val = (status &IRQENABLE_MCUACCUMINT ) ? +SR_NOTIFY_MCUACCUM :0 ; + val |= (status &IRQENABLE_MCUVALIDINT ) ? +SR_NOTIFY_MCUVALID :0 ; + val |= (status &IRQENABLE_MCUBOUNDSINT ) ? +SR_NOTIFY_MCUBOUND :0 ; + val |= (status &IRQENABLE_MCUDISABLEACKINT ) ? +SR_NOTIFY_MCUDISACK :0 ; +return val; +} + +static irqreturn_t sr_interrupt (int irq,void *data) {struct omap_sr *sr_info = (struct omap_sr *)data;u32 status =0 ; +u32 value =0 ;if (sr_info->ip_type ==SR_TYPE_V1 ) { +/* Status bits are one bit before enable bits in v1 */ + value =notifier_to_irqen_v1 (sr_class->notify_flags) >>1 ; +/* Read the status bits */ status =sr_read_reg (sr_info,ERRCONFIG_V1 ); + status &= value;/* Clear them by writing back */ -sr_write_reg (sr_info,ERRCONFIG_V1 , status); +sr_modify_reg (sr_info,ERRCONFIG_V1 , value, status); + + value =irqstat_to_notifier_v1 (status); }else if (sr_info->ip_type ==SR_TYPE_V2 ) { + value =notifier_to_irqen_v2 (sr_class->notify_flags);/* Read the status bits */ -sr_read_reg (sr_info,IRQSTATUS ); + status =sr_read_reg (sr_info,IRQSTATUS ); + status &= value;/* Clear them by writing back */ sr_write_reg (sr_info,IRQSTATUS , status); + value =irqstat_to_notifier_v2 (status); }if (sr_class->notify) - sr_class->notify (sr_info->voltdm, status); + sr_class->notify (sr_info->voltdm, value);return IRQ_HANDLED ; }
arch/arm/mach-omap2/smartreflex.h +6 -0
@@ -142,6 +142,12 @@#define OMAP3430_SR_ERRWEIGHT 0x04#define OMAP3430_SR_ERRMAXLIMIT 0x02 +/* Smart reflex notifiers for class drivers to use */ +#define SR_NOTIFY_MCUDISACK BIT(3) +#define SR_NOTIFY_MCUBOUND BIT(2) +#define SR_NOTIFY_MCUVALID BIT(1) +#define SR_NOTIFY_MCUACCUM BIT(0) +/** * struct omap_sr_pmic_data - Strucutre to be populated by pmic code to pass * pmic specific info to smartreflex driver
Signature · 1 line
1.7.1
PATCH v3 14/19 OMAP3+: SR: introduce notifiers flags
Quoted 11 lines · Nishanth Menon
SmartReflex IP V1 and V2 have different registers and offsets. Currently, we pass the status as is to the class driver. However, since we don't pass the version of the underlying SR hardware to the Class driver, it will not be unable to make consistent sense of the status bits coming over to it.
A class driver should be able to function without dependency on the exact IP version it is actually running on. We hence introduce our own translation in software level for a generic notification flag.
Quoted 4 lines
As part of this change, we will now call the notifier iff we get a match with the notifier flags that the class driver requested.
Signed-off-by Nishanth Menon <[email protected]>
Patch is mostly fine, minor coding style comments below.
Kevin
Quoted 10 lines
--- arch/arm/mach-omap2/smartreflex.c | 73 +++++++++++++++++++++++++++++++++++-- arch/arm/mach-omap2/smartreflex.h | 6 +++ 2 files changed, 76 insertions(+), 3 deletions(-)arch/arm/mach-omap2/smartreflex.c +0
-0
arch/arm/mach-omap2/smartreflex.c static struct omap_sr *_sr_lookup(struct voltagedomain *voltdm) · line 128
Quoted 6 lines
arch/arm/mach-omap2/smartreflex.c +3
-0@@ -123,27 +123,94 @@ static struct omap_sr *_sr_lookup(struct voltagedomain *voltdm)return ERR_PTR (-ENODATA ); } +static inline u32 notifier_to_irqen_v1 (u8 notify_flags) +{ +u32 val;
insert blank line
arch/arm/mach-omap2/smartreflex.c static struct omap_sr *_sr_lookup(struct voltagedomain *voltdm) · line 136
Quoted 8 lines
arch/arm/mach-omap2/smartreflex.c +8
-0+ val = (notify_flags &SR_NOTIFY_MCUACCUM ) ? +ERRCONFIG_MCUACCUMINTEN :0 ; + val |= (notify_flags &SR_NOTIFY_MCUVALID ) ? +ERRCONFIG_MCUVALIDINTEN :0 ; + val |= (notify_flags &SR_NOTIFY_MCUBOUND ) ? +ERRCONFIG_MCUBOUNDINTEN :0 ; + val |= (notify_flags &SR_NOTIFY_MCUDISACK ) ? +ERRCONFIG_MCUDISACKINTEN :0 ;
insert blank line
same for all tehe functions below
Quoted 100 lines
arch/arm/mach-omap2/smartreflex.c +59
-3+return val; +} + +static inline u32 notifier_to_irqen_v2 (u8 notify_flags) +{ +u32 val; + val = (notify_flags &SR_NOTIFY_MCUACCUM ) ? +IRQENABLE_MCUACCUMINT :0 ; + val |= (notify_flags &SR_NOTIFY_MCUVALID ) ? +IRQENABLE_MCUVALIDINT :0 ; + val |= (notify_flags &SR_NOTIFY_MCUBOUND ) ? +IRQENABLE_MCUBOUNDSINT :0 ; + val |= (notify_flags &SR_NOTIFY_MCUDISACK ) ? +IRQENABLE_MCUDISABLEACKINT :0 ; +return val; +} + +static inline u8 irqstat_to_notifier_v1 (u32 status) +{ +u8 val; + val = (status &ERRCONFIG_MCUACCUMINTST ) ? +SR_NOTIFY_MCUACCUM :0 ; + val |= (status &ERRCONFIG_MCUVALIDINTEN ) ? +SR_NOTIFY_MCUVALID :0 ; + val |= (status &ERRCONFIG_MCUBOUNDINTEN ) ? +SR_NOTIFY_MCUBOUND :0 ; + val |= (status &ERRCONFIG_MCUDISACKINTEN ) ? +SR_NOTIFY_MCUDISACK :0 ; +return val; +} + +static inline u8 irqstat_to_notifier_v2 (u32 status) +{ +u8 val; + val = (status &IRQENABLE_MCUACCUMINT ) ? +SR_NOTIFY_MCUACCUM :0 ; + val |= (status &IRQENABLE_MCUVALIDINT ) ? +SR_NOTIFY_MCUVALID :0 ; + val |= (status &IRQENABLE_MCUBOUNDSINT ) ? +SR_NOTIFY_MCUBOUND :0 ; + val |= (status &IRQENABLE_MCUDISABLEACKINT ) ? +SR_NOTIFY_MCUDISACK :0 ; +return val; +} + +static irqreturn_t sr_interrupt (int irq,void *data) {struct omap_sr *sr_info = (struct omap_sr *)data;u32 status =0 ; +u32 value =0 ;if (sr_info->ip_type ==SR_TYPE_V1 ) { +/* Status bits are one bit before enable bits in v1 */ + value =notifier_to_irqen_v1 (sr_class->notify_flags) >>1 ; +/* Read the status bits */ status =sr_read_reg (sr_info,ERRCONFIG_V1 ); + status &= value;/* Clear them by writing back */ -sr_write_reg (sr_info,ERRCONFIG_V1 , status); +sr_modify_reg (sr_info,ERRCONFIG_V1 , value, status); + + value =irqstat_to_notifier_v1 (status); }else if (sr_info->ip_type ==SR_TYPE_V2 ) { + value =notifier_to_irqen_v2 (sr_class->notify_flags);/* Read the status bits */ -sr_read_reg (sr_info,IRQSTATUS ); + status =sr_read_reg (sr_info,IRQSTATUS ); + status &= value;/* Clear them by writing back */ sr_write_reg (sr_info,IRQSTATUS , status); + value =irqstat_to_notifier_v2 (status); }if (sr_class->notify) - sr_class->notify (sr_info->voltdm, status); + sr_class->notify (sr_info->voltdm, value);return IRQ_HANDLED ; }arch/arm/mach-omap2/smartreflex.h +6
-0@@ -142,6 +142,12 @@#define OMAP3430_SR_ERRWEIGHT 0x04#define OMAP3430_SR_ERRMAXLIMIT 0x02 +/* Smart reflex notifiers for class drivers to use */ +#define SR_NOTIFY_MCUDISACK BIT(3) +#define SR_NOTIFY_MCUBOUND BIT(2) +#define SR_NOTIFY_MCUVALID BIT(1) +#define SR_NOTIFY_MCUACCUM BIT(0) +/** * struct omap_sr_pmic_data - Strucutre to be populated by pmic code to pass * pmic specific info to smartreflex driver
PATCH v3 15/19 OMAP3+: SR: introduce notifier_control
In reply to Nishanth MenonWe need some mechanism from class drivers to control when notifiers should be triggered and when not, currently we have none, which makes Class driver usage of the interrupt events almost impossible.
Introduce an SmartReflex driver API for doing the same. This is useful for SmartReflex AVS class 1.5 or 2 drivers.
--- arch/arm/mach-omap2/smartreflex.c | 57 +++++++++++++++++++++++++++++++++++++ arch/arm/mach-omap2/smartreflex.h | 8 +++++ 2 files changed, 65 insertions(+), 0 deletions(-)
arch/arm/mach-omap2/smartreflex.c +57 -0
@@ -712,6 +712,63 @@ void sr_disable(struct voltagedomain *voltdm) }/** +* sr_notifier_control() - control the notifier mechanism +* @voltdm: VDD pointer to which the SR module to be configured belongs to. +* @enable: true to enable notifiers and false to disable the same +* +* SR modules allow an MCU interrupt mechanism that vary based on the IP +* revision, we allow the system to generate interrupt if the class driver +* has capability to handle the same. it is upto the class driver to ensure +* the proper sequencing and handling for a clean implementation. returns +* 0 if all goes fine, else returns failure results +*/ +int sr_notifier_control (struct voltagedomain *voltdm,bool enable) +{ +struct omap_sr *sr =_sr_lookup (voltdm); +u32 value =0 ; +if (IS_ERR_OR_NULL (sr)) { +pr_warning ("%s: sr corresponding to domain not found\n" , + __func__); +return -EINVAL ; + } +if (!sr->autocomp_active) +return -EINVAL ; + +/* if I could never register an isr, why bother?? */ +if (!(sr_class && sr_class->notify && sr_class->notify_flags && + sr->irq)) { +dev_warn (&sr->pdev->dev, +"%s: unable to setup irq without handling mechanism\n" , + __func__); +return -EINVAL ; + } + +switch (sr->ip_type) { +case SR_TYPE_V1 : + value =notifier_to_irqen_v1 (sr_class->notify_flags); +sr_modify_reg (sr,ERRCONFIG_V1 , value, + (enable) ? value :0 ); +break ; +case SR_TYPE_V2 : + value =notifier_to_irqen_v2 (sr_class->notify_flags); +sr_write_reg (sr, (enable) ?IRQENABLE_SET :IRQENABLE_CLR , + value); +break ; +default : +dev_warn (&sr->pdev->dev,"%s: unknown type of sr??\n" , + __func__); +return -EINVAL ; + } + +if (enable) +enable_irq (sr->irq); +else +disable_irq_nosync (sr->irq); + +return 0 ; +} + +/** * sr_register_class() - API to register a smartreflex class parameters. * @class_data: The structure containing various sr class specific data. *
arch/arm/mach-omap2/smartreflex.h +8 -0
@@ -242,6 +242,7 @@ void omap_sr_register_pmic(struct omap_sr_pmic_data *pmic_data);/* Smartreflex driver hooks to be called from Smartreflex class driver */ int sr_enable (struct voltagedomain *voltdm,unsigned long volt);void sr_disable (struct voltagedomain *voltdm); +int sr_notifier_control (struct voltagedomain *voltdm,bool enable);int sr_configure_errgen (struct voltagedomain *voltdm);int sr_configure_minmax (struct voltagedomain *voltdm);
@@ -250,6 +251,13 @@ int sr_register_class(struct omap_sr_class_data *class_data);#else static inline void omap_sr_enable (struct voltagedomain *voltdm) {}static inline void omap_sr_disable (struct voltagedomain *voltdm) {} + +static inline int sr_notifier_control (struct voltagedomain *voltdm, +bool enable) +{ +return -EINVAL ; +} +static inline void omap_sr_disable_reset_volt (struct voltagedomain *voltdm) {} static inline void omap_sr_register_pmic(
Signature · 1 line
1.7.1
PATCH v3 15/19 OMAP3+: SR: introduce notifier_control
Quoted 25 lines · Nishanth Menon
We need some mechanism from class drivers to control when notifiers should be triggered and when not, currently we have none, which makes Class driver usage of the interrupt events almost impossible.
Introduce an SmartReflex driver API for doing the same. This is useful for SmartReflex AVS class 1.5 or 2 drivers.
Signed-off-by Nishanth Menon <[email protected]>--- arch/arm/mach-omap2/smartreflex.c | 57 +++++++++++++++++++++++++++++++++++++ arch/arm/mach-omap2/smartreflex.h | 8 +++++ 2 files changed, 65 insertions(+), 0 deletions(-)arch/arm/mach-omap2/smartreflex.c +4
-0@@ -712,6 +712,63 @@ void sr_disable(struct voltagedomain *voltdm) }/** +* sr_notifier_control() - control the notifier mechanism +* @voltdm: VDD pointer to which the SR module to be configured belongs to. +* @enable: true to enable notifiers and false to disable the same +*
arch/arm/mach-omap2/smartreflex.c void sr_disable(struct voltagedomain *voltdm) · line 728
Quoted 10 lines
arch/arm/mach-omap2/smartreflex.c +10
-0+* SR modules allow an MCU interrupt mechanism that vary based on the IP +* revision, we allow the system to generate interrupt if the class driver +* has capability to handle the same. it is upto the class driver to ensure +* the proper sequencing and handling for a clean implementation. returns +* 0 if all goes fine, else returns failure results +*/ +int sr_notifier_control (struct voltagedomain *voltdm,bool enable) +{ +struct omap_sr *sr =_sr_lookup (voltdm); +u32 value =0 ;
insert blank line
arch/arm/mach-omap2/smartreflex.c void sr_disable(struct voltagedomain *voltdm) · line 729
Quoted 1 line
arch/arm/mach-omap2/smartreflex.c +1
-0+if (IS_ERR_OR_NULL (sr)) {
checking for NULL should suffice
arch/arm/mach-omap2/smartreflex.c void sr_disable(struct voltagedomain *voltdm) · line 737
Quoted 8 lines
arch/arm/mach-omap2/smartreflex.c +8
-0+pr_warning ("%s: sr corresponding to domain not found\n" , + __func__); +return -EINVAL ; + } +if (!sr->autocomp_active) +return -EINVAL ; + +/* if I could never register an isr, why bother?? */
s/isr/ISR/
arch/arm/mach-omap2/smartreflex.c void sr_disable(struct voltagedomain *voltdm) · line 742
Quoted 5 lines
arch/arm/mach-omap2/smartreflex.c +5
-0+if (!(sr_class && sr_class->notify && sr_class->notify_flags && + sr->irq)) { +dev_warn (&sr->pdev->dev, +"%s: unable to setup irq without handling mechanism\n" , + __func__);
s/irq/IRQ/
Quoted 17 lines
arch/arm/mach-omap2/smartreflex.c +17
-0+return -EINVAL ; + } + +switch (sr->ip_type) { +case SR_TYPE_V1 : + value =notifier_to_irqen_v1 (sr_class->notify_flags); +sr_modify_reg (sr,ERRCONFIG_V1 , value, + (enable) ? value :0 ); +break ; +case SR_TYPE_V2 : + value =notifier_to_irqen_v2 (sr_class->notify_flags); +sr_write_reg (sr, (enable) ?IRQENABLE_SET :IRQENABLE_CLR , + value); +break ; +default : +dev_warn (&sr->pdev->dev,"%s: unknown type of sr??\n" , + __func__);
arch/arm/mach-omap2/smartreflex.c void sr_disable(struct voltagedomain *voltdm) · line 769
Quoted 10 lines
arch/arm/mach-omap2/smartreflex.c +10
-0+return -EINVAL ; + } + +if (enable) +enable_irq (sr->irq); +else +disable_irq_nosync (sr->irq); + +return 0 ; +}
I'm not all that familiar with the SR IRQs, but why do you need to disable them at the IP an at the INTC? It seems like one of the two should suffice, and it seems like the INTC would be the most efficient.
Kevin
Quoted 30 lines
arch/arm/mach-omap2/smartreflex.c +1
-0+/** * sr_register_class() - API to register a smartreflex class parameters. * @class_data: The structure containing various sr class specific data. * arch/arm/mach-omap2/smartreflex.h +8
-0@@ -242,6 +242,7 @@ void omap_sr_register_pmic(struct omap_sr_pmic_data *pmic_data);/* Smartreflex driver hooks to be called from Smartreflex class driver */ int sr_enable (struct voltagedomain *voltdm,unsigned long volt);void sr_disable (struct voltagedomain *voltdm); +int sr_notifier_control (struct voltagedomain *voltdm,bool enable);int sr_configure_errgen (struct voltagedomain *voltdm);int sr_configure_minmax (struct voltagedomain *voltdm);@@ -250,6 +251,13 @@ int sr_register_class(struct omap_sr_class_data *class_data);#else static inline void omap_sr_enable (struct voltagedomain *voltdm) {}static inline void omap_sr_disable (struct voltagedomain *voltdm) {} + +static inline int sr_notifier_control (struct voltagedomain *voltdm, +bool enable) +{ +return -EINVAL ; +} +static inline void omap_sr_disable_reset_volt (struct voltagedomain *voltdm) {} static inline void omap_sr_register_pmic(
PATCH v3 16/19 OMAP3+: SR: disable spamming interrupts
In reply to Nishanth MenonAt times with bad SR configurations, especially during silicon bring-ups, we could get continuous spurious interrupts which end up hanging the platform in the form of an ISR call for status bits that are automatically enabled by the hardware without any software clearing option.
If we detect scenarios where ISR was called without the corresponding notification bit being set, instead of hanging up the system, we will disable interrupt after noting the event in the system log to try and keep system sanity and allow developer to debug and fix the condition.
--- arch/arm/mach-omap2/smartreflex.c | 12 ++++++++++-- 1 files changed, 10 insertions(+), 2 deletions(-)
arch/arm/mach-omap2/smartreflex.c +10 -2
@@ -209,8 +209,16 @@ static irqreturn_t sr_interrupt(int irq, void *data) value =irqstat_to_notifier_v2 (status); } -if (sr_class->notify) - sr_class->notify (sr_info->voltdm, value); +/* Attempt some resemblance of recovery! */ +if (!value) { +dev_err (&sr_info->pdev->dev,"%s: Spurious interrupt!" +"status = 0x%08x. Disabling to prevent spamming!!\n" , + __func__, status); +disable_irq_nosync (sr_info->irq); + }else { +if (sr_class->notify) + sr_class->notify (sr_info->voltdm, value); + }return IRQ_HANDLED ; }
Signature · 1 line
1.7.1
PATCH v3 17/19 OMAP3+: SR: make enable path use volt_data pointer
In reply to Nishanth MenonPassing the volt_data pointers across allows us to save us the effort of looking up the voltage data pointer from the voltage value at multiple layers, we need to look at the voltage data in DVFS layer for further processing, so modify the APIs to pass the voltage data pointer all the way through to lower layers to the SmartReflex AVS class drivers.
--- arch/arm/mach-omap2/smartreflex-class3.c | 13 +++---------- arch/arm/mach-omap2/smartreflex.c | 22 ++++++++++------------ arch/arm/mach-omap2/smartreflex.h | 8 +++++--- 3 files changed, 18 insertions(+), 25 deletions(-)
arch/arm/mach-omap2/smartreflex-class3.c +3 -10
@@ -13,19 +13,12 @@#include "smartreflex.h" -static int sr_class3_enable (struct voltagedomain *voltdm) +static int sr_class3_enable (struct voltagedomain *voltdm, +struct omap_volt_data *volt_data) { -unsigned long volt =omap_get_operation_voltage ( -omap_voltage_get_nom_volt (voltdm)); - -if (!volt) { -pr_warning ("%s: Curr voltage unknown. Cannot enable sr_%s\n" , - __func__, voltdm->name); -return -ENODATA ; - }omap_vp_enable (voltdm); -return sr_enable (voltdm, volt); +return sr_enable (voltdm, volt_data); }static int sr_class3_disable (struct voltagedomain *voltdm,int is_volt_reset)
arch/arm/mach-omap2/smartreflex.c +10 -12
@@ -306,7 +306,7 @@ static void sr_start_vddautocomp(struct omap_sr *sr, bool class_start)return ; } - r = sr_class->enable (sr->voltdm); + r = sr_class->enable (sr->voltdm,omap_voltage_get_nom_volt (sr->voltdm));if (!r && class_start) sr->autocomp_active = true; }
@@ -626,7 +626,7 @@ int sr_configure_minmax(struct voltagedomain *voltdm)/** * sr_enable() - Enables the smartreflex module. * @voltdm: VDD pointer to which the SR module to be configured belongs to. -* @volt: The voltage at which the Voltage domain associated with +* @volt_data: The voltage at which the Voltage domain associated with * the smartreflex module is operating at. * This is required only to program the correct Ntarget value. *
@@ -634,10 +634,9 @@ int sr_configure_minmax(struct voltagedomain *voltdm)* enable a smartreflex module. Returns 0 on success. Returns error * value if the voltage passed is wrong or if ntarget value is wrong. */ -int sr_enable (struct voltagedomain *voltdm,unsigned long volt) +int sr_enable (struct voltagedomain *voltdm,struct omap_volt_data *volt_data) {u32 nvalue_reciprocal; -struct omap_volt_data *volt_data;struct omap_sr *sr =_sr_lookup (voltdm);int ret;
@@ -647,19 +646,16 @@ int sr_enable(struct voltagedomain *voltdm, unsigned long volt)return -EINVAL ; } - volt_data =omap_voltage_get_voltdata (sr->voltdm, volt); - -if (IS_ERR (volt_data)) { -dev_warn (&sr->pdev->dev,"%s: Unable to get voltage table" -"for nominal voltage %ld\n" , __func__, volt); -return -ENODATA ; +if (IS_ERR_OR_NULL (volt_data)) { +dev_warn (&sr->pdev->dev,"%s: bad voltage data\n" , __func__); +return -EINVAL ; } nvalue_reciprocal =sr_retrieve_nvalue (sr, volt_data->sr_efuse_offs);if (!nvalue_reciprocal) {dev_warn (&sr->pdev->dev,"%s: NVALUE = 0 at voltage %ld\n" , - __func__, volt); + __func__,omap_get_operation_voltage (volt_data));return -ENODATA ; }
@@ -816,13 +812,15 @@ int sr_register_class(struct omap_sr_class_data *class_data)* omap_sr_enable() - API to enable SR clocks and to call into the * registered smartreflex class enable API. * @voltdm: VDD pointer to which the SR module to be configured belongs to. +* @volt_data: Voltage data to go to * * This API is to be called from the kernel in order to enable * a particular smartreflex module. This API will do the initial * configurations to turn on the smartreflex module and in turn call * into the registered smartreflex class enable API. */ -void omap_sr_enable (struct voltagedomain *voltdm) +void omap_sr_enable (struct voltagedomain *voltdm, +struct omap_volt_data *volt_data) {struct omap_sr *sr =_sr_lookup (voltdm);
arch/arm/mach-omap2/smartreflex.h +5 -3
@@ -186,7 +186,8 @@ struct omap_sr_pmic_data {* @class_priv_data: Class specific private data (optional) */ struct omap_sr_class_data { -int (*enable)(struct voltagedomain *voltdm); +int (*enable)(struct voltagedomain *voltdm, +struct omap_volt_data *volt_data);int (*disable)(struct voltagedomain *voltdm,int is_volt_reset);int (*start)(struct voltagedomain *voltdm,void *class_priv_data);int (*stop)(struct voltagedomain *voltdm,void *class_priv_data);
@@ -232,7 +233,8 @@ struct omap_sr_data { };/* Smartreflex module enable/disable interface */ -void omap_sr_enable (struct voltagedomain *voltdm); +void omap_sr_enable (struct voltagedomain *voltdm, +struct omap_volt_data *volt_data);void omap_sr_disable (struct voltagedomain *voltdm);void omap_sr_disable_reset_volt (struct voltagedomain *voltdm);
@@ -240,7 +242,7 @@ void omap_sr_disable_reset_volt(struct voltagedomain *voltdm);void omap_sr_register_pmic (struct omap_sr_pmic_data *pmic_data);/* Smartreflex driver hooks to be called from Smartreflex class driver */ -int sr_enable (struct voltagedomain *voltdm,unsigned long volt); +int sr_enable (struct voltagedomain *voltdm,struct omap_volt_data *volt_data);void sr_disable (struct voltagedomain *voltdm);int sr_notifier_control (struct voltagedomain *voltdm,bool enable);int sr_configure_errgen (struct voltagedomain *voltdm);
Signature · 1 line
1.7.1
PATCH v3 17/19 OMAP3+: SR: make enable path use volt_data pointer
Quoted 8 lines · Nishanth Menon
Passing the
volt_datapointers across allows us to save us the effort of looking up the voltage data pointer from the voltage value at multiple layers, we need to look at the voltage data in DVFS layer for further processing, so modify the APIs to pass the voltage data pointer all the way through to lower layers to the SmartReflex AVS class drivers.Signed-off-by Nishanth Menon <[email protected]>
Isn't volt_data already reachable from voltdm?
I'd rather than clutter up the APIs with another argument, especially one that should be derivable from the current one
Kevin
Quoted 141 lines
--- arch/arm/mach-omap2/smartreflex-class3.c | 13 +++---------- arch/arm/mach-omap2/smartreflex.c | 22 ++++++++++------------ arch/arm/mach-omap2/smartreflex.h | 8 +++++--- 3 files changed, 18 insertions(+), 25 deletions(-)arch/arm/mach-omap2/smartreflex-class3.c +3
-10@@ -13,19 +13,12 @@#include "smartreflex.h" -static int sr_class3_enable (struct voltagedomain *voltdm) +static int sr_class3_enable (struct voltagedomain *voltdm, +struct omap_volt_data *volt_data) { -unsigned long volt =omap_get_operation_voltage ( -omap_voltage_get_nom_volt (voltdm)); - -if (!volt) { -pr_warning ("%s: Curr voltage unknown. Cannot enable sr_%s\n" , - __func__, voltdm->name); -return -ENODATA ; - }omap_vp_enable (voltdm); -return sr_enable (voltdm, volt); +return sr_enable (voltdm, volt_data); }static int sr_class3_disable (struct voltagedomain *voltdm,int is_volt_reset)arch/arm/mach-omap2/smartreflex.c +10
-12@@ -306,7 +306,7 @@ static void sr_start_vddautocomp(struct omap_sr *sr, bool class_start)return ; } - r = sr_class->enable (sr->voltdm); + r = sr_class->enable (sr->voltdm,omap_voltage_get_nom_volt (sr->voltdm));if (!r && class_start) sr->autocomp_active = true; }@@ -626,7 +626,7 @@ int sr_configure_minmax(struct voltagedomain *voltdm)/** * sr_enable() - Enables the smartreflex module. * @voltdm: VDD pointer to which the SR module to be configured belongs to. -* @volt: The voltage at which the Voltage domain associated with +* @volt_data: The voltage at which the Voltage domain associated with * the smartreflex module is operating at. * This is required only to program the correct Ntarget value. * @@ -634,10 +634,9 @@ int sr_configure_minmax(struct voltagedomain *voltdm)* enable a smartreflex module. Returns 0 on success. Returns error * value if the voltage passed is wrong or if ntarget value is wrong. */ -int sr_enable (struct voltagedomain *voltdm,unsigned long volt) +int sr_enable (struct voltagedomain *voltdm,struct omap_volt_data *volt_data) {u32 nvalue_reciprocal; -struct omap_volt_data *volt_data;struct omap_sr *sr =_sr_lookup (voltdm);int ret;@@ -647,19 +646,16 @@ int sr_enable(struct voltagedomain *voltdm, unsigned long volt)return -EINVAL ; } - volt_data =omap_voltage_get_voltdata (sr->voltdm, volt); - -if (IS_ERR (volt_data)) { -dev_warn (&sr->pdev->dev,"%s: Unable to get voltage table" -"for nominal voltage %ld\n" , __func__, volt); -return -ENODATA ; +if (IS_ERR_OR_NULL (volt_data)) { +dev_warn (&sr->pdev->dev,"%s: bad voltage data\n" , __func__); +return -EINVAL ; } nvalue_reciprocal =sr_retrieve_nvalue (sr, volt_data->sr_efuse_offs);if (!nvalue_reciprocal) {dev_warn (&sr->pdev->dev,"%s: NVALUE = 0 at voltage %ld\n" , - __func__, volt); + __func__,omap_get_operation_voltage (volt_data));return -ENODATA ; }@@ -816,13 +812,15 @@ int sr_register_class(struct omap_sr_class_data *class_data)* omap_sr_enable() - API to enable SR clocks and to call into the * registered smartreflex class enable API. * @voltdm: VDD pointer to which the SR module to be configured belongs to. +* @volt_data: Voltage data to go to * * This API is to be called from the kernel in order to enable * a particular smartreflex module. This API will do the initial * configurations to turn on the smartreflex module and in turn call * into the registered smartreflex class enable API. */ -void omap_sr_enable (struct voltagedomain *voltdm) +void omap_sr_enable (struct voltagedomain *voltdm, +struct omap_volt_data *volt_data) {struct omap_sr *sr =_sr_lookup (voltdm);arch/arm/mach-omap2/smartreflex.h +5
-3@@ -186,7 +186,8 @@ struct omap_sr_pmic_data {* @class_priv_data: Class specific private data (optional) */ struct omap_sr_class_data { -int (*enable)(struct voltagedomain *voltdm); +int (*enable)(struct voltagedomain *voltdm, +struct omap_volt_data *volt_data);int (*disable)(struct voltagedomain *voltdm,int is_volt_reset);int (*start)(struct voltagedomain *voltdm,void *class_priv_data);int (*stop)(struct voltagedomain *voltdm,void *class_priv_data);@@ -232,7 +233,8 @@ struct omap_sr_data { };/* Smartreflex module enable/disable interface */ -void omap_sr_enable (struct voltagedomain *voltdm); +void omap_sr_enable (struct voltagedomain *voltdm, +struct omap_volt_data *volt_data);void omap_sr_disable (struct voltagedomain *voltdm);void omap_sr_disable_reset_volt (struct voltagedomain *voltdm);@@ -240,7 +242,7 @@ void omap_sr_disable_reset_volt(struct voltagedomain *voltdm);void omap_sr_register_pmic (struct omap_sr_pmic_data *pmic_data);/* Smartreflex driver hooks to be called from Smartreflex class driver */ -int sr_enable (struct voltagedomain *voltdm,unsigned long volt); +int sr_enable (struct voltagedomain *voltdm,struct omap_volt_data *volt_data);void sr_disable (struct voltagedomain *voltdm);int sr_notifier_control (struct voltagedomain *voltdm,bool enable);int sr_configure_errgen (struct voltagedomain *voltdm);
PATCH v3 18/19 OMAP3630+: SR: add support for class 1.5
In reply to Nishanth MenonTraditional SmartReflex AVS(Automatic Voltage Scaling) classes are:
* Class 0 - Product test calibration
Silicon is calibration at production floor and fused with voltages for each OPP
* Class 1 - Boot time calibration
Silicon is calibrated once at boot time and voltages are stored for the lifetime of operation.
* Class 2 - Continuous s/w calibration
SR module notifies s/w for any change in the system which is desired and the s/w makes runtime decisions in terms of setting the voltage, this mechanism could be used in the system which does not have PMIC capable of SR without using the voltage controller and voltage processor blocks.
* Class 3 - Continuous h/w calibration
SR module is switch on after reaching a voltage level and SR continuously monitors the system and makes runtime adjustments without s/w involvement.
OMAP3430 has used SmartReflex AVS and with a a PMIC which understands the SR protocol, Class 3 has been used. With OMAP3630 onwards, a new SmartReflex AVS class of operation Class 1.5 was introduced.
* Class 1.5 - Periodic s/w calibration
This uses the h/w calibration loop and at the end of calibration stores the voltages to be used run time, periodic recalibration is performed as well.
The operational mode is describes as the following:
* SmartReflex AVS h/w calibration loop is essential to identify the optimal voltage for a given OPP.
* Once this optimal voltage is detected, SmartReflex AVS loop is disabled in class 1.5 mode of operation.
* Until there is a need for a recalibration, any further transition to an OPP voltage which is calibrated can use the calibrated voltage and does not require enabling the SR AVS h/w loop.
* On a periodic basis (recommendation being once approximately every 24 hours), software is expected to perform a recalibration to find a new optimal voltage which is compensated for device aging.
- For performing this recalibration, the start voltage does not need to be the nominal voltage anymore. instead, the system can start with a voltage which is 50mV higher than the previously calibrated voltage to identify the new optimal voltage as the aging factor within a period of 1 day is not going to be anywhere close to 50mV.
- This "new starting point" for recalibration is called a dynamic nominal voltage for that voltage point.
In short, with the introduction of SmartReflex class 1.5, there are three new voltages possible in a system's DVFS transition:
* Nominal Voltage - The maximum voltage needed for a worst possible device in the worst possible conditions. This is the voltage we choose as the starting point for the h/w loop to optimize for the first time calibration on system bootup.
* Dynamic Nominal Voltage - Worst case voltage for a specific device in considering the system aging on the worst process device.
* Calibrated Voltage - Best voltage for the current device at a given point of time.
In terms of the implementation, doing calibration involves waiting for the SmartReflex h/w loop to settle down, and doing this as part of the DVFS flow itself is to increase the latency of DVFS transition when there is a need to calibrate that opp. instead, the calibration is performed "out of path" using a workqueue statemachine. The workqueue waits for the system stabilization, then enables VP interrupts to monitor for system instability interms of voltage oscillations that are reported back to the system as interrupts, in case of prolonged system oscillations, nominal voltage is chosen as a safe voltage and this event is logged in the system log for developer debug and fixing.
For the recalibration, a common workqueue for all domains is started at the start of the class initialization and it resets the calibrated voltages on a periodic basis. For distros that may choose not to do the recommended periodic recalibration, instead choose to perform boot time calibration, kconfig configuration option is provided to do so.
TODO:
a) Cpuidle and suspend paths are not integrated with SmartReflex driver at this point.
b) Since the SR registers are accessed and controlled in parallel to DVFS some sort of mechanism is necessary to be introduced along with OMAP DVFS layer to ensure mutual exclusivity
c) Additional debug interfaces for vmin analysis for platform characterization and addition of system margin needs to be introduced from SmartReflex perspective.
This implementation also includes the following contributors:
Tony Lindgren for suggestion on using interrupt based mechanism instead of polling to detect voltage oscillations.
Peter 'p2' De Schrijver for debating alternatives on recalibration mechanisms Paul Walmsey, Eduardo Valentin, Ambresh K, Igor Dmitriev and quiet a few others for patient review, testing and reporting of issues of a previous incarnation of this implemenation. Last, but not the least, the TI H/w team in introducing this new SR AVS class and patiently debating it's various facets.
---
NOTE: this patch generates a false postive checkpatch warning:
WARNING: please write a paragraph that describes the config symbol fully #989: FILE: arch/arm/plat-omap/Kconfig:73:
+ help
WARNING: please write a paragraph that describes the config symbol fully #998: FILE: arch/arm/plat-omap/Kconfig:82:
+ help
There is a help documentation for each of these, but it looks like checkpatch aint too intelligent about it.
arch/arm/mach-omap2/Makefile | 1 + arch/arm/mach-omap2/smartreflex-class1p5.c | 582 ++++++++++++++++++++++++++++ arch/arm/mach-omap2/smartreflex-class3.c | 4 +- arch/arm/mach-omap2/smartreflex.c | 26 ++- arch/arm/mach-omap2/smartreflex.h | 10 +- arch/arm/mach-omap2/voltage.c | 79 ++++ arch/arm/mach-omap2/voltage.h | 23 +- arch/arm/plat-omap/Kconfig | 17 + 8 files changed, 738 insertions(+), 4 deletions(-) create mode 100644 arch/arm/mach-omap2/smartreflex-class1p5.c
arch/arm/mach-omap2/Makefile +1 -0
@@ -66,6 +66,7 @@ obj-$(CONFIG_ARCH_OMAP4) += pm44xx.o pm_bus.o obj-$(CONFIG_PM_DEBUG) += pm-debug.o obj-$(CONFIG_OMAP_SMARTREFLEX) += sr_device.o smartreflex.o obj-$(CONFIG_OMAP_SMARTREFLEX_CLASS3) += smartreflex-class3.o +obj-$(CONFIG_OMAP_SMARTREFLEX_CLASS1P5) += smartreflex-class1p5.o AFLAGS_sleep24xx.o :=-Wa,-march=armv6 AFLAGS_sleep34xx.o :=-Wa,-march=armv7-a
arch/arm/mach-omap2/smartreflex-class1p5.c new file +582 -0
582 lines not on this page · raw message
arch/arm/mach-omap2/smartreflex-class3.c +3 -1
@@ -21,7 +21,9 @@ static int sr_class3_enable(struct voltagedomain *voltdm,return sr_enable (voltdm, volt_data); } -static int sr_class3_disable (struct voltagedomain *voltdm,int is_volt_reset) +static int sr_class3_disable (struct voltagedomain *voltdm, +struct omap_volt_data *vdata, +int is_volt_reset) {omap_vp_disable (voltdm);sr_disable (voltdm);
arch/arm/mach-omap2/smartreflex.c +25 -1
@@ -324,7 +324,9 @@ static void sr_stop_vddautocomp(struct omap_sr *sr, bool class_stop,return ; } - sr_class->disable (sr->voltdm, is_volt_reset); + sr_class->disable (sr->voltdm, +omap_voltage_get_nom_volt (sr->voltdm), + is_volt_reset);if (class_stop) {if (sr_class->stop && sr_class->stop (sr->voltdm, sr_class->class_priv_data))
@@ -478,6 +480,28 @@ static u32 sr_retrieve_nvalue(struct omap_sr *sr, u32 efuse_offs)/* Public Functions */ /** +* is_sr_enabled() - is Smart reflex enabled for this domain? +* @voltdm: voltage domain to check +* +* Returns 0 if SR is enabled for this domain, else returns err +*/ +bool is_sr_enabled (struct voltagedomain *voltdm) +{ +struct omap_sr *sr; +if (IS_ERR_OR_NULL (voltdm)) { +pr_warning ("%s: invalid param voltdm\n" , __func__); +return false; + } + sr =_sr_lookup (voltdm); +if (IS_ERR (sr)) { +pr_warning ("%s: omap_sr struct for sr_%s not found\n" , + __func__, voltdm->name); +return false; + } +return sr->autocomp_active; +} + +/** * sr_configure_errgen() - Configures the smrtreflex to perform AVS using the * error generator module. * @voltdm: VDD pointer to which the SR module to be configured belongs to.
arch/arm/mach-omap2/smartreflex.h +9 -1
@@ -168,6 +168,7 @@ struct omap_sr_pmic_data {#define SR_CLASS1 0x1#define SR_CLASS2 0x2#define SR_CLASS3 0x3 +#define SR_CLASS1P5 0x4/** * struct omap_sr_class_data - Smartreflex class driver info
@@ -188,7 +189,9 @@ struct omap_sr_pmic_data {struct omap_sr_class_data {int (*enable)(struct voltagedomain *voltdm,struct omap_volt_data *volt_data); -int (*disable)(struct voltagedomain *voltdm,int is_volt_reset); +int (*disable)(struct voltagedomain *voltdm, +struct omap_volt_data *volt_data, +int is_volt_reset);int (*start)(struct voltagedomain *voltdm,void *class_priv_data);int (*stop)(struct voltagedomain *voltdm,void *class_priv_data);int (*configure)(struct voltagedomain *voltdm);
@@ -250,6 +253,7 @@ int sr_configure_minmax(struct voltagedomain *voltdm);/* API to register the smartreflex class driver with the smartreflex driver */ int sr_register_class (struct omap_sr_class_data *class_data); +bool is_sr_enabled (struct voltagedomain *voltdm);#else static inline void omap_sr_enable (struct voltagedomain *voltdm) {}static inline void omap_sr_disable (struct voltagedomain *voltdm) {}
@@ -264,5 +268,9 @@ static inline void omap_sr_disable_reset_volt( struct voltagedomain *voltdm) {}static inline void omap_sr_register_pmic (struct omap_sr_pmic_data *pmic_data) {} +static inline bool is_sr_enabled (struct voltagedomain *voltdm) +{ +return false; +}#endif #endif
arch/arm/mach-omap2/voltage.c +79 -0
100 lines not on this page · raw message
arch/arm/mach-omap2/voltage.h +22 -1
@@ -57,6 +57,8 @@ struct voltagedomain {char *name; }; +#define OMAP3PLUS_DYNAMIC_NOMINAL_MARGIN_UV 50000 +/** * struct omap_volt_data - Omap voltage specific data. * @voltage_nominal: The possible voltage value in uV
@@ -71,6 +73,8 @@ struct voltagedomain {*/ struct omap_volt_data {u32 volt_nominal; +u32 volt_calibrated; +u32 volt_dynamic_nominal;u32 sr_efuse_offs;u8 sr_errminlimit;u8 vp_errgain;
@@ -156,6 +160,7 @@ struct dentry *omap_voltage_get_dbgdir(struct voltagedomain *voltdm);int __init omap_voltage_early_init (s16 prm_mod,s16 prm_irqst_mod,struct omap_vdd_info *omap_vdd_array[],u8 omap_vdd_count); +int omap_voltage_calib_reset (struct voltagedomain *voltdm);#ifdef CONFIG_PM int omap_voltage_register_pmic (struct voltagedomain *voltdm,struct omap_volt_pmic_info *pmic_info);
@@ -189,7 +194,23 @@ static inline unsigned long omap_get_operation_voltage( {if (IS_ERR_OR_NULL (vdata))return 0 ; -return vdata->volt_nominal; +return (vdata->volt_calibrated) ? vdata->volt_calibrated : + (vdata->volt_dynamic_nominal) ? vdata->volt_dynamic_nominal : + vdata->volt_nominal; } +/* what is my dynamic nominal? */ +static inline unsigned long omap_get_dyn_nominal (struct omap_volt_data *vdata) +{ +if (IS_ERR_OR_NULL (vdata)) +return 0 ; +if (vdata->volt_calibrated) { +unsigned long v = vdata->volt_calibrated + +OMAP3PLUS_DYNAMIC_NOMINAL_MARGIN_UV ; +if (v > vdata->volt_nominal) +return vdata->volt_nominal; +return v; + } +return vdata->volt_nominal; +}#endif
arch/arm/plat-omap/Kconfig +17 -0
@@ -67,6 +67,23 @@ config OMAP_SMARTREFLEX_CLASS3 Class 3 implementation of Smartreflex employs continuous hardware voltage calibration. +config OMAP_SMARTREFLEX_CLASS1P5 + bool "Class 1.5 mode of Smartreflex Implementation" + depends on OMAP_SMARTREFLEX && TWL4030_CORE + help + Say Y to enable Class 1.5 implementation of Smartreflex + Class 1.5 implementation of Smartreflex employs software controlled + hardware voltage calibration. + +config OMAP_SR_CLASS1P5_RECALIBRATION_DELAY + int "Class 1.5 mode recalibration recalibration delay(ms)" + depends on OMAP_SMARTREFLEX_CLASS1P5 + default 86400000 + help + Setup the recalibration delay in milliseconds. Use 0 for never doing + a recalibration. Defaults to recommended recalibration every 24hrs. + If you do not understand this, use the default. + config OMAP_RESET_CLOCKS bool "Reset unused clocks during boot" depends on ARCH_OMAP
Signature · 1 line
1.7.1
PATCH v3 18/19 OMAP3630+: SR: add support for class 1.5
Quoted 90 lines · Nishanth Menon
Traditional SmartReflex AVS(Automatic Voltage Scaling) classes are:
* Class 0 - Product test calibration
Silicon is calibration at production floor and fused with voltages for each OPP
* Class 1 - Boot time calibration
Silicon is calibrated once at boot time and voltages are stored for the lifetime of operation.
* Class 2 - Continuous s/w calibration
SR module notifies s/w for any change in the system which is desired and the s/w makes runtime decisions in terms of setting the voltage, this mechanism could be used in the system which does not have PMIC capable of SR without using the voltage controller and voltage processor blocks.
* Class 3 - Continuous h/w calibration
SR module is switch on after reaching a voltage level and SR continuously monitors the system and makes runtime adjustments without s/w involvement.OMAP3430 has used SmartReflex AVS and with a a PMIC which understands the SR protocol, Class 3 has been used. With OMAP3630 onwards, a new SmartReflex AVS class of operation Class 1.5 was introduced.
* Class 1.5 - Periodic s/w calibration
This uses the h/w calibration loop and at the end of calibration stores the voltages to be used run time, periodic recalibration is performed as well.The operational mode is describes as the following:
* SmartReflex AVS h/w calibration loop is essential to identify the optimal voltage for a given OPP.
* Once this optimal voltage is detected, SmartReflex AVS loop is disabled in class 1.5 mode of operation.
* Until there is a need for a recalibration, any further transition to an OPP voltage which is calibrated can use the calibrated voltage and does not require enabling the SR AVS h/w loop.
* On a periodic basis (recommendation being once approximately every 24 hours), software is expected to perform a recalibration to find a new optimal voltage which is compensated for device aging.
- For performing this recalibration, the start voltage does not need to be the nominal voltage anymore. instead, the system can start with a voltage which is 50mV higher than the previously calibrated voltage to identify the new optimal voltage as the aging factor within a period of 1 day is not going to be anywhere close to 50mV.
- This "new starting point" for recalibration is called a dynamic nominal voltage for that voltage point.
In short, with the introduction of SmartReflex class 1.5, there are three new voltages possible in a system's DVFS transition:
* Nominal Voltage - The maximum voltage needed for a worst possible device in the worst possible conditions. This is the voltage we choose as the starting point for the h/w loop to optimize for the first time calibration on system bootup.
* Dynamic Nominal Voltage - Worst case voltage for a specific device in considering the system aging on the worst process device.
* Calibrated Voltage - Best voltage for the current device at a given point of time.In terms of the implementation, doing calibration involves waiting for the SmartReflex h/w loop to settle down, and doing this as part of the DVFS flow itself is to increase the latency of DVFS transition when there is a need to calibrate that opp. instead, the calibration is performed "out of path" using a workqueue statemachine. The workqueue waits for the system stabilization, then enables VP interrupts to monitor for system instability interms of voltage oscillations that are reported back to the system as interrupts, in case of prolonged system oscillations, nominal voltage is chosen as a safe voltage and this event is logged in the system log for developer debug and fixing.
For the recalibration, a common workqueue for all domains is started at the start of the class initialization and it resets the calibrated voltages on a periodic basis. For distros that may choose not to do the recommended periodic recalibration, instead choose to perform boot time calibration, kconfig configuration option is provided to do so.
TODO:
a) Cpuidle and suspend paths are not integrated with SmartReflex driver at this point.
b) Since the SR registers are accessed and controlled in parallel to DVFS some sort of mechanism is necessary to be introduced along with OMAP DVFS layer to ensure mutual exclusivity
c) Additional debug interfaces for vmin analysis for platform characterization and addition of system margin needs to be introduced from SmartReflex perspective.This implementation also includes the following contributors:
Tony Lindgren for suggestion on using interrupt based mechanism instead of polling to detect voltage oscillations.
Peter 'p2' De Schrijver for debating alternatives on recalibration mechanisms Paul Walmsey, Eduardo Valentin, Ambresh K, Igor Dmitriev and quiet a few others for patient review, testing and reporting of issues of a previous incarnation of this implemenation. Last, but not the least, the TI H/w team in introducing this new SR AVS class and patiently debating it's various facets.
Quoted 8 lines
Cc Ambresh K <[email protected]>Cc Eduardo Valentin <[email protected]>Cc Igor Dmitriev <[email protected]>Cc Paul <[email protected]>Cc Peter 'p2' De Schrijver <[email protected]>Cc Tony Lindgren <[email protected]>Signed-off-by Nishanth Menon <[email protected]>
You're the expert on SR1.5, but I have some comments on code and data structure organization to improve readability. It may be because I'm not deeply familiar with SR1.5, but I found code organization and data structures difficult to follow and thus understand.
Quoted 7 lines
---
NOTE: this patch generates a false postive checkpatch warning:
WARNING: please write a paragraph that describes the config symbol fully #989: FILE:arch/arm/plat-omap/Kconfig:73:
+ help
Quoted 6 lines
WARNING: please write a paragraph that describes the config symbol fully #998: FILE:
arch/arm/plat-omap/Kconfig:82:
+ helpThere is a help documentation for each of these, but it looks like checkpatch aint too intelligent about it.
Agreed. I think checkpatch wants to see a certain number of lines in the help text, and whines if they're not there.
Quoted 16 lines
arch/arm/mach-omap2/Makefile | 1 + arch/arm/mach-omap2/smartreflex-class1p5.c | 582 ++++++++++++++++++++++++++++ arch/arm/mach-omap2/smartreflex-class3.c | 4 +- arch/arm/mach-omap2/smartreflex.c | 26 ++- arch/arm/mach-omap2/smartreflex.h | 10 +- arch/arm/mach-omap2/voltage.c | 79 ++++ arch/arm/mach-omap2/voltage.h | 23 +- arch/arm/plat-omap/Kconfig | 17 + 8 files changed, 738 insertions(+), 4 deletions(-) create mode 100644 arch/arm/mach-omap2/smartreflex-class1p5.carch/arm/mach-omap2/Makefile +0
-0
arch/arm/mach-omap2/Makefile obj-$(CONFIG_ARCH_OMAP4) += pm44xx.o pm_bus.o · line 69
Quoted 4 lines
arch/arm/mach-omap2/Makefile +1
-0@@ -66,6 +66,7 @@ obj-$(CONFIG_ARCH_OMAP4) += pm44xx.o pm_bus.o obj-$(CONFIG_PM_DEBUG) += pm-debug.o obj-$(CONFIG_OMAP_SMARTREFLEX) += sr_device.o smartreflex.o obj-$(CONFIG_OMAP_SMARTREFLEX_CLASS3) += smartreflex-class3.o +obj-$(CONFIG_OMAP_SMARTREFLEX_CLASS1P5) += smartreflex-class1p5.o
Minor: personal preference here, but I don't like the 1p5 naming. I'd rather see 1_5 or even 15, but I'll leave that to you.
Quoted 23 lines
arch/arm/mach-omap2/Makefile +0
-0AFLAGS_sleep24xx.o :=-Wa,-march=armv6 AFLAGS_sleep34xx.o :=-Wa,-march=armv7-aarch/arm/mach-omap2/smartreflex-class1p5.c new file +15
-0@@ -0,0 +1,582 @@ +/* +* Smart reflex Class 1.5 specific implementations +* +* Copyright (C) 2010-2011 Texas Instruments, Inc. +* Nishanth Menon <[email protected]> +* +* Smart reflex class 1.5 is also called periodic SW Calibration +* Some of the highlights are as follows: +* ? Host CPU triggers OPP calibration when transitioning to non calibrated +* OPP +* ? SR-AVS + VP modules are used to perform calibration +* ? Once completed, the SmartReflex-AVS module can be disabled +* ? Enables savings based on process, supply DC accuracy and aging +* +* This program is free software; you can redistribute it and/or modify
arch/arm/mach-omap2/smartreflex-class1p5.c line 25
Quoted 10 lines
arch/arm/mach-omap2/smartreflex-class1p5.c new file +10
-0+* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +*/ +#include <linux/kernel.h> +#include <linux/delay.h> +#include <linux/err.h> +#include <linux/io.h> +#include <linux/fs.h> +#include <linux/string.h> +#include <linux/uaccess.h>
Is this header needed?
arch/arm/mach-omap2/smartreflex-class1p5.c line 26
Quoted 1 line
arch/arm/mach-omap2/smartreflex-class1p5.c new file +1
-0+#include <linux/kobject.h>
or this one?
Quoted 24 lines
arch/arm/mach-omap2/smartreflex-class1p5.c new file +24
-0+#include <linux/workqueue.h> +#include <linux/opp.h> + +#include "smartreflex.h" +#include "voltage.h" + +#define MAX_VDDS 3 +#define SR1P5_SAMPLING_DELAY_MS 1 +#define SR1P5_STABLE_SAMPLES 5 +#define SR1P5_MAX_TRIGGERS 5 + +/* +* we expect events in 10uS, if we dont get 2wice times as much, +* we could kind of ignore this as a missed event. +*/ +#define MAX_CHECK_VPTRANS_US 20 + +/** +* struct sr_class1p5_work_data - data meant to be used by calibration work +* @work: calibration work +* @voltdm: voltage domain for which we are triggering +* @vdata: voltage data we are calibrating +* @num_calib_triggers: number of triggers from calibration loop +* @num_osc_samples: number of samples collected by isr
arch/arm/mach-omap2/smartreflex-class1p5.c line 60
Quoted 10 lines
arch/arm/mach-omap2/smartreflex-class1p5.c new file +10
-0+* @work_active: have we scheduled a work item? +*/ +struct sr_class1p5_work_data { +struct delayed_work work; +struct voltagedomain *voltdm; +struct omap_volt_data *vdata; +u8 num_calib_triggers; +u8 num_osc_samples; +bool work_active; +};
Again, the 1p5 naming I think is a hinderance to readability.
As these are file-local, I don't think you need the sr_class1p5_ prefix.
arch/arm/mach-omap2/smartreflex-class1p5.c line 65
Quoted 4 lines
arch/arm/mach-omap2/smartreflex-class1p5.c new file +4
-0+#if CONFIG_OMAP_SR_CLASS1P5_RECALIBRATION_DELAY +/* recal_work: recalibration calibration work */ +static struct delayed_work recal_work; +#endif
No Kconfig for this option please, let's make a reasonable default and allow board code to override.
arch/arm/mach-omap2/smartreflex-class1p5.c line 79
Quoted 13 lines
arch/arm/mach-omap2/smartreflex-class1p5.c new file +13
-0+/** +* struct sr_class1p5_data - private data for class 1p5 +* @work_data: work item data per voltage domain +*/ +struct sr_class1p5_data { +struct sr_class1p5_work_data work_data[MAX_VDDS ]; +}; + +static void sr_class1p5_reset_calib (struct voltagedomain *voltdm,bool reset, +bool recal); + +/* our instance of class 1p5 private data */ +static struct sr_class1p5_data class_1p5_data;
'class1p5_data' is also used below as the name of the 'struct omap_sr_class_data'. Another name for this would help readability/grepability
arch/arm/mach-omap2/smartreflex-class1p5.c line 82
Quoted 2 lines
arch/arm/mach-omap2/smartreflex-class1p5.c new file +2
-0+static struct sr_class1p5_work_data *get_sr1p5_work (struct voltagedomain + *voltdm)
as a static function, get_work should suffice
arch/arm/mach-omap2/smartreflex-class1p5.c line 81
Quoted 2 lines
arch/arm/mach-omap2/smartreflex-class1p5.c new file +2
-0+{ +int idx;
insert blank line
arch/arm/mach-omap2/smartreflex-class1p5.c line 89
Quoted 5 lines
arch/arm/mach-omap2/smartreflex-class1p5.c new file +5
-0+for (idx =0 ; idx <MAX_VDDS ; idx++) { +if (class_1p5_data.work_data[idx].voltdm && !strcmp + (class_1p5_data.work_data[idx].voltdm->name, voltdm->name)) +return &class_1p5_data.work_data[idx]; + }
insert blank line
Also, should do this such that you don't need to do continually do string compares. Since you need to keep a mapping of voltdm -> SR class data you should make something simple for it.
Using your current names, how about something like this (not even compile tested):
static struct {
struct voltagedomain *voltdm;
struct sr_class1p5_work_data *work_data;
} voltdm_to_work[MAX_VDDS];static struct sr_class1p5_work_data *get_sr1p5_work(struct voltagedomain
*voltdm)
{
int i;
struct sr_class1p5_work_data *work_data = NULL;
for( i = 0; i < MAX_VDDS; i++) {
struct voltagedomain *v = voltdm_to_work[i];
if (v && v == voltdm)
work_data = voltdm_to_work[i].work_data;
}
return work_data;
}And you could probably have a 'set_work' helper as well. Maybe this can be initialized in the class->configure hook instead of having to be done in the ->start hook each time ?
Quoted 4 lines
arch/arm/mach-omap2/smartreflex-class1p5.c new file +4
-0+return ERR_PTR (-ENODATA ); +} + +/**
arch/arm/mach-omap2/smartreflex-class1p5.c line 103
Quoted 10 lines
arch/arm/mach-omap2/smartreflex-class1p5.c new file +10
-0+* sr_class1p5_notify() - isr notifier for status events +* @voltdm: voltage domain for which we were triggered +* @status: notifier event to use +* +* This basically collects data for the work to use. +*/ +static int sr_class1p5_notify (struct voltagedomain *voltdm,u32 status) +{ +struct sr_class1p5_work_data *work_data; +int idx =0 ;
s/idx/i/
arch/arm/mach-omap2/smartreflex-class1p5.c line 101
Quoted 1 line
arch/arm/mach-omap2/smartreflex-class1p5.c new file +1
-0+if (IS_ERR_OR_NULL (voltdm)) {
on input parameters checking for NULL should suffice.
Please fix throughout this patch (and series)
arch/arm/mach-omap2/smartreflex-class1p5.c line 117
Quoted 12 lines
arch/arm/mach-omap2/smartreflex-class1p5.c new file +12
-0+pr_err ("%s: bad parameters!\n" , __func__); +return -EINVAL ; + } + + work_data =get_sr1p5_work (voltdm); +if (unlikely (!work_data)) { +pr_err ("%s:%s no work data!!\n" , __func__, voltdm->name); +return -EINVAL ; + } + +/* Wait for transdone so that we know the voltage to read */ + do {
readablity: use:
for(i = 0; i < MAX_CHECK_VPTRANS_US; i++)
arch/arm/mach-omap2/smartreflex-class1p5.c line 120
Quoted 3 lines
arch/arm/mach-omap2/smartreflex-class1p5.c new file +3
-0+if (omap_vp_is_transdone (voltdm)) +break ; + idx++;
then drop this
arch/arm/mach-omap2/smartreflex-class1p5.c line 121
Quoted 1 line
arch/arm/mach-omap2/smartreflex-class1p5.c new file +1
-0+/* get some constant delay */
comment does not help understand code, remove
arch/arm/mach-omap2/smartreflex-class1p5.c line 123
Quoted 2 lines
arch/arm/mach-omap2/smartreflex-class1p5.c new file +2
-0+udelay (1 ); + }while (idx <MAX_CHECK_VPTRANS_US );
and this
arch/arm/mach-omap2/smartreflex-class1p5.c line 127
Quoted 3 lines
arch/arm/mach-omap2/smartreflex-class1p5.c new file +3
-0+/* +* If we timeout, we still read the data, +* if we are oscillating+irq latencies are too high, we could
s/irq/IRQ/
arch/arm/mach-omap2/smartreflex-class1p5.c line 131
Quoted 4 lines
arch/arm/mach-omap2/smartreflex-class1p5.c new file +4
-0+* have scenarios where we miss transdone event. since +* we waited long enough, it is still safe to read the voltage +* as we would have waited long enough - still flag it.. +*/
/me no understand
arch/arm/mach-omap2/smartreflex-class1p5.c line 137
Quoted 6 lines
arch/arm/mach-omap2/smartreflex-class1p5.c new file +6
-0+if (idx >=MAX_CHECK_VPTRANS_US ) +pr_warning ("%s: timed out waiting for transdone!!\n" , __func__); + +omap_vp_clear_transdone (voltdm); + + idx = (work_data->num_osc_samples) %SR1P5_STABLE_SAMPLES ;
idx not used after this
arch/arm/mach-omap2/smartreflex-class1p5.c line 148
Quoted 11 lines
arch/arm/mach-omap2/smartreflex-class1p5.c new file +11
-0+ work_data->num_osc_samples++; + +return 0 ; +} + +/** +* do_calibrate() - work which actually does the calibration +* @work: pointer to the work +* +* calibration routine uses the following logic: +* on the first trigger, we start the isr to collect sr voltages
s/isr/ISR/ (and below)
arch/arm/mach-omap2/smartreflex-class1p5.c line 149
Quoted 1 line
arch/arm/mach-omap2/smartreflex-class1p5.c new file +1
-0+* wait for stabilization delay (reschdule self instead of sleeping)
"instead of sleeping" ? you'll indeed sleep until the delayed work is run
arch/arm/mach-omap2/smartreflex-class1p5.c line 152
Quoted 3 lines
arch/arm/mach-omap2/smartreflex-class1p5.c new file +3
-0+* after the delay, see if we collected any isr events +* if none, we have calibrated voltage. +* if there are any, we retry untill we giveup.
until we give up
arch/arm/mach-omap2/smartreflex-class1p5.c line 158
Quoted 6 lines
arch/arm/mach-omap2/smartreflex-class1p5.c new file +6
-0+* on retry timeout, select a voltage to use as safe voltage. +*/ +static void do_calibrate (struct work_struct *work) +{ +struct sr_class1p5_work_data *work_data = + container_of(work, struct sr_class1p5_work_data, work.work);
Doesn't a work_struct have a data field? I thought it was meant for this kind of thing, so you don't have to do a container_of()
Quoted 22 lines
arch/arm/mach-omap2/smartreflex-class1p5.c new file +22
-0+unsigned long u_volt_safe =0 , u_volt_current =0 ; +struct omap_volt_data *volt_data; +struct voltagedomain *voltdm; + +if (unlikely (!work_data)) { +pr_err ("%s: ooops.. null work_data?\n" , __func__); +return ; + } + +/* +* TODO:Handle the case where we might have just been scheduled AND +* 1.5 disable was called. check and HOLD DVFS +*/ + + voltdm = work_data->voltdm; +/* +* In the unlikely case that we did get through when unplanned, +* flag and return. +*/ +if (unlikely (!work_data->work_active)) { +pr_err ("%s:%s unplanned work invocation!\n" , __func__, + voltdm->name);
arch/arm/mach-omap2/smartreflex-class1p5.c line 190
Quoted 10 lines
arch/arm/mach-omap2/smartreflex-class1p5.c new file +10
-0+/* TODO release the DVFS */ +return ; + } + + work_data->num_calib_triggers++; +/* if we are triggered first time, we need to start isr to sample */ +if (work_data->num_calib_triggers ==1 ) + goto start_sampling; + +/* Stop isr from interrupting our measurements :) */
ISR.
What is the smiley supposed to mean?
arch/arm/mach-omap2/smartreflex-class1p5.c line 195
Quoted 5 lines
arch/arm/mach-omap2/smartreflex-class1p5.c new file +5
-0+sr_notifier_control (voltdm, false); + + volt_data = work_data->vdata; + +/* if there are no samples captured.. SR is silent, aka stability! */
Couldn't this also be zero when sampling is initially triggered. Is there a race here?
Quoted 5 lines
arch/arm/mach-omap2/smartreflex-class1p5.c new file +5
-0+if (!work_data->num_osc_samples) { + u_volt_safe =omap_vp_get_curr_volt (voltdm); + u_volt_current = u_volt_safe; + goto done_calib; + }
arch/arm/mach-omap2/smartreflex-class1p5.c line 210
Quoted 10 lines
arch/arm/mach-omap2/smartreflex-class1p5.c new file +10
-0+if (work_data->num_calib_triggers ==SR1P5_MAX_TRIGGERS ) { +pr_warning ("%s: %s recalib timeout!\n" , __func__, + work_data->voltdm->name); + goto oscillating_calib; + } + +/* we have potential oscillations/first sample */ +start_sampling: + work_data->num_osc_samples =0 ; +/* Clear pending events */
comment doesn't match following code
arch/arm/mach-omap2/smartreflex-class1p5.c line 207
Quoted 2 lines
arch/arm/mach-omap2/smartreflex-class1p5.c new file +2
-0+sr_notifier_control (voltdm, false); +/* Clear all transdones */
comment doesn't add anything to code
Quoted 270 lines
arch/arm/mach-omap2/smartreflex-class1p5.c new file +270
-0+while (omap_vp_is_transdone (voltdm)) +omap_vp_clear_transdone (voltdm); +/* trigger sampling */ +sr_notifier_control (voltdm, true); +schedule_delayed_work (&work_data->work, +msecs_to_jiffies (SR1P5_SAMPLING_DELAY_MS * +SR1P5_STABLE_SAMPLES )); +/* TODO: release DVFS */ +return ; + +oscillating_calib: +/* Use the nominal voltage as the safe voltage */ + u_volt_safe = volt_data->volt_nominal; +/* pick up current voltage to switch if needed */ + u_volt_current =omap_vp_get_curr_volt (voltdm); + +/* Fall through to close up common stuff */ +done_calib: +omap_vp_disable (voltdm); +sr_disable (voltdm); + + volt_data->volt_calibrated = u_volt_safe; +/* Setup my dynamic voltage for the next calibration for this opp */ + volt_data->volt_dynamic_nominal =omap_get_dyn_nominal (volt_data); + +/* +* if the voltage we decided as safe is not the current voltage, +* switch +*/ +if (volt_data->volt_calibrated != u_volt_current) { +pr_debug ("%s:%s reconfiguring to voltage %d\n" , + __func__, voltdm->name, volt_data->volt_calibrated); +omap_voltage_scale_vdd (voltdm, volt_data); + } + +/* +* TODO: Setup my wakeup voltage to allow immediate going to OFF and +* on - Pending twl and voltage layer cleanups. +* This is necessary, as this is not done as part of regular +* Dvfs flow. +* vc_setup_on_voltage(voltdm, volt_data->volt_calibrated); +*/ + work_data->work_active = false; +/* TODO: release DVFS */ +} + +#if CONFIG_OMAP_SR_CLASS1P5_RECALIBRATION_DELAY +/** +* do_recalibrate() - work which actually does the calibration +* @work: pointer to the work +* +* on a periodic basis, we come and reset our calibration setup +* so that a recalibration of the OPPs take place. This takes +* care of aging factor in the system. +*/ +static void do_recalibrate (struct work_struct *work) +{ +struct voltagedomain *voltdm; +int idx; +static struct sr_class1p5_work_data *work_data; + +for (idx =0 ; idx <MAX_VDDS ; idx++) { + work_data = &class_1p5_data.work_data[idx]; + voltdm = work_data->voltdm; +if (voltdm) { +/* if sr is not enabled, we check later */ +if (!is_sr_enabled (voltdm)) +continue ; +/* TODO: Pause the DVFS transitions */ +/* if sr is not enabled, we check later */ + +/* Reset and force a recalibration for current opp */ +sr_class1p5_reset_calib (voltdm, true, true); + +/* TODO: unpause DVFS transitions */ + } + } +/* We come back again after time the usual delay */ +schedule_delayed_work (&recal_work, +msecs_to_jiffies (CONFIG_OMAP_SR_CLASS1P5_RECALIBRATION_DELAY )); +} +#endif /* CONFIG_OMAP_SR_CLASS1P5_RECALIBRATION_DELAY */ + +/** +* sr_class1p5_enable() - class 1.5 mode of enable +* @voltdm: voltage domain to enable SR for +* @volt_data: voltdata to the voltage transition taking place +* +* when this gets called, we use the h/w loop to setup our voltages +* to an calibrated voltage, detect any oscillations, recover from the same +* and finally store the optimized voltage as the calibrated voltage in the +* system +*/ +static int sr_class1p5_enable (struct voltagedomain *voltdm, +struct omap_volt_data *volt_data) +{ +int r; +struct sr_class1p5_work_data *work_data; + +if (IS_ERR_OR_NULL (voltdm) ||IS_ERR_OR_NULL (volt_data)) { +pr_err ("%s: bad parameters!\n" , __func__); +return -EINVAL ; + } + +/* if already calibrated, nothing to do here.. */ +if (volt_data->volt_calibrated) +return 0 ; + + work_data =get_sr1p5_work (voltdm); +if (unlikely (!work_data)) { +pr_err ("%s: aieeee.. bad work data??\n" , __func__); +return -EINVAL ; + } + +if (work_data->work_active) +return 0 ; + +omap_vp_enable (voltdm); + r =sr_enable (voltdm, volt_data); +if (r) { +pr_err ("%s: sr[%s] failed\n" , __func__, voltdm->name); +omap_vp_disable (voltdm); +return r; + } + work_data->vdata = volt_data; + work_data->work_active = true; + work_data->num_calib_triggers =0 ; +/* program the workqueue and leave it to calibrate offline.. */ +schedule_delayed_work (&work_data->work, +msecs_to_jiffies (SR1P5_SAMPLING_DELAY_MS * +SR1P5_STABLE_SAMPLES )); + +return 0 ; +} + +/** +* sr_class1p5_disable() - disable for class 1p5 +* @voltdm: voltage domain for the sr which needs disabling +* @volt_data: voltagedata to disable +* @is_volt_reset: reset the voltage? +* +* we dont do anything if the class 1p5 is being used. this is because we +* already disable sr at the end of calibration and no h/w loop is actually +* active when this is called. +*/ +static int sr_class1p5_disable (struct voltagedomain *voltdm, +struct omap_volt_data *volt_data, +int is_volt_reset) +{ +struct sr_class1p5_work_data *work_data; + +if (IS_ERR_OR_NULL (voltdm) ||IS_ERR_OR_NULL (volt_data)) { +pr_err ("%s: bad parameters!\n" , __func__); +return -EINVAL ; + } + + work_data =get_sr1p5_work (voltdm); +if (work_data->work_active) { +/* if volt reset and work is active, we dont allow this */ +if (is_volt_reset) +return -EBUSY ; +/* flag work is dead and remove the old work */ + work_data->work_active = false; +cancel_delayed_work_sync (&work_data->work); +sr_notifier_control (voltdm, false); +omap_vp_disable (voltdm); +sr_disable (voltdm); + } + +/* if already calibrated, nothin special to do here.. */ +if (volt_data->volt_calibrated) +return 0 ; + +if (is_volt_reset) +omap_voltage_reset (voltdm); +return 0 ; +} + +/** +* sr_class1p5_configure() - configuration function +* @voltdm: configure for which voltage domain +* +* we dont do much here other than setup some registers for +* the sr module involved. +*/ +static int sr_class1p5_configure (struct voltagedomain *voltdm) +{ +if (IS_ERR_OR_NULL (voltdm)) { +pr_err ("%s: bad parameters!\n" , __func__); +return -EINVAL ; + } + +return sr_configure_errgen (voltdm); +} + +/** +* sr_class1p5_reset_calib() - reset all calibrated voltages +* @voltdm: configure for which voltage domain +* @reset: reset voltage before we recal? +* @recal: should I recalibrate my current opp? +* +* if we call this, it means either periodic calibration trigger was +* fired(either from sysfs or other mechanisms) or we have disabled class 1p5, +* meaning we cant trust the calib voltages anymore, it is better to use +* nominal in the system +*/ +static void sr_class1p5_reset_calib (struct voltagedomain *voltdm,bool reset, +bool recal) +{ +struct sr_class1p5_work_data *work_data; + +/* I dont need to go further if sr is not present */ +if (!is_sr_enabled (voltdm)) +return ; + + work_data =get_sr1p5_work (voltdm); + +if (work_data->work_active) +sr_class1p5_disable (voltdm, work_data->vdata,0 ); + +omap_voltage_calib_reset (voltdm); + +/* +* I should now reset the voltages to my nominal to be safe +*/ +if (reset) +omap_voltage_reset (voltdm); + +/* +* I should fire a recalibration for current opp if needed +* Note: i have just reset my calibrated voltages, and if +* i call sr_enable equivalent, I will cause a recalibration +* loop, even though the function is called sr_enable.. we +* are in class 1.5 ;) +*/ +if (reset && recal) +sr_class1p5_enable (voltdm, work_data->vdata); +} + +/** +* sr_class1p5_start() - class 1p5 init +* @voltdm: sr voltage domain +* @class_priv_data: private data for the class +* +* we do class specific initialization like creating sysfs/debugfs entries +* needed, spawning of a kthread if needed etc. +*/ +static int sr_class1p5_start (struct voltagedomain *voltdm, +void *class_priv_data) +{ +struct sr_class1p5_work_data *work_data; +int idx; + +if (IS_ERR_OR_NULL (voltdm) ||IS_ERR_OR_NULL (class_priv_data)) { +pr_err ("%s: bad parameters!\n" , __func__); +return -EINVAL ; + } + +/* setup our work params */ + work_data =get_sr1p5_work (voltdm); +if (!IS_ERR_OR_NULL (work_data)) { +pr_err ("%s: ooopps.. class already initialized for %s! bug??\n" , + __func__, voltdm->name); +return -EINVAL ; + } + work_data =NULL ; +/* get the next spare work_data */ +for (idx =0 ; idx <MAX_VDDS ; idx++) { +if (!class_1p5_data.work_data[idx].voltdm) { + work_data = &class_1p5_data.work_data[idx];
arch/arm/mach-omap2/smartreflex-class1p5.c line 492
Quoted 10 lines
arch/arm/mach-omap2/smartreflex-class1p5.c new file +10
-0+break ; + } + } +if (!work_data) { +pr_err ("%s: no more space for work data for domains!\n" , + __func__); +return -ENOMEM ; + } + work_data->voltdm = voltdm; +INIT_DELAYED_WORK_DEFERRABLE (&work_data->work, do_calibrate);
Much of this looks to be one-time init stuff. Wouldn't that be better in the ->configure method?
Quoted 95 lines
arch/arm/mach-omap2/smartreflex-class1p5.c new file +90
-0+return 0 ; +} + +/** +* sr_class1p5_stop() - class 1p5 deinitialization +* @voltdm: voltage domain for which to do this. +* @class_priv_data: class private data for deinitialiation +* +* currently only resets the calibrated voltage forcing DVFS voltages +* to be used in the system +*/ +static int sr_class1p5_stop (struct voltagedomain *voltdm, +void *class_priv_data) +{ +struct sr_class1p5_work_data *work_data; + +if (IS_ERR_OR_NULL (voltdm) ||IS_ERR_OR_NULL (class_priv_data)) { +pr_err ("%s: bad parameters!\n" , __func__); +return -EINVAL ; + } + +/* setup our work params */ + work_data =get_sr1p5_work (voltdm); +if (IS_ERR_OR_NULL (work_data)) { +pr_err ("%s: ooopps.. class not initialized for %s! bug??\n" , + __func__, voltdm->name); +return -EINVAL ; + } + +/* +* we dont have SR periodic calib anymore.. so reset calibs +* we are already protected by sr debugfs lock, so no lock needed +* here. +*/ +sr_class1p5_reset_calib (voltdm, true, false); + +/* reset all data for this work data */ +memset (work_data,0 ,sizeof (*work_data)); + +return 0 ; +} + +/* SR class1p5 structure */ +static struct omap_sr_class_data class1p5_data = { + .enable = sr_class1p5_enable, + .disable = sr_class1p5_disable, + .configure = sr_class1p5_configure, + .class_type =SR_CLASS1P5 , + .start = sr_class1p5_start, + .stop = sr_class1p5_stop, + .notify = sr_class1p5_notify, +/* +* trigger for bound - this tells VP that SR has a voltage +* change. we should ensure transdone is set before reading +* vp voltage. +*/ + .notify_flags =SR_NOTIFY_MCUBOUND , + .class_priv_data = (void *)&class_1p5_data, +}; + +/** +* sr_class1p5_init() - register class 1p5 as default +* +* board files call this function to use class 1p5, we register with the +* smartreflex subsystem +*/ +static int __init sr_class1p5_init (void ) +{ +int r; + +/* Enable this class only for OMAP3630 and OMAP4 */ +if (!(cpu_is_omap3630 () ||cpu_is_omap44xx ())) +return -EINVAL ; + + r =sr_register_class (&class1p5_data); +if (r) { +pr_err ("SmartReflex class 1.5 driver: " +"failed to register with %d\n" , r); + }else { +#if CONFIG_OMAP_SR_CLASS1P5_RECALIBRATION_DELAY +INIT_DELAYED_WORK_DEFERRABLE (&recal_work, do_recalibrate); +schedule_delayed_work (&recal_work,msecs_to_jiffies ( +CONFIG_OMAP_SR_CLASS1P5_RECALIBRATION_DELAY )); +#endif +pr_info ("SmartReflex class 1.5 driver: initialized (%dms)\n" , +CONFIG_OMAP_SR_CLASS1P5_RECALIBRATION_DELAY ); + } +return r; +} +late_initcall (sr_class1p5_init);arch/arm/mach-omap2/smartreflex-class3.c +0
-0
arch/arm/mach-omap2/smartreflex-class3.c static int sr_class3_enable(struct voltagedomain *voltdm, · line 26
Quoted 7 lines
arch/arm/mach-omap2/smartreflex-class3.c +3
-1@@ -21,7 +21,9 @@ static int sr_class3_enable(struct voltagedomain *voltdm,return sr_enable (voltdm, volt_data); } -static int sr_class3_disable (struct voltagedomain *voltdm,int is_volt_reset) +static int sr_class3_disable (struct voltagedomain *voltdm, +struct omap_volt_data *vdata, +int is_volt_reset)
I think this change belonged in the previous patch.
Quoted 8 lines
arch/arm/mach-omap2/smartreflex-class3.c +0
-0{omap_vp_disable (voltdm);sr_disable (voltdm);arch/arm/mach-omap2/smartreflex.c +0
-0
arch/arm/mach-omap2/smartreflex.c static void sr_stop_vddautocomp(struct omap_sr *sr, bool class_stop, · line 329
Quoted 7 lines
arch/arm/mach-omap2/smartreflex.c +3
-1@@ -324,7 +324,9 @@ static void sr_stop_vddautocomp(struct omap_sr *sr, bool class_stop,return ; } - sr_class->disable (sr->voltdm, is_volt_reset); + sr_class->disable (sr->voltdm, +omap_voltage_get_nom_volt (sr->voltdm), + is_volt_reset);
this one too.
arch/arm/mach-omap2/smartreflex.c static u32 sr_retrieve_nvalue(struct omap_sr *sr, u32 efuse_offs) · line 488
Quoted 13 lines
arch/arm/mach-omap2/smartreflex.c +6
-0if (class_stop) {if (sr_class->stop && sr_class->stop (sr->voltdm, sr_class->class_priv_data))@@ -478,6 +480,28 @@ static u32 sr_retrieve_nvalue(struct omap_sr *sr, u32 efuse_offs)/* Public Functions */ /** +* is_sr_enabled() - is Smart reflex enabled for this domain? +* @voltdm: voltage domain to check +* +* Returns 0 if SR is enabled for this domain, else returns err +*/ +bool is_sr_enabled (struct voltagedomain *voltdm)
Please follow naming conventions of the rest of the SR layer.
arch/arm/mach-omap2/smartreflex.c static u32 sr_retrieve_nvalue(struct omap_sr *sr, u32 efuse_offs) · line 490
Quoted 2 lines
arch/arm/mach-omap2/smartreflex.c +2
-0+{ +struct omap_sr *sr;
insert blank line
Quoted 30 lines
arch/arm/mach-omap2/smartreflex.c +14
-0+if (IS_ERR_OR_NULL (voltdm)) { +pr_warning ("%s: invalid param voltdm\n" , __func__); +return false; + } + sr =_sr_lookup (voltdm); +if (IS_ERR (sr)) { +pr_warning ("%s: omap_sr struct for sr_%s not found\n" , + __func__, voltdm->name); +return false; + } +return sr->autocomp_active; +} + +/** * sr_configure_errgen() - Configures the smrtreflex to perform AVS using the * error generator module. * @voltdm: VDD pointer to which the SR module to be configured belongs to. arch/arm/mach-omap2/smartreflex.h +1
-0@@ -168,6 +168,7 @@ struct omap_sr_pmic_data {#define SR_CLASS1 0x1#define SR_CLASS2 0x2#define SR_CLASS3 0x3 +#define SR_CLASS1P5 0x4/** * struct omap_sr_class_data - Smartreflex class driver info
arch/arm/mach-omap2/smartreflex.h struct omap_sr_pmic_data { · line 194
Quoted 7 lines
arch/arm/mach-omap2/smartreflex.h +3
-1@@ -188,7 +189,9 @@ struct omap_sr_pmic_data {struct omap_sr_class_data {int (*enable)(struct voltagedomain *voltdm,struct omap_volt_data *volt_data); -int (*disable)(struct voltagedomain *voltdm,int is_volt_reset); +int (*disable)(struct voltagedomain *voltdm, +struct omap_volt_data *volt_data, +int is_volt_reset);
This change should've been part of previous patch.
Quoted 47 lines
arch/arm/mach-omap2/smartreflex.h +5
-0int (*start)(struct voltagedomain *voltdm,void *class_priv_data);int (*stop)(struct voltagedomain *voltdm,void *class_priv_data);int (*configure)(struct voltagedomain *voltdm);@@ -250,6 +253,7 @@ int sr_configure_minmax(struct voltagedomain *voltdm);/* API to register the smartreflex class driver with the smartreflex driver */ int sr_register_class (struct omap_sr_class_data *class_data); +bool is_sr_enabled (struct voltagedomain *voltdm);#else static inline void omap_sr_enable (struct voltagedomain *voltdm) {}static inline void omap_sr_disable (struct voltagedomain *voltdm) {}@@ -264,5 +268,9 @@ static inline void omap_sr_disable_reset_volt( struct voltagedomain *voltdm) {}static inline void omap_sr_register_pmic (struct omap_sr_pmic_data *pmic_data) {} +static inline bool is_sr_enabled (struct voltagedomain *voltdm) +{ +return false; +}#endif #endif arch/arm/mach-omap2/voltage.c +18
-0@@ -182,9 +182,55 @@ static int nom_volt_debug_get(void *data, u64 *val)return 0 ; } +static int dyn_volt_debug_get (void *data,u64 *val) +{ +struct omap_vdd_info *vdd = (struct omap_vdd_info *) data; +struct omap_volt_data *volt_data; + +if (!vdd) { +pr_warning ("Wrong paramater passed\n" ); +return -EINVAL ; + } + + volt_data =omap_voltage_get_nom_volt (&vdd->voltdm); +if (IS_ERR_OR_NULL (volt_data)) { +pr_warning ("%s: No voltage/domain?\n" , __func__); +return -ENODEV ; + } + + *val = volt_data->volt_dynamic_nominal; +
arch/arm/mach-omap2/voltage.c static int nom_volt_debug_get(void *data, u64 *val) · line 212
Quoted 10 lines
arch/arm/mach-omap2/voltage.c +10
-0+return 0 ; +} + +static int calib_volt_debug_get (void *data,u64 *val) +{ +struct omap_vdd_info *vdd = (struct omap_vdd_info *) data; +struct omap_volt_data *volt_data; + +if (!vdd) { +pr_warning ("Wrong paramater passed\n" );
to be a useful debug message, should at least have a __func__ involved to know where it came from.
Quoted 76 lines
arch/arm/mach-omap2/voltage.c +51
-0+return -EINVAL ; + } + + volt_data =omap_voltage_get_nom_volt (&vdd->voltdm); +if (IS_ERR_OR_NULL (volt_data)) { +pr_warning ("%s: No voltage/domain?\n" , __func__); +return -ENODEV ; + } + + *val = volt_data->volt_calibrated; + +return 0 ; +} +DEFINE_SIMPLE_ATTRIBUTE (vp_volt_debug_fops, vp_volt_debug_get,NULL ,"%llu\n" );DEFINE_SIMPLE_ATTRIBUTE (nom_volt_debug_fops, nom_volt_debug_get,NULL ,"%llu\n" ); +DEFINE_SIMPLE_ATTRIBUTE (dyn_volt_debug_fops, dyn_volt_debug_get,NULL , +"%llu\n" ); +DEFINE_SIMPLE_ATTRIBUTE (calib_volt_debug_fops, calib_volt_debug_get,NULL , +"%llu\n" );static void vp_latch_vsel (struct omap_vdd_info *vdd) {u32 vpconfig;@@ -306,6 +352,12 @@ static void __init vdd_debugfs_init(struct omap_vdd_info *vdd) (void )debugfs_create_file ("curr_nominal_volt" ,S_IRUGO , vdd->debug_dir, (void *) vdd, &nom_volt_debug_fops); + (void )debugfs_create_file ("curr_dyn_nominal_volt" ,S_IRUGO , + vdd->debug_dir, (void *) vdd, + &dyn_volt_debug_fops); + (void )debugfs_create_file ("curr_calibrated_volt" ,S_IRUGO , + vdd->debug_dir, (void *) vdd, + &calib_volt_debug_fops); }/* Voltage scale and accessory APIs */ @@ -697,6 +749,33 @@ struct omap_volt_data *omap_voltage_get_nom_volt(struct voltagedomain *voltdm) }/** +* omap_voltage_calib_reset() - reset the calibrated voltage entries +* @voltdm: voltage domain to reset the entries for +* +* when the calibrated entries are no longer valid, this api allows +* the calibrated voltages to be reset. +*/ +int omap_voltage_calib_reset (struct voltagedomain *voltdm) +{ +struct omap_vdd_info *vdd; +struct omap_volt_data *volt_data; + +if (IS_ERR_OR_NULL (voltdm)) { +pr_warning ("%s: VDD specified does not exist!\n" , __func__); +return -EINVAL ; + } + + vdd = container_of(voltdm, struct omap_vdd_info, voltdm); + volt_data = vdd->volt_data; +/* reset the calibrated voltages as 0 */ +while (volt_data->volt_nominal) { + volt_data->volt_calibrated =0 ; + volt_data++; + } +return 0 ; +} + +/** * omap_vp_get_curr_volt() - API to get the current vp voltage. * @voltdm: pointer to the VDD. * arch/arm/mach-omap2/voltage.h +0
-0
arch/arm/mach-omap2/voltage.h struct voltagedomain { · line 61
Quoted 5 lines
arch/arm/mach-omap2/voltage.h +2
-0@@ -57,6 +57,8 @@ struct voltagedomain {char *name; }; +#define OMAP3PLUS_DYNAMIC_NOMINAL_MARGIN_UV 50000 +
A comment describing this value (and where it came from) would be most useful.
Quoted 21 lines
arch/arm/mach-omap2/voltage.h +3
-0/** * struct omap_volt_data - Omap voltage specific data. * @voltage_nominal: The possible voltage value in uV @@ -71,6 +73,8 @@ struct voltagedomain {*/ struct omap_volt_data {u32 volt_nominal; +u32 volt_calibrated; +u32 volt_dynamic_nominal;u32 sr_efuse_offs;u8 sr_errminlimit;u8 vp_errgain;@@ -156,6 +160,7 @@ struct dentry *omap_voltage_get_dbgdir(struct voltagedomain *voltdm);int __init omap_voltage_early_init (s16 prm_mod,s16 prm_irqst_mod,struct omap_vdd_info *omap_vdd_array[],u8 omap_vdd_count); +int omap_voltage_calib_reset (struct voltagedomain *voltdm);#ifdef CONFIG_PM int omap_voltage_register_pmic (struct voltagedomain *voltdm,struct omap_volt_pmic_info *pmic_info);
arch/arm/mach-omap2/voltage.h static inline unsigned long omap_get_operation_voltage( · line 202
Quoted 10 lines
arch/arm/mach-omap2/voltage.h +4
-1@@ -189,7 +194,23 @@ static inline unsigned long omap_get_operation_voltage( {if (IS_ERR_OR_NULL (vdata))return 0 ; -return vdata->volt_nominal; +return (vdata->volt_calibrated) ? vdata->volt_calibrated : + (vdata->volt_dynamic_nominal) ? vdata->volt_dynamic_nominal : + vdata->volt_nominal; } +/* what is my dynamic nominal? */
comment doesn't add anything to code
Quoted 32 lines
arch/arm/mach-omap2/voltage.h +13
-0+static inline unsigned long omap_get_dyn_nominal (struct omap_volt_data *vdata) +{ +if (IS_ERR_OR_NULL (vdata)) +return 0 ; +if (vdata->volt_calibrated) { +unsigned long v = vdata->volt_calibrated + +OMAP3PLUS_DYNAMIC_NOMINAL_MARGIN_UV ; +if (v > vdata->volt_nominal) +return vdata->volt_nominal; +return v; + } +return vdata->volt_nominal; +}#endif arch/arm/plat-omap/Kconfig +10
-0@@ -67,6 +67,23 @@ config OMAP_SMARTREFLEX_CLASS3 Class 3 implementation of Smartreflex employs continuous hardware voltage calibration. +config OMAP_SMARTREFLEX_CLASS1P5 + bool "Class 1.5 mode of Smartreflex Implementation" + depends on OMAP_SMARTREFLEX && TWL4030_CORE + help + Say Y to enable Class 1.5 implementation of Smartreflex + Class 1.5 implementation of Smartreflex employs software controlled + hardware voltage calibration. + +config OMAP_SR_CLASS1P5_RECALIBRATION_DELAY + int "Class 1.5 mode recalibration recalibration delay(ms)"
arch/arm/plat-omap/Kconfig config OMAP_SMARTREFLEX_CLASS3 · line 89
Quoted 10 lines
arch/arm/plat-omap/Kconfig +7
-0+ depends on OMAP_SMARTREFLEX_CLASS1P5 + default 86400000 + help + Setup the recalibration delay in milliseconds. Use 0 for never doing + a recalibration. Defaults to recommended recalibration every 24hrs. + If you do not understand this, use the default. + config OMAP_RESET_CLOCKS bool "Reset unused clocks during boot" depends on ARCH_OMAP
Kevin
PATCH v3 19/19 OMAP3430: SR: class3: restrict CPU to run on
In reply to Nishanth MenonUse SmartReflex AVS Class3 initialization only for OMAP343x family of processors.
--- arch/arm/mach-omap2/smartreflex-class3.c | 5 +++++ 1 files changed, 5 insertions(+), 0 deletions(-)
arch/arm/mach-omap2/smartreflex-class3.c +5 -0
@@ -11,6 +11,7 @@* published by the Free Software Foundation. */ +#include <plat/cpu.h> #include "smartreflex.h" static int sr_class3_enable(struct voltagedomain *voltdm,
@@ -49,6 +50,10 @@ static struct omap_sr_class_data class3_data = {/* Smartreflex Class3 init API to be called from board file */ static int __init sr_class3_init (void ) { +/* Enable this class only for OMAP343x */ +if (!cpu_is_omap343x ()) +return -EINVAL ; +pr_info ("SmartReflex Class3 initialized\n" );return sr_register_class (&class3_data); }
Signature · 1 line
1.7.1
PATCH v3 19/19 OMAP3430: SR: class3: restrict CPU to run on
Quoted 2 lines · Nishanth Menon
Use SmartReflex AVS Class3 initialization only for OMAP343x family of processors.
Why?