PM related fixes for omap3 that were discovered during omap3
conversion to device tree. This series sets up the PMIC signaling in a way where we can test for PM regressions easily by looking at state of the the sys_clkreq and sys_off_mode pins. Note that this series alone does not make omap3 PM to cut off core voltage during off-idle, changes to twl4030-power.c configurations are still needed. Those will be posted separately. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJTa+Y/AAoJEBvUPslcq6VzzIoQAIRtJk2cvwd/8CzfmNG6OQl1 cuzO0/HUsueQtzarCcNLSR00a9COD9ZcrZPIJWGsnSs/HM0bOWQTnx2GE75o//58 PxOF527a66Eyg+VmJvJAeo/lkTWhsTrb1CgRN45KnP6sVbtO5+5MYGrkkbw2q/ML lfFqiMrB02a9mp2Rq2Qy4et4L1bedTEAX5NdmKzZRIoygavXTWe/zP/FKppBnYTh bcUGjPDbkwUHQFoJKpX4I5yq91rWdZuPD0cb+e4QYI/+C2b7yQX5HFJBT0x9hDOl aGEh08dzO6jTU5HFlJhXOjBka7M9iBaYixKOU8ejnoFtVzU1A/tXOFIdyafBWp4N iYUqTW3HTKgeFnTEW7ei55XC3Mfwuk7YHm9v+GEhU76iw9FnChMajLBaUwRnL5Tm 8YxKK2ubcgYW10bK5ZhvRP2dPAOgn7x7uwm9Mp8Il2zyvTiOR5Fw/oyd1l5G4tlD FM1+v19xypfGFIyULZwFsSDL+0M57OudvK4U75vue0oyV6QyksHDHeu2k5nETTsS CHcjUO0rJTAcgOQrgGuQCmD0qcUu7Qs40boQ8YQlZ73sJSH2qNR5QCRjOXi0r5gx yoqpor2rR4R9q+XEpHA3M/YjerH0rsAtsXETPg7yifEP9TV8TDnTTRGyxxgeXHlo 22mOK74gPcGH6EBaPeY7 =SIKK -----END PGP SIGNATURE----- Merge tag 'omap-for-v3.16/pm-signed' of git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap into next/soc Merge "ARM: omap pm changes for v3.16 merge window, resend" from Tony Lindgren: PM related fixes for omap3 that were discovered during omap3 conversion to device tree. This series sets up the PMIC signaling in a way where we can test for PM regressions easily by looking at state of the the sys_clkreq and sys_off_mode pins. Note that this series alone does not make omap3 PM to cut off core voltage during off-idle, changes to twl4030-power.c configurations are still needed. Those will be posted separately. * tag 'omap-for-v3.16/pm-signed' of git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap: ARM: OMAP2+: Enable CPUidle in omap2plus_defconfig ARM: dts: Enable N900 keyboard sleep leds by default ARM: OMAP2+: Fix voltage scaling init for device tree ARM: dts: Configure omap3 twl4030 I2C4 pins by default ARM: OMAP3: Fix voltage control for deeper idle states ARM: OMAP3: Disable broken omap3_set_off_timings function ARM: OMAP3: Fix idle mode signaling for sys_clkreq and sys_off_mode ARM: dts: Fix omap serial wake-up when booted with device tree mfd: twl-core: Fix idle mode signaling for omaps when booted with device tree Signed-off-by: Olof Johansson <olof@lixom.net>
This commit is contained in:
Коммит
2ca602de42
|
@ -89,7 +89,16 @@
|
|||
status = "disabled";
|
||||
};
|
||||
|
||||
&uart1 {
|
||||
interrupts-extended = <&intc 72 &omap3_pmx_core OMAP3_UART1_RX>;
|
||||
};
|
||||
|
||||
&uart2 {
|
||||
interrupts-extended = <&intc 73 &omap3_pmx_core OMAP3_UART2_RX>;
|
||||
};
|
||||
|
||||
&uart3 {
|
||||
interrupts-extended = <&intc 74 &omap3_pmx_core OMAP3_UART3_RX>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&uart3_pins>;
|
||||
};
|
||||
|
|
|
@ -234,6 +234,10 @@
|
|||
};
|
||||
};
|
||||
|
||||
&uart3 {
|
||||
interrupts-extended = <&intc 74 &omap3_pmx_core OMAP3_UART3_RX>;
|
||||
};
|
||||
|
||||
&usb_otg_hs {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&musb_pins>;
|
||||
|
|
|
@ -21,6 +21,17 @@
|
|||
};
|
||||
};
|
||||
|
||||
leds {
|
||||
compatible = "gpio-leds";
|
||||
heartbeat {
|
||||
label = "debug::sleep";
|
||||
gpios = <&gpio6 2 GPIO_ACTIVE_HIGH>; /* gpio162 */
|
||||
linux,default-trigger = "default-on";
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&debug_leds>;
|
||||
};
|
||||
};
|
||||
|
||||
memory {
|
||||
device_type = "memory";
|
||||
reg = <0x80000000 0x10000000>; /* 256 MB */
|
||||
|
@ -130,6 +141,12 @@
|
|||
>;
|
||||
};
|
||||
|
||||
debug_leds: pinmux_debug_led_pins {
|
||||
pinctrl-single,pins = <
|
||||
OMAP3_CORE1_IOPAD(0x2198, PIN_OUTPUT | MUX_MODE4) /* mcbsp1_clkx.gpio_162 */
|
||||
>;
|
||||
};
|
||||
|
||||
mmc1_pins: pinmux_mmc1_pins {
|
||||
pinctrl-single,pins = <
|
||||
0x114 (PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc1_clk */
|
||||
|
@ -618,11 +635,13 @@
|
|||
};
|
||||
|
||||
&uart2 {
|
||||
interrupts-extended = <&intc 73 &omap3_pmx_core OMAP3_UART2_RX>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&uart2_pins>;
|
||||
};
|
||||
|
||||
&uart3 {
|
||||
interrupts-extended = <&intc 74 &omap3_pmx_core OMAP3_UART3_RX>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&uart3_pins>;
|
||||
};
|
||||
|
|
|
@ -267,7 +267,7 @@
|
|||
uart1: serial@4806a000 {
|
||||
compatible = "ti,omap3-uart";
|
||||
reg = <0x4806a000 0x2000>;
|
||||
interrupts = <72>;
|
||||
interrupts-extended = <&intc 72>;
|
||||
dmas = <&sdma 49 &sdma 50>;
|
||||
dma-names = "tx", "rx";
|
||||
ti,hwmods = "uart1";
|
||||
|
@ -277,7 +277,7 @@
|
|||
uart2: serial@4806c000 {
|
||||
compatible = "ti,omap3-uart";
|
||||
reg = <0x4806c000 0x400>;
|
||||
interrupts = <73>;
|
||||
interrupts-extended = <&intc 73>;
|
||||
dmas = <&sdma 51 &sdma 52>;
|
||||
dma-names = "tx", "rx";
|
||||
ti,hwmods = "uart2";
|
||||
|
@ -287,7 +287,7 @@
|
|||
uart3: serial@49020000 {
|
||||
compatible = "ti,omap3-uart";
|
||||
reg = <0x49020000 0x400>;
|
||||
interrupts = <74>;
|
||||
interrupts-extended = <&intc 74>;
|
||||
dmas = <&sdma 53 &sdma 54>;
|
||||
dma-names = "tx", "rx";
|
||||
ti,hwmods = "uart3";
|
||||
|
|
|
@ -481,6 +481,21 @@
|
|||
usb-supply = <&vusb>;
|
||||
};
|
||||
|
||||
&uart2 {
|
||||
interrupts-extended = <&gic GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH
|
||||
&omap4_pmx_core OMAP4_UART2_RX>;
|
||||
};
|
||||
|
||||
&uart3 {
|
||||
interrupts-extended = <&gic GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH
|
||||
&omap4_pmx_core OMAP4_UART3_RX>;
|
||||
};
|
||||
|
||||
&uart4 {
|
||||
interrupts-extended = <&gic GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH
|
||||
&omap4_pmx_core OMAP4_UART4_RX>;
|
||||
};
|
||||
|
||||
&usb_otg_hs {
|
||||
interface-type = <1>;
|
||||
mode = <3>;
|
||||
|
|
|
@ -570,16 +570,22 @@
|
|||
};
|
||||
|
||||
&uart2 {
|
||||
interrupts-extended = <&gic GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH
|
||||
&omap4_pmx_core OMAP4_UART2_RX>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&uart2_pins>;
|
||||
};
|
||||
|
||||
&uart3 {
|
||||
interrupts-extended = <&gic GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH
|
||||
&omap4_pmx_core OMAP4_UART3_RX>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&uart3_pins>;
|
||||
};
|
||||
|
||||
&uart4 {
|
||||
interrupts-extended = <&gic GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH
|
||||
&omap4_pmx_core OMAP4_UART4_RX>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&uart4_pins>;
|
||||
};
|
||||
|
|
|
@ -311,7 +311,7 @@
|
|||
uart2: serial@4806c000 {
|
||||
compatible = "ti,omap4-uart";
|
||||
reg = <0x4806c000 0x100>;
|
||||
interrupts = <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupts-extended = <&gic GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>;
|
||||
ti,hwmods = "uart2";
|
||||
clock-frequency = <48000000>;
|
||||
};
|
||||
|
@ -319,7 +319,7 @@
|
|||
uart3: serial@48020000 {
|
||||
compatible = "ti,omap4-uart";
|
||||
reg = <0x48020000 0x100>;
|
||||
interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupts-extended = <&gic GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>;
|
||||
ti,hwmods = "uart3";
|
||||
clock-frequency = <48000000>;
|
||||
};
|
||||
|
@ -327,7 +327,7 @@
|
|||
uart4: serial@4806e000 {
|
||||
compatible = "ti,omap4-uart";
|
||||
reg = <0x4806e000 0x100>;
|
||||
interrupts = <GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupts-extended = <&gic GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>;
|
||||
ti,hwmods = "uart4";
|
||||
clock-frequency = <48000000>;
|
||||
};
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
&twl {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&twl4030_pins>;
|
||||
pinctrl-0 = <&twl4030_pins &twl4030_vpins>;
|
||||
};
|
||||
|
||||
&omap3_pmx_core {
|
||||
|
@ -23,3 +23,20 @@
|
|||
>;
|
||||
};
|
||||
};
|
||||
|
||||
/*
|
||||
* If your board is not using the I2C4 pins with twl4030, then don't include
|
||||
* this file. For proper idle mode signaling with sys_clkreq and sys_off_mode
|
||||
* pins we need to configure I2C4, or else use the legacy sys_nvmode1 and
|
||||
* sys_nvmode2 signaling.
|
||||
*/
|
||||
&omap3_pmx_wkup {
|
||||
twl4030_vpins: pinmux_twl4030_vpins {
|
||||
pinctrl-single,pins = <
|
||||
OMAP3_WKUP_IOPAD(0x2a00, PIN_INPUT | MUX_MODE0) /* i2c4_scl.i2c4_scl */
|
||||
OMAP3_WKUP_IOPAD(0x2a02, PIN_INPUT | MUX_MODE0) /* i2c4_sda.i2c4_sda */
|
||||
OMAP3_WKUP_IOPAD(0x2a06, PIN_OUTPUT | MUX_MODE0) /* sys_clkreq.sys_clkreq */
|
||||
OMAP3_WKUP_IOPAD(0x2a18, PIN_OUTPUT | MUX_MODE0) /* sys_off_mode.sys_off_mode */
|
||||
>;
|
||||
};
|
||||
};
|
||||
|
|
|
@ -21,6 +21,8 @@ CONFIG_MODULE_SRCVERSION_ALL=y
|
|||
# CONFIG_BLK_DEV_BSG is not set
|
||||
CONFIG_PARTITION_ADVANCED=y
|
||||
CONFIG_ARCH_MULTI_V6=y
|
||||
CONFIG_POWER_AVS_OMAP=y
|
||||
CONFIG_POWER_AVS_OMAP_CLASS3=y
|
||||
CONFIG_OMAP_RESET_CLOCKS=y
|
||||
CONFIG_OMAP_MUX_DEBUG=y
|
||||
CONFIG_ARCH_OMAP2=y
|
||||
|
@ -42,6 +44,7 @@ CONFIG_ARM_ATAG_DTB_COMPAT=y
|
|||
CONFIG_CMDLINE="root=/dev/mmcblk0p2 rootwait console=ttyO2,115200"
|
||||
CONFIG_KEXEC=y
|
||||
CONFIG_FPE_NWFPE=y
|
||||
CONFIG_CPU_IDLE=y
|
||||
CONFIG_BINFMT_MISC=y
|
||||
CONFIG_PM_DEBUG=y
|
||||
CONFIG_NET=y
|
||||
|
@ -159,11 +162,14 @@ CONFIG_GPIO_SYSFS=y
|
|||
CONFIG_GPIO_TWL4030=y
|
||||
CONFIG_W1=y
|
||||
CONFIG_POWER_SUPPLY=y
|
||||
CONFIG_POWER_AVS=y
|
||||
CONFIG_SENSORS_LM75=m
|
||||
CONFIG_THERMAL=y
|
||||
CONFIG_THERMAL_GOV_FAIR_SHARE=y
|
||||
CONFIG_THERMAL_GOV_USER_SPACE=y
|
||||
CONFIG_CPU_THERMAL=y
|
||||
CONFIG_TI_SOC_THERMAL=y
|
||||
CONFIG_TI_THERMAL=y
|
||||
CONFIG_OMAP4_THERMAL=y
|
||||
CONFIG_OMAP5_THERMAL=y
|
||||
CONFIG_DRA752_THERMAL=y
|
||||
|
@ -177,6 +183,7 @@ CONFIG_MFD_TPS65910=y
|
|||
CONFIG_TWL6040_CORE=y
|
||||
CONFIG_REGULATOR_FIXED_VOLTAGE=y
|
||||
CONFIG_REGULATOR_PALMAS=y
|
||||
CONFIG_REGULATOR_TI_ABB=y
|
||||
CONFIG_REGULATOR_TPS65023=y
|
||||
CONFIG_REGULATOR_TPS6507X=y
|
||||
CONFIG_REGULATOR_TPS65217=y
|
||||
|
@ -239,6 +246,7 @@ CONFIG_SDIO_UART=y
|
|||
CONFIG_MMC_OMAP=y
|
||||
CONFIG_MMC_OMAP_HS=y
|
||||
CONFIG_NEW_LEDS=y
|
||||
CONFIG_LEDS_CLASS=y
|
||||
CONFIG_LEDS_GPIO=y
|
||||
CONFIG_LEDS_TRIGGERS=y
|
||||
CONFIG_LEDS_TRIGGER_TIMER=y
|
||||
|
|
|
@ -46,15 +46,8 @@
|
|||
|
||||
static bool is_offset_valid;
|
||||
static u8 smps_offset;
|
||||
/*
|
||||
* Flag to ensure Smartreflex bit in TWL
|
||||
* being cleared in board file is not overwritten.
|
||||
*/
|
||||
static bool __initdata twl_sr_enable_autoinit;
|
||||
|
||||
#define TWL4030_DCDC_GLOBAL_CFG 0x06
|
||||
#define REG_SMPS_OFFSET 0xE0
|
||||
#define SMARTREFLEX_ENABLE BIT(3)
|
||||
|
||||
static unsigned long twl4030_vsel_to_uv(const u8 vsel)
|
||||
{
|
||||
|
@ -251,18 +244,6 @@ int __init omap3_twl_init(void)
|
|||
if (!cpu_is_omap34xx())
|
||||
return -ENODEV;
|
||||
|
||||
/*
|
||||
* The smartreflex bit on twl4030 specifies if the setting of voltage
|
||||
* is done over the I2C_SR path. Since this setting is independent of
|
||||
* the actual usage of smartreflex AVS module, we enable TWL SR bit
|
||||
* by default irrespective of whether smartreflex AVS module is enabled
|
||||
* on the OMAP side or not. This is because without this bit enabled,
|
||||
* the voltage scaling through vp forceupdate/bypass mechanism of
|
||||
* voltage scaling will not function on TWL over I2C_SR.
|
||||
*/
|
||||
if (!twl_sr_enable_autoinit)
|
||||
omap3_twl_set_sr_bit(true);
|
||||
|
||||
voltdm = voltdm_lookup("mpu_iva");
|
||||
omap_voltage_register_pmic(voltdm, &omap3_mpu_pmic);
|
||||
|
||||
|
@ -271,44 +252,3 @@ int __init omap3_twl_init(void)
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* omap3_twl_set_sr_bit() - Set/Clear SR bit on TWL
|
||||
* @enable: enable SR mode in twl or not
|
||||
*
|
||||
* If 'enable' is true, enables Smartreflex bit on TWL 4030 to make sure
|
||||
* voltage scaling through OMAP SR works. Else, the smartreflex bit
|
||||
* on twl4030 is cleared as there are platforms which use OMAP3 and T2 but
|
||||
* use Synchronized Scaling Hardware Strategy (ENABLE_VMODE=1) and Direct
|
||||
* Strategy Software Scaling Mode (ENABLE_VMODE=0), for setting the voltages,
|
||||
* in those scenarios this bit is to be cleared (enable = false).
|
||||
*
|
||||
* Returns 0 on success, error is returned if I2C read/write fails.
|
||||
*/
|
||||
int __init omap3_twl_set_sr_bit(bool enable)
|
||||
{
|
||||
u8 temp;
|
||||
int ret;
|
||||
if (twl_sr_enable_autoinit)
|
||||
pr_warning("%s: unexpected multiple calls\n", __func__);
|
||||
|
||||
ret = twl_i2c_read_u8(TWL_MODULE_PM_RECEIVER, &temp,
|
||||
TWL4030_DCDC_GLOBAL_CFG);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
if (enable)
|
||||
temp |= SMARTREFLEX_ENABLE;
|
||||
else
|
||||
temp &= ~SMARTREFLEX_ENABLE;
|
||||
|
||||
ret = twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, temp,
|
||||
TWL4030_DCDC_GLOBAL_CFG);
|
||||
if (!ret) {
|
||||
twl_sr_enable_autoinit = true;
|
||||
return 0;
|
||||
}
|
||||
err:
|
||||
pr_err("%s: Error access to TWL4030 (%d)\n", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -298,26 +298,22 @@ omap_postcore_initcall(omap2_common_pm_init);
|
|||
|
||||
int __init omap2_common_pm_late_init(void)
|
||||
{
|
||||
/*
|
||||
* In the case of DT, the PMIC and SR initialization will be done using
|
||||
* a completely different mechanism.
|
||||
* Disable this part if a DT blob is available.
|
||||
*/
|
||||
if (!of_have_populated_dt()) {
|
||||
|
||||
/* Init the voltage layer */
|
||||
omap_pmic_late_init();
|
||||
omap_voltage_late_init();
|
||||
|
||||
/* Initialize the voltages */
|
||||
omap3_init_voltages();
|
||||
omap4_init_voltages();
|
||||
|
||||
/* Smartreflex device init */
|
||||
omap_devinit_smartreflex();
|
||||
|
||||
if (of_have_populated_dt()) {
|
||||
omap3_twl_init();
|
||||
omap4_twl_init();
|
||||
}
|
||||
|
||||
/* Init the voltage layer */
|
||||
omap_pmic_late_init();
|
||||
omap_voltage_late_init();
|
||||
|
||||
/* Initialize the voltages */
|
||||
omap3_init_voltages();
|
||||
omap4_init_voltages();
|
||||
|
||||
/* Smartreflex device init */
|
||||
omap_devinit_smartreflex();
|
||||
|
||||
/* cpufreq dummy device instantiation */
|
||||
omap_init_cpufreq();
|
||||
|
||||
|
|
|
@ -50,6 +50,7 @@
|
|||
#include "sdrc.h"
|
||||
#include "sram.h"
|
||||
#include "control.h"
|
||||
#include "vc.h"
|
||||
|
||||
/* pm34xx errata defined in pm.h */
|
||||
u16 pm34xx_errata;
|
||||
|
@ -288,6 +289,9 @@ void omap_sram_idle(void)
|
|||
}
|
||||
}
|
||||
|
||||
/* Configure PMIC signaling for I2C4 or sys_off_mode */
|
||||
omap3_vc_set_pmic_signaling(core_next_state);
|
||||
|
||||
omap3_intc_prepare_idle();
|
||||
|
||||
/*
|
||||
|
|
|
@ -123,8 +123,15 @@
|
|||
#define OMAP3430_GLOBAL_SW_RST_SHIFT 1
|
||||
#define OMAP3430_GLOBAL_COLD_RST_SHIFT 0
|
||||
#define OMAP3430_GLOBAL_COLD_RST_MASK (1 << 0)
|
||||
#define OMAP3430_SEL_OFF_MASK (1 << 3)
|
||||
#define OMAP3430_AUTO_OFF_MASK (1 << 2)
|
||||
#define OMAP3430_PRM_VOLTCTRL_SEL_VMODE (1 << 4)
|
||||
#define OMAP3430_PRM_VOLTCTRL_SEL_OFF (1 << 3)
|
||||
#define OMAP3430_PRM_VOLTCTRL_AUTO_OFF (1 << 2)
|
||||
#define OMAP3430_PRM_VOLTCTRL_AUTO_RET (1 << 1)
|
||||
#define OMAP3430_PRM_VOLTCTRL_AUTO_SLEEP (1 << 0)
|
||||
#define OMAP3430_SETUP_TIME2_MASK (0xffff << 16)
|
||||
#define OMAP3430_SETUP_TIME1_MASK (0xffff << 0)
|
||||
#define OMAP3430_PRM_POLCTRL_OFFMODE_POL (1 << 3)
|
||||
#define OMAP3430_PRM_POLCTRL_CLKOUT_POL (1 << 2)
|
||||
#define OMAP3430_PRM_POLCTRL_CLKREQ_POL (1 << 1)
|
||||
#define OMAP3430_PRM_POLCTRL_EXTVOL_POL (1 << 0)
|
||||
#endif
|
||||
|
|
|
@ -220,10 +220,126 @@ static inline u32 omap_usec_to_32k(u32 usec)
|
|||
return DIV_ROUND_UP_ULL(32768ULL * (u64)usec, 1000000ULL);
|
||||
}
|
||||
|
||||
/* Set oscillator setup time for omap3 */
|
||||
static void omap3_set_clksetup(u32 usec, struct voltagedomain *voltdm)
|
||||
struct omap3_vc_timings {
|
||||
u32 voltsetup1;
|
||||
u32 voltsetup2;
|
||||
};
|
||||
|
||||
struct omap3_vc {
|
||||
struct voltagedomain *vd;
|
||||
u32 voltctrl;
|
||||
u32 voltsetup1;
|
||||
u32 voltsetup2;
|
||||
struct omap3_vc_timings timings[2];
|
||||
};
|
||||
static struct omap3_vc vc;
|
||||
|
||||
void omap3_vc_set_pmic_signaling(int core_next_state)
|
||||
{
|
||||
voltdm->write(omap_usec_to_32k(usec), OMAP3_PRM_CLKSETUP_OFFSET);
|
||||
struct voltagedomain *vd = vc.vd;
|
||||
struct omap3_vc_timings *c = vc.timings;
|
||||
u32 voltctrl, voltsetup1, voltsetup2;
|
||||
|
||||
voltctrl = vc.voltctrl;
|
||||
voltsetup1 = vc.voltsetup1;
|
||||
voltsetup2 = vc.voltsetup2;
|
||||
|
||||
switch (core_next_state) {
|
||||
case PWRDM_POWER_OFF:
|
||||
voltctrl &= ~(OMAP3430_PRM_VOLTCTRL_AUTO_RET |
|
||||
OMAP3430_PRM_VOLTCTRL_AUTO_SLEEP);
|
||||
voltctrl |= OMAP3430_PRM_VOLTCTRL_AUTO_OFF;
|
||||
if (voltctrl & OMAP3430_PRM_VOLTCTRL_SEL_OFF)
|
||||
voltsetup2 = c->voltsetup2;
|
||||
else
|
||||
voltsetup1 = c->voltsetup1;
|
||||
break;
|
||||
case PWRDM_POWER_RET:
|
||||
default:
|
||||
c++;
|
||||
voltctrl &= ~(OMAP3430_PRM_VOLTCTRL_AUTO_OFF |
|
||||
OMAP3430_PRM_VOLTCTRL_AUTO_SLEEP);
|
||||
voltctrl |= OMAP3430_PRM_VOLTCTRL_AUTO_RET;
|
||||
voltsetup1 = c->voltsetup1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (voltctrl != vc.voltctrl) {
|
||||
vd->write(voltctrl, OMAP3_PRM_VOLTCTRL_OFFSET);
|
||||
vc.voltctrl = voltctrl;
|
||||
}
|
||||
if (voltsetup1 != vc.voltsetup1) {
|
||||
vd->write(c->voltsetup1,
|
||||
OMAP3_PRM_VOLTSETUP1_OFFSET);
|
||||
vc.voltsetup1 = voltsetup1;
|
||||
}
|
||||
if (voltsetup2 != vc.voltsetup2) {
|
||||
vd->write(c->voltsetup2,
|
||||
OMAP3_PRM_VOLTSETUP2_OFFSET);
|
||||
vc.voltsetup2 = voltsetup2;
|
||||
}
|
||||
}
|
||||
|
||||
#define PRM_POLCTRL_TWL_MASK (OMAP3430_PRM_POLCTRL_CLKREQ_POL | \
|
||||
OMAP3430_PRM_POLCTRL_CLKREQ_POL)
|
||||
#define PRM_POLCTRL_TWL_VAL OMAP3430_PRM_POLCTRL_CLKREQ_POL
|
||||
|
||||
/*
|
||||
* Configure signal polarity for sys_clkreq and sys_off_mode pins
|
||||
* as the default values are wrong and can cause the system to hang
|
||||
* if any twl4030 scripts are loaded.
|
||||
*/
|
||||
static void __init omap3_vc_init_pmic_signaling(struct voltagedomain *voltdm)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
if (vc.vd)
|
||||
return;
|
||||
|
||||
vc.vd = voltdm;
|
||||
|
||||
val = voltdm->read(OMAP3_PRM_POLCTRL_OFFSET);
|
||||
if (!(val & OMAP3430_PRM_POLCTRL_CLKREQ_POL) ||
|
||||
(val & OMAP3430_PRM_POLCTRL_CLKREQ_POL)) {
|
||||
val |= OMAP3430_PRM_POLCTRL_CLKREQ_POL;
|
||||
val &= ~OMAP3430_PRM_POLCTRL_OFFMODE_POL;
|
||||
pr_debug("PM: fixing sys_clkreq and sys_off_mode polarity to 0x%x\n",
|
||||
val);
|
||||
voltdm->write(val, OMAP3_PRM_POLCTRL_OFFSET);
|
||||
}
|
||||
|
||||
/*
|
||||
* By default let's use I2C4 signaling for retention idle
|
||||
* and sys_off_mode pin signaling for off idle. This way we
|
||||
* have sys_clk_req pin go down for retention and both
|
||||
* sys_clk_req and sys_off_mode pins will go down for off
|
||||
* idle. And we can also scale voltages to zero for off-idle.
|
||||
* Note that no actual voltage scaling during off-idle will
|
||||
* happen unless the board specific twl4030 PMIC scripts are
|
||||
* loaded.
|
||||
*/
|
||||
val = voltdm->read(OMAP3_PRM_VOLTCTRL_OFFSET);
|
||||
if (!(val & OMAP3430_PRM_VOLTCTRL_SEL_OFF)) {
|
||||
val |= OMAP3430_PRM_VOLTCTRL_SEL_OFF;
|
||||
pr_debug("PM: setting voltctrl sys_off_mode signaling to 0x%x\n",
|
||||
val);
|
||||
voltdm->write(val, OMAP3_PRM_VOLTCTRL_OFFSET);
|
||||
}
|
||||
vc.voltctrl = val;
|
||||
|
||||
omap3_vc_set_pmic_signaling(PWRDM_POWER_ON);
|
||||
}
|
||||
|
||||
static void omap3_init_voltsetup1(struct voltagedomain *voltdm,
|
||||
struct omap3_vc_timings *c, u32 idle)
|
||||
{
|
||||
unsigned long val;
|
||||
|
||||
val = (voltdm->vc_param->on - idle) / voltdm->pmic->slew_rate;
|
||||
val *= voltdm->sys_clk.rate / 8 / 1000000 + 1;
|
||||
val <<= __ffs(voltdm->vfsm->voltsetup_mask);
|
||||
c->voltsetup1 &= ~voltdm->vfsm->voltsetup_mask;
|
||||
c->voltsetup1 |= val;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -236,37 +352,21 @@ static void omap3_set_clksetup(u32 usec, struct voltagedomain *voltdm)
|
|||
* or retention. Off mode has additionally an option to use sys_off_mode
|
||||
* pad, which uses a global signal to program the whole power IC to
|
||||
* off-mode.
|
||||
*
|
||||
* Note that pmic is not controlling the voltage scaling during
|
||||
* retention signaled over I2C4, so we can keep voltsetup2 as 0.
|
||||
* And the oscillator is not shut off over I2C4, so no need to
|
||||
* set clksetup.
|
||||
*/
|
||||
static void omap3_set_i2c_timings(struct voltagedomain *voltdm, bool off_mode)
|
||||
static void omap3_set_i2c_timings(struct voltagedomain *voltdm)
|
||||
{
|
||||
unsigned long voltsetup1;
|
||||
u32 tgt_volt;
|
||||
struct omap3_vc_timings *c = vc.timings;
|
||||
|
||||
/*
|
||||
* Oscillator is shut down only if we are using sys_off_mode pad,
|
||||
* thus we set a minimal setup time here
|
||||
*/
|
||||
omap3_set_clksetup(1, voltdm);
|
||||
|
||||
if (off_mode)
|
||||
tgt_volt = voltdm->vc_param->off;
|
||||
else
|
||||
tgt_volt = voltdm->vc_param->ret;
|
||||
|
||||
voltsetup1 = (voltdm->vc_param->on - tgt_volt) /
|
||||
voltdm->pmic->slew_rate;
|
||||
|
||||
voltsetup1 = voltsetup1 * voltdm->sys_clk.rate / 8 / 1000000 + 1;
|
||||
|
||||
voltdm->rmw(voltdm->vfsm->voltsetup_mask,
|
||||
voltsetup1 << __ffs(voltdm->vfsm->voltsetup_mask),
|
||||
voltdm->vfsm->voltsetup_reg);
|
||||
|
||||
/*
|
||||
* pmic is not controlling the voltage scaling during retention,
|
||||
* thus set voltsetup2 to 0
|
||||
*/
|
||||
voltdm->write(0, OMAP3_PRM_VOLTSETUP2_OFFSET);
|
||||
/* Configure PRWDM_POWER_OFF over I2C4 */
|
||||
omap3_init_voltsetup1(voltdm, c, voltdm->vc_param->off);
|
||||
c++;
|
||||
/* Configure PRWDM_POWER_RET over I2C4 */
|
||||
omap3_init_voltsetup1(voltdm, c, voltdm->vc_param->ret);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -275,69 +375,49 @@ static void omap3_set_i2c_timings(struct voltagedomain *voltdm, bool off_mode)
|
|||
*
|
||||
* Calculates and sets up off-mode timings for a channel. Off-mode
|
||||
* can use either I2C based voltage scaling, or alternatively
|
||||
* sys_off_mode pad can be used to send a global command to power IC.
|
||||
* This function first checks which mode is being used, and calls
|
||||
* omap3_set_i2c_timings() if the system is using I2C control mode.
|
||||
* sys_off_mode pad can be used to send a global command to power IC.n,
|
||||
* sys_off_mode has the additional benefit that voltages can be
|
||||
* scaled to zero volt level with TWL4030 / TWL5030, I2C can only
|
||||
* scale to 600mV.
|
||||
*
|
||||
* Note that omap is not controlling the voltage scaling during
|
||||
* off idle signaled by sys_off_mode, so we can keep voltsetup1
|
||||
* as 0.
|
||||
*/
|
||||
static void omap3_set_off_timings(struct voltagedomain *voltdm)
|
||||
{
|
||||
unsigned long clksetup;
|
||||
unsigned long voltsetup2;
|
||||
unsigned long voltsetup2_old;
|
||||
u32 val;
|
||||
u32 tstart, tshut;
|
||||
struct omap3_vc_timings *c = vc.timings;
|
||||
u32 tstart, tshut, clksetup, voltoffset;
|
||||
|
||||
/* check if sys_off_mode is used to control off-mode voltages */
|
||||
val = voltdm->read(OMAP3_PRM_VOLTCTRL_OFFSET);
|
||||
if (!(val & OMAP3430_SEL_OFF_MASK)) {
|
||||
/* No, omap is controlling them over I2C */
|
||||
omap3_set_i2c_timings(voltdm, true);
|
||||
if (c->voltsetup2)
|
||||
return;
|
||||
}
|
||||
|
||||
omap_pm_get_oscillator(&tstart, &tshut);
|
||||
omap3_set_clksetup(tstart, voltdm);
|
||||
|
||||
clksetup = voltdm->read(OMAP3_PRM_CLKSETUP_OFFSET);
|
||||
|
||||
/* voltsetup 2 in us */
|
||||
voltsetup2 = voltdm->vc_param->on / voltdm->pmic->slew_rate;
|
||||
|
||||
/* convert to 32k clk cycles */
|
||||
voltsetup2 = DIV_ROUND_UP(voltsetup2 * 32768, 1000000);
|
||||
|
||||
voltsetup2_old = voltdm->read(OMAP3_PRM_VOLTSETUP2_OFFSET);
|
||||
if (tstart == ULONG_MAX) {
|
||||
pr_debug("PM: oscillator start-up time not initialized, using 10ms\n");
|
||||
clksetup = omap_usec_to_32k(10000);
|
||||
} else {
|
||||
clksetup = omap_usec_to_32k(tstart);
|
||||
}
|
||||
|
||||
/*
|
||||
* Update voltsetup2 if higher than current value (needed because
|
||||
* we have multiple channels with different ramp times), also
|
||||
* update voltoffset always to value recommended by TRM
|
||||
* For twl4030 errata 27, we need to allow minimum ~488.32 us wait to
|
||||
* switch from HFCLKIN to internal oscillator. That means timings
|
||||
* have voltoffset fixed to 0xa in rounded up 32 KiHz cycles. And
|
||||
* that means we can calculate the value based on the oscillator
|
||||
* start-up time since voltoffset2 = clksetup - voltoffset.
|
||||
*/
|
||||
if (voltsetup2 > voltsetup2_old) {
|
||||
voltdm->write(voltsetup2, OMAP3_PRM_VOLTSETUP2_OFFSET);
|
||||
voltdm->write(clksetup - voltsetup2,
|
||||
OMAP3_PRM_VOLTOFFSET_OFFSET);
|
||||
} else
|
||||
voltdm->write(clksetup - voltsetup2_old,
|
||||
OMAP3_PRM_VOLTOFFSET_OFFSET);
|
||||
|
||||
/*
|
||||
* omap is not controlling voltage scaling during off-mode,
|
||||
* thus set voltsetup1 to 0
|
||||
*/
|
||||
voltdm->rmw(voltdm->vfsm->voltsetup_mask, 0,
|
||||
voltdm->vfsm->voltsetup_reg);
|
||||
|
||||
/* voltoffset must be clksetup minus voltsetup2 according to TRM */
|
||||
voltdm->write(clksetup - voltsetup2, OMAP3_PRM_VOLTOFFSET_OFFSET);
|
||||
voltoffset = omap_usec_to_32k(488);
|
||||
c->voltsetup2 = clksetup - voltoffset;
|
||||
voltdm->write(clksetup, OMAP3_PRM_CLKSETUP_OFFSET);
|
||||
voltdm->write(voltoffset, OMAP3_PRM_VOLTOFFSET_OFFSET);
|
||||
}
|
||||
|
||||
static void __init omap3_vc_init_channel(struct voltagedomain *voltdm)
|
||||
{
|
||||
omap3_vc_init_pmic_signaling(voltdm);
|
||||
omap3_set_off_timings(voltdm);
|
||||
omap3_set_i2c_timings(voltdm);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -117,6 +117,9 @@ extern struct omap_vc_param omap4_mpu_vc_data;
|
|||
extern struct omap_vc_param omap4_iva_vc_data;
|
||||
extern struct omap_vc_param omap4_core_vc_data;
|
||||
|
||||
void omap3_vc_set_pmic_signaling(int core_next_state);
|
||||
|
||||
|
||||
void omap_vc_init_channel(struct voltagedomain *voltdm);
|
||||
int omap_vc_pre_scale(struct voltagedomain *voltdm,
|
||||
unsigned long target_volt,
|
||||
|
|
|
@ -98,7 +98,11 @@
|
|||
#define TWL4030_BASEADD_BACKUP 0x0014
|
||||
#define TWL4030_BASEADD_INT 0x002E
|
||||
#define TWL4030_BASEADD_PM_MASTER 0x0036
|
||||
|
||||
#define TWL4030_BASEADD_PM_RECEIVER 0x005B
|
||||
#define TWL4030_DCDC_GLOBAL_CFG 0x06
|
||||
#define SMARTREFLEX_ENABLE BIT(3)
|
||||
|
||||
#define TWL4030_BASEADD_RTC 0x001C
|
||||
#define TWL4030_BASEADD_SECURED_REG 0x0000
|
||||
|
||||
|
@ -1204,6 +1208,11 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
|||
* Disable TWL4030/TWL5030 I2C Pull-up on I2C1 and I2C4(SR) interface.
|
||||
* Program I2C_SCL_CTRL_PU(bit 0)=0, I2C_SDA_CTRL_PU (bit 2)=0,
|
||||
* SR_I2C_SCL_CTRL_PU(bit 4)=0 and SR_I2C_SDA_CTRL_PU(bit 6)=0.
|
||||
*
|
||||
* Also, always enable SmartReflex bit as that's needed for omaps to
|
||||
* to do anything over I2C4 for voltage scaling even if SmartReflex
|
||||
* is disabled. Without the SmartReflex bit omap sys_clkreq idle
|
||||
* signal will never trigger for retention idle.
|
||||
*/
|
||||
if (twl_class_is_4030()) {
|
||||
u8 temp;
|
||||
|
@ -1212,6 +1221,12 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
|||
temp &= ~(SR_I2C_SDA_CTRL_PU | SR_I2C_SCL_CTRL_PU | \
|
||||
I2C_SDA_CTRL_PU | I2C_SCL_CTRL_PU);
|
||||
twl_i2c_write_u8(TWL4030_MODULE_INTBR, temp, REG_GPPUPDCTR1);
|
||||
|
||||
twl_i2c_read_u8(TWL_MODULE_PM_RECEIVER, &temp,
|
||||
TWL4030_DCDC_GLOBAL_CFG);
|
||||
temp |= SMARTREFLEX_ENABLE;
|
||||
twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, temp,
|
||||
TWL4030_DCDC_GLOBAL_CFG);
|
||||
}
|
||||
|
||||
if (node) {
|
||||
|
|
|
@ -69,5 +69,17 @@
|
|||
#define OMAP5_WKUP_IOPAD(pa, val) OMAP_IOPAD_OFFSET((pa), 0xc840) (val)
|
||||
#define DRA7XX_CORE_IOPAD(pa, val) OMAP_IOPAD_OFFSET((pa), 0x3400) (val)
|
||||
|
||||
/*
|
||||
* Define some commonly used pins configured by the boards.
|
||||
* Note that some boards use alternative pins, so check
|
||||
* the schematics before using these.
|
||||
*/
|
||||
#define OMAP3_UART1_RX 0x152
|
||||
#define OMAP3_UART2_RX 0x14a
|
||||
#define OMAP3_UART3_RX 0x16e
|
||||
#define OMAP4_UART2_RX 0xdc
|
||||
#define OMAP4_UART3_RX 0x104
|
||||
#define OMAP4_UART4_RX 0x11c
|
||||
|
||||
#endif
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче