OMAP3: PM: Smartreflex and voltage revamp.
Subsystems (5)
v2 cover OMAP3: PM: Smartreflex and voltage revamp.
The main motivations behind this patch series are the following
1. Making smartreflex a platform driver with omap-device layer.
2. Separating voltage specific code from smartreflex.c and other locations and consolidating them into voltage.c and voltage.h.
3. Smartreflex module can have Class 3 or Class 2 implementations depending on the PMIC in use. Making smartreflex.c capable of handling both the class implementaions and separating out class specific code into a separate class driver.
4. Remove dependencies on opp id in the smartreflex and voltage drivers
5. Implementating latest TI recommended register settings for Smartreflex and Voltage processor module as well as recommended sequences for enabling and disabling of Smartreflex and Voltage processor modules.
6. Implementing VP force update method of voltage scaling which is again TI hardware recommended.
What this patch series does not address are
1. Separating PMIC specific portions from smartreflex and voltage code.
2. OMAP3630 and OMP4 smartreflex support.
This patch series is based on Kevin's PM tree origin/pm-wip-opp branch and is dependent on the following patches not yet applied onto this branch.
http://patchwork.kernel.org/patch/81504/ http://patchwork.kernel.org/patch/81606/
This patch series has been tested on OMAP3430 SDP with basic power management tests including the dvfs scripts.
Thara Gopinath (17):
OMAP3: PM: Adding hwmod data for Smartreflex
OMAP3: PM: Create list to keep track of various smartreflex
instances.
OMAP3: PM: Convert smartreflex driver into a platform driver using
hwmods and omap-device layer
OMAP3: PM: Move smartreflex autocompensation enable disable hooks to
PM debugfs.
OMAP3: PM: Remove OPP id dependency from smartreflex driver
OMAP3: PM: Correcting API names in samrtreflex driver.
OMAP3: PM: Smartreflex class related changes for smartreflex.c
OMAP3: PM: Adding smartreflex class 3 driver.
OMAP3: PM: Creating separate files for handling OMAP3 voltage related
operations.
OMAP3: PM: Disabling Smartreflex across both frequency and voltage
scaling during DVFS.
OMAP3: PM: Cleaning up of smartreflex header file.
OMAP3: PM: Configurations for Smartreflex Class 2 and Smartreflex
Class 3
OMAP3: PM: Support for enabling smartreflex autocompensation by
default.
OMAP3: PM: Correcting accessing of ERRCONFIG register in
smartreflex.c
OMAP3: PM: Implement latest h/w recommendations for SR and VP
registers and SR VP enable disable sequence.
OMAP3: PM: VP force update method of voltage scaling
OMAP3: PM: Enabling Smartreflex Class 3 driver by default in pm
defconfig
arch/arm/configs/omap3_pm_defconfig | 1 + arch/arm/mach-omap2/Makefile | 6 +- arch/arm/mach-omap2/board-3430sdp.c | 3 +- arch/arm/mach-omap2/omap_hwmod_3xxx_data.c | 94 ++ arch/arm/mach-omap2/pm-debug.c | 4 +- arch/arm/mach-omap2/pm.h | 7 - arch/arm/mach-omap2/pm34xx.c | 95 +-- arch/arm/mach-omap2/resource34xx.c | 27 +- arch/arm/mach-omap2/resource34xx.h | 1 - arch/arm/mach-omap2/smartreflex-class3.c | 53 ++ arch/arm/mach-omap2/smartreflex.c | 1297 +++++++++++----------------- arch/arm/mach-omap2/smartreflex.h | 336 ++++---- arch/arm/mach-omap2/sr_device.c | 196 +++++ arch/arm/mach-omap2/voltage.c | 823 ++++++++++++++++++ arch/arm/mach-omap2/voltage.h | 80 ++ arch/arm/plat-omap/Kconfig | 11 +- 16 files changed, 1935 insertions(+), 1099 deletions(-) create mode 100644 arch/arm/mach-omap2/smartreflex-class3.c create mode 100644 arch/arm/mach-omap2/sr_device.c create mode 100644 arch/arm/mach-omap2/voltage.c create mode 100644 arch/arm/mach-omap2/voltage.h
PATCH v2 1/17 OMAP3: PM: Adding hwmod data for Smartreflex
This patch adds the hwmod strucutres and other hwmod data for OMAP3 Smartreflex IP's.
--- arch/arm/mach-omap2/omap_hwmod_3xxx_data.c | 94 ++++++++++++++++++++++++++++ 1 files changed, 94 insertions(+), 0 deletions(-)
arch/arm/mach-omap2/omap_hwmod_3xxx_data.c +94 -0
@@ -35,6 +35,8 @@ static struct omap_hwmod omap3xxx_mpu_hwmod;static struct omap_hwmod omap3xxx_l3_hwmod;static struct omap_hwmod omap3xxx_l4_core_hwmod;static struct omap_hwmod omap3xxx_l4_per_hwmod; +static struct omap_hwmod omap34xx_sr1_hwmod; +static struct omap_hwmod omap34xx_sr2_hwmod;/* L3 -> L4_CORE interface */ static struct omap_hwmod_ocp_if omap3xxx_l3__l4_core = {
@@ -88,9 +90,47 @@ static struct omap_hwmod_ocp_if omap3xxx_l4_core__l4_wkup = { .user = OCP_USER_MPU | OCP_USER_SDMA, }; +/* L4 CORE -> SR1 interface */ +static struct omap_hwmod_addr_space omap34xx_sr1_addr_space[] = { + { + .pa_start =OMAP34XX_SR1_BASE , + .pa_end =OMAP34XX_SR1_BASE +SZ_1K -1 , + .flags =ADDR_MAP_ON_INIT |ADDR_TYPE_RT , + }, +}; + +static struct omap_hwmod_ocp_if omap3_l4_core__sr1 = { + .master = &omap3xxx_l4_core_hwmod, + .slave = &omap34xx_sr1_hwmod, + .clk =NULL , + .addr = omap34xx_sr1_addr_space, + .addr_cnt =ARRAY_SIZE (omap34xx_sr1_addr_space), + .user =OCP_USER_MPU , +}; + +/* L4 CORE -> SR1 interface */ +static struct omap_hwmod_addr_space omap34xx_sr2_addr_space[] = { + { + .pa_start =OMAP34XX_SR2_BASE , + .pa_end =OMAP34XX_SR2_BASE +SZ_1K -1 , + .flags =ADDR_MAP_ON_INIT |ADDR_TYPE_RT , + }, +}; + +static struct omap_hwmod_ocp_if omap3_l4_core__sr2 = { + .master = &omap3xxx_l4_core_hwmod, + .slave = &omap34xx_sr2_hwmod, + .clk =NULL , + .addr = omap34xx_sr2_addr_space, + .addr_cnt =ARRAY_SIZE (omap34xx_sr2_addr_space), + .user =OCP_USER_MPU , +}; +/* Slave interfaces on the L4_CORE interconnect */ static struct omap_hwmod_ocp_if *omap3xxx_l4_core_slaves[] = { &omap3xxx_l3__l4_core, + &omap3_l4_core__sr1, + &omap3_l4_core__sr2, };/* Master interfaces on the L4_CORE interconnect */
@@ -164,12 +204,66 @@ static struct omap_hwmod omap3xxx_mpu_hwmod = { .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430), }; +/* SR common */ +static struct omap_hwmod_sysc_fields omap34xx_sr_sysc_fields = { + .clkact_shift =20 , +}; + +static struct omap_hwmod_class_sysconfig omap34xx_sr_sysc = { + .sysc_offs =0x24 , + .sysc_flags = (SYSC_HAS_CLOCKACTIVITY |SYSC_NO_CACHE ), + .clockact =CLOCKACT_TEST_ICLK , + .sysc_fields = &omap34xx_sr_sysc_fields, +}; + +static struct omap_hwmod_class omap34xx_smartreflex_hwmod_class = { + .name ="smartreflex" , + .sysc = &omap34xx_sr_sysc, + .rev =1 , +}; + +/* SR1 */ +static struct omap_hwmod_ocp_if *omap34xx_sr1_slaves[] = { + &omap3_l4_core__sr1, +}; + +static struct omap_hwmod omap34xx_sr1_hwmod = { + .name ="sr1_hwmod" , + .class = &omap34xx_smartreflex_hwmod_class, + .mpu_irqs =NULL , + .sdma_chs =NULL , + .main_clk ="sr1_fck" , + .slaves = omap34xx_sr1_slaves, + .slaves_cnt =ARRAY_SIZE (omap34xx_sr1_slaves), + .omap_chip =OMAP_CHIP_INIT (CHIP_IS_OMAP3430 ), + .flags =HWMOD_SET_DEFAULT_CLOCKACT , +}; + +/* SR2 */ +static struct omap_hwmod_ocp_if *omap34xx_sr2_slaves[] = { + &omap3_l4_core__sr2, +}; + +static struct omap_hwmod omap34xx_sr2_hwmod = { + .name ="sr2_hwmod" , + .class = &omap34xx_smartreflex_hwmod_class, + .mpu_irqs =NULL , + .sdma_chs =NULL , + .main_clk ="sr2_fck" , + .slaves = omap34xx_sr2_slaves, + .slaves_cnt =ARRAY_SIZE (omap34xx_sr2_slaves), + .omap_chip =OMAP_CHIP_INIT (CHIP_IS_OMAP3430 ), + .flags =HWMOD_SET_DEFAULT_CLOCKACT , +}; +static __initdata struct omap_hwmod *omap3xxx_hwmods[] = { &omap3xxx_l3_hwmod, &omap3xxx_l4_core_hwmod, &omap3xxx_l4_per_hwmod, &omap3xxx_l4_wkup_hwmod, &omap3xxx_mpu_hwmod, + &omap34xx_sr1_hwmod, + &omap34xx_sr2_hwmod,NULL , };
Signature · 1 line
1.7.0.rc1.33.g07cf0f
PATCH v2 2/17 OMAP3: PM: Create list to keep track of various smartreflex instances.
This patch removes the pointer sr1, sr2 in smartreflex.c and instead creatse a list for keeping track of multiple smartreflex instances.. This makes it scalable for next gen OMAPs where there are more than two smartreflex modules.
--- arch/arm/mach-omap2/smartreflex.c | 114 ++++++++++++++++++++++++------------ 1 files changed, 76 insertions(+), 38 deletions(-)
arch/arm/mach-omap2/smartreflex.c +76 -38
@@ -26,6 +26,7 @@#include <linux/kobject.h> #include <linux/i2c/twl.h> #include <linux/io.h> +#include <linux/list.h> #include <plat/omap34xx.h> #include <plat/control.h>
@@ -51,9 +52,12 @@ struct omap_sr {u32 opp5_nvalue;u32 senp_mod, senn_mod;void __iomem *srbase_addr; -void __iomem *vpbase_addr; +struct list_head node; }; +/* sr_list contains all the instances of smartreflex module */ +static LIST_HEAD (sr_list); +#define SR_REGADDR (offs) (sr->srbase_addr + offset)static inline void sr_write_reg (struct omap_sr *sr,unsigned offset,u32 value)
@@ -78,6 +82,20 @@ static inline u32 sr_read_reg(struct omap_sr *sr, unsigned offset)return __raw_readl (SR_REGADDR (offset)); } +static struct omap_sr *_sr_lookup (int srid) +{ +struct omap_sr *sr_info, *temp_sr_info; + + sr_info =NULL ; +list_for_each_entry (temp_sr_info, &sr_list, node) { +if (srid == temp_sr_info->srid) { + sr_info = temp_sr_info; +break ; + } + } +return sr_info; +} +static int sr_clk_enable (struct omap_sr *sr) {if (clk_enable (sr->clk) !=0 ) {
@@ -151,11 +169,17 @@ static u8 get_vdd1_opp(void) {struct omap_opp *opp;unsigned long freq; +struct omap_sr *sr_info =_sr_lookup (SR1 ); -if (sr1.vdd_opp_clk ==NULL ||IS_ERR (sr1.vdd_opp_clk)) +if (!sr_info) { +pr_warning ("omap_sr struct corresponding to SR1 not found\n" ); +return 0 ; + } + +if (sr_info->vdd_opp_clk ==NULL ||IS_ERR (sr_info->vdd_opp_clk))return 0 ; - freq = sr1.vdd_opp_clk->rate; + freq = sr_info->vdd_opp_clk->rate; opp =opp_find_freq_ceil (OPP_MPU , &freq);if (IS_ERR (opp))return 0 ;
@@ -163,9 +187,9 @@ static u8 get_vdd1_opp(void)* Use higher freq voltage even if an exact match is not available * we are probably masking a clock framework bug, so warn */ -if (unlikely (freq != sr1.vdd_opp_clk->rate)) +if (unlikely (freq != sr_info->vdd_opp_clk->rate))pr_warning ("%s: Available freq %ld != dpll freq %ld.\n" , - __func__, freq, sr1.vdd_opp_clk->rate); + __func__, freq, sr_info->vdd_opp_clk->rate);return opp_get_opp_id (opp); }
@@ -174,11 +198,17 @@ static u8 get_vdd2_opp(void) {struct omap_opp *opp;unsigned long freq; +struct omap_sr *sr_info =_sr_lookup (SR2 ); + +if (!sr_info) { +pr_warning ("omap_sr struct corresponding to SR2 not found\n" ); +return 0 ; + } -if (sr2.vdd_opp_clk ==NULL ||IS_ERR (sr2.vdd_opp_clk)) +if (sr_info->vdd_opp_clk ==NULL ||IS_ERR (sr_info->vdd_opp_clk))return 0 ; - freq = sr2.vdd_opp_clk->rate; + freq = sr_info->vdd_opp_clk->rate; opp =opp_find_freq_ceil (OPP_L3 , &freq);if (IS_ERR (opp))return 0 ;
@@ -187,9 +217,9 @@ static u8 get_vdd2_opp(void)* Use higher freq voltage even if an exact match is not available * we are probably masking a clock framework bug, so warn */ -if (unlikely (freq != sr2.vdd_opp_clk->rate)) +if (unlikely (freq != sr_info->vdd_opp_clk->rate))pr_warning ("%s: Available freq %ld != dpll freq %ld.\n" , - __func__, freq, sr2.vdd_opp_clk->rate); + __func__, freq, sr_info->vdd_opp_clk->rate);return opp_get_opp_id (opp); }
@@ -694,14 +724,13 @@ static void sr_disable(struct omap_sr *sr)void sr_start_vddautocomap (int srid,u32 target_opp_no) { -struct omap_sr *sr =NULL ; +struct omap_sr *sr =_sr_lookup (srid); -if (srid ==SR1 ) - sr = &sr1; -else if (srid ==SR2 ) - sr = &sr2; -else +if (!sr) { +pr_warning ("omap_sr struct corresponding to SR%d not found\n" , + srid);return ; + }if (sr->is_sr_reset ==1 ) {sr_clk_enable (sr);
@@ -719,14 +748,13 @@ EXPORT_SYMBOL(sr_start_vddautocomap);int sr_stop_vddautocomap (int srid) { -struct omap_sr *sr =NULL ; +struct omap_sr *sr =_sr_lookup (srid); -if (srid ==SR1 ) - sr = &sr1; -else if (srid ==SR2 ) - sr = &sr2; -else -return -EINVAL ; +if (!sr) { +pr_warning ("omap_sr struct corresponding to SR%d not found\n" , + srid); +return false; + }if (sr->is_autocomp_active ==1 ) {sr_disable (sr);
@@ -744,14 +772,13 @@ EXPORT_SYMBOL(sr_stop_vddautocomap);void enable_smartreflex (int srid) {u32 target_opp_no =0 ; -struct omap_sr *sr =NULL ; +struct omap_sr *sr =_sr_lookup (srid); -if (srid ==SR1 ) - sr = &sr1; -else if (srid ==SR2 ) - sr = &sr2; -else +if (!sr) { +pr_warning ("omap_sr struct corresponding to SR%d not found\n" , + srid);return ; + }if (sr->is_autocomp_active ==1 ) {if (sr->is_sr_reset ==1 ) {
@@ -779,15 +806,13 @@ void enable_smartreflex(int srid)void disable_smartreflex (int srid) {u32 i =0 ; +struct omap_sr *sr =_sr_lookup (srid); -struct omap_sr *sr =NULL ; - -if (srid ==SR1 ) - sr = &sr1; -else if (srid ==SR2 ) - sr = &sr2; -else +if (!sr) { +pr_warning ("omap_sr struct corresponding to SR%d not found\n" , + srid);return ; + }if (sr->is_autocomp_active ==1 ) {if (sr->is_sr_reset ==0 ) {
@@ -920,7 +945,13 @@ int sr_voltagescale_vcbypass(u32 target_opp, u32 current_opp,static ssize_t omap_sr_vdd1_autocomp_show (struct kobject *kobj,struct kobj_attribute *attr,char *buf) { -return sprintf (buf,"%d\n" , sr1.is_autocomp_active); +struct omap_sr *sr_info =_sr_lookup (SR1 ); + +if (!sr_info) { +pr_warning ("omap_sr struct corresponding to SR1 not found\n" ); +return 0 ; + } +return sprintf (buf,"%d\n" , sr_info->is_autocomp_active); } static ssize_t omap_sr_vdd1_autocomp_store(struct kobject *kobj,
@@ -960,7 +991,13 @@ static struct kobj_attribute sr_vdd1_autocomp = {static ssize_t omap_sr_vdd2_autocomp_show (struct kobject *kobj,struct kobj_attribute *attr,char *buf) { -return sprintf (buf,"%d\n" , sr2.is_autocomp_active); +struct omap_sr *sr_info =_sr_lookup (SR2 ); + +if (!sr_info) { +pr_warning ("omap_sr struct corresponding to SR2 not found\n" ); +return 0 ; + } +return sprintf (buf,"%d\n" , sr_info->is_autocomp_active); } static ssize_t omap_sr_vdd2_autocomp_store(struct kobject *kobj,
@@ -1010,7 +1047,6 @@ static int __init omap3_sr_init(void) RdReg |=DCDC_GLOBAL_CFG_ENABLE_SRFLX ; ret |=twl_i2c_write_u8 (TWL4030_MODULE_PM_RECEIVER , RdReg,R_DCDC_GLOBAL_CFG ); -if (cpu_is_omap34xx ()) { sr1.clk =clk_get (NULL ,"sr1_fck" ); sr2.clk =clk_get (NULL ,"sr2_fck" );
@@ -1036,6 +1072,8 @@ static int __init omap3_sr_init(void) ret =sysfs_create_file (power_kobj, &sr_vdd2_autocomp.attr);if (ret)pr_err ("sysfs_create_file failed: %d\n" , ret); +list_add (&sr1.node, &sr_list); +list_add (&sr2.node, &sr_list);return 0 ; }
Signature · 1 line
1.7.0.rc1.33.g07cf0f
PATCH v2 3/17 OMAP3: PM: Convert smartreflex driver into a platform driver using hwmods and omap-device layer
This patch converts the exisitng smartreflex library into a platform driver with device , driver registrations using hardware mods. As part of this Ntarget values are passed as platform data.
--- arch/arm/mach-omap2/Makefile | 2 +- arch/arm/mach-omap2/smartreflex.c | 332 +++++++++++++------------------------ arch/arm/mach-omap2/smartreflex.h | 28 +++ arch/arm/mach-omap2/sr_device.c | 176 ++++++++++++++++++++ 4 files changed, 324 insertions(+), 214 deletions(-) create mode 100644 arch/arm/mach-omap2/sr_device.c
arch/arm/mach-omap2/Makefile +1 -1
@@ -48,7 +48,7 @@ obj-$(CONFIG_ARCH_OMAP2) += pm24xx.o obj-$(CONFIG_ARCH_OMAP2) += sleep24xx.o obj-$(CONFIG_ARCH_OMAP3) += pm34xx.o sleep34xx.o cpuidle34xx.o obj-$(CONFIG_PM_DEBUG) += pm-debug.o -obj-$(CONFIG_OMAP_SMARTREFLEX) += smartreflex.o +obj-$(CONFIG_OMAP_SMARTREFLEX) += sr_device.o smartreflex.o AFLAGS_sleep24xx.o :=-Wa,-march=armv6 AFLAGS_sleep34xx.o :=-Wa,-march=armv7-a
arch/arm/mach-omap2/smartreflex.c +119 -213
452 lines not on this page · raw message
arch/arm/mach-omap2/smartreflex.h +28 -0
@@ -14,6 +14,8 @@* published by the Free Software Foundation. */ +#include <linux/platform_device.h> +#define PHY_TO_OFF_PM_MASTER (p) (p - 0x36)#define PHY_TO_OFF_PM_RECIEVER (p) (p - 0x5b)#define PHY_TO_OFF_PM_INT (p) (p - 0x2e)
@@ -243,6 +245,32 @@ extern u32 current_vdd2_opp;* do anything. */ #ifdef CONFIG_OMAP_SMARTREFLEX +/** +* omap_smartreflex_data - Smartreflex platform data +* +* @senp_mod : SENPENABLE value for the sr +* @senn_mod : SENNENABLE value for sr +* @sr_nvalue : array of n target values for sr +* @no_opp : number of opp's for this SR +* @enable_on_init : whether this sr module needs to enabled at +* boot up or not +* @device_enable : fn pointer to be populated with omap_device +* enable API +* @device_shutdown : fn pointer to be populated with omap_device +* shutdown API +* @device_idle : fn pointer to be pouplated with omap_device idle API +*/ +struct omap_smartreflex_data { +u32 senp_mod; +u32 senn_mod; +u32 *sr_nvalue; +int no_opp; +bool enable_on_init; +int (*device_enable)(struct platform_device *pdev); +int (*device_shutdown)(struct platform_device *pdev); +int (*device_idle)(struct platform_device *pdev); +}; +void enable_smartreflex (int srid);void disable_smartreflex (int srid);int sr_voltagescale_vcbypass (u32 t_opp,u32 c_opp,u8 t_vsel,u8 c_vsel);
arch/arm/mach-omap2/sr_device.c new file +176 -0
176 lines not on this page · raw message
Signature · 1 line
1.7.0.rc1.33.g07cf0f
PATCH v2 4/17 OMAP3: PM: Move smartreflex autocompensation enable disable hooks to PM debugfs.
This patch moves the hooks to enable disable smartreflex autocompensation to pm debugfs from the /sys/power/.
To enable autocompensation for smartreflex SR<n> do
echo 1 > <path>/pm_debug/sr<n>_autocomp
To disable autocompensation for smartreflex SR<n> do
echo 0 > <path>/pm_debug/sr<n>_autocomp--- arch/arm/mach-omap2/pm-debug.c | 4 +- arch/arm/mach-omap2/smartreflex.c | 114 ++++++++++-------------------------- arch/arm/mach-omap2/smartreflex.h | 2 + 3 files changed, 36 insertions(+), 84 deletions(-)
arch/arm/mach-omap2/pm-debug.c +2 -2
@@ -162,7 +162,7 @@ void omap2_pm_dump(int mode, int resume, unsigned int us)static void pm_dbg_regset_store (u32 *ptr); -struct dentry *pm_dbg_dir; +struct dentry *pm_dbg_dir, *pm_dbg_main_dir;static int pm_dbg_init_done;
@@ -613,7 +613,7 @@ static int __init pm_dbg_init(void)S_IRUGO |S_IWUGO , d, &voltage_off_while_idle, &pm_dbg_option_fops); - + pm_dbg_main_dir = d; pm_dbg_init_done =1 ;return 0 ;
arch/arm/mach-omap2/smartreflex.c +32 -82
168 lines not on this page · raw message
arch/arm/mach-omap2/smartreflex.h +2 -0
@@ -16,6 +16,8 @@#include <linux/platform_device.h> +extern struct dentry *pm_dbg_main_dir; +#define PHY_TO_OFF_PM_MASTER (p) (p - 0x36)#define PHY_TO_OFF_PM_RECIEVER (p) (p - 0x5b)#define PHY_TO_OFF_PM_INT (p) (p - 0x2e)
Signature · 1 line
1.7.0.rc1.33.g07cf0f
PATCH v2 5/17 OMAP3: PM: Remove OPP id dependency from smartreflex driver
This patch removes get_vdd1_opp and get_vdd2_opp API's and replaces them with get_curr_vdd1_voltage and get_curr_vdd2_voltage API's. N-target values are now linked to voltages and the link bewtween voltage and n-target values is managed internally in smartreflex driver and sr_devices.c
get_curr_vdd1_voltage and get_curr_vdd2_voltage are added in smartreflex driver in this patch. These API's will be moved to the voltage driver in a later patch when voltage specific code is separated out of smartreflex.
--- arch/arm/mach-omap2/smartreflex.c | 219 ++++++++++++++---------------------- arch/arm/mach-omap2/smartreflex.h | 27 ++++- arch/arm/mach-omap2/sr_device.c | 88 ++++++++------- 3 files changed, 152 insertions(+), 182 deletions(-)
arch/arm/mach-omap2/smartreflex.c +85 -134
@@ -45,14 +45,14 @@#define SMARTREFLEX_NAME_LEN 16struct omap_sr { -int srid; -int is_sr_reset; -int is_autocomp_active; -struct clk *vdd_opp_clk; -u32 clk_length; -unsigned int irq; -struct platform_device *pdev; -struct list_head node; +int srid; +int is_sr_reset; +int is_autocomp_active; +u32 clk_length; +unsigned int irq; +struct platform_device *pdev; +struct omap_sr_volt_tuple *volt_tuple; +struct list_head node; };/* sr_list contains all the instances of smartreflex module */
@@ -119,64 +119,62 @@ static void sr_clk_disable(struct omap_sr *sr) sr->is_sr_reset =1 ; } -static u8 get_vdd1_opp (void ) +static unsigned long get_curr_vdd1_voltage (void ) {struct omap_opp *opp;unsigned long freq; -struct omap_sr *sr_info =_sr_lookup (SR1 ); +struct clk *dpll1_clk; -if (!sr_info) { -pr_warning ("omap_sr struct corresponding to SR1 not found\n" ); -return 0 ; - } - -if (sr_info->vdd_opp_clk ==NULL ||IS_ERR (sr_info->vdd_opp_clk)) + dpll1_clk =clk_get (NULL ,"dpll1_ck" ); +if (IS_ERR (dpll1_clk))return 0 ; - freq = sr_info->vdd_opp_clk->rate; - opp =opp_find_freq_ceil (OPP_MPU , &freq); + freq = dpll1_clk->rate; + opp =opp_find_freq_exact (OPP_MPU , freq,1 );if (IS_ERR (opp))return 0 ; -/* -* Use higher freq voltage even if an exact match is not available -* we are probably masking a clock framework bug, so warn -*/ -if (unlikely (freq != sr_info->vdd_opp_clk->rate)) -pr_warning ("%s: Available freq %ld != dpll freq %ld.\n" , - __func__, freq, sr_info->vdd_opp_clk->rate); -return opp_get_opp_id (opp); +return opp_get_voltage (opp); } -static u8 get_vdd2_opp (void ) +static unsigned long get_curr_vdd2_voltage (void ) {struct omap_opp *opp;unsigned long freq; -struct omap_sr *sr_info =_sr_lookup (SR2 ); +struct clk *l3_clk; -if (!sr_info) { -pr_warning ("omap_sr struct corresponding to SR2 not found\n" ); -return 0 ; - } - -if (sr_info->vdd_opp_clk ==NULL ||IS_ERR (sr_info->vdd_opp_clk)) + l3_clk =clk_get (NULL ,"l3_ick" ); +if (IS_ERR (l3_clk))return 0 ; - freq = sr_info->vdd_opp_clk->rate; - opp =opp_find_freq_ceil (OPP_L3 , &freq); + freq = l3_clk->rate; + opp =opp_find_freq_exact (OPP_L3 , freq,1 );if (IS_ERR (opp))return 0 ; -/* -* Use higher freq voltage even if an exact match is not available -* we are probably masking a clock framework bug, so warn -*/ -if (unlikely (freq != sr_info->vdd_opp_clk->rate)) -pr_warning ("%s: Available freq %ld != dpll freq %ld.\n" , - __func__, freq, sr_info->vdd_opp_clk->rate); -return opp_get_opp_id (opp); +return opp_get_voltage (opp); } +static int sr_match_volt (struct omap_sr *sr,unsigned long volt, +struct omap_sr_volt_data *volt_data) +{ +struct omap_smartreflex_data *pdata = sr->pdev->dev.platform_data; +int i; + +if (!pdata->sr_volt_data) { +pr_notice ("voltage table does not exist for SR %d\n" , sr->srid); +return false; + } +for (i =0 ; i < pdata->no_opp; i++) { +if (pdata->sr_volt_data[i].voltage == volt) { + *volt_data = pdata->sr_volt_data[i]; +return true; + } + } +pr_notice ("Unable to match the current voltage with \ +the voltage table for SR %d\n" , sr->srid); +return false; +}static void sr_set_clk_length (struct omap_sr *sr) {
@@ -211,21 +209,14 @@ static void sr_set_clk_length(struct omap_sr *sr)static void sr_configure_vp (int srid) { -u32 vpconfig; -u32 vsel; -int uvdc; -u32 target_opp_no; -struct omap_opp *opp; +u32 vpconfig, vsel; +unsigned long uvdc;if (srid ==SR1 ) { - target_opp_no =get_vdd1_opp (); -if (!target_opp_no) - target_opp_no =VDD1_OPP3 ; - - opp =opp_find_by_opp_id (OPP_MPU , target_opp_no); -BUG_ON (!opp);/* XXX ugh */ - - uvdc =opp_get_voltage (opp); + uvdc =get_curr_vdd1_voltage (); +if (!uvdc) +pr_err ("Something wrong.Current voltage not obtained \ +from OPP framework for SR %d!\n" , srid); vsel =omap_twl_uv_to_vsel (uvdc); vpconfig = PRM_VP1_CONFIG_ERROROFFSET |
@@ -267,14 +258,10 @@ static void sr_configure_vp(int srid) OMAP3_PRM_VP1_CONFIG_OFFSET); }else if (srid ==SR2 ) { - target_opp_no =get_vdd2_opp (); -if (!target_opp_no) - target_opp_no =VDD2_OPP3 ; - - opp =opp_find_by_opp_id (OPP_L3 , target_opp_no); -BUG_ON (!opp);/* XXX ugh */ - - uvdc =opp_get_voltage (opp); + uvdc =get_curr_vdd2_voltage (); +if (!uvdc) +pr_err ("Something wrong.Current voltage not obtained \ +from OPP framework for SR %d!\n" , srid); vsel =omap_twl_uv_to_vsel (uvdc); vpconfig = PRM_VP2_CONFIG_ERROROFFSET |
@@ -368,9 +355,8 @@ static void sr_configure(struct omap_sr *sr)static int sr_reset_voltage (int srid) { -struct omap_opp *opp;unsigned long uvdc; -u32 target_opp_no, vsel =0 ; +u32 vsel =0 ;u32 reg_addr =0 ;u32 loop_cnt =0 , retries_cnt =0 ;u32 vc_bypass_value;
@@ -379,17 +365,12 @@ static int sr_reset_voltage(int srid)u32 prm_vp1_voltage, prm_vp2_voltage;if (srid ==SR1 ) { - target_opp_no =get_vdd1_opp (); -if (!target_opp_no) { -pr_info ("Current OPP unknown: Cannot reset voltage\n" ); + uvdc =get_curr_vdd1_voltage (); +if (!uvdc) { +pr_err ("Something wrong.Current voltage not obtained \ +from OPP framework for SR %d!\n" , srid);return 1 ; } - - opp =opp_find_by_opp_id (OPP_MPU , target_opp_no); -if (!opp) -return 1 ; - - uvdc =opp_get_voltage (opp); vsel =omap_twl_uv_to_vsel (uvdc); reg_addr =R_VDD1_SR_CONTROL ;
@@ -397,17 +378,12 @@ static int sr_reset_voltage(int srid) OMAP3_PRM_VP1_VOLTAGE_OFFSET); t2_smps_steps =abs (vsel - prm_vp1_voltage); }else if (srid ==SR2 ) { - target_opp_no =get_vdd2_opp (); -if (!target_opp_no) { -pr_info ("Current OPP unknown: Cannot reset voltage\n" ); + uvdc =get_curr_vdd2_voltage (); +if (!uvdc) { +pr_err ("Something wrong.Current voltage not obtained \ +from OPP framework for SR %d!\n" , srid);return 1 ; } - - opp =opp_find_by_opp_id (OPP_L3 , target_opp_no); -if (!opp) -return 1 ; - - uvdc =opp_get_voltage (opp); vsel =omap_twl_uv_to_vsel (uvdc); reg_addr =R_VDD2_SR_CONTROL ;
@@ -452,40 +428,19 @@ static int sr_reset_voltage(int srid)return 0 ; } -static int sr_enable (struct omap_sr *sr,u32 target_opp_no) +static int sr_enable (struct omap_sr *sr,unsigned long volt) {u32 nvalue_reciprocal, v; -struct omap_opp *opp; -struct omap_smartreflex_data *pdata = sr->pdev->dev.platform_data; -int uvdc; +struct omap_sr_volt_data volt_data;char vsel; -if (sr->srid ==SR1 ) { - opp =opp_find_by_opp_id (OPP_MPU , target_opp_no); -if (!opp) -return false; - }else { - opp =opp_find_by_opp_id (OPP_L3 , target_opp_no); -if (!opp) -return false; - } - -if (target_opp_no > pdata->no_opp) { -pr_notice ("Wrong target opp for VDD %d\n" , sr->srid); -return false; - } - -if (!pdata->sr_nvalue) { -pr_notice ("N target values does not exist for SR%d\n" , - sr->srid); +if (!sr_match_volt (sr, volt, &volt_data))return false; - } - - nvalue_reciprocal = pdata->sr_nvalue[target_opp_no -1 ]; + nvalue_reciprocal = volt_data.sr_nvalue;if (nvalue_reciprocal ==0 ) { -pr_notice ("OPP%d doesn't support SmartReflex\n" , - target_opp_no); +pr_notice ("NVALUE = 0 at voltage %ld for Smartreflex %d\n" , + volt, sr->srid);return false; }
@@ -496,8 +451,7 @@ static int sr_enable(struct omap_sr *sr, u32 target_opp_no) (ERRCONFIG_VPBOUNDINTEN |ERRCONFIG_VPBOUNDINTST ), (ERRCONFIG_VPBOUNDINTEN | ERRCONFIG_VPBOUNDINTST)); - uvdc =opp_get_voltage (opp); - vsel =omap_twl_uv_to_vsel (uvdc); + vsel =omap_twl_uv_to_vsel (volt);if (sr->srid ==SR1 ) {/* set/latch init voltage */
@@ -583,7 +537,7 @@ static void sr_disable(struct omap_sr *sr) } -void sr_start_vddautocomap (int srid,u32 target_opp_no) +void sr_start_vddautocomap (int srid,unsigned long volt) {struct omap_sr *sr =_sr_lookup (srid);
@@ -599,7 +553,7 @@ void sr_start_vddautocomap(int srid, u32 target_opp_no) } sr->is_autocomp_active =1 ; -if (!sr_enable (sr, target_opp_no)) { +if (!sr_enable (sr, volt)) { sr->is_autocomp_active =0 ;if (sr->is_sr_reset ==1 )sr_clk_disable (sr);
@@ -632,7 +586,7 @@ EXPORT_SYMBOL(sr_stop_vddautocomap);void enable_smartreflex (int srid) { -u32 target_opp_no =0 ; +unsigned long curr_volt =0 ;struct omap_sr *sr =_sr_lookup (srid);if (!sr) {
@@ -647,18 +601,18 @@ void enable_smartreflex(int srid)sr_clk_enable (sr);if (srid ==SR1 ) - target_opp_no =get_vdd1_opp (); + curr_volt =get_curr_vdd1_voltage ();else if (srid ==SR2 ) - target_opp_no =get_vdd2_opp (); + curr_volt =get_curr_vdd2_voltage (); -if (!target_opp_no) { -pr_info ("Current OPP unknown \ +if (!curr_volt) { +pr_info ("Current voltage unknown \ Cannot configure SR\n" ); }sr_configure (sr); -if (!sr_enable (sr, target_opp_no)) +if (!sr_enable (sr, curr_volt))sr_clk_disable (sr); } }
@@ -793,10 +747,13 @@ int sr_voltagescale_vcbypass(u32 target_opp, u32 current_opp,udelay (t2_smps_delay);if (sr_status) { +unsigned long volt; + + volt = (target_vsel *12500 ) +600000 ;if (vdd ==VDD1_OPP ) -sr_start_vddautocomap (SR1 , target_opp_no); +sr_start_vddautocomap (SR1 , volt);else if (vdd ==VDD2_OPP ) -sr_start_vddautocomap (SR2 , target_opp_no); +sr_start_vddautocomap (SR2 , volt); }return 0 ;
@@ -829,13 +786,13 @@ static int omap_sr_autocomp_store(void *data, u64 val)if (val ==0 ) {sr_stop_vddautocomap (sr_info->srid); }else { -u32 current_opp; +unsigned long curr_volt;if (sr_info->srid ==SR1 ) - current_opp =get_vdd1_opp (); + curr_volt =get_curr_vdd1_voltage ();else - current_opp =get_vdd2_opp (); -sr_start_vddautocomap (sr_info->srid, current_opp); + curr_volt =get_curr_vdd2_voltage (); +sr_start_vddautocomap (sr_info->srid, curr_volt); }return 0 ; }
@@ -861,12 +818,6 @@ static int __devinit omap_smartreflex_probe(struct platform_device *pdev) sr_info->irq = odev->hwmods[0 ]->mpu_irqs[0 ].irq;sr_set_clk_length (sr_info); -if (sr_info->srid ==SR1 ) { - sr_info->vdd_opp_clk =clk_get (NULL ,"dpll1_ck" ); - }else { - sr_info->vdd_opp_clk =clk_get (NULL ,"l3_ick" ); - } -/* Create the debug fs enteries */ sprintf (name,"sr%d_autocomp" , sr_info->srid); (void) debugfs_create_file(name, S_IRUGO | S_IWUGO, pm_dbg_main_dir,
arch/arm/mach-omap2/smartreflex.h +20 -7
@@ -248,11 +248,23 @@ extern u32 current_vdd2_opp;*/ #ifdef CONFIG_OMAP_SMARTREFLEX /** +* omap_sr_volt_data - Smartreflex voltage specific data +* +* @voltage : The possible voltage value +* @sr_nvalue : Smartreflex N target value at voltage <voltage> +*/ +struct omap_sr_volt_data { +unsigned long voltage; +u32 sr_nvalue; +}; + +/** * omap_smartreflex_data - Smartreflex platform data * * @senp_mod : SENPENABLE value for the sr * @senn_mod : SENNENABLE value for sr -* @sr_nvalue : array of n target values for sr +* @sr_volt_data : array of various possible voltages and N target +* values for a particular SR. * @no_opp : number of opp's for this SR * @enable_on_init : whether this sr module needs to enabled at * boot up or not
@@ -263,11 +275,12 @@ extern u32 current_vdd2_opp;* @device_idle : fn pointer to be pouplated with omap_device idle API */ struct omap_smartreflex_data { -u32 senp_mod; -u32 senn_mod; -u32 *sr_nvalue; -int no_opp; -bool enable_on_init; +u32 senp_mod; +u32 senn_mod; +u32 *sr_nvalue; +struct omap_sr_volt_data *sr_volt_data; +int no_opp; +bool enable_on_init;int (*device_enable)(struct platform_device *pdev);int (*device_shutdown)(struct platform_device *pdev);int (*device_idle)(struct platform_device *pdev);
@@ -276,7 +289,7 @@ struct omap_smartreflex_data {void enable_smartreflex (int srid);void disable_smartreflex (int srid);int sr_voltagescale_vcbypass (u32 t_opp,u32 c_opp,u8 t_vsel,u8 c_vsel); -void sr_start_vddautocomap (int srid,u32 target_opp_no); +void sr_start_vddautocomap (int srid,unsigned long volt);int sr_stop_vddautocomap (int srid);#else static inline void enable_smartreflex (int srid) {}
arch/arm/mach-omap2/sr_device.c +47 -41
141 lines not on this page · raw message
Signature · 1 line
1.7.0.rc1.33.g07cf0f
PATCH v2 6/17 OMAP3: PM: Correcting API names in samrtreflex driver.
This patch corrects typo in some of the API names in smartreflex driver.
--- arch/arm/mach-omap2/pm34xx.c | 8 ++++---- arch/arm/mach-omap2/smartreflex.c | 26 +++++++++++++------------- arch/arm/mach-omap2/smartreflex.h | 8 ++++---- 3 files changed, 21 insertions(+), 21 deletions(-)
arch/arm/mach-omap2/pm34xx.c +4 -4
@@ -430,9 +430,9 @@ void omap_sram_idle(void)* Only needed if we are going to enter retention or off. */ if (mpu_next_state <=PWRDM_POWER_RET ) -disable_smartreflex (SR1 ); +omap_smartreflex_disable (SR1 );if (core_next_state <=PWRDM_POWER_RET ) -disable_smartreflex (SR2 ); +omap_smartreflex_disable (SR2 );/* CORE */ if (core_next_state <PWRDM_POWER_ON ) {
@@ -531,9 +531,9 @@ void omap_sram_idle(void)* retention or off */ if (mpu_next_state <=PWRDM_POWER_RET ) -enable_smartreflex (SR1 ); +omap_smartreflex_enable (SR1 );if (core_next_state <=PWRDM_POWER_RET ) -enable_smartreflex (SR2 ); +omap_smartreflex_enable (SR2 );/* PER */ if (per_next_state <PWRDM_POWER_ON ) {
arch/arm/mach-omap2/smartreflex.c +13 -13
@@ -537,7 +537,7 @@ static void sr_disable(struct omap_sr *sr) } -void sr_start_vddautocomap (int srid,unsigned long volt) +void sr_start_vddautocomp (int srid,unsigned long volt) {struct omap_sr *sr =_sr_lookup (srid);
@@ -559,9 +559,9 @@ void sr_start_vddautocomap(int srid, unsigned long volt)sr_clk_disable (sr); } } -EXPORT_SYMBOL (sr_start_vddautocomap); +EXPORT_SYMBOL (sr_start_vddautocomp); -int sr_stop_vddautocomap (int srid) +int sr_stop_vddautocomp (int srid) {struct omap_sr *sr =_sr_lookup (srid);
@@ -582,9 +582,9 @@ int sr_stop_vddautocomap(int srid)return false; } -EXPORT_SYMBOL (sr_stop_vddautocomap); +EXPORT_SYMBOL (sr_stop_vddautocomp); -void enable_smartreflex (int srid) +void omap_smartreflex_enable (int srid) {unsigned long curr_volt =0 ;struct omap_sr *sr =_sr_lookup (srid);
@@ -618,7 +618,7 @@ void enable_smartreflex(int srid) } } -void disable_smartreflex (int srid) +void omap_smartreflex_disable (int srid) {u32 i =0 ;struct omap_sr *sr =_sr_lookup (srid);
@@ -693,7 +693,7 @@ int sr_voltagescale_vcbypass(u32 target_opp, u32 current_opp, current_opp_no =get_opp_no (current_opp);if (vdd ==VDD1_OPP ) { - sr_status =sr_stop_vddautocomap (SR1 ); + sr_status =sr_stop_vddautocomp (SR1 ); t2_smps_steps =abs (target_vsel - current_vsel); prm_rmw_mod_reg_bits(OMAP3430_VC_CMD_ON_MASK,
@@ -703,7 +703,7 @@ int sr_voltagescale_vcbypass(u32 target_opp, u32 current_opp, reg_addr =R_VDD1_SR_CONTROL ; }else if (vdd ==VDD2_OPP ) { - sr_status =sr_stop_vddautocomap (SR2 ); + sr_status =sr_stop_vddautocomp (SR2 ); t2_smps_steps =abs (target_vsel - current_vsel); prm_rmw_mod_reg_bits(OMAP3430_VC_CMD_ON_MASK,
@@ -751,9 +751,9 @@ int sr_voltagescale_vcbypass(u32 target_opp, u32 current_opp, volt = (target_vsel *12500 ) +600000 ;if (vdd ==VDD1_OPP ) -sr_start_vddautocomap (SR1 , volt); +sr_start_vddautocomp (SR1 , volt);else if (vdd ==VDD2_OPP ) -sr_start_vddautocomap (SR2 , volt); +sr_start_vddautocomp (SR2 , volt); }return 0 ;
@@ -784,7 +784,7 @@ static int omap_sr_autocomp_store(void *data, u64 val)return 0 ; }if (val ==0 ) { -sr_stop_vddautocomap (sr_info->srid); +sr_stop_vddautocomp (sr_info->srid); }else {unsigned long curr_volt;
@@ -792,7 +792,7 @@ static int omap_sr_autocomp_store(void *data, u64 val) curr_volt =get_curr_vdd1_voltage (); else curr_volt =get_curr_vdd2_voltage (); -sr_start_vddautocomap (sr_info->srid, curr_volt); +sr_start_vddautocomp (sr_info->srid, curr_volt); }return 0 ; }
@@ -839,7 +839,7 @@ static int __devexit omap_smartreflex_remove(struct platform_device *pdev)/* Disable Autocompensation if enabled before removing the module */ if (sr_info->is_autocomp_active ==1 ) -sr_stop_vddautocomap (sr_info->srid); +sr_stop_vddautocomp (sr_info->srid);list_del (&sr_info->node);kfree (sr_info);
arch/arm/mach-omap2/smartreflex.h +4 -4
@@ -286,11 +286,11 @@ struct omap_smartreflex_data { int (*device_idle)(struct platform_device *pdev); }; -void enable_smartreflex (int srid); -void disable_smartreflex (int srid); +void omap_smartreflex_enable (int srid); +void omap_smartreflex_disable (int srid);int sr_voltagescale_vcbypass (u32 t_opp,u32 c_opp,u8 t_vsel,u8 c_vsel); -void sr_start_vddautocomap (int srid,unsigned long volt); -int sr_stop_vddautocomap (int srid); +void sr_start_vddautocomp (int srid,unsigned long volt); +int sr_stop_vddautocomp (int srid);#else static inline void enable_smartreflex (int srid) {}static inline void disable_smartreflex (int srid) {}
Signature · 1 line
1.7.0.rc1.33.g07cf0f
PATCH v2 7/17 OMAP3: PM: Smartreflex class related changes for smartreflex.c
OMAP3 smartreflex modules are capable of two different classes of implementaion -
Class-2: Continuous Software Calibration
Class-3: Continuous Hardware Calibration.
OMAP3 along with T2/Gaia supports the Class 3 implementaion. With a different PMIC it can support Class 2 implementaion also.
The idea behind this patch is that smartreflex.c should be able to support both the classes of Smartreflex and the class specific details for smartreflex should stay out of this file in a separate class file.
This patch introduces smartreflex class specific hooks in smartreflex.c. This patch only takes care of smartreflex enable disable hooks which differ between Class 2 and Class 3. There are some register setting changes between both the classes which will be taken care of in a later patch.
This will form the base for adding class specific drivers in later patches.
--- arch/arm/mach-omap2/smartreflex.c | 259 ++++++++++++++++++++---------------- arch/arm/mach-omap2/smartreflex.h | 44 ++++++- 2 files changed, 181 insertions(+), 122 deletions(-)
arch/arm/mach-omap2/smartreflex.c +144 -115
@@ -57,6 +57,7 @@ struct omap_sr {/* sr_list contains all the instances of smartreflex module */ static LIST_HEAD (sr_list); +static struct omap_smartreflex_class_data *sr_class;static inline void sr_write_reg (struct omap_sr *sr,unsigned offset,u32 value) {
@@ -428,12 +429,84 @@ static int sr_reset_voltage(int srid)return 0 ; } -static int sr_enable (struct omap_sr *sr,unsigned long volt) +static void sr_start_vddautocomp (int srid) +{ +struct omap_sr *sr =_sr_lookup (srid); + +if (!sr) { +pr_warning ("omap_sr struct corresponding to SR%d not found\n" , + srid); +return ; + } + +if (!sr_class || !(sr_class->enable)) { +pr_warning ("smartreflex class driver not registered\n" ); +return ; + } + +if (sr->is_sr_reset ==1 ) { +sr_clk_enable (sr); +sr_configure (sr); + } + + sr->is_autocomp_active =1 ; +if (!sr_class->enable (srid)) { + sr->is_autocomp_active =0 ; +if (sr->is_sr_reset ==1 ) +sr_clk_disable (sr); + } +} + +static void sr_stop_vddautocomp (int srid) +{ +struct omap_sr *sr =_sr_lookup (srid); + +if (!sr) { +pr_warning ("omap_sr struct corresponding to SR%d not found\n" , + srid); +return ; + } + +if (!sr_class || !(sr_class->disable)) { +pr_warning ("smartreflex class driver not registered\n" ); +return ; + } + +if (sr->is_autocomp_active ==1 ) { + sr_class->disable (srid); +sr_clk_disable (sr); + sr->is_autocomp_active =0 ; +/* Reset the volatage for current OPP */ +sr_reset_voltage (srid); + } +} + +/* Public Functions */ + +/** +* sr_enable : Enables the smartreflex module. +* @srid - The id of the sr module to be enabled. +* @target_opp_no - The OPP at which the Voltage domain associated with +* the smartreflex module is operating at. This is required only to program +* the correct Ntarget value. +* +* This API is to be called from the smartreflex class driver to +* enable a smartreflex module. Returns true on success.Returns false if the +* target opp id passed is wrong or if ntarget value is wrong. +*/ +int sr_enable (int srid,unsigned long volt) {u32 nvalue_reciprocal, v;struct omap_sr_volt_data volt_data; +struct omap_sr *sr =_sr_lookup (srid);char vsel; +if (!sr) { +pr_warning ("omap_sr struct corresponding to SR%d not found\n" , + srid); +return false; + } +if (!sr_match_volt (sr, volt, &volt_data))return false; nvalue_reciprocal = volt_data.sr_nvalue;
@@ -495,10 +568,24 @@ static int sr_enable(struct omap_sr *sr, unsigned long volt)return true; } -static void sr_disable (struct omap_sr *sr) +/** +* sr_disable : Disables the smartreflex module. +* @srid - The id of the sr module to be disabled. +* +* This API is to be called from the smartreflex class driver to +* disable a smartreflex module. +*/ +void sr_disable (int srid) { +struct omap_sr *sr =_sr_lookup (srid);u32 i =0 ; +if (!sr) { +pr_warning ("omap_sr struct corresponding to SR%d not found\n" , + srid); +return ; + } + sr->is_sr_reset =1 ;/* SRCONFIG - disable SR */
@@ -536,8 +623,17 @@ static void sr_disable(struct omap_sr *sr) } } - -void sr_start_vddautocomp (int srid,unsigned long volt) +/** +* omap_smartreflex_enable : API to enable SR clocks and to call into the +* registered smartreflex class enable API. +* @srid - The id of the sr module to be enabled. +* +* 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_smartreflex_enable (int srid) {struct omap_sr *sr =_sr_lookup (srid);
@@ -547,51 +643,8 @@ void sr_start_vddautocomp(int srid, unsigned long volt)return ; } -if (sr->is_sr_reset ==1 ) { -sr_clk_enable (sr); -sr_configure (sr); - } - - sr->is_autocomp_active =1 ; -if (!sr_enable (sr, volt)) { - sr->is_autocomp_active =0 ; -if (sr->is_sr_reset ==1 ) -sr_clk_disable (sr); - } -} -EXPORT_SYMBOL (sr_start_vddautocomp); - -int sr_stop_vddautocomp (int srid) -{ -struct omap_sr *sr =_sr_lookup (srid); - -if (!sr) { -pr_warning ("omap_sr struct corresponding to SR%d not found\n" , - srid); -return false; - } - -if (sr->is_autocomp_active ==1 ) { -sr_disable (sr); -sr_clk_disable (sr); - sr->is_autocomp_active =0 ; -/* Reset the volatage for current OPP */ -sr_reset_voltage (srid); -return true; - }else -return false; - -} -EXPORT_SYMBOL (sr_stop_vddautocomp); - -void omap_smartreflex_enable (int srid) -{ -unsigned long curr_volt =0 ; -struct omap_sr *sr =_sr_lookup (srid); - -if (!sr) { -pr_warning ("omap_sr struct corresponding to SR%d not found\n" , - srid); +if (!sr_class || !(sr_class->enable)) { +pr_warning ("smartreflex class driver not registered\n" );return ; }
@@ -599,28 +652,24 @@ void omap_smartreflex_enable(int srid)if (sr->is_sr_reset ==1 ) {/* Enable SR clks */ sr_clk_enable (sr); - -if (srid ==SR1 ) - curr_volt =get_curr_vdd1_voltage (); -else if (srid ==SR2 ) - curr_volt =get_curr_vdd2_voltage (); - -if (!curr_volt) { -pr_info ("Current voltage unknown \ -Cannot configure SR\n" ); - } -sr_configure (sr); - -if (!sr_enable (sr, curr_volt)) +if (!sr_class->enable (srid))sr_clk_disable (sr); } } } +/** +* omap_smartreflex_disable : API to disable SR clocks and to call into the +* registered smartreflex class disable API. +* @srid - The id of the sr module to be disabled. +* +* This API is to be called from the kernel in order to disable +* a particular smartreflex module. This API will in turn call +* into the registered smartreflex class disable API. +*/ void omap_smartreflex_disable (int srid) { -u32 i =0 ;struct omap_sr *sr =_sr_lookup (srid);if (!sr) {
@@ -629,53 +678,43 @@ void omap_smartreflex_disable(int srid)return ; } +if (!sr_class || !(sr_class->disable)) { +pr_warning ("smartreflex class driver not registered\n" ); +return ; + } +if (sr->is_autocomp_active ==1 ) {if (sr->is_sr_reset ==0 ) { - - sr->is_sr_reset =1 ; -/* SRCONFIG - disable SR */ -sr_modify_reg (sr,SRCONFIG ,SRCONFIG_SRENABLE , - ~SRCONFIG_SRENABLE ); - + sr_class->disable (srid);/* Disable SR clk */ sr_clk_disable (sr); -if (sr->srid ==SR1 ) { -/* Wait for VP idle before disabling VP */ -while ((!prm_read_mod_reg (OMAP3430_GR_MOD , -OMAP3_PRM_VP1_STATUS_OFFSET )) - && i++ <MAX_TRIES ) -udelay (1 ); - -if (i >=MAX_TRIES ) -pr_warning ("VP1 not idle, still going \ -ahead with VP1 disable\n" ); - -/* Disable VP1 */ -prm_clear_mod_reg_bits (PRM_VP1_CONFIG_VPENABLE , -OMAP3430_GR_MOD , -OMAP3_PRM_VP1_CONFIG_OFFSET ); - }else if (sr->srid ==SR2 ) { -/* Wait for VP idle before disabling VP */ -while ((!prm_read_mod_reg (OMAP3430_GR_MOD , -OMAP3_PRM_VP2_STATUS_OFFSET )) - && i++ <MAX_TRIES ) -udelay (1 ); - -if (i >=MAX_TRIES ) -pr_warning ("VP2 not idle, still going \ -ahead with VP2 disable\n" ); - -/* Disable VP2 */ -prm_clear_mod_reg_bits (PRM_VP2_CONFIG_VPENABLE , -OMAP3430_GR_MOD , -OMAP3_PRM_VP2_CONFIG_OFFSET ); - }/* Reset the volatage for current OPP */ sr_reset_voltage (srid); } } } +/** +* omap_sr_register_class : API to register a smartreflex class parameters. +* @class_data - The structure containing various sr class specific data. +* +* This API is to be called by the smartreflex class driver to register itself +* with the smartreflex driver during init. +*/ +void omap_sr_register_class (struct omap_smartreflex_class_data *class_data) +{ +if (!class_data) { +pr_warning ("Smartreflex class data passed is NULL\n" ); +return ; + } + +if (sr_class) { +pr_warning ("Smartreflex class driver already registered\n" ); +return ; + } + sr_class = class_data; +} +/* Voltage Scaling using SR VCBYPASS */ int sr_voltagescale_vcbypass (u32 target_opp,u32 current_opp,u8 target_vsel,u8 current_vsel)
@@ -747,13 +786,10 @@ int sr_voltagescale_vcbypass(u32 target_opp, u32 current_opp,udelay (t2_smps_delay);if (sr_status) { -unsigned long volt; - - volt = (target_vsel *12500 ) +600000 ;if (vdd ==VDD1_OPP ) -sr_start_vddautocomp (SR1 , volt); +sr_start_vddautocomp (SR1 );else if (vdd ==VDD2_OPP ) -sr_start_vddautocomp (SR2 , volt); +sr_start_vddautocomp (SR2 ); }return 0 ;
@@ -783,17 +819,10 @@ static int omap_sr_autocomp_store(void *data, u64 val) sr_info->srid);return 0 ; } -if (val ==0 ) { +if (val ==0 )sr_stop_vddautocomp (sr_info->srid); - }else { -unsigned long curr_volt; - -if (sr_info->srid ==SR1 ) - curr_volt =get_curr_vdd1_voltage (); -else - curr_volt =get_curr_vdd2_voltage (); -sr_start_vddautocomp (sr_info->srid, curr_volt); - } +else +sr_start_vddautocomp (sr_info->srid);return 0 ; }
arch/arm/mach-omap2/smartreflex.h +37 -7
61 lines not on this page · raw message
Signature · 1 line
1.7.0.rc1.33.g07cf0f
PATCH v2 8/17 OMAP3: PM: Adding smartreflex class 3 driver.
This patch adds smartreflex class 3 driver. This driver hooks up with the generic smartreflex driver smartreflex.c to abstract out class specific implementations out of the generic driver.
--- arch/arm/mach-omap2/Makefile | 1 + arch/arm/mach-omap2/smartreflex-class3.c | 48 ++++++++++++++++++++++++++++++ arch/arm/plat-omap/Kconfig | 11 ++++++- 3 files changed, 59 insertions(+), 1 deletions(-) create mode 100644 arch/arm/mach-omap2/smartreflex-class3.c
arch/arm/mach-omap2/Makefile +1 -0
@@ -49,6 +49,7 @@ obj-$(CONFIG_ARCH_OMAP2) += sleep24xx.o obj-$(CONFIG_ARCH_OMAP3) += pm34xx.o sleep34xx.o cpuidle34xx.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 AFLAGS_sleep24xx.o :=-Wa,-march=armv6 AFLAGS_sleep34xx.o :=-Wa,-march=armv7-a
arch/arm/mach-omap2/smartreflex-class3.c new file +48 -0
48 lines not on this page · raw message
arch/arm/plat-omap/Kconfig +10 -1
@@ -55,7 +55,7 @@ config OMAP_DEBUG_LEDS config OMAP_SMARTREFLEX bool "SmartReflex support" - depends on ARCH_OMAP3 && TWL4030_CORE && PM + depends on ARCH_OMAP3 && PM help Say Y if you want to enable SmartReflex.
@@ -70,6 +70,15 @@ config OMAP_SMARTREFLEX compensation for VDD1 and VDD2, user must write 1 to /sys/power/sr_vddX_autocomp, where X is 1 or 2. +config OMAP_SMARTREFLEX_CLASS3 + bool "Class 3 mode of Smartreflex Implementation" + depends on OMAP_SMARTREFLEX && TWL4030_CORE + help + Say Y to enable Class 3 implementation of Smartreflex + + Class 3 implementation of Smartreflex employs continuous hardware + voltage caliberation. + config OMAP_SMARTREFLEX_TESTING bool "Smartreflex testing support" depends on OMAP_SMARTREFLEX
Signature · 1 line
1.7.0.rc1.33.g07cf0f
PATCH v2 9/17 OMAP3: PM: Creating separate files for handling OMAP3 voltage related operations.
This patch creates voltage.c and voltage.h files and moves all voltage processor and voltage controller specific code from smartreflex.c and other places in the OMAP3 codebase into these two files.
This along with smartreflex class driver addition will make smartreflex.c a generic driver to support both Class 2 and Class 3 smartreflex implementaions.
--- arch/arm/mach-omap2/Makefile | 3 +- arch/arm/mach-omap2/board-3430sdp.c | 3 +- arch/arm/mach-omap2/pm.h | 7 - arch/arm/mach-omap2/pm34xx.c | 87 +----- arch/arm/mach-omap2/smartreflex-class3.c | 4 + arch/arm/mach-omap2/smartreflex.c | 378 +------------------- arch/arm/mach-omap2/smartreflex.h | 137 ------- arch/arm/mach-omap2/voltage.c | 601 ++++++++++++++++++++++++++++++ arch/arm/mach-omap2/voltage.h | 75 ++++ 9 files changed, 688 insertions(+), 607 deletions(-) create mode 100644 arch/arm/mach-omap2/voltage.c create mode 100644 arch/arm/mach-omap2/voltage.h
arch/arm/mach-omap2/Makefile +2 -1
@@ -46,7 +46,8 @@ obj-$(CONFIG_ARCH_OMAP2) += sdrc2xxx.o ifeq ($(CONFIG_PM),y) obj-$(CONFIG_ARCH_OMAP2) += pm24xx.o obj-$(CONFIG_ARCH_OMAP2) += sleep24xx.o -obj-$(CONFIG_ARCH_OMAP3) += pm34xx.o sleep34xx.o cpuidle34xx.o +obj-$(CONFIG_ARCH_OMAP3) += pm34xx.o sleep34xx.o cpuidle34xx.o \ + voltage.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
arch/arm/mach-omap2/board-3430sdp.c +2 -1
@@ -49,6 +49,7 @@#include "sdram-qimonda-hyb18m512160af-6.h" #include "hsmmc.h" #include "pm.h" +#include "voltage.h" #include "omap3-opp.h" #define SDP3430_TS_GPIO_IRQ_SDPV1 3
@@ -346,7 +347,7 @@ static void __init omap_3430sdp_init_irq(void) omap_board_config_size =ARRAY_SIZE (sdp3430_config);omap3_pm_init_opp_table ();omap3_pm_init_cpuidle (omap3_cpuidle_params_table); -omap3_pm_init_vc (&omap3_setuptime_table); +omap_voltage_init_vc (&omap3_setuptime_table);omap2_init_common_hw (hyb18m512160af6_sdrc_params,NULL );omap_init_irq ();omap_gpio_init ();
arch/arm/mach-omap2/pm.h +0 -7
@@ -57,13 +57,6 @@ struct prm_setup_vc {u16 vdd1_ret;u16 vdd1_off; }; -#ifdef CONFIG_PM -extern void omap3_pm_init_vc (struct prm_setup_vc *setup_vc); -#else -static inline void omap3_pm_init_vc (struct prm_setup_vc *setup_vc) -{ -} -#endif extern int omap3_pm_get_suspend_state (struct powerdomain *pwrdm);extern int omap3_pm_set_suspend_state (struct powerdomain *pwrdm,int state);
arch/arm/mach-omap2/pm34xx.c +3 -84
115 lines not on this page · raw message
arch/arm/mach-omap2/smartreflex-class3.c +4 -0
@@ -10,6 +10,7 @@*/ #include "smartreflex.h" +#include "voltage.h" static int sr_class3_enable (int id) {
@@ -24,12 +25,15 @@ static int sr_class3_enable(int id)return false; } +omap_voltageprocessor_enable (id);return sr_enable (id, volt); }static int sr_class3_disable (int id) { +omap_voltageprocessor_disable (id);sr_disable (id); +omap_reset_voltage (id);return true; }
arch/arm/mach-omap2/smartreflex.c +1 -377
469 lines not on this page · raw message
arch/arm/mach-omap2/smartreflex.h +0 -137
180 lines not on this page · raw message
arch/arm/mach-omap2/voltage.c new file +601 -0
601 lines not on this page · raw message
arch/arm/mach-omap2/voltage.h new file +75 -0
75 lines not on this page · raw message
Signature · 1 line
1.7.0.rc1.33.g07cf0f
PATCH v2 10/17 OMAP3: PM: Disabling Smartreflex across both frequency and voltage scaling during DVFS.
This patch disables smartreflex across both frequency and voltage scaling instead of just across voltage scaling as before. This is the hardware recommended practice.
This bug was first reported and solved on Nokia N900 code base by Nishanth Menon and Paul Walmsley.
This patch also does some changes in SRF to adapt to the new smartreflex and voltage driver.
--- arch/arm/mach-omap2/resource34xx.c | 27 ++++++++++----------------- arch/arm/mach-omap2/resource34xx.h | 1 - 2 files changed, 10 insertions(+), 18 deletions(-)
arch/arm/mach-omap2/resource34xx.c +10 -17
@@ -28,6 +28,7 @@#include <plat/opp_twl_tps.h> #include "smartreflex.h" +#include "voltage.h" #include "resource34xx.h" #include "pm.h" #include "cm.h"
@@ -331,12 +332,6 @@ static int program_opp(int res, enum opp_t opp_type, int target_level, {int i, ret =0 , raise;unsigned long freq; -#ifdef CONFIG_OMAP_SMARTREFLEX -unsigned long t_opp, c_opp; - - t_opp =ID_VDD (res) |ID_OPP_NO (target_level); - c_opp =ID_VDD (res) |ID_OPP_NO (current_level); -#endif /* See if have a freq associated, if not, invalid opp */ ret =opp_to_freq (&freq, opp_type, target_level);
@@ -348,15 +343,15 @@ static int program_opp(int res, enum opp_t opp_type, int target_level,else raise =0 ; +omap_smartreflex_disable (res); +for (i =0 ; i <2 ; i++) { -if (i == raise) +if (i == raise) { ret =program_opp_freq (res, target_level, current_level); -#ifdef CONFIG_OMAP_SMARTREFLEX - else { -u8 vc, vt; + }else {struct omap_opp *oppx; -unsigned long uvdc; +unsigned long uvdc_current, uvdc_target;/* * transitioning from good to good OPP
@@ -364,21 +359,19 @@ static int program_opp(int res, enum opp_t opp_type, int target_level,*/ oppx =opp_find_freq_exact (opp_type, freq, true);BUG_ON (IS_ERR (oppx)); - uvdc =opp_get_voltage (oppx); - vt =omap_twl_uv_to_vsel (uvdc); + uvdc_target =opp_get_voltage (oppx);BUG_ON (opp_to_freq (&freq, opp_type, current_level)); oppx =opp_find_freq_exact (opp_type, freq, true);BUG_ON (IS_ERR (oppx)); - uvdc =opp_get_voltage (oppx); - vc =omap_twl_uv_to_vsel (uvdc); + uvdc_current =opp_get_voltage (oppx);/* ok to scale.. */ - sr_voltagescale_vcbypass(t_opp, c_opp, vt, vc); +omap_voltage_scale (res, uvdc_target, uvdc_current); } -#endif } +omap_smartreflex_enable (res);return ret; }
arch/arm/mach-omap2/resource34xx.h +0 -1
@@ -30,7 +30,6 @@#include <plat/opp.h> #include <plat/omap34xx.h> -extern int sr_voltagescale_vcbypass (u32 t_opp,u32 c_opp,u8 t_vsel,u8 c_vsel);extern void lock_scratchpad_sem (void );extern void unlock_scratchpad_sem (void );
Signature · 1 line
1.7.0.rc1.33.g07cf0f
PATCH v2 11/17 OMAP3: PM: Cleaning up of smartreflex header file.
This patch cleans up smartreflex.h removing all unnecessary and duplicate definitions.
--- arch/arm/mach-omap2/smartreflex.h | 99 +++++++++++++++++++++--------------- 1 files changed, 58 insertions(+), 41 deletions(-)
arch/arm/mach-omap2/smartreflex.h +58 -41
@@ -18,20 +18,6 @@extern struct dentry *pm_dbg_main_dir; -#define PHY_TO_OFF_PM_RECIEVER (p) (p - 0x5b) - -/* SMART REFLEX REG ADDRESS OFFSET */ -#define SRCONFIG 0x00 -#define SRSTATUS 0x04 -#define SENVAL 0x08 -#define SENMIN 0x0C -#define SENMAX 0x10 -#define SENAVG 0x14 -#define AVGWEIGHT 0x18 -#define NVALUERECIPROCAL 0x1C -#define SENERROR 0x20 -#define ERRCONFIG 0x24 -/* SR Modules */ #define SR1 1#define SR2 2
@@ -39,37 +25,38 @@ extern struct dentry *pm_dbg_main_dir;#define GAIN_MAXLIMIT 16#define R_MAXLIMIT 256 -#define SR1_CLK_ENABLE BIT(6) -#define SR2_CLK_ENABLE BIT(7) +/* SMART REFLEX REG ADDRESS OFFSET */ +#define SRCONFIG 0x00 +#define SRSTATUS 0x04 +#define SENVAL 0x08 +#define SENMIN 0x0C +#define SENMAX 0x10 +#define SENAVG 0x14 +#define AVGWEIGHT 0x18 +#define NVALUERECIPROCAL 0x1C +#define SENERROR 0x20 +#define ERRCONFIG 0x24 -/* SRCONFIG */ -#define SR1_SRCONFIG_ACCUMDATA (0x1F4 << 22) -#define SR2_SRCONFIG_ACCUMDATA (0x1F4 << 22) - -#define SRCLKLENGTH_12MHZ_SYSCLK 0x3C -#define SRCLKLENGTH_13MHZ_SYSCLK 0x41 -#define SRCLKLENGTH_19MHZ_SYSCLK 0x60 -#define SRCLKLENGTH_26MHZ_SYSCLK 0x82 -#define SRCLKLENGTH_38MHZ_SYSCLK 0xC0 +/* Bit/Shift Positions */ +/* SRCONFIG */ +#define SRCONFIG_ACCUMDATA_SHIFT 22#define SRCONFIG_SRCLKLENGTH_SHIFT 12#define SRCONFIG_SENNENABLE_SHIFT 5#define SRCONFIG_SENPENABLE_SHIFT 3 +#define SRCONFIG_CLKCTRL_SHIFT 0 + +#define SRCONFIG_ACCUMDATA_MASK (0x3FF << 22)#define SRCONFIG_SRENABLE BIT(11)#define SRCONFIG_SENENABLE BIT(10)#define SRCONFIG_ERRGEN_EN BIT(9)#define SRCONFIG_MINMAXAVG_EN BIT(8) -#define SRCONFIG_DELAYCTRL BIT(2) -#define SRCONFIG_CLKCTRL (0x00 << 0)/* AVGWEIGHT */ -#define SR1_AVGWEIGHT_SENPAVGWEIGHT (0x03 << 2) -#define SR1_AVGWEIGHT_SENNAVGWEIGHT (0x03 << 0) - -#define SR2_AVGWEIGHT_SENPAVGWEIGHT BIT(2) -#define SR2_AVGWEIGHT_SENNAVGWEIGHT BIT(0) +#define AVGWEIGHT_SENPAVGWEIGHT_SHIFT 2 +#define AVGWEIGHT_SENNAVGWEIGHT_SHIFT 0/* NVALUERECIPROCAL */ #define NVALUERECIPROCAL_SENPGAIN_SHIFT 20
@@ -78,25 +65,55 @@ extern struct dentry *pm_dbg_main_dir;#define NVALUERECIPROCAL_RNSENN_SHIFT 0/* ERRCONFIG */ -#define SR_CLKACTIVITY_MASK (0x03 << 20) +#define ERRCONFIG_ERRWEIGHT_SHIFT 16 +#define ERRCONFIG_ERRMAXLIMIT_SHIFT 8 +#define ERRCONFIG_ERRMiNLIMIT_SHIFT 0 +#define SR_ERRWEIGHT_MASK (0x07 << 16)#define SR_ERRMAXLIMIT_MASK (0xFF << 8)#define SR_ERRMINLIMIT_MASK (0xFF << 0)#define ERRCONFIG_VPBOUNDINTEN BIT(31)#define ERRCONFIG_VPBOUNDINTST BIT(30) +#define ERRCONFIG_MCUACCUMINTEN BIT(29) +#define ERRCONFIG_MCUACCUMINTST BIT(28) +#define ERRCONFIG_MCUVALIDINTEN BIT(27) +#define ERRCONFIG_MCUVALIDINTST BIT(26) +#define ERRCONFIG_MCUBOUNDINTEN BIT(25) +#define ERRCONFIG_MCUBOUNDINTST BIT(24) +#define ERRCONFIG_MCUDISACKINTEN BIT(23) +#define ERRCONFIG_MCUDISACKINTST BIT(22) -#define SR1_ERRWEIGHT (0x07 << 16) -#define SR1_ERRMAXLIMIT (0x02 << 8) -#define SR1_ERRMINLIMIT (0xFA << 0) +/* Common Bit values */ -#define SR2_ERRWEIGHT (0x07 << 16) -#define SR2_ERRMAXLIMIT (0x02 << 8) -#define SR2_ERRMINLIMIT (0xF9 << 0) +#define SRCLKLENGTH_12MHZ_SYSCLK 0x3C +#define SRCLKLENGTH_13MHZ_SYSCLK 0x41 +#define SRCLKLENGTH_19MHZ_SYSCLK 0x60 +#define SRCLKLENGTH_26MHZ_SYSCLK 0x82 +#define SRCLKLENGTH_38MHZ_SYSCLK 0xC0 -/* Vmode control */ -#define R_DCDC_GLOBAL_CFG PHY_TO_OFF_PM_RECIEVER(0x61) +/* +* 3430 specific values. Maybe these should be passed from board file or +* pmic structures. +*/ +#define OMAP3430_SR_ACCUMDATA 0x1F4 + +#define OMAP3430_SR1_SENPAVGWEIGHT 0x03 +#define OMAP3430_SR1_SENNAVGWEIGHT 0x03 + +#define OMAP3430_SR2_SENPAVGWEIGHT 0x01 +#define OMAP3430_SR2_SENNAVGWEIGHT 0x01 +#define OMAP3430_SR_ERRWEIGHT 0x07 +#define OMAP3430_SR_ERRMAXLIMIT 0x02 +#define OMAP3430_SR1_ERRMINLIMIT 0xFA +#define OMAP3430_SR2_ERRMINLIMIT 0xF9 + +/* TODO:3630/OMAP4 values if it has to come from this file */ + +/* Info for enabling SR in T2/gaia. ToDo: Move it to twl4030_power.c */ +#define PHY_TO_OFF_PM_RECIEVER (p) (p - 0x5b) +#define R_DCDC_GLOBAL_CFG PHY_TO_OFF_PM_RECIEVER(0x61)/* R_DCDC_GLOBAL_CFG register, SMARTREFLEX_ENABLE values */ #define DCDC_GLOBAL_CFG_ENABLE_SRFLX 0x08
Signature · 1 line
1.7.0.rc1.33.g07cf0f
PATCH v2 12/17 OMAP3: PM: Configurations for Smartreflex Class 2 and Smartreflex Class 3
There are two separate modules in SmartReflex-AVS :
MinMaxAvg module and Error module. Class3 uses the Error module only. In Class2 you can choose between either module since it is software based. The registers are mapped to the modules as followed:
MinMaxAvg module: AccumData, MinMaxAvgEnable, MinMaxAvgValid,
MinMaxAvgAccumValid, SenVal, SenMin, SenMax, SenAverage, AverageWeight, MCUAccum, MCUValid, MCUBounds.
Error module: SenNGain, SenPGain, SenPRN, SenNRN, AvgError,
SenError, VPBounds, ErrWeight, ErrMaxLimit, ErrMinLimit.
Shared between both: SRClkLength, SREnable, SenEnable, SenNEnable,
SenPEnable, DelayCtrl, MCUDisableAck, ClkActivity.
This patch introduces class specific configuration of registers in smartreflex.c This also allows for choosing between Error module and Minmaxavg module for Class 2 SR. This patch allows allows for registering for smartreflex interrupt handler and notification of interrupts in case requested by the smartreflex class driver.
--- arch/arm/mach-omap2/smartreflex-class3.c | 1 + arch/arm/mach-omap2/smartreflex.c | 201 ++++++++++++++++++++++++------ arch/arm/mach-omap2/smartreflex.h | 22 ++++ 3 files changed, 187 insertions(+), 37 deletions(-)
arch/arm/mach-omap2/smartreflex-class3.c +1 -0
@@ -42,6 +42,7 @@ static int sr_class3_disable(int id)struct omap_smartreflex_class_data class3_data = { .enable = sr_class3_enable, .disable = sr_class3_disable, + .class_type =SR_CLASS3 , };static int __init sr_class3_init (void )
arch/arm/mach-omap2/smartreflex.c +164 -37
271 lines not on this page · raw message
arch/arm/mach-omap2/smartreflex.h +22 -0
@@ -124,6 +124,24 @@ extern struct dentry *pm_dbg_main_dir;#endif #ifdef CONFIG_OMAP_SMARTREFLEX +/* +* The smart reflex driver supports both CLASS2 and CLASS3 SR. +* The smartreflex class driver should pass the class type. +* Should be used to populate the class_type field of the +* omap_smartreflex_class_data structure. +*/ +#define SR_CLASS2 0x1 +#define SR_CLASS3 0x2 + +/* +* CLASS2 SR can use either the MINMAXAVG module or the ERROR module +* of the Smartreflex. Should be used to populate the mod_use field +* of omap_smartreflex_class_data structure is class_type is chosen +* as SR_CLASS2. +*/ +#define SR_USE_MINMAXAVG_MOD 0x1 +#define SR_USE_ERROR_MOD 0x2 +/** * omap_smartreflex_class_data : Structure to be populated by * Smartreflex class driver with corresponding class enable disable API's
@@ -135,6 +153,9 @@ extern struct dentry *pm_dbg_main_dir;* @notify_flags - specify the events to be notified to the class driver * @class_type - specify which smartreflex class. Can be used by the SR driver * to take any class based decisions. +* @calib_mode - specify whether to use the error module or minmaxavg module +* for smartreflex calibrations in case of class2 SR. In case of +* class 3 SR only error module is used. */ struct omap_smartreflex_class_data {int (*enable)(int sr_id);
@@ -142,6 +163,7 @@ struct omap_smartreflex_class_data {int (*notify)(int sr_id,u32 status);u8 notify_flags;u8 class_type; +u8 calib_mode; };/**
Signature · 1 line
1.7.0.rc1.33.g07cf0f
PATCH v2 13/17 OMAP3: PM: Support for enabling smartreflex autocompensation by default.
This patch adds support to pdata enable smartreflex autocompenstion during init based on enable_on_init flag passed as pdata.
This patch also adds enabling of autocompensation by default (setting enable_on_init flag to true) in case of ES3.1 OMAP3430 chip. In the current implementation
this step is kept in smartreflex.c itself.Later an API can be added so that the decision to enable autocompensation by default can be passed from the corresponding board files.
--- arch/arm/mach-omap2/smartreflex.c | 5 +++++ arch/arm/mach-omap2/sr_device.c | 16 +++++++++++++++- 2 files changed, 20 insertions(+), 1 deletions(-)
arch/arm/mach-omap2/smartreflex.c +5 -0
@@ -345,6 +345,7 @@ static void sr_stop_vddautocomp(int srid)static int sr_late_init (struct omap_sr *sr_info) {char name[SMARTREFLEX_NAME_LEN ]; +struct omap_smartreflex_data *pdata = sr_info->pdev->dev.platform_data;int ret =0 ; if (sr_class->class_type == SR_CLASS2 &&
@@ -358,6 +359,10 @@ static int sr_late_init(struct omap_sr *sr_info) handler for SR%d. Smartreflex will \ not function as desired\n", sr_info->srid); } + +if (pdata->enable_on_init) +sr_start_vddautocomp (sr_info->srid); +return ret; }
arch/arm/mach-omap2/sr_device.c +15 -1
@@ -162,7 +162,21 @@ static int __init omap_devinit_smartreflex(void)if (WARN_ON (!sr_data))return -ENOMEM ; - sr_data->enable_on_init = false; +/* +* OMAP3430 ES3.1 chips by default come with Efuse burnt +* with parameters required for full functionality of +* smartreflex AVS feature like ntarget values , sennenable +* and senpenable. So enable the SR AVS feature during boot up +* itself if it is a OMAP3430 ES3.1 chip. +*/ +if (cpu_is_omap343x ()) { +if (omap_rev () ==OMAP3430_REV_ES3_1 ) + sr_data->enable_on_init = true; +else + sr_data->enable_on_init = false; + }else { + sr_data->enable_on_init = false; + } sr_data->device_enable = omap_device_enable; sr_data->device_shutdown = omap_device_shutdown; sr_data->device_idle = omap_device_idle;
Signature · 1 line
1.7.0.rc1.33.g07cf0f
PATCH v2 14/17 OMAP3: PM: Correcting accessing of ERRCONFIG register in smartreflex.c
Smartreflex error config register is special as it contains certain status bits which if written a 1 into means a clear of those bits. This patch takes special care during modify of this register that no status bits in this register are accidently set to 1.
This issue was first reported by Nishanth Menon.
--- arch/arm/mach-omap2/smartreflex.c | 11 +++++++++++ arch/arm/mach-omap2/smartreflex.h | 6 ++++++ 2 files changed, 17 insertions(+), 0 deletions(-)
arch/arm/mach-omap2/smartreflex.c +11 -0
@@ -71,6 +71,17 @@ static inline void sr_modify_reg(struct omap_sr *sr, unsigned offset, u32 mask, reg_val =omap_hwmod_readl (odev->hwmods[0 ], offset); reg_val &= ~mask; +/* +* Smartreflex error config register is special as it contains +* certain status bits which if written a 1 into means a clear +* of those bits. So in order to make sure no accidental write of +* 1 happens to those status bits, do a clear of them in the read +* value. Now if there is an actual reguest to write to these bits +* they will be set in the nex step. +*/ +if (offset ==ERRCONFIG ) + reg_val &= ~ERRCONFIG_STATUS_MASK ; + reg_val |= value;omap_hwmod_writel (reg_val, odev->hwmods[0 ], offset);
arch/arm/mach-omap2/smartreflex.h +6 -0
@@ -84,6 +84,12 @@ extern struct dentry *pm_dbg_main_dir;#define ERRCONFIG_MCUDISACKINTEN BIT(23)#define ERRCONFIG_MCUDISACKINTST BIT(22) +#define ERRCONFIG_STATUS_MASK (ERRCONFIG_VPBOUNDINTST | \ + ERRCONFIG_MCUACCUMINTST | \ + ERRCONFIG_MCUVALIDINTST | \ + ERRCONFIG_MCUBOUNDINTST | \ + ERRCONFIG_MCUDISACKINTST) +/* Common Bit values */ #define SRCLKLENGTH_12MHZ_SYSCLK 0x3C
Signature · 1 line
1.7.0.rc1.33.g07cf0f
PATCH v2 15/17 OMAP3: PM: Implement latest h/w recommendations for SR and VP registers and SR VP enable disable sequence.
This patch introduces OMAP3 specific values for Smartreflex and Voltage processor registers as per the latest TI recommendations. This patch also improves the smartreflex and voltage processor enable disable sequences as per the latest recommendations.
These recommendations were first formed based on experimentations on N900 platform and were implemented in the N900 codebase base first by Nishanth Menon and Paul Walmsley.
--- arch/arm/mach-omap2/smartreflex.c | 72 ++++++++++++++++++++++++----- arch/arm/mach-omap2/smartreflex.h | 9 ++- arch/arm/mach-omap2/voltage.c | 93 +++++++++++++++++++++++++++++++----- arch/arm/mach-omap2/voltage.h | 16 ++++--- 4 files changed, 155 insertions(+), 35 deletions(-)
arch/arm/mach-omap2/smartreflex.c +60 -12
@@ -27,13 +27,16 @@#include <linux/io.h> #include <linux/list.h> #include <linux/debugfs.h> +#include <linux/delay.h> #include <plat/omap_hwmod.h> #include <plat/omap_device.h> +#include <plat/common.h> #include "smartreflex.h" #define SMARTREFLEX_NAME_LEN 16 +#define SR_DISABLE_TIMEOUT 200struct omap_sr {int srid;
@@ -207,17 +210,33 @@ static void sr_set_regfields(struct omap_sr *sr)* fields will have to be populated using the pdata or pmic structure. */ if (cpu_is_omap343x ()) { +struct omap_smartreflex_data *pdata = + sr->pdev->dev.platform_data; sr->err_weight =OMAP3430_SR_ERRWEIGHT ; sr->err_maxlimit =OMAP3430_SR_ERRMAXLIMIT ; sr->accum_data =OMAP3430_SR_ACCUMDATA ;if (sr->srid ==SR1 ) { - sr->err_minlimit =OMAP3430_SR1_ERRMINLIMIT ; sr->senn_avgweight =OMAP3430_SR1_SENNAVGWEIGHT ; sr->senp_avgweight =OMAP3430_SR1_SENPAVGWEIGHT ; + pdata->sr_volt_data[0 ].sr_errminlimit = +OMAP3430_SR_ERRMINLIMIT_LOWOPP ; + pdata->sr_volt_data[1 ].sr_errminlimit = +OMAP3430_SR_ERRMINLIMIT_LOWOPP ; + pdata->sr_volt_data[2 ].sr_errminlimit = +OMAP3430_SR_ERRMINLIMIT_HIGHOPP ; + pdata->sr_volt_data[3 ].sr_errminlimit = +OMAP3430_SR_ERRMINLIMIT_HIGHOPP ; + pdata->sr_volt_data[4 ].sr_errminlimit = +OMAP3430_SR_ERRMINLIMIT_HIGHOPP ; }else { - sr->err_minlimit =OMAP3430_SR2_ERRMINLIMIT ; sr->senn_avgweight =OMAP3430_SR2_SENNAVGWEIGHT ; sr->senp_avgweight =OMAP3430_SR2_SENPAVGWEIGHT ; + pdata->sr_volt_data[0 ].sr_errminlimit = +OMAP3430_SR_ERRMINLIMIT_LOWOPP ; + pdata->sr_volt_data[1 ].sr_errminlimit = +OMAP3430_SR_ERRMINLIMIT_LOWOPP ; + pdata->sr_volt_data[2 ].sr_errminlimit = +OMAP3430_SR_ERRMINLIMIT_HIGHOPP ; } }/* TODO: 3630 and Omap4 specific bit field values */
@@ -307,11 +326,6 @@ static void sr_start_vddautocomp(int srid)return ; } -if (sr->is_sr_reset ==1 ) { -sr_clk_enable (sr); -sr_configure (sr); - } - sr->is_autocomp_active =1 ;if (!sr_class->enable (srid)) { sr->is_autocomp_active =0 ;
@@ -412,6 +426,13 @@ int sr_enable(int srid, unsigned long volt)return false; } +/* errminlimit is opp dependent and hence linked to voltage */ + sr->err_minlimit = volt_data.sr_errminlimit; + +/* Enable the clocks and configure SR */ +sr_clk_enable (sr); +sr_configure (sr); +sr_write_reg (sr,NVALUERECIPROCAL , nvalue_reciprocal);/* SRCONFIG - enable SR */ sr_modify_reg (sr,SRCONFIG ,SRCONFIG_SRENABLE ,SRCONFIG_SRENABLE );
@@ -428,6 +449,7 @@ int sr_enable(int srid, unsigned long volt)void sr_disable (int srid) {struct omap_sr *sr =_sr_lookup (srid); +int timeout =0 ;if (!sr) { pr_warning("omap_sr struct corresponding to SR%d not found\n",
@@ -435,10 +457,39 @@ void sr_disable(int srid)return ; } - sr->is_sr_reset =1 ; +/* Check if SR is already disabled. If yes do nothing */ +if (!(sr_read_reg (sr,SRCONFIG ) &SRCONFIG_SRENABLE )) +return ; + +/* Enable MCUDisableAcknowledge interrupt */ +sr_modify_reg (sr,ERRCONFIG , +ERRCONFIG_MCUDISACKINTEN ,ERRCONFIG_MCUDISACKINTEN ); +/* SRCONFIG - disable SR */ -sr_modify_reg (sr,SRCONFIG ,SRCONFIG_SRENABLE , ~SRCONFIG_SRENABLE ); +sr_modify_reg (sr,SRCONFIG ,SRCONFIG_SRENABLE ,0x0 ); + +/* Disable all other SR interrupts and clear the status */ +sr_modify_reg (sr,ERRCONFIG , + (ERRCONFIG_MCUACCUMINTEN |ERRCONFIG_MCUVALIDINTEN | +ERRCONFIG_MCUBOUNDINTEN |ERRCONFIG_VPBOUNDINTEN ), + (ERRCONFIG_MCUACCUMINTST |ERRCONFIG_MCUVALIDINTST | +ERRCONFIG_MCUBOUNDINTST |ERRCONFIG_VPBOUNDINTST )); +/* Wait for SR to be disabled. +* wait until ERRCONFIG.MCUDISACKINTST = 1. Typical latency is 1us. +*/ +omap_test_timeout ((sr_read_reg (sr,ERRCONFIG ) & +ERRCONFIG_MCUDISACKINTST ),SR_DISABLE_TIMEOUT , + timeout); + +if (timeout >=SR_DISABLE_TIMEOUT ) +pr_warning ("SR%d disable timedout\n" , srid); + +/* Disable MCUDisableAcknowledge interrupt & clear pending interrupt +* Also enable VPBOUND interrrupt +*/ +sr_modify_reg (sr,ERRCONFIG ,ERRCONFIG_MCUDISACKINTEN , +ERRCONFIG_MCUDISACKINTST ); }/**
@@ -468,9 +519,6 @@ void omap_smartreflex_enable(int srid)if (sr->is_autocomp_active ==1 ) {if (sr->is_sr_reset ==1 ) { -/* Enable SR clks */ -sr_clk_enable (sr); -sr_configure (sr);if (!sr_class->enable (srid))sr_clk_disable (sr); }
arch/arm/mach-omap2/smartreflex.h +6 -3
@@ -110,10 +110,10 @@ extern struct dentry *pm_dbg_main_dir;#define OMAP3430_SR2_SENPAVGWEIGHT 0x01#define OMAP3430_SR2_SENNAVGWEIGHT 0x01 -#define OMAP3430_SR_ERRWEIGHT 0x07 +#define OMAP3430_SR_ERRWEIGHT 0x04#define OMAP3430_SR_ERRMAXLIMIT 0x02 -#define OMAP3430_SR1_ERRMINLIMIT 0xFA -#define OMAP3430_SR2_ERRMINLIMIT 0xF9 +#define OMAP3430_SR_ERRMINLIMIT_HIGHOPP 0xF9 +#define OMAP3430_SR_ERRMINLIMIT_LOWOPP 0xF4/* TODO:3630/OMAP4 values if it has to come from this file */
@@ -177,10 +177,13 @@ struct omap_smartreflex_class_data {* * @voltage : The possible voltage value * @sr_nvalue : Smartreflex N target value at voltage <voltage> +* @sr_errminlimt : SR error min limit value. This value is different +* at differnet opp and thus is linked with voltage. */ struct omap_sr_volt_data {unsigned long voltage;u32 sr_nvalue; +u32 sr_errminlimit; };/**
arch/arm/mach-omap2/voltage.c +80 -13
159 lines not on this page · raw message
arch/arm/mach-omap2/voltage.h +9 -7
@@ -20,6 +20,7 @@#define VP_CONFIG_INITVDD OMAP3430_INITVDD#define VP_FORCEUPDATE OMAP3430_FORCEUPDATE#define VP_CONFIG_VPENABLE OMAP3430_VPENABLE +#define VP_ERRORGAIN_MASK OMAP3430_ERRORGAIN_MASK#define VP_INITVOLTAGE_MASK OMAP3430_INITVOLTAGE_MASK#define VP_INITVOLTAGE_SHIFT OMAP3430_INITVOLTAGE_SHIFT
@@ -50,16 +51,17 @@* board file or PMIC data structure */ #define OMAP3_VP_CONFIG_ERROROFFSET 0x00 -#define OMAP3_VP_CONFIG_ERRORGAIN 0x20 -#define OMAP3_VP_VSTEPMIN_SMPSWAITTIMEMIN 0x01F4 +#define OMAP3_VP_CONFIG_ERRORGAIN_LOWOPP 0x0C +#define OMAP3_VP_CONFIG_ERRORGAIN_HIGHOPP 0x18 +#define OMAP3_VP_VSTEPMIN_SMPSWAITTIMEMIN 0x3C#define OMAP3_VP_VSTEPMIN_VSTEPMIN 0x1 -#define OMAP3_VP_VSTEPMAX_SMPSWAITTIMEMAX 0x01F4 +#define OMAP3_VP_VSTEPMAX_SMPSWAITTIMEMAX 0x3C#define OMAP3_VP_VSTEPMAX_VSTEPMAX 0x04 -#define OMAP3_VP1_VLIMITTO_VDDMIN 0x0 -#define OMAP3_VP1_VLIMITTO_VDDMAX 0x3C +#define OMAP3_VP1_VLIMITTO_VDDMIN 0x14 +#define OMAP3_VP1_VLIMITTO_VDDMAX 0x42#define OMAP3_VP2_VLIMITTO_VDDMAX 0x2C -#define OMAP3_VP2_VLIMITTO_VDDMIN 0x0 -#define OMAP3_VP_VLIMITTO_TIMEOUT 0xFFFF +#define OMAP3_VP2_VLIMITTO_VDDMIN 0x18 +#define OMAP3_VP_VLIMITTO_TIMEOUT_US 0x200#define VOLTAGE_MOD OMAP3430_GR_MOD/* TODO OMAP4 VP register values if the same file is used for OMAP4*/
Signature · 1 line
1.7.0.rc1.33.g07cf0f
PATCH v2 16/17 OMAP3: PM: VP force update method of voltage scaling
This patch introduces VP force update method of voltage scaling and enables it by default. The older method of vc bypass is now configuratble through a menu config option. VP force update is the hardware recommended method of voltage scaling.
--- arch/arm/mach-omap2/voltage.c | 171 +++++++++++++++++++++++++++++++++++++++-- arch/arm/mach-omap2/voltage.h | 3 + 2 files changed, 166 insertions(+), 8 deletions(-)
arch/arm/mach-omap2/voltage.c +163 -8
@@ -35,6 +35,7 @@#include "voltage.h" #define VP_IDLE_TIMEOUT 200 +#define VP_TRANXDONE_TIMEOUT 300#define VDD1_LOWOPP_VOLT 1075000#define VDD2_LOWOPP_VOLT 1050000
@@ -77,6 +78,7 @@ struct vp_reg_info {u32 vp_vddmin;u32 vp_vddmax;u32 vp_timeout; +u32 vp_tranxdone_status; };static struct vp_reg_info *vp_reg;/*
@@ -140,6 +142,9 @@ static struct prm_setup_vc vc_config = { .vdd1_off = 0x00, /* 0.6v */ }; +/* By default VPFORCEUPDATE is the chosen method of voltage scaling */ +static bool voltscale_vpforceupdate = true; +static inline u32 voltage_read_reg (void __iomem *offset) {return __raw_readl (offset);
@@ -311,12 +316,16 @@ static void __init vp_reg_configure(int vp_id) OMAP3430_VDDMIN_SHIFT); vp_reg[vp_id].vp_vddmax = (OMAP3_VP1_VLIMITTO_VDDMAX <<OMAP3430_VDDMAX_SHIFT ); + vp_reg[vp_id].vp_tranxdone_status = +OMAP3430_VP1_TRANXDONE_ST ; }else if (vp_id ==VP2 ) { curr_volt =get_curr_vdd2_voltage (); vp_reg[vp_id].vp_vddmin = (OMAP3_VP2_VLIMITTO_VDDMIN <<OMAP3430_VDDMIN_SHIFT ); vp_reg[vp_id].vp_vddmax = (OMAP3_VP2_VLIMITTO_VDDMAX <<OMAP3430_VDDMAX_SHIFT ); + vp_reg[vp_id].vp_tranxdone_status = +OMAP3430_VP2_TRANXDONE_ST ; }else {pr_warning ("Voltage processor%d does not exisit\ in OMAP3 \n" , vp_id);
@@ -360,6 +369,127 @@ static void __init vp_reg_configure(int vp_id)/* TODO Extend this for OMAP4 ?? Or need a separate file */ } +/* VP force update method of voltage scaling */ +static int vp_forceupdate_scale_voltage (u32 vdd,unsigned long target_volt, +unsigned long current_volt) +{ +u32 smps_steps =0 , smps_delay =0 ; +u32 vpconfig; +int timeout =0 ; +int vp_id = vdd -1 ; +u8 target_vsel, current_vsel; + +if (!((vdd ==VDD1_OPP ) || (vdd ==VDD2_OPP ))) { +pr_warning ("Wrong vdd id passed to vp forceupdate\n" ); +return false; + } + + target_vsel =omap_twl_uv_to_vsel (target_volt); + current_vsel =omap_twl_uv_to_vsel (current_volt); + smps_steps =abs (target_vsel - current_vsel); + +if (vdd ==VDD1_OPP ) { +u32 vc_cmdval0; + + vc_cmdval0 =voltage_read_reg (vc_reg.cmdval0_reg); + vc_cmdval0 &= ~VC_CMD_ON_MASK ; + vc_cmdval0 |= (target_vsel <<VC_CMD_ON_SHIFT ); +voltage_write_reg (vc_reg.cmdval0_reg, vc_cmdval0); + }else if (vdd ==VDD2_OPP ) { +u32 vc_cmdval1; + + vc_cmdval1 =voltage_read_reg (vc_reg.cmdval1_reg); + vc_cmdval1 &= ~VC_CMD_ON_MASK ; + vc_cmdval1 |= (target_vsel <<VC_CMD_ON_SHIFT ); +voltage_write_reg (vc_reg.cmdval1_reg, vc_cmdval1); + } + +/* +* Clear all pending TransactionDone interrupt/status. Typical latency +* is <3us +*/ +while (timeout++ <VP_TRANXDONE_TIMEOUT ) { +voltage_write_reg (PRM_IRQSTATUS_REG , + vp_reg[vp_id].vp_tranxdone_status); +if (!(voltage_read_reg (PRM_IRQSTATUS_REG ) & + vp_reg[vp_id].vp_tranxdone_status)) +break ; +udelay (1 ); + } + +if (timeout >=VP_TRANXDONE_TIMEOUT ) { +pr_warning ("VP%d TRANXDONE timeout exceeded. Voltage change \ +aborted" , vdd); +return false; + } + +/* OMAP3430 has errorgain varying btw higher and lower opp's */ +if (cpu_is_omap34xx ()) + vp_reg[vp_id].vp_errorgain = (omap3_get_vp_errorgain ((vp_id), + target_volt) <<OMAP3430_ERRORGAIN_SHIFT ); + +/* Configure for VP-Force Update */ + vpconfig =voltage_read_reg (vp_reg[vp_id].vp_offs.vpconfig_reg); + vpconfig &= ~(VP_CONFIG_INITVDD |VP_FORCEUPDATE | +VP_INITVOLTAGE_MASK |VP_ERRORGAIN_MASK ); + vpconfig |= ((target_vsel <<VP_INITVOLTAGE_SHIFT ) | + vp_reg[vp_id].vp_errorgain); +voltage_write_reg (vp_reg[vp_id].vp_offs.vpconfig_reg, vpconfig); + +/* Trigger initVDD value copy to voltage processor */ + vpconfig |=VP_CONFIG_INITVDD ; +voltage_write_reg (vp_reg[vp_id].vp_offs.vpconfig_reg, vpconfig); + +/* Force update of voltage */ + vpconfig |=VP_FORCEUPDATE ; +voltage_write_reg (vp_reg[vp_id].vp_offs.vpconfig_reg, vpconfig); + + timeout =0 ; +/* +* Wait for TransactionDone. Typical latency is <200us. +* Depends on SMPSWAITTIMEMIN/MAX and voltage change +*/ +omap_test_timeout ((voltage_read_reg (PRM_IRQSTATUS_REG ) & + vp_reg[vp_id].vp_tranxdone_status), +VP_TRANXDONE_TIMEOUT , timeout); + +if (timeout >=VP_TRANXDONE_TIMEOUT ) +pr_warning ("VP%d TRANXDONE timeout exceeded. TRANXDONE never \ +got set after the voltage update.Serious error!!!!\n" , + vdd); + +/* Wait for voltage to settle with SW wait-loop */ + smps_delay = ((smps_steps *125 ) /40 ) +2 ; +udelay (smps_delay); + +/* +* Disable TransactionDone interrupt , clear all status, clear +* control registers +*/ + timeout =0 ; +while (timeout++ <VP_TRANXDONE_TIMEOUT ) { +voltage_write_reg (PRM_IRQSTATUS_REG , + vp_reg[vp_id].vp_tranxdone_status); +if (!(voltage_read_reg (PRM_IRQSTATUS_REG ) & + vp_reg[vp_id].vp_tranxdone_status)) +break ; +udelay (1 ); + } +if (timeout >=VP_TRANXDONE_TIMEOUT ) +pr_warning ("VP%d TRANXDONE timeout exceeded while trying to \ +clear the TRANXDONE status\n" , vdd); + + vpconfig =voltage_read_reg (vp_reg[vp_id].vp_offs.vpconfig_reg); +/* Clear initVDD copy trigger bit */ + vpconfig &= ~VP_CONFIG_INITVDD ; +voltage_write_reg (vp_reg[vp_id].vp_offs.vpconfig_reg, vpconfig); +/* Clear force bit */ + vpconfig &= ~VP_FORCEUPDATE ; +voltage_write_reg (vp_reg[vp_id].vp_offs.vpconfig_reg, vpconfig); + +return true; +} +/** * vc_bypass_scale_voltage - VC bypass method of voltage scaling */
@@ -447,7 +577,6 @@ static int vc_bypass_scale_voltage(u32 vdd, unsigned long target_volt,return true; } -static void __init init_voltageprocessors (void ) {int i;
@@ -537,9 +666,11 @@ void omap_voltageprocessor_enable(int vp_id)* This latching is required only if VC bypass method is used for * voltage scaling during dvfs. */ -vp_latch_vsel (vp_id -1 ); - vpconfig =voltage_read_reg (vp_reg[vp_id -1 ].vp_offs.vpconfig_reg); +if (!voltscale_vpforceupdate) +vp_latch_vsel (vp_id -1 ); +/* Enable VP */ + vpconfig =voltage_read_reg (vp_reg[vp_id -1 ].vp_offs.vpconfig_reg);voltage_write_reg (vp_reg[vp_id -1 ].vp_offs.vpconfig_reg, vpconfig |VP_CONFIG_VPENABLE ); }
@@ -589,11 +720,12 @@ void omap_voltageprocessor_disable(int vp_id)*/ int omap_voltage_scale (int vdd,unsigned long target_volt,unsigned long current_volt) -{/* -* TODO add VP force update method of voltage scaling -* and choose btw the two -*/ -return vc_bypass_scale_voltage (vdd, target_volt, current_volt); +{ +if (voltscale_vpforceupdate) +return vp_forceupdate_scale_voltage (vdd, target_volt, + current_volt); +else +return vc_bypass_scale_voltage (vdd, target_volt, current_volt); }/**
@@ -629,6 +761,29 @@ void omap_reset_voltage(int vdd) }/** +* omap_change_voltscale_method : API to change the voltage scaling method. +* @voltscale_method : the method to be used for voltage scaling. +* +* This API can be used by the board files to change the method of voltage +* scaling between vpforceupdate and vcbypass. The parameter values are +* defined in voltage.h +*/ +void omap_change_voltscale_method (int voltscale_method) +{ +switch (voltscale_method) { +case VOLTSCALE_VPFORCEUPDATE : + voltscale_vpforceupdate = true; +return ; +case VOLTSCALE_VCBYPASS : + voltscale_vpforceupdate = false; +return ; +default : +pr_warning ("Trying to change the method of voltage scaling \ +to an unsupported one!\n" ); + } +} + +/** * omap3_pm_init_vc - polpulates vc_config with values specified in board file * @setup_vc - the structure with various vc parameters *
arch/arm/mach-omap2/voltage.h +3 -0
@@ -14,7 +14,10 @@#define VP1 0#define VP2 1 +#define VOLTSCALE_VPFORCEUPDATE 1 +#define VOLTSCALE_VCBYPASS 2 +#define PRM_IRQSTATUS_REG OMAP3430_PRM_IRQSTATUS_MPU/* Generic VP definitions. Need to be redefined for OMAP4 */ #define VP_CONFIG_TIMEOUTEN OMAP3430_TIMEOUTEN#define VP_CONFIG_INITVDD OMAP3430_INITVDD
Signature · 1 line
1.7.0.rc1.33.g07cf0f
PATCH v2 17/17 OMAP3: PM: Enabling Smartreflex Class 3 driver by default in pm defconfig
This patch enables smartreflex class 3 driver in omap3_pm_defconfig.
--- arch/arm/configs/omap3_pm_defconfig | 1 + 1 files changed, 1 insertions(+), 0 deletions(-)
arch/arm/configs/omap3_pm_defconfig +1 -0
@@ -246,6 +246,7 @@ CONFIG_ARCH_OMAP4=y # OMAP Feature Selections # CONFIG_OMAP_SMARTREFLEX=y +CONFIG_OMAP_SMARTREFLEX_CLASS3=y # CONFIG_OMAP_SMARTREFLEX_TESTING is not set CONFIG_OMAP_RESET_CLOCKS=y CONFIG_OMAP_MUX=y
Signature · 1 line
1.7.0.rc1.33.g07cf0f
Re: [PATCHv2 03/17] OMAP3: PM: Convert smartreflex driver into a platform driver using hwmods and omap-device layer
In reply to Thara GopinathGopinath, Thara had written, on 03/18/2010 04:15 AM, the following:
Quoted 5 lines
This patch converts the exisitng smartreflex library into a platform driver with device , driver registrations using hardware mods. As part of this Ntarget values are passed as platform data.
Signed-off-by Thara Gopinath <[email protected]>
[...]
Quoted 26 lines
arch/arm/mach-omap2/sr_device.c new file +26
-0+/* +* Hard coded nvalues for testing purposes for OMAP3430, +* may cause device to hang! +*/ +static void __init omap34xx_sr_set_testing_nvalues ( +struct omap_smartreflex_data *sr_data,int srid) +{ +if (srid ==SR1 ) { + sr_data->no_opp =opp_get_opp_count (OPP_MPU ); + sr_data->sr_nvalue =kzalloc (sizeof (sr_data->sr_nvalue) * + sr_data->no_opp ,GFP_KERNEL ); +if (WARN_ON (!sr_data->sr_nvalue)) +return ; + + sr_data->senp_mod =0x03 ;/* SenN-M5 enabled */ + sr_data->senn_mod =0x03 ; +/* calculate nvalues for each opp */ + sr_data->sr_nvalue[4 ] =0x0 ; + sr_data->sr_nvalue[3 ] =0x0 ; + sr_data->sr_nvalue[2 ] =0x0 ; + sr_data->sr_nvalue[1 ] =0x0 ; + sr_data->sr_nvalue[0 ] =0x0 ; + }else if (srid ==SR2 ) { + sr_data->no_opp =3 ; + sr_data->sr_nvalue =kzalloc (sizeof (sr_data->sr_nvalue) * + sr_data->no_opp ,GFP_KERNEL );
arch/arm/mach-omap2/sr_device.c line 126
Quoted 10 lines
arch/arm/mach-omap2/sr_device.c new file +10
-0+if (WARN_ON (!sr_data->sr_nvalue)) +return ; + + sr_data->senp_mod =0x03 ;/* SenN-M5 enabled */ + sr_data->senn_mod =0x03 ; + sr_data->sr_nvalue[2 ] =0x0 ; + sr_data->sr_nvalue[1 ] =0x0 ; + sr_data->sr_nvalue[0 ] =0x0 ; + } +}
NAK to opp IDs, and IMHO if we can remove SRIDs as well, it will be good. Related discussion in http://marc.info/?t=126893797600009&r=1&w=2
Signature · 2 lines
Regards, Nishanth Menon
Paul Walmsley
maintainerRe: [PATCHv2 01/17] OMAP3: PM: Adding hwmod data for Smartreflex
In reply to Thara GopinathHello Thara,
a few comments:
Quoted 22 lines · Thara Gopinath
This patch adds the hwmod strucutres and other hwmod data for OMAP3 Smartreflex IP's.
Signed-off-by Thara Gopinath <[email protected]>--- arch/arm/mach-omap2/omap_hwmod_3xxx_data.c | 94 ++++++++++++++++++++++++++++ 1 files changed, 94 insertions(+), 0 deletions(-)arch/arm/mach-omap2/omap_hwmod_3xxx_data.c +2
-0@@ -35,6 +35,8 @@ static struct omap_hwmod omap3xxx_mpu_hwmod;static struct omap_hwmod omap3xxx_l3_hwmod;static struct omap_hwmod omap3xxx_l4_core_hwmod;static struct omap_hwmod omap3xxx_l4_per_hwmod; +static struct omap_hwmod omap34xx_sr1_hwmod; +static struct omap_hwmod omap34xx_sr2_hwmod;/* L3 -> L4_CORE interface */ static struct omap_hwmod_ocp_if omap3xxx_l3__l4_core = {
arch/arm/mach-omap2/omap_hwmod_3xxx_data.c static struct omap_hwmod_ocp_if omap3xxx_l4_core__l4_wkup = { · line 98
Quoted 9 lines
arch/arm/mach-omap2/omap_hwmod_3xxx_data.c +6
-0@@ -88,9 +90,47 @@ static struct omap_hwmod_ocp_if omap3xxx_l4_core__l4_wkup = { .user = OCP_USER_MPU | OCP_USER_SDMA, }; +/* L4 CORE -> SR1 interface */ +static struct omap_hwmod_addr_space omap34xx_sr1_addr_space[] = { + { + .pa_start =OMAP34XX_SR1_BASE , + .pa_end =OMAP34XX_SR1_BASE +SZ_1K -1 , + .flags =ADDR_MAP_ON_INIT |ADDR_TYPE_RT ,
Why ADDR_MAP_ON_INIT ? This should only be used for a handful of modules, such as SDRC, SMS, etc.
arch/arm/mach-omap2/omap_hwmod_3xxx_data.c static struct omap_hwmod_ocp_if omap3xxx_l4_core__l4_wkup = { · line 105
Quoted 7 lines
arch/arm/mach-omap2/omap_hwmod_3xxx_data.c +7
-0+ }, +}; + +static struct omap_hwmod_ocp_if omap3_l4_core__sr1 = { + .master = &omap3xxx_l4_core_hwmod, + .slave = &omap34xx_sr1_hwmod, + .clk =NULL ,
This should be "sr_l4_ick"
arch/arm/mach-omap2/omap_hwmod_3xxx_data.c static struct omap_hwmod_ocp_if omap3xxx_l4_core__l4_wkup = { · line 116
Quoted 11 lines
arch/arm/mach-omap2/omap_hwmod_3xxx_data.c +11
-0+ .addr = omap34xx_sr1_addr_space, + .addr_cnt = ARRAY_SIZE(omap34xx_sr1_addr_space), + .user = OCP_USER_MPU, +}; + +/* L4 CORE -> SR1 interface */ +static struct omap_hwmod_addr_space omap34xx_sr2_addr_space[] = { + { + .pa_start =OMAP34XX_SR2_BASE , + .pa_end =OMAP34XX_SR2_BASE +SZ_1K -1 , + .flags =ADDR_MAP_ON_INIT |ADDR_TYPE_RT ,
As above.
arch/arm/mach-omap2/omap_hwmod_3xxx_data.c static struct omap_hwmod_ocp_if omap3xxx_l4_core__l4_wkup = { · line 123
Quoted 7 lines
arch/arm/mach-omap2/omap_hwmod_3xxx_data.c +7
-0+ }, +}; + +static struct omap_hwmod_ocp_if omap3_l4_core__sr2 = { + .master = &omap3xxx_l4_core_hwmod, + .slave = &omap34xx_sr2_hwmod, + .clk =NULL ,
As above.
Quoted 16 lines
arch/arm/mach-omap2/omap_hwmod_3xxx_data.c +7
-0+ .addr = omap34xx_sr2_addr_space, + .addr_cnt = ARRAY_SIZE(omap34xx_sr2_addr_space), + .user = OCP_USER_MPU, +}; +/* Slave interfaces on the L4_CORE interconnect */ static struct omap_hwmod_ocp_if *omap3xxx_l4_core_slaves[] = { &omap3xxx_l3__l4_core, + &omap3_l4_core__sr1, + &omap3_l4_core__sr2, };/* Master interfaces on the L4_CORE interconnect */ @@ -164,12 +204,66 @@ static struct omap_hwmod omap3xxx_mpu_hwmod = { .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430), };
arch/arm/mach-omap2/omap_hwmod_3xxx_data.c static struct omap_hwmod omap3xxx_mpu_hwmod = { · line 215
Quoted 10 lines
arch/arm/mach-omap2/omap_hwmod_3xxx_data.c +9
-0+/* SR common */ +static struct omap_hwmod_sysc_fields omap34xx_sr_sysc_fields = { + .clkact_shift =20 , +}; + +static struct omap_hwmod_class_sysconfig omap34xx_sr_sysc = { + .sysc_offs =0x24 , + .sysc_flags = (SYSC_HAS_CLOCKACTIVITY |SYSC_NO_CACHE ), + .clockact =CLOCKACT_TEST_ICLK ,
What's the motivation behind this setting? My understanding is that this is supposed to be set by the clock framework as FCLKEN, ICLKEN bits are set and cleared. i.e., after *CLKEN is set to 1, the corresponding CLOCKACTIVITY bit would be set to 1; and before *CLKEN is set to 0, the corresponding CLOCKACTIVITY bit would be set to 0. Is there a need here to initialize the CLOCKACTIVITY bits upon init?
arch/arm/mach-omap2/omap_hwmod_3xxx_data.c static struct omap_hwmod omap3xxx_mpu_hwmod = { · line 222
Quoted 7 lines
arch/arm/mach-omap2/omap_hwmod_3xxx_data.c +7
-0+ .sysc_fields = &omap34xx_sr_sysc_fields, +}; + +static struct omap_hwmod_class omap34xx_smartreflex_hwmod_class = { + .name ="smartreflex" , + .sysc = &omap34xx_sr_sysc, + .rev =1 ,
The above three lines need to be tab-aligned, ideally to the tab stop in the previous structures.
Quoted 50 lines
arch/arm/mach-omap2/omap_hwmod_3xxx_data.c +38
-0+}; + +/* SR1 */ +static struct omap_hwmod_ocp_if *omap34xx_sr1_slaves[] = { + &omap3_l4_core__sr1, +}; + +static struct omap_hwmod omap34xx_sr1_hwmod = { + .name ="sr1_hwmod" , + .class = &omap34xx_smartreflex_hwmod_class, + .mpu_irqs =NULL , + .sdma_chs =NULL , + .main_clk ="sr1_fck" , + .slaves = omap34xx_sr1_slaves, + .slaves_cnt =ARRAY_SIZE (omap34xx_sr1_slaves), + .omap_chip =OMAP_CHIP_INIT (CHIP_IS_OMAP3430 ), + .flags =HWMOD_SET_DEFAULT_CLOCKACT , +}; + +/* SR2 */ +static struct omap_hwmod_ocp_if *omap34xx_sr2_slaves[] = { + &omap3_l4_core__sr2, +}; + +static struct omap_hwmod omap34xx_sr2_hwmod = { + .name ="sr2_hwmod" , + .class = &omap34xx_smartreflex_hwmod_class, + .mpu_irqs =NULL , + .sdma_chs =NULL , + .main_clk ="sr2_fck" , + .slaves = omap34xx_sr2_slaves, + .slaves_cnt =ARRAY_SIZE (omap34xx_sr2_slaves), + .omap_chip =OMAP_CHIP_INIT (CHIP_IS_OMAP3430 ), + .flags =HWMOD_SET_DEFAULT_CLOCKACT , +}; +static __initdata struct omap_hwmod *omap3xxx_hwmods[] = { &omap3xxx_l3_hwmod, &omap3xxx_l4_core_hwmod, &omap3xxx_l4_per_hwmod, &omap3xxx_l4_wkup_hwmod, &omap3xxx_mpu_hwmod, + &omap34xx_sr1_hwmod, + &omap34xx_sr2_hwmod,NULL , };Signature · 1 line
1.7.0.rc1.33.g07cf0f
- Paul
Gopinath, Thara had written, on 03/18/2010 04:15 AM, the following:
[..]
Quoted 5 lines
This patch series is based on Kevin's PM tree origin/pm-wip-opp branch and is dependent on the following patches not yet applied onto this branch.
http://patchwork.kernel.org/patch/81504/ http://patchwork.kernel.org/patch/81606/
The 2nd patch does not seem to apply anymore
see [1] - no more sysc_flags as it was queued to .34-rcX?
Signature · 4 lines
Regards, Nishanth Menon Ref: [1] http://git.kernel.org/?p=linux/kernel/git/khilman/linux-omap-pm.git;a=blob;f=arch/arm/plat-omap/include/plat/omap_hwmod.h;h=440b4164f2f65e8557713ce9fff2636ed02fe523;hb=pm-wip-opp#l258
Quoted 13 lines
Quoted 13 lines
-----Original Message-----
From: Menon, Nishanth
Sent: Friday, March 19, 2010 12:45 AM
To: Gopinath, Thara
Cc: [email protected]; [email protected]; [email protected]; Cousson, Benoit; Sripathy, Vishwanath; Sawant, Anand
Subject: Re: [PATCHv2 00/17] OMAP3: PM: Smartreflex and voltage revamp.Gopinath, Thara had written, on 03/18/2010 04:15 AM, the following:
[..]
Quoted 8 lines
Quoted 8 lines
Quoted 5 lines
This patch series is based on Kevin's PM tree origin/pm-wip-opp branch and is dependent on the following patches not yet applied onto this branch.
http://patchwork.kernel.org/patch/81504/ http://patchwork.kernel.org/patch/81606/The 2nd patch does not seem to apply anymore
see [1] - no more
sysc_flagsas it was queued to .34-rcX?
I do not understand this.. Second patch seems to apply for me on wip-opp branch off Kevin's tree
Quoted 8 lines
Quoted 8 lines
--
Regards,
Nishanth Menon
Ref:
[1]
http://git.kernel.org/?p=linux/kernel/git/khilman/linux-omap-pm.git;a=blob;f=arch/arm/plat-
omap/include/plat/omap_hwmod.h;h=440b4164f2f65e8557713ce9fff2636ed02fe523;hb=pm-wip-opp#l258
Gopinath, Thara had written, on 03/22/2010 09:39 AM, the following:
Quoted 15 lines
Quoted 15 lines
Quoted 15 lines
-----Original Message-----
From: Menon, Nishanth
Sent: Friday, March 19, 2010 12:45 AM
To: Gopinath, Thara
Cc: [email protected]; [email protected]; [email protected]; Cousson, Benoit; Sripathy, Vishwanath; Sawant, Anand
Subject: Re: [PATCHv2 00/17] OMAP3: PM: Smartreflex and voltage revamp.Gopinath, Thara had written, on 03/18/2010 04:15 AM, the following:
[..]Quoted 3 lines
This patch series is based on Kevin's PM tree origin/pm-wip-opp branch and is dependent on the following patches not yet applied onto this branch.
Quoted 7 lines
Quoted 5 lines
Quoted 5 lines
The 2nd patch does not seem to apply anymore
see [1] - no more
sysc_flagsas it was queued to .34-rcX?I do not understand this.. Second patch seems to apply for me on wip-opp branch off Kevin's tree
did you check the link i posted below? this is from pm-wip-opp branch and it does not seem to have the sysc_flags in it.. how would a patch that modifies sysc_flags work? I think there might be a different sequence to use your series.
Quoted 7 lines
Quoted 7 lines
Quoted 7 lines
--
Regards,
Nishanth Menon
Ref:
[1]
http://git.kernel.org/?p=linux/kernel/git/khilman/linux-omap-pm.git;a=blob;f=arch/arm/plat-
omap/include/plat/omap_hwmod.h;h=440b4164f2f65e8557713ce9fff2636ed02fe523;hb=pm-wip-opp#l258
Signature · 2 lines
Regards, Nishanth Menon
Quoted 11 lines · Nishanth Menon
Gopinath, Thara had written, on 03/22/2010 09:39 AM, the following:
Quoted 10 lines
Quoted 10 lines
Quoted 10 lines
Gopinath, Thara had written, on 03/18/2010 04:15 AM, the following:
[..]Quoted 5 lines
This patch series is based on Kevin's PM tree origin/pm-wip-opp branch and is dependent on the following patches not yet applied onto this branch.
http://patchwork.kernel.org/patch/81504/ http://patchwork.kernel.org/patch/81606/
Quoted 7 lines
Quoted 5 lines
Quoted 3 lines
Quoted 3 lines
The 2nd patch does not seem to apply anymore
see [1] - no more
sysc_flagsas it was queued to .34-rcX?I do not understand this.. Second patch seems to apply for me on wip-opp branch off Kevin's tree
did you check the link i posted below? this is from pm-wip-opp branch and it does not seem to have the
sysc_flagsin it..
I think you're looking at an old pm-wip-opp branch. The 2nd patch applies to current pm-wip-opp (albiet with some fuzz)
Kevin
Kevin Hilman had written, on 03/22/2010 11:50 AM, the following:
Quoted 14 lines
Quoted 12 lines · Nishanth Menon
Gopinath, Thara had written, on 03/22/2010 09:39 AM, the following:
Quoted 11 lines
Quoted 11 lines
Quoted 11 lines
Gopinath, Thara had written, on 03/18/2010 04:15 AM, the following:
[..]Quoted 5 lines
This patch series is based on Kevin's PM tree origin/pm-wip-opp branch and is dependent on the following patches not yet applied onto this branch.
http://patchwork.kernel.org/patch/81504/ http://patchwork.kernel.org/patch/81606/The 2nd patch does not seem to apply anymore
see [1] - no more
sysc_flagsas it was queued to .34-rcX?
Quoted 8 lines
Quoted 3 lines
Quoted 1 line
I do not understand this.. Second patch seems to apply for me on wip-opp branch off Kevin's tree
did you check the link i posted below? this is from pm-wip-opp branch and it does not seem to have the
sysc_flagsin it..I think you're looking at an old pm-wip-opp branch. The 2nd patch applies to current pm-wip-opp (albiet with some fuzz)
Kevin
http://git.kernel.org/?p=linux/kernel/git/khilman/linux-omap-pm.git;a=summary
4 days ago pm-wip-opp shortlog | log | tree
Ref[1]
Aaah.. indeed.. my apologies.
Signature · 4 lines
Regards, Nishanth Menon [1]: http://git.kernel.org/?p=linux/kernel/git/khilman/linux-omap-pm.git;a=blob;f=arch/arm/plat-omap/include/plat/omap_hwmod.h;h=440b4164f2f65e8557713ce9fff2636ed02fe523;hb=pm-wip-opp#l293