aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-omap2
diff options
context:
space:
mode:
authorColin Cross <ccross@android.com>2011-11-03 22:09:11 -0700
committerColin Cross <ccross@android.com>2011-11-03 22:09:11 -0700
commitf1e5f49f2f2ed46e5356e091de1e86dc08b20d85 (patch)
treebfc8970948e006af8069a5f732bbd59c0f18bf34 /arch/arm/mach-omap2
parent70c7a98bb28405787cf7aaf9d8a216b559bd4a35 (diff)
parent90672f17369273aba3fb402d5c41752686c65d53 (diff)
downloadkernel_samsung_tuna-f1e5f49f2f2ed46e5356e091de1e86dc08b20d85.zip
kernel_samsung_tuna-f1e5f49f2f2ed46e5356e091de1e86dc08b20d85.tar.gz
kernel_samsung_tuna-f1e5f49f2f2ed46e5356e091de1e86dc08b20d85.tar.bz2
Merge branch 'android-omap-3.0' into android-omap-tuna-3.0
Conflicts: arch/arm/mach-omap2/dpll3xxx.c Change-Id: Ie53daed5cabbadef73d18969263ff2f7b77b3dc7
Diffstat (limited to 'arch/arm/mach-omap2')
-rw-r--r--arch/arm/mach-omap2/clock.h1
-rw-r--r--arch/arm/mach-omap2/dpll3xxx.c58
-rw-r--r--arch/arm/mach-omap2/mailbox.c3
-rw-r--r--arch/arm/mach-omap2/mux.c49
-rw-r--r--arch/arm/mach-omap2/mux.h20
-rw-r--r--arch/arm/mach-omap2/pm24xx.c2
-rw-r--r--arch/arm/mach-omap2/pm34xx.c2
-rwxr-xr-xarch/arm/mach-omap2/pm44xx.c19
-rw-r--r--arch/arm/mach-omap2/prcm-debug.c11
9 files changed, 137 insertions, 28 deletions
diff --git a/arch/arm/mach-omap2/clock.h b/arch/arm/mach-omap2/clock.h
index da332d2..450aabf 100644
--- a/arch/arm/mach-omap2/clock.h
+++ b/arch/arm/mach-omap2/clock.h
@@ -41,6 +41,7 @@
/* CM_CLKEN_PLL*.EN* bit values - not all are available for every DPLL */
#define DPLL_LOW_POWER_STOP 0x1
+#define DPLL_MN_BYPASS 0x4
#define DPLL_LOW_POWER_BYPASS 0x5
#define DPLL_LOCKED 0x7
diff --git a/arch/arm/mach-omap2/dpll3xxx.c b/arch/arm/mach-omap2/dpll3xxx.c
index 38207d5..2499afb 100644
--- a/arch/arm/mach-omap2/dpll3xxx.c
+++ b/arch/arm/mach-omap2/dpll3xxx.c
@@ -32,8 +32,10 @@
#include <plat/clock.h>
#include "clock.h"
+#include "cm2_44xx.h"
#include "cm2xxx_3xxx.h"
#include "cm-regbits-34xx.h"
+#include "cm-regbits-44xx.h"
/* CM_AUTOIDLE_PLL*.AUTO_* bit values */
#define DPLL_AUTOIDLE_DISABLE 0x0
@@ -61,24 +63,75 @@ static void _omap3_dpll_write_clken(struct clk *clk, u8 clken_bits)
static int _omap3_wait_dpll_status(struct clk *clk, u8 state)
{
const struct dpll_data *dd;
- int i = 0;
+ int i;
int ret = -EINVAL;
+ bool first_time = true;
+ u32 reg;
+ u32 orig_cm_div_m2_dpll_usb;
+ u32 orig_cm_clkdcoldo_dpll_usb;
+retry:
dd = clk->dpll_data;
state <<= __ffs(dd->idlest_mask);
+ i = 0;
while (((__raw_readl(dd->idlest_reg) & dd->idlest_mask) != state) &&
i < MAX_DPLL_WAIT_TRIES) {
i++;
udelay(1);
}
+ /* restore back old values if hit work-around */
+ if (!first_time) {
+ __raw_writel(orig_cm_div_m2_dpll_usb,
+ OMAP4430_CM_DIV_M2_DPLL_USB);
+ __raw_writel(orig_cm_clkdcoldo_dpll_usb,
+ OMAP4430_CM_CLKDCOLDO_DPLL_USB);
+ }
+
if (i == MAX_DPLL_WAIT_TRIES) {
printk(KERN_ERR "clock: %s failed transition to '%s'\n",
clk->name, (state) ? "locked" : "bypassed");
- /* Catch failing usb-dpll lock error */
+
+ /* Try Error Recovery: for failing usbdpll locking */
if (!strcmp(clk->name, "dpll_usb_ck")) {
+ reg = __raw_readl(dd->mult_div1_reg);
+
+ /* Put in MN bypass */
+ _omap3_dpll_write_clken(clk, DPLL_MN_BYPASS);
+ i = 0;
+ while (!(__raw_readl(dd->idlest_reg) & (1 << OMAP4430_ST_MN_BYPASS_SHIFT)) &&
+ i < MAX_DPLL_WAIT_TRIES) {
+ i++;
+ udelay(1);
+ }
+
+ /* MN bypass looses contents of CM_CLKSEL_DPLL_USB */
+ __raw_writel(reg, dd->mult_div1_reg);
+
+ /* Force generate request to PRCM: put in Force mode */
+
+ /* a) CM_DIV_M2_DPLL_USB.DPLL_CLKOUT_GATE_CTRL = 1 */
+ orig_cm_div_m2_dpll_usb = __raw_readl(OMAP4430_CM_DIV_M2_DPLL_USB);
+ __raw_writel(orig_cm_div_m2_dpll_usb |
+ (1 << OMAP4430_DPLL_CLKOUT_GATE_CTRL_SHIFT),
+ OMAP4430_CM_DIV_M2_DPLL_USB);
+
+ /* b) CM_CLKDCOLDO_DPLL_USB.DPLL_CLKDCOLDO_GATE_CTRL = 1 */
+ orig_cm_clkdcoldo_dpll_usb = __raw_readl(OMAP4430_CM_CLKDCOLDO_DPLL_USB);
+ __raw_writel(orig_cm_clkdcoldo_dpll_usb |
+ (1 << OMAP4430_DPLL_CLKDCOLDO_GATE_CTRL_SHIFT),
+ OMAP4430_CM_CLKDCOLDO_DPLL_USB);
+
+ /* Put back to locked mode */
+ _omap3_dpll_write_clken(clk, DPLL_LOCKED);
+
+ if (first_time) {
+ first_time = false;
+ goto retry;
+ }
+
pr_info("\n========== USB DPLL DUMP ===========\n");
pr_info("CM_CLKMODE_DPLL_USB :%08x\n", omap_readl(0x4A008180));
pr_info("CM_IDLEST_DPLL_USB :%08x\n", omap_readl(0x4A008184));
@@ -90,7 +143,6 @@ static int _omap3_wait_dpll_status(struct clk *clk, u8 state)
pr_info("CM_CLKDCOLDO_DPLL_USB :%08x\n", omap_readl(0x4A0081B4));
pr_info("========== USB DPLL DUMP: End ===========\n");
}
-
} else {
pr_debug("clock: %s transition to '%s' in %d loops\n",
clk->name, (state) ? "locked" : "bypassed", i);
diff --git a/arch/arm/mach-omap2/mailbox.c b/arch/arm/mach-omap2/mailbox.c
index d94205d..74750bf 100644
--- a/arch/arm/mach-omap2/mailbox.c
+++ b/arch/arm/mach-omap2/mailbox.c
@@ -397,6 +397,9 @@ static int __devinit omap2_mbox_probe(struct platform_device *pdev)
}
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!mem)
+ return -ENODEV;
+
mbox_base = ioremap(mem->start, resource_size(mem));
if (!mbox_base)
return -ENOMEM;
diff --git a/arch/arm/mach-omap2/mux.c b/arch/arm/mach-omap2/mux.c
index c3caae2..a2ed524 100644
--- a/arch/arm/mach-omap2/mux.c
+++ b/arch/arm/mach-omap2/mux.c
@@ -936,7 +936,7 @@ static struct omap_mux *omap_mux_get_by_gpio(
}
/* Needed for dynamic muxing of GPIO pins for off-idle */
-u16 omap_mux_get_gpio(int gpio)
+struct omap_mux *omap_mux_get_gpio(int gpio)
{
struct omap_mux_partition *partition;
struct omap_mux *m = NULL;
@@ -944,13 +944,10 @@ u16 omap_mux_get_gpio(int gpio)
list_for_each_entry(partition, &mux_partitions, node) {
m = omap_mux_get_by_gpio(partition, gpio);
if (m)
- return omap_mux_read(partition, m->reg_offset);
+ return m;
}
- if (!m || m->reg_offset == OMAP_MUX_TERMINATOR)
- pr_err("%s: Could not get gpio%i\n", __func__, gpio);
-
- return OMAP_MUX_TERMINATOR;
+ return NULL;
}
/* Needed for dynamic muxing of GPIO pins for off-idle */
@@ -971,6 +968,45 @@ void omap_mux_set_gpio(u16 val, int gpio)
pr_err("%s: Could not set gpio%i\n", __func__, gpio);
}
+/* Has no locking, don't use on a pad that is remuxed (by hwmod or otherwise) */
+bool omap_mux_get_wakeupenable(struct omap_mux *m)
+{
+ u16 val;
+ if (IS_ERR_OR_NULL(m))
+ return false;
+
+ val = omap_mux_read(m->partition, m->reg_offset);
+ return val & OMAP_PIN_OFF_WAKEUPENABLE;
+}
+
+/* Has no locking, don't use on a pad that is remuxed (by hwmod or otherwise) */
+int omap_mux_set_wakeupenable(struct omap_mux *m)
+{
+ u16 val;
+ if (IS_ERR_OR_NULL(m))
+ return -EINVAL;
+
+ val = omap_mux_read(m->partition, m->reg_offset);
+ val |= OMAP_PIN_OFF_WAKEUPENABLE;
+ omap_mux_write(m->partition, val, m->reg_offset);
+
+ return 0;
+}
+
+/* Has no locking, don't use on a pad that is remuxed (by hwmod or otherwise) */
+int omap_mux_clear_wakeupenable(struct omap_mux *m)
+{
+ u16 val;
+ if (IS_ERR_OR_NULL(m))
+ return -EINVAL;
+
+ val = omap_mux_read(m->partition, m->reg_offset);
+ val &= ~OMAP_PIN_OFF_WAKEUPENABLE;
+ omap_mux_write(m->partition, val, m->reg_offset);
+
+ return 0;
+}
+
static struct omap_mux * __init omap_mux_list_add(
struct omap_mux_partition *partition,
struct omap_mux *src)
@@ -984,6 +1020,7 @@ static struct omap_mux * __init omap_mux_list_add(
m = &entry->mux;
entry->mux = *src;
+ m->partition = partition;
#ifdef CONFIG_OMAP_MUX
if (omap_mux_copy_names(src, m)) {
diff --git a/arch/arm/mach-omap2/mux.h b/arch/arm/mach-omap2/mux.h
index 47c47d1..87bf022 100644
--- a/arch/arm/mach-omap2/mux.h
+++ b/arch/arm/mach-omap2/mux.h
@@ -131,6 +131,7 @@ struct omap_mux_partition {
struct omap_mux {
u16 reg_offset;
u16 gpio;
+ struct omap_mux_partition *partition;
#ifdef CONFIG_OMAP_MUX
char *muxnames[OMAP_MUX_NR_MODES];
#ifdef CONFIG_DEBUG_FS
@@ -264,11 +265,26 @@ static struct omap_board_mux *board_mux __initdata __maybe_unused;
#endif
/**
- * omap_mux_get_gpio() - get mux register value based on GPIO number
+ * omap_mux_get_gpio() - get mux struct based on GPIO number
* @gpio: GPIO number
*
*/
-u16 omap_mux_get_gpio(int gpio);
+struct omap_mux *omap_mux_get_gpio(int gpio);
+
+/** omap_mux_set_wakeupenable() - set the wakeupenable bit on a mux struct
+ * @m: mux struct
+ */
+int omap_mux_set_wakeupenable(struct omap_mux *m);
+
+/** omap_mux_clear_wakeupenable() - clear the wakeupenable bit on a mux struct
+ * @m: mux struct
+ */
+int omap_mux_clear_wakeupenable(struct omap_mux *m);
+
+/** omap_mux_get_wakeupenable() - get the wakeupenable bit from a mux struct
+ * @m: mux struct
+ */
+bool omap_mux_get_wakeupenable(struct omap_mux *m);
/**
* omap_mux_set_gpio() - set mux register value based on GPIO number
diff --git a/arch/arm/mach-omap2/pm24xx.c b/arch/arm/mach-omap2/pm24xx.c
index fb999bc..faa8463 100644
--- a/arch/arm/mach-omap2/pm24xx.c
+++ b/arch/arm/mach-omap2/pm24xx.c
@@ -148,7 +148,7 @@ no_sleep:
tmp = timespec_to_ns(&ts_idle) * NSEC_PER_USEC;
omap2_pm_dump(0, 1, tmp);
}
- omap2_gpio_resume_after_idle();
+ omap2_gpio_resume_after_idle(0);
clk_enable(osc_ck);
diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index 321a7e6..535480f 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -449,7 +449,7 @@ void omap_sram_idle(void)
/* PER */
if (per_next_state < PWRDM_POWER_ON) {
per_prev_state = pwrdm_read_prev_pwrst(per_pwrdm);
- omap2_gpio_resume_after_idle();
+ omap2_gpio_resume_after_idle(per_going_off);
}
/* Disable IO-PAD and IO-CHAIN wakeup */
diff --git a/arch/arm/mach-omap2/pm44xx.c b/arch/arm/mach-omap2/pm44xx.c
index 8c21358..8b47481 100755
--- a/arch/arm/mach-omap2/pm44xx.c
+++ b/arch/arm/mach-omap2/pm44xx.c
@@ -142,6 +142,7 @@ void omap4_enter_sleep(unsigned int cpu, unsigned int power_state, bool suspend)
int per_next_state = PWRDM_POWER_ON;
int core_next_state = PWRDM_POWER_ON;
int mpu_next_state = PWRDM_POWER_ON;
+ int ret;
pwrdm_clear_all_prev_pwrst(cpu0_pwrdm);
pwrdm_clear_all_prev_pwrst(mpu_pwrdm);
@@ -154,6 +155,10 @@ void omap4_enter_sleep(unsigned int cpu, unsigned int power_state, bool suspend)
core_next_state = pwrdm_read_next_pwrst(core_pwrdm);
mpu_next_state = pwrdm_read_next_pwrst(mpu_pwrdm);
+ ret = omap2_gpio_prepare_for_idle(omap4_device_next_state_off());
+ if (ret)
+ goto abort_gpio;
+
if (mpu_next_state < PWRDM_POWER_INACTIVE) {
if (omap_dvfs_is_scaling(mpu_voltdm)) {
mpu_next_state = PWRDM_POWER_INACTIVE;
@@ -190,10 +195,7 @@ void omap4_enter_sleep(unsigned int cpu, unsigned int power_state, bool suspend)
}
}
- omap2_gpio_set_edge_wakeup();
-
if (omap4_device_next_state_off()) {
- omap2_gpio_prepare_for_idle(true);
omap_gpmc_save_context();
omap_dma_global_context_save();
}
@@ -248,26 +250,21 @@ abort_device_off:
}
if (omap4_device_next_state_off()) {
- /*
- * GPIO: since we have put_synced clks, we need to resume
- * even if OFF was not really achieved
- */
- omap2_gpio_resume_after_idle();
-
/* Disable the extension of Non-EMIF I/O isolation */
omap4_prminst_rmw_inst_reg_bits(OMAP4430_ISOOVR_EXTEND_MASK,
0, OMAP4430_PRM_PARTITION,
OMAP4430_PRM_DEVICE_INST, OMAP4_PRM_IO_PMCTRL_OFFSET);
}
- omap2_gpio_restore_edge_wakeup();
-
if (mpu_next_state < PWRDM_POWER_INACTIVE) {
omap_vc_set_auto_trans(mpu_voltdm,
OMAP_VC_CHANNEL_AUTO_TRANSITION_DISABLE);
omap_sr_enable(mpu_voltdm);
}
+ omap2_gpio_resume_after_idle(omap4_device_next_state_off());
+
+abort_gpio:
return;
}
diff --git a/arch/arm/mach-omap2/prcm-debug.c b/arch/arm/mach-omap2/prcm-debug.c
index 12e3e55..ab638c2 100644
--- a/arch/arm/mach-omap2/prcm-debug.c
+++ b/arch/arm/mach-omap2/prcm-debug.c
@@ -1480,6 +1480,8 @@ static void prcmdebug_dump_real_cd(struct seq_file *sf, struct d_clkd_info *cd,
u32 clktrctrl =
omap4_cminst_read_inst_reg(cd->prcm_partition, cd->cm_inst,
cd->clkdm_offs + OMAP4_CM_CLKSTCTRL);
+ u32 mode = (clktrctrl & OMAP4430_CLKTRCTRL_MASK) >>
+ OMAP4430_CLKTRCTRL_SHIFT;
u32 activity = clktrctrl & cd->activity;
#if 0
u32 staticdep =
@@ -1492,9 +1494,10 @@ static void prcmdebug_dump_real_cd(struct seq_file *sf, struct d_clkd_info *cd,
int i;
#endif
- d_pr(sf, " %s mode=%s", cd->name,
- cmtrctrl_s[(clktrctrl & OMAP4430_CLKTRCTRL_MASK) >>
- OMAP4430_CLKTRCTRL_SHIFT]);
+ if (flags & PRCMDEBUG_LASTSLEEP && mode == 3 /* HW_AUTO */)
+ return;
+
+ d_pr(sf, " %s mode=%s", cd->name, cmtrctrl_s[mode]);
d_pr_ctd(sf, " activity=0x%x", activity);
@@ -1525,7 +1528,7 @@ static void prcmdebug_dump_cd(struct seq_file *sf, struct d_clkd_info *cd,
if (cd->cm_inst != -1) {
prcmdebug_dump_real_cd(sf, cd, flags);
- } else {
+ } else if (!(flags & PRCMDEBUG_LASTSLEEP)) {
d_pr(sf, " %s\n", cd->name);
}