diff options
author | guoyin.chen <guoyin.chen@freescale.com> | 2013-07-15 15:01:21 +0800 |
---|---|---|
committer | guoyin.chen <guoyin.chen@freescale.com> | 2013-07-15 15:01:21 +0800 |
commit | 5793da66dd82a437c23d4a833674c0e09bd1aa07 (patch) | |
tree | 2f34bdc95dedb46d2a91d12837e58b1cf3a3e33f /arch | |
parent | f128c5660150679f00e518da8e3f582e9a2f03a8 (diff) | |
parent | 9e268cc3e4386f1a5a31a62f7207e5a9b8420124 (diff) |
Merge remote-tracking branch 'fsl-linux-sdk/imx_3.0.35_4.1.0' into imx_3.0.35_android
Conflicts:
arch/arm/mach-mx6/Kconfig
arch/arm/mach-mx6/board-mx6q_arm2.c
arch/arm/mach-mx6/board-mx6q_arm2.h
arch/arm/mach-mx6/board-mx6q_hdmidongle.c
arch/arm/mach-mx6/board-mx6q_sabreauto.c
arch/arm/mach-mx6/board-mx6q_sabreauto.h
arch/arm/mach-mx6/board-mx6q_sabrelite.c
arch/arm/mach-mx6/board-mx6q_sabresd.c
arch/arm/mach-mx6/board-mx6q_sabresd.h
arch/arm/mach-mx6/clock.c
arch/arm/mach-mx6/pcie.c
arch/arm/plat-mxc/include/mach/iomux-mx6q.h
arch/arm/plat-mxc/include/mach/pcie.h
drivers/dma/imx-sdma.c
drivers/input/touchscreen/egalax_ts.c
drivers/media/video/mxc/capture/csi_v4l2_capture.c
drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.c
drivers/mxc/mlb/mxc_mlb150.c
drivers/mxc/thermal/thermal.c
drivers/net/fec.c
drivers/usb/host/ehci-arc.c
drivers/video/mxc/mxc_ipuv3_fb.c
include/linux/fec.h
sound/soc/imx/imx-wm8962.c
Diffstat (limited to 'arch')
41 files changed, 1077 insertions, 342 deletions
diff --git a/arch/arm/configs/imx6s_defconfig b/arch/arm/configs/imx6s_defconfig index 7620cab69c61..1cae0463855e 100644 --- a/arch/arm/configs/imx6s_defconfig +++ b/arch/arm/configs/imx6s_defconfig @@ -1,3 +1,4 @@ + # # Automatically generated make config: don't edit # Linux/arm 3.0.35 Kernel Configuration @@ -316,6 +317,7 @@ CONFIG_MACH_MX6SL_EVK=y # CONFIG_MACH_MX6Q_SABRELITE is not set CONFIG_MACH_MX6Q_SABRESD=y # CONFIG_MACH_MX6Q_SABREAUTO is not set +CONFIG_SDMA_IRAM=y # # MX6 Options: @@ -1818,6 +1820,7 @@ CONFIG_SND_SOC=y CONFIG_SND_SOC_AC97_BUS=y CONFIG_SND_IMX_SOC=y CONFIG_SND_MXC_SOC_MX2=y +CONFIG_SND_MXC_SOC_IRAM=y CONFIG_SND_MXC_SOC_SPDIF_DAI=y CONFIG_SND_SOC_IMX_SGTL5000=y CONFIG_SND_SOC_IMX_WM8958=y diff --git a/arch/arm/mach-mx6/Kconfig b/arch/arm/mach-mx6/Kconfig index df954b40d8e8..005b56551ffb 100644 --- a/arch/arm/mach-mx6/Kconfig +++ b/arch/arm/mach-mx6/Kconfig @@ -288,6 +288,14 @@ config IMX_PCIE bool "PCI Express support" select PCI +config IMX_PCIE_EP_MODE_IN_EP_RC_SYS + bool "PCI Express EP mode in the IMX6 RC/EP interconnection system" + depends on IMX_PCIE + +config IMX_PCIE_RC_MODE_IN_EP_RC_SYS + bool "PCI Express RC mode in the IMX6 RC/EP interconnection system" + depends on IMX_PCIE + config USB_EHCI_ARC_H1 tristate "USB Host 1 support" depends on USB_EHCI_ARC @@ -295,6 +303,11 @@ config USB_EHCI_ARC_H1 config USB_FSL_ARC_OTG tristate "FSL USB OTG support" +config USB_ID_WAKEUP_ENABLE + bool "Enable USB ID Pin As System Wakeup Source" + depends on SOC_IMX6SL + default n + config MX6_INTER_LDO_BYPASS bool "Internal LDO in MX6Q/DL bypass" depends on REGULATOR_PFUZE100 && CPU_FREQ_IMX && ARCH_MX6 @@ -319,11 +332,10 @@ config MACH_IMX_BLUETOOTH_RFKILL ---help--- Say Y to get the standard rfkill interface of Bluetooth -config MX6_ENET_IRQ_TO_GPIO - bool "Route ENET interrupts to GPIO" - default n +config SDMA_IRAM + bool "Use Internal RAM for SDMA data structures" + depends on IMX_SDMA && SOC_IMX6SL help - Enabling this will direct all the ENET interrupts to a board specific GPIO. - This will allow the system to enter WAIT mode when ENET is active. + SDMA buffer or control structures are stored in the IRAM/OCRAM endif diff --git a/arch/arm/mach-mx6/board-mx6dl_arm2.h b/arch/arm/mach-mx6/board-mx6dl_arm2.h index 429febb9813d..f4560e4a0d74 100644 --- a/arch/arm/mach-mx6/board-mx6dl_arm2.h +++ b/arch/arm/mach-mx6/board-mx6dl_arm2.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright (C) 2012-2013 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 @@ -182,13 +182,7 @@ static iomux_v3_cfg_t mx6dl_arm2_pads[] = { /* USBOTG ID pin */ MX6DL_PAD_GPIO_1__USBOTG_ID, - - /* MLB150 */ - MX6DL_PAD_GPIO_3__MLB_MLBCLK, - MX6DL_PAD_GPIO_6__MLB_MLBSIG, - MX6DL_PAD_GPIO_2__MLB_MLBDAT, - -}; + }; static iomux_v3_cfg_t mx6dl_arm2_epdc_pads[] = { MX6DL_PAD_EIM_A17__GPIO_2_21, diff --git a/arch/arm/mach-mx6/board-mx6dl_sabresd.h b/arch/arm/mach-mx6/board-mx6dl_sabresd.h index fe278e82491f..7cb69246a824 100644 --- a/arch/arm/mach-mx6/board-mx6dl_sabresd.h +++ b/arch/arm/mach-mx6/board-mx6dl_sabresd.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright (C) 2012-2013 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 @@ -66,7 +66,6 @@ static iomux_v3_cfg_t mx6dl_sabresd_pads[] = { /* I2C3 */ MX6DL_PAD_GPIO_3__I2C3_SCL, - MX6DL_PAD_GPIO_6__I2C3_SDA, /* DISPLAY */ MX6DL_PAD_DI0_DISP_CLK__IPU1_DI0_DISP_CLK, @@ -167,7 +166,7 @@ static iomux_v3_cfg_t mx6dl_sabresd_pads[] = { MX6DL_PAD_SD4_DAT7__USDHC4_DAT7_50MHZ, /* HDMI_CEC_IN*/ - MX6DL_PAD_KEY_ROW2__GPIO_4_11, + MX6DL_PAD_KEY_ROW2__HDMI_TX_CEC_LINE, /* CCM - Audio, Camera clock */ MX6DL_PAD_GPIO_0__CCM_CLKO, diff --git a/arch/arm/mach-mx6/board-mx6q_arm2.c b/arch/arm/mach-mx6/board-mx6q_arm2.c index 8a2687d04f36..721db5490a6c 100644 --- a/arch/arm/mach-mx6/board-mx6q_arm2.c +++ b/arch/arm/mach-mx6/board-mx6q_arm2.c @@ -156,12 +156,10 @@ #define MX6_ARM2_CAN2_STBY MX6_ARM2_IO_EXP_GPIO2(1) -#ifdef CONFIG_MX6_ENET_IRQ_TO_GPIO #define MX6_ENET_IRQ IMX_GPIO_NR(1, 6) #define IOMUX_OBSRV_MUX1_OFFSET 0x3c #define OBSRV_MUX1_MASK 0x3f #define OBSRV_MUX1_ENET_IRQ 0x9 -#endif #define BMCR_PDOWN 0x0800 /* PHY Powerdown */ @@ -180,6 +178,7 @@ extern char *gp_reg_id; extern char *soc_reg_id; extern char *pu_reg_id; extern int epdc_enabled; +extern bool enet_to_gpio_6; static int max17135_regulator_init(struct max17135 *max17135); enum sd_pad_mode { @@ -394,9 +393,7 @@ static struct fec_platform_data fec_data __initdata = { .init = mx6_arm2_fec_phy_init, .power_hibernate = mx6_arm2_fec_power_hibernate, .phy = PHY_INTERFACE_MODE_RGMII, -#ifdef CONFIG_MX6_ENET_IRQ_TO_GPIO .gpio_irq = MX6_ENET_IRQ, -#endif }; static int mx6_arm2_spi_cs[] = { @@ -883,11 +880,7 @@ static struct i2c_board_info mxc_i2c0_board_info[] __initdata = { }, }; -static struct imxi2c_platform_data mx6_arm2_i2c0_data = { - .bitrate = 100000, -}; - -static struct imxi2c_platform_data mx6_arm2_i2c1_data = { +static struct imxi2c_platform_data mx6_arm2_i2c_data = { .bitrate = 100000, }; @@ -2087,6 +2080,18 @@ static void __init mx6_arm2_init(void) spdif_pads_cnt = ARRAY_SIZE(mx6q_arm2_spdif_pads); flexcan_pads_cnt = ARRAY_SIZE(mx6q_arm2_can_pads); i2c3_pads_cnt = ARRAY_SIZE(mx6q_arm2_i2c3_pads); + if (enet_to_gpio_6) { + iomux_v3_cfg_t enet_gpio_pad = + MX6Q_PAD_GPIO_6__ENET_IRQ_TO_GPIO_6; + mxc_iomux_v3_setup_pad(enet_gpio_pad); + } else { + iomux_v3_cfg_t mlb_pads[] = { + MX6Q_PAD_GPIO_3__MLB_MLBCLK, + MX6Q_PAD_GPIO_6__MLB_MLBSIG, + MX6Q_PAD_GPIO_2__MLB_MLBDAT}; + mxc_iomux_v3_setup_multiple_pads(mlb_pads, + ARRAY_SIZE(mlb_pads)); + } } else if (cpu_is_mx6dl()) { common_pads = mx6dl_arm2_pads; esai_rec_pads = mx6dl_arm2_esai_record_pads; @@ -2101,6 +2106,18 @@ static void __init mx6_arm2_init(void) flexcan_pads_cnt = ARRAY_SIZE(mx6dl_arm2_can_pads); i2c3_pads_cnt = ARRAY_SIZE(mx6dl_arm2_i2c3_pads); epdc_pads_cnt = ARRAY_SIZE(mx6dl_arm2_epdc_pads); + if (enet_to_gpio_6) { + iomux_v3_cfg_t enet_gpio_pad = + MX6DL_PAD_GPIO_6__ENET_IRQ_TO_GPIO_6; + mxc_iomux_v3_setup_pad(enet_gpio_pad); + } else { + iomux_v3_cfg_t mlb_pads[] = { + MX6DL_PAD_GPIO_3__MLB_MLBCLK, + MX6DL_PAD_GPIO_6__MLB_MLBSIG, + MX6DL_PAD_GPIO_2__MLB_MLBDAT}; + mxc_iomux_v3_setup_multiple_pads(mlb_pads, + ARRAY_SIZE(mlb_pads)); + } } BUG_ON(!common_pads); @@ -2187,8 +2204,8 @@ static void __init mx6_arm2_init(void) imx6q_add_imx_caam(); - imx6q_add_imx_i2c(0, &mx6_arm2_i2c0_data); - imx6q_add_imx_i2c(1, &mx6_arm2_i2c1_data); + imx6q_add_imx_i2c(0, &mx6_arm2_i2c_data); + imx6q_add_imx_i2c(1, &mx6_arm2_i2c_data); i2c_register_board_info(0, mxc_i2c0_board_info, ARRAY_SIZE(mxc_i2c0_board_info)); i2c_register_board_info(1, mxc_i2c1_board_info, @@ -2200,6 +2217,8 @@ static void __init mx6_arm2_init(void) i2c_register_board_info(2, mxc_i2c2_board_info, ARRAY_SIZE(mxc_i2c2_board_info)); } + if (cpu_is_mx6dl()) + imx6q_add_imx_i2c(3, &mx6_arm2_i2c_data); /* SPI */ imx6q_add_ecspi(0, &mx6_arm2_spi_data); @@ -2210,12 +2229,15 @@ static void __init mx6_arm2_init(void) imx6q_add_anatop_thermal_imx(1, &mx6_arm2_anatop_thermal_data); if (!esai_record) { + if (enet_to_gpio_6) + /* Make sure the IOMUX_OBSRV_MUX1 is set to ENET_IRQ. */ + mxc_iomux_set_specialbits_register( + IOMUX_OBSRV_MUX1_OFFSET, + OBSRV_MUX1_ENET_IRQ, + OBSRV_MUX1_MASK); + else + fec_data.gpio_irq = -1; imx6_init_fec(fec_data); -#ifdef CONFIG_MX6_ENET_IRQ_TO_GPIO - /* Make sure the IOMUX_OBSRV_MUX1 is set to ENET_IRQ. */ - mxc_iomux_set_specialbits_register(IOMUX_OBSRV_MUX1_OFFSET, - OBSRV_MUX1_ENET_IRQ, OBSRV_MUX1_MASK); -#endif } imx6q_add_pm_imx(0, &mx6_arm2_pm_data); diff --git a/arch/arm/mach-mx6/board-mx6q_arm2.h b/arch/arm/mach-mx6/board-mx6q_arm2.h index 2a6a2052b3f9..24a894fab905 100644 --- a/arch/arm/mach-mx6/board-mx6q_arm2.h +++ b/arch/arm/mach-mx6/board-mx6q_arm2.h @@ -182,16 +182,7 @@ static iomux_v3_cfg_t mx6q_arm2_pads[] = { /* USBOTG ID pin */ MX6Q_PAD_GPIO_1__USBOTG_ID, - -#ifdef CONFIG_MX6_ENET_IRQ_TO_GPIO - MX6Q_PAD_GPIO_6__OBSERVE_MUX_OBSRV_INT_OUT1, -#else - /* MLB150 */ - MX6Q_PAD_GPIO_3__MLB_MLBCLK, - MX6Q_PAD_GPIO_6__MLB_MLBSIG, - MX6Q_PAD_GPIO_2__MLB_MLBDAT, -#endif -}; + }; static iomux_v3_cfg_t mx6q_arm2_i2c3_pads[] = { MX6Q_PAD_GPIO_5__I2C3_SCL, diff --git a/arch/arm/mach-mx6/board-mx6q_sabreauto.c b/arch/arm/mach-mx6/board-mx6q_sabreauto.c index 3f7824fbaf62..e5378ba92cf6 100644 --- a/arch/arm/mach-mx6/board-mx6q_sabreauto.c +++ b/arch/arm/mach-mx6/board-mx6q_sabreauto.c @@ -115,12 +115,10 @@ #define SABREAUTO_MAX7310_2_BASE_ADDR IMX_GPIO_NR(8, 8) #define SABREAUTO_MAX7310_3_BASE_ADDR IMX_GPIO_NR(8, 16) -#ifdef CONFIG_MX6_ENET_IRQ_TO_GPIO #define MX6_ENET_IRQ IMX_GPIO_NR(1, 6) #define IOMUX_OBSRV_MUX1_OFFSET 0x3c #define OBSRV_MUX1_MASK 0x3f #define OBSRV_MUX1_ENET_IRQ 0x9 -#endif #define SABREAUTO_IO_EXP_GPIO1(x) (SABREAUTO_MAX7310_1_BASE_ADDR + (x)) #define SABREAUTO_IO_EXP_GPIO2(x) (SABREAUTO_MAX7310_2_BASE_ADDR + (x)) @@ -143,6 +141,7 @@ extern char *gp_reg_id; extern char *soc_reg_id; extern char *pu_reg_id; +extern bool enet_to_gpio_6; static int mma8x5x_position = 7; static int mag3110_position = 7; @@ -417,9 +416,7 @@ static struct fec_platform_data fec_data __initdata = { .init = mx6q_sabreauto_fec_phy_init, .power_hibernate = mx6q_sabreauto_fec_power_hibernate, .phy = PHY_INTERFACE_MODE_RGMII, -#ifdef CONFIG_MX6_ENET_IRQ_TO_GPIO - .gpio_irq = MX6_ENET_IRQ, -#endif + .gpio_irq = MX6_ENET_IRQ, }; static int mx6q_sabreauto_spi_cs[] = { @@ -753,7 +750,7 @@ static struct imxi2c_platform_data mx6q_sabreauto_i2c2_data = { .bitrate = 400000, }; -static struct imxi2c_platform_data mx6q_sabreauto_i2c1_data = { +static struct imxi2c_platform_data mx6q_sabreauto_i2c_data = { .bitrate = 100000, }; @@ -1570,6 +1567,18 @@ static void __init mx6_board_init(void) mxc_iomux_v3_setup_multiple_pads(extra_pads, extra_pads_cnt); } + if (enet_to_gpio_6) { + iomux_v3_cfg_t enet_gpio_pad = + MX6Q_PAD_GPIO_6__ENET_IRQ_TO_GPIO_6; + mxc_iomux_v3_setup_pad(enet_gpio_pad); + } else { + iomux_v3_cfg_t mlb_pads[] = { + MX6Q_PAD_ENET_TXD1__MLB_MLBCLK, + MX6Q_PAD_GPIO_6__MLB_MLBSIG, + MX6Q_PAD_GPIO_2__MLB_MLBDAT}; + mxc_iomux_v3_setup_multiple_pads(mlb_pads, + ARRAY_SIZE(mlb_pads)); + } } else if (cpu_is_mx6dl()) { common_pads = mx6dl_sabreauto_pads; can0_pads = mx6dl_sabreauto_can0_pads; @@ -1602,6 +1611,18 @@ static void __init mx6_board_init(void) mxc_iomux_v3_setup_multiple_pads(extra_pads, extra_pads_cnt); } + if (enet_to_gpio_6) { + iomux_v3_cfg_t enet_gpio_pad = + MX6DL_PAD_GPIO_6__ENET_IRQ_TO_GPIO_6; + mxc_iomux_v3_setup_pad(enet_gpio_pad); + } else { + iomux_v3_cfg_t mlb_pads[] = { + MX6DL_PAD_ENET_TXD1__MLB_MLBCLK, + MX6DL_PAD_GPIO_6__MLB_MLBSIG, + MX6DL_PAD_GPIO_2__MLB_MLBDAT}; + mxc_iomux_v3_setup_multiple_pads(mlb_pads, + ARRAY_SIZE(mlb_pads)); + } } BUG_ON(!common_pads); @@ -1715,12 +1736,15 @@ static void __init mx6_board_init(void) if (1 == caam_enabled) imx6q_add_imx_caam(); - imx6q_add_imx_i2c(1, &mx6q_sabreauto_i2c1_data); + imx6q_add_imx_i2c(1, &mx6q_sabreauto_i2c_data); i2c_register_board_info(1, mxc_i2c1_board_info, ARRAY_SIZE(mxc_i2c1_board_info)); imx6q_add_imx_i2c(2, &mx6q_sabreauto_i2c2_data); i2c_register_board_info(2, mxc_i2c2_board_info, ARRAY_SIZE(mxc_i2c2_board_info)); + if (cpu_is_mx6dl()) + imx6q_add_imx_i2c(3, &mx6q_sabreauto_i2c_data); + ret = gpio_request(SABREAUTO_PMIC_INT, "pFUZE-int"); if (ret) { @@ -1743,13 +1767,15 @@ static void __init mx6_board_init(void) imx6q_add_anatop_thermal_imx(1, &mx6q_sabreauto_anatop_thermal_data); if (!can0_enable) { + if (enet_to_gpio_6) + /* Make sure the IOMUX_OBSRV_MUX1 is set to ENET_IRQ. */ + mxc_iomux_set_specialbits_register( + IOMUX_OBSRV_MUX1_OFFSET, + OBSRV_MUX1_ENET_IRQ, + OBSRV_MUX1_MASK); + else + fec_data.gpio_irq = -1; imx6_init_fec(fec_data); -#ifdef CONFIG_MX6_ENET_IRQ_TO_GPIO - /* Make sure the IOMUX_OBSRV_MUX1 is set to ENET_IRQ. */ - mxc_iomux_set_specialbits_register(IOMUX_OBSRV_MUX1_OFFSET, - OBSRV_MUX1_ENET_IRQ, OBSRV_MUX1_MASK); -#endif - } imx6q_add_pm_imx(0, &mx6q_sabreauto_pm_data); diff --git a/arch/arm/mach-mx6/board-mx6q_sabreauto.h b/arch/arm/mach-mx6/board-mx6q_sabreauto.h index e4d62f1baaa5..436a11d03a31 100644 --- a/arch/arm/mach-mx6/board-mx6q_sabreauto.h +++ b/arch/arm/mach-mx6/board-mx6q_sabreauto.h @@ -207,16 +207,7 @@ static iomux_v3_cfg_t mx6q_sabreauto_pads[] = { /* HDMI */ MX6Q_PAD_EIM_A25__HDMI_TX_CEC_LINE, - -#ifdef CONFIG_MX6_ENET_IRQ_TO_GPIO - MX6Q_PAD_GPIO_6__OBSERVE_MUX_OBSRV_INT_OUT1, -#else - /* MLB150 */ - MX6Q_PAD_ENET_TXD1__MLB_MLBCLK, - MX6Q_PAD_GPIO_6__MLB_MLBSIG, - MX6Q_PAD_GPIO_2__MLB_MLBDAT, -#endif -}; + }; static iomux_v3_cfg_t mx6q_sabreauto_can0_pads[] = { /* CAN1 */ diff --git a/arch/arm/mach-mx6/board-mx6q_sabrelite.c b/arch/arm/mach-mx6/board-mx6q_sabrelite.c index ec77b8646266..636bfa9a65ff 100644 --- a/arch/arm/mach-mx6/board-mx6q_sabrelite.c +++ b/arch/arm/mach-mx6/board-mx6q_sabrelite.c @@ -94,12 +94,10 @@ #define MX6Q_SABRELITE_CSI0_RST IMX_GPIO_NR(1, 8) #define MX6Q_SABRELITE_CSI0_PWN IMX_GPIO_NR(1, 6) -#ifdef CONFIG_MX6_ENET_IRQ_TO_GPIO #define MX6_ENET_IRQ IMX_GPIO_NR(1, 6) #define IOMUX_OBSRV_MUX1_OFFSET 0x3c #define OBSRV_MUX1_MASK 0x3f #define OBSRV_MUX1_ENET_IRQ 0x9 -#endif #define MX6Q_SABRELITE_SD3_WP_PADCFG (PAD_CTL_PKE | PAD_CTL_PUE | \ PAD_CTL_PUS_22K_UP | PAD_CTL_SPEED_MED | \ @@ -111,6 +109,7 @@ static struct clk *sata_clk; extern char *gp_reg_id; extern char *soc_reg_id; extern char *pu_reg_id; +extern bool enet_to_gpio_6; static int caam_enabled; extern struct regulator *(*get_cpu_regulator)(void); @@ -217,8 +216,8 @@ static iomux_v3_cfg_t mx6q_sabrelite_pads[] = { MX6Q_PAD_EIM_D28__I2C1_SDA, /* GPIO3[28] */ /* I2C2 Camera, MIPI */ - MX6Q_PAD_KEY_COL3__I2C2_SCL, /* GPIO4[12] */ - MX6Q_PAD_KEY_ROW3__I2C2_SDA, /* GPIO4[13] */ + MX6Q_PAD_KEY_COL3__I2C2_SCL, /* GPIO4[12] */ + MX6Q_PAD_KEY_ROW3__I2C2_SDA, /* GPIO4[13] */ /* I2C3 */ MX6Q_PAD_GPIO_5__I2C3_SCL, /* GPIO1[5] - J7 - Display card */ @@ -329,9 +328,6 @@ static iomux_v3_cfg_t mx6q_sabrelite_csi0_sensor_pads[] = { MX6Q_PAD_CSI0_MCLK__IPU1_CSI0_HSYNC, MX6Q_PAD_CSI0_PIXCLK__IPU1_CSI0_PIXCLK, MX6Q_PAD_CSI0_VSYNC__IPU1_CSI0_VSYNC, -#ifndef CONFIG_MX6_ENET_IRQ_TO_GPIO - MX6Q_PAD_GPIO_6__GPIO_1_6, /* J5 - Camera GP */ -#endif MX6Q_PAD_GPIO_8__GPIO_1_8, /* J5 - Camera Reset */ MX6Q_PAD_SD1_DAT0__GPIO_1_16, /* J5 - Camera GP */ MX6Q_PAD_NANDF_D5__GPIO_2_5, /* J16 - MIPI GP */ @@ -477,9 +473,7 @@ static int mx6q_sabrelite_fec_phy_init(struct phy_device *phydev) static struct fec_platform_data fec_data __initdata = { .init = mx6q_sabrelite_fec_phy_init, .phy = PHY_INTERFACE_MODE_RGMII, -#ifdef CONFIG_MX6_ENET_IRQ_TO_GPIO .gpio_irq = MX6_ENET_IRQ, -#endif }; static int mx6q_sabrelite_spi_cs[] = { @@ -931,6 +925,16 @@ static struct fsl_mxc_capture_platform_data capture_data[] = { }; +struct imx_vout_mem { + resource_size_t res_mbase; + resource_size_t res_msize; +}; + +static struct imx_vout_mem vout_mem __initdata = { + .res_msize = SZ_128M, +}; + + static void sabrelite_suspend_enter(void) { /* suspend preparation */ @@ -1216,10 +1220,22 @@ static void __init mx6_sabrelite_board_init(void) struct clk *clko2; struct clk *new_parent; int rate; + struct platform_device *voutdev; mxc_iomux_v3_setup_multiple_pads(mx6q_sabrelite_pads, ARRAY_SIZE(mx6q_sabrelite_pads)); + if (enet_to_gpio_6) { + iomux_v3_cfg_t enet_gpio_pad = + MX6Q_PAD_GPIO_6__ENET_IRQ_TO_GPIO_6; + mxc_iomux_v3_setup_pad(enet_gpio_pad); + } else { + /* J5 - Camera GP */ + iomux_v3_cfg_t camera_gpio_pad = + MX6Q_PAD_GPIO_6__GPIO_1_6; + mxc_iomux_v3_setup_pad(camera_gpio_pad); + } + #ifdef CONFIG_FEC_1588 /* Set GPIO_16 input for IEEE-1588 ts_clk and RMII reference clock * For MX6 GPR1 bit21 meaning: @@ -1244,7 +1260,17 @@ static void __init mx6_sabrelite_board_init(void) imx6q_add_vdoa(); imx6q_add_lcdif(&lcdif_data); imx6q_add_ldb(&ldb_data); - imx6q_add_v4l2_output(0); + voutdev = imx6q_add_v4l2_output(0); + if (vout_mem.res_msize && voutdev) { + dma_declare_coherent_memory(&voutdev->dev, + vout_mem.res_mbase, + vout_mem.res_mbase, + vout_mem.res_msize, + (DMA_MEMORY_MAP | + DMA_MEMORY_EXCLUSIVE)); + } + + imx6q_add_v4l2_capture(0, &capture_data[0]); imx6q_add_v4l2_capture(1, &capture_data[1]); imx6q_add_mipi_csi2(&mipi_csi2_pdata); @@ -1270,6 +1296,15 @@ static void __init mx6_sabrelite_board_init(void) imx6q_add_mxc_hdmi(&hdmi_data); imx6q_add_anatop_thermal_imx(1, &mx6q_sabrelite_anatop_thermal_data); + if (enet_to_gpio_6) + /* Make sure the IOMUX_OBSRV_MUX1 is set to ENET_IRQ. */ + mxc_iomux_set_specialbits_register( + IOMUX_OBSRV_MUX1_OFFSET, + OBSRV_MUX1_ENET_IRQ, + OBSRV_MUX1_MASK); + else + fec_data.gpio_irq = -1; + imx6_init_fec(fec_data); #ifdef CONFIG_MX6_ENET_IRQ_TO_GPIO /* Make sure the IOMUX_OBSRV_MUX1 is set to ENET_IRQ. */ @@ -1403,6 +1438,13 @@ static void __init mx6q_sabrelite_reserve(void) memblock_remove(phys, sabrelite_fb_data[i].res_size[0]); sabrelite_fb_data[i].res_base[0] = phys; } + if (vout_mem.res_msize) { + phys = memblock_alloc_base(vout_mem.res_msize, + SZ_4K, SZ_1G); + memblock_remove(phys, vout_mem.res_msize); + vout_mem.res_mbase = phys; + } + } /* diff --git a/arch/arm/mach-mx6/board-mx6q_sabresd.c b/arch/arm/mach-mx6/board-mx6q_sabresd.c index 8921a995c270..193931e446f3 100644 --- a/arch/arm/mach-mx6/board-mx6q_sabresd.c +++ b/arch/arm/mach-mx6/board-mx6q_sabresd.c @@ -201,12 +201,10 @@ #define SABRESD_ELAN_RST IMX_GPIO_NR(3, 8) #define SABRESD_ELAN_INT IMX_GPIO_NR(3, 28) -#ifdef CONFIG_MX6_ENET_IRQ_TO_GPIO #define MX6_ENET_IRQ IMX_GPIO_NR(1, 6) #define IOMUX_OBSRV_MUX1_OFFSET 0x3c #define OBSRV_MUX1_MASK 0x3f #define OBSRV_MUX1_ENET_IRQ 0x9 -#endif static struct clk *sata_clk; static struct clk *clko; @@ -220,6 +218,7 @@ extern char *gp_reg_id; extern char *soc_reg_id; extern char *pu_reg_id; extern int epdc_enabled; +extern bool enet_to_gpio_6; static int max17135_regulator_init(struct max17135 *max17135); @@ -310,9 +309,7 @@ static int mx6q_sabresd_fec_phy_init(struct phy_device *phydev) static struct fec_platform_data fec_data __initdata = { .init = mx6q_sabresd_fec_phy_init, .phy = PHY_INTERFACE_MODE_RGMII, -#ifdef CONFIG_MX6_ENET_IRQ_TO_GPIO .gpio_irq = MX6_ENET_IRQ, -#endif }; static int mx6q_sabresd_spi_cs[] = { @@ -1368,6 +1365,8 @@ static struct fsl_mxc_hdmi_platform_data hdmi_data = { .init = hdmi_init, .enable_pins = hdmi_enable_ddc_pin, .disable_pins = hdmi_disable_ddc_pin, + .phy_reg_vlev = 0x0294, + .phy_reg_cksymtx = 0x800d, }; static struct fsl_mxc_hdmi_core_platform_data hdmi_core_data = { @@ -1474,6 +1473,16 @@ static struct platform_device mxc_bt_rfkill = { static struct imx_bt_rfkill_platform_data mxc_bt_rfkill_data = { .power_change = mx6q_sd_bt_power_change, }; + +struct imx_vout_mem { + resource_size_t res_mbase; + resource_size_t res_msize; +}; + +static struct imx_vout_mem vout_mem __initdata = { + .res_msize = 0, +}; + static void sabresd_suspend_enter(void) { /* suspend preparation */ @@ -1794,6 +1803,11 @@ static const struct imx_pcie_platform_data mx6_sabresd_pcie_data __initconst = { .pcie_rst = SABRESD_PCIE_RST_B_REVB, .pcie_wake_up = SABRESD_PCIE_WAKE_B, .pcie_dis = SABRESD_PCIE_DIS_B, +#ifdef CONFIG_IMX_PCIE_EP_MODE_IN_EP_RC_SYS + .type_ep = 1, +#else + .type_ep = 0, +#endif .pcie_power_always_on = 1, }; @@ -1863,15 +1877,36 @@ static void __init mx6_sabresd_board_init(void) struct clk *clko, *clko2; struct clk *new_parent; int rate; + struct platform_device *voutdev; - if (cpu_is_mx6q()) + if (cpu_is_mx6q()) { mxc_iomux_v3_setup_multiple_pads(mx6q_sabresd_pads, ARRAY_SIZE(mx6q_sabresd_pads)); - else if (cpu_is_mx6dl()) { + if (enet_to_gpio_6) { + iomux_v3_cfg_t enet_gpio_pad = + MX6Q_PAD_GPIO_6__ENET_IRQ_TO_GPIO_6; + mxc_iomux_v3_setup_pad(enet_gpio_pad); + } else { + iomux_v3_cfg_t i2c3_pad = + MX6Q_PAD_GPIO_6__I2C3_SDA; + mxc_iomux_v3_setup_pad(i2c3_pad); + } + } else if (cpu_is_mx6dl()) { mxc_iomux_v3_setup_multiple_pads(mx6dl_sabresd_pads, ARRAY_SIZE(mx6dl_sabresd_pads)); + + if (enet_to_gpio_6) { + iomux_v3_cfg_t enet_gpio_pad = + MX6DL_PAD_GPIO_6__ENET_IRQ_TO_GPIO_6; + mxc_iomux_v3_setup_pad(enet_gpio_pad); + } else { + iomux_v3_cfg_t i2c3_pad = + MX6DL_PAD_GPIO_6__I2C3_SDA; + mxc_iomux_v3_setup_pad(i2c3_pad); + } } + #ifdef CONFIG_FEC_1588 /* Set GPIO_16 input for IEEE-1588 ts_clk and RMII reference clock * For MX6 GPR1 bit21 meaning: @@ -1922,7 +1957,16 @@ static void __init mx6_sabresd_board_init(void) imx6q_add_mipi_dsi(&mipi_dsi_pdata); imx6q_add_lcdif(&lcdif_data); imx6q_add_ldb(&ldb_data); - imx6q_add_v4l2_output(0); + voutdev = imx6q_add_v4l2_output(0); + if (vout_mem.res_msize && voutdev) { + dma_declare_coherent_memory(&voutdev->dev, + vout_mem.res_mbase, + vout_mem.res_mbase, + vout_mem.res_msize, + (DMA_MEMORY_MAP | + DMA_MEMORY_EXCLUSIVE)); + } + imx6q_add_v4l2_capture(0, &capture_data[0]); imx6q_add_v4l2_capture(1, &capture_data[1]); imx6q_add_mipi_csi2(&mipi_csi2_pdata); @@ -1943,6 +1987,8 @@ static void __init mx6_sabresd_board_init(void) imx6q_add_imx_i2c(0, &mx6q_sabresd_i2c_data); imx6q_add_imx_i2c(1, &mx6q_sabresd_i2c_data); imx6q_add_imx_i2c(2, &mx6q_sabresd_i2c_data); + if (cpu_is_mx6dl()) + imx6q_add_imx_i2c(3, &mx6q_sabresd_i2c_data); i2c_register_board_info(0, mxc_i2c0_board_info, ARRAY_SIZE(mxc_i2c0_board_info)); i2c_register_board_info(1, mxc_i2c1_board_info, @@ -1964,12 +2010,16 @@ static void __init mx6_sabresd_board_init(void) imx6q_add_mxc_hdmi(&hdmi_data); imx6q_add_anatop_thermal_imx(1, &mx6q_sabresd_anatop_thermal_data); + + if (enet_to_gpio_6) + /* Make sure the IOMUX_OBSRV_MUX1 is set to ENET_IRQ. */ + mxc_iomux_set_specialbits_register( + IOMUX_OBSRV_MUX1_OFFSET, + OBSRV_MUX1_ENET_IRQ, + OBSRV_MUX1_MASK); + else + fec_data.gpio_irq = -1; imx6_init_fec(fec_data); -#ifdef CONFIG_MX6_ENET_IRQ_TO_GPIO - /* Make sure the IOMUX_OBSRV_MUX1 is set to ENET_IRQ. */ - mxc_iomux_set_specialbits_register(IOMUX_OBSRV_MUX1_OFFSET, - OBSRV_MUX1_ENET_IRQ, OBSRV_MUX1_MASK); -#endif imx6q_add_pm_imx(0, &mx6q_sabresd_pm_data); @@ -2192,6 +2242,13 @@ static void __init mx6q_sabresd_reserve(void) imx_ion_data.heaps[0].base = phys; } #endif + + if (vout_mem.res_msize) { + phys = memblock_alloc_base(vout_mem.res_msize, + SZ_4K, SZ_1G); + memblock_remove(phys, vout_mem.res_msize); + vout_mem.res_mbase = phys; + } } /* diff --git a/arch/arm/mach-mx6/board-mx6q_sabresd.h b/arch/arm/mach-mx6/board-mx6q_sabresd.h index b2bb8c923f0f..73ee909e50ef 100644 --- a/arch/arm/mach-mx6/board-mx6q_sabresd.h +++ b/arch/arm/mach-mx6/board-mx6q_sabresd.h @@ -132,13 +132,9 @@ static iomux_v3_cfg_t mx6q_sabresd_pads[] = { MX6Q_PAD_KEY_COL3__I2C2_SCL, MX6Q_PAD_KEY_ROW3__I2C2_SDA, -#ifdef CONFIG_MX6_ENET_IRQ_TO_GPIO - MX6Q_PAD_GPIO_6__OBSERVE_MUX_OBSRV_INT_OUT1, -#else /* I2C3 */ MX6Q_PAD_GPIO_3__I2C3_SCL, /* GPIO1[3] */ MX6Q_PAD_GPIO_6__I2C3_SDA, -#endif /* DISPLAY */ MX6Q_PAD_DI0_DISP_CLK__IPU1_DI0_DISP_CLK, diff --git a/arch/arm/mach-mx6/board-mx6sl_arm2.c b/arch/arm/mach-mx6/board-mx6sl_arm2.c index cd21b37a6885..a29f3bcb9b07 100755 --- a/arch/arm/mach-mx6/board-mx6sl_arm2.c +++ b/arch/arm/mach-mx6/board-mx6sl_arm2.c @@ -484,8 +484,8 @@ static int mxc_wm8962_init(void) clk_set_parent(extern_audio_root, pll4); - rate = clk_round_rate(extern_audio_root, 26000000); - clk_set_rate(extern_audio_root, rate); + rate = 24000000; + clk_set_rate(extern_audio_root, 24000000); wm8962_data.sysclk = rate; @@ -1092,7 +1092,7 @@ static struct platform_pwm_backlight_data mx6_arm2_pwm_backlight_data = { static struct fb_videomode video_modes[] = { { /* 800x480 @ 57 Hz , pixel clk @ 32MHz */ - "SEIKO-WVGA", 60, 800, 480, 29850, 99, 164, 33, 10, 10, 10, + "SEIKO-WVGA", 60, 800, 480, 29850, 89, 164, 23, 10, 10, 10, FB_SYNC_CLK_LAT_FALL, FB_VMODE_NONINTERLACED, 0,}, diff --git a/arch/arm/mach-mx6/board-mx6sl_common.h b/arch/arm/mach-mx6/board-mx6sl_common.h index 2b2dd6b93c9a..897099f2c1ea 100644 --- a/arch/arm/mach-mx6/board-mx6sl_common.h +++ b/arch/arm/mach-mx6/board-mx6sl_common.h @@ -481,7 +481,9 @@ static iomux_v3_cfg_t suspend_enter_pads[] = { MX6SL_PAD_SD3_DAT3__GPIO_5_17, /* USBOTG ID pin */ +#ifndef CONFIG_USB_ID_WAKEUP_ENABLE MX6SL_PAD_EPDC_PWRCOM__GPIO_2_11, +#endif MX6SL_PAD_HSIC_STROBE__GPIO_3_20, MX6SL_PAD_HSIC_DAT__GPIO_3_19, diff --git a/arch/arm/mach-mx6/board-mx6sl_evk.c b/arch/arm/mach-mx6/board-mx6sl_evk.c index 729054c9f015..082845ba22a3 100644 --- a/arch/arm/mach-mx6/board-mx6sl_evk.c +++ b/arch/arm/mach-mx6/board-mx6sl_evk.c @@ -547,8 +547,8 @@ static int mxc_wm8962_init(void) clk_set_parent(extern_audio_root, pll4); - rate = clk_round_rate(extern_audio_root, 26000000); - clk_set_rate(extern_audio_root, rate); + rate = 24000000; + clk_set_rate(extern_audio_root, 24000000); wm8962_data.sysclk = rate; /* set AUDMUX pads to 1.8v */ @@ -1255,6 +1255,14 @@ static void imx6_evk_usbotg_vbus(bool on) gpio_set_value(MX6_BRD_USBOTG1_PWR, 0); } +static void imx6_evk_usbh1_vbus(bool on) +{ + if (on) + gpio_set_value(MX6_BRD_USBOTG2_PWR, 1); + else + gpio_set_value(MX6_BRD_USBOTG2_PWR, 0); +} + static void __init mx6_evk_init_usb(void) { int ret = 0; @@ -1277,9 +1285,10 @@ static void __init mx6_evk_init_usb(void) pr_err("failed to get GPIO MX6_BRD_USBOTG2_PWR:%d\n", ret); return; } - gpio_direction_output(MX6_BRD_USBOTG2_PWR, 1); + gpio_direction_output(MX6_BRD_USBOTG2_PWR, 0); mx6_set_otghost_vbus_func(imx6_evk_usbotg_vbus); + mx6_set_host1_vbus_func(imx6_evk_usbh1_vbus); #ifdef CONFIG_USB_EHCI_ARC_HSIC mx6_usb_h2_init(); @@ -1295,7 +1304,7 @@ static struct platform_pwm_backlight_data mx6_evk_pwm_backlight_data = { static struct fb_videomode wvga_video_modes[] = { { /* 800x480 @ 57 Hz , pixel clk @ 32MHz */ - "SEIKO-WVGA", 60, 800, 480, 29850, 99, 164, 33, 10, 10, 10, + "SEIKO-WVGA", 60, 800, 480, 29850, 89, 164, 23, 10, 10, 10, FB_SYNC_CLK_LAT_FALL, FB_VMODE_NONINTERLACED, 0,}, diff --git a/arch/arm/mach-mx6/board-mx6solo_sabreauto.h b/arch/arm/mach-mx6/board-mx6solo_sabreauto.h index 9d65724cd910..da36cb7187b2 100644 --- a/arch/arm/mach-mx6/board-mx6solo_sabreauto.h +++ b/arch/arm/mach-mx6/board-mx6solo_sabreauto.h @@ -207,12 +207,7 @@ static iomux_v3_cfg_t mx6dl_sabreauto_pads[] = { /* HDMI */ MX6DL_PAD_EIM_A25__HDMI_TX_CEC_LINE, - - /* MLB150 */ - MX6DL_PAD_ENET_TXD1__MLB_MLBCLK, - MX6DL_PAD_GPIO_6__MLB_MLBSIG, - MX6DL_PAD_GPIO_2__MLB_MLBDAT, -}; + }; static iomux_v3_cfg_t mx6dl_sabreauto_can0_pads[] = { /* CAN1 */ diff --git a/arch/arm/mach-mx6/bus_freq.c b/arch/arm/mach-mx6/bus_freq.c index 1f429f9e0656..ba2636785232 100644 --- a/arch/arm/mach-mx6/bus_freq.c +++ b/arch/arm/mach-mx6/bus_freq.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011-2012 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright (C) 2011-2013 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 @@ -47,7 +47,7 @@ #include <linux/suspend.h> #define LPAPM_CLK 24000000 -#define DDR_AUDIO_CLK 50000000 +#define DDR_AUDIO_CLK 100000000 #define DDR_MED_CLK 400000000 #define DDR3_NORMAL_CLK 528000000 #define GPC_PGC_GPU_PGCR_OFFSET 0x260 @@ -78,7 +78,8 @@ unsigned int ddr_normal_rate; int low_freq_bus_used(void); void set_ddr_freq(int ddr_freq); void *mx6sl_wfi_iram_base; -void (*mx6sl_wfi_iram)(int arm_podf, unsigned long wfi_iram_addr) = NULL; +void (*mx6sl_wfi_iram)(int arm_podf, unsigned long wfi_iram_addr,\ + int audio_mode) = NULL; extern void mx6sl_wait (int arm_podf, unsigned long wfi_iram_addr); void *mx6sl_ddr_freq_base; @@ -169,6 +170,10 @@ void reduce_bus_freq(void) /* PLL2 is on in this mode, as DDR is at 50MHz. */ /* Now change DDR freq while running from IRAM. */ + /* Set AHB to 24MHz. */ + clk_set_rate(ahb_clk, + clk_round_rate(ahb_clk, LPAPM_CLK / 3)); + spin_lock_irqsave(&freq_lock, flags); mx6sl_ddr_freq_change_iram(DDR_AUDIO_CLK, low_bus_freq_mode); @@ -269,7 +274,7 @@ int set_low_bus_freq(void) if (!bus_freq_scaling_initialized || !bus_freq_scaling_is_active) return 0; - /* Check to see if we need to got from + /* Check to see if we need to get from * low bus freq mode to audio bus freq mode. * If so, the change needs to be done immediately. */ diff --git a/arch/arm/mach-mx6/clock.c b/arch/arm/mach-mx6/clock.c index 574b142eb758..1bf20d5857c2 100644 --- a/arch/arm/mach-mx6/clock.c +++ b/arch/arm/mach-mx6/clock.c @@ -52,6 +52,7 @@ extern int wait_mode_arm_podf; extern int lp_audio_freq; extern int cur_arm_podf; extern bool enet_is_active; +extern bool enet_to_gpio_6; void __iomem *apll_base; @@ -1025,7 +1026,8 @@ static int _clk_audio_video_set_rate(struct clk *clk, unsigned long rate) __raw_writel(mfn, pllbase + PLL_NUM_DIV_OFFSET); __raw_writel(mfd, pllbase + PLL_DENOM_DIV_OFFSET); - if (rev >= IMX_CHIP_REVISION_1_1) { + if ((rev >= IMX_CHIP_REVISION_1_1) && + (pllbase == PLL5_VIDEO_BASE_ADDR)) { reg = __raw_readl(ANA_MISC2_BASE_ADDR) & ~ANADIG_ANA_MISC2_CONTROL3_MASK; reg |= control3 << ANADIG_ANA_MISC2_CONTROL3_OFFSET; @@ -1865,6 +1867,8 @@ static int _clk_ipg_perclk_set_rate(struct clk *clk, unsigned long rate) reg = __raw_readl(MXC_CCM_CSCMR1); reg &= ~MXC_CCM_CSCMR1_PERCLK_PODF_MASK; reg |= (div - 1) << MXC_CCM_CSCMR1_PERCLK_PODF_OFFSET; + /* aclk_podf fixup */ + reg ^= 0x00600000; __raw_writel(reg, MXC_CCM_CSCMR1); return 0; @@ -2396,6 +2400,9 @@ static int _clk_usdhc1_set_parent(struct clk *clk, struct clk *parent) if (parent == &pll2_pfd_352M) reg |= (MXC_CCM_CSCMR1_USDHC1_CLK_SEL); + /* aclk_podf fixup */ + reg ^= 0x00600000; + __raw_writel(reg, MXC_CCM_CSCMR1); return 0; @@ -2453,6 +2460,9 @@ static int _clk_usdhc2_set_parent(struct clk *clk, struct clk *parent) if (parent == &pll2_pfd_352M) reg |= (MXC_CCM_CSCMR1_USDHC2_CLK_SEL); + /* aclk_podf fixup */ + reg ^= 0x00600000; + __raw_writel(reg, MXC_CCM_CSCMR1); return 0; @@ -2510,6 +2520,9 @@ static int _clk_usdhc3_set_parent(struct clk *clk, struct clk *parent) if (parent == &pll2_pfd_352M) reg |= (MXC_CCM_CSCMR1_USDHC3_CLK_SEL); + /* aclk_podf fixup */ + reg ^= 0x00600000; + __raw_writel(reg, MXC_CCM_CSCMR1); return 0; @@ -2568,6 +2581,9 @@ static int _clk_usdhc4_set_parent(struct clk *clk, struct clk *parent) if (parent == &pll2_pfd_352M) reg |= (MXC_CCM_CSCMR1_USDHC4_CLK_SEL); + /* aclk_podf fixup */ + reg ^= 0x00600000; + __raw_writel(reg, MXC_CCM_CSCMR1); return 0; @@ -2683,6 +2699,8 @@ static int _clk_ssi1_set_parent(struct clk *clk, struct clk *parent) mux = _get_mux6(parent, &pll3_pfd_508M, &pll3_pfd_454M, &pll4_audio_main_clk, NULL, NULL, NULL); reg |= (mux << MXC_CCM_CSCMR1_SSI1_CLK_SEL_OFFSET); + /* aclk_podf fixup */ + reg ^= 0x00600000; __raw_writel(reg, MXC_CCM_CSCMR1); @@ -2757,6 +2775,8 @@ static int _clk_ssi2_set_parent(struct clk *clk, struct clk *parent) mux = _get_mux6(parent, &pll3_pfd_508M, &pll3_pfd_454M, &pll4_audio_main_clk, NULL, NULL, NULL); reg |= (mux << MXC_CCM_CSCMR1_SSI2_CLK_SEL_OFFSET); + /* aclk_podf fixup */ + reg ^= 0x00600000; __raw_writel(reg, MXC_CCM_CSCMR1); @@ -2830,6 +2850,8 @@ static int _clk_ssi3_set_parent(struct clk *clk, struct clk *parent) mux = _get_mux6(parent, &pll3_pfd_508M, &pll3_pfd_454M, &pll4_audio_main_clk, NULL, NULL, NULL); reg |= (mux << MXC_CCM_CSCMR1_SSI3_CLK_SEL_OFFSET); + /* aclk_podf fixup */ + reg ^= 0x00600000; __raw_writel(reg, MXC_CCM_CSCMR1); @@ -3731,9 +3753,9 @@ static unsigned long _clk_enet_get_rate(struct clk *clk) static int _clk_enet_enable(struct clk *clk) { -#ifndef CONFIG_MX6_ENET_IRQ_TO_GPIO - enet_is_active = true; -#endif + if (!enet_to_gpio_6) + enet_is_active = true; + _clk_enable(clk); return 0; } @@ -3741,9 +3763,9 @@ static int _clk_enet_enable(struct clk *clk) static void _clk_enet_disable(struct clk *clk) { _clk_disable(clk); -#ifndef CONFIG_MX6_ENET_IRQ_TO_GPIO - enet_is_active = false; -#endif + + if (!enet_to_gpio_6) + enet_is_active = false; } static struct clk enet_clk[] = { @@ -3848,6 +3870,8 @@ static int _clk_emi_slow_set_parent(struct clk *clk, struct clk *parent) mux = _get_mux6(parent, &axi_clk, &pll3_usb_otg_main_clk, &pll2_pfd_400M, &pll2_pfd_352M, NULL, NULL); reg |= (mux << MXC_CCM_CSCMR1_ACLK_EMI_SLOW_OFFSET); + /* aclk_podf fixup */ + reg ^= 0x00600000; __raw_writel(reg, MXC_CCM_CSCMR1); return 0; @@ -3878,6 +3902,8 @@ static int _clk_emi_slow_set_rate(struct clk *clk, unsigned long rate) reg = __raw_readl(MXC_CCM_CSCMR1); reg &= ~MXC_CCM_CSCMR1_ACLK_EMI_SLOW_PODF_MASK; reg |= (div - 1) << MXC_CCM_CSCMR1_ACLK_EMI_SLOW_PODF_OFFSET; + /* aclk_podf fixup */ + reg ^= 0x00600000; __raw_writel(reg, MXC_CCM_CSCMR1); return 0; @@ -3922,9 +3948,11 @@ static int _clk_emi_set_parent(struct clk *clk, struct clk *parent) int mux; u32 reg = __raw_readl(MXC_CCM_CSCMR1) & ~MXC_CCM_CSCMR1_ACLK_EMI_MASK; - mux = _get_mux6(parent, &axi_clk, &pll3_usb_otg_main_clk, - &pll2_pfd_400M, &pll2_pfd_352M, NULL, NULL); + mux = _get_mux6(parent, &pll2_pfd_400M, &pll3_usb_otg_main_clk, + &axi_clk, &pll2_pfd_352M, NULL, NULL); reg |= (mux << MXC_CCM_CSCMR1_ACLK_EMI_OFFSET); + /* aclk_podf fixup */ + reg ^= 0x00600000; __raw_writel(reg, MXC_CCM_CSCMR1); return 0; @@ -3934,6 +3962,7 @@ static unsigned long _clk_emi_get_rate(struct clk *clk) { u32 reg, div; + /* ACLK_EMI_PODF read value matches with real divider value */ reg = __raw_readl(MXC_CCM_CSCMR1); div = ((reg & MXC_CCM_CSCMR1_ACLK_EMI_PODF_MASK) >> MXC_CCM_CSCMR1_ACLK_EMI_PODF_OFFSET) + 1; @@ -3952,9 +3981,26 @@ static int _clk_emi_set_rate(struct clk *clk, unsigned long rate) if (((parent_rate / div) != rate) || (div > 8)) return -EINVAL; + /* + * This is a software workaround for ACLK_EMI_PODF SoC + * implementation bug. The write/read/divider values + * have the relationship described by the following table: + * + * write value read value description + * 3b'000 3b'110 divided by 7 + * 3b'001 3b'111 divided by 8 + * 3b'010 3b'100 divided by 5 + * 3b'011 3b'101 divided by 6 + * 3b'100 3b'010 divided by 3 + * 3b'101 3b'011 divided by 4 + * 3b'110 3b'000 divided by 1 + * 3b'111 3b'001 divided by 2(default) + * + * That's why we do the xor operation below. + */ reg = __raw_readl(MXC_CCM_CSCMR1); reg &= ~MXC_CCM_CSCMR1_ACLK_EMI_PODF_MASK; - reg |= (div - 1) << MXC_CCM_CSCMR1_ACLK_EMI_PODF_OFFSET; + reg |= ((div - 1)^0x6) << MXC_CCM_CSCMR1_ACLK_EMI_PODF_OFFSET; __raw_writel(reg, MXC_CCM_CSCMR1); return 0; @@ -4793,6 +4839,7 @@ static int _clk_pcie_enable(struct clk *clk) { unsigned int reg; +#ifndef CONFIG_IMX_PCIE_RC_MODE_IN_EP_RC_SYS /* Activate LVDS CLK1 (the MiniPCIe slot clock input) */ reg = __raw_readl(ANADIG_MISC1_REG); reg &= ~ANATOP_LVDS_CLK1_IBEN_MASK; @@ -4805,6 +4852,7 @@ static int _clk_pcie_enable(struct clk *clk) reg = __raw_readl(ANADIG_MISC1_REG); reg |= ANATOP_LVDS_CLK1_OBEN_MASK; __raw_writel(reg, ANADIG_MISC1_REG); +#endif /* Enable PCIE ref clock */ reg = __raw_readl(PLL8_ENET_BASE_ADDR); @@ -4822,9 +4870,10 @@ static void _clk_pcie_disable(struct clk *clk) _clk_disable(clk); +#ifndef CONFIG_IMX_PCIE_RC_MODE_IN_EP_RC_SYS /* De-activate LVDS CLK1 (the MiniPCIe slot clock input) */ reg = __raw_readl(ANADIG_MISC1_REG); - reg &= ~ANATOP_LVDS_CLK1_IBEN_MASK; + reg |= ANATOP_LVDS_CLK1_IBEN_MASK; __raw_writel(reg, ANADIG_MISC1_REG); reg = __raw_readl(ANADIG_MISC1_REG); @@ -4834,6 +4883,7 @@ static void _clk_pcie_disable(struct clk *clk) reg = __raw_readl(ANADIG_MISC1_REG); reg &= ~ANATOP_LVDS_CLK1_OBEN_MASK; __raw_writel(reg, ANADIG_MISC1_REG); +#endif /* Disable PCIE ref clock */ reg = __raw_readl(PLL8_ENET_BASE_ADDR); @@ -4867,6 +4917,53 @@ static struct clk pcie_clk[] = { }, }; +static int _clk_pcie_ep_enable(struct clk *clk) +{ + unsigned int reg; + + /* Enable PCIE ref clock */ + reg = __raw_readl(PLL8_ENET_BASE_ADDR); + reg |= ANADIG_PLL_ENET_EN_PCIE; + __raw_writel(reg, PLL8_ENET_BASE_ADDR); + + _clk_enable(clk); + + return 0; +} + +static void _clk_pcie_ep_disable(struct clk *clk) +{ + unsigned int reg; + + _clk_disable(clk); + + /* Disable PCIE ref clock */ + reg = __raw_readl(PLL8_ENET_BASE_ADDR); + reg &= ~ANADIG_PLL_ENET_EN_PCIE; + __raw_writel(reg, PLL8_ENET_BASE_ADDR); +} + +static struct clk pcie_ep_clk[] = { + { + __INIT_CLK_DEBUG(pcie_ep_clk) + .parent = &pcie_axi_clk, + .enable = _clk_pcie_ep_enable, + .disable = _clk_pcie_ep_disable, + .enable_reg = MXC_CCM_CCGR4, + .enable_shift = MXC_CCM_CCGRx_CG0_OFFSET, + .secondary = &pcie_ep_clk[1], + .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE, + }, + { + .parent = &pll8_enet_main_clk, + .secondary = &pcie_ep_clk[2], + }, + { + .parent = &mmdc_ch0_axi_clk[0], + .secondary = &mx6fast1_clk, + }, +}; + static struct clk usboh3_clk[] = { { __INIT_CLK_DEBUG(usboh3_clk) @@ -5274,7 +5371,6 @@ static struct clk_lookup lookups[] = { _REGISTER_CLOCK("imx6q-ecspi.1", NULL, ecspi_clk[1]), _REGISTER_CLOCK("imx6q-ecspi.2", NULL, ecspi_clk[2]), _REGISTER_CLOCK("imx6q-ecspi.3", NULL, ecspi_clk[3]), - _REGISTER_CLOCK("imx6q-ecspi.4", NULL, ecspi_clk[4]), _REGISTER_CLOCK(NULL, "emi_slow_clk", emi_slow_clk), _REGISTER_CLOCK(NULL, "emi_clk", emi_clk), _REGISTER_CLOCK(NULL, "enfc_clk", enfc_clk), @@ -5303,6 +5399,7 @@ static struct clk_lookup lookups[] = { _REGISTER_CLOCK("mxc_pwm.2", NULL, pwm_clk[2]), _REGISTER_CLOCK("mxc_pwm.3", NULL, pwm_clk[3]), _REGISTER_CLOCK(NULL, "pcie_clk", pcie_clk[0]), + _REGISTER_CLOCK(NULL, "pcie_ep_clk", pcie_ep_clk[0]), _REGISTER_CLOCK("enet.0", NULL, enet_clk[0]), _REGISTER_CLOCK(NULL, "imx_sata_clk", sata_clk[0]), _REGISTER_CLOCK(NULL, "usboh3_clk", usboh3_clk[0]), @@ -5331,6 +5428,11 @@ static struct clk_lookup lookups[] = { _REGISTER_CLOCK(NULL, "apb_pclk", dummy_clk), }; +static struct +clk_lookup imx6dl_i2c4 = _REGISTER_CLOCK("imx-i2c.3", NULL, ecspi_clk[4]); +static struct +clk_lookup imx6q_ecspi5 = _REGISTER_CLOCK("imx6q-ecspi.4", NULL, ecspi_clk[4]); + static void clk_tree_init(void) { @@ -5368,13 +5470,18 @@ int __init mx6_clocks_init(unsigned long ckil, unsigned long osc, clk_debug_register(lookups[i].clk); } - /* Lower the ipg_perclk frequency to 22MHz. - * I2C needs a minimum of 12.8MHz as its source - * to acheive 400KHz speed. IPG_PERCLK sources - * I2C. 22MHz when divided by the I2C divider gives the - * freq closest to 400KHz. - */ - clk_set_rate(&ipg_perclk, 22000000); + /* + * imx6q have 5 ecspi and 3 i2c + * imx6dl have 4 ecspi and 4 i2c + * imx6dl i2c4 use the imx6q ecspi5 clock source + */ + if (cpu_is_mx6dl()) { + clkdev_add(&imx6dl_i2c4); + clk_debug_register(imx6dl_i2c4.clk); + } else { + clkdev_add(&imx6q_ecspi5); + clk_debug_register(imx6q_ecspi5.clk); + } /* Timer needs to be initialized first as the * the WAIT routines use GPT counter as @@ -5393,6 +5500,15 @@ int __init mx6_clocks_init(unsigned long ckil, unsigned long osc, clk_tree_init(); + /* + * Lower the ipg_perclk frequency to 22MHz. + * I2C needs a minimum of 12.8MHz as its source + * to acheive 400KHz speed. IPG_PERCLK sources + * I2C. 22MHz when divided by the I2C divider gives the + * freq closest to 400KHz. + */ + clk_set_rate(&ipg_perclk, 22000000); + #ifdef CONFIG_MX6_VPU_352M if (cpu_is_mx6q()) { clk_set_rate(&pll2_pfd_400M, 352000000); @@ -5461,8 +5577,11 @@ int __init mx6_clocks_init(unsigned long ckil, unsigned long osc, clk_set_parent(&ipu2_di_clk[1], &pll5_video_main_clk); clk_set_parent(&emi_clk, &pll2_pfd_400M); - clk_set_rate(&emi_clk, 200000000); - +#ifdef CONFIG_MX6_VPU_352M + clk_set_rate(&emi_clk, 176000000); +#else + clk_set_rate(&emi_clk, 198000000); +#endif /* * on mx6dl, 2d core clock sources from 3d shader core clock, * but 3d shader clock multiplexer of mx6dl is different from diff --git a/arch/arm/mach-mx6/clock_mx6sl.c b/arch/arm/mach-mx6/clock_mx6sl.c index c6b08cbce8cb..d8f33877bfe0 100755 --- a/arch/arm/mach-mx6/clock_mx6sl.c +++ b/arch/arm/mach-mx6/clock_mx6sl.c @@ -73,6 +73,7 @@ static struct cpu_op *cpu_op_tbl; static int cpu_op_nr; static bool pll1_enabled; static bool arm_needs_pll2_400; +static bool audio_pll_bypass; DEFINE_SPINLOCK(mx6sl_clk_lock); #define SPIN_DELAY 1200000 /* in nanoseconds */ @@ -429,7 +430,8 @@ static int _clk_pll_enable(struct clk *clk) pllbase = _get_pll_base(clk); reg = __raw_readl(pllbase); - reg &= ~ANADIG_PLL_POWER_DOWN; + if (clk != &pll4_audio_main_clk || !audio_pll_bypass) + reg &= ~ANADIG_PLL_POWER_DOWN; /* The 480MHz PLLs have the opposite definition for power bit. */ if (clk == &pll3_usb_otg_main_clk || clk == &pll7_usb_host_main_clk) @@ -442,14 +444,20 @@ static int _clk_pll_enable(struct clk *clk) __raw_writel(BM_ANADIG_ANA_MISC2_CONTROL0, apll_base + HW_ANADIG_ANA_MISC2_CLR); /* Wait for PLL to lock */ - if (!WAIT((__raw_readl(pllbase) & ANADIG_PLL_LOCK), - SPIN_DELAY)) - panic("pll enable failed\n"); - + if (clk != &pll4_audio_main_clk || !audio_pll_bypass) { + if (!WAIT((__raw_readl(pllbase) & ANADIG_PLL_LOCK), + SPIN_DELAY)) + panic("pll enable failed\n"); + } /* Enable the PLL output now*/ reg = __raw_readl(pllbase); - reg &= ~ANADIG_PLL_BYPASS; + + /* If audio PLL is set to 24MHz, leave it in bypass mode. */ + if (clk != &pll4_audio_main_clk || !audio_pll_bypass) + reg &= ~ANADIG_PLL_BYPASS; + reg |= ANADIG_PLL_ENABLE; + __raw_writel(reg, pllbase); return 0; @@ -874,6 +882,9 @@ static unsigned long _clk_audio_video_get_rate(struct clk *clk) pllbase = _get_pll_base(clk); + if (__raw_readl(pllbase) & ANADIG_PLL_BYPASS) + return 24000000; + test_div_sel = (__raw_readl(pllbase) & ANADIG_PLL_AV_TEST_DIV_SEL_MASK) >> ANADIG_PLL_AV_TEST_DIV_SEL_OFFSET; @@ -917,6 +928,16 @@ static int _clk_audio_video_set_rate(struct clk *clk, unsigned long rate) u32 test_div_sel = 2; u32 control3 = 0; + pllbase = _get_pll_base(clk); + + if (clk == &pll4_audio_main_clk && audio_pll_bypass) { + reg = __raw_readl(pllbase) + & ~ANADIG_PLL_SYS_DIV_SELECT_MASK + & ~ANADIG_PLL_AV_TEST_DIV_SEL_MASK; + __raw_writel(reg, pllbase); + return 0; + } + if (clk == &pll4_audio_main_clk) min_clk_rate = AUDIO_VIDEO_MIN_CLK_FREQ / 4; else @@ -925,8 +946,6 @@ static int _clk_audio_video_set_rate(struct clk *clk, unsigned long rate) if ((rate < min_clk_rate) || (rate > AUDIO_VIDEO_MAX_CLK_FREQ)) return -EINVAL; - pllbase = _get_pll_base(clk); - pre_div_rate = rate; while (pre_div_rate < AUDIO_VIDEO_MIN_CLK_FREQ) { pre_div_rate *= 2; @@ -986,6 +1005,9 @@ static unsigned long _clk_audio_video_round_rate(struct clk *clk, u32 control3 = 0; unsigned long final_rate; + if (clk == &pll4_audio_main_clk && audio_pll_bypass) + return 24000000; + if (clk == &pll4_audio_main_clk) min_clk_rate = AUDIO_VIDEO_MIN_CLK_FREQ / 4; else @@ -1681,6 +1703,7 @@ static struct clk mmdc_ch1_axi_clk[] = { .secondary = &tzasc2_clk, }, }; + #if defined(CONFIG_SDMA_IRAM) || defined(CONFIG_SND_MXC_SOC_IRAM) static struct clk ocram_clk = { __INIT_CLK_DEBUG(ocram_clk) @@ -1692,6 +1715,7 @@ static struct clk ocram_clk = { .disable = _clk_disable_inwait, }; #endif + static unsigned long _clk_ipg_perclk_get_rate(struct clk *clk) { u32 reg, div; @@ -2376,14 +2400,23 @@ static int _clk_extern_audio_set_rate(struct clk *clk, unsigned long rate) u32 reg, div, pre, post; u32 parent_rate = clk_get_rate(clk->parent); - div = parent_rate / rate; - if (div == 0) - div++; - if (((parent_rate / div) != rate) || div > 64) - return -EINVAL; + if (rate == 24000000 && clk->parent == &pll4_audio_main_clk) { + /* If the requested rate is 24MHz, + * set the PLL4 to bypass mode. + */ + audio_pll_bypass = 1; + pre = post = 1; + } else { + div = parent_rate / rate; + if (div == 0) + div++; + if (((parent_rate / div) != rate) || div > 64) + return -EINVAL; - __calc_pre_post_dividers(1 << 3, div, &pre, &post); + audio_pll_bypass = 0; + __calc_pre_post_dividers(1 << 3, div, &pre, &post); + } reg = __raw_readl(MXC_CCM_CS1CDR); reg &= ~(MXC_CCM_CS1CDR_ESAI_CLK_PRED_MASK| MXC_CCM_CS1CDR_ESAI_CLK_PODF_MASK); @@ -2442,15 +2475,10 @@ static struct clk ssi1_clk[] = { .flags = AHB_AUDIO_SET_POINT | CPU_FREQ_TRIG_UPDATE, #ifndef CONFIG_SND_MXC_SOC_IRAM .secondary = &mmdc_ch1_axi_clk[0], - }, #else - .secondary = &ssi1_clk[1], - }, - { - .parent = &mmdc_ch1_axi_clk[0], .secondary = &ocram_clk, - }, #endif + }, }; static unsigned long _clk_ssi2_get_rate(struct clk *clk) @@ -2523,15 +2551,10 @@ static struct clk ssi2_clk[] = { .flags = AHB_AUDIO_SET_POINT | CPU_FREQ_TRIG_UPDATE, #ifndef CONFIG_SND_MXC_SOC_IRAM .secondary = &mmdc_ch1_axi_clk[0], - }, #else - .secondary = &ssi2_clk[1], - }, - { - .parent = &mmdc_ch1_axi_clk[0], .secondary = &ocram_clk, - }, #endif + }, }; static unsigned long _clk_ssi3_get_rate(struct clk *clk) @@ -2603,15 +2626,10 @@ static struct clk ssi3_clk[] = { .flags = AHB_AUDIO_SET_POINT | CPU_FREQ_TRIG_UPDATE, #ifndef CONFIG_SND_MXC_SOC_IRAM .secondary = &mmdc_ch1_axi_clk[0], - }, #else - .secondary = &ssi3_clk[1], - }, - { - .parent = &mmdc_ch1_axi_clk[0], .secondary = &ocram_clk, - }, #endif + }, }; static unsigned long _clk_epdc_lcdif_pix_round_rate(struct clk *clk, @@ -4118,6 +4136,8 @@ int __init mx6sl_clocks_init(unsigned long ckil, unsigned long osc, /* lcdif pix - PLL5 as parent */ clk_set_parent(&lcdif_pix_clk, &pll5_video_main_clk); + clk_set_parent(&ssi2_clk[0], &pll4_audio_main_clk); + lp_high_freq = 0; lp_med_freq = 0; diff --git a/arch/arm/mach-mx6/cpu.c b/arch/arm/mach-mx6/cpu.c index eaeae1d3c57c..a65ad81e666d 100644 --- a/arch/arm/mach-mx6/cpu.c +++ b/arch/arm/mach-mx6/cpu.c @@ -37,6 +37,7 @@ bool enable_wait_mode = true; u32 enable_ldo_mode = LDO_MODE_DEFAULT; u32 arm_max_freq = CPU_AT_1_2GHz; bool mem_clk_on_in_wait; +bool enet_to_gpio_6; int chip_rev; void __iomem *gpc_base; @@ -276,5 +277,10 @@ static int __init enable_mem_clk_in_wait(char *p) early_param("mem_clk_on", enable_mem_clk_in_wait); +static int __init set_enet_irq_to_gpio(char *p) +{ + enet_to_gpio_6 = true; + return 0; +} - +early_param("enet_gpio_6", set_enet_irq_to_gpio); diff --git a/arch/arm/mach-mx6/crm_regs.h b/arch/arm/mach-mx6/crm_regs.h index c4e923eeb650..0ae8e41e01a5 100644 --- a/arch/arm/mach-mx6/crm_regs.h +++ b/arch/arm/mach-mx6/crm_regs.h @@ -178,9 +178,9 @@ #define ANADIG_ANA_MISC2_REG1_BO_EN (1 << 13) #define ANADIG_ANA_MISC2_CONTROL3_MASK 0xC0000000 #define ANADIG_ANA_MISC2_CONTROL3_OFFSET 30 -#define ANADIG_ANA_MISC2_REG0_STEP_TIME_MASK 0x30000000 -#define ANADIG_ANA_MISC2_REG1_STEP_TIME_MASK 0xC000000 -#define ANADIG_ANA_MISC2_REG2_STEP_TIME_MASK 0x3000000 +#define ANADIG_ANA_MISC2_REG0_STEP_TIME_MASK 0x03000000 +#define ANADIG_ANA_MISC2_REG1_STEP_TIME_MASK 0x0C000000 +#define ANADIG_ANA_MISC2_REG2_STEP_TIME_MASK 0x30000000 #define MXC_CCM_BASE MX6_IO_ADDRESS(CCM_BASE_ADDR) /* CCM Register Offsets. */ diff --git a/arch/arm/mach-mx6/mx6_ddr_freq.S b/arch/arm/mach-mx6/mx6_ddr_freq.S index 8d649f336085..de20f0c3248a 100644 --- a/arch/arm/mach-mx6/mx6_ddr_freq.S +++ b/arch/arm/mach-mx6/mx6_ddr_freq.S @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011-2012 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright (C) 2011-2013 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 @@ -401,20 +401,6 @@ ddr_freq_change: adr r10, ddr_freq_change @Address in this function. - - mcr p15, 0, r10, c8, c7, 1 @//@ Make sure freq code address - @// @ is not already in TLB. - mcr p15, 0, r6, c8, c7, 1 @//@ Make sure CCM address - @//@ is not already in TLB. - mcr p15, 0, r5, c8, c7, 1 @//@ make sure MMDC address - @//@ is not already in TLB. - mcr p15, 0, r7, c8, c7, 1 @//@ make sure IOMUX address - @//@ is not already in TLB. - - mrc p15, 0, r0, c10, c0, 0 @//@ Read the TLB lockdown register - orr r0, r0, #1 @//@ Set the Preserve bit. - mcr p15, 0, r0, c10, c0, 0 @//@ Write to the lockdown register - ldr r2, [r6] @ TLB will miss, @CCM address will be loaded ldr r2, [r5] @ TLB will miss, @@ -423,18 +409,33 @@ ddr_freq_change: @IOMUX will be loaded ldr r2, [r8] @ Get the DDR settings. - ldr r2, [r10] @ TLB will miss - ldr r2, [r11] @Get the IOMUX settings - mrc p15, 0, r0, c10, c0, 0 @//@ Read the lockdown register - @//@ (victim will be incremented) - bic r0, r0, #1 @//@ Clear the preserve bit - mcr p15, 0, r0, c10, c0, 0 @//@ Write to the lockdown register + /* Make sure all the L1 & L2 buffers are drained, as + * we don't want any writes to the DDR when it is + * in self-refresh. + */ + /* Make sure the L1 buffers are drained. */ + dsb - /* Disable automatic power saving. */ +#ifdef CONFIG_CACHE_L2X0 + /* Make sure the L2 buffers are drained. + * Sync operation on L2 drains the buffers. + */ + ldr r0, =L2_BASE_ADDR + add r0, r0, #PERIPBASE_VIRT + mov r1, #0x0 + str r1, [r0, #0x730] +#endif + /* The second dsb might be needed to keep cache sync (device write) + * ordering with the memory accesses before it. + */ + dsb + isb + + /* Disable automatic power saving. */ ldr r0, [r5, #0x404] orr r0, r0, #0x01 str r0, [r5, #0x404] diff --git a/arch/arm/mach-mx6/mx6sl_ddr.S b/arch/arm/mach-mx6/mx6sl_ddr.S index 3059f3aa3c8c..9e83985ed0f8 100644 --- a/arch/arm/mach-mx6/mx6sl_ddr.S +++ b/arch/arm/mach-mx6/mx6sl_ddr.S @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright (C) 2012-2013 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 @@ -116,13 +116,6 @@ mmdc_podf0: .macro ddr_switch_400MHz - /* Check if we are switching between - * 400Mhz <-> 50MHz. If so, we only need to - * update MMDC divider. - */ - cmp r1, #0 - beq change_divider_only - /* Set MMDC divider first, in case PLL3 is at 480MHz. */ ldr r6, [r3, #0x10] and r6, r6, #0x10000 @@ -141,6 +134,13 @@ mmdc_podf: pll3_in_bypass: + /* Check if we are switching between + * 400Mhz <-> 100MHz.If so, we should + * try to source MMDC from PLL2_200M. + */ + cmp r1, #0 + beq not_low_bus_freq + /* Ensure that MMDC is sourced from PLL2 mux first. */ ldr r6, [r2, #0x14] bic r6, r6, #0x4000000 @@ -151,6 +151,7 @@ periph2_clk_switch4: cmp r6, #0 bne periph2_clk_switch4 +not_low_bus_freq: /* Now ensure periph2_clk2_sel mux is set to PLL3 */ ldr r6, [r2, #0x18] bic r6, r6, #0x100000 @@ -166,6 +167,12 @@ periph2_clk_switch5: cmp r6, #0 bne periph2_clk_switch5 + /* Check if PLL2 is already unlocked. + * If so do nothing with PLL2. + */ + cmp r1, #0 + beq pll2_already_on + /* Now power up PLL2 and unbypass it. */ ldr r6, [r3, #0x30] bic r6, r6, #0x1000 @@ -192,27 +199,43 @@ wait_for_pll_lock: bic r6, r6, #0x800000 str r6, [r3, #0x100] +pll2_already_on: /* Now switch MMDC clk back to pll2_mux option. */ /* Ensure pre_periph2_clk2 is set to pll2_pfd_400M */ + /* If switching to audio DDR freq, set the + * pre_periph2_clk2 to PLL2_PFD_200M + */ + ldr r6, =400000000 + cmp r6, r0 + bne use_pll2_pfd_200M + ldr r6, [r2, #0x18] bic r6, r6, #0x600000 orr r6, r6, #0x200000 str r6, [r2, #0x18] + ldr r6, =400000000 + b cont2 - ldr r6, [r2, #0x14] - bic r6, r6, #0x4000000 - str r6, [r2, #0x14] +use_pll2_pfd_200M: + ldr r6, [r2, #0x18] + orr r6, r6, #0x600000 + str r6, [r2, #0x18] + ldr r6, =200000000 + +cont2: + ldr r4, [r2, #0x14] + bic r4, r4, #0x4000000 + str r4, [r2, #0x14] periph2_clk_switch6: - ldr r6, [r2, #0x48] - cmp r6, #0 + ldr r4, [r2, #0x48] + cmp r4, #0 bne periph2_clk_switch6 change_divider_only: /* Calculate the MMDC divider * based on the requested freq. */ - ldr r6, =400000000 ldr r4, =0 Loop2: sub r6, r6, r0 @@ -306,7 +329,7 @@ force_measure1: */ ENTRY(mx6sl_ddr_iram) - push {r4, r5, r6, r7, r8, r9, r10 } + push {r4-r10} mx6sl_ddr_freq_change: ldr r3, =ANATOP_BASE_ADDR @@ -326,6 +349,21 @@ mx6sl_ddr_freq_change: ldr r6, [r3] ldr r6, [r2] + /* Drain all the L1 buffers. */ + dsb + +#ifdef CONFIG_CACHE_L2X0 + /* Need to make sure the buffers in L2 are drained. + * Performing a sync operation does this. */ + ldr r7, =L2_BASE_ADDR + add r7, r7, #PERIPBASE_VIRT + mov r6, #0x0 + str r6, [r7, #0x730] +#endif + + /* The second dsb might be needed to keep cache sync (device write) + * ordering with the memory accesses before it. + */ dsb isb @@ -421,7 +459,7 @@ skip_power_down: bic r6, r6, #0x100 str r6, [r8, #0x410] - pop {r4,r5, r6, r7, r8, r9, r10} + pop {r4-r10} /* Restore registers */ mov pc, lr diff --git a/arch/arm/mach-mx6/mx6sl_wfi.S b/arch/arm/mach-mx6/mx6sl_wfi.S index 4ec97e424237..bd5a00c67828 100644 --- a/arch/arm/mach-mx6/mx6sl_wfi.S +++ b/arch/arm/mach-mx6/mx6sl_wfi.S @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright (C) 2012-2013 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 @@ -158,9 +158,11 @@ fifo_reset2_wait: */ ENTRY(mx6sl_wait) - push {r4, r5, r6, r7, r8, r9, r10} + push {r4-r11} mx6sl_lpm_wfi: + mov r11, r2 + /* Get the IRAM data storage address. */ mov r10, r1 mov r9, r1 /* get suspend_iram_base */ @@ -192,7 +194,23 @@ mx6sl_lpm_wfi: ldr r6, [r2] ldr r6, [r1] + /* Drain all the L1 buffers. */ + dsb + +#ifdef CONFIG_CACHE_L2X0 + /* Need to make sure the buffers in L2 are drained. + * Performing a sync operation does this. */ + ldr r7, =L2_BASE_ADDR + add r7, r7, #PERIPBASE_VIRT + mov r6, #0x0 + str r6, [r7, #0x730] +#endif + + /* The second dsb might be needed to keep cache sync (device write) + * ordering with the memory accesses before it. + */ dsb + isb /* Disable Automatic power savings. */ ldr r6, [r8, #0x404] @@ -215,6 +233,9 @@ poll_dvfs_set_1: orr r6, r6, #0x100 str r6, [r8, #0x410] + cmp r11, #1 + beq audio_mode + /* Now set DDR rate to 1MHz. */ /* DDR is from bypassed PLL2 on periph2_clk2 path. * Set the periph2_clk2_podf to divide by 8. @@ -228,6 +249,15 @@ poll_dvfs_set_1: bic r6, r6, #0x38 orr r6, r6, #0x10 str r6, [r2, #0x14] + b mmdc_podf + +audio_mode: + /* MMDC is from PLL2_200M. + * Set the mmdc_podf to div by 8. + */ + ldr r6, [r2, #0x14] + orr r6, r6, #0x38 + str r6, [r2, #0x14] /* Loop till podf is accepted. */ mmdc_podf: @@ -238,6 +268,9 @@ mmdc_podf: /* Set the DDR IO in LPM state. */ sl_ddr_io_set_lpm + cmp r11, #1 + beq do_audio_arm_clk + /* Check if none of the PLLs are * locked, except PLL1 which will get * bypassed below. @@ -378,6 +411,30 @@ podf_loop: orr r6, r6, #0x1 str r6, [r3, #0x150] + b do_wfi + +do_audio_arm_clk: + /* ARM is from PLL2_PFD2_400M here. + * Switch ARM to bypassed PLL1. + */ + ldr r6, [r2, #0xC] + bic r6, r6, #0x4 + str r6, [r2, #0xC] + + /* Set the ARM_PODF to divide by 2 + * as IPG is at 4MHz, we cannot run + * ARM_CLK above 9.6MHz when + * system enters WAIT mode. + */ + ldr r6, =0x2 + str r6, [r2, #0x10] + + /* Loop till podf is accepted. */ +podf_loop_audio: + ldr r6, [r2, #0x48] + cmp r6, #0x0 + bne podf_loop_audio + do_wfi: /* Now do WFI. */ wfi @@ -391,6 +448,9 @@ podf_loop1: cmp r6, #0x0 bne podf_loop1 + cmp r11, #1 + beq audio_arm_clk_restore + /* Check if powered down * analog components. */ @@ -473,12 +533,24 @@ ahb_podf1: cmp r6, #0x0 bne podf_loop1 - mov r9, r10 /* get suspend_iram_base */ + b wfi_restore + +audio_arm_clk_restore: + /* Move ARM back to PLL2_PFD2_400M */ + ldr r6, [r2, #0xC] + orr r6, r6, #0x4 + str r6, [r2, #0xC] + +wfi_restore: + mov r9, r10 /* get suspend_iram_base */ add r9, r9, #IRAM_WAIT_SIZE /* 4K */ /* Restore the DDR IO before exiting self-refresh. */ sl_ddr_io_restore + cmp r11, #1 + beq mmdc_audio_restore + /* Set MMDC back to 24MHz. */ /* Set periph2_clk2_podf to divide by 1. */ /* Now set MMDC PODF to divide by 1. */ @@ -486,6 +558,15 @@ ahb_podf1: bic r6, r6, #0x3f str r6, [r2, #0x14] + b mmdc_podf1 + +mmdc_audio_restore: + /* Set MMDC back to 100MHz. */ + ldr r6, [r2, #0x14] + bic r6, r6, #0x38 + orr r6, r6, #0x8 + str r6, [r2, $0x14] + mmdc_podf1: ldr r6, [r2, #0x48] cmp r6, #0x0 @@ -549,7 +630,7 @@ poll_dvfs_clear_1: str r6, [r8, #0x410] - pop {r4,r5, r6, r7, r8, r9, r10} + pop {r4-r11} /* Restore registers */ mov pc, lr diff --git a/arch/arm/mach-mx6/pcie.c b/arch/arm/mach-mx6/pcie.c index e6b77ae9e750..5a6374cbe6ab 100644 --- a/arch/arm/mach-mx6/pcie.c +++ b/arch/arm/mach-mx6/pcie.c @@ -29,7 +29,9 @@ #include <linux/clk.h> #include <linux/delay.h> #include <linux/gpio.h> +#include <linux/slab.h> #include <linux/platform_device.h> +#include <linux/time.h> #include <mach/pcie.h> @@ -160,6 +162,21 @@ #define PCIE_CONF_FUNC(f) (((f) & 0x7) << 8) #define PCIE_CONF_REG(r) ((r) & ~0x3) +/* + * The default values of the RC's reserved ddr memory + * used to verify EP mode. + * BTW, here is the layout of the 1G ddr on SD boards + * 0x1000_0000 ~ 0x4FFF_FFFF + */ +static u32 rc_ddr_test_region = 0x40000000; +static u32 rc_ddr_test_region_size = (SZ_16M - SZ_16K); + +#ifdef EP_SELF_IO_TEST +static void *rc_ddr_test_reg1, *rc_ddr_test_reg2; +static void __iomem *pcie_arb_base_addr; +static struct timeval tv1, tv2, tv3; +static u32 tv_count1, tv_count2; +#endif static void __iomem *base; static void __iomem *dbi_base; @@ -228,7 +245,7 @@ static int __init imx_pcie_setup(int nr, struct pci_sys_data *sys) pp->io_space_name[sizeof(pp->io_space_name) - 1] = 0; pp->res[0].name = pp->io_space_name; if (pp->index == 0) { - pp->res[0].start = PCIE_ARB_BASE_ADDR; + pp->res[0].start = PCIE_ARB_BASE_ADDR + SZ_16M - SZ_2M; pp->res[0].end = pp->res[0].start + SZ_1M - 1; } pp->res[0].flags = IORESOURCE_IO; @@ -244,7 +261,7 @@ static int __init imx_pcie_setup(int nr, struct pci_sys_data *sys) pp->mem_space_name[sizeof(pp->mem_space_name) - 1] = 0; pp->res[1].name = pp->mem_space_name; if (pp->index == 0) { - pp->res[1].start = PCIE_ARB_BASE_ADDR + SZ_1M; + pp->res[1].start = PCIE_ARB_BASE_ADDR; pp->res[1].end = pp->res[1].start + SZ_16M - SZ_2M - 1; } pp->res[1].flags = IORESOURCE_MEM; @@ -303,10 +320,11 @@ static int imx_pcie_link_up(void __iomem *dbi_base) return 1; } -static void imx_pcie_regions_setup(void __iomem *dbi_base) +static void imx_pcie_regions_setup(struct device *dev, void __iomem *dbi_base) { - unsigned int i; + struct imx_pcie_platform_data *pdata = dev->platform_data; #ifdef CONFIG_PCI_MSI + unsigned int i; void __iomem *p = dbi_base + PCIE_PL_MSIC_INT; #endif @@ -317,9 +335,13 @@ static void imx_pcie_regions_setup(void __iomem *dbi_base) * split and defined into different regions by iATU, * with sizes and offsets as follows: * - * 0x0100_0000 --- 0x010F_FFFF 1MB IORESOURCE_IO - * 0x0110_0000 --- 0x01EF_FFFF 14MB IORESOURCE_MEM + * RC: + * 0x0100_0000 --- 0x01DF_FFFF 14MB IORESOURCE_MEM + * 0x01E0_0000 --- 0x01EF_FFFF 1MB IORESOURCE_IO * 0x01F0_0000 --- 0x01FF_FFFF 1MB Cfg + MSI + Registers + * + * EP (default value): + * 0x0100_0000 --- 0x01FF_C000 16MB - 16KB IORESOURCE_MEM */ /* CMD reg:I/O space, MEM space, and Bus Master Enable */ @@ -329,23 +351,80 @@ static void imx_pcie_regions_setup(void __iomem *dbi_base) | PCI_COMMAND_MASTER, dbi_base + PCI_COMMAND); - /* Set the CLASS_REV of RC CFG header to PCI_CLASS_BRIDGE_PCI */ - writel(readl(dbi_base + PCI_CLASS_REVISION) - | (PCI_CLASS_BRIDGE_PCI << 16), - dbi_base + PCI_CLASS_REVISION); + if (pdata->type_ep) { + /* + * configure the class_rev(emaluate one memory ram ep device), + * bar0 and bar1 of ep + */ + writel(0xdeadbeaf, dbi_base + PCI_VENDOR_ID); + writel(readl(dbi_base + PCI_CLASS_REVISION) + | (PCI_CLASS_MEMORY_RAM << 16), + dbi_base + PCI_CLASS_REVISION); + writel(0xdeadbeaf, dbi_base + PCI_SUBSYSTEM_VENDOR_ID); + + /* 32bit none-prefetchable 8M bytes memory on bar0 */ + writel(0x0, dbi_base + PCI_BASE_ADDRESS_0); + writel(SZ_8M - 1, dbi_base + (1 << 12) + PCI_BASE_ADDRESS_0); + + /* None used bar1 */ + writel(0x0, dbi_base + PCI_BASE_ADDRESS_1); + writel(0, dbi_base + (1 << 12) + PCI_BASE_ADDRESS_1); + + /* 4K bytes IO on bar2 */ + writel(0x1, dbi_base + PCI_BASE_ADDRESS_2); + writel(SZ_4K - 1, dbi_base + (1 << 12) + PCI_BASE_ADDRESS_2); + + /* + * 32bit prefetchable 1M bytes memory on bar3 + * FIXME BAR MASK3 is not changable, the size + * is fixed to 256 bytes. + */ + writel(0x8, dbi_base + PCI_BASE_ADDRESS_3); + writel(SZ_1M - 1, dbi_base + (1 << 12) + PCI_BASE_ADDRESS_3); - /* - * region0 outbound used to access target cfg - */ - writel(0, dbi_base + ATU_VIEWPORT_R); - writel(PCIE_ARB_END_ADDR - SZ_1M + 1, dbi_base + ATU_REGION_LOWBASE_R); - writel(PCIE_ARB_END_ADDR - SZ_64K, dbi_base + ATU_REGION_LIMIT_ADDR_R); - writel(0, dbi_base + ATU_REGION_UPBASE_R); + /* + * 64bit prefetchable 1M bytes memory on bar4-5. + * FIXME BAR4,5 are not enabled yet + */ + writel(0xc, dbi_base + PCI_BASE_ADDRESS_4); + writel(SZ_1M - 1, dbi_base + (1 << 12) + PCI_BASE_ADDRESS_4); + writel(0, dbi_base + (1 << 12) + PCI_BASE_ADDRESS_5); - writel(0, dbi_base + ATU_REGION_LOW_TRGT_ADDR_R); - writel(0, dbi_base + ATU_REGION_UP_TRGT_ADDR_R); - writel(CfgRdWr0, dbi_base + ATU_REGION_CTRL1_R); - writel((1<<31), dbi_base + ATU_REGION_CTRL2_R); + /* + * region0 outbound used to access RC's reserved ddr memory + */ + writel(0, dbi_base + ATU_VIEWPORT_R); + writel(PCIE_ARB_BASE_ADDR, dbi_base + ATU_REGION_LOWBASE_R); + writel(0, dbi_base + ATU_REGION_UPBASE_R); + writel(PCIE_ARB_BASE_ADDR + rc_ddr_test_region_size, + dbi_base + ATU_REGION_LIMIT_ADDR_R); + + writel(rc_ddr_test_region, + dbi_base + ATU_REGION_LOW_TRGT_ADDR_R); + writel(0, dbi_base + ATU_REGION_UP_TRGT_ADDR_R); + writel(MemRdWr, dbi_base + ATU_REGION_CTRL1_R); + writel((1<<31), dbi_base + ATU_REGION_CTRL2_R); + } else { + /* Set the CLASS_REV of RC CFG header to PCI_CLASS_BRIDGE_PCI */ + writel(readl(dbi_base + PCI_CLASS_REVISION) + | (PCI_CLASS_BRIDGE_PCI << 16), + dbi_base + PCI_CLASS_REVISION); + + /* + * region0 outbound used to access target cfg + */ + writel(0, dbi_base + ATU_VIEWPORT_R); + writel(PCIE_ARB_END_ADDR - SZ_1M + 1, + dbi_base + ATU_REGION_LOWBASE_R); + writel(PCIE_ARB_END_ADDR - SZ_64K, + dbi_base + ATU_REGION_LIMIT_ADDR_R); + writel(0, dbi_base + ATU_REGION_UPBASE_R); + + writel(0, dbi_base + ATU_REGION_LOW_TRGT_ADDR_R); + writel(0, dbi_base + ATU_REGION_UP_TRGT_ADDR_R); + writel(CfgRdWr0, dbi_base + ATU_REGION_CTRL1_R); + writel((1<<31), dbi_base + ATU_REGION_CTRL2_R); + } #ifdef CONFIG_PCI_MSI writel(MSI_MATCH_ADDR, dbi_base + PCIE_PL_MSICA); @@ -700,14 +779,26 @@ static void imx_pcie_enable_controller(struct device *dev) imx_pcie_clrset(IOMUXC_GPR1_TEST_POWERDOWN, 0 << 18, IOMUXC_GPR1); + /* enable the clks */ - pcie_clk = clk_get(NULL, "pcie_clk"); - if (IS_ERR(pcie_clk)) - pr_err("no pcie clock.\n"); + if (pdata->type_ep) { + pcie_clk = clk_get(NULL, "pcie_ep_clk"); + if (IS_ERR(pcie_clk)) + pr_err("no pcie_ep clock.\n"); - if (clk_enable(pcie_clk)) { - pr_err("can't enable pcie clock.\n"); - clk_put(pcie_clk); + if (clk_enable(pcie_clk)) { + pr_err("can't enable pcie_ep clock.\n"); + clk_put(pcie_clk); + } + } else { + pcie_clk = clk_get(NULL, "pcie_clk"); + if (IS_ERR(pcie_clk)) + pr_err("no pcie clock.\n"); + + if (clk_enable(pcie_clk)) { + pr_err("can't enable pcie clock.\n"); + clk_put(pcie_clk); + } } imx_pcie_clrset(IOMUXC_GPR1_PCIE_REF_CLK_EN, 1 << 16, IOMUXC_GPR1); } @@ -750,6 +841,7 @@ static void __init add_pcie_port(void __iomem *base, void __iomem *dbi_base, pdata->pcie_power_always_on); /* Release the clocks, and disable the power */ + /* Release the clocks, and disable the power */ pcie_clk = clk_get(NULL, "pcie_clk"); if (IS_ERR(pcie_clk)) pr_err("no pcie clock.\n"); @@ -786,18 +878,107 @@ static int imx6q_pcie_abort_handler(unsigned long addr, return 0; } +#ifdef CONFIG_IMX_PCIE_EP_MODE_IN_EP_RC_SYS +static ssize_t imx_pcie_rc_memw_info(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + return sprintf(buf, "imx-pcie-rc-memw-info start 0x%08x, size 0x%08x\n", + rc_ddr_test_region, rc_ddr_test_region_size); +} + +static ssize_t +imx_pcie_rc_memw_start(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + u32 memw_start; + + sscanf(buf, "%x\n", &memw_start); + + if (memw_start < 0x10000000) { + dev_err(dev, "Invalid memory start address.\n"); + dev_info(dev, "For example: echo 0x41000000 > /sys/..."); + return -1; + } + + if (rc_ddr_test_region != memw_start) { + rc_ddr_test_region = memw_start; + /* Re-setup the iATU */ + imx_pcie_regions_setup(dev, dbi_base); + } + + return count; +} + +static ssize_t +imx_pcie_rc_memw_size(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + u32 memw_size; + + sscanf(buf, "%x\n", &memw_size); + + if ((memw_size > (SZ_16M - SZ_16K)) || (memw_size < SZ_64K)) { + dev_err(dev, "Invalid, should be [SZ_64K,SZ_16M - SZ_16KB].\n"); + dev_info(dev, "For example: echo 0x800000 > /sys/..."); + return -1; + } + + if (rc_ddr_test_region_size != memw_size) { + rc_ddr_test_region_size = memw_size; + /* Re-setup the iATU */ + imx_pcie_regions_setup(dev, dbi_base); + } + + return count; +} + +static DEVICE_ATTR(rc_memw_info, S_IRUGO, imx_pcie_rc_memw_info, NULL); +static DEVICE_ATTR(rc_memw_start_set, S_IWUGO, NULL, imx_pcie_rc_memw_start); +static DEVICE_ATTR(rc_memw_size_set, S_IWUGO, NULL, imx_pcie_rc_memw_size); + +static struct attribute *imx_pcie_attrs[] = { + /* + * The start address, and the limitation (64KB ~ (16MB - 16KB)) + * of the ddr mem window reserved by RC, and used for EP to access. + * BTW, these attrs are only configured at EP side. + */ + &dev_attr_rc_memw_info.attr, + &dev_attr_rc_memw_start_set.attr, + &dev_attr_rc_memw_size_set.attr, + NULL +}; + +static struct attribute_group imx_pcie_attrgroup = { + .attrs = imx_pcie_attrs, +}; +#endif + static int __devinit imx_pcie_pltfm_probe(struct platform_device *pdev) { +#ifdef EP_SELF_IO_TEST + int i; +#endif + int ret = 0; struct resource *mem; struct device *dev = &pdev->dev; struct imx_pcie_platform_data *pdata = dev->platform_data; + pr_info("iMX6 PCIe %s mode %s entering.\n", + pdata->type_ep ? "PCIe EP" : "PCIe RC", __func__); + mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!mem) { dev_err(dev, "no mmio space\n"); return -EINVAL; } +#ifdef CONFIG_IMX_PCIE_EP_MODE_IN_EP_RC_SYS + /* add attributes for device */ + ret = sysfs_create_group(&pdev->dev.kobj, &imx_pcie_attrgroup); + if (ret) + return -EINVAL; +#endif + /* Added for PCI abort handling */ hook_fault_code(16 + 6, imx6q_pcie_abort_handler, SIGBUS, 0, "imprecise external abort"); @@ -805,21 +986,32 @@ static int __devinit imx_pcie_pltfm_probe(struct platform_device *pdev) base = ioremap_nocache(PCIE_ARB_END_ADDR - SZ_1M + 1, SZ_1M - SZ_16K); if (!base) { pr_err("error with ioremap in function %s\n", __func__); - return -EIO; + ret = PTR_ERR(base); +#ifdef CONFIG_IMX_PCIE_EP_MODE_IN_EP_RC_SYS + sysfs_remove_group(&pdev->dev.kobj, &imx_pcie_attrgroup); +#endif + return ret; } dbi_base = devm_ioremap(dev, mem->start, resource_size(mem)); if (!dbi_base) { dev_err(dev, "can't map %pR\n", mem); - return -ENOMEM; + ret = PTR_ERR(dbi_base); + goto err_base; } /* FIXME the field name should be aligned to RM */ imx_pcie_clrset(IOMUXC_GPR12_APP_LTSSM_ENABLE, 0 << 10, IOMUXC_GPR12); /* configure constant input signal to the pcie ctrl and phy */ - imx_pcie_clrset(IOMUXC_GPR12_DEVICE_TYPE, PCI_EXP_TYPE_ROOT_PORT << 12, - IOMUXC_GPR12); + if (pdata->type_ep & 1) + /* EP */ + imx_pcie_clrset(IOMUXC_GPR12_DEVICE_TYPE, + PCI_EXP_TYPE_ENDPOINT << 12, IOMUXC_GPR12); + else + /* RC */ + imx_pcie_clrset(IOMUXC_GPR12_DEVICE_TYPE, + PCI_EXP_TYPE_ROOT_PORT << 12, IOMUXC_GPR12); imx_pcie_clrset(IOMUXC_GPR12_LOS_LEVEL, 9 << 4, IOMUXC_GPR12); imx_pcie_clrset(IOMUXC_GPR8_TX_DEEMPH_GEN1, 0 << 0, IOMUXC_GPR8); @@ -830,58 +1022,116 @@ static int __devinit imx_pcie_pltfm_probe(struct platform_device *pdev) /* Enable the pwr, clks and so on */ imx_pcie_enable_controller(dev); + if (!(pdata->type_ep)) { + /*Only RC: togle the external card's reset */ + card_reset(dev) ; - /* togle the external card's reset */ - card_reset(dev) ; - - usleep_range(3000, 4000); - imx_pcie_regions_setup(dbi_base); - usleep_range(3000, 4000); + imx_pcie_regions_setup(dev, dbi_base); + } + pr_info("PCIE: %s start link up.\n", __func__); /* start link up */ imx_pcie_clrset(IOMUXC_GPR12_APP_LTSSM_ENABLE, 1 << 10, IOMUXC_GPR12); - /* add the pcie port */ - add_pcie_port(base, dbi_base, pdata); - + if (pdata->type_ep) { +#ifdef EP_SELF_IO_TEST + /* Prepare the test regions and data */ + rc_ddr_test_reg1 = kzalloc(rc_ddr_test_region_size, GFP_KERNEL); + if (!rc_ddr_test_reg1) + pr_err("PCIe EP: can't alloc the test region1.\n"); + + rc_ddr_test_reg2 = kzalloc(rc_ddr_test_region_size, GFP_KERNEL); + if (!rc_ddr_test_reg2) { + kfree(rc_ddr_test_reg1); + pr_err("PCIe EP: can't alloc the test region2.\n"); + } - pci_common_init(&imx_pci); - return 0; -} + pcie_arb_base_addr = ioremap_cached(PCIE_ARB_BASE_ADDR, + rc_ddr_test_region_size); -static int __devexit imx_pcie_pltfm_remove(struct platform_device *pdev) -{ - struct clk *pcie_clk; - struct device *dev = &pdev->dev; - struct imx_pcie_platform_data *pdata = dev->platform_data; - struct resource *iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!pcie_arb_base_addr) { + pr_err("error with ioremap in function %s\n", __func__); + ret = PTR_ERR(pcie_arb_base_addr); + kfree(rc_ddr_test_reg2); + kfree(rc_ddr_test_reg1); + goto err_base; + } - /* Release clocks, and disable power */ - pcie_clk = clk_get(NULL, "pcie_clk"); - if (IS_ERR(pcie_clk)) - pr_err("no pcie clock.\n"); + for (i = 0; i < rc_ddr_test_region_size; i = i + 4) { + writel(0xE6600D00 + i, rc_ddr_test_reg1 + i); + writel(0xDEADBEAF, rc_ddr_test_reg2 + i); + } +#endif - if (pcie_clk) { - clk_disable(pcie_clk); - clk_put(pcie_clk); - } + pr_info("PCIe EP: waiting for link up...\n"); + /* link is debug bit 36 debug 1 start in bit 32 */ + do { + usleep_range(10, 20); + } while ((readl(dbi_base + DB_R1) & 0x10) == 0); + /* Make sure that the PCIe link is up */ + if (imx_pcie_link_up(dbi_base)) { + pr_info("PCIe EP: link up.\n"); + } else { + pr_info("PCIe EP: ERROR link is down, exit!\n"); +#ifdef EP_SELF_IO_TEST + kfree(rc_ddr_test_reg2); + kfree(rc_ddr_test_reg1); + iounmap(pcie_arb_base_addr); +#endif + goto err_link_down; + } - imx_pcie_clrset(IOMUXC_GPR1_PCIE_REF_CLK_EN, 0 << 16, IOMUXC_GPR1); + imx_pcie_regions_setup(dev, dbi_base); +#ifdef EP_SELF_IO_TEST + /* PCIe EP start the data transfer after link up */ + pr_info("PCIe EP: Starting data transfer...\n"); + do_gettimeofday(&tv1); + + memcpy((unsigned long *)pcie_arb_base_addr, + (unsigned long *)rc_ddr_test_reg1, 0xFFC000); + + do_gettimeofday(&tv2); + + memcpy((unsigned long *)rc_ddr_test_reg2, + (unsigned long *)pcie_arb_base_addr, 0xFFC000); + + do_gettimeofday(&tv3); + + if (memcmp(rc_ddr_test_reg2, rc_ddr_test_reg1, 0xFFC000) != 0) { + pr_info("PCIe EP: Data transfer is failed.\n"); + } else { + tv_count1 = (tv2.tv_sec - tv1.tv_sec) * USEC_PER_SEC + + tv2.tv_usec - tv1.tv_usec; + tv_count2 = (tv3.tv_sec - tv2.tv_sec) * USEC_PER_SEC + + tv3.tv_usec - tv2.tv_usec; + + pr_info("PCIe EP: Data transfer is successful." + "tv_count1 %dus, tv_count2 %dus.\n", + tv_count1, tv_count2); + pr_info("PCIe EP: Data write speed is %ldMB/s.\n", + ((((0xFFC000/1024) * MSEC_PER_SEC))) + /(tv_count1)); + pr_info("PCIe EP: Data read speed is %ldMB/s.\n", + ((((0xFFC000/1024) * MSEC_PER_SEC))) + /(tv_count2)); + } +#endif - /* Disable PCIE power */ - gpio_request(pdata->pcie_pwr_en, "PCIE POWER_EN"); + } else { + /* add the pcie port */ + add_pcie_port(base, dbi_base, pdata); - /* activate PCIE_PWR_EN */ - gpio_direction_output(pdata->pcie_pwr_en, 0); + pci_common_init(&imx_pci); + } + return 0; - imx_pcie_clrset(IOMUXC_GPR1_TEST_POWERDOWN, 1 << 18, IOMUXC_GPR1); +err_link_down: + iounmap(dbi_base); +err_base: iounmap(base); - iounmap(dbi_base); - release_mem_region(iomem->start, resource_size(iomem)); - platform_set_drvdata(pdev, NULL); - return 0; + return ret; } static struct platform_driver imx_pcie_pltfm_driver = { @@ -890,7 +1140,6 @@ static struct platform_driver imx_pcie_pltfm_driver = { .owner = THIS_MODULE, }, .probe = imx_pcie_pltfm_probe, - .remove = __devexit_p(imx_pcie_pltfm_remove), }; /*****************************************************************************\ diff --git a/arch/arm/mach-mx6/pm.c b/arch/arm/mach-mx6/pm.c index 6e306c279d20..d9c04e11bed0 100644 --- a/arch/arm/mach-mx6/pm.c +++ b/arch/arm/mach-mx6/pm.c @@ -176,9 +176,8 @@ static void usb_power_up_handler(void) static void disp_power_down(void) { -#if !defined(CONFIG_FB_MXC_ELCDIF_FB) && \ - !defined(CONFIG_FB_MXC_ELCDIF_FB_MODULE) - if (cpu_is_mx6sl()) { + if (cpu_is_mx6sl() && (mx6sl_revision() >= IMX_CHIP_REVISION_1_2)) { + __raw_writel(0xFFFFFFFF, gpc_base + GPC_PGC_DISP_PUPSCR_OFFSET); __raw_writel(0xFFFFFFFF, gpc_base + GPC_PGC_DISP_PDNSCR_OFFSET); @@ -194,14 +193,11 @@ static void disp_power_down(void) ~MXC_CCM_CCGRx_CG1_MASK, MXC_CCM_CCGR3); } -#endif } static void disp_power_up(void) { -#if !defined(CONFIG_FB_MXC_ELCDIF_FB) && \ - !defined(CONFIG_FB_MXC_ELCDIF_FB_MODULE) - if (cpu_is_mx6sl()) { + if (cpu_is_mx6sl() && (mx6sl_revision() >= IMX_CHIP_REVISION_1_2)) { /* * Need to enable EPDC/LCDIF pix clock, and * EPDC/LCDIF/PXP axi clock before power up. @@ -217,7 +213,6 @@ static void disp_power_up(void) __raw_writel(0x20, gpc_base + GPC_CNTR_OFFSET); __raw_writel(0x1, gpc_base + GPC_PGC_DISP_SR_OFFSET); } -#endif } static void mx6_suspend_store(void) @@ -342,6 +337,14 @@ static int mx6_suspend_enter(suspend_state_t state) return -EINVAL; } + /* + * L2 can exit by 'reset' or Inband beacon (from remote EP) + * toggling phy_powerdown has same effect as 'inband beacon' + * So, toggle bit18 of GPR1, to fix errata + * "PCIe PCIe does not support L2 Power Down" + */ + __raw_writel(__raw_readl(IOMUXC_GPR1) | (1 << 18), IOMUXC_GPR1); + if (state == PM_SUSPEND_MEM || state == PM_SUSPEND_STANDBY) { local_flush_tlb_all(); @@ -405,6 +408,14 @@ static int mx6_suspend_enter(suspend_state_t state) cpu_do_idle(); } + /* + * L2 can exit by 'reset' or Inband beacon (from remote EP) + * toggling phy_powerdown has same effect as 'inband beacon' + * So, toggle bit18 of GPR1, to fix errata + * "PCIe PCIe does not support L2 Power Down" + */ + __raw_writel(__raw_readl(IOMUXC_GPR1) & (~(1 << 18)), IOMUXC_GPR1); + return 0; } diff --git a/arch/arm/mach-mx6/regs-anadig.h b/arch/arm/mach-mx6/regs-anadig.h index 773a43d1f9ae..b1d164561f8e 100644 --- a/arch/arm/mach-mx6/regs-anadig.h +++ b/arch/arm/mach-mx6/regs-anadig.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright (C) 2011-2013 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 @@ -622,7 +622,8 @@ #define BF_ANADIG_ANA_MISC0_OSC_I(v) \ (((v) << 14) & BM_ANADIG_ANA_MISC0_OSC_I) #define BM_ANADIG_ANA_MISC0_RTC_RINGOSC_EN 0x00002000 -#define BM_ANADIG_ANA_MISC0_STOP_MODE_CONFIG 0x00001000 +#define BM_ANADIG_ANA_MISC0_STOP_MODE_CONFIG \ + (cpu_is_mx6sl() ? 0x00000800 : 0x00001000) #define BP_ANADIG_ANA_MISC0_RSVD0 10 #define BM_ANADIG_ANA_MISC0_RSVD0 0x00000C00 #define BF_ANADIG_ANA_MISC0_RSVD0(v) \ diff --git a/arch/arm/mach-mx6/system.c b/arch/arm/mach-mx6/system.c index 6b30d08cb830..ff1feda30f5b 100644 --- a/arch/arm/mach-mx6/system.c +++ b/arch/arm/mach-mx6/system.c @@ -61,7 +61,8 @@ bool enet_is_active; void arch_idle_with_workaround(int cpu); extern void *mx6sl_wfi_iram_base; -extern void (*mx6sl_wfi_iram)(int arm_podf, unsigned long wfi_iram_addr); +extern void (*mx6sl_wfi_iram)(int arm_podf, unsigned long wfi_iram_addr, \ + int audio_mode); extern void mx6_wait(void *num_cpu_idle_lock, void *num_cpu_idle, \ int wait_arm_podf, int cur_arm_podf); extern bool enable_wait_mode; @@ -262,7 +263,7 @@ 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()) { + if (!cpu_is_mx6sl() && stop_mode >= 2) { /* * For MX6QTO1.2 or later and MX6DLTO1.1 or later, * ensure that the CCM_CGPR bit 17 is cleared before @@ -306,8 +307,8 @@ void arch_idle_single_core(void) if ((mmdc_ch0_axi != NULL)) ddr_usecount = clk_get_usecount(mmdc_ch0_axi); - if (cpu_is_mx6sl() && low_bus_freq_mode - && ddr_usecount == 1) { + if (cpu_is_mx6sl() && (ddr_usecount == 1) && + (low_bus_freq_mode || audio_bus_freq_mode)) { /* In this mode PLL2 i already in bypass, * ARM is sourced from PLL1. The code in IRAM * will set ARM to be sourced from STEP_CLK @@ -320,7 +321,8 @@ void arch_idle_single_core(void) * we can lower DDR freq. */ mx6sl_wfi_iram(org_arm_podf, - (unsigned long)mx6sl_wfi_iram_base); + (unsigned long)mx6sl_wfi_iram_base, + audio_bus_freq_mode); } else { /* Need to set ARM to run at 24MHz since IPG * is at 12MHz. This is valid for audio mode on diff --git a/arch/arm/mach-mx6/usb_dr.c b/arch/arm/mach-mx6/usb_dr.c index 8fb850397c10..e6496bc9cd50 100644 --- a/arch/arm/mach-mx6/usb_dr.c +++ b/arch/arm/mach-mx6/usb_dr.c @@ -37,6 +37,8 @@ static void _dr_discharge_line(bool enable); extern bool usb_icbug_swfix_need(void); static void enter_phy_lowpower_suspend(struct fsl_usb2_platform_data *pdata, \ bool enable); +static u32 wakeup_irq_enable_src; /* only useful at otg mode */ +static u32 low_power_enable_src; /* only useful at otg mode */ /* The usb_phy1_clk do not have enable/disable function at clock.c * and PLL output for usb1's phy should be always enabled. @@ -99,6 +101,16 @@ static int usb_phy_enable(struct fsl_usb2_platform_data *pdata) UOG_USBCMD |= UCMD_RESET; while ((UOG_USBCMD) & (UCMD_RESET)) ; + + /* + * If the controller reset does not put the PHY be out of + * low power mode, do it manually. + */ + if (UOG_PORTSC1 & PORTSC_PHCD) { + UOG_PORTSC1 &= ~PORTSC_PHCD; + mdelay(1); + } + /* Reset USBPHY module */ phy_ctrl = phy_reg + HW_USBPHY_CTRL; tmp = __raw_readl(phy_ctrl); @@ -152,6 +164,8 @@ static int usbotg_init_ext(struct platform_device *pdev) return ret; } if (!otg_used) { + wakeup_irq_enable_src = 0; + low_power_enable_src = 0; usb_phy_enable(pdev->dev.platform_data); enter_phy_lowpower_suspend(pdev->dev.platform_data, false); /*after the phy reset,can not read the readingvalue for id/vbus at @@ -168,10 +182,7 @@ static void usbotg_uninit_ext(struct platform_device *pdev) { otg_used--; if (!otg_used) { - clk_disable(usb_phy1_clk); clk_put(usb_phy1_clk); - - clk_disable(usb_oh3_clk); clk_put(usb_oh3_clk); } } @@ -218,7 +229,6 @@ static void _dr_discharge_line(bool enable) /* Below two macros are used at otg mode to indicate usb mode*/ #define ENABLED_BY_HOST (0x1 << 0) #define ENABLED_BY_DEVICE (0x1 << 1) -static u32 low_power_enable_src; /* only useful at otg mode */ static void enter_phy_lowpower_suspend(struct fsl_usb2_platform_data *pdata, bool enable) { void __iomem *phy_reg = MX6_IO_ADDRESS(USB_PHY0_BASE_ADDR); @@ -251,6 +261,19 @@ static void enter_phy_lowpower_suspend(struct fsl_usb2_platform_data *pdata, boo | BM_USBPHY_PWD_RXPWDDIFF | BM_USBPHY_PWD_RXPWDRX); __raw_writel(tmp, phy_reg + HW_USBPHY_PWD_CLR); + /* + * The PHY works at 32Khz clock when it is at low power mode, + * it needs 10 clocks from 32Khz to normal work state, so + * 500us is the safe value for PHY enters stable status + * according to IC engineer. + * + * Besides, the digital value needs 1ms debounce time to + * wait the value to be stable. We have expected the + * value from OTGSC is correct after calling this API. + * + * So delay 2ms is a save value. + */ + mdelay(2); } pr_debug("DR: %s ends, enable is %d\n", __func__, enable); @@ -289,6 +312,12 @@ static void otg_wake_up_enable(struct fsl_usb2_platform_data *pdata, bool enable | BM_USBPHY_CTRL_ENAUTO_PWRON_PLL , phy_reg + HW_USBPHY_CTRL_SET); USB_OTG_CTRL |= UCTRL_OWIE; } else { + __raw_writel(BM_USBPHY_CTRL_ENDPDMCHG_WKUP + | BM_USBPHY_CTRL_ENAUTOSET_USBCLKS + | BM_USBPHY_CTRL_ENAUTOCLR_PHY_PWD + | BM_USBPHY_CTRL_ENAUTOCLR_CLKGATE + | BM_USBPHY_CTRL_ENAUTOCLR_USBCLKGATE + | BM_USBPHY_CTRL_ENAUTO_PWRON_PLL , phy_reg + HW_USBPHY_CTRL_CLR); USB_OTG_CTRL &= ~UCTRL_OWIE; /* The interrupt must be disabled for at least 3 clock * cycles of the standby clock(32k Hz) , that is 0.094 ms*/ @@ -296,7 +325,6 @@ static void otg_wake_up_enable(struct fsl_usb2_platform_data *pdata, bool enable } } -static u32 wakeup_irq_enable_src; /* only useful at otg mode */ static void __wakeup_irq_enable(struct fsl_usb2_platform_data *pdata, bool on, int source) { /* otg host and device share the OWIE bit, only when host and device @@ -491,6 +519,7 @@ static void _host_wakeup_enable(struct fsl_usb2_platform_data *pdata, bool enabl { void __iomem *phy_reg = MX6_IO_ADDRESS(USB_PHY0_BASE_ADDR); __wakeup_irq_enable(pdata, enable, ENABLED_BY_HOST); +#ifdef CONFIG_USB_OTG if (enable) { pr_debug("host wakeup enable\n"); USB_OTG_CTRL |= UCTRL_WKUP_ID_EN; @@ -504,6 +533,7 @@ static void _host_wakeup_enable(struct fsl_usb2_platform_data *pdata, bool enabl udelay(100); } pr_debug("the otgsc is 0x%x, usbsts is 0x%x, portsc is 0x%x, otgctrl: 0x%x\n", UOG_OTGSC, UOG_USBSTS, UOG_PORTSC1, USB_OTG_CTRL); +#endif } static enum usb_wakeup_event _is_host_wakeup(struct fsl_usb2_platform_data *pdata) @@ -517,8 +547,6 @@ static enum usb_wakeup_event _is_host_wakeup(struct fsl_usb2_platform_data *pdat /* if ID change sts, it is a host wakeup event */ if (otgsc & OTGSC_IS_USB_ID) { pr_debug("otg host ID wakeup\n"); - /* if host ID wakeup, we must clear the ID change sts */ - otgsc |= OTGSC_IS_USB_ID; return WAKEUP_EVENT_ID; } if (wakeup_req && (!(otgsc & OTGSC_STS_USB_ID))) { diff --git a/arch/arm/mach-mx6/usb_h1.c b/arch/arm/mach-mx6/usb_h1.c index d4b7001a111c..6de99d96142b 100644 --- a/arch/arm/mach-mx6/usb_h1.c +++ b/arch/arm/mach-mx6/usb_h1.c @@ -111,6 +111,16 @@ static int usb_phy_enable(struct fsl_usb2_platform_data *pdata) UH1_USBCMD |= UCMD_RESET; while ((UH1_USBCMD) & (UCMD_RESET)) ; + + /* + * If the controller reset does not put the PHY be out of + * low power mode, do it manually. + */ + if (UH1_PORTSC1 & PORTSC_PHCD) { + UH1_PORTSC1 &= ~PORTSC_PHCD; + mdelay(1); + } + /* Reset USBPHY module */ phy_ctrl = phy_reg + HW_USBPHY_CTRL; tmp = __raw_readl(phy_ctrl); @@ -164,7 +174,6 @@ static void fsl_usb_host_uninit_ext(struct platform_device *pdev) fsl_usb_host_uninit(pdata); - clk_disable(usb_oh3_clk); clk_put(usb_oh3_clk); } @@ -194,9 +203,14 @@ static void _wake_up_enable(struct fsl_usb2_platform_data *pdata, bool enable) | BM_USBPHY_CTRL_ENAUTO_PWRON_PLL , phy_reg + HW_USBPHY_CTRL_SET); USB_H1_CTRL |= (UCTRL_OWIE); } else { - USB_H1_CTRL &= ~(UCTRL_OWIE); __raw_writel(BM_USBPHY_CTRL_ENIDCHG_WKUP | BM_USBPHY_CTRL_ENVBUSCHG_WKUP - | BM_USBPHY_CTRL_ENDPDMCHG_WKUP, phy_reg + HW_USBPHY_CTRL_CLR); + | BM_USBPHY_CTRL_ENDPDMCHG_WKUP + | BM_USBPHY_CTRL_ENAUTOSET_USBCLKS + | BM_USBPHY_CTRL_ENAUTOCLR_PHY_PWD + | BM_USBPHY_CTRL_ENAUTOCLR_CLKGATE + | BM_USBPHY_CTRL_ENAUTOCLR_USBCLKGATE + | BM_USBPHY_CTRL_ENAUTO_PWRON_PLL , phy_reg + HW_USBPHY_CTRL_CLR); + USB_H1_CTRL &= ~(UCTRL_OWIE); /* The interrupt must be disabled for at least 3 * cycles of the standby clock(32k Hz) , that is 0.094 ms*/ udelay(100); @@ -331,6 +345,13 @@ static void _phy_lowpower_suspend(struct fsl_usb2_platform_data *pdata, bool ena | BM_USBPHY_PWD_RXPWDDIFF | BM_USBPHY_PWD_RXPWDRX); __raw_writel(tmp, phy_reg + HW_USBPHY_PWD_CLR); + /* + * The PHY works at 32Khz clock when it is at low power mode, + * it needs 10 clocks from 32Khz to normal work state, so + * 500us is the safe value for PHY enters stable status + * according to IC engineer. + */ + udelay(500); } } @@ -353,13 +374,16 @@ static void h1_wakeup_handler(struct fsl_usb2_platform_data *pdata) static void usbh1_wakeup_event_clear(void) { - void __iomem *phy_reg = MX6_IO_ADDRESS(USB_PHY1_BASE_ADDR); - u32 wakeup_irq_bits; - - wakeup_irq_bits = BM_USBPHY_CTRL_RESUME_IRQ | BM_USBPHY_CTRL_WAKEUP_IRQ; - if (__raw_readl(phy_reg + HW_USBPHY_CTRL) && wakeup_irq_bits) { - /* clear the wakeup interrupt status */ - __raw_writel(wakeup_irq_bits, phy_reg + HW_USBPHY_CTRL_CLR); + int wakeup_req = USB_H1_CTRL & UCTRL_OWIR; + + if (wakeup_req != 0) { + printk(KERN_INFO "Unknown wakeup.(H1 OTGSC 0x%x)\n", UH1_OTGSC); + /* Disable OWIE to clear OWIR, wait 3 clock + * cycles of standly clock(32KHz) + */ + USB_H1_CTRL &= ~UCTRL_OWIE; + udelay(100); + USB_H1_CTRL |= UCTRL_OWIE; } } diff --git a/arch/arm/mach-mx6/usb_h2.c b/arch/arm/mach-mx6/usb_h2.c index be092ab8c97c..6ce99abafa41 100644 --- a/arch/arm/mach-mx6/usb_h2.c +++ b/arch/arm/mach-mx6/usb_h2.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011-2012 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright (C) 2011-2013 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 @@ -89,12 +89,7 @@ static void fsl_usb_host_uninit_ext(struct platform_device *pdev) fsl_usb_host_uninit(pdata); - usbh2_internal_phy_clock_gate(false); - - clk_disable(usb_phy3_clk); clk_put(usb_phy3_clk); - - clk_disable(usb_oh3_clk); clk_put(usb_oh3_clk); } diff --git a/arch/arm/mach-mx6/usb_h3.c b/arch/arm/mach-mx6/usb_h3.c index e25c01621b52..cddf55244098 100644 --- a/arch/arm/mach-mx6/usb_h3.c +++ b/arch/arm/mach-mx6/usb_h3.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011-2012 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright (C) 2011-2013 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 @@ -89,12 +89,7 @@ static void fsl_usb_host_uninit_ext(struct platform_device *pdev) fsl_usb_host_uninit(pdata); - usbh3_internal_phy_clock_gate(false); - - clk_disable(usb_phy4_clk); clk_put(usb_phy4_clk); - - clk_disable(usb_oh3_clk); clk_put(usb_oh3_clk); } diff --git a/arch/arm/plat-mxc/devices/platform-imx-i2c.c b/arch/arm/plat-mxc/devices/platform-imx-i2c.c index d11f52da4ac2..f2780ad46a91 100755 --- a/arch/arm/plat-mxc/devices/platform-imx-i2c.c +++ b/arch/arm/plat-mxc/devices/platform-imx-i2c.c @@ -102,9 +102,12 @@ const struct imx_imx_i2c_data imx53_imx_i2c_data[] __initconst = { const struct imx_imx_i2c_data imx6q_imx_i2c_data[] __initconst = { #define imx6q_imx_i2c_data_entry(_id, _hwid) \ imx_imx_i2c_data_entry(MX6Q, _id, _hwid, SZ_4K) +#define imx6dl_imx_i2c_data_entry(_id, _hwid) \ + imx_imx_i2c_data_entry(MX6DL, _id, _hwid, SZ_4K) imx6q_imx_i2c_data_entry(0, 1), imx6q_imx_i2c_data_entry(1, 2), imx6q_imx_i2c_data_entry(2, 3), + imx6dl_imx_i2c_data_entry(3, 4), }; #endif /* ifdef CONFIG_SOC_IMX6Q */ diff --git a/arch/arm/plat-mxc/devices/platform-imx_vpu.c b/arch/arm/plat-mxc/devices/platform-imx_vpu.c index 9e00b2fd22aa..f0295ad16cf9 100755 --- a/arch/arm/plat-mxc/devices/platform-imx_vpu.c +++ b/arch/arm/plat-mxc/devices/platform-imx_vpu.c @@ -123,7 +123,7 @@ void mx6q_vpu_reset(void) __raw_writel(reg, src_base + 0x18); reg = __raw_readl(src_base); - reg |= 0x5; /* warm reset vpu */ + reg |= 0x4; /* warm reset vpu */ __raw_writel(reg, src_base); while (__raw_readl(src_base) & 0x04) ; diff --git a/arch/arm/plat-mxc/gpio.c b/arch/arm/plat-mxc/gpio.c index 82b70d537df9..e12aee5b093b 100755 --- a/arch/arm/plat-mxc/gpio.c +++ b/arch/arm/plat-mxc/gpio.c @@ -3,7 +3,7 @@ * Copyright 2008 Juergen Beisert, kernel@pengutronix.de * * Based on code from Freescale, - * Copyright (C) 2004-2012 Freescale Semiconductor, Inc. + * Copyright (C) 2004-2013 Freescale Semiconductor, Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -283,8 +283,13 @@ static int mxc_gpio_get(struct gpio_chip *chip, unsigned offset) { struct mxc_gpio_port *port = container_of(chip, struct mxc_gpio_port, chip); + u32 gpio_direction; - return (__raw_readl(port->base + GPIO_PSR) >> offset) & 1; + gpio_direction = __raw_readl(port->base + GPIO_GDIR); + if (((gpio_direction >> offset) & 1)) /* output mode */ + return (__raw_readl(port->base + GPIO_DR) >> offset) & 1; + else /* input mode */ + return (__raw_readl(port->base + GPIO_PSR) >> offset) & 1; } static int mxc_gpio_direction_input(struct gpio_chip *chip, unsigned offset) diff --git a/arch/arm/plat-mxc/include/mach/arc_otg.h b/arch/arm/plat-mxc/include/mach/arc_otg.h index f2bb01c6a8c9..fdd84503686b 100755 --- a/arch/arm/plat-mxc/include/mach/arc_otg.h +++ b/arch/arm/plat-mxc/include/mach/arc_otg.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2012 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright (C) 2005-2013 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 @@ -121,6 +121,7 @@ extern void __iomem *imx_otg_base; /* configured_flag (0x180) configflag (supports HS) */ #define UH1_PORTSC1 USBH1_REG32(0x184) /* port status and control */ /* end EHCI registers: */ +#define UH1_OTGSC USBH1_REG32(0x1a4) /* OTG status and control */ #define UH1_USBMODE USBH1_REG32(0x1a8) /* USB device mode */ /* diff --git a/arch/arm/plat-mxc/include/mach/iomux-mx6dl.h b/arch/arm/plat-mxc/include/mach/iomux-mx6dl.h index dbfc9a2d8012..59f8399be39c 100644 --- a/arch/arm/plat-mxc/include/mach/iomux-mx6dl.h +++ b/arch/arm/plat-mxc/include/mach/iomux-mx6dl.h @@ -84,11 +84,18 @@ PAD_CTL_DSE_40ohm | PAD_CTL_PUS_100K_DOWN | \ PAD_CTL_HYS | PAD_CTL_SPEED_MED) +#define MX6DL_HDMICEC_PAD_CTRL (PAD_CTL_HYS | PAD_CTL_PUS_100K_UP | \ + PAD_CTL_PUE | PAD_CTL_PKE | PAD_CTL_ODE | PAD_CTL_SPEED_MED | \ + PAD_CTL_DSE_40ohm | PAD_CTL_SRE_SLOW) + #define MX6DL_GPMI_PAD_CTRL0 (PAD_CTL_PKE | PAD_CTL_PUE | PAD_CTL_PUS_100K_UP) #define MX6DL_GPMI_PAD_CTRL1 (PAD_CTL_DSE_40ohm | PAD_CTL_SPEED_MED | PAD_CTL_SRE_FAST) #define MX6DL_GPMI_PAD_CTRL2 (MX6DL_GPMI_PAD_CTRL0 | MX6DL_GPMI_PAD_CTRL1) #define MX6DL_SPDIF_OUT_PAD_CTRL (PAD_CTL_DSE_120ohm | PAD_CTL_SRE_FAST) +#define ENET_IRQ_PAD_CTRL (PAD_CTL_SRE_FAST | PAD_CTL_DSE_40ohm | \ + PAD_CTL_SPEED_MED) + #define MX6DL_PAD_CSI0_DAT10__IPU1_CSI0_D_10 \ IOMUX_PAD(0x0360, 0x004C, 0, 0x0000, 0, NO_PAD_CTRL) #define MX6DL_PAD_CSI0_DAT10__AUDMUX_AUD3_RXC \ @@ -1425,7 +1432,7 @@ #define MX6DL_PAD_EIM_A25__GPIO_5_2 \ IOMUX_PAD(0x0504, 0x0134, 5, 0x0000, 0, NO_PAD_CTRL) #define MX6DL_PAD_EIM_A25__HDMI_TX_CEC_LINE \ - IOMUX_PAD(0x0504, 0x0134, 6, 0x085C, 0, NO_PAD_CTRL) + IOMUX_PAD(0x0504, 0x0134, 6, 0x085C, 0, MX6DL_HDMICEC_PAD_CTRL) #define MX6DL_PAD_EIM_A25__PL301_SIM_MX6DL_PER1_HBURST_0 \ IOMUX_PAD(0x0504, 0x0134, 7, 0x0000, 0, NO_PAD_CTRL) #define MX6DL_PAD_EIM_A25__EPDC_SDDO_15 \ @@ -2524,10 +2531,12 @@ #define MX6DL_PAD_GPIO_5__SIMBA_EVENTI \ IOMUX_PAD(0x0600, 0x0230, 7, 0x0000, 0, NO_PAD_CTRL) -#define MX6DL_PAD_GPIO_6__ESAI1_SCKT \ - IOMUX_PAD(0x0604, 0x0234, 0, 0x0840, 1, NO_PAD_CTRL) +#define MX6DL_PAD_GPIO_6__ENET_IRQ_TO_GPIO_6 \ + IOMUX_PAD(0x0604, 0x0234, 1 | IOMUX_CONFIG_SION, 0x0000, 0, ENET_IRQ_PAD_CTRL) #define MX6DL_PAD_GPIO_6__OBSERVE_MUX_OBSRV_INT_OUT1 \ IOMUX_PAD(0x0604, 0x0234, 1, 0x0000, 0, NO_PAD_CTRL) +#define MX6DL_PAD_GPIO_6__ESAI1_SCKT \ + IOMUX_PAD(0x0604, 0x0234, 0, 0x0840, 1, NO_PAD_CTRL) #define MX6DL_PAD_GPIO_6__I2C3_SDA \ IOMUX_PAD(0x0604, 0x0234, 2 | IOMUX_CONFIG_SION, 0x087C, 2, MX6DL_I2C_PAD_CTRL) #define MX6DL_PAD_GPIO_6__CCM_CCM_OUT_0 \ @@ -2760,7 +2769,7 @@ #define MX6DL_PAD_KEY_ROW2__GPIO_4_11 \ IOMUX_PAD(0x0648, 0x0260, 5, 0x0000, 0, NO_PAD_CTRL) #define MX6DL_PAD_KEY_ROW2__HDMI_TX_CEC_LINE \ - IOMUX_PAD(0x0648, 0x0260, 6, 0x085C, 1, NO_PAD_CTRL) + IOMUX_PAD(0x0648, 0x0260, 6, 0x085C, 1, MX6DL_HDMICEC_PAD_CTRL) #define MX6DL_PAD_KEY_ROW2__PL301_SIM_MX6DL_PER1_HADDR_4 \ IOMUX_PAD(0x0648, 0x0260, 7, 0x0000, 0, NO_PAD_CTRL) diff --git a/arch/arm/plat-mxc/include/mach/iomux-mx6q.h b/arch/arm/plat-mxc/include/mach/iomux-mx6q.h index 557fc4398cd1..16cd87f46459 100644 --- a/arch/arm/plat-mxc/include/mach/iomux-mx6q.h +++ b/arch/arm/plat-mxc/include/mach/iomux-mx6q.h @@ -85,7 +85,7 @@ #define MX6Q_ECSPI_PAD_CTRL (PAD_CTL_SRE_FAST | PAD_CTL_SPEED_MED | \ PAD_CTL_DSE_40ohm | PAD_CTL_HYS) -#define MX6Q_HDMICEC_PAD_CTRL (PAD_CTL_HYS | PAD_CTL_PUS_22K_UP | \ +#define MX6Q_HDMICEC_PAD_CTRL (PAD_CTL_HYS | PAD_CTL_PUS_100K_UP | \ PAD_CTL_PUE | PAD_CTL_PKE | PAD_CTL_ODE | PAD_CTL_SPEED_MED | \ PAD_CTL_DSE_40ohm | PAD_CTL_SRE_SLOW) @@ -2332,13 +2332,10 @@ #define _MX6Q_PAD_GPIO_6__ESAI1_SCKT \ IOMUX_PAD(0x0600, 0x0230, 0, 0x0870, 1, 0) -#ifdef CONFIG_MX6_ENET_IRQ_TO_GPIO -#define _MX6Q_PAD_GPIO_6__OBSERVE_MUX_OBSRV_INT_OUT1 \ +#define _MX6Q_PAD_GPIO_6__ENET_IRQ_TO_GPIO_6 \ IOMUX_PAD(0x0600, 0x0230, 1 | IOMUX_CONFIG_SION, 0x0000, 0, 0) -#else #define _MX6Q_PAD_GPIO_6__OBSERVE_MUX_OBSRV_INT_OUT1 \ IOMUX_PAD(0x0600, 0x0230, 1, 0x0000, 0, 0) -#endif #define _MX6Q_PAD_GPIO_6__I2C3_SDA \ IOMUX_PAD(0x0600, 0x0230, 2 | IOMUX_CONFIG_SION, 0x08AC, 1, 0) #define _MX6Q_PAD_GPIO_6__CCM_CCM_OUT_0 \ @@ -5940,10 +5937,8 @@ #define MX6Q_PAD_GPIO_3__MLB_MLBCLK \ (_MX6Q_PAD_GPIO_3__MLB_MLBCLK | MUX_PAD_CTRL(MX6Q_MLB150_PAD_CTRL)) -#ifdef CONFIG_MX6_ENET_IRQ_TO_GPIO -#define MX6Q_PAD_GPIO_6__OBSERVE_MUX_OBSRV_INT_OUT1 \ - (_MX6Q_PAD_GPIO_6__OBSERVE_MUX_OBSRV_INT_OUT1 | MUX_PAD_CTRL(ENET_IRQ_PAD_CTRL)) -#else +#define MX6Q_PAD_GPIO_6__ENET_IRQ_TO_GPIO_6 \ + (_MX6Q_PAD_GPIO_6__ENET_IRQ_TO_GPIO_6 | MUX_PAD_CTRL(ENET_IRQ_PAD_CTRL)) #define MX6Q_PAD_GPIO_6__OBSERVE_MUX_OBSRV_INT_OUT1 \ (_MX6Q_PAD_GPIO_6__OBSERVE_MUX_OBSRV_INT_OUT1 | MUX_PAD_CTRL(NO_PAD_CTRL)) #define MX6Q_PAD_GPIO_6__ESAI1_SCKT \ @@ -5960,7 +5955,6 @@ (_MX6Q_PAD_GPIO_6__USDHC2_LCTL | MUX_PAD_CTRL(MX6Q_USDHC_PAD_CTRL)) #define MX6Q_PAD_GPIO_6__MLB_MLBSIG \ (_MX6Q_PAD_GPIO_6__MLB_MLBSIG | MUX_PAD_CTRL(MX6Q_MLB150_PAD_CTRL)) -#endif #define MX6Q_PAD_GPIO_2__ESAI1_FST \ (_MX6Q_PAD_GPIO_2__ESAI1_FST | MUX_PAD_CTRL(NO_PAD_CTRL)) diff --git a/arch/arm/plat-mxc/include/mach/ipu-v3.h b/arch/arm/plat-mxc/include/mach/ipu-v3.h index f4f7a06e8b88..8dda339c4fb0 100755 --- a/arch/arm/plat-mxc/include/mach/ipu-v3.h +++ b/arch/arm/plat-mxc/include/mach/ipu-v3.h @@ -641,7 +641,7 @@ int32_t ipu_disable_csi(struct ipu_soc *ipu, uint32_t csi); int ipu_lowpwr_display_enable(void); int ipu_lowpwr_display_disable(void); -void ipu_enable_irq(struct ipu_soc *ipu, uint32_t irq); +int ipu_enable_irq(struct ipu_soc *ipu, uint32_t irq); void ipu_disable_irq(struct ipu_soc *ipu, uint32_t irq); void ipu_clear_irq(struct ipu_soc *ipu, uint32_t irq); int ipu_request_irq(struct ipu_soc *ipu, uint32_t irq, diff --git a/arch/arm/plat-mxc/include/mach/mxc_hdmi.h b/arch/arm/plat-mxc/include/mach/mxc_hdmi.h index 60946cadc441..94f76380caf6 100644 --- a/arch/arm/plat-mxc/include/mach/mxc_hdmi.h +++ b/arch/arm/plat-mxc/include/mach/mxc_hdmi.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011-2012 Freescale Semiconductor, Inc. + * Copyright (C) 2011-2013 Freescale Semiconductor, Inc. */ /* @@ -1085,4 +1085,11 @@ enum { }; +/* IOCTL commands */ +#define HDMI_IOC_MAGIC 'H' + +#define HDMI_IOC_GET_RESOURCE _IO(HDMI_IOC_MAGIC, 0) +#define HDMI_IOC_GET_CPU_TYPE _IO(HDMI_IOC_MAGIC, 1) + + #endif /* __MXC_HDMI_H__ */ diff --git a/arch/arm/plat-mxc/include/mach/mxc_vpu.h b/arch/arm/plat-mxc/include/mach/mxc_vpu.h index 7a6e24f2b0dd..7869d59c5eec 100755 --- a/arch/arm/plat-mxc/include/mach/mxc_vpu.h +++ b/arch/arm/plat-mxc/include/mach/mxc_vpu.h @@ -1,5 +1,5 @@ /* - * Copyright 2004-2012 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright 2004-2013 Freescale Semiconductor, Inc. All Rights Reserved. */ /* @@ -16,7 +16,7 @@ */ /*! - * @file arch-mxc/mxc_vpu.h + * @file plat-mxc/include/mach/mxc_vpu.h * * @brief VPU system initialization and file operation definition * @@ -58,6 +58,7 @@ struct vpu_mem_desc { #define VPU_IOC_QUERY_BITWORK_MEM _IO(VPU_IOC_MAGIC, 13) #define VPU_IOC_SET_BITWORK_MEM _IO(VPU_IOC_MAGIC, 14) #define VPU_IOC_PHYMEM_CHECK _IO(VPU_IOC_MAGIC, 15) +#define VPU_IOC_LOCK_DEV _IO(VPU_IOC_MAGIC, 16) #define BIT_CODE_RUN 0x000 #define BIT_CODE_DOWN 0x004 diff --git a/arch/arm/plat-mxc/include/mach/pcie.h b/arch/arm/plat-mxc/include/mach/pcie.h index 2e8eb44be0c7..79b62c6374ad 100644 --- a/arch/arm/plat-mxc/include/mach/pcie.h +++ b/arch/arm/plat-mxc/include/mach/pcie.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright (C) 2012-2013 Freescale Semiconductor, Inc. All Rights Reserved. */ /* @@ -35,6 +35,7 @@ struct imx_pcie_platform_data { unsigned int pcie_rst; unsigned int pcie_wake_up; unsigned int pcie_dis; + unsigned int type_ep; /* 1 EP, 0 RC */ unsigned int pcie_power_always_on; }; #endif /* __ASM_ARCH_IMX_PCIE_H */ |