diff options
author | Paul Walmsley <paul@pwsan.com> | 2011-03-10 22:17:45 -0700 |
---|---|---|
committer | Paul Walmsley <paul@pwsan.com> | 2011-03-10 22:17:45 -0700 |
commit | c0718df4d666cc5fd8837ac93c82995a17bfdbf5 (patch) | |
tree | 32df3f7405be2be07bdb1c6b98ebc0b143cf6571 | |
parent | e1d6f4729e9fd46efa1029b6e806bb8b6c24e776 (diff) |
OMAP2+: voltage: reorganize, split code from data
This is a first pass at reorganizing mach-omap2/voltage.c:
- Separate almost all of the data from the code of mach-omap2/voltage.c.
The code remains in mach-omap2/voltage.c. The data goes into one
of several places, depending on what type of data it is:
- Silicon process/validation data: mach-omap2/opp*_data.c
- VC (Voltage Controller) data: mach-omap2/vc*_data.c
- VP (Voltage Processor) data: mach-omap2/vp*_data.c
- Voltage domain data: mach-omap2/voltagedomains*_data.c
The ultimate goal is for all this data to be autogenerated, the same
way we autogenerate the rest of our data.
- Separate VC and VP common data from VDD-specific VC and VP data.
- Separate common voltage.c code from SoC-specific code; reuse common code.
- Reorganize structures to avoid unnecessary memory loss due to unpacked
fields.
There is much left to be done. VC code and VP code should be separated out
into vc*.c and vp*.c files. Many fields in the existing structures are
superfluous, and should be removed. Some code in voltage.c seems to be
duplicated; that code should be moved into functions of its own. Proper
voltage domain code should be created, as was done with the powerdomain
and clockdomains, and powerdomains should reference voltagedomains.
Thanks to Shweta Gulati <shweta.gulati@ti.com> for comments. Thanks
to Rajendra Nayak <rnayak@ti.com> for finding and fixing some bugs
that prevented OMAP4 from booting:
https://patchwork.kernel.org/patch/587311/
His patch has been folded into this one to avoid breaking OMAP4
between patches. Thanks also to Kevin Hilman <khilman@ti.com> for
finding and fixing a compile problem when !CONFIG_PM:
http://www.spinics.net/lists/arm-kernel/msg118067.html
His patch has also been folded into this one to avoid breaking
!CONFIG_PM builds.
Signed-off-by: Paul Walmsley <paul@pwsan.com>
Cc: Shweta Gulati <shweta.gulati@ti.com>
Cc: Rajendra Nayak <rnayak@ti.com>
Cc: Kevin Hilman <khilman@ti.com>
-rw-r--r-- | arch/arm/mach-omap2/Makefile | 22 | ||||
-rw-r--r-- | arch/arm/mach-omap2/omap_opp_data.h | 24 | ||||
-rw-r--r-- | arch/arm/mach-omap2/opp3xxx_data.c | 66 | ||||
-rw-r--r-- | arch/arm/mach-omap2/opp4xxx_data.c | 43 | ||||
-rw-r--r-- | arch/arm/mach-omap2/vc.h | 83 | ||||
-rw-r--r-- | arch/arm/mach-omap2/vc3xxx_data.c | 63 | ||||
-rw-r--r-- | arch/arm/mach-omap2/vc44xx_data.c | 75 | ||||
-rw-r--r-- | arch/arm/mach-omap2/voltage.c | 1017 | ||||
-rw-r--r-- | arch/arm/mach-omap2/voltage.h | 89 | ||||
-rw-r--r-- | arch/arm/mach-omap2/voltagedomains3xxx_data.c | 95 | ||||
-rw-r--r-- | arch/arm/mach-omap2/voltagedomains44xx_data.c | 102 | ||||
-rw-r--r-- | arch/arm/mach-omap2/vp.h | 143 | ||||
-rw-r--r-- | arch/arm/mach-omap2/vp3xxx_data.c | 82 | ||||
-rw-r--r-- | arch/arm/mach-omap2/vp44xx_data.c | 100 |
14 files changed, 1226 insertions, 778 deletions
diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile index c5b1be9b732..ea1e26f58b9 100644 --- a/arch/arm/mach-omap2/Makefile +++ b/arch/arm/mach-omap2/Makefile @@ -59,10 +59,10 @@ endif # Power Management ifeq ($(CONFIG_PM),y) obj-$(CONFIG_ARCH_OMAP2) += pm24xx.o -obj-$(CONFIG_ARCH_OMAP2) += sleep24xx.o pm_bus.o voltage.o -obj-$(CONFIG_ARCH_OMAP3) += pm34xx.o sleep34xx.o voltage.o \ +obj-$(CONFIG_ARCH_OMAP2) += sleep24xx.o pm_bus.o +obj-$(CONFIG_ARCH_OMAP3) += pm34xx.o sleep34xx.o \ cpuidle34xx.o pm_bus.o -obj-$(CONFIG_ARCH_OMAP4) += pm44xx.o voltage.o pm_bus.o +obj-$(CONFIG_ARCH_OMAP4) += pm44xx.o pm_bus.o obj-$(CONFIG_PM_DEBUG) += pm-debug.o obj-$(CONFIG_OMAP_SMARTREFLEX) += sr_device.o smartreflex.o obj-$(CONFIG_OMAP_SMARTREFLEX_CLASS3) += smartreflex-class3.o @@ -78,13 +78,25 @@ endif # PRCM obj-$(CONFIG_ARCH_OMAP2) += prcm.o cm2xxx_3xxx.o prm2xxx_3xxx.o -obj-$(CONFIG_ARCH_OMAP3) += prcm.o cm2xxx_3xxx.o prm2xxx_3xxx.o +obj-$(CONFIG_ARCH_OMAP3) += prcm.o cm2xxx_3xxx.o prm2xxx_3xxx.o \ + vc3xxx_data.o vp3xxx_data.o # XXX The presence of cm2xxx_3xxx.o on the line below is temporary and # will be removed once the OMAP4 part of the codebase is converted to # use OMAP4-specific PRCM functions. obj-$(CONFIG_ARCH_OMAP4) += prcm.o cm2xxx_3xxx.o cminst44xx.o \ cm44xx.o prcm_mpu44xx.o \ - prminst44xx.o + prminst44xx.o vc44xx_data.o \ + vp44xx_data.o + +# OMAP voltage domains +ifeq ($(CONFIG_PM),y) +voltagedomain-common := voltage.o +obj-$(CONFIG_ARCH_OMAP2) += $(voltagedomain-common) +obj-$(CONFIG_ARCH_OMAP3) += $(voltagedomain-common) \ + voltagedomains3xxx_data.o +obj-$(CONFIG_ARCH_OMAP4) += $(voltagedomain-common) \ + voltagedomains44xx_data.o +endif # OMAP powerdomain framework powerdomain-common += powerdomain.o powerdomain-common.o diff --git a/arch/arm/mach-omap2/omap_opp_data.h b/arch/arm/mach-omap2/omap_opp_data.h index 46ac27dd6c8..c784c12f98a 100644 --- a/arch/arm/mach-omap2/omap_opp_data.h +++ b/arch/arm/mach-omap2/omap_opp_data.h @@ -21,6 +21,8 @@ #include <plat/omap_hwmod.h> +#include "voltage.h" + /* * *BIG FAT WARNING*: * USE the following ONLY in opp data initialization common to an SoC. @@ -65,8 +67,30 @@ struct omap_opp_def { .u_volt = _uv, \ } +/* + * Initialization wrapper used to define SmartReflex process data + * XXX Is this needed? Just use C99 initializers in data files? + */ +#define VOLT_DATA_DEFINE(_v_nom, _efuse_offs, _errminlimit, _errgain) \ +{ \ + .volt_nominal = _v_nom, \ + .sr_efuse_offs = _efuse_offs, \ + .sr_errminlimit = _errminlimit, \ + .vp_errgain = _errgain \ +} + /* Use this to initialize the default table */ extern int __init omap_init_opp_table(struct omap_opp_def *opp_def, u32 opp_def_size); + +extern struct omap_volt_data omap34xx_vddmpu_volt_data[]; +extern struct omap_volt_data omap34xx_vddcore_volt_data[]; +extern struct omap_volt_data omap36xx_vddmpu_volt_data[]; +extern struct omap_volt_data omap36xx_vddcore_volt_data[]; + +extern struct omap_volt_data omap44xx_vdd_mpu_volt_data[]; +extern struct omap_volt_data omap44xx_vdd_iva_volt_data[]; +extern struct omap_volt_data omap44xx_vdd_core_volt_data[]; + #endif /* __ARCH_ARM_MACH_OMAP2_OMAP_OPP_DATA_H */ diff --git a/arch/arm/mach-omap2/opp3xxx_data.c b/arch/arm/mach-omap2/opp3xxx_data.c index 0486fce8a92..3bba9204a17 100644 --- a/arch/arm/mach-omap2/opp3xxx_data.c +++ b/arch/arm/mach-omap2/opp3xxx_data.c @@ -4,8 +4,9 @@ * Copyright (C) 2009-2010 Texas Instruments Incorporated - http://www.ti.com/ * Nishanth Menon * Kevin Hilman - * Copyright (C) 2010 Nokia Corporation. + * Copyright (C) 2010-2011 Nokia Corporation. * Eduardo Valentin + * Paul Walmsley * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -20,8 +21,71 @@ #include <plat/cpu.h> +#include "control.h" #include "omap_opp_data.h" +/* 34xx */ + +/* VDD1 */ + +#define OMAP3430_VDD_MPU_OPP1_UV 975000 +#define OMAP3430_VDD_MPU_OPP2_UV 1075000 +#define OMAP3430_VDD_MPU_OPP3_UV 1200000 +#define OMAP3430_VDD_MPU_OPP4_UV 1270000 +#define OMAP3430_VDD_MPU_OPP5_UV 1350000 + +struct omap_volt_data omap34xx_vddmpu_volt_data[] = { + VOLT_DATA_DEFINE(OMAP3430_VDD_MPU_OPP1_UV, OMAP343X_CONTROL_FUSE_OPP1_VDD1, 0xf4, 0x0c), + VOLT_DATA_DEFINE(OMAP3430_VDD_MPU_OPP2_UV, OMAP343X_CONTROL_FUSE_OPP2_VDD1, 0xf4, 0x0c), + VOLT_DATA_DEFINE(OMAP3430_VDD_MPU_OPP3_UV, OMAP343X_CONTROL_FUSE_OPP3_VDD1, 0xf9, 0x18), + VOLT_DATA_DEFINE(OMAP3430_VDD_MPU_OPP4_UV, OMAP343X_CONTROL_FUSE_OPP4_VDD1, 0xf9, 0x18), + VOLT_DATA_DEFINE(OMAP3430_VDD_MPU_OPP5_UV, OMAP343X_CONTROL_FUSE_OPP5_VDD1, 0xf9, 0x18), + VOLT_DATA_DEFINE(0, 0, 0, 0), +}; + +/* VDD2 */ + +#define OMAP3430_VDD_CORE_OPP1_UV 975000 +#define OMAP3430_VDD_CORE_OPP2_UV 1050000 +#define OMAP3430_VDD_CORE_OPP3_UV 1150000 + +struct omap_volt_data omap34xx_vddcore_volt_data[] = { + VOLT_DATA_DEFINE(OMAP3430_VDD_CORE_OPP1_UV, OMAP343X_CONTROL_FUSE_OPP1_VDD2, 0xf4, 0x0c), + VOLT_DATA_DEFINE(OMAP3430_VDD_CORE_OPP2_UV, OMAP343X_CONTROL_FUSE_OPP2_VDD2, 0xf4, 0x0c), + VOLT_DATA_DEFINE(OMAP3430_VDD_CORE_OPP3_UV, OMAP343X_CONTROL_FUSE_OPP3_VDD2, 0xf9, 0x18), + VOLT_DATA_DEFINE(0, 0, 0, 0), +}; + +/* 36xx */ + +/* VDD1 */ + +#define OMAP3630_VDD_MPU_OPP50_UV 1012500 +#define OMAP3630_VDD_MPU_OPP100_UV 1200000 +#define OMAP3630_VDD_MPU_OPP120_UV 1325000 +#define OMAP3630_VDD_MPU_OPP1G_UV 1375000 + +struct omap_volt_data omap36xx_vddmpu_volt_data[] = { + VOLT_DATA_DEFINE(OMAP3630_VDD_MPU_OPP50_UV, OMAP3630_CONTROL_FUSE_OPP50_VDD1, 0xf4, 0x0c), + VOLT_DATA_DEFINE(OMAP3630_VDD_MPU_OPP100_UV, OMAP3630_CONTROL_FUSE_OPP100_VDD1, 0xf9, 0x16), + VOLT_DATA_DEFINE(OMAP3630_VDD_MPU_OPP120_UV, OMAP3630_CONTROL_FUSE_OPP120_VDD1, 0xfa, 0x23), + VOLT_DATA_DEFINE(OMAP3630_VDD_MPU_OPP1G_UV, OMAP3630_CONTROL_FUSE_OPP1G_VDD1, 0xfa, 0x27), + VOLT_DATA_DEFINE(0, 0, 0, 0), +}; + +/* VDD2 */ + +#define OMAP3630_VDD_CORE_OPP50_UV 1000000 +#define OMAP3630_VDD_CORE_OPP100_UV 1200000 + +struct omap_volt_data omap36xx_vddcore_volt_data[] = { + VOLT_DATA_DEFINE(OMAP3630_VDD_CORE_OPP50_UV, OMAP3630_CONTROL_FUSE_OPP50_VDD2, 0xf4, 0x0c), + VOLT_DATA_DEFINE(OMAP3630_VDD_CORE_OPP100_UV, OMAP3630_CONTROL_FUSE_OPP100_VDD2, 0xf9, 0x16), + VOLT_DATA_DEFINE(0, 0, 0, 0), +}; + +/* OPP data */ + static struct omap_opp_def __initdata omap34xx_opp_def_list[] = { /* MPU OPP1 */ OPP_INITIALIZER("mpu", true, 125000000, 975000), diff --git a/arch/arm/mach-omap2/opp4xxx_data.c b/arch/arm/mach-omap2/opp4xxx_data.c index a11fa566d8e..fdee8d4186a 100644 --- a/arch/arm/mach-omap2/opp4xxx_data.c +++ b/arch/arm/mach-omap2/opp4xxx_data.c @@ -5,8 +5,9 @@ * Nishanth Menon * Kevin Hilman * Thara Gopinath - * Copyright (C) 2010 Nokia Corporation. + * Copyright (C) 2010-2011 Nokia Corporation. * Eduardo Valentin + * Paul Walmsley * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -21,8 +22,48 @@ #include <plat/cpu.h> +#include "control.h" #include "omap_opp_data.h" +/* + * Structures containing OMAP4430 voltage supported and various + * voltage dependent data for each VDD. + */ + +#define OMAP4430_VDD_MPU_OPP50_UV 930000 +#define OMAP4430_VDD_MPU_OPP100_UV 1100000 +#define OMAP4430_VDD_MPU_OPPTURBO_UV 1260000 +#define OMAP4430_VDD_MPU_OPPNITRO_UV 1350000 + +struct omap_volt_data omap44xx_vdd_mpu_volt_data[] = { + VOLT_DATA_DEFINE(OMAP4430_VDD_MPU_OPP50_UV, OMAP44XX_CONTROL_FUSE_MPU_OPP50, 0xf4, 0x0c), + VOLT_DATA_DEFINE(OMAP4430_VDD_MPU_OPP100_UV, OMAP44XX_CONTROL_FUSE_MPU_OPP100, 0xf9, 0x16), + VOLT_DATA_DEFINE(OMAP4430_VDD_MPU_OPPTURBO_UV, OMAP44XX_CONTROL_FUSE_MPU_OPPTURBO, 0xfa, 0x23), + VOLT_DATA_DEFINE(OMAP4430_VDD_MPU_OPPNITRO_UV, OMAP44XX_CONTROL_FUSE_MPU_OPPNITRO, 0xfa, 0x27), + VOLT_DATA_DEFINE(0, 0, 0, 0), +}; + +#define OMAP4430_VDD_IVA_OPP50_UV 930000 +#define OMAP4430_VDD_IVA_OPP100_UV 1100000 +#define OMAP4430_VDD_IVA_OPPTURBO_UV 1260000 + +struct omap_volt_data omap44xx_vdd_iva_volt_data[] = { + VOLT_DATA_DEFINE(OMAP4430_VDD_IVA_OPP50_UV, OMAP44XX_CONTROL_FUSE_IVA_OPP50, 0xf4, 0x0c), + VOLT_DATA_DEFINE(OMAP4430_VDD_IVA_OPP100_UV, OMAP44XX_CONTROL_FUSE_IVA_OPP100, 0xf9, 0x16), + VOLT_DATA_DEFINE(OMAP4430_VDD_IVA_OPPTURBO_UV, OMAP44XX_CONTROL_FUSE_IVA_OPPTURBO, 0xfa, 0x23), + VOLT_DATA_DEFINE(0, 0, 0, 0), +}; + +#define OMAP4430_VDD_CORE_OPP50_UV 930000 +#define OMAP4430_VDD_CORE_OPP100_UV 1100000 + +struct omap_volt_data omap44xx_vdd_core_volt_data[] = { + VOLT_DATA_DEFINE(OMAP4430_VDD_CORE_OPP50_UV, OMAP44XX_CONTROL_FUSE_CORE_OPP50, 0xf4, 0x0c), + VOLT_DATA_DEFINE(OMAP4430_VDD_CORE_OPP100_UV, OMAP44XX_CONTROL_FUSE_CORE_OPP100, 0xf9, 0x16), + VOLT_DATA_DEFINE(0, 0, 0, 0), +}; + + static struct omap_opp_def __initdata omap44xx_opp_def_list[] = { /* MPU OPP1 - OPP50 */ OPP_INITIALIZER("mpu", true, 300000000, 1100000), diff --git a/arch/arm/mach-omap2/vc.h b/arch/arm/mach-omap2/vc.h new file mode 100644 index 00000000000..e7767771de4 --- /dev/null +++ b/arch/arm/mach-omap2/vc.h @@ -0,0 +1,83 @@ +/* + * OMAP3/4 Voltage Controller (VC) structure and macro definitions + * + * Copyright (C) 2007, 2010 Texas Instruments, Inc. + * Rajendra Nayak <rnayak@ti.com> + * Lesly A M <x0080970@ti.com> + * Thara Gopinath <thara@ti.com> + * + * Copyright (C) 2008, 2011 Nokia Corporation + * Kalle Jokiniemi + * Paul Walmsley + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version + * 2 as published by the Free Software Foundation. + */ +#ifndef __ARCH_ARM_MACH_OMAP2_VC_H +#define __ARCH_ARM_MACH_OMAP2_VC_H + +#include <linux/kernel.h> + +/** + * struct omap_vc_common_data - per-VC register/bitfield data + * @cmd_on_mask: ON bitmask in PRM_VC_CMD_VAL* register + * @valid: VALID bitmask in PRM_VC_BYPASS_VAL register + * @smps_sa_reg: Offset of PRM_VC_SMPS_SA reg from PRM start + * @smps_volra_reg: Offset of PRM_VC_SMPS_VOL_RA reg from PRM start + * @bypass_val_reg: Offset of PRM_VC_BYPASS_VAL reg from PRM start + * @data_shift: DATA field shift in PRM_VC_BYPASS_VAL register + * @slaveaddr_shift: SLAVEADDR field shift in PRM_VC_BYPASS_VAL register + * @regaddr_shift: REGADDR field shift in PRM_VC_BYPASS_VAL register + * @cmd_on_shift: ON field shift in PRM_VC_CMD_VAL_* register + * @cmd_onlp_shift: ONLP field shift in PRM_VC_CMD_VAL_* register + * @cmd_ret_shift: RET field shift in PRM_VC_CMD_VAL_* register + * @cmd_off_shift: OFF field shift in PRM_VC_CMD_VAL_* register + * + * XXX One of cmd_on_mask and cmd_on_shift are not needed + * XXX VALID should probably be a shift, not a mask + */ +struct omap_vc_common_data { + u32 cmd_on_mask; + u32 valid; + u8 smps_sa_reg; + u8 smps_volra_reg; + u8 bypass_val_reg; + u8 data_shift; + u8 slaveaddr_shift; + u8 regaddr_shift; + u8 cmd_on_shift; + u8 cmd_onlp_shift; + u8 cmd_ret_shift; + u8 cmd_off_shift; +}; + +/** + * struct omap_vc_instance_data - VC per-instance data + * @vc_common: pointer to VC common data for this platform + * @smps_sa_mask: SA* bitmask in the PRM_VC_SMPS_SA register + * @smps_volra_mask: VOLRA* bitmask in the PRM_VC_VOL_RA register + * @smps_sa_shift: SA* field shift in the PRM_VC_SMPS_SA register + * @smps_volra_shift: VOLRA* field shift in the PRM_VC_VOL_RA register + * + * XXX It is not necessary to have both a *_mask and a *_shift - + * remove one + */ +struct omap_vc_instance_data { + const struct omap_vc_common_data *vc_common; + u32 smps_sa_mask; + u32 smps_volra_mask; + u8 cmdval_reg; + u8 smps_sa_shift; + u8 smps_volra_shift; +}; + +extern struct omap_vc_instance_data omap3_vc1_data; +extern struct omap_vc_instance_data omap3_vc2_data; + +extern struct omap_vc_instance_data omap4_vc_mpu_data; +extern struct omap_vc_instance_data omap4_vc_iva_data; +extern struct omap_vc_instance_data omap4_vc_core_data; + +#endif + diff --git a/arch/arm/mach-omap2/vc3xxx_data.c b/arch/arm/mach-omap2/vc3xxx_data.c new file mode 100644 index 00000000000..f37dc4bc379 --- /dev/null +++ b/arch/arm/mach-omap2/vc3xxx_data.c @@ -0,0 +1,63 @@ +/* + * OMAP3 Voltage Controller (VC) data + * + * Copyright (C) 2007, 2010 Texas Instruments, Inc. + * Rajendra Nayak <rnayak@ti.com> + * Lesly A M <x0080970@ti.com> + * Thara Gopinath <thara@ti.com> + * + * Copyright (C) 2008, 2011 Nokia Corporation + * Kalle Jokiniemi + * Paul Walmsley + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include <linux/io.h> +#include <linux/err.h> +#include <linux/init.h> + +#include <plat/common.h> + +#include "prm-regbits-34xx.h" +#include "voltage.h" + +#include "vc.h" + +/* + * VC data common to 34xx/36xx chips + * XXX This stuff presumably belongs in the vc3xxx.c or vc.c file. + */ +static struct omap_vc_common_data omap3_vc_common = { + .smps_sa_reg = OMAP3_PRM_VC_SMPS_SA_OFFSET, + .smps_volra_reg = OMAP3_PRM_VC_SMPS_VOL_RA_OFFSET, + .bypass_val_reg = OMAP3_PRM_VC_BYPASS_VAL_OFFSET, + .data_shift = OMAP3430_DATA_SHIFT, + .slaveaddr_shift = OMAP3430_SLAVEADDR_SHIFT, + .regaddr_shift = OMAP3430_REGADDR_SHIFT, + .valid = OMAP3430_VALID_MASK, + .cmd_on_shift = OMAP3430_VC_CMD_ON_SHIFT, + .cmd_on_mask = OMAP3430_VC_CMD_ON_MASK, + .cmd_onlp_shift = OMAP3430_VC_CMD_ONLP_SHIFT, + .cmd_ret_shift = OMAP3430_VC_CMD_RET_SHIFT, + .cmd_off_shift = OMAP3430_VC_CMD_OFF_SHIFT, +}; + +struct omap_vc_instance_data omap3_vc1_data = { + .vc_common = &omap3_vc_common, + .cmdval_reg = OMAP3_PRM_VC_CMD_VAL_0_OFFSET, + .smps_sa_shift = OMAP3430_PRM_VC_SMPS_SA_SA0_SHIFT, + .smps_sa_mask = OMAP3430_PRM_VC_SMPS_SA_SA0_MASK, + .smps_volra_shift = OMAP3430_VOLRA0_SHIFT, + .smps_volra_mask = OMAP3430_VOLRA0_MASK, +}; + +struct omap_vc_instance_data omap3_vc2_data = { + .vc_common = &omap3_vc_common, + .cmdval_reg = OMAP3_PRM_VC_CMD_VAL_1_OFFSET, + .smps_sa_shift = OMAP3430_PRM_VC_SMPS_SA_SA1_SHIFT, + .smps_sa_mask = OMAP3430_PRM_VC_SMPS_SA_SA1_MASK, + .smps_volra_shift = OMAP3430_VOLRA1_SHIFT, + .smps_volra_mask = OMAP3430_VOLRA1_MASK, +}; diff --git a/arch/arm/mach-omap2/vc44xx_data.c b/arch/arm/mach-omap2/vc44xx_data.c new file mode 100644 index 00000000000..a98da8ddec5 --- /dev/null +++ b/arch/arm/mach-omap2/vc44xx_data.c @@ -0,0 +1,75 @@ +/* + * OMAP4 Voltage Controller (VC) data + * + * Copyright (C) 2007, 2010 Texas Instruments, Inc. + * Rajendra Nayak <rnayak@ti.com> + * Lesly A M <x0080970@ti.com> + * Thara Gopinath <thara@ti.com> + * + * Copyright (C) 2008, 2011 Nokia Corporation + * Kalle Jokiniemi + * Paul Walmsley + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include <linux/io.h> +#include <linux/err.h> +#include <linux/init.h> + +#include <plat/common.h> + +#include "prm44xx.h" +#include "prm-regbits-44xx.h" +#include "voltage.h" + +#include "vc.h" + +/* + * VC data common to 44xx chips + * XXX This stuff presumably belongs in the vc3xxx.c or vc.c file. + */ +static const struct omap_vc_common_data omap4_vc_common = { + .smps_sa_reg = OMAP4_PRM_VC_SMPS_SA_OFFSET, + .smps_volra_reg = OMAP4_PRM_VC_VAL_SMPS_RA_VOL_OFFSET, + .bypass_val_reg = OMAP4_PRM_VC_VAL_BYPASS_OFFSET, + .data_shift = OMAP4430_DATA_SHIFT, + .slaveaddr_shift = OMAP4430_SLAVEADDR_SHIFT, + .regaddr_shift = OMAP4430_REGADDR_SHIFT, + .valid = OMAP4430_VALID_MASK, + .cmd_on_shift = OMAP4430_ON_SHIFT, + .cmd_on_mask = OMAP4430_ON_MASK, + .cmd_onlp_shift = OMAP4430_ONLP_SHIFT, + .cmd_ret_shift = OMAP4430_RET_SHIFT, + .cmd_off_shift = OMAP4430_OFF_SHIFT, +}; + +/* VC instance data for each controllable voltage line */ +struct omap_vc_instance_data omap4_vc_mpu_data = { + .vc_common = &omap4_vc_common, + .cmdval_reg = OMAP4_PRM_VC_VAL_CMD_VDD_MPU_L_OFFSET, + .smps_sa_shift = OMAP4430_SA_VDD_MPU_L_PRM_VC_SMPS_SA_SHIFT, + .smps_sa_mask = OMAP4430_SA_VDD_MPU_L_PRM_VC_SMPS_SA_MASK, + .smps_volra_shift = OMAP4430_VOLRA_VDD_MPU_L_SHIFT, + .smps_volra_mask = OMAP4430_VOLRA_VDD_MPU_L_MASK, +}; + +struct omap_vc_instance_data omap4_vc_iva_data = { + .vc_common = &omap4_vc_common, + .cmdval_reg = OMAP4_PRM_VC_VAL_CMD_VDD_IVA_L_OFFSET, + .smps_sa_shift = OMAP4430_SA_VDD_IVA_L_PRM_VC_SMPS_SA_SHIFT, + .smps_sa_mask = OMAP4430_SA_VDD_IVA_L_PRM_VC_SMPS_SA_MASK, + .smps_volra_shift = OMAP4430_VOLRA_VDD_IVA_L_SHIFT, + .smps_volra_mask = OMAP4430_VOLRA_VDD_IVA_L_MASK, +}; + +struct omap_vc_instance_data omap4_vc_core_data = { + .vc_common = &omap4_vc_common, + .cmdval_reg = OMAP4_PRM_VC_VAL_CMD_VDD_CORE_L_OFFSET, + .smps_sa_shift = OMAP4430_SA_VDD_CORE_L_0_6_SHIFT, + .smps_sa_mask = OMAP4430_SA_VDD_CORE_L_0_6_MASK, + .smps_volra_shift = OMAP4430_VOLRA_VDD_CORE_L_SHIFT, + .smps_volra_mask = OMAP4430_VOLRA_VDD_CORE_L_MASK, +}; + diff --git a/arch/arm/mach-omap2/voltage.c b/arch/arm/mach-omap2/voltage.c index 3c9bcdce612..c6facf7becf 100644 --- a/arch/arm/mach-omap2/voltage.c +++ b/arch/arm/mach-omap2/voltage.c @@ -7,8 +7,9 @@ * Rajendra Nayak <rnayak@ti.com> * Lesly A M <x0080970@ti.com> * - * Copyright (C) 2008 Nokia Corporation + * Copyright (C) 2008, 2011 Nokia Corporation * Kalle Jokiniemi + * Paul Walmsley * * Copyright (C) 2010 Texas Instruments, Inc. * Thara Gopinath <thara@ti.com> @@ -36,284 +37,28 @@ #include "voltage.h" -#define VP_IDLE_TIMEOUT 200 -#define VP_TRANXDONE_TIMEOUT 300 +#include "vc.h" +#include "vp.h" + #define VOLTAGE_DIR_SIZE 16 -/* Voltage processor register offsets */ -struct vp_reg_offs { - u8 vpconfig; - u8 vstepmin; - u8 vstepmax; - u8 vlimitto; - u8 vstatus; - u8 voltage; -}; - -/* Voltage Processor bit field values, shifts and masks */ -struct vp_reg_val { - /* PRM module */ - u16 prm_mod; - /* VPx_VPCONFIG */ - u32 vpconfig_erroroffset; - u16 vpconfig_errorgain; - u32 vpconfig_errorgain_mask; - u8 vpconfig_errorgain_shift; - u32 vpconfig_initvoltage_mask; - u8 vpconfig_initvoltage_shift; - u32 vpconfig_timeouten; - u32 vpconfig_initvdd; - u32 vpconfig_forceupdate; - u32 vpconfig_vpenable; - /* VPx_VSTEPMIN */ - u8 vstepmin_stepmin; - u16 vstepmin_smpswaittimemin; - u8 vstepmin_stepmin_shift; - u8 vstepmin_smpswaittimemin_shift; - /* VPx_VSTEPMAX */ - u8 vstepmax_stepmax; - u16 vstepmax_smpswaittimemax; - u8 vstepmax_stepmax_shift; - u8 vstepmax_smpswaittimemax_shift; - /* VPx_VLIMITTO */ - u8 vlimitto_vddmin; - u8 vlimitto_vddmax; - u16 vlimitto_timeout; - u8 vlimitto_vddmin_shift; - u8 vlimitto_vddmax_shift; - u8 vlimitto_timeout_shift; - /* PRM_IRQSTATUS*/ - u32 tranxdone_status; -}; - -/* Voltage controller registers and offsets */ -struct vc_reg_info { - /* PRM module */ - u16 prm_mod; - /* VC register offsets */ - u8 smps_sa_reg; - u8 smps_volra_reg; - u8 bypass_val_reg; - u8 cmdval_reg; - u8 voltsetup_reg; - /*VC_SMPS_SA*/ - u8 smps_sa_shift; - u32 smps_sa_mask; - /* VC_SMPS_VOL_RA */ - u8 smps_volra_shift; - u32 smps_volra_mask; - /* VC_BYPASS_VAL */ - u8 data_shift; - u8 slaveaddr_shift; - u8 regaddr_shift; - u32 valid; - /* VC_CMD_VAL */ - u8 cmd_on_shift; - u8 cmd_onlp_shift; - u8 cmd_ret_shift; - u8 cmd_off_shift; - u32 cmd_on_mask; - /* PRM_VOLTSETUP */ - u8 voltsetup_shift; - u32 voltsetup_mask; -}; -/** - * omap_vdd_info - Per Voltage Domain info - * - * @volt_data : voltage table having the distinct voltages supported - * by the domain and other associated per voltage data. - * @pmic_info : pmic specific parameters which should be populted by - * the pmic drivers. - * @vp_offs : structure containing the offsets for various - * vp registers - * @vp_reg : the register values, shifts, masks for various - * vp registers - * @vc_reg : structure containing various various vc registers, - * shifts, masks etc. - * @voltdm : pointer to the voltage domain structure - * @debug_dir : debug directory for this voltage domain. - * @curr_volt : current voltage for this vdd. - * @ocp_mod : The prm module for accessing the prm irqstatus reg. - * @prm_irqst_reg : prm irqstatus register. - * @vp_enabled : flag to keep track of whether vp is enabled or not - * @volt_scale : API to scale the voltage of the vdd. - */ -struct omap_vdd_info { - struct omap_volt_data *volt_data; - struct omap_volt_pmic_info *pmic_info; - struct vp_reg_offs vp_offs; - struct vp_reg_val vp_reg; - struct vc_reg_info vc_reg; - struct voltagedomain voltdm; - struct dentry *debug_dir; - u32 curr_volt; - u16 ocp_mod; - u8 prm_irqst_reg; - bool vp_enabled; - u32 (*read_reg) (u16 mod, u8 offset); - void (*write_reg) (u32 val, u16 mod, u8 offset); - int (*volt_scale) (struct omap_vdd_info *vdd, - unsigned long target_volt); -}; - -static struct omap_vdd_info *vdd_info; +static struct omap_vdd_info **vdd_info; + /* * Number of scalable voltage domains. */ static int nr_scalable_vdd; -/* OMAP3 VDD sturctures */ -static struct omap_vdd_info omap3_vdd_info[] = { - { - .vp_offs = { - .vpconfig = OMAP3_PRM_VP1_CONFIG_OFFSET, - .vstepmin = OMAP3_PRM_VP1_VSTEPMIN_OFFSET, - .vstepmax = OMAP3_PRM_VP1_VSTEPMAX_OFFSET, - .vlimitto = OMAP3_PRM_VP1_VLIMITTO_OFFSET, - .vstatus = OMAP3_PRM_VP1_STATUS_OFFSET, - .voltage = OMAP3_PRM_VP1_VOLTAGE_OFFSET, - }, - .voltdm = { - .name = "mpu", - }, - }, - { - .vp_offs = { - .vpconfig = OMAP3_PRM_VP2_CONFIG_OFFSET, - .vstepmin = OMAP3_PRM_VP2_VSTEPMIN_OFFSET, - .vstepmax = OMAP3_PRM_VP2_VSTEPMAX_OFFSET, - .vlimitto = OMAP3_PRM_VP2_VLIMITTO_OFFSET, - .vstatus = OMAP3_PRM_VP2_STATUS_OFFSET, - .voltage = OMAP3_PRM_VP2_VOLTAGE_OFFSET, - }, - .voltdm = { - .name = "core", - }, - }, -}; - -#define OMAP3_NR_SCALABLE_VDD ARRAY_SIZE(omap3_vdd_info) - -/* OMAP4 VDD sturctures */ -static struct omap_vdd_info omap4_vdd_info[] = { - { - .vp_offs = { - .vpconfig = OMAP4_PRM_VP_MPU_CONFIG_OFFSET, - .vstepmin = OMAP4_PRM_VP_MPU_VSTEPMIN_OFFSET, - .vstepmax = OMAP4_PRM_VP_MPU_VSTEPMAX_OFFSET, - .vlimitto = OMAP4_PRM_VP_MPU_VLIMITTO_OFFSET, - .vstatus = OMAP4_PRM_VP_MPU_STATUS_OFFSET, - .voltage = OMAP4_PRM_VP_MPU_VOLTAGE_OFFSET, - }, - .voltdm = { - .name = "mpu", - }, - }, - { - .vp_offs = { - .vpconfig = OMAP4_PRM_VP_IVA_CONFIG_OFFSET, - .vstepmin = OMAP4_PRM_VP_IVA_VSTEPMIN_OFFSET, - .vstepmax = OMAP4_PRM_VP_IVA_VSTEPMAX_OFFSET, - .vlimitto = OMAP4_PRM_VP_IVA_VLIMITTO_OFFSET, - .vstatus = OMAP4_PRM_VP_IVA_STATUS_OFFSET, - .voltage = OMAP4_PRM_VP_IVA_VOLTAGE_OFFSET, - }, - .voltdm = { - .name = "iva", - }, - }, - { - .vp_offs = { - .vpconfig = OMAP4_PRM_VP_CORE_CONFIG_OFFSET, - .vstepmin = OMAP4_PRM_VP_CORE_VSTEPMIN_OFFSET, - .vstepmax = OMAP4_PRM_VP_CORE_VSTEPMAX_OFFSET, - .vlimitto = OMAP4_PRM_VP_CORE_VLIMITTO_OFFSET, - .vstatus = OMAP4_PRM_VP_CORE_STATUS_OFFSET, - .voltage = OMAP4_PRM_VP_CORE_VOLTAGE_OFFSET, - }, - .voltdm = { - .name = "core", - }, - }, -}; - -#define OMAP4_NR_SCALABLE_VDD ARRAY_SIZE(omap4_vdd_info) - -/* - * Structures containing OMAP3430/OMAP3630 voltage supported and various - * voltage dependent data for each VDD. - */ -#define VOLT_DATA_DEFINE(_v_nom, _efuse_offs, _errminlimit, _errgain) \ -{ \ - .volt_nominal = _v_nom, \ - .sr_efuse_offs = _efuse_offs, \ - .sr_errminlimit = _errminlimit, \ - .vp_errgain = _errgain \ -} - -/* VDD1 */ -static struct omap_volt_data omap34xx_vddmpu_volt_data[] = { - VOLT_DATA_DEFINE(OMAP3430_VDD_MPU_OPP1_UV, OMAP343X_CONTROL_FUSE_OPP1_VDD1, 0xf4, 0x0c), - VOLT_DATA_DEFINE(OMAP3430_VDD_MPU_OPP2_UV, OMAP343X_CONTROL_FUSE_OPP2_VDD1, 0xf4, 0x0c), - VOLT_DATA_DEFINE(OMAP3430_VDD_MPU_OPP3_UV, OMAP343X_CONTROL_FUSE_OPP3_VDD1, 0xf9, 0x18), - VOLT_DATA_DEFINE(OMAP3430_VDD_MPU_OPP4_UV, OMAP343X_CONTROL_FUSE_OPP4_VDD1, 0xf9, 0x18), - VOLT_DATA_DEFINE(OMAP3430_VDD_MPU_OPP5_UV, OMAP343X_CONTROL_FUSE_OPP5_VDD1, 0xf9, 0x18), - VOLT_DATA_DEFINE(0, 0, 0, 0), -}; - -static struct omap_volt_data omap36xx_vddmpu_volt_data[] = { - VOLT_DATA_DEFINE(OMAP3630_VDD_MPU_OPP50_UV, OMAP3630_CONTROL_FUSE_OPP50_VDD1, 0xf4, 0x0c), - VOLT_DATA_DEFINE(OMAP3630_VDD_MPU_OPP100_UV, OMAP3630_CONTROL_FUSE_OPP100_VDD1, 0xf9, 0x16), - VOLT_DATA_DEFINE(OMAP3630_VDD_MPU_OPP120_UV, OMAP3630_CONTROL_FUSE_OPP120_VDD1, 0xfa, 0x23), - VOLT_DATA_DEFINE(OMAP3630_VDD_MPU_OPP1G_UV, OMAP3630_CONTROL_FUSE_OPP1G_VDD1, 0xfa, 0x27), - VOLT_DATA_DEFINE(0, 0, 0, 0), -}; - -/* VDD2 */ -static struct omap_volt_data omap34xx_vddcore_volt_data[] = { - VOLT_DATA_DEFINE(OMAP3430_VDD_CORE_OPP1_UV, OMAP343X_CONTROL_FUSE_OPP1_VDD2, 0xf4, 0x0c), - VOLT_DATA_DEFINE(OMAP3430_VDD_CORE_OPP2_UV, OMAP343X_CONTROL_FUSE_OPP2_VDD2, 0xf4, 0x0c), - VOLT_DATA_DEFINE(OMAP3430_VDD_CORE_OPP3_UV, OMAP343X_CONTROL_FUSE_OPP3_VDD2, 0xf9, 0x18), - VOLT_DATA_DEFINE(0, 0, 0, 0), -}; - -static struct omap_volt_data omap36xx_vddcore_volt_data[] = { - VOLT_DATA_DEFINE(OMAP3630_VDD_CORE_OPP50_UV, OMAP3630_CONTROL_FUSE_OPP50_VDD2, 0xf4, 0x0c), - VOLT_DATA_DEFINE(OMAP3630_VDD_CORE_OPP100_UV, OMAP3630_CONTROL_FUSE_OPP100_VDD2, 0xf9, 0x16), - VOLT_DATA_DEFINE(0, 0, 0, 0), -}; - -/* - * Structures containing OMAP4430 voltage supported and various - * voltage dependent data for each VDD. - */ -static struct omap_volt_data omap44xx_vdd_mpu_volt_data[] = { - VOLT_DATA_DEFINE(OMAP4430_VDD_MPU_OPP50_UV, OMAP44XX_CONTROL_FUSE_MPU_OPP50, 0xf4, 0x0c), - VOLT_DATA_DEFINE(OMAP4430_VDD_MPU_OPP100_UV, OMAP44XX_CONTROL_FUSE_MPU_OPP100, 0xf9, 0x16), - VOLT_DATA_DEFINE(OMAP4430_VDD_MPU_OPPTURBO_UV, OMAP44XX_CONTROL_FUSE_MPU_OPPTURBO, 0xfa, 0x23), - VOLT_DATA_DEFINE(OMAP4430_VDD_MPU_OPPNITRO_UV, OMAP44XX_CONTROL_FUSE_MPU_OPPNITRO, 0xfa, 0x27), - VOLT_DATA_DEFINE(0, 0, 0, 0), -}; - -static struct omap_volt_data omap44xx_vdd_iva_volt_data[] = { - VOLT_DATA_DEFINE(OMAP4430_VDD_IVA_OPP50_UV, OMAP44XX_CONTROL_FUSE_IVA_OPP50, 0xf4, 0x0c), - VOLT_DATA_DEFINE(OMAP4430_VDD_IVA_OPP100_UV, OMAP44XX_CONTROL_FUSE_IVA_OPP100, 0xf9, 0x16), - VOLT_DATA_DEFINE(OMAP4430_VDD_IVA_OPPTURBO_UV, OMAP44XX_CONTROL_FUSE_IVA_OPPTURBO, 0xfa, 0x23), - VOLT_DATA_DEFINE(0, 0, 0, 0), -}; - -static struct omap_volt_data omap44xx_vdd_core_volt_data[] = { - VOLT_DATA_DEFINE(OMAP4430_VDD_CORE_OPP50_UV, OMAP44XX_CONTROL_FUSE_CORE_OPP50, 0xf4, 0x0c), - VOLT_DATA_DEFINE(OMAP4430_VDD_CORE_OPP100_UV, OMAP44XX_CONTROL_FUSE_CORE_OPP100, 0xf9, 0x16), - VOLT_DATA_DEFINE(0, 0, 0, 0), -}; +/* XXX document */ +static s16 prm_mod_offs; +static s16 prm_irqst_ocp_mod_offs; static struct dentry *voltage_dir; /* Init function pointers */ -static void (*vc_init) (struct omap_vdd_info *vdd); -static int (*vdd_data_configure) (struct omap_vdd_info *vdd); +static int vp_forceupdate_scale_voltage(struct omap_vdd_info *vdd, + unsigned long target_volt); static u32 omap3_voltage_read_reg(u16 mod, u8 offset) { @@ -336,6 +81,62 @@ static void omap4_voltage_write_reg(u32 val, u16 mod, u8 offset) omap4_prminst_write_inst_reg(val, OMAP4430_PRM_PARTITION, mod, offset); } +static int __init _config_common_vdd_data(struct omap_vdd_info *vdd) +{ + char *sys_ck_name; + struct clk *sys_ck; + u32 sys_clk_speed, timeout_val, waittime; + + /* + * XXX Clockfw should handle this, or this should be in a + * struct record + */ + if (cpu_is_omap24xx() || cpu_is_omap34xx()) + sys_ck_name = "sys_ck"; + else if (cpu_is_omap44xx()) + sys_ck_name = "sys_clkin_ck"; + else + return -EINVAL; + + /* + * Sys clk rate is require to calculate vp timeout value and + * smpswaittimemin and smpswaittimemax. + */ + sys_ck = clk_get(NULL, sys_ck_name); + if (IS_ERR(sys_ck)) { + pr_warning("%s: Could not get the sys clk to calculate" + "various vdd_%s params\n", __func__, vdd->voltdm.name); + return -EINVAL; + } + sys_clk_speed = clk_get_rate(sys_ck); + clk_put(sys_ck); + /* Divide to avoid overflow */ + sys_clk_speed /= 1000; + + /* Generic voltage parameters */ + vdd->curr_volt = 1200000; + vdd->volt_scale = vp_forceupdate_scale_voltage; + vdd->vp_enabled = false; + + vdd->vp_rt_data.vpconfig_erroroffset = + (vdd->pmic_info->vp_erroroffset << + vdd->vp_data->vp_common->vpconfig_erroroffset_shift); + + timeout_val = (sys_clk_speed * vdd->pmic_info->vp_timeout_us) / 1000; + vdd->vp_rt_data.vlimitto_timeout = timeout_val; + vdd->vp_rt_data.vlimitto_vddmin = vdd->pmic_info->vp_vddmin; + vdd->vp_rt_data.vlimitto_vddmax = vdd->pmic_info->vp_vddmax; + + waittime = ((vdd->pmic_info->step_size / vdd->pmic_info->slew_rate) * + sys_clk_speed) / 1000; + vdd->vp_rt_data.vstepmin_smpswaittimemin = waittime; + vdd->vp_rt_data.vstepmax_smpswaittimemax = waittime; + vdd->vp_rt_data.vstepmin_stepmin = vdd->pmic_info->vp_vstepmin; + vdd->vp_rt_data.vstepmax_stepmax = vdd->pmic_info->vp_vstepmax; + + return 0; +} + /* Voltage debugfs support */ static int vp_volt_debug_get(void *data, u64 *val) { @@ -347,7 +148,7 @@ static int vp_volt_debug_get(void *data, u64 *val) return -EINVAL; } - vsel = vdd->read_reg(vdd->vp_reg.prm_mod, vdd->vp_offs.voltage); + vsel = vdd->read_reg(prm_mod_offs, vdd->vp_data->voltage); pr_notice("curr_vsel = %x\n", vsel); if (!vdd->pmic_info->vsel_to_uv) { @@ -380,7 +181,6 @@ DEFINE_SIMPLE_ATTRIBUTE(nom_volt_debug_fops, nom_volt_debug_get, NULL, static void vp_latch_vsel(struct omap_vdd_info *vdd) { u32 vpconfig; - u16 mod; unsigned long uvdc; char vsel; @@ -397,30 +197,27 @@ static void vp_latch_vsel(struct omap_vdd_info *vdd) return; } - mod = vdd->vp_reg.prm_mod; - vsel = vdd->pmic_info->uv_to_vsel(uvdc); - vpconfig = vdd->read_reg(mod, vdd->vp_offs.vpconfig); - vpconfig &= ~(vdd->vp_reg.vpconfig_initvoltage_mask | - vdd->vp_reg.vpconfig_initvdd); - vpconfig |= vsel << vdd->vp_reg.vpconfig_initvoltage_shift; + vpconfig = vdd->read_reg(prm_mod_offs, vdd->vp_data->vpconfig); + vpconfig &= ~(vdd->vp_data->vp_common->vpconfig_initvoltage_mask | + vdd->vp_data->vp_common->vpconfig_initvdd); + vpconfig |= vsel << vdd->vp_data->vp_common->vpconfig_initvoltage_shift; - vdd->write_reg(vpconfig, mod, vdd->vp_offs.vpconfig); + vdd->write_reg(vpconfig, prm_mod_offs, vdd->vp_data->vpconfig); /* Trigger initVDD value copy to voltage processor */ - vdd->write_reg((vpconfig | vdd->vp_reg.vpconfig_initvdd), mod, - vdd->vp_offs.vpconfig); + vdd->write_reg((vpconfig | vdd->vp_data->vp_common->vpconfig_initvdd), + prm_mod_offs, vdd->vp_data->vpconfig); /* Clear initVDD copy trigger bit */ - vdd->write_reg(vpconfig, mod, vdd->vp_offs.vpconfig); + vdd->write_reg(vpconfig, prm_mod_offs, vdd->vp_data->vpconfig); } /* Generic voltage init functions */ |