diff options
author | Xinyu Chen <xinyu.chen@freescale.com> | 2012-08-01 10:03:09 +0800 |
---|---|---|
committer | Xinyu Chen <xinyu.chen@freescale.com> | 2012-08-01 10:03:09 +0800 |
commit | d81dac54ea06a1f8a74acf91499d5946d94d9e6a (patch) | |
tree | a137a6698343f3dfb880456cc4d89872f2a9b877 /arch | |
parent | c72eec4afb9215391f06c1a1ce14a63e17ed64e2 (diff) | |
parent | 091604c85f017199cae9d437545a96157ab063e0 (diff) |
Merge remote branch 'fsl-linux-sdk/imx_3.0.35' into imx_3.0.35_android
Conflicts:
drivers/mxc/vpu/mxc_vpu.c
Diffstat (limited to 'arch')
26 files changed, 350 insertions, 143 deletions
diff --git a/arch/arm/configs/imx6_defconfig b/arch/arm/configs/imx6_defconfig index e032e6cc3de3..181cf312d2b4 100644 --- a/arch/arm/configs/imx6_defconfig +++ b/arch/arm/configs/imx6_defconfig @@ -1938,6 +1938,7 @@ CONFIG_USB_OTG=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_EHCI_ARC=y CONFIG_USB_EHCI_ARC_OTG=y +CONFIG_USB_EHCI_ARC_H1=y # CONFIG_USB_EHCI_ARC_HSIC is not set # CONFIG_USB_STATIC_IRAM is not set CONFIG_USB_EHCI_ROOT_HUB_TT=y diff --git a/arch/arm/configs/imx6s_defconfig b/arch/arm/configs/imx6s_defconfig index 78efc6b7563e..04c445e3258b 100644 --- a/arch/arm/configs/imx6s_defconfig +++ b/arch/arm/configs/imx6s_defconfig @@ -1924,6 +1924,7 @@ CONFIG_USB_OTG=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_EHCI_ARC=y CONFIG_USB_EHCI_ARC_OTG=y +CONFIG_USB_EHCI_ARC_H1=y # CONFIG_USB_EHCI_ARC_HSIC is not set # CONFIG_USB_STATIC_IRAM is not set CONFIG_USB_EHCI_ROOT_HUB_TT=y diff --git a/arch/arm/mach-mx6/Kconfig b/arch/arm/mach-mx6/Kconfig index 5c60c560f03a..08875a60a31c 100644 --- a/arch/arm/mach-mx6/Kconfig +++ b/arch/arm/mach-mx6/Kconfig @@ -218,6 +218,10 @@ config IMX_PCIE bool "PCI Express support" select PCI +config USB_EHCI_ARC_H1 + tristate "USB Host 1 support" + depends on USB_EHCI_ARC + config MX6_INTER_LDO_BYPASS bool "Internal LDO in MX6Q/DL bypass" depends on REGULATOR_PFUZE100 && CPU_FREQ_IMX && ARCH_MX6 diff --git a/arch/arm/mach-mx6/Makefile b/arch/arm/mach-mx6/Makefile index 03ae8ddfc75d..24dae23dd089 100644 --- a/arch/arm/mach-mx6/Makefile +++ b/arch/arm/mach-mx6/Makefile @@ -3,7 +3,7 @@ # # Object file lists. -obj-y := cpu.o mm.o system.o devices.o dummy_gpio.o irq.o bus_freq.o usb_dr.o usb_h1.o usb_h2.o usb_h3.o \ +obj-y := cpu.o mm.o system.o devices.o dummy_gpio.o irq.o bus_freq.o usb_dr.o usb_h2.o usb_h3.o\ pm.o cpu_op-mx6.o mx6_wfi.o mx6_fec.o mx6_anatop_regulator.o cpu_regulator-mx6.o \ mx6_mmdc.o mx6_ddr_freq.o @@ -16,3 +16,4 @@ obj-$(CONFIG_MACH_MX6Q_SABREAUTO) += board-mx6q_sabreauto.o mx6q_sabreauto_pmic_ obj-$(CONFIG_SMP) += plat_hotplug.o platsmp.o headsmp.o obj-$(CONFIG_LOCAL_TIMERS) += localtimer.o obj-$(CONFIG_IMX_PCIE) += pcie.o +obj-$(CONFIG_USB_EHCI_ARC_H1) += usb_h1.o
\ No newline at end of file diff --git a/arch/arm/mach-mx6/board-mx6q_arm2.c b/arch/arm/mach-mx6/board-mx6q_arm2.c index c335e5e451c0..f298e8d67c06 100644 --- a/arch/arm/mach-mx6/board-mx6q_arm2.c +++ b/arch/arm/mach-mx6/board-mx6q_arm2.c @@ -182,9 +182,9 @@ static int plt_sd_pad_change(unsigned int index, int clock) /* LOW speed is the default state of SD pads */ static enum sd_pad_mode pad_mode = SD_PAD_MODE_LOW_SPEED; - iomux_v3_cfg_t *sd_pads_200mhz; - iomux_v3_cfg_t *sd_pads_100mhz; - iomux_v3_cfg_t *sd_pads_50mhz; + iomux_v3_cfg_t *sd_pads_200mhz = NULL; + iomux_v3_cfg_t *sd_pads_100mhz = NULL; + iomux_v3_cfg_t *sd_pads_50mhz = NULL; u32 sd_pads_200mhz_cnt; u32 sd_pads_100mhz_cnt; @@ -390,7 +390,7 @@ static struct mtd_partition m25p32_partitions[] = { { .name = "bootloader", .offset = 0, - .size = 0x00040000, + .size = 0x00100000, }, { .name = "kernel", .offset = MTDPART_OFS_APPEND, @@ -1240,7 +1240,6 @@ static void __init mx6_arm2_init_usb(void) mx6_set_otghost_vbus_func(imx6_arm2_usbotg_vbus); mx6_usb_dr_init(); - mx6_usb_h1_init(); #ifdef CONFIG_USB_EHCI_ARC_HSIC mx6_usb_h2_init(); mx6_usb_h3_init(); @@ -1410,6 +1409,8 @@ static void hdmi_init(int ipu_id, int disp_id) /* GPR3, bits 2-3 = HDMI_MUX_CTL */ mxc_iomux_set_gpr_register(3, 2, 2, hdmi_mux_setting); + /* GPR0, bit 0 = 1 */ + mxc_iomux_set_gpr_register(0, 0, 1, 1); } /* On mx6x arm2 board i2c2 iomux with hdmi ddc, diff --git a/arch/arm/mach-mx6/board-mx6q_sabreauto.c b/arch/arm/mach-mx6/board-mx6q_sabreauto.c index 7d2eab2c89f2..2acfea71f331 100644 --- a/arch/arm/mach-mx6/board-mx6q_sabreauto.c +++ b/arch/arm/mach-mx6/board-mx6q_sabreauto.c @@ -55,6 +55,7 @@ #include <linux/regulator/consumer.h> #include <linux/regulator/machine.h> #include <linux/regulator/fixed.h> +#include <linux/mxc_asrc.h> #include <sound/pcm.h> #include <mach/common.h> @@ -224,9 +225,9 @@ static int plt_sd_pad_change(unsigned int index, int clock) /* LOW speed is the default state of SD pads */ static enum sd_pad_mode pad_mode = SD_PAD_MODE_LOW_SPEED; - iomux_v3_cfg_t *sd_pads_200mhz; - iomux_v3_cfg_t *sd_pads_100mhz; - iomux_v3_cfg_t *sd_pads_50mhz; + iomux_v3_cfg_t *sd_pads_200mhz = NULL; + iomux_v3_cfg_t *sd_pads_100mhz = NULL; + iomux_v3_cfg_t *sd_pads_50mhz = NULL; u32 sd_pads_200mhz_cnt; u32 sd_pads_100mhz_cnt; @@ -401,7 +402,7 @@ static struct mtd_partition m25p32_partitions[] = { { .name = "bootloader", .offset = 0, - .size = 0x00040000, + .size = 0x00100000, }, { .name = "kernel", .offset = MTDPART_OFS_APPEND, @@ -757,7 +758,6 @@ static void __init imx6q_sabreauto_init_usb(void) mx6_set_otghost_vbus_func(imx6q_sabreauto_usbotg_vbus); mx6_usb_dr_init(); mx6_set_host1_vbus_func(imx6q_sabreauto_usbhost1_vbus); - mx6_usb_h1_init(); #ifdef CONFIG_USB_EHCI_ARC_HSIC mx6_usb_h2_init(); mx6_usb_h3_init(); @@ -1075,9 +1075,15 @@ static const struct pm_platform_data mx6q_sabreauto_pm_data __initconst = { .suspend_exit = sabreauto_suspend_exit, }; +static const struct asrc_p2p_params esai_p2p = { + .p2p_rate = 48000, + .p2p_width = ASRC_WIDTH_24_BIT, +}; + static struct mxc_audio_platform_data sab_audio_data = { .sysclk = 24576000, .codec_name = "cs42888.1-0048", + .priv = (void *)&esai_p2p, }; static struct platform_device sab_audio_device = { diff --git a/arch/arm/mach-mx6/board-mx6q_sabrelite.c b/arch/arm/mach-mx6/board-mx6q_sabrelite.c index 925dfb71ea0e..16ee57e1df2b 100644 --- a/arch/arm/mach-mx6/board-mx6q_sabrelite.c +++ b/arch/arm/mach-mx6/board-mx6q_sabrelite.c @@ -365,9 +365,9 @@ static int plt_sd_pad_change(unsigned int index, int clock) /* LOW speed is the default state of SD pads */ static enum sd_pad_mode pad_mode = SD_PAD_MODE_LOW_SPEED; - iomux_v3_cfg_t *sd_pads_200mhz; - iomux_v3_cfg_t *sd_pads_100mhz; - iomux_v3_cfg_t *sd_pads_50mhz; + iomux_v3_cfg_t *sd_pads_200mhz = NULL; + iomux_v3_cfg_t *sd_pads_100mhz = NULL; + iomux_v3_cfg_t *sd_pads_50mhz = NULL; u32 sd_pads_200mhz_cnt; u32 sd_pads_100mhz_cnt; @@ -482,7 +482,7 @@ static struct mtd_partition imx6_sabrelite_spi_nor_partitions[] = { { .name = "bootloader", .offset = 0, - .size = 0x00040000, + .size = 0x00100000, }, { .name = "kernel", @@ -660,7 +660,6 @@ static void __init imx6q_sabrelite_init_usb(void) mx6_set_otghost_vbus_func(imx6q_sabrelite_usbotg_vbus); mx6_usb_dr_init(); - mx6_usb_h1_init(); } /* HW Initialization, if return 0, initialization is successful. */ diff --git a/arch/arm/mach-mx6/board-mx6q_sabresd.c b/arch/arm/mach-mx6/board-mx6q_sabresd.c index bdcef07c6a4e..ee40c551bbb8 100644 --- a/arch/arm/mach-mx6/board-mx6q_sabresd.c +++ b/arch/arm/mach-mx6/board-mx6q_sabresd.c @@ -298,7 +298,7 @@ static struct mtd_partition imx6_sabresd_spi_nor_partitions[] = { { .name = "bootloader", .offset = 0, - .size = 0x00040000, + .size = 0x00100000, }, { .name = "kernel", @@ -1118,7 +1118,6 @@ static void __init imx6q_sabresd_init_usb(void) mx6_set_otghost_vbus_func(imx6q_sabresd_usbotg_vbus); mx6_usb_dr_init(); - mx6_usb_h1_init(); } /* HW Initialization, if return 0, initialization is successful. */ diff --git a/arch/arm/mach-mx6/board-mx6sl_arm2.c b/arch/arm/mach-mx6/board-mx6sl_arm2.c index 2efca1ba5d93..0097fdc05fa7 100755 --- a/arch/arm/mach-mx6/board-mx6sl_arm2.c +++ b/arch/arm/mach-mx6/board-mx6sl_arm2.c @@ -146,9 +146,9 @@ static int plt_sd_pad_change(unsigned int index, int clock) /* LOW speed is the default state of SD pads */ static enum sd_pad_mode pad_mode = SD_PAD_MODE_LOW_SPEED; - iomux_v3_cfg_t *sd_pads_200mhz; - iomux_v3_cfg_t *sd_pads_100mhz; - iomux_v3_cfg_t *sd_pads_50mhz; + iomux_v3_cfg_t *sd_pads_200mhz = NULL; + iomux_v3_cfg_t *sd_pads_100mhz = NULL; + iomux_v3_cfg_t *sd_pads_50mhz = NULL; u32 sd_pads_200mhz_cnt; u32 sd_pads_100mhz_cnt; @@ -458,7 +458,7 @@ static struct mtd_partition m25p32_partitions[] = { { .name = "bootloader", .offset = 0, - .size = 0x00040000, + .size = 0x00100000, }, { .name = "kernel", .offset = MTDPART_OFS_APPEND, @@ -1127,7 +1127,6 @@ static void __init mx6_arm2_init_usb(void) mx6_set_otghost_vbus_func(imx6_arm2_usbotg_vbus); mx6_usb_dr_init(); - mx6_usb_h1_init(); #ifdef CONFIG_USB_EHCI_ARC_HSIC mx6_usb_h2_init(); #endif diff --git a/arch/arm/mach-mx6/bus_freq.c b/arch/arm/mach-mx6/bus_freq.c index b1a0af0f3d35..12dea1474d9a 100644 --- a/arch/arm/mach-mx6/bus_freq.c +++ b/arch/arm/mach-mx6/bus_freq.c @@ -78,6 +78,8 @@ void set_ddr_freq(int ddr_freq); extern int init_mmdc_settings(void); extern struct cpu_op *(*get_cpu_op)(int *op); extern int update_ddr_freq(int ddr_rate); +extern int chip_rev; +extern bool arm_mem_clked_in_wait; struct mutex bus_freq_mutex; @@ -128,7 +130,6 @@ static void reduce_bus_freq_handler(struct work_struct *work) if (!cpu_is_mx6sl()) { clk_enable(pll3); - if (lp_audio_freq) { /* Need to ensure that PLL2_PFD_400M is kept ON. */ clk_enable(pll2_400); @@ -149,6 +150,7 @@ static void reduce_bus_freq_handler(struct work_struct *work) if (med_bus_freq_mode) clk_disable(pll2_400); + clk_disable(pll3); } else { /* Set VDDSOC_CAP to 1.1V */ @@ -162,6 +164,8 @@ static void reduce_bus_freq_handler(struct work_struct *work) udelay(150); + arm_mem_clked_in_wait = true; + /* Set periph_clk to be sourced from OSC_CLK */ /* Set MMDC clk to 25MHz. */ /* First need to set the divider before changing the parent */ @@ -305,6 +309,12 @@ int set_high_bus_freq(int high_bus_freq) low_bus_freq_mode = 0; audio_bus_freq_mode = 0; + + /* Ensure that WAIT mode can be entered in high bus freq mode. */ + + if (cpu_is_mx6sl()) + arm_mem_clked_in_wait = false; + mutex_unlock(&bus_freq_mutex); return 0; diff --git a/arch/arm/mach-mx6/clock.c b/arch/arm/mach-mx6/clock.c index 600cd8b23414..34c26d4d3bc0 100644 --- a/arch/arm/mach-mx6/clock.c +++ b/arch/arm/mach-mx6/clock.c @@ -50,8 +50,6 @@ extern int lp_med_freq; extern int wait_mode_arm_podf; extern int lp_audio_freq; extern int cur_arm_podf; -extern bool arm_mem_clked_in_wait; -extern bool enable_wait_mode; void __iomem *apll_base; @@ -1295,23 +1293,6 @@ static int _clk_arm_set_rate(struct clk *clk, unsigned long rate) ipg_clk_rate = clk_get_rate(&ipg_clk); max_arm_wait_clk = (12 * ipg_clk_rate) / 5; wait_mode_arm_podf = parent_rate / max_arm_wait_clk; - if (wait_mode_arm_podf > 7) { - /* IPG_CLK is too low and we cannot get a ARM_CLK - * that will satisfy the 12:5 ratio. - * Use the mem_ipg_stop_mask bit to ensure clocks to ARM - * memories are not gated during WAIT mode. - * This bit is NOT available on MX6DQ TO1.1/TO1.0 and - * MX6DL TO1.0. - * Else disable entry to WAIT mode. - */ - if ((mx6q_revision() > IMX_CHIP_REVISION_1_1) || - (mx6dl_revision() > IMX_CHIP_REVISION_1_0)) - arm_mem_clked_in_wait = true; - else { - enable_wait_mode = false; - pr_info("wait mode is disabled due to ipg clock is too low\n"); - } - } if (div == 0) div = 1; @@ -5383,7 +5364,7 @@ int __init mx6_clocks_init(unsigned long ckil, unsigned long osc, /* on mx6dl gpu2d_axi_clk source from mmdc0 directly */ clk_set_parent(&gpu2d_axi_clk, &mmdc_ch0_axi_clk[0]); - clk_set_parent(&ipu1_clk, &pll2_pfd_400M); + clk_set_parent(&ipu1_clk, &pll3_pfd_540M); /* pxp & epdc */ clk_set_parent(&ipu2_clk, &pll2_pfd_400M); clk_set_rate(&ipu2_clk, 200000000); diff --git a/arch/arm/mach-mx6/clock_mx6sl.c b/arch/arm/mach-mx6/clock_mx6sl.c index 577a52277d68..887e6ad6fa96 100755 --- a/arch/arm/mach-mx6/clock_mx6sl.c +++ b/arch/arm/mach-mx6/clock_mx6sl.c @@ -52,7 +52,6 @@ extern int lp_high_freq; extern int lp_med_freq; extern int wait_mode_arm_podf; extern int mx6q_revision(void); -extern bool arm_mem_clked_in_wait; extern int cur_arm_podf; static void __iomem *apll_base; @@ -1180,16 +1179,6 @@ static int _clk_arm_set_rate(struct clk *clk, unsigned long rate) ipg_clk_rate = clk_get_rate(&ipg_clk); max_arm_wait_clk = (12 * ipg_clk_rate) / 5; wait_mode_arm_podf = parent_rate / max_arm_wait_clk; - if (wait_mode_arm_podf > 7) - /* IPG_CLK is too low and we cannot get a ARM_CLK - * that will satisfy the 12:5 ratio. - * Use the mem_ipg_stop_mask bit to ensure clocks - * to ARM memories are not gated during WAIT mode. - * Else disable entry to WAIT mode. - */ - arm_mem_clked_in_wait = true; - else - arm_mem_clked_in_wait = false; if (div == 0) div = 1; @@ -3964,7 +3953,7 @@ int __init mx6sl_clocks_init(unsigned long ckil, unsigned long osc, /* keep correct count. */ clk_enable(&cpu_clk); clk_enable(&periph_clk); - clk_enable(&mmdc_ch1_axi_clk); + clk_enable(&mmdc_ch1_axi_clk[0]); clk_tree_init(); diff --git a/arch/arm/mach-mx6/cpu.c b/arch/arm/mach-mx6/cpu.c index 5d9749653988..9a60d9817ec3 100644 --- a/arch/arm/mach-mx6/cpu.c +++ b/arch/arm/mach-mx6/cpu.c @@ -35,6 +35,7 @@ struct cpu_op *(*get_cpu_op)(int *op); bool enable_wait_mode = true; u32 arm_max_freq = CPU_AT_1GHz; bool mem_clk_on_in_wait; +int chip_rev; void __iomem *gpc_base; void __iomem *ccm_base; @@ -197,6 +198,13 @@ static int __init post_cpu_init(void) (mx6dl_revision() < IMX_CHIP_REVISION_1_1)) mem_clk_on_in_wait = false; + if (cpu_is_mx6q()) + chip_rev = mx6q_revision(); + else if (cpu_is_mx6dl()) + chip_rev = mx6dl_revision; + else + chip_rev = mx6sl_revision; + return 0; } postcore_initcall(post_cpu_init); diff --git a/arch/arm/mach-mx6/crm_regs.h b/arch/arm/mach-mx6/crm_regs.h index 2e1f3e4a32c4..5e03312b7fce 100644 --- a/arch/arm/mach-mx6/crm_regs.h +++ b/arch/arm/mach-mx6/crm_regs.h @@ -498,6 +498,7 @@ #define MXC_CCM_CGPR_MMDC_EXT_CLK_DIS (1 << 2) #define MXC_CCM_CGPR_PMIC_DELAY_SCALER (1) #define MXC_CCM_CGPR_MEM_IPG_STOP_MASK (1 << 1) +#define MXC_CCM_CGPR_WAIT_MODE_FIX (1 << 17) /* Define the bits in registers CCGRx */ #define MXC_CCM_CCGRx_CG_MASK 0x3 diff --git a/arch/arm/mach-mx6/mx6_wfi.S b/arch/arm/mach-mx6/mx6_wfi.S index a616dabc4a80..afe7b9a3f6cd 100644 --- a/arch/arm/mach-mx6/mx6_wfi.S +++ b/arch/arm/mach-mx6/mx6_wfi.S @@ -28,7 +28,7 @@ */ ENTRY(mx6_wait) - push {r4, r5, r6, r7, r8} + push {r4, r5, r6, r7, r8, r9} mov r7, r2 /* Store the arm_podf to be used. */ mov r6, r3 @@ -69,8 +69,11 @@ ENTRY(mx6_wait) /* Check to see if we need to switch to 24MHz */ cmp r7, #0 bne use_podf - ldr r6, =(1 << 16) - str r6, [r2, #0x04] + /* Switch ARM to PLL1 output. */ + /* PLL1 should already be in bypass state. */ + ldr r6, [r8, #0x0C] + bic r6, r6, #0x04 + str r6, [r8, #0x0C] b cont use_podf: @@ -100,7 +103,9 @@ cont: /* Switch to 24MHz or use ARM_PODF. */ cmp r7, #0x0 bne use_podf1 - str r6, [r2, #0x08] + /* Set pll1_sw_clk to run from STEP_CLK. */ + orr r6, r6, #0x04 + str r6, [r8, #0x0C] b DO_WFI use_podf1: str r6, [r8, #0x10] @@ -124,8 +129,11 @@ DO_WFI: mov r4, #0x0 cmp r7, #0x0 bne use_podf2 - ldr r6, =(1 << 16) - str r6, [r2, #0x08] + /* Set pll1_sw_clk to run from STEP_CLK. */ + ldr r6, [r8, #0x0C] + orr r6, r6, #0x04 + str r6, [r8, #0x0C] + b cont1 use_podf2: @@ -137,7 +145,7 @@ cont1: DONE: - pop {r4,r5, r6, r7, r8} + pop {r4,r5, r6, r7, r8, r9} /* Restore registers */ mov pc, lr diff --git a/arch/arm/mach-mx6/system.c b/arch/arm/mach-mx6/system.c index b9efbb64c8f9..ebc1ca1ee3cc 100644 --- a/arch/arm/mach-mx6/system.c +++ b/arch/arm/mach-mx6/system.c @@ -57,6 +57,7 @@ volatile unsigned int num_cpu_idle_lock = 0x0; int wait_mode_arm_podf; int cur_arm_podf; bool arm_mem_clked_in_wait; +void arch_idle_with_workaround(int cpu); extern void mx6_wait(void *num_cpu_idle_lock, void *num_cpu_idle, \ int wait_arm_podf, int cur_arm_podf); @@ -64,6 +65,7 @@ extern bool enable_wait_mode; extern int low_bus_freq_mode; extern int audio_bus_freq_mode; extern bool mem_clk_on_in_wait; +extern int chip_rev; void gpc_set_wakeup(unsigned int irq[4]) { @@ -201,6 +203,14 @@ void mxc_cpu_lp_set(enum mxc_cpu_pwr_mode mode) */ reg = __raw_readl(MXC_CCM_CGPR); reg |= MXC_CCM_CGPR_MEM_IPG_STOP_MASK; + if (!cpu_is_mx6sl()) { + /* + * For MX6QTO1.2 or later and MX6DLTO1.1 or later, + * ensure that the CCM_CGPR bit 17 is cleared before + * dormant mode is entered. + */ + reg &= ~MXC_CCM_CGPR_WAIT_MODE_FIX; + } __raw_writel(reg, MXC_CCM_CGPR); } } @@ -209,56 +219,122 @@ void mxc_cpu_lp_set(enum mxc_cpu_pwr_mode mode) extern int tick_broadcast_oneshot_active(void); - void arch_idle(void) +void arch_idle_single_core(void) { - if (enable_wait_mode) { - u32 reg; - int cpu = smp_processor_id(); - *((char *)(&num_cpu_idle_lock) + (char)cpu) = 0x0; - mxc_cpu_lp_set(WAIT_UNCLOCKED_POWER_OFF); - if (arm_mem_clked_in_wait || mem_clk_on_in_wait) { + u32 reg; + + if (cpu_is_mx6dl() && chip_rev > IMX_CHIP_REVISION_1_0) { + /* + * MX6DLS TO1.1 has the HW fix for the WAIT mode issue. + * Ensure that the CGPR bit 17 is set to enable the fix. + */ + reg = __raw_readl(MXC_CCM_CGPR); + reg |= MXC_CCM_CGPR_WAIT_MODE_FIX; + __raw_writel(reg, MXC_CCM_CGPR); + + cpu_do_idle(); + } else { + /* + * Implement the 12:5 ARM:IPG_CLK ratio + * workaround for the WAIT mode issue. + * We can directly use the divider to drop the ARM + * core freq in a single core environment. + * Set the ARM_PODF to get the max freq possible + * to avoid the WAIT mode issue when IPG is at 66MHz. + */ + if (cpu_is_mx6sl()) { reg = __raw_readl(MXC_CCM_CGPR); - reg &= ~MXC_CCM_CGPR_MEM_IPG_STOP_MASK; + reg |= MXC_CCM_CGPR_MEM_IPG_STOP_MASK; __raw_writel(reg, MXC_CCM_CGPR); + } + __raw_writel(wait_mode_arm_podf, MXC_CCM_CACRR); + while (__raw_readl(MXC_CCM_CDHIPR)) + ; + cpu_do_idle(); - cpu_do_idle(); - } else if (num_possible_cpus() == 1) { - /* We can directly use the divider to drop the ARM - * core freq in a single core environment. - */ - u32 podf = wait_mode_arm_podf; - /* Set the ARM_PODF to get the max freq possible - * to avoid the WAIT mode issue when IPG is at 66MHz. - */ - if (low_bus_freq_mode) - podf = 7; + __raw_writel(cur_arm_podf - 1, MXC_CCM_CACRR); + } +} - __raw_writel(podf, MXC_CCM_CACRR); - while (__raw_readl(MXC_CCM_CDHIPR)) - ; - cpu_do_idle(); +void arch_idle_with_workaround(cpu) +{ + u32 reg; + u32 podf = wait_mode_arm_podf; + + *((char *)(&num_cpu_idle_lock) + (char)cpu) = 0x0; + + if (low_bus_freq_mode || audio_bus_freq_mode) + /* In case when IPG is at 12MHz, we need to ensure that + * ARM is at 24MHz, as the max freq ARM can run at is + *~28.8MHz. + */ + podf = 0; + + mx6_wait((void *)&num_cpu_idle_lock, + (void *)&num_cpu_idle, + podf, cur_arm_podf - 1); + +} + +void arch_idle_multi_core(void) +{ + u32 reg; + int cpu = smp_processor_id(); - __raw_writel(cur_arm_podf - 1, MXC_CCM_CACRR); - } else { #ifdef CONFIG_LOCAL_TIMERS - if (!tick_broadcast_oneshot_active() - || !tick_oneshot_mode_active()) - return; + if (!tick_broadcast_oneshot_active() + || !tick_oneshot_mode_active()) + return; - clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu); + clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu); #endif - if (low_bus_freq_mode || audio_bus_freq_mode) - mx6_wait((void *)&num_cpu_idle_lock, - (void *)&num_cpu_idle, - 7, cur_arm_podf - 1); - else - mx6_wait((void *)&num_cpu_idle_lock, - (void *)&num_cpu_idle, - wait_mode_arm_podf, cur_arm_podf - 1); + /* iMX6Q and iMX6DL */ + if ((cpu_is_mx6q() && chip_rev >= IMX_CHIP_REVISION_1_2) || + (cpu_is_mx6dl() && chip_rev >= IMX_CHIP_REVISION_1_1)) { + /* + * This code should only be executed on MX6QTO1.2 or later + * and MX6DL TO1.1 or later. + * These chips have the HW fix for the WAIT mode issue. + * Ensure that the CGPR bit 17 is set to enable the fix. + */ + + reg = __raw_readl(MXC_CCM_CGPR); + reg |= MXC_CCM_CGPR_WAIT_MODE_FIX; + __raw_writel(reg, MXC_CCM_CGPR); + + cpu_do_idle(); + } else + arch_idle_with_workaround(cpu); #ifdef CONFIG_LOCAL_TIMERS - clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu); + clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu); #endif - } + +} + +void arch_idle(void) +{ + if (enable_wait_mode) { + mxc_cpu_lp_set(WAIT_UNCLOCKED_POWER_OFF); + if ((mem_clk_on_in_wait || arm_mem_clked_in_wait)) { + u32 reg; + /* + * MX6SL, MX6Q (TO1.2 or later) and + * MX6DL (TO1.1 or later) have a bit in CCM_CGPR that + * when cleared keeps the clocks to memories ON + * when ARM is in WFI. This mode can be used when + * IPG clock is very low (12MHz) and the ARM:IPG ratio + * perhaps cannot be maintained. + */ + reg = __raw_readl(MXC_CCM_CGPR); + reg &= ~MXC_CCM_CGPR_MEM_IPG_STOP_MASK; + __raw_writel(reg, MXC_CCM_CGPR); + + cpu_do_idle(); + } else if (num_possible_cpus() == 1) + /* iMX6SL or iMX6DLS */ + arch_idle_single_core(); + else + arch_idle_multi_core(); } else { mxc_cpu_lp_set(WAIT_CLOCKED); cpu_do_idle(); diff --git a/arch/arm/mach-mx6/usb.h b/arch/arm/mach-mx6/usb.h index 145cfbfcc728..f796e7dad87c 100644 --- a/arch/arm/mach-mx6/usb.h +++ b/arch/arm/mach-mx6/usb.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright (C) 2011-2012 Freescale Semiconductor, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -29,7 +29,7 @@ extern int gpio_usbotg_utmi_active(void); extern void gpio_usbotg_utmi_inactive(void); extern void __init mx6_usb_dr_init(void); -extern void __init mx6_usb_h1_init(void); +extern bool usb_icbug_swfix_need(void); extern void __init mx6_usb_h2_init(void); extern void __init mx6_usb_h3_init(void); @@ -38,6 +38,7 @@ extern void mx6_set_host3_vbus_func(driver_vbus_func); extern void mx6_set_host2_vbus_func(driver_vbus_func); extern void mx6_set_host1_vbus_func(driver_vbus_func); extern void mx6_set_otghost_vbus_func(driver_vbus_func); +extern void mx6_set_usb_host1_vbus_func(driver_vbus_func *driver_vbus); extern struct platform_device anatop_thermal_device; extern struct platform_device mxc_usbdr_otg_device; extern struct platform_device mxc_usbdr_udc_device; @@ -60,3 +61,15 @@ extern struct platform_device mxc_usbh1_wakeup_device; #endif extern void __iomem *imx_otg_base; +#define imx_fsl_usb2_wakeup_data_entry_single(soc, _id, hs) \ + { \ + .id = _id, \ + .irq_phy = soc ## _INT_USB_PHY ## _id, \ + .irq_core = soc ## _INT_USB_ ## hs, \ + } +#define imx_mxc_ehci_data_entry_single(soc, _id, hs) \ + { \ + .id = _id, \ + .iobase = soc ## _USB_ ## hs ## _BASE_ADDR, \ + .irq = soc ## _INT_USB_ ## hs, \ + } diff --git a/arch/arm/mach-mx6/usb_dr.c b/arch/arm/mach-mx6/usb_dr.c index dbd1e67b3fc5..1efac33aa7fc 100644 --- a/arch/arm/mach-mx6/usb_dr.c +++ b/arch/arm/mach-mx6/usb_dr.c @@ -164,8 +164,9 @@ static int usb_phy_enable(struct fsl_usb2_platform_data *pdata) } if (!usb_icbug_swfix_need()) - __raw_writel(((1 << 17) | (1 << 18)), - phy_reg + HW_USBPHY_IP_SET); + __raw_writel((1 << 17), phy_reg + HW_USBPHY_IP_SET); + if (cpu_is_mx6sl()) + __raw_writel((1 << 18), phy_reg + HW_USBPHY_IP_SET); return 0; } /* Notes: configure USB clock*/ @@ -380,7 +381,7 @@ static void usbotg_wakeup_event_clear(void) #ifdef CONFIG_USB_EHCI_ARC_OTG /* Beginning of host related operation for DR port */ -static void _host_platform_rh_suspend(struct fsl_usb2_platform_data *pdata) +static void _host_platform_rh_suspend_swfix(struct fsl_usb2_platform_data *pdata) { void __iomem *phy_reg = MX6_IO_ADDRESS(USB_PHY0_BASE_ADDR); u32 tmp; @@ -419,7 +420,7 @@ static void _host_platform_rh_suspend(struct fsl_usb2_platform_data *pdata) fsl_platform_otg_set_usb_phy_dis(pdata, 0); } -static void _host_platform_rh_resume(struct fsl_usb2_platform_data *pdata) +static void _host_platform_rh_resume_swfix(struct fsl_usb2_platform_data *pdata) { u32 index = 0; @@ -438,6 +439,25 @@ static void _host_platform_rh_resume(struct fsl_usb2_platform_data *pdata) udelay(500); fsl_platform_otg_set_usb_phy_dis(pdata, 1); } +static void _host_platform_rh_suspend(struct fsl_usb2_platform_data *pdata) +{ + /*for mx6sl ,we do not need any sw fix*/ + if (cpu_is_mx6sl()) + return ; + __raw_writel(BM_USBPHY_CTRL_ENHOSTDISCONDETECT, + MX6_IO_ADDRESS(pdata->phy_regs) + + HW_USBPHY_CTRL_CLR); +} + +static void _host_platform_rh_resume(struct fsl_usb2_platform_data *pdata) +{ + /*for mx6sl ,we do not need any sw fix*/ + if (cpu_is_mx6sl()) + return ; + __raw_writel(BM_USBPHY_CTRL_ENHOSTDISCONDETECT, + MX6_IO_ADDRESS(pdata->phy_regs) + + HW_USBPHY_CTRL_SET); +} static void _host_phy_lowpower_suspend(struct fsl_usb2_platform_data *pdata, bool enable) { @@ -579,11 +599,11 @@ void __init mx6_usb_dr_init(void) dr_utmi_config.operating_mode = DR_HOST_MODE; dr_utmi_config.wake_up_enable = _host_wakeup_enable; if (usb_icbug_swfix_need()) { + dr_utmi_config.platform_rh_suspend = _host_platform_rh_suspend_swfix; + dr_utmi_config.platform_rh_resume = _host_platform_rh_resume_swfix; + } else { dr_utmi_config.platform_rh_suspend = _host_platform_rh_suspend; dr_utmi_config.platform_rh_resume = _host_platform_rh_resume; - } else { - dr_utmi_config.platform_rh_suspend = NULL; - dr_utmi_config.platform_rh_resume = NULL; } dr_utmi_config.platform_set_disconnect_det = fsl_platform_otg_set_usb_phy_dis; dr_utmi_config.phy_lowpower_suspend = _host_phy_lowpower_suspend; diff --git a/arch/arm/mach-mx6/usb_h1.c b/arch/arm/mach-mx6/usb_h1.c index bff9a29aef02..92ef0ec3c3f5 100644 --- a/arch/arm/mach-mx6/usb_h1.c +++ b/arch/arm/mach-mx6/usb_h1.c @@ -34,7 +34,6 @@ static struct clk *usb_oh3_clk; extern int clk_get_usecount(struct clk *clk); static struct fsl_usb2_platform_data usbh1_config; -extern bool usb_icbug_swfix_need(void); static void fsl_platform_h1_set_usb_phy_dis( struct fsl_usb2_platform_data *pdata, bool enable) @@ -126,8 +125,9 @@ static int usb_phy_enable(struct fsl_usb2_platform_data *pdata) __raw_writel(tmp, phy_reg + HW_USBPHY_CTRL); if (!usb_icbug_swfix_need()) - __raw_writel(((1 << 17) | (1 << 18)), - phy_reg + HW_USBPHY_IP_SET); + __raw_writel((1 << 17), phy_reg + HW_USBPHY_IP_SET); + if (cpu_is_mx6sl()) + __raw_writel((1 << 18), phy_reg + HW_USBPHY_IP_SET); return 0; } static int fsl_usb_host_init_ext(struct platform_device *pdev) @@ -170,11 +170,6 @@ static void usbh1_clock_gate(bool on) } } -void mx6_set_host1_vbus_func(driver_vbus_func driver_vbus) -{ - usbh1_config.platform_driver_vbus = driver_vbus; -} - static void _wake_up_enable(struct fsl_usb2_platform_data *pdata, bool enable) { void __iomem *phy_reg = MX6_IO_ADDRESS(USB_PHY1_BASE_ADDR); @@ -199,7 +194,7 @@ static void _wake_up_enable(struct fsl_usb2_platform_data *pdata, bool enable) } } -static void usbh1_platform_rh_suspend(struct fsl_usb2_platform_data *pdata) +static void usbh1_platform_rh_suspend_swfix(struct fsl_usb2_platform_data *pdata) { void __iomem *phy_reg = MX6_IO_ADDRESS(USB_PHY1_BASE_ADDR); u32 tmp; @@ -238,7 +233,7 @@ static void usbh1_platform_rh_suspend(struct fsl_usb2_platform_data *pdata) fsl_platform_h1_set_usb_phy_dis(pdata, 0); } -static void usbh1_platform_rh_resume(struct fsl_usb2_platform_data *pdata) +static void usbh1_platform_rh_resume_swfix(struct fsl_usb2_platform_data *pdata) { u32 index = 0; @@ -258,6 +253,26 @@ static void usbh1_platform_rh_resume(struct fsl_usb2_platform_data *pdata) fsl_platform_h1_set_usb_phy_dis(pdata, 1); } +static void usbh1_platform_rh_suspend(struct fsl_usb2_platform_data *pdata) +{ + /*for mx6sl ,we do not need any sw fix*/ + if (cpu_is_mx6sl()) + return ; + __raw_writel(BM_USBPHY_CTRL_ENHOSTDISCONDETECT, + MX6_IO_ADDRESS(pdata->phy_regs) + + HW_USBPHY_CTRL_CLR); +} + +static void usbh1_platform_rh_resume(struct fsl_usb2_platform_data *pdata) +{ + /*for mx6sl ,we do not need any sw fix*/ + if (cpu_is_mx6sl()) + return ; + __raw_writel(BM_USBPHY_CTRL_ENHOSTDISCONDETECT, + MX6_IO_ADDRESS(pdata->phy_regs) + + HW_USBPHY_CTRL_SET); +} + static void _phy_lowpower_suspend(struct fsl_usb2_platform_data *pdata, bool enable) { u32 tmp; @@ -347,18 +362,49 @@ static struct fsl_usb2_wakeup_platform_data usbh1_wakeup_config = { .usb_wakeup_exhandle = usbh1_wakeup_event_clear, }; -void __init mx6_usb_h1_init(void) +static struct platform_device *pdev, *pdev_wakeup; +static driver_vbus_func mx6_set_usb_host1_vbus; + +static int __init mx6_usb_h1_init(void) { - struct platform_device *pdev, *pdev_wakeup; static void __iomem *anatop_base_addr = MX6_IO_ADDRESS(ANATOP_BASE_ADDR); + struct imx_fsl_usb2_wakeup_data imx6q_fsl_hs_wakeup_data[] = { + imx_fsl_usb2_wakeup_data_entry_single(MX6Q, 1, HS1)}; + struct imx_fsl_usb2_wakeup_data imx6sl_fsl_hs_wakeup_data[] = { + imx_fsl_usb2_wakeup_data_entry_single(MX6SL, 1, HS1)}; + struct imx_mxc_ehci_data imx6q_mxc_ehci_hs_data[] = { + imx_mxc_ehci_data_entry_single(MX6Q, 1, HS1)}; + struct imx_mxc_ehci_data imx6sl_mxc_ehci_hs_data[] = { + imx_mxc_ehci_data_entry_single(MX6SL, 1, HS1)}; + + mx6_set_usb_host1_vbus_func(&mx6_set_usb_host1_vbus); + if (mx6_set_usb_host1_vbus) + mx6_set_usb_host1_vbus(true); + + /* Some phy and power's special controls for host1 + * 1. The external charger detector needs to be disabled + * or the signal at DP will be poor + * 2. The PLL's power and output to usb for host 1 + * is totally controlled by IC, so the Software only needs + * to enable them at initializtion. + */ + __raw_writel(BM_ANADIG_USB2_CHRG_DETECT_EN_B \ + | BM_ANADIG_USB2_CHRG_DETECT_CHK_CHRG_B, \ + anatop_base_addr + HW_ANADIG_USB2_CHRG_DETECT); + __raw_writel(BM_ANADIG_USB2_PLL_480_CTRL_BYPASS, + anatop_base_addr + HW_ANADIG_USB2_PLL_480_CTRL_CLR); + __raw_writel(BM_ANADIG_USB2_PLL_480_CTRL_ENABLE \ + | BM_ANADIG_USB2_PLL_480_CTRL_POWER \ + | BM_ANADIG_USB2_PLL_480_CTRL_EN_USB_CLKS, \ + anatop_base_addr + HW_ANADIG_USB2_PLL_480_CTRL_SET); usbh1_config.wakeup_pdata = &usbh1_wakeup_config; if (usb_icbug_swfix_need()) { + usbh1_config.platform_rh_suspend = usbh1_platform_rh_suspend_swfix; + usbh1_config.platform_rh_resume = usbh1_platform_rh_resume_swfix; + } else { usbh1_config.platform_rh_suspend = usbh1_platform_rh_suspend; usbh1_config.platform_rh_resume = usbh1_platform_rh_resume; - } else { - usbh1_config.platform_rh_suspend = NULL; - usbh1_config.platform_rh_resume = NULL; } if (cpu_is_mx6sl()) pdev = imx6sl_add_fsl_ehci_hs(1, &usbh1_config); @@ -371,21 +417,28 @@ void __init mx6_usb_h1_init(void) pdev_wakeup = imx6q_add_fsl_usb2_hs_wakeup(1, &usbh1_wakeup_config); ((struct fsl_usb2_platform_data *)(pdev->dev.platform_data))->wakeup_pdata = (struct fsl_usb2_wakeup_platform_data *)(pdev_wakeup->dev.platform_data); + return 0; +} +module_init(mx6_usb_h1_init); - /* Some phy and power's special controls for host1 - * 1. The external charger detector needs to be disabled - * or the signal at DP will be poor - * 2. The PLL's power and output to usb for host 1 - * is totally controlled by IC, so the Software only needs - * to enable them at initializtion. - */ - __raw_writel(BM_ANADIG_USB2_CHRG_DETECT_EN_B \ - | BM_ANADIG_USB2_CHRG_DETECT_CHK_CHRG_B, \ - anatop_base_addr + HW_ANADIG_USB2_CHRG_DETECT); +static void __exit mx6_usb_h1_exit(void) +{ + static void __iomem *anatop_base_addr = MX6_IO_ADDRESS(ANATOP_BASE_ADDR); + + platform_device_unregister(pdev); + platform_device_unregister(pdev_wakeup); __raw_writel(BM_ANADIG_USB2_PLL_480_CTRL_BYPASS, - anatop_base_addr + HW_ANADIG_USB2_PLL_480_CTRL_CLR); + anatop_base_addr + HW_ANADIG_USB2_PLL_480_CTRL_SET); __raw_writel(BM_ANADIG_USB2_PLL_480_CTRL_ENABLE \ | BM_ANADIG_USB2_PLL_480_CTRL_POWER \ | BM_ANADIG_USB2_PLL_480_CTRL_EN_USB_CLKS, \ - anatop_base_addr + HW_ANADIG_USB2_PLL_480_CTRL_SET); + anatop_base_addr + HW_ANADIG_USB2_PLL_480_CTRL_CLR); + if (mx6_set_usb_host1_vbus) + mx6_set_usb_host1_vbus(false); + + return ; } +module_exit(mx6_usb_h1_exit); + +MODULE_AUTHOR("Freescale Semiconductor"); +MODULE_LICENSE("GPL"); diff --git a/arch/arm/plat-mxc/cpufreq.c b/arch/arm/plat-mxc/cpufreq.c index b31970c667d2..765f05e23712 100755 --- a/arch/arm/plat-mxc/cpufreq.c +++ b/arch/arm/plat-mxc/cpufreq.c @@ -56,6 +56,7 @@ extern struct regulator *cpu_regulator; extern int dvfs_core_is_active; extern struct cpu_op *(*get_cpu_op)(int *op); extern int low_bus_freq_mode; +extern int audio_bus_freq_mode; extern int high_bus_freq_mode; extern int set_low_bus_freq(void); extern int set_high_bus_freq(int high_bus_speed); @@ -85,7 +86,7 @@ int set_cpu_freq(int freq) #endif /*Set the voltage for the GP domain. */ if (freq > org_cpu_rate) { - if (low_bus_freq_mode) + if (low_bus_freq_mode || audio_bus_freq_mode) set_high_bus_freq(0); ret = regulator_set_voltage(cpu_regulator, gp_volt, gp_volt); @@ -108,7 +109,8 @@ int set_cpu_freq(int freq) printk(KERN_DEBUG "COULD NOT SET GP VOLTAGE!!!!\n"); return ret; } - if (low_freq_bus_used() && !low_bus_freq_mode) + if (low_freq_bus_used() && + !(low_bus_freq_mode || audio_bus_freq_mode)) set_low_bus_freq(); } diff --git a/arch/arm/plat-mxc/devices/platform-fsl-usb2-wakeup.c b/arch/arm/plat-mxc/devices/platform-fsl-usb2-wakeup.c index 986b766fabde..3dacd287c6b8 100644 --- a/arch/arm/plat-mxc/devices/platform-fsl-usb2-wakeup.c +++ b/arch/arm/plat-mxc/devices/platform-fsl-usb2-wakeup.c @@ -52,3 +52,4 @@ struct platform_device *__init imx_add_fsl_usb2_wakeup( res, ARRAY_SIZE(res), pdata, sizeof(*pdata), DMA_BIT_MASK(32)); } +EXPORT_SYMBOL(imx_add_fsl_usb2_wakeup); diff --git a/arch/arm/plat-mxc/devices/platform-mxc-ehci.c b/arch/arm/plat-mxc/devices/platform-mxc-ehci.c index c39f6d7561c6..2b9cdff2ff97 100644 --- a/arch/arm/plat-mxc/devices/platform-mxc-ehci.c +++ b/arch/arm/plat-mxc/devices/platform-mxc-ehci.c @@ -83,6 +83,7 @@ struct platform_device *__init imx_add_mxc_ehci( res, ARRAY_SIZE(res), pdata, sizeof(*pdata), DMA_BIT_MASK(32)); } +EXPORT_SYMBOL(imx_add_mxc_ehci); /* FSL internal non-upstream code */ struct platform_device *__init imx_add_fsl_ehci( @@ -104,3 +105,4 @@ struct platform_device *__init imx_add_fsl_ehci( res, ARRAY_SIZE(res), pdata, sizeof(*pdata), DMA_BIT_MASK(32)); } +EXPORT_SYMBOL(imx_add_fsl_ehci); diff --git a/arch/arm/plat-mxc/include/mach/dma.h b/arch/arm/plat-mxc/include/mach/dma.h index ba00959c19fa..3fccb3be9e15 100644 --- a/arch/arm/plat-mxc/include/mach/dma.h +++ b/arch/arm/plat-mxc/include/mach/dma.h @@ -45,6 +45,7 @@ enum sdma_peripheral_type { IMX_DMATYPE_IPU_MEMORY, /* IPU Memory */ IMX_DMATYPE_ASRC, /* ASRC */ IMX_DMATYPE_ESAI, /* ESAI */ + IMX_DMATYPE_HDMI, }; enum imx_dma_prio { @@ -58,6 +59,7 @@ struct imx_dma_data { int dma_request_p2p; enum sdma_peripheral_type peripheral_type; int priority; + void *private; }; struct imx_pcm_dma_params { diff --git a/arch/arm/plat-mxc/include/mach/sdma.h b/arch/arm/plat-mxc/include/mach/sdma.h index a145c56b649d..cee7fe490188 100644 --- a/arch/arm/plat-mxc/include/mach/sdma.h +++ b/arch/arm/plat-mxc/include/mach/sdma.h @@ -45,6 +45,7 @@ struct sdma_script_start_addrs { s32 ram_code_start_addr; s32 mcu_2_ssish_addr; s32 ssish_2_mcu_addr; + s32 hdmi_dma_addr; }; /** diff --git a/arch/arm/plat-mxc/usb_common.c b/arch/arm/plat-mxc/usb_common.c index b18f5239c8b9..97d963a54a54 100755 --- a/arch/arm/plat-mxc/usb_common.c +++ b/arch/arm/plat-mxc/usb_common.c @@ -49,8 +49,12 @@ #include <mach/arc_otg.h> #include <mach/hardware.h> #include <mach/mxc.h> +typedef void (*driver_vbus_func)(bool); void __iomem *imx_otg_base; +static driver_vbus_func s_driver_vbus; + +EXPORT_SYMBOL(imx_otg_base); #define MXC_NUMBER_USB_TRANSCEIVER 6 struct fsl_xcvr_ops *g_xc_ops[MXC_NUMBER_USB_TRANSCEIVER] = { NULL }; @@ -59,10 +63,26 @@ bool usb_icbug_swfix_need(void) { if (cpu_is_mx6sl()) return false; - else - return true; + else if ((mx6q_revision() > IMX_CHIP_REVISION_1_1)) + return false; + else if ((mx6dl_revision() > IMX_CHIP_REVISION_1_0)) + return false; + return true; +} +EXPORT_SYMBOL(usb_icbug_swfix_need); + +void mx6_set_host1_vbus_func(driver_vbus_func driver_vbus) +{ + s_driver_vbus = driver_vbus; } +void mx6_set_usb_host1_vbus_func(driver_vbus_func *driver_vbus) +{ + *driver_vbus = s_driver_vbus; +} +EXPORT_SYMBOL(mx6_set_usb_host1_vbus_func); + + enum fsl_usb2_modes get_usb_mode(struct fsl_usb2_platform_data *pdata) { enum fsl_usb2_modes mode; diff --git a/arch/arm/plat-mxc/usb_wakeup.c b/arch/arm/plat-mxc/usb_wakeup.c index 4704eae91a51..e67c2219e52d 100755 --- a/arch/arm/plat-mxc/usb_wakeup.c +++ b/arch/arm/plat-mxc/usb_wakeup.c @@ -32,6 +32,7 @@ struct wakeup_ctrl { int wakeup_irq; int usb_irq; + bool thread_close; struct fsl_usb2_wakeup_platform_data *pdata; struct task_struct *thread; struct completion event; @@ -145,12 +146,18 @@ static int wakeup_event_thread(void *param) { struct wakeup_ctrl *ctrl = (struct wakeup_ctrl *)param; struct sched_param sch_param = {.sched_priority = 1}; + u32 timeout = 0; sched_setscheduler(current, SCHED_RR, &sch_param); while (1) { wait_for_completion_interruptible(&ctrl->event); - if (kthread_should_stop()) + if (ctrl->thread_close) { + while (!kthread_should_stop() && (timeout < 1000)) { + timeout++; + msleep(1); + } break; + } wakeup_event_handler(ctrl); enable_irq(ctrl->wakeup_irq); if ((ctrl->usb_irq > 0) && (ctrl->wakeup_irq != ctrl->usb_irq)) @@ -184,6 +191,7 @@ static int wakeup_dev_probe(struct platform_device *pdev) */ ctrl->wakeup_irq = platform_get_irq(pdev, 1); ctrl->usb_irq = platform_get_irq(pdev, 1); + ctrl->thread_close = false; if (ctrl->wakeup_irq != ctrl->usb_irq) interrupt_flag = IRQF_DISABLED; else @@ -210,6 +218,7 @@ error1: static int wakeup_dev_exit(struct platform_device *pdev) { if (g_ctrl->thread) { + g_ctrl->thread_close = true; complete(&g_ctrl->event); kthread_stop(g_ctrl->thread); } |