diff options
46 files changed, 813 insertions, 289 deletions
diff --git a/arch/arm/mach-omap1/mailbox.c b/arch/arm/mach-omap1/mailbox.c index c0e1f48aa11..99971bf73b2 100644 --- a/arch/arm/mach-omap1/mailbox.c +++ b/arch/arm/mach-omap1/mailbox.c @@ -151,6 +151,9 @@ static int __devinit omap1_mbox_probe(struct platform_device *pdev) list[0]->irq = platform_get_irq_byname(pdev, "dsp"); 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/clock.h b/arch/arm/mach-omap2/clock.h index da332d2b4af..450aabf4609 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/devices.c b/arch/arm/mach-omap2/devices.c index 4979efd5396..ef7c65e5f4d 100644 --- a/arch/arm/mach-omap2/devices.c +++ b/arch/arm/mach-omap2/devices.c @@ -491,6 +491,39 @@ static void omap_init_audio(void) static inline void omap_init_audio(void) {} #endif +#if defined(CONFIG_SND_OMAP_SOC_MCASP) || \ + defined(CONFIG_SND_OMAP_SOC_MCASP_MODULE) +static struct omap_device_pm_latency omap_mcasp_latency[] = { + { + .deactivate_func = omap_device_idle_hwmods, + .activate_func = omap_device_enable_hwmods, + .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST, + }, +}; + +static void omap_init_mcasp(void) +{ + struct omap_hwmod *oh; + struct omap_device *od; + char *oh_name = "omap-mcasp-dai"; + char *dev_name = "omap-mcasp-dai"; + + oh = omap_hwmod_lookup(oh_name); + if (!oh) { + pr_err("%s: could not look up %s\n", __func__, oh_name); + return; + } + + od = omap_device_build(dev_name, -1, oh, NULL, 0, + omap_mcasp_latency, + ARRAY_SIZE(omap_mcasp_latency), 0); + WARN(IS_ERR(od), "could not build omap_device for %s:%s\n", + oh_name, dev_name); +} +#else +static inline void omap_init_mcasp(void) {} +#endif + #if defined(CONFIG_SPI_OMAP24XX) || defined(CONFIG_SPI_OMAP24XX_MODULE) #include <plat/mcspi.h> @@ -911,6 +944,7 @@ static int __init omap2_init_devices(void) omap_init_audio(); omap_init_camera(); omap_init_mbox(); + omap_init_mcasp(); omap_init_mcspi(); omap_init_pmu(); omap_hdq_init(); diff --git a/arch/arm/mach-omap2/dpll3xxx.c b/arch/arm/mach-omap2/dpll3xxx.c index 73a1595c5f2..7fb0d21b6b1 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,22 +63,76 @@ 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"); + + /* 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; + } + } } else { pr_debug("clock: %s transition to '%s' in %d loops\n", clk->name, (state) ? "locked" : "bypassed", i); @@ -135,11 +191,20 @@ static u16 _omap3_dpll_compute_freqsel(struct clk *clk, u8 n) */ static int _omap3_noncore_dpll_lock(struct clk *clk) { + const struct dpll_data *dd; u8 ai; - int r; + u8 state = 1; + int r = 0; pr_debug("clock: locking DPLL %s\n", clk->name); + dd = clk->dpll_data; + state <<= __ffs(dd->idlest_mask); + + /* Check if already locked */ + if ((__raw_readl(dd->idlest_reg) & dd->idlest_mask) == state) + goto done; + ai = omap3_dpll_autoidle_read(clk); omap3_dpll_deny_idle(clk); @@ -151,6 +216,7 @@ static int _omap3_noncore_dpll_lock(struct clk *clk) if (ai) omap3_dpll_allow_idle(clk); +done: return r; } diff --git a/arch/arm/mach-omap2/include/mach/ctrl_module_pad_core_44xx.h b/arch/arm/mach-omap2/include/mach/ctrl_module_pad_core_44xx.h index 2f9b0551d03..6cdb5d494c9 100644 --- a/arch/arm/mach-omap2/include/mach/ctrl_module_pad_core_44xx.h +++ b/arch/arm/mach-omap2/include/mach/ctrl_module_pad_core_44xx.h @@ -1189,6 +1189,10 @@ #define OMAP4_LPDDR21_VREF_EN_CA_MASK (1 << 3) #define OMAP4_LPDDR21_VREF_EN_DQ_SHIFT 2 #define OMAP4_LPDDR21_VREF_EN_DQ_MASK (1 << 2) +#define OMAP4_LPDDR21_VREF_AUTO_EN_CA_SHIFT 1 +#define OMAP4_LPDDR21_VREF_AUTO_EN_CA_MASK (1 << 1) +#define OMAP4_LPDDR21_VREF_AUTO_EN_DQ_SHIFT 0 +#define OMAP4_LPDDR21_VREF_AUTO_EN_DQ_MASK (1 << 0) /* CONTROL_LPDDR2IO2_0 */ #define OMAP4_LPDDR2IO2_GR4_SR_SHIFT 30 diff --git a/arch/arm/mach-omap2/mailbox.c b/arch/arm/mach-omap2/mailbox.c index d94205d819e..74750bfd9ed 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 637ce2def14..d2ef973e86b 100644 --- a/arch/arm/mach-omap2/mux.c +++ b/arch/arm/mach-omap2/mux.c @@ -971,7 +971,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; @@ -979,13 +979,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 */ @@ -1006,6 +1003,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) @@ -1019,6 +1055,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 3447c374de6..063b158a588 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 @@ -281,11 +282,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 fb999bc0eea..faa84634402 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 321a7e69d7b..535480f5527 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 aaaebd8194f..42582a8f12c 100644 --- a/arch/arm/mach-omap2/pm44xx.c +++ b/arch/arm/mach-omap2/pm44xx.c @@ -126,6 +126,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); @@ -138,6 +139,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; @@ -174,10 +179,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(); } @@ -232,26 +234,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; } @@ -752,13 +749,15 @@ static void __init syscontrol_setup_regs(void) { u32 v; - /* Disable LPDDR VREF manual control */ + /* Disable LPDDR VREF manual control and enable Auto control */ v = omap4_ctrl_pad_readl(OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_LPDDR2IO1_3); v &= ~(OMAP4_LPDDR21_VREF_EN_CA_MASK | OMAP4_LPDDR21_VREF_EN_DQ_MASK); + v |= OMAP4_LPDDR21_VREF_AUTO_EN_CA_MASK | OMAP4_LPDDR21_VREF_AUTO_EN_DQ_MASK; omap4_ctrl_pad_writel(v, OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_LPDDR2IO1_3); v = omap4_ctrl_pad_readl(OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_LPDDR2IO2_3); v &= ~(OMAP4_LPDDR21_VREF_EN_CA_MASK | OMAP4_LPDDR21_VREF_EN_DQ_MASK); + v |= OMAP4_LPDDR21_VREF_AUTO_EN_CA_MASK | OMAP4_LPDDR21_VREF_AUTO_EN_DQ_MASK; omap4_ctrl_pad_writel(v, OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_LPDDR2IO2_3); /* diff --git a/arch/arm/mach-omap2/prcm-debug.c b/arch/arm/mach-omap2/prcm-debug.c index 12e3e555003..ab638c2e973 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); } diff --git a/arch/arm/plat-omap/Makefile b/arch/arm/plat-omap/Makefile index c3fa01564fe..476d817d1d7 100644 --- a/arch/arm/plat-omap/Makefile +++ b/arch/arm/plat-omap/Makefile @@ -15,7 +15,8 @@ obj-$(CONFIG_ARCH_OMAP16XX) += ocpi.o # omap_device support (OMAP2+ only at the moment) obj-$(CONFIG_ARCH_OMAP2) += omap_device.o obj-$(CONFIG_ARCH_OMAP3) += omap_device.o -obj-$(CONFIG_ARCH_OMAP4) += omap_device.o rproc_user.o +obj-$(CONFIG_ARCH_OMAP4) += omap_device.o +obj-$(CONFIG_REMOTE_PROC) += rproc_user.o obj-$(CONFIG_OMAP_MCBSP) += mcbsp.o obj-$(CONFIG_OMAP_RPMSG) += omap_rpmsg.o diff --git a/arch/arm/plat-omap/devices.c b/arch/arm/plat-omap/devices.c index 2bf146fbcac..70d8f8d3bc1 100644 --- a/arch/arm/plat-omap/devices.c +++ b/arch/arm/plat-omap/devices.c @@ -29,7 +29,6 @@ #include <plat/mmc.h> #include <mach/gpio.h> #include <plat/menelaus.h> -#include <plat/mcasp.h> #include <plat/mcbsp.h> #include <plat/remoteproc.h> #include <plat/omap44xx.h> @@ -77,43 +76,6 @@ void omap_mcbsp_register_board_cfg(struct resource *res, int res_count, { } #endif - -/*-------------------------------------------------------------------------*/ - -#if defined(CONFIG_SND_OMAP_SOC_MCASP) || \ - defined(CONFIG_SND_OMAP_SOC_MCASP_MODULE) - -static struct omap_device_pm_latency omap_mcasp_latency[] = { - { - .deactivate_func = omap_device_idle_hwmods, - .activate_func = omap_device_enable_hwmods, - .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST, - }, -}; - -void omap_init_mcasp(struct omap_mcasp_platform_data *pdata) -{ - struct omap_hwmod *oh; - struct omap_device *od; - - oh = omap_hwmod_lookup("omap-mcasp-dai"); - if (!oh) { - printk(KERN_ERR "Could not look up mcasp hw_mod\n"); - return; - } - - od = omap_device_build("omap-mcasp-dai", -1, oh, pdata, - sizeof(struct omap_mcasp_platform_data), - omap_mcasp_latency, - ARRAY_SIZE(omap_mcasp_latency), 0); - - if (od <= 0) - printk(KERN_ERR "Could not build omap_device for omap-mcasp-dai\n"); -} -#else -inline void omap_init_mcasp(struct omap_mcasp_platform_data *pdata) {} -#endif - /*-------------------------------------------------------------------------*/ #if defined(CONFIG_SND_OMAP_SOC_DMIC) || \ diff --git a/arch/arm/plat-omap/include/plat/gpio.h b/arch/arm/plat-omap/include/plat/gpio.h index 89af4ad8a37..0b1f7c539d1 100644 --- a/arch/arm/plat-omap/include/plat/gpio.h +++ b/arch/arm/plat-omap/include/plat/gpio.h @@ -213,12 +213,10 @@ struct omap_gpio_platform_data { struct omap_gpio_reg_offs *regs; }; -extern void omap2_gpio_prepare_for_idle(int off_mode); -extern void omap2_gpio_resume_after_idle(void); +extern int omap2_gpio_prepare_for_idle(int off_mode); +extern void omap2_gpio_resume_after_idle(int off_mode); extern void omap_set_gpio_debounce(int gpio, int enable); extern void omap_set_gpio_debounce_time(int gpio, int enable); -extern void omap2_gpio_set_edge_wakeup(void); -extern void omap2_gpio_restore_edge_wakeup(void); /*-------------------------------------------------------------------------*/ /* Wrappers for "new style" GPIO calls, using the new infrastructure diff --git a/arch/arm/plat-omap/iovmm.c b/arch/arm/plat-omap/iovmm.c index 83a37c54342..6e711b94026 100644 --- a/arch/arm/plat-omap/iovmm.c +++ b/arch/arm/plat-omap/iovmm.c @@ -163,10 +163,10 @@ static void sgtable_free(struct sg_table *sgt) if (!sgt) return; + pr_debug("%s: sgt:%p\n", __func__, sgt); + sg_free_table(sgt); kfree(sgt); - - pr_debug("%s: sgt:%p\n", __func__, sgt); } /* map 'sglist' to a contiguous mpu virtual area and return 'va' */ diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index d91a5aa5cc8..5b45bc1d9af 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -21,6 +21,7 @@ #include <linux/io.h> #include <linux/slab.h> #include <linux/pm_runtime.h> +#include <linux/bitops.h> #include <mach/hardware.h> #include <asm/irq.h> @@ -29,6 +30,8 @@ #include <asm/mach/irq.h> #include <plat/omap-pm.h> +#include "../mux.h" + static LIST_HEAD(omap_gpio_list); struct gpio_regs { @@ -46,6 +49,7 @@ struct gpio_regs { u32 debounce_en; u32 edge_falling; u32 edge_rising; + u32 pad_set_wakeupenable; }; struct gpio_bank { @@ -81,6 +85,8 @@ struct gpio_bank { void (*set_dataout)(struct gpio_bank *bank, int gpio, int enable); struct omap_gpio_reg_offs *regs; + + struct omap_mux *mux[32]; }; static void omap_gpio_mod_init(struct gpio_bank *bank); @@ -761,6 +767,7 @@ static struct irq_chip gpio_irq_chip = { .irq_unmask = gpio_unmask_irq, .irq_set_type = gpio_irq_type, .irq_set_wake = gpio_wake_enable, + .flags = IRQCHIP_MASK_ON_SUSPEND, }; /*---------------------------------------------------------------------*/ @@ -941,6 +948,8 @@ static struct lock_class_key gpio_lock_class; static void omap_gpio_mod_init(struct gpio_bank *bank) { + int i; + if (bank->width == 32) { u32 clr_all = 0; /* clear all the bits */ u32 set_all = 0xFFFFFFFF; /* set all the bits */ @@ -1036,6 +1045,11 @@ static void omap_gpio_mod_init(struct gpio_bank *bank) ULPD_CAM_CLK_CTRL); } } + + for (i = 0; i < bank->width; i++) { + int gpio = irq_to_gpio(bank->virtual_irq_start + i); + bank->mux[i] = omap_mux_get_gpio(gpio); + } } static __init void @@ -1271,6 +1285,35 @@ static int omap_gpio_resume(struct device *dev) #ifdef CONFIG_ARCH_OMAP2PLUS static void omap_gpio_save_context(struct gpio_bank *bank); static void omap_gpio_restore_context(struct gpio_bank *bank); + +static void omap2_gpio_set_wakeupenables(struct gpio_bank *bank) +{ + unsigned long pad_wakeup; + int i; + + bank->context.pad_set_wakeupenable = 0; + + pad_wakeup = __raw_readl(bank->base + bank->regs->irqenable); + + for_each_set_bit(i, &pad_wakeup, bank->width) { + if (!omap_mux_get_wakeupenable(bank->mux[i])) { + bank->context.pad_set_wakeupenable |= BIT(i); + omap_mux_set_wakeupenable(bank->mux[i]); + } + } +} + +static void omap2_gpio_clear_wakeupenables(struct gpio_bank *bank) +{ + unsigned long pad_wakeup; + int i; + + pad_wakeup = bank->context.pad_set_wakeupenable; + + for_each_set_bit(i, &pad_wakeup, bank->width) + omap_mux_clear_wakeupenable(bank->mux[i]); +} + #endif static int omap_gpio_pm_runtime_suspend(struct device *dev) @@ -1385,100 +1428,125 @@ static int omap_gpio_pm_runtime_resume(struct device *dev) } #ifdef CONFIG_ARCH_OMAP2PLUS -void omap2_gpio_set_edge_wakeup(void) +static int omap2_gpio_set_edge_wakeup(struct gpio_bank *bank) { - struct gpio_bank *bank; + int ret = 0; + u32 wkup_status = 0; + u32 datain; - list_for_each_entry(bank, &omap_gpio_list, node) { - u32 level_low = 0; - u32 level_high = 0; - u32 wkup_status = 0; + if (pm_runtime_get_sync(bank->dev) < 0) { + dev_err(bank->dev, "%s: GPIO bank %d pm_runtime_get_sync " + "failed\n", __func__, bank->id); + return -EINVAL; + } - if (pm_runtime_get_sync(bank->dev) < 0) { - dev_err(bank->dev, "%s: GPIO bank %d pm_runtime_get_sync " - "failed\n", __func__, bank->id); - return; - } + bank->context.leveldetect0 = __raw_readl(bank->base + + bank->regs->leveldetect0); + bank->context.leveldetect1 = __raw_readl(bank->base + + bank->regs->leveldetect1); + wkup_status = __raw_readl(bank->base + + bank->regs->wkup_status); + bank->context.edge_falling = __raw_readl(bank->base + + bank->regs->fallingdetect); + bank->context.edge_rising = __raw_readl(bank->base + + bank->regs->risingdetect); - level_low = __raw_readl(bank->base + - bank->regs->leveldetect0); - level_high = __raw_readl(bank->base + - bank->regs->leveldetect1); - wkup_status = __raw_readl(bank->base + - bank->regs->wkup_status); - bank->context.edge_falling = __raw_readl(bank->base + - bank->regs->fallingdetect); - bank->context.edge_rising = __raw_readl(bank->base + - bank->regs->risingdetect); + /* + * Set edge trigger for all gpio's that are + * expected to produce wakeup from low power. + * even if they are set for level detection only. + */ + __raw_writel(bank->context.edge_falling | + (bank->context.leveldetect0 & wkup_status), + (bank->base + bank->regs->fallingdetect)); + __raw_writel(bank->context.edge_rising | + (bank->context.leveldetect1 & wkup_status), + (bank->base + bank->regs->risingdetect)); + __raw_writel(0, bank->base + bank->regs->leveldetect0); + __raw_writel(0, bank->base + bank->regs->leveldetect1); - /* - * Set edge trigger for all gpio's that are - * expected to produce wakeup from low power. - * even if they are set for level detection only. - */ - __raw_writel(bank->context.edge_falling | (level_low & wkup_status), - (bank->base + bank->regs->fallingdetect)); - __raw_writel(bank->context.edge_rising | (level_high & wkup_status), - (bank->base + bank->regs->risingdetect)); - - if (pm_runtime_put_sync_suspend(bank->dev) < 0) { - dev_err(bank->dev, "%s: GPIO bank %d pm_runtime_put_sync " - "failed\n", __func__, bank->id); - return; - } + /* + * If a level interrupt is pending it will be lost since + * we just cleared it's enable bit. Detect and abort, + * the interrupt will be delivered when + * omap2_gpio_restore_edge_wakeup restores the level + * interrupt mask. + */ + datain = __raw_readl(bank->base + bank->regs->datain); + if ((datain & bank->context.leveldetect1) || + (~datain & bank->context.leveldetect0)) + ret = -EBUSY; + + if (pm_runtime_put_sync_suspend(bank->dev) < 0) { + dev_err(bank->dev, "%s: GPIO bank %d pm_runtime_put_sync " + "failed\n", __func__, bank->id); + return -EINVAL; } + + return ret; } -void omap2_gpio_restore_edge_wakeup(void) +static void omap2_gpio_restore_edge_wakeup(struct gpio_bank *bank) { - struct gpio_bank *bank; - - list_for_each_entry(bank, &omap_gpio_list, node) { - /* restore edge setting */ - if (pm_runtime_get_sync(bank->dev) < 0) { - dev_err(bank->dev, "%s: GPIO bank %d pm_runtime_get_sync " - "failed\n", __func__, bank->id); - return; - } + if (pm_runtime_get_sync(bank->dev) < 0) { + dev_err(bank->dev, "%s: GPIO bank %d pm_runtime_get_sync " + "failed\n", __func__, bank->id); + return; + } - __raw_writel(bank->context.edge_falling, - (bank->base + bank->regs->fallingdetect)); - __raw_writel(bank->context.edge_rising, - (bank->base + bank->regs->risingdetect)); + __raw_writel(bank->context.edge_falling, + (bank->base + bank->regs->fallingdetect)); + __raw_writel(bank->context.edge_rising, + (bank->base + bank->regs->risingdetect)); + __raw_writel(bank->context.leveldetect0, + (bank->base + bank->regs->leveldetect0)); + __raw_writel(bank->context.leveldetect1, + (bank->base + bank->regs->leveldetect1)); - if (pm_runtime_put_sync_suspend(bank->dev) < 0) { - dev_err(bank->dev, "%s: GPIO bank %d pm_runtime_put_sync " - "failed\n", __func__, bank->id); - return; - } + if (pm_runtime_put_sync_suspend(bank->dev) < 0) { + dev_err(bank->dev, "%s: GPIO bank %d pm_runtime_put_sync " + "failed\n", __func__, bank->id); + return; } } -void omap2_gpio_prepare_for_idle(int off_mode) +int omap2_gpio_prepare_for_idle(int off_mode) { + int ret = 0; struct gpio_bank *bank; - if (!off_mode) - return; - list_for_each_entry(bank, &omap_gpio_list, node) { - if (!bank->mod_usage || !bank->loses_context) + omap2_gpio_set_wakeupenables(bank); + + if (!bank->mod_usage || !bank->loses_context || !off_mode) { + if (omap2_gpio_set_edge_wakeup(bank)) + ret = -EBUSY; continue; + } if (pm_runtime_put_sync_suspend(bank->dev) < 0) dev_err(bank->dev, "%s: GPIO bank %d " "pm_runtime_put_sync failed\n", __func__, bank->id); } + + if (ret) + omap2_gpio_resume_after_idle(off_mode); + + return ret; } -void omap2_gpio_resume_after_idle(void) +void omap2_gpio_resume_after_idle(int off_mode) { struct gpio_bank *bank; list_for_each_entry(bank, &omap_gpio_list, node) { - if (!bank->mod_usage || !bank->loses_context) + omap2_gpio_clear_wakeupenables(bank); + + if (!bank->mod_usage || !bank->loses_context || !off_mode) { + omap2_gpio_restore_edge_wakeup(bank); continue; + } if (pm_runtime_get_sync(bank->dev) < 0) dev_err(bank->dev, "%s: GPIO bank %d " diff --git a/drivers/gpu/ion/ion.c b/drivers/gpu/ion/ion.c index 37b23af0550..688e7ed46dc 100644 --- a/drivers/gpu/ion/ion.c +++ b/drivers/gpu/ion/ion.c @@ -332,6 +332,7 @@ end: ion_buffer_put(buffer); return handle; } +EXPORT_SYMBOL(ion_alloc); void ion_free(struct ion_client *client, struct ion_handle *handle) { @@ -349,6 +350,7 @@ void ion_free(struct ion_client *client, struct ion_handle *handle) } ion_handle_put(handle); } +EXPORT_SYMBOL(ion_free); static void ion_client_get(struct ion_client *client); static int ion_client_put(struct ion_client *client); @@ -406,6 +408,7 @@ int ion_phys(struct ion_client *client, struct ion_handle *handle, ret = buffer->heap->ops->phys(buffer->heap, buffer, addr, len); return ret; } +EXPORT_SYMBOL(ion_phys); void *ion_map_kernel(struct ion_client *client, struct ion_handle *handle) { @@ -443,6 +446,7 @@ void *ion_map_kernel(struct ion_client *client, struct ion_handle *handle) mutex_unlock(&client->lock); return vaddr; } +EXPORT_SYMBOL(ion_map_kernel); struct scatterlist *ion_map_dma(struct ion_client *client, struct ion_handle *handle) @@ -479,6 +483,7 @@ struct scatterlist *ion_map_dma(struct ion_client *client, mutex_unlock(&client->lock); return sglist; } +EXPORT_SYMBOL(ion_map_dma); void ion_unmap_kernel(struct ion_client *client, struct ion_handle *handle) { @@ -494,6 +499,7 @@ void ion_unmap_kernel(struct ion_client *client, struct ion_handle *handle) mutex_unlock(&buffer->lock); mutex_unlock(&client->lock); } +EXPORT_SYMBOL(ion_unmap_kernel); void ion_unmap_dma(struct ion_client *client, struct ion_handle *handle) { @@ -509,7 +515,7 @@ void ion_unmap_dma(struct ion_client *client, struct ion_handle *handle) mutex_unlock(&buffer->lock); mutex_unlock(&client->lock); } - +EXPORT_SYMBOL(ion_unmap_dma); struct ion_buffer *ion_share(struct ion_client *client, struct ion_handle *handle) @@ -531,6 +537,7 @@ struct ion_buffer *ion_share(struct ion_client *client, */ return handle->buffer; } +EXPORT_SYMBOL(ion_share); struct ion_handle *ion_import(struct ion_client *client, struct ion_buffer *buffer) @@ -552,6 +559,7 @@ end: mutex_unlock(&client->lock); return handle; } +EXPORT_SYMBOL(ion_import); static const struct file_operations ion_share_fops; @@ -575,6 +583,7 @@ end: fput(file); return handle; } +EXPORT_SYMBOL(ion_import_fd); static int ion_debug_client_show(struct seq_file *s, void *unused) { @@ -728,6 +737,7 @@ struct ion_client *ion_client_create(struct ion_device *dev, return client; } +EXPORT_SYMBOL(ion_client_create); static void _ion_client_destroy(struct kref *kref) { @@ -768,6 +778,7 @@ void ion_client_destroy(struct ion_client *client) { ion_client_put(client); } +EXPORT_SYMBOL(ion_client_destroy); static int ion_share_release(struct inode *inode, struct file* file) { diff --git a/drivers/gpu/ion/omap/omap_ion.c b/drivers/gpu/ion/omap/omap_ion.c index 00c93de9095..1ae3e536397 100644 --- a/drivers/gpu/ion/omap/omap_ion.c +++ b/drivers/gpu/ion/omap/omap_ion.c @@ -24,6 +24,8 @@ #include "omap_ion_priv.h" struct ion_device *omap_ion_device; +EXPORT_SYMBOL(omap_ion_device); + int num_heaps; struct ion_heap **heaps; struct ion_heap *tiler_heap; diff --git a/drivers/gpu/pvr/deviceclass.c b/drivers/gpu/pvr/deviceclass.c index d011bacdd31..f8c83f66073 100644 --- a/drivers/gpu/pvr/deviceclass.c +++ b/drivers/gpu/pvr/deviceclass.c @@ -1700,7 +1700,7 @@ PVRSRV_ERROR PVRSRVSwapToDCBuffer2KM(IMG_HANDLE hDeviceKM, psFlipCmd->pvPrivData = pvPrivData; psFlipCmd->ui32PrivDataLength = ui32PrivDataLength; - psFlipCmd->ppvMemInfos = ppvMemInfos; + psFlipCmd->ppsMemInfos = (PDC_MEM_INFO *)ppvMemInfos; psFlipCmd->ui32NumMemInfos = ui32NumMemSyncInfos; SysAcquireData(&psSysData); @@ -1988,6 +1988,29 @@ IMG_VOID IMG_CALLCONV PVRSRVSetDCState(IMG_UINT32 ui32State) ui32State); } +static PVRSRV_ERROR +PVRSRVDCMemInfoGetCpuVAddr(PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo, + IMG_CPU_VIRTADDR *pVAddr) +{ + *pVAddr = psKernelMemInfo->pvLinAddrKM; + return PVRSRV_OK; +} + +static PVRSRV_ERROR +PVRSRVDCMemInfoGetCpuPAddr(PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo, + IMG_SIZE_T uByteOffset, IMG_CPU_PHYADDR *pPAddr) +{ + *pPAddr = OSMemHandleToCpuPAddr(psKernelMemInfo->sMemBlk.hOSMemHandle, uByteOffset); + return PVRSRV_OK; +} + +static PVRSRV_ERROR +PVRSRVDCMemInfoGetByteSize(PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo, + IMG_SIZE_T *uByteSize) +{ + *uByteSize = psKernelMemInfo->uAllocSize; + return PVRSRV_OK; +} IMG_EXPORT IMG_BOOL PVRGetDisplayClassJTable(PVRSRV_DC_DISP2SRV_KMJTABLE *psJTable) @@ -2008,7 +2031,9 @@ IMG_BOOL PVRGetDisplayClassJTable(PVRSRV_DC_DISP2SRV_KMJTABLE *psJTable) #if defined(SUPPORT_CUSTOM_SWAP_OPERATIONS) psJTable->pfnPVRSRVFreeCmdCompletePacket = &PVRSRVFreeCommandCompletePacketKM; #endif - + psJTable->pfnPVRSRVDCMemInfoGetCpuVAddr = &PVRSRVDCMemInfoGetCpuVAddr; + psJTable->pfnPVRSRVDCMemInfoGetCpuPAddr = &PVRSRVDCMemInfoGetCpuPAddr; + psJTable->pfnPVRSRVDCMemInfoGetByteSize = &PVRSRVDCMemInfoGetByteSize; return IMG_TRUE; } diff --git a/drivers/gpu/pvr/kerneldisplay.h b/drivers/gpu/pvr/kerneldisplay.h index 76ee4b8947c..7e9ba51d6df 100644 --- a/drivers/gpu/pvr/kerneldisplay.h +++ b/drivers/gpu/pvr/kerneldisplay.h @@ -106,6 +106,12 @@ typedef PVRSRV_ERROR (*PFN_DC_REGISTER_POWER)(IMG_UINT32, PFN_PRE_POWER, PFN_POS PFN_PRE_CLOCKSPEED_CHANGE, PFN_POST_CLOCKSPEED_CHANGE, IMG_HANDLE, PVRSRV_DEV_POWER_STATE, PVRSRV_DEV_POWER_STATE); +typedef struct _PVRSRV_KERNEL_MEM_INFO_* PDC_MEM_INFO; + +typedef PVRSRV_ERROR (*PFN_DC_MEMINFO_GET_CPU_VADDR)(PDC_MEM_INFO, IMG_CPU_VIRTADDR *pVAddr); +typedef PVRSRV_ERROR (*PFN_DC_MEMINFO_GET_CPU_PADDR)(PDC_MEM_INFO, IMG_SIZE_T uByteOffset, IMG_CPU_PHYADDR *pPAddr); +typedef PVRSRV_ERROR (*PFN_DC_MEMINFO_GET_BYTE_SIZE)(PDC_MEM_INFO, IMG_SIZE_T *uByteSize); + typedef struct PVRSRV_DC_DISP2SRV_KMJTABLE_TAG { IMG_UINT32 ui32TableSize; @@ -118,6 +124,10 @@ typedef struct PVRSRV_DC_DISP2SRV_KMJTABLE_TAG PFN_DC_REGISTER_SYS_ISR pfnPVRSRVRegisterSystemISRHandler; PFN_DC_REGISTER_POWER pfnPVRSRVRegisterPowerDevice; PFN_DC_CMD_COMPLETE pfnPVRSRVFreeCmdCompletePacket; + PFN_DC_MEMINFO_GET_CPU_VADDR pfnPVRSRVDCMemInfoGetCpuVAddr; + PFN_DC_MEMINFO_GET_CPU_PADDR pfnPVRSRVDCMemInfoGetCpuPAddr; + PFN_DC_MEMINFO_GET_BYTE_SIZE pfnPVRSRVDCMemInfoGetByteSize; + } PVRSRV_DC_DISP2SRV_KMJTABLE, *PPVRSRV_DC_DISP2SRV_KMJTABLE; @@ -168,7 +178,7 @@ typedef struct DISPLAYCLASS_FLIP_COMMAND2_TAG IMG_UINT32 ui32PrivDataLength; - IMG_VOID **ppvMemInfos; + PDC_MEM_INFO *ppsMemInfos; IMG_UINT32 ui32NumMemInfos; diff --git a/drivers/gpu/pvr/module.c b/drivers/gpu/pvr/module.c index 0abff8414f0..91d61f2a747 100644 --- a/drivers/gpu/pvr/module.c +++ b/drivers/gpu/pvr/module.c @@ -148,6 +148,7 @@ module_param(sgx_apm_latency, uint, 0644); #include <linux/omap_ion.h> extern struct ion_device *omap_ion_device; struct ion_client *gpsIONClient; +EXPORT_SYMBOL(gpsIONClient); #endif diff --git a/drivers/gpu/pvr/omaplfb/omaplfb_displayclass.c b/drivers/gpu/pvr/omaplfb/omaplfb_displayclass.c index 3d0eb29ebca..d16ebbde472 100644 --- a/drivers/gpu/pvr/omaplfb/omaplfb_displayclass.c +++ b/drivers/gpu/pvr/omaplfb/omaplfb_displayclass.c @@ -44,6 +44,9 @@ extern struct ion_client *gpsIONClient; #endif #if defined(CONFIG_TI_TILER) #include <mach/tiler.h> +#include <video/dsscomp.h> +#include <plat/dsscomp.h> + #endif #define OMAPLFB_COMMAND_COUNT 1 @@ -868,13 +871,11 @@ static IMG_BOOL ProcessFlipV1(IMG_HANDLE hCmdCookie, static IMG_BOOL ProcessFlipV2(IMG_HANDLE hCmdCookie, OMAPLFB_DEVINFO *psDevInfo, - IMG_VOID **ppvMemInfos, + PDC_MEM_INFO *ppsMemInfos, IMG_UINT32 ui32NumMemInfos, struct dsscomp_setup_dispc_data *psDssData, IMG_UINT32 uiDssDataLength) { - PVRSRV_KERNEL_MEM_INFO **ppsMemInfos = - (PVRSRV_KERNEL_MEM_INFO **)ppvMemInfos; struct tiler_pa_info *apsTilerPAs[5]; IMG_UINT32 i, k; @@ -894,34 +895,36 @@ static IMG_BOOL ProcessFlipV2(IMG_HANDLE hCmdCookie, for(i = k = 0; i < ui32NumMemInfos && k < ARRAY_SIZE(apsTilerPAs); i++, k++) { struct tiler_pa_info *psTilerInfo; - LinuxMemArea *psLinuxMemArea; + IMG_CPU_VIRTADDR virtAddr; + IMG_CPU_PHYADDR phyAddr; IMG_UINT32 ui32NumPages; - IMG_UINT32 uiAddr; + IMG_SIZE_T uByteSize; int j; - psLinuxMemArea = ppsMemInfos[i]->sMemBlk.hOSMemHandle; - ui32NumPages = (psLinuxMemArea->ui32ByteSize + PAGE_SIZE - 1) >> PAGE_SHIFT; + psDevInfo->sPVRJTable.pfnPVRSRVDCMemInfoGetByteSize(ppsMemInfos[i], &uByteSize); + ui32NumPages = (uByteSize + PAGE_SIZE - 1) >> PAGE_SHIFT; apsTilerPAs[k] = NULL; - uiAddr = (IMG_UINT32) LinuxMemAreaToCpuPAddr(psLinuxMemArea, 0).uiAddr; + psDevInfo->sPVRJTable.pfnPVRSRVDCMemInfoGetCpuPAddr(ppsMemInfos[i], 0, &phyAddr); + /* NV12 buffers do not need meminfos */ if(psDssData->ovls[k].cfg.color_mode == OMAP_DSS_COLOR_NV12) { /* must have still 2 meminfos in array */ BUG_ON(i + 1 >= ui32NumMemInfos); - psDssData->ovls[k].ba = uiAddr; + psDssData->ovls[k].ba = (u32)phyAddr.uiAddr; i++; - psLinuxMemArea = ppsMemInfos[i]->sMemBlk.hOSMemHandle; - psDssData->ovls[k].uv = (u32)LinuxMemAreaToCpuPAddr(psLinuxMemArea, 0).uiAddr; + psDevInfo->sPVRJTable.pfnPVRSRVDCMemInfoGetCpuPAddr(ppsMemInfos[i], 0, &phyAddr); + psDssData->ovls[k].uv = (u32)phyAddr.uiAddr; continue; } /* check if it is a TILER buffer */ - else if(is_tiler_addr(uiAddr)) + else if(is_tiler_addr((u32)phyAddr.uiAddr)) { - psDssData->ovls[k].ba = uiAddr; + psDssData->ovls[k].ba = (u32)phyAddr.uiAddr; continue; } @@ -943,12 +946,13 @@ static IMG_BOOL ProcessFlipV2(IMG_HANDLE hCmdCookie, for(j = 0; j < ui32NumPages; j++) { - psTilerInfo->mem[j] = - (u32)LinuxMemAreaToCpuPAddr(psLinuxMemArea, j << PAGE_SHIFT).uiAddr; + psDevInfo->sPVRJTable.pfnPVRSRVDCMemInfoGetCpuPAddr(ppsMemInfos[i], j << PAGE_SHIFT, &phyAddr); + psTilerInfo->mem[j] = (u32)phyAddr.uiAddr; } /* need base address for in-page offset */ - psDssData->ovls[k].ba = (u32)ppsMemInfos[i]->pvLinAddrKM; + psDevInfo->sPVRJTable.pfnPVRSRVDCMemInfoGetCpuVAddr(ppsMemInfos[i], &virtAddr); + psDssData->ovls[k].ba = (u32)virtAddr; apsTilerPAs[k] = psTilerInfo; } @@ -956,6 +960,12 @@ static IMG_BOOL ProcessFlipV2(IMG_HANDLE hCmdCookie, for(i = k; i < psDssData->num_ovls && i < ARRAY_SIZE(apsTilerPAs); i++) { unsigned int ix = psDssData->ovls[i].ba; + if(ix >= ARRAY_SIZE(apsTilerPAs)) + { + WARN(1, "Invalid clone layer (%u); skipping all cloned layers", ix); + psDssData->num_ovls = k; + break; + } apsTilerPAs[i] = apsTilerPAs[ix]; psDssData->ovls[i].ba = psDssData->ovls[ix].ba; psDssData->ovls[i].uv = psDssData->ovls[ix].uv; @@ -1011,7 +1021,7 @@ static IMG_BOOL ProcessFlip(IMG_HANDLE hCmdCookie, psFlipCmd2 = (DISPLAYCLASS_FLIP_COMMAND2 *)pvData; return ProcessFlipV2(hCmdCookie, psDevInfo, - psFlipCmd2->ppvMemInfos, + psFlipCmd2->ppsMemInfos, psFlipCmd2->ui32NumMemInfos, psFlipCmd2->pvPrivData, psFlipCmd2->ui32PrivDataLength); diff --git a/drivers/gpu/pvr/pvrversion.h b/drivers/gpu/pvr/pvrversion.h index 8f987efa132..c887f583d7d 100644 --- a/drivers/gpu/pvr/pvrversion.h +++ b/drivers/gpu/pvr/pvrversion.h @@ -36,7 +36,7 @@ #define PVRVERSION_FAMILY "sgxddk" #define PVRVERSION_BRANCHNAME "1.8" -#define PVRVERSION_BUILD 300406 +#define PVRVERSION_BUILD 550175 #define PVRVERSION_BSCONTROL "CustomerGoogle_Android_ogles1_ogles2_GPL" #define PVRVERSION_STRING "CustomerGoogle_Android_ogles1_ogles2_GPL sgxddk 18 1.8@" PVR_STR2(PVRVERSION_BUILD) @@ -44,8 +44,8 @@ #define COPYRIGHT_TXT "Copyright (c) Imagination Technologies Ltd. All Rights Reserved." -#define PVRVERSION_BUILD_HI 30 -#define PVRVERSION_BUILD_LO 406 +#define PVRVERSION_BUILD_HI 55 +#define PVRVERSION_BUILD_LO 175 #define PVRVERSION_STRING_NUMERIC PVR_STR2(PVRVERSION_MAJ) "." PVR_STR2(PVRVERSION_MIN) "." PVR_STR2(PVRVERSION_BUILD_HI) "." PVR_STR2(PVRVERSION_BUILD_LO) #endif /* _PVRVERSION_H_ */ diff --git a/drivers/gpu/pvr/sgx/sgxinfokm.h b/drivers/gpu/pvr/sgx/sgxinfokm.h index 2f25a87e67f..7e2b3f9e71a 100644 --- a/drivers/gpu/pvr/sgx/sgxinfokm.h +++ b/drivers/gpu/pvr/sgx/sgxinfokm.h @@ -545,6 +545,9 @@ PVRSRV_ERROR SGXPostClockSpeedChange(IMG_HANDLE hDevHandle, IMG_VOID SGXPanic(PVRSRV_SGXDEV_INFO *psDevInfo); +IMG_VOID SGXDumpDebugInfo (PVRSRV_SGXDEV_INFO *psDevInfo, + IMG_BOOL bDumpSGXRegs); + PVRSRV_ERROR SGXDevInitCompatCheck(PVRSRV_DEVICE_NODE *psDeviceNode); #if defined(SGX_DYNAMIC_TIMING_INFO) diff --git a/drivers/gpu/pvr/sgx/sgxinit.c b/drivers/gpu/pvr/sgx/sgxinit.c index b48269b64e3..934f88f3354 100644 --- a/drivers/gpu/pvr/sgx/sgxinit.c +++ b/drivers/gpu/pvr/sgx/sgxinit.c @@ -519,6 +519,7 @@ PVRSRV_ERROR SGXInitialise(PVRSRV_SGXDEV_INFO *psDevInfo, { PVR_DPF((PVR_DBG_ERROR, "SGXInitialise: Wait for uKernel initialisation failed")); #if !defined(FIX_HW_BRN_23281) + SGXDumpDebugInfo(psDevInfo, IMG_FALSE); PVR_DBG_BREAK; #endif return PVRSRV_ERROR_RETRY; @@ -1013,8 +1014,8 @@ static IMG_VOID SGXDumpDebugReg (PVRSRV_SGXDEV_INFO *psDevInfo, } void dsscomp_kdump(void); -static IMG_VOID SGXDumpDebugInfo (PVRSRV_SGXDEV_INFO *psDevInfo, - IMG_BOOL bDumpSGXRegs) +IMG_VOID SGXDumpDebugInfo (PVRSRV_SGXDEV_INFO *psDevInfo, + IMG_BOOL bDumpSGXRegs) { IMG_UINT32 ui32CoreNum; diff --git a/drivers/gpu/pvr/sgx/sgxpower.c b/drivers/gpu/pvr/sgx/sgxpower.c index 3947cddea8b..696941f7a79 100644 --- a/drivers/gpu/pvr/sgx/sgxpower.c +++ b/drivers/gpu/pvr/sgx/sgxpower.c @@ -202,6 +202,7 @@ static IMG_VOID SGXPollForClockGating (PVRSRV_SGXDEV_INFO *psDevInfo, IMG_FALSE) != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"SGXPollForClockGating: %s failed.", pszComment)); + SGXDumpDebugInfo(psDevInfo, IMG_FALSE); PVR_DBG_BREAK; } #endif diff --git a/drivers/gpu/pvr/sgx/sgxutils.c b/drivers/gpu/pvr/sgx/sgxutils.c index 84cf702f9c6..f362e064820 100644 --- a/drivers/gpu/pvr/sgx/sgxutils.c +++ b/drivers/gpu/pvr/sgx/sgxutils.c @@ -664,6 +664,7 @@ PVRSRV_ERROR SGXCleanupRequest(PVRSRV_DEVICE_NODE *psDeviceNode, if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"SGXCleanupRequest: Failed to submit clean-up command")); + SGXDumpDebugInfo(psDevInfo, IMG_FALSE); PVR_DBG_BREAK; return eError; } @@ -679,6 +680,7 @@ PVRSRV_ERROR SGXCleanupRequest(PVRSRV_DEVICE_NODE *psDeviceNode, { PVR_DPF((PVR_DBG_ERROR,"SGXCleanupRequest: Wait for uKernel to clean up (%u) failed", ui32CleanupType)); eError = PVRSRV_ERROR_TIMEOUT; + SGXDumpDebugInfo(psDevInfo, IMG_FALSE); PVR_DBG_BREAK; } #endif diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index 0679c2a218f..6b325c4dafe 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c @@ -314,7 +314,7 @@ static void omap_i2c_unidle(struct omap_i2c_dev *dev) } dev->idle = 0; - if (dev->rev >= OMAP_I2C_REV_ON_4430) { + if (cpu_is_omap44xx() && dev->rev >= OMAP_I2C_REV_ON_4430) { omap_i2c_write_reg(dev, OMAP_I2C_IRQENABLE_CLR,0x6FFF); omap_i2c_write_reg(dev, OMAP_I2C_IRQENABLE_SET, dev->iestate); } else { @@ -333,7 +333,7 @@ static void omap_i2c_idle(struct omap_i2c_dev *dev) pdev = to_platform_device(dev->dev); pdata = pdev->dev.platform_data; - if (dev->rev >= OMAP_I2C_REV_ON_4430) + if (cpu_is_omap44xx() && dev->rev >= OMAP_I2C_REV_ON_4430) omap_i2c_write_reg(dev, OMAP_I2C_IRQENABLE_CLR, 0x6FFF); else omap_i2c_write_reg(dev, OMAP_I2C_IE_REG, 0); diff --git a/drivers/mfd/twl6030-madc.c b/drivers/mfd/twl6030-madc.c index c7a9e55ad85..f537ba5cbc8 100644 --- a/drivers/mfd/twl6030-madc.c +++ b/drivers/mfd/twl6030-madc.c @@ -68,6 +68,7 @@ struct twl6030_madc_data { }; static struct twl6030_madc_data *twl6030_madc; +static u8 gpadc_ctrl_reg; static inline int twl6030_madc_start_conversion(struct twl6030_madc_data *madc) { @@ -281,12 +282,55 @@ static int __devexit twl6030_madc_remove(struct platform_device *pdev) return 0; } +static int twl6030_madc_suspend(struct device *pdev) +{ + int ret; + u8 reg_val; + + ret = twl_i2c_read_u8(TWL_MODULE_MADC, ®_val, TWL6030_MADC_CTRL); + if (!ret) { + reg_val &= ~(TWL6030_MADC_TEMP1_EN); + ret = twl_i2c_write_u8(TWL_MODULE_MADC, reg_val, + TWL6030_MADC_CTRL); + } + + if (ret) { + dev_err(twl6030_madc->dev, "unable to disable madc temp1!\n"); + gpadc_ctrl_reg = TWL6030_MADC_TEMP1_EN; + } else + gpadc_ctrl_reg = reg_val; + + return 0; +}; + +static int twl6030_madc_resume(struct device *pdev) +{ + int ret; + + if (!(gpadc_ctrl_reg & TWL6030_MADC_TEMP1_EN)) { + gpadc_ctrl_reg |= TWL6030_MADC_TEMP1_EN; + ret = twl_i2c_write_u8(TWL_MODULE_MADC, gpadc_ctrl_reg, + TWL6030_MADC_CTRL); + if (ret) + dev_err(twl6030_madc->dev, + "unable to enable madc temp1!\n"); + } + + return 0; +}; + +static const struct dev_pm_ops twl6030_madc_pm_ops = { + .suspend = twl6030_madc_suspend, + .resume = twl6030_madc_resume, +}; + static struct platform_driver twl6030_madc_driver = { .probe = twl6030_madc_probe, .remove = __exit_p(twl6030_madc_remove), .driver = { .name = "twl6030_madc", .owner = THIS_MODULE, + .pm = &twl6030_madc_pm_ops, }, }; diff --git a/drivers/mfd/twl6030-power.c b/drivers/mfd/twl6030-power.c index 84a8a225f31..2bbea1a37d5 100644 --- a/drivers/mfd/twl6030-power.c +++ b/drivers/mfd/twl6030-power.c @@ -18,11 +18,14 @@ #include <linux/pm.h> #include <linux/i2c/twl.h> #include <linux/platform_device.h> +#include <linux/suspend.h> #include <asm/mach-types.h> #define VREG_GRP 0 +static u8 dev_on_group; + /** * struct twl6030_resource_map - describe the resource mapping for TWL6030 * @name: name of the resource @@ -70,11 +73,60 @@ static __initdata struct twl6030_resource_map twl6030_res_map[] = { /* TEMP cannot be modified */ }; +static struct twl4030_system_config twl6030_sys_config[] = { + {.name = "DEV_ON", .group = DEV_GRP_P1,}, +}; + /* Actual power groups that TWL understands */ #define P3_GRP_6030 BIT(2) /* secondary processor, modem, etc */ #define P2_GRP_6030 BIT(1) /* "peripherals" */ #define P1_GRP_6030 BIT(0) /* CPU/Linux */ +static __init void twl6030_process_system_config(void) +{ + u8 grp; + int r; + bool i = false; + + struct twl4030_system_config *sys_config; + sys_config = twl6030_sys_config; + + while (sys_config && sys_config->name) { + if (!strcmp(sys_config->name, "DEV_ON")) { + dev_on_group = sys_config->group; + i = true; + break; + } + sys_config++; + } + if (!i) + pr_err("%s: Couldn't find DEV_ON resource configuration!" + " MOD & CON group would be kept active.\n", __func__); + + if (dev_on_group) { + r = twl_i2c_read_u8(TWL_MODULE_PM_MASTER, &grp, + TWL6030_PHOENIX_DEV_ON); + if (r) { + pr_err("%s: Error(%d) reading {addr=0x%02x}", + __func__, r, TWL6030_PHOENIX_DEV_ON); + /* + * On error resetting to 0, so that all the process + * groups are kept active. + */ + dev_on_group = 0; + } else { + /* + * Unmapped processor groups are disabled by writing + * 1 to corresponding group in DEV_ON. + */ + grp |= (dev_on_group & DEV_GRP_P1) ? 0 : P1_GRP_6030; + grp |= (dev_on_group & DEV_GRP_P2) ? 0 : P2_GRP_6030; + grp |= (dev_on_group & DEV_GRP_P3) ? 0 : P3_GRP_6030; + dev_on_group = grp; + } + } +} + static __init void twl6030_program_map(void) { struct twl6030_resource_map *res = twl6030_res_map; @@ -98,6 +150,24 @@ static __init void twl6030_program_map(void) } } +static __init void twl6030_update_system_map + (struct twl4030_system_config *sys_list) +{ + int i; + struct twl4030_system_config *sys_res; + + while (sys_list && sys_list->name) { + sys_res = twl6030_sys_config; + for (i = 0; i < ARRAY_SIZE(twl6030_sys_config); i++) { + if (!strcmp(sys_res->name, sys_list->name)) + sys_res->group = sys_list->group & + (DEV_GRP_P1 | DEV_GRP_P2 | DEV_GRP_P3); + sys_res++; + } + sys_list++; + } +} + static __init void twl6030_update_map(struct twl4030_resconfig *res_list) { int i, res_idx = 0; @@ -124,6 +194,29 @@ static __init void twl6030_update_map(struct twl4030_resconfig *res_list) } } + +static int twl6030_power_notifier_cb(struct notifier_block *notifier, + unsigned long pm_event, void *unused) +{ + int r = 0; + + switch (pm_event) { + case PM_SUSPEND_PREPARE: + r = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, dev_on_group, + TWL6030_PHOENIX_DEV_ON); + if (r) + pr_err("%s: Error(%d) programming {addr=0x%02x}", + __func__, r, TWL6030_PHOENIX_DEV_ON); + break; + } + + return notifier_from_errno(r); +} + +static struct notifier_block twl6030_power_pm_notifier = { + .notifier_call = twl6030_power_notifier_cb, +}; + /** * twl6030_power_init() - Update the power map to reflect connectivity of board * @power_data: power resource map to update (OPTIONAL) - use this if a resource @@ -131,16 +224,28 @@ static __init void twl6030_update_map(struct twl4030_resconfig *res_list) */ void __init twl6030_power_init(struct twl4030_power_data *power_data) { - if (power_data && !power_data->resource_config) { - pr_err("%s: power data from platform without resources!\n", + int r; + + if (power_data && (!power_data->resource_config && + !power_data->sys_config)) { + pr_err("%s: power data from platform without configuration!\n", __func__); return; } - if (power_data) + if (power_data && power_data->resource_config) twl6030_update_map(power_data->resource_config); + if (power_data && power_data->sys_config) + twl6030_update_system_map(power_data->sys_config); + + twl6030_process_system_config(); + twl6030_program_map(); + r = register_pm_notifier(&twl6030_power_pm_notifier); + if (r) + pr_err("%s: twl6030 power registration failed!\n", __func__); + return; } diff --git a/drivers/misc/omap_temp_sensor.c b/drivers/misc/omap_temp_sensor.c index 68ac804af4e..6fc4d5522b5 100644 --- a/drivers/misc/omap_temp_sensor.c +++ b/drivers/misc/omap_temp_sensor.c @@ -60,8 +60,8 @@ static void throttle_delayed_work_fn(struct work_struct *work); #define TSHUT_THRESHOLD_TSHUT_HOT 110000 /* 110 deg C */ #define TSHUT_THRESHOLD_TSHUT_COLD 100000 /* 100 deg C */ -#define BGAP_THRESHOLD_T_HOT 83000 /* 83 deg C */ -#define BGAP_THRESHOLD_T_COLD 76000 /* 76 deg C */ +#define BGAP_THRESHOLD_T_HOT 64000 /* 64 deg C */ +#define BGAP_THRESHOLD_T_COLD 61000 /* 61 deg C */ #define OMAP_ADC_START_VALUE 530 #define OMAP_ADC_END_VALUE 923 diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 8014565e138..e892ec9d40c 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -2352,8 +2352,9 @@ static int omap_hsmmc_suspend(struct device *dev) } } cancel_work_sync(&host->mmc_carddetect_work); - if (host->mmc->card && (host->mmc->card->type != MMC_TYPE_SDIO)) - ret = mmc_suspend_host(host->mmc); + if (mmc_slot(host).mmc_data.built_in) + host->mmc->pm_flags |= MMC_PM_KEEP_POWER; + ret = mmc_suspend_host(host->mmc); mmc_host_enable(host->mmc); if (ret == 0) { omap_hsmmc_disable_irq(host); @@ -2415,8 +2416,7 @@ static int omap_hsmmc_resume(struct device *dev) omap_hsmmc_protect_card(host); /* Notify the core to resume the host */ - if (host->mmc->card && (host->mmc->card->type != MMC_TYPE_SDIO)) - ret = mmc_resume_host(host->mmc); + ret = mmc_resume_host(host->mmc); if (ret == 0) host->suspended = 0; diff --git a/drivers/net/wireless/bcm4329/dhd_linux.c b/drivers/net/wireless/bcm4329/dhd_linux.c index 3ec1f3f108d..5f5b418abc2 100644 --- a/drivers/net/wireless/bcm4329/dhd_linux.c +++ b/drivers/net/wireless/bcm4329/dhd_linux.c @@ -1519,7 +1519,8 @@ dhd_dpc_thread(void *data) dhd_os_wake_unlock(&dhd->pub); } } else { - dhd_bus_stop(dhd->pub.bus, TRUE); + if (dhd->pub.up) + dhd_bus_stop(dhd->pub.bus, TRUE); dhd_os_wake_unlock(&dhd->pub); } } diff --git a/drivers/net/wireless/bcmdhd/bcmsdh_linux.c b/drivers/net/wireless/bcmdhd/bcmsdh_linux.c index a4dc6ff4042..04c43a3225c 100644 --- a/drivers/net/wireless/bcmdhd/bcmsdh_linux.c +++ b/drivers/net/wireless/bcmdhd/bcmsdh_linux.c @@ -611,6 +611,13 @@ static irqreturn_t wlan_oob_irq(int irq, void *dev_id) return IRQ_HANDLED; } +void *bcmsdh_get_drvdata(void) +{ + if (!sdhcinfo) + return NULL; + return dev_get_drvdata(sdhcinfo->dev); +} + int bcmsdh_register_oob_intr(void * dhdp) { int error = 0; diff --git a/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc_linux.c b/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc_linux.c index 8baa60bf24f..726b6391353 100644 --- a/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc_linux.c +++ b/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc_linux.c @@ -66,6 +66,9 @@ extern void wl_cfg80211_set_sdio_func(void *func); extern void sdioh_sdmmc_devintr_off(sdioh_info_t *sd); extern void sdioh_sdmmc_devintr_on(sdioh_info_t *sd); +extern int dhd_os_check_wakelock(void *dhdp); +extern int dhd_os_check_if_up(void *dhdp); +extern void *bcmsdh_get_drvdata(void); int sdio_function_init(void); void sdio_function_cleanup(void); @@ -87,6 +90,8 @@ PBCMSDH_SDMMC_INSTANCE gInstance; extern int bcmsdh_probe(struct device *dev); extern int bcmsdh_remove(struct device *dev); +extern volatile bool dhd_mmc_suspend; + static int bcmsdh_sdmmc_probe(struct sdio_func *func, const struct sdio_device_id *id) { @@ -154,12 +159,56 @@ static const struct sdio_device_id bcmsdh_sdmmc_ids[] = { MODULE_DEVICE_TABLE(sdio, bcmsdh_sdmmc_ids); +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39)) && defined(CONFIG_PM) +static int bcmsdh_sdmmc_suspend(struct device *pdev) +{ + struct sdio_func *func = dev_to_sdio_func(pdev); + + if (func->num != 2) + return 0; + if (dhd_os_check_wakelock(bcmsdh_get_drvdata())) + return -EBUSY; +#if defined(OOB_INTR_ONLY) + bcmsdh_oob_intr_set(0); +#endif + dhd_mmc_suspend = TRUE; + smp_mb(); + + return 0; +} + +static int bcmsdh_sdmmc_resume(struct device *pdev) +{ + struct sdio_func *func = dev_to_sdio_func(pdev); + + if (func->num != 2) + return 0; + dhd_mmc_suspend = FALSE; +#if defined(OOB_INTR_ONLY) + if (dhd_os_check_if_up(bcmsdh_get_drvdata())) + bcmsdh_oob_intr_set(1); +#endif + smp_mb(); + return 0; +} + +static const struct dev_pm_ops bcmsdh_sdmmc_pm_ops = { + .suspend = bcmsdh_sdmmc_suspend, + .resume = bcmsdh_sdmmc_resume, +}; +#endif + static struct sdio_driver bcmsdh_sdmmc_driver = { .probe = bcmsdh_sdmmc_probe, .remove = bcmsdh_sdmmc_remove, .name = "bcmsdh_sdmmc", .id_table = bcmsdh_sdmmc_ids, - }; +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39)) && defined(CONFIG_PM) + .drv = { + .pm = &bcmsdh_sdmmc_pm_ops, + }, +#endif +}; struct sdos_info { sdioh_info_t *sd; diff --git a/drivers/net/wireless/bcmdhd/dhd.h b/drivers/net/wireless/bcmdhd/dhd.h index 0ea5d4a9961..c87f6cf37d9 100644 --- a/drivers/net/wireless/bcmdhd/dhd.h +++ b/drivers/net/wireless/bcmdhd/dhd.h @@ -235,11 +235,12 @@ typedef struct dhd_cmn { #define DHD_PM_RESUME_WAIT_INIT(a) DECLARE_WAIT_QUEUE_HEAD(a); #define _DHD_PM_RESUME_WAIT(a, b) do {\ int retry = 0; \ - smp_mb(); \ + SMP_RD_BARRIER_DEPENDS(); \ while (dhd_mmc_suspend && retry++ != b) { \ - wait_event_interruptible_timeout(a, FALSE, HZ/100); \ + SMP_RD_BARRIER_DEPENDS(); \ + wait_event_interruptible_timeout(a, !dhd_mmc_suspend, HZ/100); \ } \ - } while (0) + } while (0) #define DHD_PM_RESUME_WAIT(a) _DHD_PM_RESUME_WAIT(a, 200) #define DHD_PM_RESUME_WAIT_FOREVER(a) _DHD_PM_RESUME_WAIT(a, ~0) #define DHD_PM_RESUME_RETURN_ERROR(a) do { if (dhd_mmc_suspend) return a; } while (0) @@ -422,6 +423,7 @@ extern int dhd_dev_pno_enable(struct net_device *dev, int pfn_enabled); extern int dhd_dev_get_pno_status(struct net_device *dev); extern int dhd_get_dtim_skip(dhd_pub_t *dhd); extern bool dhd_check_ap_wfd_mode_set(dhd_pub_t *dhd); +extern bool dhd_os_check_hang(dhd_pub_t *dhdp, int ifidx, int ret); #define DHD_UNICAST_FILTER_NUM 0 #define DHD_BROADCAST_FILTER_NUM 1 diff --git a/drivers/net/wireless/bcmdhd/dhd_common.c b/drivers/net/wireless/bcmdhd/dhd_common.c index 2222b029f51..a29c2fab28c 100644 --- a/drivers/net/wireless/bcmdhd/dhd_common.c +++ b/drivers/net/wireless/bcmdhd/dhd_common.c @@ -300,7 +300,8 @@ dhd_wl_ioctl(dhd_pub_t *dhd_pub, int ifindex, wl_ioctl_t *ioc, void *buf, int le dhd_os_proto_block(dhd_pub); ret = dhd_prot_ioctl(dhd_pub, ifindex, ioc, buf, len); - + if (!ret) + dhd_os_check_hang(dhd_pub, ifindex, ret); dhd_os_proto_unblock(dhd_pub); return ret; diff --git a/drivers/net/wireless/bcmdhd/dhd_linux.c b/drivers/net/wireless/bcmdhd/dhd_linux.c index 014a40dc6c8..92cdc9b1a4b 100644 --- a/drivers/net/wireless/bcmdhd/dhd_linux.c +++ b/drivers/net/wireless/bcmdhd/dhd_linux.c @@ -478,19 +478,21 @@ static int dhd_sleep_pm_callback(struct notifier_block *nfb, unsigned long actio { int ret = NOTIFY_DONE; - switch (action) { +#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 39)) + switch (action) { case PM_HIBERNATION_PREPARE: case PM_SUSPEND_PREPARE: dhd_mmc_suspend = TRUE; - ret = NOTIFY_OK; + ret = NOTIFY_OK; break; case PM_POST_HIBERNATION: case PM_POST_SUSPEND: dhd_mmc_suspend = FALSE; - ret = NOTIFY_OK; + ret = NOTIFY_OK; break; } smp_mb(); +#endif return ret; } @@ -1742,7 +1744,8 @@ dhd_dpc_thread(void *data) DHD_OS_WAKE_UNLOCK(&dhd->pub); } } else { - dhd_bus_stop(dhd->pub.bus, TRUE); + if (dhd->pub.up) + dhd_bus_stop(dhd->pub.bus, TRUE); DHD_OS_WAKE_UNLOCK(&dhd->pub); } } @@ -2312,6 +2315,7 @@ dhd_open(struct net_device *net) #endif int ifidx; int32 ret = 0; + DHD_OS_WAKE_LOCK(&dhd->pub); /* Update FW path if it was changed */ if ((firmware_path != NULL) && (firmware_path[0] != '\0')) { @@ -4510,6 +4514,31 @@ int dhd_os_wake_unlock(dhd_pub_t *pub) return ret; } +int dhd_os_check_wakelock(void *dhdp) +{ +#ifdef CONFIG_HAS_WAKELOCK + dhd_pub_t *pub = (dhd_pub_t *)dhdp; + dhd_info_t *dhd; + + if (!pub) + return 0; + dhd = (dhd_info_t *)(pub->info); + + if (dhd && wake_lock_active(&dhd->wl_wifi)) + return 1; +#endif + return 0; +} + +int dhd_os_check_if_up(void *dhdp) +{ + dhd_pub_t *pub = (dhd_pub_t *)dhdp; + + if (!pub) + return 0; + return pub->up; +} + int net_os_wake_unlock(struct net_device *dev) { dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); @@ -4546,6 +4575,14 @@ int dhd_ioctl_entry_local(struct net_device *net, wl_ioctl_t *ioc, int cmd) return ret; } +bool dhd_os_check_hang(dhd_pub_t *dhdp, int ifidx, int ret) +{ + struct net_device *net; + + net = dhd_idx2net(dhdp, ifidx); + return dhd_check_hang(net, dhdp, ret); +} + #ifdef PROP_TXSTATUS extern int dhd_wlfc_interface_entry_update(void* state, ewlfc_mac_entry_action_t action, uint8 ifid, uint8 iftype, uint8* ea); diff --git a/drivers/net/wireless/bcmdhd/wl_android.c b/drivers/net/wireless/bcmdhd/wl_android.c index 76df647b677..7c6ab2fb282 100644 --- a/drivers/net/wireless/bcmdhd/wl_android.c +++ b/drivers/net/wireless/bcmdhd/wl_android.c @@ -126,6 +126,8 @@ int wl_cfg80211_get_p2p_noa(struct net_device *net, char* buf, int len) int wl_cfg80211_set_p2p_ps(struct net_device *net, char* buf, int len) { return 0; } #endif +extern int dhd_os_check_if_up(void *dhdp); +extern void *bcmsdh_get_drvdata(void); extern bool ap_fw_loaded; #ifdef CUSTOMER_HW2 @@ -708,7 +710,7 @@ int wifi_set_power(int on, unsigned long msec) wifi_control_data->set_power(on); } if (msec) - mdelay(msec); + msleep(msec); return 0; } @@ -784,18 +786,19 @@ static int wifi_remove(struct platform_device *pdev) static int wifi_suspend(struct platform_device *pdev, pm_message_t state) { DHD_TRACE(("##> %s\n", __FUNCTION__)); -#if defined(OOB_INTR_ONLY) +#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 39)) && defined(OOB_INTR_ONLY) bcmsdh_oob_intr_set(0); -#endif /* (OOB_INTR_ONLY) */ +#endif return 0; } static int wifi_resume(struct platform_device *pdev) { DHD_TRACE(("##> %s\n", __FUNCTION__)); -#if defined(OOB_INTR_ONLY) - bcmsdh_oob_intr_set(1); -#endif /* (OOB_INTR_ONLY) */ +#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 39)) && defined(OOB_INTR_ONLY) + if (dhd_os_check_if_up(bcmsdh_get_drvdata())) + bcmsdh_oob_intr_set(1); +#endif return 0; } diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c index 5749b72b80c..c82086dc5d7 100644 --- a/drivers/usb/musb/omap2430.c +++ b/drivers/usb/musb/omap2430.c @@ -361,7 +361,8 @@ static void musb_otg_notifier_work(struct work_struct *data_notifier_work) static int omap2430_musb_init(struct musb *musb) { - u32 l, status = 0; + u32 l; + int status = 0; struct device *dev = musb->controller; /* We require some kind of external transceiver, hooked diff --git a/drivers/video/omap2/dss/fifothreshold.c b/drivers/video/omap2/dss/fifothreshold.c index e82e0e019a2..74359561d5a 100644 --- a/drivers/video/omap2/dss/fifothreshold.c +++ b/drivers/video/omap2/dss/fifothreshold.c @@ -358,7 +358,6 @@ static void sa_calc(struct dispc_config *dispc_reg_config, u32 channel_no, * buffers allocated. */ i = Tot_mem / pict_16word_ceil; - Tot_mem -= pict_16word_ceil * i; if (i == 0) { /* LineSize > MemoryLineBufferSize (Valid only for 1D) */ @@ -368,22 +367,26 @@ static void sa_calc(struct dispc_config *dispc_reg_config, u32 channel_no, * When MemoryLineBufferSize > LineSize > * (MemoryLineBufferSize/2) */ - - /* HACK: we multiplied pict_16word by 2 as we hit underflow */ - sa_info->min_sa = 2 * pict_16word + C2 * (Tot_mem - 8); + sa_info->min_sa = pict_16word + C2 * (Tot_mem - + pict_16word_ceil - 8); } else { /* All other cases */ - sa_info->min_sa = (4 * (i - 2) + C1) * pict_16word + - C2 * (Tot_mem - 8); + sa_info->min_sa = 4 * pict_16word_ceil; } /* C2=0:: no partialy filed lines:: Then minLT = 0 */ - if (C2 == 0) + if (C2 == 0) { sa_info->min_lt = 0; - else if (bh_config.antifckr == 1 && (C1 == 3 || C1 == 4)) - sa_info->min_lt = (6 - C1) * pict_16word_ceil + C2 * Tot_mem; - else - sa_info->min_lt = (C2 - 1) * Tot_mem; + } else if (bh_config.antifckr == 1) { + if (C1 == 3) + sa_info->min_lt = 3 * pict_16word_ceil + C2 * (Tot_mem - + (pict_16word_ceil*i)); + else if (C1 == 4) + sa_info->min_lt = 2 * pict_16word_ceil + C2 * (Tot_mem - + (pict_16word_ceil*i)); + } else { + sa_info->min_lt = (C2 - 1) * (Tot_mem - (pict_16word_ceil*i)); + } sa_info->max_lt = max(sa_info->min_sa - 8, sa_info->min_lt + 1); } diff --git a/drivers/video/omap2/dsscomp/queue.c b/drivers/video/omap2/dsscomp/queue.c index ef778bb2bc8..c25d65596c5 100644 --- a/drivers/video/omap2/dsscomp/queue.c +++ b/drivers/video/omap2/dsscomp/queue.c @@ -547,8 +547,6 @@ skip_ovl_set: if (r && !comp->must_apply) { dev_err(DEV(cdev), "[%p] set failed %d\n", comp, r); - /* extra callbacks in case of delayed apply */ - dsscomp_mgr_callback(comp, mgr->id, DSS_COMPLETION_ECLIPSED_SET); goto done; } else { if (r) diff --git a/include/linux/i2c/twl.h b/include/linux/i2c/twl.h index 623c6e0a1c6..1172847d6bb 100644 --- a/include/linux/i2c/twl.h +++ b/include/linux/i2c/twl.h @@ -468,6 +468,8 @@ int twl6030_unregister_notifier(struct notifier_block *nb, #define TWL4030_PM_MASTER_GLOBAL_TST 0xb6 +#define TWL6030_PHOENIX_DEV_ON 0x06 + /* * TWL6030 PM Master module register offsets (use TWL_MODULE_PM_MASTER) */ @@ -709,10 +711,16 @@ struct twl4030_resconfig { u8 remap_sleep; /* sleep state remapping */ }; +struct twl4030_system_config { + char *name; + u8 group; +}; + struct twl4030_power_data { struct twl4030_script **scripts; /* used in TWL4030 only */ unsigned num; /* used in TWL4030 only */ struct twl4030_resconfig *resource_config; + struct twl4030_system_config *sys_config; /*system resources*/ #define TWL4030_RESCONFIG_UNDEF ((u8)-1) }; diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 5eb7af23461..09ced58e6a5 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -273,6 +273,8 @@ #include <net/xfrm.h> #include <net/ip.h> #include <net/ip6_route.h> +#include <net/ipv6.h> +#include <net/transp_v6.h> #include <net/netdma.h> #include <net/sock.h> @@ -3374,8 +3376,16 @@ restart: sk_nulls_for_each(sk, node, &tcp_hashinfo.ehash[bucket].chain) { struct inet_sock *inet = inet_sk(sk); + if (sysctl_ip_dynaddr && sk->sk_state == TCP_SYN_SENT) + continue; + if (sock_flag(sk, SOCK_DEAD)) + continue; + if (family == AF_INET) { __be32 s4 = inet->inet_rcv_saddr; + if (s4 == LOOPBACK4_IPV6) + continue; + if (in->s_addr != s4 && !(in->s_addr == INADDR_ANY && !tcp_is_local(net, s4))) @@ -3387,7 +3397,11 @@ restart: struct in6_addr *s6; if (!inet->pinet6) continue; + s6 = &inet->pinet6->rcv_saddr; + if (ipv6_addr_type(s6) == IPV6_ADDR_MAPPED) + continue; + if (!ipv6_addr_equal(in6, s6) && !(ipv6_addr_equal(in6, &in6addr_any) && !tcp_is_local6(net, s6))) @@ -3395,11 +3409,6 @@ restart: } #endif - if (sysctl_ip_dynaddr && sk->sk_state == TCP_SYN_SENT) - continue; - if (sock_flag(sk, SOCK_DEAD)) - continue; - sock_hold(sk); spin_unlock_bh(lock); diff --git a/sound/soc/omap/omap-mcasp.c b/sound/soc/omap/omap-mcasp.c index 2f680c2b162..bf8e1fb0fa4 100644 --- a/sound/soc/omap/omap-mcasp.c +++ b/sound/soc/omap/omap-mcasp.c @@ -199,6 +199,21 @@ */ #define TXDATADMADIS BIT(0) +#define MCASP_ALLOWED_PPM 100 + +/* + * OMAP_MCASP_DITCSRA_REG/OMAP_MCASP_DITCSRB_REG + */ +#define OMAP_MCASP_DITCSR_44100HZ (0x0 << 24) +#define OMAP_MCASP_DITCSR_48000HZ (0x2 << 24) +#define OMAP_MCASP_DITCSR_32000HZ (0x3 << 24) +#define OMAP_MCASP_DITCSR_22050HZ (0x4 << 24) +#define OMAP_MCASP_DITCSR_24000HZ (0x6 << 24) +#define OMAP_MCASP_DITCSR_88200HZ (0x8 << 24) +#define OMAP_MCASP_DITCSR_96000HZ (0xA << 24) +#define OMAP_MCASP_DITCSR_176400HZ (0xC << 24) +#define OMAP_MCASP_DITCSR_192000HZ (0xE << 24) + /* * Stream DMA parameters */ @@ -279,7 +294,8 @@ static int mcasp_compute_clock_dividers(long fclk_rate, int tgt_sample_rate, * the transmit clock. */ long divisor; - int i; + unsigned long ppm; + int sample_rate, i; BUG_ON(!out_div_lo); BUG_ON(!out_div_hi); @@ -291,11 +307,19 @@ static int mcasp_compute_clock_dividers(long fclk_rate, int tgt_sample_rate, fclk_rate >>= 7; - /* Next, make sure that our target Fs divides fClk/128 */ - if (fclk_rate % tgt_sample_rate) + /* rounded division: fclk_rate / tgt_sample_rate + 0.5 */ + divisor = (2 * fclk_rate + tgt_sample_rate) / (2 * tgt_sample_rate); + if (!divisor) return -EINVAL; - divisor = fclk_rate / tgt_sample_rate; + sample_rate = fclk_rate / divisor; + + /* ppm calculation in two steps to avoid overflow */ + ppm = abs(tgt_sample_rate - sample_rate); + ppm = (1000000 * ppm) / tgt_sample_rate; + + if (ppm > MCASP_ALLOWED_PPM) + return -EINVAL; /* At this point, divisor holds the product of the two divider values we * need to use for ACLKXCTL and AHCLKXCTL. ACLKXCTL holds a 5 bit @@ -319,43 +343,7 @@ static int mcasp_compute_clock_dividers(long fclk_rate, int tgt_sample_rate, return (*out_div_hi <= 4096) ? 0 : -EINVAL; } -static int mcasp_compute_playback_rates(long fclk_rate) -{ - static const int rate_table[][2] = { - { 5512, SNDRV_PCM_RATE_5512 }, - { 8000, SNDRV_PCM_RATE_8000 }, - { 11025, SNDRV_PCM_RATE_11025 }, - { 16000, SNDRV_PCM_RATE_16000 }, - { 22050, SNDRV_PCM_RATE_22050 }, - { 32000, SNDRV_PCM_RATE_32000 }, - { 44100, SNDRV_PCM_RATE_44100 }, - { 48000, SNDRV_PCM_RATE_48000 }, - { 64000, SNDRV_PCM_RATE_64000 }, - { 88200, SNDRV_PCM_RATE_88200 }, - { 96000, SNDRV_PCM_RATE_96000 }, - { 176400, SNDRV_PCM_RATE_176400 }, - { 192000, SNDRV_PCM_RATE_192000 }, - }; - int i, res; - - if (!fclk_rate) - return 0; - - res = 0; - for (i = 0; i < ARRAY_SIZE(rate_table); ++i) { - int lo, hi; - - if (!mcasp_compute_clock_dividers(fclk_rate, - rate_table[i][0], - &lo, - &hi)) - res |= rate_table[i][1]; - } - - return res; -} - -static int mcasp_start_tx(struct omap_mcasp *mcasp) +static int omap_mcasp_start(struct omap_mcasp *mcasp) { int i; mcasp_set_ctl_reg(mcasp->base + OMAP_MCASP_GBLCTL_REG, TXHCLKRST); @@ -386,39 +374,22 @@ static int mcasp_start_tx(struct omap_mcasp *mcasp) return 0; } -static int omap_mcasp_start(struct omap_mcasp *mcasp, int stream) -{ - if (stream == SNDRV_PCM_STREAM_PLAYBACK) - return mcasp_start_tx(mcasp); - - return -EINVAL; -} - -static void mcasp_stop_tx(struct omap_mcasp *mcasp) +static void omap_mcasp_stop(struct omap_mcasp *mcasp) { mcasp_set_reg(mcasp->base + OMAP_MCASP_GBLCTL_REG, 0); mcasp_set_reg(mcasp->base + OMAP_MCASP_TXSTAT_REG, OMAP_MCASP_TXSTAT_MASK); } -static void omap_mcasp_stop(struct omap_mcasp *mcasp, int stream) -{ - if (stream == SNDRV_PCM_STREAM_PLAYBACK) - mcasp_stop_tx(mcasp); -} - static int omap_mcasp_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct platform_device *pdev; struct omap_mcasp *mcasp = snd_soc_dai_get_drvdata(dai); mcasp_clk_on(mcasp); - pdev = to_platform_device(mcasp->dev); - if (!mcasp->active++) - pm_runtime_get_sync(&pdev->dev); + pm_runtime_get_sync(mcasp->dev); mcasp_set_reg(mcasp->base + OMAP_MCASP_SYSCONFIG_REG, 0x1); @@ -428,15 +399,12 @@ static int omap_mcasp_startup(struct snd_pcm_substream *substream, static void omap_mcasp_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct platform_device *pdev; struct omap_mcasp *mcasp = snd_soc_dai_get_drvdata(dai); - pdev = to_platform_device(mcasp->dev); - mcasp_set_reg(mcasp->base + OMAP_MCASP_SYSCONFIG_REG, 0x2); if (!--mcasp->active) - pm_runtime_put_sync(&pdev->dev); + pm_runtime_put_sync(mcasp->dev); mcasp_clk_off(mcasp); } @@ -444,7 +412,7 @@ static void omap_mcasp_shutdown(struct snd_pcm_substream *substream, /* S/PDIF */ static int omap_hw_dit_param(struct omap_mcasp *mcasp, unsigned int rate) { - u32 aclkxdiv, ahclkxdiv; + u32 aclkxdiv, ahclkxdiv, ditcsr; int res; /* Set TX frame synch : DIT Mode, 1 bit width, internal, rising edge */ @@ -478,6 +446,41 @@ static int omap_hw_dit_param(struct omap_mcasp *mcasp, unsigned int rate) return res; } + switch (rate) { + case 22050: + ditcsr = OMAP_MCASP_DITCSR_22050HZ; + break; + case 24000: + ditcsr = OMAP_MCASP_DITCSR_24000HZ; + break; + case 32000: + ditcsr = OMAP_MCASP_DITCSR_32000HZ; + break; + case 44100: + ditcsr = OMAP_MCASP_DITCSR_44100HZ; + break; + case 48000: + ditcsr = OMAP_MCASP_DITCSR_48000HZ; + break; + case 88200: + ditcsr = OMAP_MCASP_DITCSR_88200HZ; + break; + case 96000: + ditcsr = OMAP_MCASP_DITCSR_96000HZ; + break; + case 176400: + ditcsr = OMAP_MCASP_DITCSR_176400HZ; + break; + case 192000: + ditcsr = OMAP_MCASP_DITCSR_192000HZ; + break; + default: + dev_err(mcasp->dev, "%s: Invalid sampling rate: %d\n", + __func__, rate); + return -EINVAL; + } + mcasp_set_reg(mcasp->base + OMAP_MCASP_DITCSRA_REG, ditcsr); + mcasp_set_reg(mcasp->base + OMAP_MCASP_DITCSRB_REG, ditcsr); mcasp_set_bits(mcasp->base + OMAP_MCASP_AHCLKXCTL_REG, AHCLKXDIV(ahclkxdiv)); mcasp_set_bits(mcasp->base + OMAP_MCASP_ACLKXCTL_REG, @@ -516,12 +519,7 @@ static int omap_mcasp_hw_params(struct snd_pcm_substream *substream, struct omap_mcasp *mcasp = snd_soc_dai_get_drvdata(dai); int stream = substream->stream; - mcasp_stop_tx(mcasp); - - if ((params_format(params)) != SNDRV_PCM_FORMAT_S16_LE) { - printk(KERN_WARNING "omap-mcasp: unsupported PCM format"); - return -EINVAL; - } + omap_mcasp_stop(mcasp); if (omap_hw_dit_param(mcasp, params_rate(params)) < 0) return -EPERM; @@ -542,13 +540,13 @@ static int omap_mcasp_trigger(struct snd_pcm_substream *substream, case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - ret = omap_mcasp_start(mcasp, substream->stream); + ret = omap_mcasp_start(mcasp); break; case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - omap_mcasp_stop(mcasp, substream->stream); + omap_mcasp_stop(mcasp); break; default: @@ -566,6 +564,11 @@ static struct snd_soc_dai_ops omap_mcasp_dai_ops = { }; +#define MCASP_RATES (SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | \ + SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | \ + SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 | \ + SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000) + static struct snd_soc_dai_driver omap_mcasp_dai[] = { { .name = "omap-mcasp-dai", @@ -573,6 +576,7 @@ static struct snd_soc_dai_driver omap_mcasp_dai[] = { .channels_min = 1, .channels_max = 384, .formats = SNDRV_PCM_FMTBIT_S16_LE, + .rates = MCASP_RATES, }, .ops = &omap_mcasp_dai_ops, }, @@ -613,15 +617,6 @@ static __devinit int omap_mcasp_probe(struct platform_device *pdev) platform_set_drvdata(pdev, mcasp); mcasp->dev = &pdev->dev; - omap_mcasp_dai[0].playback.rates = - mcasp_compute_playback_rates(fclk_rate); - if (!omap_mcasp_dai[0].playback.rates) { - dev_err(&pdev->dev, "no valid sample rates can be produce from" - " a %ld Hz fClk\n", fclk_rate); - ret = -ENODEV; - goto err; - } - ret = snd_soc_register_dai(&pdev->dev, omap_mcasp_dai); if (ret < 0) |