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:
Olof Johansson 2014-05-26 13:24:56 -07:00
commit 2ca602de42
17 changed files with 298 additions and 163 deletions

View File

@ -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>;
};

View File

@ -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>;

View File

@ -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>;
};

View File

@ -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";

View File

@ -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>;

View File

@ -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>;
};

View File

@ -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>;
};

View File

@ -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 */
>;
};
};

View File

@ -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

View File

@ -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;
}

View File

@ -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();

View File

@ -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();
/*

View File

@ -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

View File

@ -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);
}
/**

View File

@ -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,

View File

@ -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) {

View File

@ -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