diff options
author | Jack Lee <jacklee@freescale.com> | 2012-09-05 10:21:49 +0800 |
---|---|---|
committer | Jack Lee <jacklee@freescale.com> | 2012-09-05 10:21:49 +0800 |
commit | a0619e1d6c1c51a367b8d0bf74bb9058df919545 (patch) | |
tree | d40e30c91892ea35c82d22a8364b9b9548e42b7a /arch/arm/mach-mx6 | |
parent | 65745dd4b7f80711d03dce5529fc501162428c53 (diff) | |
parent | 85a6685fb327f1eebaeea5dfc04a6750573472ef (diff) |
Merge commit 'rel_imx_3.0.35_12.09.02_RC1' into imx_3.0.35_android_r13.5-beta
Conflicts:
arch/arm/mach-mx6/board-mx6q_sabresd.c
arch/arm/mach-mx6/board-mx6sl_arm2.c
arch/arm/mach-mx6/bus_freq.c
arch/arm/mach-mx6/cpu_op-mx6.c
arch/arm/plat-mxc/cpufreq.c
Signed-off-by: Jack Lee <jacklee@freescale.com>
Diffstat (limited to 'arch/arm/mach-mx6')
29 files changed, 3799 insertions, 595 deletions
diff --git a/arch/arm/mach-mx6/Kconfig b/arch/arm/mach-mx6/Kconfig index 08875a60a31c..45ae9eac67d2 100644 --- a/arch/arm/mach-mx6/Kconfig +++ b/arch/arm/mach-mx6/Kconfig @@ -107,6 +107,43 @@ config MACH_MX6SL_ARM2 Include support for i.MX 6Sololite Armadillo2 platform. This includes specific configurations for the board and its peripherals. +config MACH_MX6SL_EVK + bool "Support i.MX 6SoloLite EVK platform" + select ARCH_MX6Q + select SOC_IMX6SL + select IMX_HAVE_PLATFORM_IMX_UART + select IMX_HAVE_PLATFORM_DMA + select IMX_HAVE_PLATFORM_FEC + select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX + select IMX_HAVE_PLATFORM_SPI_IMX + select IMX_HAVE_PLATFORM_IMX_I2C + select IMX_HAVE_PLATFORM_VIV_GPU + select IMX_HAVE_PLATFORM_IMX_DVFS + select IMX_HAVE_PLATFORM_IMX_SSI + select IMX_HAVE_PLATFORM_IMX_ANATOP_THERMAL + select IMX_HAVE_PLATFORM_FSL_USB2_UDC + select IMX_HAVE_PLATFORM_MXC_EHCI + select IMX_HAVE_PLATFORM_FSL_OTG + select IMX_HAVE_PLATFORM_FSL_USB_WAKEUP + select IMX_HAVE_PLATFORM_AHCI + select IMX_HAVE_PLATFORM_IMX_OCOTP + select IMX_HAVE_PLATFORM_IMX_VIIM + select IMX_HAVE_PLATFORM_IMX2_WDT + select IMX_HAVE_PLATFORM_IMX_SNVS_RTC + select IMX_HAVE_PLATFORM_IMX_PM + select IMX_HAVE_PLATFORM_IMX_SPDIF + select IMX_HAVE_PLATFORM_PERFMON + select IMX_HAVE_PLATFORM_IMX_EPDC + select IMX_HAVE_PLATFORM_IMX_SPDC + select IMX_HAVE_PLATFORM_IMX_PXP + select IMX_HAVE_PLATFORM_IMX_KEYPAD + select IMX_HAVE_PLATFORM_IMX_DCP + select IMX_HAVE_PLATFORM_RANDOM_RNGC + select ARCH_HAS_RNGC + help + Include support for i.MX 6Sololite EVK platform. This includes specific + configurations for the board and its peripherals. + config MACH_MX6Q_SABRELITE bool "Support i.MX 6Quad SABRE Lite platform" select ARCH_MX6Q diff --git a/arch/arm/mach-mx6/Makefile b/arch/arm/mach-mx6/Makefile index 24dae23dd089..49b5f86a6920 100644 --- a/arch/arm/mach-mx6/Makefile +++ b/arch/arm/mach-mx6/Makefile @@ -5,15 +5,16 @@ # Object file lists. obj-y := cpu.o mm.o system.o devices.o dummy_gpio.o irq.o bus_freq.o usb_dr.o usb_h2.o usb_h3.o\ pm.o cpu_op-mx6.o mx6_wfi.o mx6_fec.o mx6_anatop_regulator.o cpu_regulator-mx6.o \ -mx6_mmdc.o mx6_ddr_freq.o +mx6_mmdc.o mx6_ddr_freq.o mx6sl_ddr.o mx6sl_wfi.o obj-$(CONFIG_ARCH_MX6) += clock.o mx6_suspend.o clock_mx6sl.o obj-$(CONFIG_MACH_MX6Q_ARM2) += board-mx6q_arm2.o obj-$(CONFIG_MACH_MX6SL_ARM2) += board-mx6sl_arm2.o mx6sl_arm2_pmic_pfuze100.o +obj-$(CONFIG_MACH_MX6SL_EVK) += board-mx6sl_evk.o mx6sl_evk_pmic_pfuze100.o obj-$(CONFIG_MACH_MX6Q_SABRELITE) += board-mx6q_sabrelite.o obj-$(CONFIG_MACH_MX6Q_SABRESD) += board-mx6q_sabresd.o mx6q_sabresd_pmic_pfuze100.o obj-$(CONFIG_MACH_MX6Q_SABREAUTO) += board-mx6q_sabreauto.o mx6q_sabreauto_pmic_pfuze100.o obj-$(CONFIG_SMP) += plat_hotplug.o platsmp.o headsmp.o obj-$(CONFIG_LOCAL_TIMERS) += localtimer.o obj-$(CONFIG_IMX_PCIE) += pcie.o -obj-$(CONFIG_USB_EHCI_ARC_H1) += usb_h1.o
\ No newline at end of file +obj-$(CONFIG_USB_EHCI_ARC_H1) += usb_h1.o diff --git a/arch/arm/mach-mx6/board-mx6dl_arm2.h b/arch/arm/mach-mx6/board-mx6dl_arm2.h index 6ed3e65e68ee..429febb9813d 100644 --- a/arch/arm/mach-mx6/board-mx6dl_arm2.h +++ b/arch/arm/mach-mx6/board-mx6dl_arm2.h @@ -188,7 +188,9 @@ static iomux_v3_cfg_t mx6dl_arm2_pads[] = { MX6DL_PAD_GPIO_6__MLB_MLBSIG, MX6DL_PAD_GPIO_2__MLB_MLBDAT, - /* EPDC pins */ +}; + +static iomux_v3_cfg_t mx6dl_arm2_epdc_pads[] = { MX6DL_PAD_EIM_A17__GPIO_2_21, MX6DL_PAD_EIM_D17__GPIO_3_17, MX6DL_PAD_EIM_A18__GPIO_2_20, diff --git a/arch/arm/mach-mx6/board-mx6q_arm2.c b/arch/arm/mach-mx6/board-mx6q_arm2.c index 62db4d47ba41..c604319ef986 100644 --- a/arch/arm/mach-mx6/board-mx6q_arm2.c +++ b/arch/arm/mach-mx6/board-mx6q_arm2.c @@ -2005,12 +2005,14 @@ static void __init mx6_arm2_init(void) iomux_v3_cfg_t *spdif_pads = NULL; iomux_v3_cfg_t *flexcan_pads = NULL; iomux_v3_cfg_t *i2c3_pads = NULL; + iomux_v3_cfg_t *epdc_pads = NULL; int common_pads_cnt; int esai_rec_pads_cnt; int spdif_pads_cnt; int flexcan_pads_cnt; int i2c3_pads_cnt; + int epdc_pads_cnt; /* @@ -2036,12 +2038,14 @@ static void __init mx6_arm2_init(void) spdif_pads = mx6dl_arm2_spdif_pads; flexcan_pads = mx6dl_arm2_can_pads; i2c3_pads = mx6dl_arm2_i2c3_pads; + epdc_pads = mx6dl_arm2_epdc_pads; common_pads_cnt = ARRAY_SIZE(mx6dl_arm2_pads); esai_rec_pads_cnt = ARRAY_SIZE(mx6dl_arm2_esai_record_pads); spdif_pads_cnt = ARRAY_SIZE(mx6dl_arm2_spdif_pads); 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); } BUG_ON(!common_pads); @@ -2222,6 +2226,8 @@ static void __init mx6_arm2_init(void) imx6q_add_mlb150(&mx6_arm2_mlb150_data); if (cpu_is_mx6dl() && epdc_enabled) { + BUG_ON(!epdc_pads); + mxc_iomux_v3_setup_multiple_pads(epdc_pads, epdc_pads_cnt); imx6dl_add_imx_pxp(); imx6dl_add_imx_pxp_client(); mxc_register_device(&max17135_sensor_device, NULL); diff --git a/arch/arm/mach-mx6/board-mx6q_sabrelite.c b/arch/arm/mach-mx6/board-mx6q_sabrelite.c index d972cda66750..530466dd7b2f 100644 --- a/arch/arm/mach-mx6/board-mx6q_sabrelite.c +++ b/arch/arm/mach-mx6/board-mx6q_sabrelite.c @@ -576,6 +576,15 @@ static struct i2c_board_info mxc_i2c0_board_info[] __initdata = { }, }; +static void mx6q_csi0_cam_powerdown(int powerdown) +{ + if (powerdown) + gpio_set_value(MX6Q_SABRELITE_CSI0_PWN, 1); + else + gpio_set_value(MX6Q_SABRELITE_CSI0_PWN, 0); + + msleep(2); +} static void mx6q_csi0_io_init(void) { @@ -616,6 +625,7 @@ static struct fsl_mxc_camera_platform_data camera_data = { .mclk_source = 0, .csi = 0, .io_init = mx6q_csi0_io_init, + .pwdn = mx6q_csi0_cam_powerdown, }; static struct i2c_board_info mxc_i2c1_board_info[] __initdata = { @@ -1260,6 +1270,10 @@ static void __init mx6_sabrelite_board_init(void) clk_set_rate(clko2, rate); clk_enable(clko2); imx6q_add_busfreq(); + + imx6q_add_perfmon(0); + imx6q_add_perfmon(1); + imx6q_add_perfmon(2); } extern void __iomem *twd_base; diff --git a/arch/arm/mach-mx6/board-mx6q_sabresd.c b/arch/arm/mach-mx6/board-mx6q_sabresd.c index 3a02094869e7..9bb1ee3f93ed 100644 --- a/arch/arm/mach-mx6/board-mx6q_sabresd.c +++ b/arch/arm/mach-mx6/board-mx6q_sabresd.c @@ -1592,13 +1592,14 @@ static struct platform_pwm_backlight_data mx6_sabresd_pwm_backlight_data = { }; static struct mxc_dvfs_platform_data sabresd_dvfscore_data = { - #ifdef CONFIG_MX6_INTER_LDO_BYPASS +#ifdef CONFIG_MX6_INTER_LDO_BYPASS .reg_id = "VDDCORE", - #else + .soc_id = "VDDSOC", +#else .reg_id = "cpu_vddgp", .soc_id = "cpu_vddsoc", .pu_id = "cpu_vddvpu", - #endif +#endif .clk1_id = "cpu_clk", .clk2_id = "gpc_dvfs_clk", .gpc_cntr_offset = MXC_GPC_CNTR_OFFSET, @@ -1824,12 +1825,9 @@ static void __init mx6_sabresd_board_init(void) imx6q_add_dma(); imx6q_add_dvfs_core(&sabresd_dvfscore_data); - #ifndef CONFIG_MX6_INTER_LDO_BYPASS +#ifndef CONFIG_MX6_INTER_LDO_BYPASS mx6_cpu_regulator_init(); - #endif - - imx6q_add_ion(0, &imx_ion_data, - sizeof(imx_ion_data) + sizeof(struct ion_platform_heap)); +#endif imx6q_add_device_buttons(); /* enable sensor 3v3 and 1v8 */ diff --git a/arch/arm/mach-mx6/board-mx6sl_arm2.c b/arch/arm/mach-mx6/board-mx6sl_arm2.c index 249912b82d04..419b2447e215 100755 --- a/arch/arm/mach-mx6/board-mx6sl_arm2.c +++ b/arch/arm/mach-mx6/board-mx6sl_arm2.c @@ -33,7 +33,6 @@ #include <linux/spi/flash.h> #include <linux/i2c.h> #include <linux/i2c/pca953x.h> -#include <linux/ata.h> #include <linux/mtd/mtd.h> #include <linux/mtd/map.h> #include <linux/mtd/partitions.h> @@ -71,67 +70,11 @@ #include "devices-imx6q.h" #include "crm_regs.h" #include "cpu_op-mx6.h" -#include "board-mx6sl_arm2.h" - -#define MX6_ARM2_USBOTG1_PWR IMX_GPIO_NR(4, 0) /* KEY_COL4 */ -#define MX6_ARM2_USBOTG2_PWR IMX_GPIO_NR(4, 2) /* KEY_COL5 */ -#define MX6_ARM2_LCD_PWR_EN IMX_GPIO_NR(4, 3) /* KEY_ROW5 */ -#define MX6_ARM2_SD1_WP IMX_GPIO_NR(4, 6) /* KEY_COL7 */ -#define MX6_ARM2_SD1_CD IMX_GPIO_NR(4, 7) /* KEY_ROW7 */ -#define MX6_ARM2_ECSPI1_CS0 IMX_GPIO_NR(4, 11) /* ECSPI1_SS0 */ -#define MX6_ARM2_HEADPHONE_DET IMX_GPIO_NR(4, 19) /* FEC_RX_ER */ -#define MX6_ARM2_SD2_WP IMX_GPIO_NR(4, 29) /* SD2_DAT6 */ -#define MX6_ARM2_SD2_CD IMX_GPIO_NR(5, 0) /* SD2_DAT7 */ -#define MX6_ARM2_SD3_CD IMX_GPIO_NR(3, 22) /* REF_CLK_32K */ -#define MX6_ARM2_FEC_PWR_EN IMX_GPIO_NR(4, 21) /* FEC_TX_CLK */ - -/* EPDC GPIO pins */ -#define MX6SL_ARM2_EPDC_SDDO_0 IMX_GPIO_NR(1, 7) -#define MX6SL_ARM2_EPDC_SDDO_1 IMX_GPIO_NR(1, 8) -#define MX6SL_ARM2_EPDC_SDDO_2 IMX_GPIO_NR(1, 9) -#define MX6SL_ARM2_EPDC_SDDO_3 IMX_GPIO_NR(1, 10) -#define MX6SL_ARM2_EPDC_SDDO_4 IMX_GPIO_NR(1, 11) -#define MX6SL_ARM2_EPDC_SDDO_5 IMX_GPIO_NR(1, 12) -#define MX6SL_ARM2_EPDC_SDDO_6 IMX_GPIO_NR(1, 13) -#define MX6SL_ARM2_EPDC_SDDO_7 IMX_GPIO_NR(1, 14) -#define MX6SL_ARM2_EPDC_SDDO_8 IMX_GPIO_NR(1, 15) -#define MX6SL_ARM2_EPDC_SDDO_9 IMX_GPIO_NR(1, 16) -#define MX6SL_ARM2_EPDC_SDDO_10 IMX_GPIO_NR(1, 17) -#define MX6SL_ARM2_EPDC_SDDO_11 IMX_GPIO_NR(1, 18) -#define MX6SL_ARM2_EPDC_SDDO_12 IMX_GPIO_NR(1, 19) -#define MX6SL_ARM2_EPDC_SDDO_13 IMX_GPIO_NR(1, 20) -#define MX6SL_ARM2_EPDC_SDDO_14 IMX_GPIO_NR(1, 21) -#define MX6SL_ARM2_EPDC_SDDO_15 IMX_GPIO_NR(1, 22) -#define MX6SL_ARM2_EPDC_GDCLK IMX_GPIO_NR(1, 31) -#define MX6SL_ARM2_EPDC_GDSP IMX_GPIO_NR(2, 2) -#define MX6SL_ARM2_EPDC_GDOE IMX_GPIO_NR(2, 0) -#define MX6SL_ARM2_EPDC_GDRL IMX_GPIO_NR(2, 1) -#define MX6SL_ARM2_EPDC_SDCLK IMX_GPIO_NR(1, 23) -#define MX6SL_ARM2_EPDC_SDOE IMX_GPIO_NR(1, 25) -#define MX6SL_ARM2_EPDC_SDLE IMX_GPIO_NR(1, 24) -#define MX6SL_ARM2_EPDC_SDSHR IMX_GPIO_NR(1, 26) -#define MX6SL_ARM2_EPDC_PWRCOM IMX_GPIO_NR(2, 11) -#define MX6SL_ARM2_EPDC_PWRSTAT IMX_GPIO_NR(2, 13) -#define MX6SL_ARM2_EPDC_PWRCTRL0 IMX_GPIO_NR(2, 7) -#define MX6SL_ARM2_EPDC_PWRCTRL1 IMX_GPIO_NR(2, 8) -#define MX6SL_ARM2_EPDC_PWRCTRL2 IMX_GPIO_NR(2, 9) -#define MX6SL_ARM2_EPDC_PWRCTRL3 IMX_GPIO_NR(2, 10) -#define MX6SL_ARM2_EPDC_BDR0 IMX_GPIO_NR(2, 5) -#define MX6SL_ARM2_EPDC_BDR1 IMX_GPIO_NR(2, 6) -#define MX6SL_ARM2_EPDC_SDCE0 IMX_GPIO_NR(1, 27) -#define MX6SL_ARM2_EPDC_SDCE1 IMX_GPIO_NR(1, 28) -#define MX6SL_ARM2_EPDC_SDCE2 IMX_GPIO_NR(1, 29) -#define MX6SL_ARM2_EPDC_SDCE3 IMX_GPIO_NR(1, 30) -#define MX6SL_ARM2_EPDC_PMIC_WAKE IMX_GPIO_NR(2, 14) /* EPDC_PWRWAKEUP */ -#define MX6SL_ARM2_EPDC_PMIC_INT IMX_GPIO_NR(2, 12) /* EPDC_PWRINT */ -#define MX6SL_ARM2_EPDC_VCOM IMX_GPIO_NR(2, 3) -#define MX6SL_ARM2_ELAN_CE IMX_GPIO_NR(2, 9) -#define MX6SL_ARM2_ELAN_INT IMX_GPIO_NR(2, 10) -#define MX6SL_ARM2_ELAN_RST IMX_GPIO_NR(4, 4) +#include "board-mx6sl_common.h" static int spdc_sel; static int max17135_regulator_init(struct max17135 *max17135); -struct clk *extern_audio_root; +static struct clk *extern_audio_root; extern char *gp_reg_id; extern char *soc_reg_id; @@ -215,8 +158,8 @@ static int plt_sd_pad_change(unsigned int index, int clock) } static const struct esdhc_platform_data mx6_arm2_sd1_data __initconst = { - .cd_gpio = MX6_ARM2_SD1_CD, - .wp_gpio = MX6_ARM2_SD1_WP, + .cd_gpio = MX6_BRD_SD1_CD, + .wp_gpio = MX6_BRD_SD1_WP, .support_8bit = 1, .support_18v = 1, .keep_power_at_suspend = 1, @@ -225,8 +168,8 @@ static const struct esdhc_platform_data mx6_arm2_sd1_data __initconst = { }; static const struct esdhc_platform_data mx6_arm2_sd2_data __initconst = { - .cd_gpio = MX6_ARM2_SD2_CD, - .wp_gpio = MX6_ARM2_SD2_WP, + .cd_gpio = MX6_BRD_SD2_CD, + .wp_gpio = MX6_BRD_SD2_WP, .keep_power_at_suspend = 1, .delay_line = 0, .support_18v = 1, @@ -234,7 +177,7 @@ static const struct esdhc_platform_data mx6_arm2_sd2_data __initconst = { }; static const struct esdhc_platform_data mx6_arm2_sd3_data __initconst = { - .cd_gpio = MX6_ARM2_SD3_CD, + .cd_gpio = MX6_BRD_SD3_CD, .wp_gpio = -1, .keep_power_at_suspend = 1, .delay_line = 0, @@ -377,11 +320,11 @@ static struct max17135_platform_data max17135_pdata __initdata = { .vpos_pwrdn = 2, .gvee_pwrdn = 1, .vneg_pwrdn = 1, - .gpio_pmic_pwrgood = MX6SL_ARM2_EPDC_PWRSTAT, - .gpio_pmic_vcom_ctrl = MX6SL_ARM2_EPDC_VCOM, - .gpio_pmic_wakeup = MX6SL_ARM2_EPDC_PMIC_WAKE, - .gpio_pmic_v3p3 = MX6SL_ARM2_EPDC_PWRCTRL0, - .gpio_pmic_intr = MX6SL_ARM2_EPDC_PMIC_INT, + .gpio_pmic_pwrgood = MX6SL_BRD_EPDC_PWRSTAT, + .gpio_pmic_vcom_ctrl = MX6SL_BRD_EPDC_VCOM, + .gpio_pmic_wakeup = MX6SL_BRD_EPDC_PMIC_WAKE, + .gpio_pmic_v3p3 = MX6SL_BRD_EPDC_PWRCTRL0, + .gpio_pmic_intr = MX6SL_BRD_EPDC_PMIC_INT, .regulator_init = max17135_init_data, .init = max17135_regulator_init, }; @@ -448,7 +391,7 @@ static int __init max17135_regulator_init(struct max17135 *max17135) } static int mx6_arm2_spi_cs[] = { - MX6_ARM2_ECSPI1_CS0, + MX6_BRD_ECSPI1_CS0, }; static const struct spi_imx_master mx6_arm2_spi_data __initconst = { @@ -551,7 +494,7 @@ static struct mxc_audio_platform_data wm8962_data = { .ssi_num = 1, .src_port = 2, .ext_port = 3, - .hp_gpio = MX6_ARM2_HEADPHONE_DET, + .hp_gpio = MX6_BRD_HEADPHONE_DET, .hp_active_low = 1, .mic_gpio = -1, .mic_active_low = 1, @@ -618,7 +561,9 @@ static struct i2c_board_info mxc_i2c0_board_info[] __initdata = { .platform_data = &max17135_pdata, }, { I2C_BOARD_INFO("elan-touch", 0x10), - .irq = gpio_to_irq(MX6SL_ARM2_ELAN_INT), + .irq = gpio_to_irq(MX6SL_BRD_ELAN_INT), + }, { + I2C_BOARD_INFO("mma8450", 0x1c), }, }; @@ -635,13 +580,14 @@ static struct i2c_board_info mxc_i2c2_board_info[] __initdata = { }; static struct mxc_dvfs_platform_data mx6sl_arm2_dvfscore_data = { - #ifdef CONFIG_MX6_INTER_LDO_BYPASS +#ifdef CONFIG_MX6_INTER_LDO_BYPASS .reg_id = "VDDCORE", - #else + .soc_id = "VDDSOC", +#else .reg_id = "cpu_vddgp", .soc_id = "cpu_vddsoc", .pu_id = "cpu_vddvpu", - #endif +#endif .clk1_id = "cpu_clk", .clk2_id = "gpc_dvfs_clk", .gpc_cntr_offset = MXC_GPC_CNTR_OFFSET, @@ -679,11 +625,11 @@ static int mx6sl_arm2_fec_phy_init(struct phy_device *phydev) int val; /* power on FEC phy and reset phy */ - gpio_request(MX6_ARM2_FEC_PWR_EN, "fec-pwr"); - gpio_direction_output(MX6_ARM2_FEC_PWR_EN, 0); + gpio_request(MX6_BRD_FEC_PWR_EN, "fec-pwr"); + gpio_direction_output(MX6_BRD_FEC_PWR_EN, 0); /* wait RC ms for hw reset */ msleep(1); - gpio_direction_output(MX6_ARM2_FEC_PWR_EN, 1); + gpio_direction_output(MX6_BRD_FEC_PWR_EN, 1); /* check phy power */ val = phy_read(phydev, 0x0); @@ -704,109 +650,109 @@ static int epdc_get_pins(void) int ret = 0; /* Claim GPIOs for EPDC pins - used during power up/down */ - ret |= gpio_request(MX6SL_ARM2_EPDC_SDDO_0, "epdc_d0"); - ret |= gpio_request(MX6SL_ARM2_EPDC_SDDO_1, "epdc_d1"); - ret |= gpio_request(MX6SL_ARM2_EPDC_SDDO_2, "epdc_d2"); - ret |= gpio_request(MX6SL_ARM2_EPDC_SDDO_3, "epdc_d3"); - ret |= gpio_request(MX6SL_ARM2_EPDC_SDDO_4, "epdc_d4"); - ret |= gpio_request(MX6SL_ARM2_EPDC_SDDO_5, "epdc_d5"); - ret |= gpio_request(MX6SL_ARM2_EPDC_SDDO_6, "epdc_d6"); - ret |= gpio_request(MX6SL_ARM2_EPDC_SDDO_7, "epdc_d7"); - ret |= gpio_request(MX6SL_ARM2_EPDC_GDCLK, "epdc_gdclk"); - ret |= gpio_request(MX6SL_ARM2_EPDC_GDSP, "epdc_gdsp"); - ret |= gpio_request(MX6SL_ARM2_EPDC_GDOE, "epdc_gdoe"); - ret |= gpio_request(MX6SL_ARM2_EPDC_GDRL, "epdc_gdrl"); - ret |= gpio_request(MX6SL_ARM2_EPDC_SDCLK, "epdc_sdclk"); - ret |= gpio_request(MX6SL_ARM2_EPDC_SDOE, "epdc_sdoe"); - ret |= gpio_request(MX6SL_ARM2_EPDC_SDLE, "epdc_sdle"); - ret |= gpio_request(MX6SL_ARM2_EPDC_SDSHR, "epdc_sdshr"); - ret |= gpio_request(MX6SL_ARM2_EPDC_BDR0, "epdc_bdr0"); - ret |= gpio_request(MX6SL_ARM2_EPDC_SDCE0, "epdc_sdce0"); - ret |= gpio_request(MX6SL_ARM2_EPDC_SDCE1, "epdc_sdce1"); - ret |= gpio_request(MX6SL_ARM2_EPDC_SDCE2, "epdc_sdce2"); + ret |= gpio_request(MX6SL_BRD_EPDC_SDDO_0, "epdc_d0"); + ret |= gpio_request(MX6SL_BRD_EPDC_SDDO_1, "epdc_d1"); + ret |= gpio_request(MX6SL_BRD_EPDC_SDDO_2, "epdc_d2"); + ret |= gpio_request(MX6SL_BRD_EPDC_SDDO_3, "epdc_d3"); + ret |= gpio_request(MX6SL_BRD_EPDC_SDDO_4, "epdc_d4"); + ret |= gpio_request(MX6SL_BRD_EPDC_SDDO_5, "epdc_d5"); + ret |= gpio_request(MX6SL_BRD_EPDC_SDDO_6, "epdc_d6"); + ret |= gpio_request(MX6SL_BRD_EPDC_SDDO_7, "epdc_d7"); + ret |= gpio_request(MX6SL_BRD_EPDC_GDCLK, "epdc_gdclk"); + ret |= gpio_request(MX6SL_BRD_EPDC_GDSP, "epdc_gdsp"); + ret |= gpio_request(MX6SL_BRD_EPDC_GDOE, "epdc_gdoe"); + ret |= gpio_request(MX6SL_BRD_EPDC_GDRL, "epdc_gdrl"); + ret |= gpio_request(MX6SL_BRD_EPDC_SDCLK, "epdc_sdclk"); + ret |= gpio_request(MX6SL_BRD_EPDC_SDOE, "epdc_sdoe"); + ret |= gpio_request(MX6SL_BRD_EPDC_SDLE, "epdc_sdle"); + ret |= gpio_request(MX6SL_BRD_EPDC_SDSHR, "epdc_sdshr"); + ret |= gpio_request(MX6SL_BRD_EPDC_BDR0, "epdc_bdr0"); + ret |= gpio_request(MX6SL_BRD_EPDC_SDCE0, "epdc_sdce0"); + ret |= gpio_request(MX6SL_BRD_EPDC_SDCE1, "epdc_sdce1"); + ret |= gpio_request(MX6SL_BRD_EPDC_SDCE2, "epdc_sdce2"); return ret; } static void epdc_put_pins(void) { - gpio_free(MX6SL_ARM2_EPDC_SDDO_0); - gpio_free(MX6SL_ARM2_EPDC_SDDO_1); - gpio_free(MX6SL_ARM2_EPDC_SDDO_2); - gpio_free(MX6SL_ARM2_EPDC_SDDO_3); - gpio_free(MX6SL_ARM2_EPDC_SDDO_4); - gpio_free(MX6SL_ARM2_EPDC_SDDO_5); - gpio_free(MX6SL_ARM2_EPDC_SDDO_6); - gpio_free(MX6SL_ARM2_EPDC_SDDO_7); - gpio_free(MX6SL_ARM2_EPDC_GDCLK); - gpio_free(MX6SL_ARM2_EPDC_GDSP); - gpio_free(MX6SL_ARM2_EPDC_GDOE); - gpio_free(MX6SL_ARM2_EPDC_GDRL); - gpio_free(MX6SL_ARM2_EPDC_SDCLK); - gpio_free(MX6SL_ARM2_EPDC_SDOE); - gpio_free(MX6SL_ARM2_EPDC_SDLE); - gpio_free(MX6SL_ARM2_EPDC_SDSHR); - gpio_free(MX6SL_ARM2_EPDC_BDR0); - gpio_free(MX6SL_ARM2_EPDC_SDCE0); - gpio_free(MX6SL_ARM2_EPDC_SDCE1); - gpio_free(MX6SL_ARM2_EPDC_SDCE2); + gpio_free(MX6SL_BRD_EPDC_SDDO_0); + gpio_free(MX6SL_BRD_EPDC_SDDO_1); + gpio_free(MX6SL_BRD_EPDC_SDDO_2); + gpio_free(MX6SL_BRD_EPDC_SDDO_3); + gpio_free(MX6SL_BRD_EPDC_SDDO_4); + gpio_free(MX6SL_BRD_EPDC_SDDO_5); + gpio_free(MX6SL_BRD_EPDC_SDDO_6); + gpio_free(MX6SL_BRD_EPDC_SDDO_7); + gpio_free(MX6SL_BRD_EPDC_GDCLK); + gpio_free(MX6SL_BRD_EPDC_GDSP); + gpio_free(MX6SL_BRD_EPDC_GDOE); + gpio_free(MX6SL_BRD_EPDC_GDRL); + gpio_free(MX6SL_BRD_EPDC_SDCLK); + gpio_free(MX6SL_BRD_EPDC_SDOE); + gpio_free(MX6SL_BRD_EPDC_SDLE); + gpio_free(MX6SL_BRD_EPDC_SDSHR); + gpio_free(MX6SL_BRD_EPDC_BDR0); + gpio_free(MX6SL_BRD_EPDC_SDCE0); + gpio_free(MX6SL_BRD_EPDC_SDCE1); + gpio_free(MX6SL_BRD_EPDC_SDCE2); } static void epdc_enable_pins(void) { /* Configure MUX settings to enable EPDC use */ - mxc_iomux_v3_setup_multiple_pads(mx6sl_arm2_epdc_enable_pads, \ - ARRAY_SIZE(mx6sl_arm2_epdc_enable_pads)); - - gpio_direction_input(MX6SL_ARM2_EPDC_SDDO_0); - gpio_direction_input(MX6SL_ARM2_EPDC_SDDO_1); - gpio_direction_input(MX6SL_ARM2_EPDC_SDDO_2); - gpio_direction_input(MX6SL_ARM2_EPDC_SDDO_3); - gpio_direction_input(MX6SL_ARM2_EPDC_SDDO_4); - gpio_direction_input(MX6SL_ARM2_EPDC_SDDO_5); - gpio_direction_input(MX6SL_ARM2_EPDC_SDDO_6); - gpio_direction_input(MX6SL_ARM2_EPDC_SDDO_7); - gpio_direction_input(MX6SL_ARM2_EPDC_GDCLK); - gpio_direction_input(MX6SL_ARM2_EPDC_GDSP); - gpio_direction_input(MX6SL_ARM2_EPDC_GDOE); - gpio_direction_input(MX6SL_ARM2_EPDC_GDRL); - gpio_direction_input(MX6SL_ARM2_EPDC_SDCLK); - gpio_direction_input(MX6SL_ARM2_EPDC_SDOE); - gpio_direction_input(MX6SL_ARM2_EPDC_SDLE); - gpio_direction_input(MX6SL_ARM2_EPDC_SDSHR); - gpio_direction_input(MX6SL_ARM2_EPDC_BDR0); - gpio_direction_input(MX6SL_ARM2_EPDC_SDCE0); - gpio_direction_input(MX6SL_ARM2_EPDC_SDCE1); - gpio_direction_input(MX6SL_ARM2_EPDC_SDCE2); + mxc_iomux_v3_setup_multiple_pads(mx6sl_brd_epdc_enable_pads, \ + ARRAY_SIZE(mx6sl_brd_epdc_enable_pads)); + + gpio_direction_input(MX6SL_BRD_EPDC_SDDO_0); + gpio_direction_input(MX6SL_BRD_EPDC_SDDO_1); + gpio_direction_input(MX6SL_BRD_EPDC_SDDO_2); + gpio_direction_input(MX6SL_BRD_EPDC_SDDO_3); + gpio_direction_input(MX6SL_BRD_EPDC_SDDO_4); + gpio_direction_input(MX6SL_BRD_EPDC_SDDO_5); + gpio_direction_input(MX6SL_BRD_EPDC_SDDO_6); + gpio_direction_input(MX6SL_BRD_EPDC_SDDO_7); + gpio_direction_input(MX6SL_BRD_EPDC_GDCLK); + gpio_direction_input(MX6SL_BRD_EPDC_GDSP); + gpio_direction_input(MX6SL_BRD_EPDC_GDOE); + gpio_direction_input(MX6SL_BRD_EPDC_GDRL); + gpio_direction_input(MX6SL_BRD_EPDC_SDCLK); + gpio_direction_input(MX6SL_BRD_EPDC_SDOE); + gpio_direction_input(MX6SL_BRD_EPDC_SDLE); + gpio_direction_input(MX6SL_BRD_EPDC_SDSHR); + gpio_direction_input(MX6SL_BRD_EPDC_BDR0); + gpio_direction_input(MX6SL_BRD_EPDC_SDCE0); + gpio_direction_input(MX6SL_BRD_EPDC_SDCE1); + gpio_direction_input(MX6SL_BRD_EPDC_SDCE2); } static void epdc_disable_pins(void) { /* Configure MUX settings for EPDC pins to * GPIO and drive to 0. */ - mxc_iomux_v3_setup_multiple_pads(mx6sl_arm2_epdc_disable_pads, \ - ARRAY_SIZE(mx6sl_arm2_epdc_disable_pads)); - - gpio_direction_output(MX6SL_ARM2_EPDC_SDDO_0, 0); - gpio_direction_output(MX6SL_ARM2_EPDC_SDDO_1, 0); - gpio_direction_output(MX6SL_ARM2_EPDC_SDDO_2, 0); - gpio_direction_output(MX6SL_ARM2_EPDC_SDDO_3, 0); - gpio_direction_output(MX6SL_ARM2_EPDC_SDDO_4, 0); - gpio_direction_output(MX6SL_ARM2_EPDC_SDDO_5, 0); - gpio_direction_output(MX6SL_ARM2_EPDC_SDDO_6, 0); - gpio_direction_output(MX6SL_ARM2_EPDC_SDDO_7, 0); - gpio_direction_output(MX6SL_ARM2_EPDC_GDCLK, 0); - gpio_direction_output(MX6SL_ARM2_EPDC_GDSP, 0); - gpio_direction_output(MX6SL_ARM2_EPDC_GDOE, 0); - gpio_direction_output(MX6SL_ARM2_EPDC_GDRL, 0); - gpio_direction_output(MX6SL_ARM2_EPDC_SDCLK, 0); - gpio_direction_output(MX6SL_ARM2_EPDC_SDOE, 0); - gpio_direction_output(MX6SL_ARM2_EPDC_SDLE, 0); - gpio_direction_output(MX6SL_ARM2_EPDC_SDSHR, 0); - gpio_direction_output(MX6SL_ARM2_EPDC_BDR0, 0); - gpio_direction_output(MX6SL_ARM2_EPDC_SDCE0, 0); - gpio_direction_output(MX6SL_ARM2_EPDC_SDCE1, 0); - gpio_direction_output(MX6SL_ARM2_EPDC_SDCE2, 0); + mxc_iomux_v3_setup_multiple_pads(mx6sl_brd_epdc_disable_pads, \ + ARRAY_SIZE(mx6sl_brd_epdc_disable_pads)); + + gpio_direction_output(MX6SL_BRD_EPDC_SDDO_0, 0); + gpio_direction_output(MX6SL_BRD_EPDC_SDDO_1, 0); + gpio_direction_output(MX6SL_BRD_EPDC_SDDO_2, 0); + gpio_direction_output(MX6SL_BRD_EPDC_SDDO_3, 0); + gpio_direction_output(MX6SL_BRD_EPDC_SDDO_4, 0); + gpio_direction_output(MX6SL_BRD_EPDC_SDDO_5, 0); + gpio_direction_output(MX6SL_BRD_EPDC_SDDO_6, 0); + gpio_direction_output(MX6SL_BRD_EPDC_SDDO_7, 0); + gpio_direction_output(MX6SL_BRD_EPDC_GDCLK, 0); + gpio_direction_output(MX6SL_BRD_EPDC_GDSP, 0); + gpio_direction_output(MX6SL_BRD_EPDC_GDOE, 0); + gpio_direction_output(MX6SL_BRD_EPDC_GDRL, 0); + gpio_direction_output(MX6SL_BRD_EPDC_SDCLK, 0); + gpio_direction_output(MX6SL_BRD_EPDC_SDOE, 0); + gpio_direction_output(MX6SL_BRD_EPDC_SDLE, 0); + gpio_direction_output(MX6SL_BRD_EPDC_SDSHR, 0); + gpio_direction_output(MX6SL_BRD_EPDC_BDR0, 0); + gpio_direction_output(MX6SL_BRD_EPDC_SDCE0, 0); + gpio_direction_output(MX6SL_BRD_EPDC_SDCE1, 0); + gpio_direction_output(MX6SL_BRD_EPDC_SDCE2, 0); } static struct fb_videomode e60_v110_mode = { @@ -946,108 +892,108 @@ static int spdc_get_pins(void) int ret = 0; /* Claim GPIOs for SPDC pins - used during power up/down */ - ret |= gpio_request(MX6SL_ARM2_EPDC_SDDO_0, "SPDC_D0"); - ret |= gpio_request(MX6SL_ARM2_EPDC_SDDO_1, "SPDC_D1"); - ret |= gpio_request(MX6SL_ARM2_EPDC_SDDO_2, "SPDC_D2"); - ret |= gpio_request(MX6SL_ARM2_EPDC_SDDO_3, "SPDC_D3"); - ret |= gpio_request(MX6SL_ARM2_EPDC_SDDO_4, "SPDC_D4"); - ret |= gpio_request(MX6SL_ARM2_EPDC_SDDO_5, "SPDC_D5"); - ret |= gpio_request(MX6SL_ARM2_EPDC_SDDO_6, "SPDC_D6"); - ret |= gpio_request(MX6SL_ARM2_EPDC_SDDO_7, "SPDC_D7"); + ret |= gpio_request(MX6SL_BRD_EPDC_SDDO_0, "SPDC_D0"); + ret |= gpio_request(MX6SL_BRD_EPDC_SDDO_1, "SPDC_D1"); + ret |= gpio_request(MX6SL_BRD_EPDC_SDDO_2, "SPDC_D2"); + ret |= gpio_request(MX6SL_BRD_EPDC_SDDO_3, "SPDC_D3"); + ret |= gpio_request(MX6SL_BRD_EPDC_SDDO_4, "SPDC_D4"); + ret |= gpio_request(MX6SL_BRD_EPDC_SDDO_5, "SPDC_D5"); + ret |= gpio_request(MX6SL_BRD_EPDC_SDDO_6, "SPDC_D6"); + ret |= gpio_request(MX6SL_BRD_EPDC_SDDO_7, "SPDC_D7"); - ret |= gpio_request(MX6SL_ARM2_EPDC_GDOE, "SIPIX_YOE"); - ret |= gpio_request(MX6SL_ARM2_EPDC_SDDO_9, "SIPIX_PWR_RDY"); + ret |= gpio_request(MX6SL_BRD_EPDC_GDOE, "SIPIX_YOE"); + ret |= gpio_request(MX6SL_BRD_EPDC_SDDO_9, "SIPIX_PWR_RDY"); - ret |= gpio_request(MX6SL_ARM2_EPDC_GDSP, "SIPIX_YDIO"); + ret |= gpio_request(MX6SL_BRD_EPDC_GDSP, "SIPIX_YDIO"); - ret |= gpio_request(MX6SL_ARM2_EPDC_GDCLK, "SIPIX_YCLK"); - ret |= gpio_request(MX6SL_ARM2_EPDC_SDSHR, "SIPIX_XDIO"); + ret |= gpio_request(MX6SL_BRD_EPDC_GDCLK, "SIPIX_YCLK"); + ret |= gpio_request(MX6SL_BRD_EPDC_SDSHR, "SIPIX_XDIO"); - ret |= gpio_request(MX6SL_ARM2_EPDC_SDLE, "SIPIX_LD"); - ret |= gpio_request(MX6SL_ARM2_EPDC_SDCE1, "SIPIX_SOE"); + ret |= gpio_request(MX6SL_BRD_EPDC_SDLE, "SIPIX_LD"); + ret |= gpio_request(MX6SL_BRD_EPDC_SDCE1, "SIPIX_SOE"); - ret |= gpio_request(MX6SL_ARM2_EPDC_SDCLK, "SIPIX_XCLK"); - ret |= gpio_request(MX6SL_ARM2_EPDC_SDDO_10, "SIPIX_SHD_N"); - ret |= gpio_request(MX6SL_ARM2_EPDC_SDCE0, "SIPIX2_CE"); + ret |= gpio_request(MX6SL_BRD_EPDC_SDCLK, "SIPIX_XCLK"); + ret |= gpio_request(MX6SL_BRD_EPDC_SDDO_10, "SIPIX_SHD_N"); + ret |= gpio_request(MX6SL_BRD_EPDC_SDCE0, "SIPIX2_CE"); return ret; } static void spdc_put_pins(void) { - gpio_free(MX6SL_ARM2_EPDC_SDDO_0); - gpio_free(MX6SL_ARM2_EPDC_SDDO_1); - gpio_free(MX6SL_ARM2_EPDC_SDDO_2); - gpio_free(MX6SL_ARM2_EPDC_SDDO_3); - gpio_free(MX6SL_ARM2_EPDC_SDDO_4); - gpio_free(MX6SL_ARM2_EPDC_SDDO_5); - gpio_free(MX6SL_ARM2_EPDC_SDDO_6); - gpio_free(MX6SL_ARM2_EPDC_SDDO_7); - - gpio_free(MX6SL_ARM2_EPDC_GDOE); - gpio_free(MX6SL_ARM2_EPDC_SDDO_9); - gpio_free(MX6SL_ARM2_EPDC_GDSP); - gpio_free(MX6SL_ARM2_EPDC_GDCLK); - gpio_free(MX6SL_ARM2_EPDC_SDSHR); - gpio_free(MX6SL_ARM2_EPDC_SDLE); - gpio_free(MX6SL_ARM2_EPDC_SDCE1); - gpio_free(MX6SL_ARM2_EPDC_SDCLK); - gpio_free(MX6SL_ARM2_EPDC_SDDO_10); - gpio_free(MX6SL_ARM2_EPDC_SDCE0); + gpio_free(MX6SL_BRD_EPDC_SDDO_0); + gpio_free(MX6SL_BRD_EPDC_SDDO_1); + gpio_free(MX6SL_BRD_EPDC_SDDO_2); + gpio_free(MX6SL_BRD_EPDC_SDDO_3); + gpio_free(MX6SL_BRD_EPDC_SDDO_4); + gpio_free(MX6SL_BRD_EPDC_SDDO_5); + gpio_free(MX6SL_BRD_EPDC_SDDO_6); + gpio_free(MX6SL_BRD_EPDC_SDDO_7); + + gpio_free(MX6SL_BRD_EPDC_GDOE); + gpio_free(MX6SL_BRD_EPDC_SDDO_9); + gpio_free(MX6SL_BRD_EPDC_GDSP); + gpio_free(MX6SL_BRD_EPDC_GDCLK); + gpio_free(MX6SL_BRD_EPDC_SDSHR); + gpio_free(MX6SL_BRD_EPDC_SDLE); + gpio_free(MX6SL_BRD_EPDC_SDCE1); + gpio_free(MX6SL_BRD_EPDC_SDCLK); + gpio_free(MX6SL_BRD_EPDC_SDDO_10); + gpio_free(MX6SL_BRD_EPDC_SDCE0); } static void spdc_enable_pins(void) { /* Configure MUX settings to enable SPDC use */ - mxc_iomux_v3_setup_multiple_pads(mx6sl_arm2_spdc_enable_pads, \ - ARRAY_SIZE(mx6sl_arm2_spdc_enable_pads)); - - gpio_direction_input(MX6SL_ARM2_EPDC_SDDO_0); - gpio_direction_input(MX6SL_ARM2_EPDC_SDDO_1); - gpio_direction_input(MX6SL_ARM2_EPDC_SDDO_2); - gpio_direction_input(MX6SL_ARM2_EPDC_SDDO_3); - gpio_direction_input(MX6SL_ARM2_EPDC_SDDO_4); - gpio_direction_input(MX6SL_ARM2_EPDC_SDDO_5); - gpio_direction_input(MX6SL_ARM2_EPDC_SDDO_6); - gpio_direction_input(MX6SL_ARM2_EPDC_SDDO_7); - gpio_direction_input(MX6SL_ARM2_EPDC_GDOE); - gpio_direction_input(MX6SL_ARM2_EPDC_SDDO_9); - gpio_direction_input(MX6SL_ARM2_EPDC_GDSP); - gpio_direction_input(MX6SL_ARM2_EPDC_GDCLK); - gpio_direction_input(MX6SL_ARM2_EPDC_SDSHR); - gpio_direction_input(MX6SL_ARM2_EPDC_SDLE); - gpio_direction_input(MX6SL_ARM2_EPDC_SDCE1); - gpio_direction_input(MX6SL_ARM2_EPDC_SDCLK); - gpio_direction_input(MX6SL_ARM2_EPDC_SDDO_10); - gpio_direction_input(MX6SL_ARM2_EPDC_SDCE0); + mxc_iomux_v3_setup_multiple_pads(mx6sl_brd_spdc_enable_pads, \ + ARRAY_SIZE(mx6sl_brd_spdc_enable_pads)); + + gpio_direction_input(MX6SL_BRD_EPDC_SDDO_0); + gpio_direction_input(MX6SL_BRD_EPDC_SDDO_1); + gpio_direction_input(MX6SL_BRD_EPDC_SDDO_2); + gpio_direction_input(MX6SL_BRD_EPDC_SDDO_3); + gpio_direction_input(MX6SL_BRD_EPDC_SDDO_4); + gpio_direction_input(MX6SL_BRD_EPDC_SDDO_5); + gpio_direction_input(MX6SL_BRD_EPDC_SDDO_6); + gpio_direction_input(MX6SL_BRD_EPDC_SDDO_7); + gpio_direction_input(MX6SL_BRD_EPDC_GDOE); + gpio_direction_input(MX6SL_BRD_EPDC_SDDO_9); + gpio_direction_input(MX6SL_BRD_EPDC_GDSP); + gpio_direction_input(MX6SL_BRD_EPDC_GDCLK); + gpio_direction_input(MX6SL_BRD_EPDC_SDSHR); + gpio_direction_input(MX6SL_BRD_EPDC_SDLE); + gpio_direction_input(MX6SL_BRD_EPDC_SDCE1); + gpio_direction_input(MX6SL_BRD_EPDC_SDCLK); + gpio_direction_input(MX6SL_BRD_EPDC_SDDO_10); + gpio_direction_input(MX6SL_BRD_EPDC_SDCE0); } static void spdc_disable_pins(void) { /* Configure MUX settings for SPDC pins to * GPIO and drive to 0. */ - mxc_iomux_v3_setup_multiple_pads(mx6sl_arm2_spdc_disable_pads, \ - ARRAY_SIZE(mx6sl_arm2_spdc_disable_pads)); - - gpio_direction_output(MX6SL_ARM2_EPDC_SDDO_0, 0); - gpio_direction_output(MX6SL_ARM2_EPDC_SDDO_1, 0); - gpio_direction_output(MX6SL_ARM2_EPDC_SDDO_2, 0); - gpio_direction_output(MX6SL_ARM2_EPDC_SDDO_3, 0); - gpio_direction_output(MX6SL_ARM2_EPDC_SDDO_4, 0); - gpio_direction_output(MX6SL_ARM2_EPDC_SDDO_5, 0); - gpio_direction_output(MX6SL_ARM2_EPDC_SDDO_6, 0); - gpio_direction_output(MX6SL_ARM2_EPDC_SDDO_7, 0); - - gpio_direction_output(MX6SL_ARM2_EPDC_GDOE, 0); - gpio_direction_output(MX6SL_ARM2_EPDC_SDDO_9, 0); - gpio_direction_output(MX6SL_ARM2_EPDC_GDSP, 0); - gpio_direction_output(MX6SL_ARM2_EPDC_GDCLK, 0); - gpio_direction_output(MX6SL_ARM2_EPDC_SDSHR, 0); - gpio_direction_output(MX6SL_ARM2_EPDC_SDLE, 0); - gpio_direction_output(MX6SL_ARM2_EPDC_SDCE1, 0); - gpio_direction_output(MX6SL_ARM2_EPDC_SDCLK, 0); - gpio_direction_output(MX6SL_ARM2_EPDC_SDDO_10, 0); - gpio_direction_output(MX6SL_ARM2_EPDC_SDCE0, 0); + mxc_iomux_v3_setup_multiple_pads(mx6sl_brd_spdc_disable_pads, \ + ARRAY_SIZE(mx6sl_brd_spdc_disable_pads)); + + gpio_direction_output(MX6SL_BRD_EPDC_SDDO_0, 0); + gpio_direction_output(MX6SL_BRD_EPDC_SDDO_1, 0); + gpio_direction_output(MX6SL_BRD_EPDC_SDDO_2, 0); + gpio_direction_output(MX6SL_BRD_EPDC_SDDO_3, 0); + gpio_direction_output(MX6SL_BRD_EPDC_SDDO_4, 0); + gpio_direction_output(MX6SL_BRD_EPDC_SDDO_5, 0); + gpio_direction_output(MX6SL_BRD_EPDC_SDDO_6, 0); + gpio_direction_output(MX6SL_BRD_EPDC_SDDO_7, 0); + + gpio_direction_output(MX6SL_BRD_EPDC_GDOE, 0); + gpio_direction_output(MX6SL_BRD_EPDC_SDDO_9, 0); + gpio_direction_output(MX6SL_BRD_EPDC_GDSP, 0); + gpio_direction_output(MX6SL_BRD_EPDC_GDCLK, 0); + gpio_direction_output(MX6SL_BRD_EPDC_SDSHR, 0); + gpio_direction_output(MX6SL_BRD_EPDC_SDLE, 0); + gpio_direction_output(MX6SL_BRD_EPDC_SDCE1, 0); + gpio_direction_output(MX6SL_BRD_EPDC_SDCLK, 0); + gpio_direction_output(MX6SL_BRD_EPDC_SDDO_10, 0); + gpio_direction_output(MX6SL_BRD_EPDC_SDCE0, 0); } static struct imx_spdc_panel_init_set spdc_init_set = { @@ -1105,9 +1051,9 @@ static void setup_spdc(void) static void imx6_arm2_usbotg_vbus(bool on) { if (on) - gpio_set_value(MX6_ARM2_USBOTG1_PWR, 1); + gpio_set_value(MX6_BRD_USBOTG1_PWR, 1); else - gpio_set_value(MX6_ARM2_USBOTG1_PWR, 0); + gpio_set_value(MX6_BRD_USBOTG1_PWR, 0); } static void __init mx6_arm2_init_usb(void) @@ -1120,23 +1066,28 @@ static void __init mx6_arm2_init_usb(void) * or it will affect signal quality at dp. */ - ret = gpio_request(MX6_ARM2_USBOTG1_PWR, "usbotg-pwr"); + ret = gpio_request(MX6_BRD_USBOTG1_PWR, "usbotg-pwr"); if (ret) { - pr_err("failed to get GPIO MX6_ARM2_USBOTG1_PWR:%d\n", ret); + pr_err("failed to get GPIO MX6_BRD_USBOTG1_PWR:%d\n", ret); return; } - gpio_direction_output(MX6_ARM2_USBOTG1_PWR, 0); + gpio_direction_output(MX6_BRD_USBOTG1_PWR, 0); - ret = gpio_request(MX6_ARM2_USBOTG2_PWR, "usbh1-pwr"); + ret = gpio_request(MX6_BRD_USBOTG2_PWR, "usbh1-pwr"); if (ret) { - pr_err("failed to get GPIO MX6_ARM2_USBOTG2_PWR:%d\n", ret); + pr_err("failed to get GPIO MX6_BRD_USBOTG2_PWR:%d\n", ret); return; } - gpio_direction_output(MX6_ARM2_USBOTG2_PWR, 1); + gpio_direction_output(MX6_BRD_USBOTG2_PWR, 1); mx6_set_otghost_vbus_func(imx6_arm2_usbotg_vbus); mx6_usb_dr_init(); #ifdef CONFIG_USB_EHCI_ARC_HSIC + mxc_iomux_set_specialbits_register(MX6SL_PAD_HSIC_DAT, + PAD_CTL_DDR_SEL_DDR3, PAD_CTL_DDR_SEL_MASK); + mxc_iomux_set_specialbits_register(MX6SL_PAD_HSIC_STROBE, + PAD_CTL_DDR_SEL_DDR3, PAD_CTL_DDR_SEL_MASK); + mx6_usb_h2_init(); #endif } @@ -1197,23 +1148,23 @@ static const struct matrix_keymap_data mx6sl_arm2_map_data __initconst = { }; static void __init elan_ts_init(void) { - mxc_iomux_v3_setup_multiple_pads(mx6sl_arm2_elan_pads, - ARRAY_SIZE(mx6sl_arm2_elan_pads)); + mxc_iomux_v3_setup_multiple_pads(mx6sl_brd_elan_pads, + ARRAY_SIZE(mx6sl_brd_elan_pads)); /* ELAN Touchscreen */ - gpio_request(MX6SL_ARM2_ELAN_INT, "elan-interrupt"); - gpio_direction_input(MX6SL_ARM2_ELAN_INT); + gpio_request(MX6SL_BRD_ELAN_INT, "elan-interrupt"); + gpio_direction_input(MX6SL_BRD_ELAN_INT); - gpio_request(MX6SL_ARM2_ELAN_CE, "elan-cs"); - gpio_direction_output(MX6SL_ARM2_ELAN_CE, 1); - gpio_direction_output(MX6SL_ARM2_ELAN_CE, 0); + gpio_request(MX6SL_BRD_ELAN_CE, "elan-cs"); + gpio_direction_output(MX6SL_BRD_ELAN_CE, 1); + gpio_direction_output(MX6SL_BRD_ELAN_CE, 0); - gpio_request(MX6SL_ARM2_ELAN_RST, "elan-rst"); - gpio_direction_output(MX6SL_ARM2_ELAN_RST, 1); - gpio_direction_output(MX6SL_ARM2_ELAN_RST, 0); + gpio_request(MX6SL_BRD_ELAN_RST, "elan-rst"); + gpio_direction_output(MX6SL_BRD_ELAN_RST, 1); + gpio_direction_output(MX6SL_BRD_ELAN_RST, 0); mdelay(1); - gpio_direction_output(MX6SL_ARM2_ELAN_RST, 1); - gpio_direction_output(MX6SL_ARM2_ELAN_CE, 1); + gpio_direction_output(MX6SL_BRD_ELAN_RST, 1); + gpio_direction_output(MX6SL_BRD_ELAN_CE, 1); } #define SNVS_LPCR 0x38 @@ -1232,18 +1183,20 @@ static void mx6_snvs_poweroff(void) */ static void __init mx6_arm2_init(void) { - mxc_iomux_v3_setup_multiple_pads(mx6sl_arm2_pads, ARRAY_SIZE(mx6sl_arm2_pads)); + mxc_iomux_v3_setup_multiple_pads(mx6sl_brd_pads, + ARRAY_SIZE(mx6sl_brd_pads)); elan_ts_init(); - #ifdef CONFIG_MX6_INTER_LDO_BYPASS +#ifdef CONFIG_MX6_INTER_LDO_BYPASS gp_reg_id = mx6sl_arm2_dvfscore_data.reg_id; - #else + soc_reg_id = mx6sl_arm2_dvfscore_data.soc_id; +#else gp_reg_id = mx6sl_arm2_dvfscore_data.reg_id; soc_reg_id = mx6sl_arm2_dvfscore_data.soc_id; pu_reg_id = mx6sl_arm2_dvfscore_data.pu_id; mx6_cpu_regulator_init(); - #endif +#endif imx6q_add_imx_snvs_rtc(); @@ -1285,8 +1238,8 @@ static void __init mx6_arm2_init(void) imx6q_add_mxc_pwm_backlight(0, &mx6_arm2_pwm_backlight_data); imx6dl_add_imx_elcdif(&fb_data[0]); - gpio_request(MX6_ARM2_LCD_PWR_EN, "elcdif-power-on"); - gpio_direction_output(MX6_ARM2_LCD_PWR_EN, 1); + gpio_request(MX6_BRD_LCD_PWR_EN, "elcdif-power-on"); + gpio_direction_output(MX6_BRD_LCD_PWR_EN, 1); mxc_register_device(&lcd_wvga_device, NULL); imx6dl_add_imx_pxp(); @@ -1309,6 +1262,11 @@ static void __init mx6_arm2_init(void) imx6q_add_busfreq(); imx6sl_add_dcp(); imx6sl_add_rngb(); + imx6sl_add_imx_pxp_v4l2(); + + imx6q_add_perfmon(0); + imx6q_add_perfmon(1); + imx6q_add_perfmon(2); pm_power_off = mx6_snvs_poweroff; } diff --git a/arch/arm/mach-mx6/board-mx6sl_arm2.h b/arch/arm/mach-mx6/board-mx6sl_common.h index 09a211690029..d005e02cb6ac 100755..100644 --- a/arch/arm/mach-mx6/board-mx6sl_arm2.h +++ b/arch/arm/mach-mx6/board-mx6sl_common.h @@ -16,11 +16,68 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#ifndef _BOARD_MX6SL_ARM2_H -#define _BOARD_MX6SL_ARM2_H +#ifndef _BOARD_MX6SL_COMMON_H +#define _BOARD_MX6SL_COMMON_H #include <mach/iomux-mx6sl.h> -static iomux_v3_cfg_t mx6sl_arm2_pads[] = { +#define MX6_BRD_USBOTG1_PWR IMX_GPIO_NR(4, 0) /* KEY_COL4 */ +#define MX6_BRD_USBOTG2_PWR IMX_GPIO_NR(4, 2) /* KEY_COL5 */ +#define MX6_BRD_LCD_PWR_EN IMX_GPIO_NR(4, 3) /* KEY_ROW5 */ +#define MX6_BRD_SD1_WP IMX_GPIO_NR(4, 6) /* KEY_COL7 */ +#define MX6_BRD_SD1_CD IMX_GPIO_NR(4, 7) /* KEY_ROW7 */ +#define MX6_BRD_ECSPI1_CS0 IMX_GPIO_NR(4, 11) /* ECSPI1_SS0 */ +#define MX6_BRD_HEADPHONE_DET IMX_GPIO_NR(4, 19) /* FEC_RX_ER */ +#define MX6_BRD_SD2_WP IMX_GPIO_NR(4, 29) /* SD2_DAT6 */ +#define MX6_BRD_SD2_CD IMX_GPIO_NR(5, 0) /* SD2_DAT7 */ +#define MX6_BRD_SD3_CD IMX_GPIO_NR(3, 22) /* REF_CLK_32K */ +#define MX6_BRD_FEC_PWR_EN IMX_GPIO_NR(4, 21) /* FEC_TX_CLK */ + +/* EPDC GPIO pins */ +#define MX6SL_BRD_EPDC_SDDO_0 IMX_GPIO_NR(1, 7) +#define MX6SL_BRD_EPDC_SDDO_1 IMX_GPIO_NR(1, 8) +#define MX6SL_BRD_EPDC_SDDO_2 IMX_GPIO_NR(1, 9) +#define MX6SL_BRD_EPDC_SDDO_3 IMX_GPIO_NR(1, 10) +#define MX6SL_BRD_EPDC_SDDO_4 IMX_GPIO_NR(1, 11) +#define MX6SL_BRD_EPDC_SDDO_5 IMX_GPIO_NR(1, 12) +#define MX6SL_BRD_EPDC_SDDO_6 IMX_GPIO_NR(1, 13) +#define MX6SL_BRD_EPDC_SDDO_7 IMX_GPIO_NR(1, 14) +#define MX6SL_BRD_EPDC_SDDO_8 IMX_GPIO_NR(1, 15) +#define MX6SL_BRD_EPDC_SDDO_9 IMX_GPIO_NR(1, 16) +#define MX6SL_BRD_EPDC_SDDO_10 IMX_GPIO_NR(1, 17) +#define MX6SL_BRD_EPDC_SDDO_11 IMX_GPIO_NR(1, 18) +#define MX6SL_BRD_EPDC_SDDO_12 IMX_GPIO_NR(1, 19) +#define MX6SL_BRD_EPDC_SDDO_13 IMX_GPIO_NR(1, 20) +#define MX6SL_BRD_EPDC_SDDO_14 IMX_GPIO_NR(1, 21) +#define MX6SL_BRD_EPDC_SDDO_15 IMX_GPIO_NR(1, 22) +#define MX6SL_BRD_EPDC_GDCLK IMX_GPIO_NR(1, 31) +#define MX6SL_BRD_EPDC_GDSP IMX_GPIO_NR(2, 2) +#define MX6SL_BRD_EPDC_GDOE IMX_GPIO_NR(2, 0) +#define MX6SL_BRD_EPDC_GDRL IMX_GPIO_NR(2, 1) +#define MX6SL_BRD_EPDC_SDCLK IMX_GPIO_NR(1, 23) +#define MX6SL_BRD_EPDC_SDOE IMX_GPIO_NR(1, 25) +#define MX6SL_BRD_EPDC_SDLE IMX_GPIO_NR(1, 24) +#define MX6SL_BRD_EPDC_SDSHR IMX_GPIO_NR(1, 26) +#define MX6SL_BRD_EPDC_PWRCOM IMX_GPIO_NR(2, 11) +#define MX6SL_BRD_EPDC_PWRSTAT IMX_GPIO_NR(2, 13) +#define MX6SL_BRD_EPDC_PWRCTRL0 IMX_GPIO_NR(2, 7) +#define MX6SL_BRD_EPDC_PWRCTRL1 IMX_GPIO_NR(2, 8) +#define MX6SL_BRD_EPDC_PWRCTRL2 IMX_GPIO_NR(2, 9) +#define MX6SL_BRD_EPDC_PWRCTRL3 IMX_GPIO_NR(2, 10) +#define MX6SL_BRD_EPDC_BDR0 IMX_GPIO_NR(2, 5) +#define MX6SL_BRD_EPDC_BDR1 IMX_GPIO_NR(2, 6) +#define MX6SL_BRD_EPDC_SDCE0 IMX_GPIO_NR(1, 27) +#define MX6SL_BRD_EPDC_SDCE1 IMX_GPIO_NR(1, 28) +#define MX6SL_BRD_EPDC_SDCE2 IMX_GPIO_NR(1, 29) +#define MX6SL_BRD_EPDC_SDCE3 IMX_GPIO_NR(1, 30) +#define MX6SL_BRD_EPDC_PMIC_WAKE IMX_GPIO_NR(2, 14) /* EPDC_PWRWAKEUP */ +#define MX6SL_BRD_EPDC_PMIC_INT IMX_GPIO_NR(2, 12) /* EPDC_PWRINT */ +#define MX6SL_BRD_EPDC_VCOM IMX_GPIO_NR(2, 3) +/* ELAN TS */ +#define MX6SL_BRD_ELAN_CE IMX_GPIO_NR(2, 9) +#define MX6SL_BRD_ELAN_INT IMX_GPIO_NR(2, 10) +#define MX6SL_BRD_ELAN_RST IMX_GPIO_NR(4, 4) + +static iomux_v3_cfg_t mx6sl_brd_pads[] = { /* AUDMUX */ MX6SL_PAD_AUD_TXC__AUDMUX_AUD3_TXC, @@ -158,7 +215,7 @@ static iomux_v3_cfg_t mx6sl_arm2_pads[] = { MX6SL_PAD_WDOG_B__WDOG1_WDOG_B, }; -static iomux_v3_cfg_t mx6sl_arm2_epdc_enable_pads[] = { +static iomux_v3_cfg_t mx6sl_brd_epdc_enable_pads[] = { /* EPDC */ MX6SL_PAD_EPDC_D0__EPDC_SDDO_0, MX6SL_PAD_EPDC_D1__EPDC_SDDO_1, @@ -197,7 +254,7 @@ static iomux_v3_cfg_t mx6sl_arm2_epdc_enable_pads[] = { MX6SL_PAD_EPDC_PWRWAKEUP__GPIO_2_14, }; -static iomux_v3_cfg_t mx6sl_arm2_epdc_disable_pads[] = { +static iomux_v3_cfg_t mx6sl_brd_epdc_disable_pads[] = { /* EPDC */ MX6SL_PAD_EPDC_D0__GPIO_1_7, MX6SL_PAD_EPDC_D1__GPIO_1_8, @@ -236,7 +293,7 @@ static iomux_v3_cfg_t mx6sl_arm2_epdc_disable_pads[] = { MX6SL_PAD_EPDC_PWRWAKEUP__GPIO_2_14, }; -static iomux_v3_cfg_t mx6sl_arm2_spdc_enable_pads[] = { +static iomux_v3_cfg_t mx6sl_brd_spdc_enable_pads[] = { /* SPDC data*/ MX6SL_PAD_EPDC_D0__TCON_E_DATA_0, MX6SL_PAD_EPDC_D1__TCON_E_DATA_1, @@ -280,7 +337,7 @@ static iomux_v3_cfg_t mx6sl_arm2_spdc_enable_pads[] = { MX6SL_PAD_EPDC_PWRWAKEUP__GPIO_2_14, }; -static iomux_v3_cfg_t mx6sl_arm2_spdc_disable_pads[] = { +static iomux_v3_cfg_t mx6sl_brd_spdc_disable_pads[] = { MX6SL_PAD_EPDC_D0__GPIO_1_7, MX6SL_PAD_EPDC_D1__GPIO_1_8, MX6SL_PAD_EPDC_D2__GPIO_1_9, @@ -315,7 +372,7 @@ static iomux_v3_cfg_t mx6sl_arm2_spdc_disable_pads[] = { MX6SL_PAD_EPDC_PWRWAKEUP__GPIO_2_14, }; -static iomux_v3_cfg_t mx6sl_arm2_elan_pads[] = { +static iomux_v3_cfg_t mx6sl_brd_elan_pads[] = { MX6SL_PAD_EPDC_PWRCTRL3__GPIO_2_10, /* INT */ MX6SL_PAD_EPDC_PWRCTRL2__GPIO_2_9, /* CE */ MX6SL_PAD_KEY_COL6__GPIO_4_4, /* RST */ diff --git a/arch/arm/mach-mx6/board-mx6sl_evk.c b/arch/arm/mach-mx6/board-mx6sl_evk.c new file mode 100644 index 000000000000..81654a0c99fd --- /dev/null +++ b/arch/arm/mach-mx6/board-mx6sl_evk.c @@ -0,0 +1,1320 @@ +/* + * Copyright (C) 2012 Freescale Semiconductor, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include <linux/types.h> +#include <linux/sched.h> +#include <linux/delay.h> +#include <linux/pm.h> +#include <linux/interrupt.h> +#include <linux/irq.h> +#include <linux/init.h> +#include <linux/input.h> +#include <linux/nodemask.h> +#include <linux/clk.h> +#include <linux/platform_device.h> +#include <linux/fsl_devices.h> +#include <linux/smsc911x.h> +#include <linux/spi/spi.h> +#include <linux/spi/flash.h> +#include <linux/i2c.h> +#include <linux/i2c/pca953x.h> +#include <linux/ata.h> +#include <linux/mtd/mtd.h> +#include <linux/mtd/map.h> +#include <linux/mtd/partitions.h> +#include <linux/pmic_external.h> +#include <linux/pmic_status.h> +#include <linux/mxcfb.h> +#include <linux/pwm_backlight.h> +#include <linux/fec.h> +#include <linux/memblock.h> +#include <linux/gpio.h> +#include <linux/etherdevice.h> +#include <linux/regulator/anatop-regulator.h> +#include <linux/regulator/consumer.h> +#include <linux/regulator/machine.h> +#include <linux/regulator/fixed.h> +#include <linux/mfd/max17135.h> +#include <sound/wm8962.h> +#include <sound/pcm.h> + +#include <mach/common.h> +#include <mach/hardware.h> +#include <mach/mxc_dvfs.h> +#include <mach/memory.h> +#include <mach/iomux-mx6sl.h> +#include <mach/imx-uart.h> +#include <mach/viv_gpu.h> + +#include <asm/irq.h> +#include <asm/setup.h> +#include <asm/mach-types.h> +#include <asm/mach/arch.h> +#include <asm/mach/time.h> + +#include "usb.h" +#include "devices-imx6q.h" +#include "crm_regs.h" +#include "cpu_op-mx6.h" +#include "board-mx6sl_common.h" + + +static int spdc_sel; +static int max17135_regulator_init(struct max17135 *max17135); +struct clk *extern_audio_root; + +extern char *gp_reg_id; +extern char *soc_reg_id; +extern char *pu_reg_id; +extern int __init mx6sl_evk_init_pfuze100(u32 int_gpio); + +enum sd_pad_mode { + SD_PAD_MODE_LOW_SPEED, + SD_PAD_MODE_MED_SPEED, + SD_PAD_MODE_HIGH_SPEED, +}; + +static int plt_sd_pad_change(unsigned int index, int clock) +{ + /* LOW speed is the default state of SD pads */ + static enum sd_pad_mode pad_mode = SD_PAD_MODE_LOW_SPEED; + + iomux_v3_cfg_t *sd_pads_200mhz = NULL; + iomux_v3_cfg_t *sd_pads_100mhz = NULL; + iomux_v3_cfg_t *sd_pads_50mhz = NULL; + + u32 sd_pads_200mhz_cnt; + u32 sd_pads_100mhz_cnt; + u32 sd_pads_50mhz_cnt; + + switch (index) { + case 0: + sd_pads_200mhz = mx6sl_sd1_200mhz; + sd_pads_100mhz = mx6sl_sd1_100mhz; + sd_pads_50mhz = mx6sl_sd1_50mhz; + + sd_pads_200mhz_cnt = ARRAY_SIZE(mx6sl_sd1_200mhz); + sd_pads_100mhz_cnt = ARRAY_SIZE(mx6sl_sd1_100mhz); + sd_pads_50mhz_cnt = ARRAY_SIZE(mx6sl_sd1_50mhz); + break; + case 1: + sd_pads_200mhz = mx6sl_sd2_200mhz; + sd_pads_100mhz = mx6sl_sd2_100mhz; + sd_pads_50mhz = mx6sl_sd2_50mhz; + + sd_pads_200mhz_cnt = ARRAY_SIZE(mx6sl_sd2_200mhz); + sd_pads_100mhz_cnt = ARRAY_SIZE(mx6sl_sd2_100mhz); + sd_pads_50mhz_cnt = ARRAY_SIZE(mx6sl_sd2_50mhz); + break; + case 2: + sd_pads_200mhz = mx6sl_sd3_200mhz; + sd_pads_100mhz = mx6sl_sd3_100mhz; + sd_pads_50mhz = mx6sl_sd3_50mhz; + + sd_pads_200mhz_cnt = ARRAY_SIZE(mx6sl_sd3_200mhz); + sd_pads_100mhz_cnt = ARRAY_SIZE(mx6sl_sd3_100mhz); + sd_pads_50mhz_cnt = ARRAY_SIZE(mx6sl_sd3_50mhz); + break; + default: + printk(KERN_ERR "no such SD host controller index %d\n", index); + return -EINVAL; + } + + if (clock > 100000000) { + if (pad_mode == SD_PAD_MODE_HIGH_SPEED) + return 0; + BUG_ON(!sd_pads_200mhz); + pad_mode = SD_PAD_MODE_HIGH_SPEED; + return mxc_iomux_v3_setup_multiple_pads(sd_pads_200mhz, + sd_pads_200mhz_cnt); + } else if (clock > 52000000) { + if (pad_mode == SD_PAD_MODE_MED_SPEED) + return 0; + BUG_ON(!sd_pads_100mhz); + pad_mode = SD_PAD_MODE_MED_SPEED; + return mxc_iomux_v3_setup_multiple_pads(sd_pads_100mhz, + sd_pads_100mhz_cnt); + } else { + if (pad_mode == SD_PAD_MODE_LOW_SPEED) + return 0; + BUG_ON(!sd_pads_50mhz); + pad_mode = SD_PAD_MODE_LOW_SPEED; + return mxc_iomux_v3_setup_multiple_pads(sd_pads_50mhz, + sd_pads_50mhz_cnt); + } +} + +static const struct esdhc_platform_data mx6_evk_sd1_data __initconst = { + .cd_gpio = MX6_BRD_SD1_CD, + .wp_gpio = MX6_BRD_SD1_WP, + .support_8bit = 1, + .support_18v = 1, + .keep_power_at_suspend = 1, + .delay_line = 0, + .platform_pad_change = plt_sd_pad_change, +}; + +static const struct esdhc_platform_data mx6_evk_sd2_data __initconst = { + .cd_gpio = MX6_BRD_SD2_CD, + .wp_gpio = MX6_BRD_SD2_WP, + .keep_power_at_suspend = 1, + .delay_line = 0, + .support_18v = 1, + .platform_pad_change = plt_sd_pad_change, +}; + +static const struct esdhc_platform_data mx6_evk_sd3_data __initconst = { + .cd_gpio = MX6_BRD_SD3_CD, + .wp_gpio = -1, + .keep_power_at_suspend = 1, + .delay_line = 0, + .support_18v = 1, + .platform_pad_change = plt_sd_pad_change, +}; + +#define mV_to_uV(mV) (mV * 1000) +#define uV_to_mV(uV) (uV / 1000) +#define V_to_uV(V) (mV_to_uV(V * 1000)) +#define uV_to_V(uV) (uV_to_mV(uV) / 1000) + +static struct regulator_consumer_supply evk_vmmc_consumers[] = { + REGULATOR_SUPPLY("vmmc", "sdhci-esdhc-imx.0"), + REGULATOR_SUPPLY("vmmc", "sdhci-esdhc-imx.1"), + REGULATOR_SUPPLY("vmmc", "sdhci-esdhc-imx.2"), +}; + +static struct regulator_init_data evk_vmmc_init = { + .num_consumer_supplies = ARRAY_SIZE(evk_vmmc_consumers), + .consumer_supplies = evk_vmmc_consumers, +}; + +static struct fixed_voltage_config evk_vmmc_reg_config = { + .supply_name = "vmmc", + .microvolts = 3300000, + .gpio = -1, + .init_data = &evk_vmmc_init, +}; + +static struct platform_device evk_vmmc_reg_devices = { + .name = "reg-fixed-voltage", + .id = 0, + .dev = { + .platform_data = &evk_vmmc_reg_config, + }, +}; + +static struct regulator_consumer_supply display_consumers[] = { + { + /* MAX17135 */ + .supply = "DISPLAY", + }, +}; + +static struct regulator_consumer_supply vcom_consumers[] = { + { + /* MAX17135 */ + .supply = "VCOM", + }, +}; + +static struct regulator_consumer_supply v3p3_consumers[] = { + { + /* MAX17135 */ + .supply = "V3P3", + }, +}; + +static struct regulator_init_data max17135_init_data[] = { + { + .constraints = { + .name = "DISPLAY", + .valid_ops_mask = REGULATOR_CHANGE_STATUS, + }, + .num_consumer_supplies = ARRAY_SIZE(display_consumers), + .consumer_supplies = display_consumers, + }, { + .constraints = { + .name = "GVDD", + .min_uV = V_to_uV(20), + .max_uV = V_to_uV(20), + }, + }, { + .constraints = { + .name = "GVEE", + .min_uV = V_to_uV(-22), + .max_uV = V_to_uV(-22), + }, + }, { + .constraints = { + .name = "HVINN", + .min_uV = V_to_uV(-22), + .max_uV = V_to_uV(-22), + }, + }, { + .constraints = { + .name = "HVINP", + .min_uV = V_to_uV(20), + .max_uV = V_to_uV(20), + }, + }, { + .constraints = { + .name = "VCOM", + .min_uV = mV_to_uV(-4325), + .max_uV = mV_to_uV(-500), + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE | + REGULATOR_CHANGE_STATUS, + }, + .num_consumer_supplies = ARRAY_SIZE(vcom_consumers), + .consumer_supplies = vcom_consumers, + }, { + .constraints = { + .name = "VNEG", + .min_uV = V_to_uV(-15), + .max_uV = V_to_uV(-15), + }, + }, { + .constraints = { + .name = "VPOS", + .min_uV = V_to_uV(15), + .max_uV = V_to_uV(15), + }, + }, { + .constraints = { + .name = "V3P3", + .valid_ops_mask = REGULATOR_CHANGE_STATUS, + }, + .num_consumer_supplies = ARRAY_SIZE(v3p3_consumers), + .consumer_supplies = v3p3_consumers, + }, +}; + +static const struct anatop_thermal_platform_data + mx6sl_anatop_thermal_data __initconst = { + .name = "anatop_thermal", + }; + +static struct platform_device max17135_sensor_device = { + .name = "max17135_sensor", + .id = 0, +}; + +static struct max17135_platform_data max17135_pdata __initdata = { + .vneg_pwrup = 1, + .gvee_pwrup = 1, + .vpos_pwrup = 2, + .gvdd_pwrup = 1, + .gvdd_pwrdn = 1, + .vpos_pwrdn = 2, + .gvee_pwrdn = 1, + .vneg_pwrdn = 1, + .gpio_pmic_pwrgood = MX6SL_BRD_EPDC_PWRSTAT, + .gpio_pmic_vcom_ctrl = MX6SL_BRD_EPDC_VCOM, + .gpio_pmic_wakeup = MX6SL_BRD_EPDC_PMIC_WAKE, + .gpio_pmic_v3p3 = MX6SL_BRD_EPDC_PWRCTRL0, + .gpio_pmic_intr = MX6SL_BRD_EPDC_PMIC_INT, + .regulator_init = max17135_init_data, + .init = max17135_regulator_init, +}; + +static int __init max17135_regulator_init(struct max17135 *max17135) +{ + struct max17135_platform_data *pdata = &max17135_pdata; + int i, ret; + + max17135->gvee_pwrup = pdata->gvee_pwrup; + max17135->vneg_pwrup = pdata->vneg_pwrup; + max17135->vpos_pwrup = pdata->vpos_pwrup; + max17135->gvdd_pwrup = pdata->gvdd_pwrup; + max17135->gvdd_pwrdn = pdata->gvdd_pwrdn; + max17135->vpos_pwrdn = pdata->vpos_pwrdn; + max17135->vneg_pwrdn = pdata->vneg_pwrdn; + max17135->gvee_pwrdn = pdata->gvee_pwrdn; + + max17135->max_wait = pdata->vpos_pwrup + pdata->vneg_pwrup + + pdata->gvdd_pwrup + pdata->gvee_pwrup; + + max17135->gpio_pmic_pwrgood = pdata->gpio_pmic_pwrgood; + max17135->gpio_pmic_vcom_ctrl = pdata->gpio_pmic_vcom_ctrl; + max17135->gpio_pmic_wakeup = pdata->gpio_pmic_wakeup; + max17135->gpio_pmic_v3p3 = pdata->gpio_pmic_v3p3; + max17135->gpio_pmic_intr = pdata->gpio_pmic_intr; + + gpio_request(max17135->gpio_pmic_wakeup, "epdc-pmic-wake"); + gpio_direction_output(max17135->gpio_pmic_wakeup, 0); + + gpio_request(max17135->gpio_pmic_vcom_ctrl, "epdc-vcom"); + gpio_direction_output(max17135->gpio_pmic_vcom_ctrl, 0); + + gpio_request(max17135->gpio_pmic_v3p3, "epdc-v3p3"); + gpio_direction_output(max17135->gpio_pmic_v3p3, 0); + + gpio_request(max17135->gpio_pmic_intr, "epdc-pmic-int"); + gpio_direction_input(max17135->gpio_pmic_intr); + + gpio_request(max17135->gpio_pmic_pwrgood, "epdc-pwrstat"); + gpio_direction_input(max17135->gpio_pmic_pwrgood); + + max17135->vcom_setup = false; + max17135->init_done = false; + + for (i = 0; i < MAX17135_NUM_REGULATORS; i++) { + ret = max17135_register_regulator(max17135, i, + &pdata->regulator_init[i]); + if (ret != 0) { + printk(KERN_ERR"max17135 regulator init failed: %d\n", + ret); + return ret; + } + } + + /* + * TODO: We cannot enable full constraints for now, since + * it results in the PFUZE regulators being disabled + * at the end of boot, which disables critical regulators. + */ + /*regulator_has_full_constraints();*/ + + return 0; +} + +static int mx6_evk_spi_cs[] = { + MX6_BRD_ECSPI1_CS0, +}; + +static const struct spi_imx_master mx6_evk_spi_data __initconst = { + .chipselect = mx6_evk_spi_cs, + .num_chipselect = ARRAY_SIZE(mx6_evk_spi_cs), +}; + +#if defined(CONFIG_MTD_M25P80) || defined(CONFIG_MTD_M25P80_MODULE) +static struct mtd_partition m25p32_partitions[] = { + { + .name = "bootloader", + .offset = 0, + .size = 0x00100000, + }, { + .name = "kernel", + .offset = MTDPART_OFS_APPEND, + .size = MTDPART_SIZ_FULL, + }, +}; + +static struct flash_platform_data m25p32_spi_flash_data = { + .name = "m25p32", + .parts = m25p32_partitions, + .nr_parts = ARRAY_SIZE(m25p32_partitions), + .type = "m25p32", +}; + +static struct spi_board_info m25p32_spi0_board_info[] __initdata = { + { + /* The modalias must be the same as spi device driver name */ + .modalias = "m25p80", + .max_speed_hz = 20000000, + .bus_num = 0, + .chip_select = 0, + .platform_data = &m25p32_spi_flash_data, + }, +}; +#endif + +static void spi_device_init(void) +{ +#if defined(CONFIG_MTD_M25P80) || defined(CONFIG_MTD_M25P80_MODULE) + spi_register_board_info(m25p32_spi0_board_info, + ARRAY_SIZE(m25p32_spi0_board_info)); +#endif +} + +static struct imx_ssi_platform_data mx6_sabresd_ssi_pdata = { + .flags = IMX_SSI_DMA | IMX_SSI_SYN, +}; + +static struct mxc_audio_platform_data wm8962_data; + +static struct platform_device mx6_sabresd_audio_wm8962_device = { + .name = "imx-wm8962", +}; + +static struct wm8962_pdata wm8962_config_data = { + +}; + +static int wm8962_clk_enable(int enable) +{ + if (enable) + clk_enable(extern_audio_root); + else + clk_disable(extern_audio_root); + + return 0; +} + +static int mxc_wm8962_init(void) +{ + struct clk *pll4; + int rate; + + extern_audio_root = clk_get(NULL, "extern_audio_clk"); + if (IS_ERR(extern_audio_root)) { + pr_err("can't get extern_audio_root clock.\n"); + return PTR_ERR(extern_audio_root); + } + + pll4 = clk_get(NULL, "pll4"); + if (IS_ERR(pll4)) { + pr_err("can't get pll4 clock.\n"); + return PTR_ERR(pll4); + } + + clk_set_parent(extern_audio_root, pll4); + + rate = clk_round_rate(extern_audio_root, 26000000); + clk_set_rate(extern_audio_root, rate); + + wm8962_data.sysclk = rate; + /* set AUDMUX pads to 1.8v */ + mxc_iomux_set_specialbits_register(MX6SL_PAD_AUD_MCLK, + PAD_CTL_LVE, PAD_CTL_LVE_MASK); + mxc_iomux_set_specialbits_register(MX6SL_PAD_AUD_RXD, + PAD_CTL_LVE, PAD_CTL_LVE_MASK); + mxc_iomux_set_specialbits_register(MX6SL_PAD_AUD_TXC, + PAD_CTL_LVE, PAD_CTL_LVE_MASK); + mxc_iomux_set_specialbits_register(MX6SL_PAD_AUD_TXD, + PAD_CTL_LVE, PAD_CTL_LVE_MASK); + mxc_iomux_set_specialbits_register(MX6SL_PAD_AUD_TXFS, + PAD_CTL_LVE, PAD_CTL_LVE_MASK); + + return 0; +} + +static struct mxc_audio_platform_data wm8962_data = { + .ssi_num = 1, + .src_port = 2, + .ext_port = 3, + .hp_gpio = MX6_BRD_HEADPHONE_DET, + .hp_active_low = 1, + .mic_gpio = -1, + .mic_active_low = 1, + .init = mxc_wm8962_init, + .clock_enable = wm8962_clk_enable, +}; + +static struct regulator_consumer_supply sabresd_vwm8962_consumers[] = { + REGULATOR_SUPPLY("SPKVDD1", "1-001a"), + REGULATOR_SUPPLY("SPKVDD2", "1-001a"), +}; + +static struct regulator_init_data sabresd_vwm8962_init = { + .constraints = { + .name = "SPKVDD", + .valid_ops_mask = REGULATOR_CHANGE_STATUS, + .boot_on = 1, + }, + .num_consumer_supplies = ARRAY_SIZE(sabresd_vwm8962_consumers), + .consumer_supplies = sabresd_vwm8962_consumers, +}; + +static struct fixed_voltage_config sabresd_vwm8962_reg_config = { + .supply_name = "SPKVDD", + .microvolts = 4325000, + .gpio = -1, + .enabled_at_boot = 1, + .init_data = &sabresd_vwm8962_init, +}; + +static struct platform_device sabresd_vwm8962_reg_devices = { + .name = "reg-fixed-voltage", + .id = 4, + .dev = { + .platform_data = &sabresd_vwm8962_reg_config, + }, +}; + +static int __init imx6q_init_audio(void) +{ + platform_device_register(&sabresd_vwm8962_reg_devices); + mxc_register_device(&mx6_sabresd_audio_wm8962_device, + &wm8962_data); + imx6q_add_imx_ssi(1, &mx6_sabresd_ssi_pdata); + + return 0; +} + +static struct imxi2c_platform_data mx6_evk_i2c0_data = { + .bitrate = 100000, +}; + +static struct imxi2c_platform_data mx6_evk_i2c1_data = { + .bitrate = 100000, +}; + +static struct imxi2c_platform_data mx6_evk_i2c2_data = { + .bitrate = 400000, +}; + +static struct i2c_board_info mxc_i2c0_board_info[] __initdata = { + { + I2C_BOARD_INFO("max17135", 0x48), + .platform_data = &max17135_pdata, + }, { + I2C_BOARD_INFO("elan-touch", 0x10), + .irq = gpio_to_irq(MX6SL_BRD_ELAN_INT), + }, { + I2C_BOARD_INFO("mma8450", 0x1c), + }, +}; + +static struct i2c_board_info mxc_i2c1_board_info[] __initdata = { + { + I2C_BOARD_INFO("wm8962", 0x1a), + .platform_data = &wm8962_config_data, + }, +}; + +static struct i2c_board_info mxc_i2c2_board_info[] __initdata = { + { + }, +}; + +static struct mxc_dvfs_platform_data mx6sl_evk_dvfscore_data = { +#ifdef CONFIG_MX6_INTER_LDO_BYPASS + .reg_id = "VDDCORE", + .soc_id = "VDDSOC", +#else + .reg_id = "cpu_vddgp", + .soc_id = "cpu_vddsoc", + .pu_id = "cpu_vddvpu", +#endif + .clk1_id = "cpu_clk", + .clk2_id = "gpc_dvfs_clk", + .gpc_cntr_offset = MXC_GPC_CNTR_OFFSET, + .ccm_cdcr_offset = MXC_CCM_CDCR_OFFSET, + .ccm_cacrr_offset = MXC_CCM_CACRR_OFFSET, + .ccm_cdhipr_offset = MXC_CCM_CDHIPR_OFFSET, + .prediv_mask = 0x1F800, + .prediv_offset = 11, + .prediv_val = 3, + .div3ck_mask = 0xE0000000, + .div3ck_offset = 29, + .div3ck_val = 2, + .emac_val = 0x08, + .upthr_val = 25, + .dnthr_val = 9, + .pncthr_val = 33, + .upcnt_val = 10, + .dncnt_val = 10, + .delay_time = 80, +}; + +static struct viv_gpu_platform_data imx6q_gpu_pdata __initdata = { + .reserved_mem_size = SZ_128M, +}; + +void __init early_console_setup(unsigned long base, struct clk *clk); + +static inline void mx6_evk_init_uart(void) +{ + imx6q_add_imx_uart(0, NULL); /* DEBUG UART1 */ +} + +static int mx6sl_evk_fec_phy_init(struct phy_device *phydev) +{ + int val; + + /* power on FEC phy and reset phy */ + gpio_request(MX6_BRD_FEC_PWR_EN, "fec-pwr"); + gpio_direction_output(MX6_BRD_FEC_PWR_EN, 0); + /* wait RC ms for hw reset */ + msleep(1); + gpio_direction_output(MX6_BRD_FEC_PWR_EN, 1); + + /* check phy power */ + val = phy_read(phydev, 0x0); + if (val & BMCR_PDOWN) + phy_write(phydev, 0x0, (val & ~BMCR_PDOWN)); + + return 0; +} + +static struct fec_platform_data fec_data __initdata = { + .init = mx6sl_evk_fec_phy_init, + .phy = PHY_INTERFACE_MODE_RMII, +}; + +static int epdc_get_pins(void) +{ + int ret = 0; + + /* Claim GPIOs for EPDC pins - used during power up/down */ + ret |= gpio_request(MX6SL_BRD_EPDC_SDDO_0, "epdc_d0"); + ret |= gpio_request(MX6SL_BRD_EPDC_SDDO_1, "epdc_d1"); + ret |= gpio_request(MX6SL_BRD_EPDC_SDDO_2, "epdc_d2"); + ret |= gpio_request(MX6SL_BRD_EPDC_SDDO_3, "epdc_d3"); + ret |= gpio_request(MX6SL_BRD_EPDC_SDDO_4, "epdc_d4"); + ret |= gpio_request(MX6SL_BRD_EPDC_SDDO_5, "epdc_d5"); + ret |= gpio_request(MX6SL_BRD_EPDC_SDDO_6, "epdc_d6"); + ret |= gpio_request(MX6SL_BRD_EPDC_SDDO_7, "epdc_d7"); + ret |= gpio_request(MX6SL_BRD_EPDC_GDCLK, "epdc_gdclk"); + ret |= gpio_request(MX6SL_BRD_EPDC_GDSP, "epdc_gdsp"); + ret |= gpio_request(MX6SL_BRD_EPDC_GDOE, "epdc_gdoe"); + ret |= gpio_request(MX6SL_BRD_EPDC_GDRL, "epdc_gdrl"); + ret |= gpio_request(MX6SL_BRD_EPDC_SDCLK, "epdc_sdclk"); + ret |= gpio_request(MX6SL_BRD_EPDC_SDOE, "epdc_sdoe"); + ret |= gpio_request(MX6SL_BRD_EPDC_SDLE, "epdc_sdle"); + ret |= gpio_request(MX6SL_BRD_EPDC_SDSHR, "epdc_sdshr"); + ret |= gpio_request(MX6SL_BRD_EPDC_BDR0, "epdc_bdr0"); + ret |= gpio_request(MX6SL_BRD_EPDC_SDCE0, "epdc_sdce0"); + ret |= gpio_request(MX6SL_BRD_EPDC_SDCE1, "epdc_sdce1"); + ret |= gpio_request(MX6SL_BRD_EPDC_SDCE2, "epdc_sdce2"); + + return ret; +} + +static void epdc_put_pins(void) +{ + gpio_free(MX6SL_BRD_EPDC_SDDO_0); + gpio_free(MX6SL_BRD_EPDC_SDDO_1); + gpio_free(MX6SL_BRD_EPDC_SDDO_2); + gpio_free(MX6SL_BRD_EPDC_SDDO_3); + gpio_free(MX6SL_BRD_EPDC_SDDO_4); + gpio_free(MX6SL_BRD_EPDC_SDDO_5); + gpio_free(MX6SL_BRD_EPDC_SDDO_6); + gpio_free(MX6SL_BRD_EPDC_SDDO_7); + gpio_free(MX6SL_BRD_EPDC_GDCLK); + gpio_free(MX6SL_BRD_EPDC_GDSP); + gpio_free(MX6SL_BRD_EPDC_GDOE); + gpio_free(MX6SL_BRD_EPDC_GDRL); + gpio_free(MX6SL_BRD_EPDC_SDCLK); + gpio_free(MX6SL_BRD_EPDC_SDOE); + gpio_free(MX6SL_BRD_EPDC_SDLE); + gpio_free(MX6SL_BRD_EPDC_SDSHR); + gpio_free(MX6SL_BRD_EPDC_BDR0); + gpio_free(MX6SL_BRD_EPDC_SDCE0); + gpio_free(MX6SL_BRD_EPDC_SDCE1); + gpio_free(MX6SL_BRD_EPDC_SDCE2); +} + +static void epdc_enable_pins(void) +{ + /* Configure MUX settings to enable EPDC use */ + mxc_iomux_v3_setup_multiple_pads(mx6sl_brd_epdc_enable_pads, \ + ARRAY_SIZE(mx6sl_brd_epdc_enable_pads)); + + gpio_direction_input(MX6SL_BRD_EPDC_SDDO_0); + gpio_direction_input(MX6SL_BRD_EPDC_SDDO_1); + gpio_direction_input(MX6SL_BRD_EPDC_SDDO_2); + gpio_direction_input(MX6SL_BRD_EPDC_SDDO_3); + gpio_direction_input(MX6SL_BRD_EPDC_SDDO_4); + gpio_direction_input(MX6SL_BRD_EPDC_SDDO_5); + gpio_direction_input(MX6SL_BRD_EPDC_SDDO_6); + gpio_direction_input(MX6SL_BRD_EPDC_SDDO_7); + gpio_direction_input(MX6SL_BRD_EPDC_GDCLK); + gpio_direction_input(MX6SL_BRD_EPDC_GDSP); + gpio_direction_input(MX6SL_BRD_EPDC_GDOE); + gpio_direction_input(MX6SL_BRD_EPDC_GDRL); + gpio_direction_input(MX6SL_BRD_EPDC_SDCLK); + gpio_direction_input(MX6SL_BRD_EPDC_SDOE); + gpio_direction_input(MX6SL_BRD_EPDC_SDLE); + gpio_direction_input(MX6SL_BRD_EPDC_SDSHR); + gpio_direction_input(MX6SL_BRD_EPDC_BDR0); + gpio_direction_input(MX6SL_BRD_EPDC_SDCE0); + gpio_direction_input(MX6SL_BRD_EPDC_SDCE1); + gpio_direction_input(MX6SL_BRD_EPDC_SDCE2); +} + +static void epdc_disable_pins(void) +{ + /* Configure MUX settings for EPDC pins to + * GPIO and drive to 0. */ + mxc_iomux_v3_setup_multiple_pads(mx6sl_brd_epdc_disable_pads, \ + ARRAY_SIZE(mx6sl_brd_epdc_disable_pads)); + + gpio_direction_output(MX6SL_BRD_EPDC_SDDO_0, 0); + gpio_direction_output(MX6SL_BRD_EPDC_SDDO_1, 0); + gpio_direction_output(MX6SL_BRD_EPDC_SDDO_2, 0); + gpio_direction_output(MX6SL_BRD_EPDC_SDDO_3, 0); + gpio_direction_output(MX6SL_BRD_EPDC_SDDO_4, 0); + gpio_direction_output(MX6SL_BRD_EPDC_SDDO_5, 0); + gpio_direction_output(MX6SL_BRD_EPDC_SDDO_6, 0); + gpio_direction_output(MX6SL_BRD_EPDC_SDDO_7, 0); + gpio_direction_output(MX6SL_BRD_EPDC_GDCLK, 0); + gpio_direction_output(MX6SL_BRD_EPDC_GDSP, 0); + gpio_direction_output(MX6SL_BRD_EPDC_GDOE, 0); + gpio_direction_output(MX6SL_BRD_EPDC_GDRL, 0); + gpio_direction_output(MX6SL_BRD_EPDC_SDCLK, 0); + gpio_direction_output(MX6SL_BRD_EPDC_SDOE, 0); + gpio_direction_output(MX6SL_BRD_EPDC_SDLE, 0); + gpio_direction_output(MX6SL_BRD_EPDC_SDSHR, 0); + gpio_direction_output(MX6SL_BRD_EPDC_BDR0, 0); + gpio_direction_output(MX6SL_BRD_EPDC_SDCE0, 0); + gpio_direction_output(MX6SL_BRD_EPDC_SDCE1, 0); + gpio_direction_output(MX6SL_BRD_EPDC_SDCE2, 0); +} + +static struct fb_videomode e60_v110_mode = { + .name = "E60_V110", + .refresh = 50, + .xres = 800, + .yres = 600, + .pixclock = 18604700, + .left_margin = 8, + .right_margin = 178, + .upper_margin = 4, + .lower_margin = 10, + .hsync_len = 20, + .vsync_len = 4, + .sync = 0, + .vmode = FB_VMODE_NONINTERLACED, + .flag = 0, +}; +static struct fb_videomode e60_v220_mode = { + .name = "E60_V220", + .refresh = 85, + .xres = 800, + .yres = 600, + .pixclock = 30000000, + .left_margin = 8, + .right_margin = 164, + .upper_margin = 4, + .lower_margin = 8, + .hsync_len = 4, + .vsync_len = 1, + .sync = 0, + .vmode = FB_VMODE_NONINTERLACED, + .flag = 0, + .refresh = 85, + .xres = 800, + .yres = 600, +}; +static struct fb_videomode e060scm_mode = { + .name = "E060SCM", + .refresh = 85, + .xres = 800, + .yres = 600, + .pixclock = 26666667, + .left_margin = 8, + .right_margin = 100, + .upper_margin = 4, + .lower_margin = 8, + .hsync_len = 4, + .vsync_len = 1, + .sync = 0, + .vmode = FB_VMODE_NONINTERLACED, + .flag = 0, +}; +static struct fb_videomode e97_v110_mode = { + .name = "E97_V110", + .refresh = 50, + .xres = 1200, + .yres = 825, + .pixclock = 32000000, + .left_margin = 12, + .right_margin = 128, + .upper_margin = 4, + .lower_margin = 10, + .hsync_len = 20, + .vsync_len = 4, + .sync = 0, + .vmode = FB_VMODE_NONINTERLACED, + .flag = 0, +}; + +static struct imx_epdc_fb_mode panel_modes[] = { + { + &e60_v110_mode, + 4, /* vscan_holdoff */ + 10, /* sdoed_width */ + 20, /* sdoed_delay */ + 10, /* sdoez_width */ + 20, /* sdoez_delay */ + 428, /* gdclk_hp_offs */ + 20, /* gdsp_offs */ + 0, /* gdoe_offs */ + 1, /* gdclk_offs */ + 1, /* num_ce */ + }, + { + &e60_v220_mode, + 4, /* vscan_holdoff */ + 10, /* sdoed_width */ + 20, /* sdoed_delay */ + 10, /* sdoez_width */ + 20, /* sdoez_delay */ + 465, /* gdclk_hp_offs */ + 20, /* gdsp_offs */ + 0, /* gdoe_offs */ + 9, /* gdclk_offs */ + 1, /* num_ce */ + }, + { + &e060scm_mode, + 4, /* vscan_holdoff */ + 10, /* sdoed_width */ + 20, /* sdoed_delay */ + 10, /* sdoez_width */ + 20, /* sdoez_delay */ + 419, /* gdclk_hp_offs */ + 20, /* gdsp_offs */ + 0, /* gdoe_offs */ + 5, /* gdclk_offs */ + 1, /* num_ce */ + }, + { + &e97_v110_mode, + 8, /* vscan_holdoff */ + 10, /* sdoed_width */ + 20, /* sdoed_delay */ + 10, /* sdoez_width */ + 20, /* sdoez_delay */ + 632, /* gdclk_hp_offs */ + 20, /* gdsp_offs */ + 0, /* gdoe_offs */ + 1, /* gdclk_offs */ + 3, /* num_ce */ + } +}; + +static struct imx_epdc_fb_platform_data epdc_data = { + .epdc_mode = panel_modes, + .num_modes = ARRAY_SIZE(panel_modes), + .get_pins = epdc_get_pins, + .put_pins = epdc_put_pins, + .enable_pins = epdc_enable_pins, + .disable_pins = epdc_disable_pins, +}; + +static int spdc_get_pins(void) +{ + int ret = 0; + + /* Claim GPIOs for SPDC pins - used during power up/down */ + ret |= gpio_request(MX6SL_BRD_EPDC_SDDO_0, "SPDC_D0"); + ret |= gpio_request(MX6SL_BRD_EPDC_SDDO_1, "SPDC_D1"); + ret |= gpio_request(MX6SL_BRD_EPDC_SDDO_2, "SPDC_D2"); + ret |= gpio_request(MX6SL_BRD_EPDC_SDDO_3, "SPDC_D3"); + ret |= gpio_request(MX6SL_BRD_EPDC_SDDO_4, "SPDC_D4"); + ret |= gpio_request(MX6SL_BRD_EPDC_SDDO_5, "SPDC_D5"); + ret |= gpio_request(MX6SL_BRD_EPDC_SDDO_6, "SPDC_D6"); + ret |= gpio_request(MX6SL_BRD_EPDC_SDDO_7, "SPDC_D7"); + + ret |= gpio_request(MX6SL_BRD_EPDC_GDOE, "SIPIX_YOE"); + ret |= gpio_request(MX6SL_BRD_EPDC_SDDO_9, "SIPIX_PWR_RDY"); + + ret |= gpio_request(MX6SL_BRD_EPDC_GDSP, "SIPIX_YDIO"); + + ret |= gpio_request(MX6SL_BRD_EPDC_GDCLK, "SIPIX_YCLK"); + ret |= gpio_request(MX6SL_BRD_EPDC_SDSHR, "SIPIX_XDIO"); + + ret |= gpio_request(MX6SL_BRD_EPDC_SDLE, "SIPIX_LD"); + ret |= gpio_request(MX6SL_BRD_EPDC_SDCE1, "SIPIX_SOE"); + + ret |= gpio_request(MX6SL_BRD_EPDC_SDCLK, "SIPIX_XCLK"); + ret |= gpio_request(MX6SL_BRD_EPDC_SDDO_10, "SIPIX_SHD_N"); + ret |= gpio_request(MX6SL_BRD_EPDC_SDCE0, "SIPIX2_CE"); + + return ret; +} + +static void spdc_put_pins(void) +{ + gpio_free(MX6SL_BRD_EPDC_SDDO_0); + gpio_free(MX6SL_BRD_EPDC_SDDO_1); + gpio_free(MX6SL_BRD_EPDC_SDDO_2); + gpio_free(MX6SL_BRD_EPDC_SDDO_3); + gpio_free(MX6SL_BRD_EPDC_SDDO_4); + gpio_free(MX6SL_BRD_EPDC_SDDO_5); + gpio_free(MX6SL_BRD_EPDC_SDDO_6); + gpio_free(MX6SL_BRD_EPDC_SDDO_7); + + gpio_free(MX6SL_BRD_EPDC_GDOE); + gpio_free(MX6SL_BRD_EPDC_SDDO_9); + gpio_free(MX6SL_BRD_EPDC_GDSP); + gpio_free(MX6SL_BRD_EPDC_GDCLK); + gpio_free(MX6SL_BRD_EPDC_SDSHR); + gpio_free(MX6SL_BRD_EPDC_SDLE); + gpio_free(MX6SL_BRD_EPDC_SDCE1); + gpio_free(MX6SL_BRD_EPDC_SDCLK); + gpio_free(MX6SL_BRD_EPDC_SDDO_10); + gpio_free(MX6SL_BRD_EPDC_SDCE0); +} + +static void spdc_enable_pins(void) +{ + /* Configure MUX settings to enable SPDC use */ + mxc_iomux_v3_setup_multiple_pads(mx6sl_brd_spdc_enable_pads, \ + ARRAY_SIZE(mx6sl_brd_spdc_enable_pads)); + + gpio_direction_input(MX6SL_BRD_EPDC_SDDO_0); + gpio_direction_input(MX6SL_BRD_EPDC_SDDO_1); + gpio_direction_input(MX6SL_BRD_EPDC_SDDO_2); + gpio_direction_input(MX6SL_BRD_EPDC_SDDO_3); + gpio_direction_input(MX6SL_BRD_EPDC_SDDO_4); + gpio_direction_input(MX6SL_BRD_EPDC_SDDO_5); + gpio_direction_input(MX6SL_BRD_EPDC_SDDO_6); + gpio_direction_input(MX6SL_BRD_EPDC_SDDO_7); + gpio_direction_input(MX6SL_BRD_EPDC_GDOE); + gpio_direction_input(MX6SL_BRD_EPDC_SDDO_9); + gpio_direction_input(MX6SL_BRD_EPDC_GDSP); + gpio_direction_input(MX6SL_BRD_EPDC_GDCLK); + gpio_direction_input(MX6SL_BRD_EPDC_SDSHR); + gpio_direction_input(MX6SL_BRD_EPDC_SDLE); + gpio_direction_input(MX6SL_BRD_EPDC_SDCE1); + gpio_direction_input(MX6SL_BRD_EPDC_SDCLK); + gpio_direction_input(MX6SL_BRD_EPDC_SDDO_10); + gpio_direction_input(MX6SL_BRD_EPDC_SDCE0); +} + +static void spdc_disable_pins(void) +{ + /* Configure MUX settings for SPDC pins to + * GPIO and drive to 0. */ + mxc_iomux_v3_setup_multiple_pads(mx6sl_brd_spdc_disable_pads, \ + ARRAY_SIZE(mx6sl_brd_spdc_disable_pads)); + + gpio_direction_output(MX6SL_BRD_EPDC_SDDO_0, 0); + gpio_direction_output(MX6SL_BRD_EPDC_SDDO_1, 0); + gpio_direction_output(MX6SL_BRD_EPDC_SDDO_2, 0); + gpio_direction_output(MX6SL_BRD_EPDC_SDDO_3, 0); + gpio_direction_output(MX6SL_BRD_EPDC_SDDO_4, 0); + gpio_direction_output(MX6SL_BRD_EPDC_SDDO_5, 0); + gpio_direction_output(MX6SL_BRD_EPDC_SDDO_6, 0); + gpio_direction_output(MX6SL_BRD_EPDC_SDDO_7, 0); + + gpio_direction_output(MX6SL_BRD_EPDC_GDOE, 0); + gpio_direction_output(MX6SL_BRD_EPDC_SDDO_9, 0); + gpio_direction_output(MX6SL_BRD_EPDC_GDSP, 0); + gpio_direction_output(MX6SL_BRD_EPDC_GDCLK, 0); + gpio_direction_output(MX6SL_BRD_EPDC_SDSHR, 0); + gpio_direction_output(MX6SL_BRD_EPDC_SDLE, 0); + gpio_direction_output(MX6SL_BRD_EPDC_SDCE1, 0); + gpio_direction_output(MX6SL_BRD_EPDC_SDCLK, 0); + gpio_direction_output(MX6SL_BRD_EPDC_SDDO_10, 0); + gpio_direction_output(MX6SL_BRD_EPDC_SDCE0, 0); +} + +static struct imx_spdc_panel_init_set spdc_init_set = { + .yoe_pol = false, + .dual_gate = false, + .resolution = 0, + .ud = false, + .rl = false, + .data_filter_n = true, + .power_ready = true, + .rgbw_mode_enable = false, + .hburst_len_en = true, +}; + +static struct fb_videomode erk_1_4_a01 = { + .name = "ERK_1_4_A01", + .refresh = 50, + .xres = 800, + .yres = 600, + .pixclock = 40000000, + .vmode = FB_VMODE_NONINTERLACED, +}; + +static struct imx_spdc_fb_mode spdc_panel_modes[] = { + { + &erk_1_4_a01, + &spdc_init_set, + .wave_timing = "pvi" + }, +}; + +static struct imx_spdc_fb_platform_data spdc_data = { + .spdc_mode = spdc_panel_modes, + .num_modes = ARRAY_SIZE(spdc_panel_modes), + .get_pins = spdc_get_pins, + .put_pins = spdc_put_pins, + .enable_pins = spdc_enable_pins, + .disable_pins = spdc_disable_pins, +}; + +static int __init early_use_spdc_sel(char *p) +{ + spdc_sel = 1; + return 0; +} +early_param("spdc", early_use_spdc_sel); + +static void setup_spdc(void) +{ + /* GPR0[8]: 0:EPDC, 1:SPDC */ + if (spdc_sel) + mxc_iomux_set_gpr_register(0, 8, 1, 1); +} + +static void imx6_evk_usbotg_vbus(bool on) +{ + if (on) + gpio_set_value(MX6_BRD_USBOTG1_PWR, 1); + else + gpio_set_value(MX6_BRD_USBOTG1_PWR, 0); +} + +static void __init mx6_evk_init_usb(void) +{ + int ret = 0; + + imx_otg_base = MX6_IO_ADDRESS(MX6Q_USB_OTG_BASE_ADDR); + + /* disable external charger detect, + * or it will affect signal quality at dp. + */ + + ret = gpio_request(MX6_BRD_USBOTG1_PWR, "usbotg-pwr"); + if (ret) { + pr_err("failed to get GPIO MX6_BRD_USBOTG1_PWR:%d\n", ret); + return; + } + gpio_direction_output(MX6_BRD_USBOTG1_PWR, 0); + + ret = gpio_request(MX6_BRD_USBOTG2_PWR, "usbh1-pwr"); + if (ret) { + pr_err("failed to get GPIO MX6_BRD_USBOTG2_PWR:%d\n", ret); + return; + } + gpio_direction_output(MX6_BRD_USBOTG2_PWR, 1); + + mx6_set_otghost_vbus_func(imx6_evk_usbotg_vbus); + mx6_usb_dr_init(); +#ifdef CONFIG_USB_EHCI_ARC_HSIC + mx6_usb_h2_init(); +#endif +} + +static struct platform_pwm_backlight_data mx6_evk_pwm_backlight_data = { + .pwm_id = 0, + .max_brightness = 255, + .dft_brightness = 128, + .pwm_period_ns = 50000, +}; +static struct fb_videomode video_modes[] = { + { + /* 800x480 @ 57 Hz , pixel clk @ 32MHz */ + "SEIKO-WVGA", 60, 800, 480, 29850, 99, 164, 33, 10, 10, 10, + FB_SYNC_CLK_LAT_FALL, + FB_VMODE_NONINTERLACED, + 0,}, +}; + +static struct mxc_fb_platform_data fb_data[] = { + { + .interface_pix_fmt = V4L2_PIX_FMT_RGB24, + .mode_str = "SEIKO-WVGA", + .mode = video_modes, + .num_modes = ARRAY_SIZE(video_modes), + }, +}; + +static struct platform_device lcd_wvga_device = { + .name = "lcd_seiko", +}; + +static int mx6sl_evk_keymap[] = { + KEY(0, 0, KEY_SELECT), + KEY(0, 1, KEY_BACK), + KEY(0, 2, KEY_F1), + KEY(0, 3, KEY_F2), + + KEY(1, 0, KEY_F3), + KEY(1, 1, KEY_F4), + KEY(1, 2, KEY_F5), + KEY(1, 3, KEY_MENU), + + KEY(2, 0, KEY_PREVIOUS), + KEY(2, 1, KEY_NEXT), + KEY(2, 2, KEY_HOME), + KEY(2, 3, KEY_NEXT), + + KEY(3, 0, KEY_UP), + KEY(3, 1, KEY_LEFT), + KEY(3, 2, KEY_RIGHT), + KEY(3, 3, KEY_DOWN), +}; + +static const struct matrix_keymap_data mx6sl_evk_map_data __initconst = { + .keymap = mx6sl_evk_keymap, + .keymap_size = ARRAY_SIZE(mx6sl_evk_keymap), +}; +static void __init elan_ts_init(void) +{ + mxc_iomux_v3_setup_multiple_pads(mx6sl_brd_elan_pads, + ARRAY_SIZE(mx6sl_brd_elan_pads)); + + /* ELAN Touchscreen */ + gpio_request(MX6SL_BRD_ELAN_INT, "elan-interrupt"); + gpio_direction_input(MX6SL_BRD_ELAN_INT); + + gpio_request(MX6SL_BRD_ELAN_CE, "elan-cs"); + gpio_direction_output(MX6SL_BRD_ELAN_CE, 1); + gpio_direction_output(MX6SL_BRD_ELAN_CE, 0); + + gpio_request(MX6SL_BRD_ELAN_RST, "elan-rst"); + gpio_direction_output(MX6SL_BRD_ELAN_RST, 1); + gpio_direction_output(MX6SL_BRD_ELAN_RST, 0); + mdelay(1); + gpio_direction_output(MX6SL_BRD_ELAN_RST, 1); + gpio_direction_output(MX6SL_BRD_ELAN_CE, 1); +} + +#define SNVS_LPCR 0x38 +static void mx6_snvs_poweroff(void) +{ + u32 value; + void __iomem *mx6_snvs_base = MX6_IO_ADDRESS(MX6Q_SNVS_BASE_ADDR); + + value = readl(mx6_snvs_base + SNVS_LPCR); + /* set TOP and DP_EN bit */ + writel(value | 0x60, mx6_snvs_base + SNVS_LPCR); +} + +/*! + * Board specific initialization. + */ +static void __init mx6_evk_init(void) +{ + mxc_iomux_v3_setup_multiple_pads(mx6sl_brd_pads, + ARRAY_SIZE(mx6sl_brd_pads)); + + elan_ts_init(); + +#ifdef CONFIG_MX6_INTER_LDO_BYPASS + gp_reg_id = mx6sl_evk_dvfscore_data.reg_id; + soc_reg_id = mx6sl_evk_dvfscore_data.soc_id; +#else + gp_reg_id = mx6sl_evk_dvfscore_data.reg_id; + soc_reg_id = mx6sl_evk_dvfscore_data.soc_id; + pu_reg_id = mx6sl_evk_dvfscore_data.pu_id; + mx6_cpu_regulator_init(); +#endif + + imx6q_add_imx_snvs_rtc(); + + imx6q_add_imx_i2c(0, &mx6_evk_i2c0_data); + imx6q_add_imx_i2c(1, &mx6_evk_i2c1_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, + ARRAY_SIZE(mxc_i2c1_board_info)); + imx6q_add_imx_i2c(2, &mx6_evk_i2c2_data); + i2c_register_board_info(2, mxc_i2c2_board_info, + ARRAY_SIZE(mxc_i2c2_board_info)); + + /* SPI */ + imx6q_add_ecspi(0, &mx6_evk_spi_data); + spi_device_init(); + + mx6sl_evk_init_pfuze100(0); + + imx6q_add_anatop_thermal_imx(1, &mx6sl_anatop_thermal_data); + + mx6_evk_init_uart(); + /* get enet tx reference clk from FEC_REF_CLK pad. + * GPR1[14] = 0, GPR1[18:17] = 00 + */ + mxc_iomux_set_gpr_register(1, 14, 1, 0); + mxc_iomux_set_gpr_register(1, 17, 2, 0); + + imx6_init_fec(fec_data); + + platform_device_register(&evk_vmmc_reg_devices); + imx6q_add_sdhci_usdhc_imx(0, &mx6_evk_sd1_data); + imx6q_add_sdhci_usdhc_imx(1, &mx6_evk_sd2_data); + imx6q_add_sdhci_usdhc_imx(2, &mx6_evk_sd3_data); + + mx6_evk_init_usb(); + imx6q_add_otp(); + imx6q_add_mxc_pwm(0); + imx6q_add_mxc_pwm_backlight(0, &mx6_evk_pwm_backlight_data); + imx6dl_add_imx_elcdif(&fb_data[0]); + + gpio_request(MX6_BRD_LCD_PWR_EN, "elcdif-power-on"); + gpio_direction_output(MX6_BRD_LCD_PWR_EN, 1); + mxc_register_device(&lcd_wvga_device, NULL); + + imx6dl_add_imx_pxp(); + imx6dl_add_imx_pxp_client(); + mxc_register_device(&max17135_sensor_device, NULL); + setup_spdc(); + if (!spdc_sel) + imx6dl_add_imx_epdc(&epdc_data); + else + imx6sl_add_imx_spdc(&spdc_data); + imx6q_add_dvfs_core(&mx6sl_evk_dvfscore_data); + + imx6q_init_audio(); + + imx6q_add_viim(); + imx6q_add_imx2_wdt(0, NULL); + + imx_add_viv_gpu(&imx6_gpu_data, &imx6q_gpu_pdata); + imx6sl_add_imx_keypad(&mx6sl_evk_map_data); + imx6q_add_busfreq(); + imx6sl_add_dcp(); + imx6sl_add_rngb(); + imx6sl_add_imx_pxp_v4l2(); + + imx6q_add_perfmon(0); + imx6q_add_perfmon(1); + imx6q_add_perfmon(2); + + pm_power_off = mx6_snvs_poweroff; +} + +extern void __iomem *twd_base; +static void __init mx6_timer_init(void) +{ + struct clk *uart_clk; +#ifdef CONFIG_LOCAL_TIMERS + twd_base = ioremap(LOCAL_TWD_ADDR, SZ_256); + BUG_ON(!twd_base); +#endif + mx6sl_clocks_init(32768, 24000000, 0, 0); + + uart_clk = clk_get_sys("imx-uart.0", NULL); + early_console_setup(UART1_BASE_ADDR, uart_clk); +} + +static struct sys_timer mxc_timer = { + .init = mx6_timer_init, +}; + +static void __init mx6_evk_reserve(void) +{ +#if defined(CONFIG_MXC_GPU_VIV) || defined(CONFIG_MXC_GPU_VIV_MODULE) + phys_addr_t phys; + + if (imx6q_gpu_pdata.reserved_mem_size) { + phys = memblock_alloc_base(imx6q_gpu_pdata.reserved_mem_size, + SZ_4K, MEMBLOCK_ALLOC_ACCESSIBLE); + memblock_remove(phys, imx6q_gpu_pdata.reserved_mem_size); + imx6q_gpu_pdata.reserved_mem_base = phys; + } +#endif +} + +MACHINE_START(MX6SL_EVK, "Freescale i.MX 6SoloLite EVK Board") + .boot_params = MX6SL_PHYS_OFFSET + 0x100, + .map_io = mx6_map_io, + .init_irq = mx6_init_irq, + .init_machine = mx6_evk_init, + .timer = &mxc_timer, + .reserve = mx6_evk_reserve, +MACHINE_END diff --git a/arch/arm/mach-mx6/bus_freq.c b/arch/arm/mach-mx6/bus_freq.c index 9304c48361fa..151b4ee27eb6 100644 --- a/arch/arm/mach-mx6/bus_freq.c +++ b/arch/arm/mach-mx6/bus_freq.c @@ -47,12 +47,13 @@ #include <linux/suspend.h> #define LPAPM_CLK 24000000 +#define DDR_AUDIO_CLK 50000000 #define DDR_MED_CLK 400000000 #define DDR3_NORMAL_CLK 528000000 #define GPC_PGC_GPU_PGCR_OFFSET 0x260 #define GPC_CNTR_OFFSET 0x0 -DEFINE_SPINLOCK(ddr_freq_lock); +static DEFINE_SPINLOCK(freq_lock); int low_bus_freq_mode; int audio_bus_freq_mode; @@ -69,18 +70,25 @@ int bus_freq_scaling_is_active; int lp_high_freq; int lp_med_freq; int lp_audio_freq; +int high_cpu_freq; unsigned int ddr_low_rate; unsigned int ddr_med_rate; 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; +extern void mx6sl_wait (int arm_podf, unsigned long wfi_iram_addr); + +void *mx6sl_ddr_freq_base; +void (*mx6sl_ddr_freq_change_iram)(int ddr_freq, int low_bus_freq_mode) = NULL; +extern void mx6sl_ddr_iram(int ddr_freq); extern int init_mmdc_settings(void); extern struct cpu_op *(*get_cpu_op)(int *op); extern int update_ddr_freq(int ddr_rate); extern int chip_rev; -extern bool arm_mem_clked_in_wait; DEFINE_MUTEX(bus_freq_mutex); @@ -88,6 +96,7 @@ struct timeval start_time; struct timeval end_time; static int cpu_op_nr; +static u32 org_arm_podf; static struct cpu_op *cpu_op_tbl; static struct clk *pll2_400; static struct clk *axi_clk; @@ -97,18 +106,17 @@ static struct clk *osc_clk; static struct clk *cpu_clk; static struct clk *pll3; static struct clk *pll2; +static struct clk *pll1; +static struct clk *pll1_sw_clk; static struct clk *pll3_sw_clk; static struct clk *pll2_200; static struct clk *mmdc_ch0_axi; -struct regulator *vddsoc_cap_regulator; static struct clk *pll3_540; static struct delayed_work low_bus_freq_handler; static void reduce_bus_freq_handler(struct work_struct *work) { - int ret; - mutex_lock(&bus_freq_mutex); if (low_bus_freq_mode || !low_freq_bus_used()) { mutex_unlock(&bus_freq_mutex); @@ -133,13 +141,13 @@ static void reduce_bus_freq_handler(struct work_struct *work) if (lp_audio_freq) { /* Need to ensure that PLL2_PFD_400M is kept ON. */ clk_enable(pll2_400); - update_ddr_freq(50000000); + update_ddr_freq(DDR_AUDIO_CLK); /* Make sure periph clk's parent also got updated */ clk_set_parent(periph_clk, pll2_200); audio_bus_freq_mode = 1; low_bus_freq_mode = 0; } else { - update_ddr_freq(24000000); + update_ddr_freq(LPAPM_CLK); /* Make sure periph clk's parent also got updated */ clk_set_parent(periph_clk, osc_clk); if (audio_bus_freq_mode) @@ -154,43 +162,77 @@ static void reduce_bus_freq_handler(struct work_struct *work) clk_disable(pll3); med_bus_freq_mode = 0; } else { - /* Set VDDSOC_CAP to 1.1V */ - ret = regulator_set_voltage(vddsoc_cap_regulator, 1100000, - 1100000); - if (ret < 0) { - printk(KERN_DEBUG - "COULD NOT DECREASE VDDSOC_CAP VOLTAGE!!!!\n"); - return; - } - - udelay(150); + u32 reg; + u32 div; + unsigned long flags; - arm_mem_clked_in_wait = true; + spin_lock_irqsave(&freq_lock, flags); - /* Set periph_clk to be sourced from OSC_CLK */ - /* Set MMDC clk to 25MHz. */ - /* First need to set the divider before changing the parent */ - /* if parent clock is larger than previous one */ - clk_set_rate(mmdc_ch0_axi, clk_get_rate(mmdc_ch0_axi) / 2); - clk_set_parent(mmdc_ch0_axi, pll3_sw_clk); - clk_set_parent(mmdc_ch0_axi, pll2_200); - clk_set_rate(mmdc_ch0_axi, - clk_round_rate(mmdc_ch0_axi, LPAPM_CLK)); - - /* Set AXI to 24MHz. */ - clk_set_parent(periph_clk, osc_clk); - clk_set_rate(axi_clk, clk_round_rate(axi_clk, LPAPM_CLK)); - /* Set AHB to 24MHz. */ - clk_set_rate(ahb_clk, clk_round_rate(ahb_clk, LPAPM_CLK)); + if (high_bus_freq_mode) { + /* Set periph_clk to be sourced from OSC_CLK */ + /* Set AXI to 24MHz. */ + clk_set_parent(periph_clk, osc_clk); + clk_set_rate(axi_clk, + clk_round_rate(axi_clk, LPAPM_CLK)); + /* Set AHB to 24MHz. */ + clk_set_rate(ahb_clk, + clk_round_rate(ahb_clk, LPAPM_CLK)); + } + if (lp_audio_freq) { + /* PLL2 is on in this mode, as DDR is at 50MHz. */ + /* Now change DDR freq while running from IRAM. */ + mx6sl_ddr_freq_change_iram(DDR_AUDIO_CLK, + low_bus_freq_mode); + + if (low_bus_freq_mode) { + /* Swtich ARM to run off PLL2_PFD2_400MHz + * since DDR is anway at 50MHz. + */ + clk_set_parent(pll1_sw_clk, pll2_400); + + /* Ensure that the clock will be + * at original speed. + */ + reg = __raw_writel(org_arm_podf, MXC_CCM_CACRR); + while (__raw_readl(MXC_CCM_CDHIPR)) + ; + } + low_bus_freq_mode = 0; + audio_bus_freq_mode = 1; + } else { + /* Set MMDC clk to 24MHz. */ + /* Since we are going to set PLL2 in bypass mode, + * move the CPU clock off PLL2. + */ + /* Ensure that the clock will be at + * lowest possible freq. + */ + org_arm_podf = __raw_readl(MXC_CCM_CACRR); + /* Need to enable PLL1 before setting its rate. */ + clk_enable(pll1); + clk_set_rate(pll1, + cpu_op_tbl[cpu_op_nr - 1].pll_lpm_rate); + div = clk_get_rate(pll1) / + cpu_op_tbl[cpu_op_nr - 1].cpu_rate; + + reg = __raw_writel(div - 1, MXC_CCM_CACRR); + while (__raw_readl(MXC_CCM_CDHIPR)) + ; + clk_set_parent(pll1_sw_clk, pll1); + + /* Now change DDR freq while running from IRAM. */ + mx6sl_ddr_freq_change_iram(LPAPM_CLK, + low_bus_freq_mode); - low_bus_freq_mode = 1; - audio_bus_freq_mode = 0; + low_bus_freq_mode = 1; + audio_bus_freq_mode = 0; + } + spin_unlock_irqrestore(&freq_lock, flags); } - high_bus_freq_mode = 0; - med_bus_freq_mode = 0; mutex_unlock(&bus_freq_mutex); } + /* Set the DDR, AHB to 24MHz. * This mode will be activated only when none of the modules that * need a higher DDR or AHB frequency are active. @@ -215,61 +257,43 @@ int set_low_bus_freq(void) */ int set_high_bus_freq(int high_bus_freq) { - int ret; - if (bus_freq_scaling_initialized && bus_freq_scaling_is_active) cancel_delayed_work_sync(&low_bus_freq_handler); - mutex_lock(&bus_freq_mutex); - if (busfreq_suspended) { - mutex_unlock(&bus_freq_mutex); + + if (busfreq_suspended) return 0; - } - if (!bus_freq_scaling_initialized || !bus_freq_scaling_is_active) { - mutex_unlock(&bus_freq_mutex); + + if (!bus_freq_scaling_initialized || !bus_freq_scaling_is_active) return 0; - } - if (high_bus_freq_mode && high_bus_freq) { - mutex_unlock(&bus_freq_mutex); + + if (high_bus_freq_mode && high_bus_freq) return 0; - } - if (med_bus_freq_mode && !high_bus_freq) { - mutex_unlock(&bus_freq_mutex); + + /* medium bus freq is only supported for MX6DQ */ + if (cpu_is_mx6q() && med_bus_freq_mode && !high_bus_freq) return 0; - } if (cpu_is_mx6dl() && high_bus_freq) high_bus_freq = 0; - if (cpu_is_mx6dl() && med_bus_freq_mode) { - mutex_unlock(&bus_freq_mutex); + if (cpu_is_mx6dl() && med_bus_freq_mode) return 0; - } + if ((high_bus_freq_mode && (high_bus_freq || lp_high_freq)) || (med_bus_freq_mode && !high_bus_freq && lp_med_freq && - !lp_high_freq)) { - mutex_unlock(&bus_freq_mutex); + !lp_high_freq)) return 0; - } + if (cpu_is_mx6sl()) { - /* Set the voltage of VDDSOC to 1.2V as in normal mode. */ - ret = regulator_set_voltage(vddsoc_cap_regulator, 1200000, - 1200000); - if (ret < 0) { - printk(KERN_DEBUG - "COULD NOT INCREASE VDDSOC_CAP VOLTAGE!!!!\n"); - return ret; - } + u32 reg; + unsigned long flags; - /* Need to wait for the regulator to come back up */ - /* - * Delay time is based on the number of 24MHz clock cycles - * programmed in the ANA_MISC2_BASE_ADDR for each - * 25mV step. - */ - udelay(150); + spin_lock_irqsave(&freq_lock, flags); + /* Change DDR freq in IRAM. */ + mx6sl_ddr_freq_change_iram(ddr_normal_rate, low_bus_freq_mode); /* Set periph_clk to be sourced from pll2_pfd2_400M */ /* First need to set the divider before changing the */ @@ -280,17 +304,20 @@ int set_high_bus_freq(int high_bus_freq) clk_round_rate(axi_clk, LPAPM_CLK / 2)); clk_set_parent(periph_clk, pll2_400); - /* Set mmdc_clk_root to be sourced */ - /* from pll2_pfd2_400M */ - clk_set_rate(mmdc_ch0_axi, - clk_round_rate(mmdc_ch0_axi, LPAPM_CLK / 2)); - clk_set_parent(mmdc_ch0_axi, pll3_sw_clk); - clk_set_parent(mmdc_ch0_axi, pll2_400); - clk_set_rate(mmdc_ch0_axi, - clk_round_rate(mmdc_ch0_axi, DDR_MED_CLK)); + if (low_bus_freq_mode) { + /* Now move ARM to be sourced from PLL2_400 too. */ + clk_set_parent(pll1_sw_clk, pll2_400); + /* Ensure that the clock will be at original speed. */ + reg = __raw_writel(org_arm_podf, MXC_CCM_CACRR); + while (__raw_readl(MXC_CCM_CDHIPR)) + ; + clk_disable(pll1); + } high_bus_freq_mode = 1; - med_bus_freq_mode = 0; + low_bus_freq_mode = 0; + audio_bus_freq_mode = 0; + spin_unlock_irqrestore(&freq_lock, flags); } else { clk_enable(pll3); if (high_bus_freq) { @@ -317,18 +344,11 @@ int set_high_bus_freq(int high_bus_freq) clk_get_parent(axi_clk) != pll3_540) clk_set_parent(axi_clk, pll3_540); + low_bus_freq_mode = 0; + audio_bus_freq_mode = 0; + clk_disable(pll3); } - - low_bus_freq_mode = 0; - audio_bus_freq_mode = 0; - - /* Ensure that WAIT mode can be entered in high bus freq mode. */ - - if (cpu_is_mx6sl()) - arm_mem_clked_in_wait = false; - - mutex_unlock(&bus_freq_mutex); return 0; } @@ -340,11 +360,8 @@ int low_freq_bus_used(void) /* We only go the lowest setpoint if ARM is also * at the lowest setpoint. */ - if ((clk_get_rate(cpu_clk) > - cpu_op_tbl[cpu_op_nr - 1].cpu_rate) - || (cpu_op_nr == 1)) { + if (high_cpu_freq) return 0; - } if ((lp_high_freq == 0) && (lp_med_freq == 0)) @@ -356,62 +373,80 @@ int low_freq_bus_used(void) void bus_freq_update(struct clk *clk, bool flag) { mutex_lock(&bus_freq_mutex); + if (flag) { - /* Update count */ - if (clk->flags & AHB_HIGH_SET_POINT) - lp_high_freq++; - else if (clk->flags & AHB_MED_SET_POINT) - lp_med_freq++; - else if (clk->flags & AHB_AUDIO_SET_POINT) - lp_audio_freq++; - /* Update bus freq */ - if ((clk->flags & CPU_FREQ_TRIG_UPDATE) - && (clk_get_usecount(clk) == 0)) { - if (!(clk->flags & - (AHB_HIGH_SET_POINT | AHB_MED_SET_POINT))) { - if (low_freq_bus_used()) { - if ((clk->flags & AHB_AUDIO_SET_POINT) & !audio_bus_freq_mode) - set_low_bus_freq(); - else if (!low_bus_freq_mode) - set_low_bus_freq(); - } - } else { - if ((clk->flags & AHB_MED_SET_POINT) - && !med_bus_freq_mode) { - /* Set to Medium setpoint */ - mutex_unlock(&bus_freq_mutex); + if (clk == cpu_clk) { + /* The CPU freq is being increased. + * check if we need to increase the bus freq + */ + high_cpu_freq = 1; + if (low_bus_freq_mode || audio_bus_freq_mode) set_high_bus_freq(0); - return; - } - else if ((clk->flags & AHB_HIGH_SET_POINT) - && !high_bus_freq_mode) { - /* Currently at low or medium set point, - * need to set to high setpoint - */ - mutex_unlock(&bus_freq_mutex); - set_high_bus_freq(1); - return; - } + } else { + /* Update count */ + if (clk->flags & AHB_HIGH_SET_POINT) + lp_high_freq++; + else if (clk->flags & AHB_MED_SET_POINT) + lp_med_freq++; + else if (clk->flags & AHB_AUDIO_SET_POINT) + lp_audio_freq++; + /* Update bus freq */ + if ((clk->flags & CPU_FREQ_TRIG_UPDATE) + && (clk_get_usecount(clk) == 0)) { + if (!(clk->flags & + (AHB_HIGH_SET_POINT | AHB_MED_SET_POINT))) { + if (low_freq_bus_used()) { + if ((clk->flags & AHB_AUDIO_SET_POINT) & + !audio_bus_freq_mode) + set_low_bus_freq(); + else if (!low_bus_freq_mode) + set_low_bus_freq(); + } + } else { + if ((clk->flags & AHB_MED_SET_POINT) + && !med_bus_freq_mode) { + /* Set to Medium setpoint */ + set_high_bus_freq(0); + } else if ((clk->flags & AHB_HIGH_SET_POINT) + && !high_bus_freq_mode) { + /* Currently at low or medium + * set point, need to set to + * high setpoint + */ + set_high_bus_freq(1); + } + } } } } else { - /* Update count */ - if (clk->flags & AHB_HIGH_SET_POINT) - lp_high_freq--; - else if (clk->flags & AHB_MED_SET_POINT) - lp_med_freq--; - else if (clk->flags & AHB_AUDIO_SET_POINT) - lp_audio_freq--; - /* Update bus freq */ - if ((clk->flags & CPU_FREQ_TRIG_UPDATE) - && (clk_get_usecount(clk) == 0)) { - if (low_freq_bus_used() && !low_bus_freq_mode) + if (clk == cpu_clk) { + /* CPU freq is dropped, check if we can + * lower the bus freq. + */ + high_cpu_freq = 0; + + if (low_freq_bus_used() && + !(low_bus_freq_mode || audio_bus_freq_mode)) set_low_bus_freq(); - else { - /* Set to either high or medium setpoint. */ - mutex_unlock(&bus_freq_mutex); - set_high_bus_freq(0); - return; + } else { + /* Update count */ + if (clk->flags & AHB_HIGH_SET_POINT) + lp_high_freq--; + else if (clk->flags & AHB_MED_SET_POINT) + lp_med_freq--; + else if (clk->flags & AHB_AUDIO_SET_POINT) + lp_audio_freq--; + /* Update bus freq */ + if ((clk->flags & CPU_FREQ_TRIG_UPDATE) + && (clk_get_usecount(clk) == 0)) { + if (low_freq_bus_used()) + set_low_bus_freq(); + else { + /* Set to either high or + * medium setpoint. + */ + set_high_bus_freq(0); + } } } } @@ -436,7 +471,15 @@ static ssize_t bus_freq_scaling_enable_store(struct device *dev, const char *buf, size_t size) { if (strncmp(buf, "1", 1) == 0) { +#ifdef CONFIG_MX6_VPU_352M + if (cpu_is_mx6q()) + /*do not enable bus freq*/ + bus_freq_scaling_is_active = 0; + printk(KERN_WARNING "Bus frequency can't be enabled if using VPU 352M!\n"); + return size; +#else bus_freq_scaling_is_active = 1; +#endif set_high_bus_freq(0); /* Make sure system can enter low bus mode if it should be in low bus mode */ @@ -458,6 +501,8 @@ static int busfreq_suspend(struct platform_device *pdev, pm_message_t message) static int bus_freq_pm_notify(struct notifier_block *nb, unsigned long event, void *dummy) { + mutex_lock(&bus_freq_mutex); + if (event == PM_SUSPEND_PREPARE) { set_high_bus_freq(1); busfreq_suspended = 1; @@ -465,6 +510,8 @@ static int bus_freq_pm_notify(struct notifier_block *nb, unsigned long event, busfreq_suspended = 0; } + mutex_unlock(&bus_freq_mutex); + return NOTIFY_OK; } static int busfreq_resume(struct platform_device *pdev) @@ -486,6 +533,7 @@ static DEVICE_ATTR(enable, 0644, bus_freq_scaling_enable_show, * @return The function returns 0 on success * */ + static int __devinit busfreq_probe(struct platform_device *pdev) { u32 err; @@ -513,6 +561,28 @@ static int __devinit busfreq_probe(struct platform_device *pdev) return PTR_ERR(pll2); } + pll1 = clk_get(NULL, "pll1_main_clk"); + if (IS_ERR(pll1)) { + printk(KERN_DEBUG "%s: failed to get pll1\n", + __func__); + return PTR_ERR(pll1); + } + + pll1_sw_clk = clk_get(NULL, "pll1_sw_clk"); + if (IS_ERR(pll1_sw_clk)) { + printk(KERN_DEBUG "%s: failed to get pll1_sw_clk\n", + __func__); + return PTR_ERR(pll1_sw_clk); + } + + + if (IS_ERR(pll2)) { + printk(KERN_DEBUG "%s: failed to get pll2\n", + __func__); + return PTR_ERR(pll2); + } + + cpu_clk = clk_get(NULL, "cpu_clk"); if (IS_ERR(cpu_clk)) { printk(KERN_DEBUG "%s: failed to get cpu_clk\n", @@ -576,13 +646,6 @@ static int __devinit busfreq_probe(struct platform_device *pdev) return PTR_ERR(mmdc_ch0_axi); } - vddsoc_cap_regulator = regulator_get(NULL, "cpu_vddsoc"); - if (IS_ERR(vddsoc_cap_regulator)) { - printk(KERN_ERR "%s: failed to get vddsoc_cap regulator\n", - __func__); - return PTR_ERR(vddsoc_cap_regulator); - } - err = sysfs_create_file(&busfreq_dev->kobj, &dev_attr_enable.attr); if (err) { printk(KERN_ERR @@ -598,6 +661,11 @@ static int __devinit busfreq_probe(struct platform_device *pdev) /* To make pll2_400 use count right, as when system enter 24M, it will disable pll2_400 */ clk_enable(pll2_400); + } else if (cpu_is_mx6sl()) { + /* Set med_bus_freq_mode to 1 since med_bus_freq_mode + is not supported as yet for MX6SL */ + high_bus_freq_mode = 1; + med_bus_freq_mode = 1; } else { high_bus_freq_mode = 1; med_bus_freq_mode = 0; @@ -620,6 +688,33 @@ static int __devinit busfreq_probe(struct platform_device *pdev) if (!cpu_is_mx6sl()) init_mmdc_settings(); + else { + unsigned long iram_paddr; + + /* Allocate IRAM for WFI code when system is + * in low freq mode. + */ + iram_alloc(SZ_4K, &iram_paddr); + /* Need to remap the area here since we want + * the memory region to be executable. + */ + mx6sl_wfi_iram_base = __arm_ioremap(iram_paddr, + SZ_4K, MT_MEMORY_NONCACHED); + memcpy(mx6sl_wfi_iram_base, mx6sl_wait, SZ_4K); + mx6sl_wfi_iram = (void *)mx6sl_wfi_iram_base; + + /* Allocate IRAM for WFI code when system is + *in low freq mode. + */ + iram_alloc(SZ_4K, &iram_paddr); + /* Need to remap the area here since we want the memory region + to be executable. */ + mx6sl_ddr_freq_base = __arm_ioremap(iram_paddr, + SZ_4K, MT_MEMORY_NONCACHED); + memcpy(mx6sl_ddr_freq_base, mx6sl_ddr_iram, SZ_4K); + mx6sl_ddr_freq_change_iram = (void *)mx6sl_ddr_freq_base; + + } return 0; } @@ -648,19 +743,19 @@ static int __init busfreq_init(void) printk(KERN_INFO "Bus freq driver module loaded\n"); +#ifdef CONFIG_MX6_VPU_352M + if (cpu_is_mx6q()) + bus_freq_scaling_is_active = 0;/*disable bus_freq*/ + +#else /* Enable busfreq by default. */ bus_freq_scaling_is_active = 1; - +#endif if (cpu_is_mx6q()) set_high_bus_freq(1); - else + else if (cpu_is_mx6dl()) set_high_bus_freq(0); - /* Make sure system can enter low bus mode if it should be in - low bus mode */ - if (low_freq_bus_used() && !low_bus_freq_mode) - set_low_bus_freq(); - printk(KERN_INFO "Bus freq driver Enabled\n"); return 0; } diff --git a/arch/arm/mach-mx6/clock.c b/arch/arm/mach-mx6/clock.c index 86587b5eb2e2..80781a6869ad 100644 --- a/arch/arm/mach-mx6/clock.c +++ b/arch/arm/mach-mx6/clock.c @@ -472,7 +472,6 @@ static int _clk_pll_enable(struct clk *clk) pllbase = _get_pll_base(clk); reg = __raw_readl(pllbase); - reg &= ~ANADIG_PLL_BYPASS; reg &= ~ANADIG_PLL_POWER_DOWN; /* The 480MHz PLLs have the opposite definition for power bit. */ @@ -492,6 +491,7 @@ static int _clk_pll_enable(struct clk *clk) /* Enable the PLL output now*/ reg = __raw_readl(pllbase); + reg &= ~ANADIG_PLL_BYPASS; reg |= ANADIG_PLL_ENABLE; __raw_writel(reg, pllbase); @@ -505,6 +505,15 @@ static void _clk_pll_disable(struct clk *clk) if ((arm_needs_pll2_400) && (clk == &pll2_528_bus_main_clk)) return; + /* + * To support USB remote wake up, need always keep power and enable bit + * BM_ANADIG_ANA_MISC2_CONTROL0 will power off PLL3's power + * Please see TKT064178 for detail. + */ + if (clk == &pll3_usb_otg_main_clk) { + __raw_writel(BM_ANADIG_ANA_MISC2_CONTROL0, apll_base + HW_ANADIG_ANA_MISC2_SET); + return; + } pllbase = _get_pll_base(clk); @@ -514,12 +523,6 @@ static void _clk_pll_disable(struct clk *clk) __raw_writel(reg, pllbase); - /* - * It will power off PLL3's power, it is the TO1.1 fix - * Please see TKT064178 for detail. - */ - if (clk == &pll3_usb_otg_main_clk) - __raw_writel(BM_ANADIG_ANA_MISC2_CONTROL0, apll_base + HW_ANADIG_ANA_MISC2_SET); } static unsigned long _clk_pll1_main_get_rate(struct clk *clk) @@ -1258,15 +1261,27 @@ static int _clk_arm_set_rate(struct clk *clk, unsigned long rate) * PLL2_PFD_400M. */ if (pll1_sw_clk.parent != &pll2_pfd_400M) { - pll2_pfd_400M.enable(&pll2_pfd_400M); + if (pll2_pfd_400M.usecount == 0) { + /* Check if PLL2 needs to be enabled also. */ + if (pll2_528_bus_main_clk.usecount == 0) + pll2_528_bus_main_clk.enable(&pll2_528_bus_main_clk); + /* Ensure parent usecount is + * also incremented. + */ + pll2_528_bus_main_clk.usecount++; + pll2_pfd_400M.enable(&pll2_pfd_400M); + } + pll2_pfd_400M.usecount++; arm_needs_pll2_400 = true; pll1_sw_clk.set_parent(&pll1_sw_clk, &pll2_pfd_400M); pll1_sw_clk.parent = &pll2_pfd_400M; } } else { /* Make sure PLL1 is enabled */ - if (!pll1_enabled) + if (!pll1_enabled) { pll1_sys_main_clk.enable(&pll1_sys_main_clk); + pll1_sys_main_clk.usecount = 1; + } /* Make sure PLL1 rate is what we want */ if (cpu_op_tbl[i].pll_rate != clk_get_rate(&pll1_sys_main_clk)) { /* If pll1_sw_clk is from pll1_sys_main_clk, switch it */ @@ -1282,9 +1297,19 @@ static int _clk_arm_set_rate(struct clk *clk, unsigned long rate) /* Make sure pll1_sw_clk is from pll1_sys_main_clk */ pll1_sw_clk.set_parent(&pll1_sw_clk, &pll1_sys_main_clk); pll1_sw_clk.parent = &pll1_sys_main_clk; + if (arm_needs_pll2_400) { + pll2_pfd_400M.usecount--; + if (pll2_pfd_400M.usecount == 0) { + pll2_pfd_400M.disable(&pll2_pfd_400M); + /* Ensure parent usecount is + * also decremented. + */ + pll2_528_bus_main_clk.usecount--; + if (pll2_528_bus_main_clk.usecount == 0) + pll2_528_bus_main_clk.disable(&pll2_528_bus_main_clk); + } + } arm_needs_pll2_400 = false; - if (pll2_pfd_400M.usecount == 0) - pll2_pfd_400M.disable(&pll2_pfd_400M); } parent_rate = clk_get_rate(clk->parent); div = parent_rate / rate; @@ -1320,8 +1345,10 @@ static int _clk_arm_set_rate(struct clk *clk, unsigned long rate) while (__raw_readl(MXC_CCM_CDHIPR)) ; - if (pll1_sys_main_clk.usecount == 1 && arm_needs_pll2_400) + if (pll1_sys_main_clk.usecount == 1 && arm_needs_pll2_400) { pll1_sys_main_clk.disable(&pll1_sys_main_clk); + pll1_sys_main_clk.usecount = 0; + } spin_unlock_irqrestore(&clk_lock, flags); @@ -5301,6 +5328,8 @@ int __init mx6_clocks_init(unsigned long ckil, unsigned long osc, { __iomem void *base; int i, reg; + u32 parent_rate, rate; + unsigned long ipg_clk_rate, max_arm_wait_clk; external_low_reference = ckil; external_high_reference = ckih1; @@ -5336,6 +5365,12 @@ int __init mx6_clocks_init(unsigned long ckil, unsigned long osc, clk_tree_init(); +#ifdef CONFIG_MX6_VPU_352M + if (cpu_is_mx6q()) { + clk_set_rate(&pll2_pfd_400M, 352000000); + clk_set_parent(&vpu_clk[0], &pll2_pfd_400M); + } +#endif /* keep correct count. */ clk_enable(&cpu_clk); clk_enable(&periph_clk); @@ -5504,6 +5539,20 @@ int __init mx6_clocks_init(unsigned long ckil, unsigned long osc, lp_med_freq = 0; lp_audio_freq = 0; + /* Get current ARM_PODF value */ + rate = clk_get_rate(&cpu_clk); + parent_rate = clk_get_rate(&pll1_sw_clk); + cur_arm_podf = parent_rate / rate; + + /* Calculate the ARM_PODF to be applied when the system + * enters WAIT state. + * The max ARM clk is decided by the ipg_clk and has to + * follow the ratio of ARM_CLK:IPG_CLK of 12:5. + */ + ipg_clk_rate = clk_get_rate(&ipg_clk); + max_arm_wait_clk = (12 * ipg_clk_rate) / 5; + wait_mode_arm_podf = parent_rate / max_arm_wait_clk; + /* Turn OFF all unnecessary PHYs. */ if (cpu_is_mx6q()) { /* Turn off SATA PHY. */ diff --git a/arch/arm/mach-mx6/clock_mx6sl.c b/arch/arm/mach-mx6/clock_mx6sl.c index 3b2d9e527625..9742db4907f5 100755 --- a/arch/arm/mach-mx6/clock_mx6sl.c +++ b/arch/arm/mach-mx6/clock_mx6sl.c @@ -67,6 +67,7 @@ static struct clk pll7_usb_host_main_clk; static struct clk usdhc3_clk; static struct clk ipg_clk; static struct clk gpt_clk[]; +static struct clk ahb_clk; static struct cpu_op *cpu_op_tbl; static int cpu_op_nr; @@ -100,7 +101,9 @@ DEFINE_SPINLOCK(mx6sl_clk_lock); u32 gpt_ticks; \ u32 gpt_cnt; \ u32 reg; \ + unsigned long flags; \ int result = 1; \ + spin_lock_irqsave(&mx6sl_clk_lock, flags); \ gpt_rate = clk_get_rate(&gpt_clk[0]); \ gpt_ticks = timeout / (1000000000 / gpt_rate); \ reg = __raw_readl(timer_base + V2_TSTAT);\ @@ -130,6 +133,7 @@ DEFINE_SPINLOCK(mx6sl_clk_lock); } \ } \ } \ + spin_unlock_irqrestore(&mx6sl_clk_lock, flags); \ result; \ }) @@ -409,6 +413,7 @@ static int _clk_pfd_enable(struct clk *clk) __raw_writel((1 << (clk->enable_shift + 7)), (int)clk->enable_reg + 8); + udelay(3); return 0; } @@ -427,7 +432,6 @@ static int _clk_pll_enable(struct clk *clk) pllbase = _get_pll_base(clk); reg = __raw_readl(pllbase); - reg &= ~ANADIG_PLL_BYPASS; reg &= ~ANADIG_PLL_POWER_DOWN; /* The 480MHz PLLs have the opposite definition for power bit. */ @@ -447,6 +451,7 @@ static int _clk_pll_enable(struct clk *clk) /* Enable the PLL output now*/ reg = __raw_readl(pllbase); + reg &= ~ANADIG_PLL_BYPASS; reg |= ANADIG_PLL_ENABLE; __raw_writel(reg, pllbase); @@ -466,7 +471,18 @@ static void _clk_pll_disable(struct clk *clk) reg = __raw_readl(pllbase); reg |= ANADIG_PLL_BYPASS; - reg &= ~ANADIG_PLL_ENABLE; + 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) + reg &= ~ANADIG_PLL_POWER_DOWN; + + /* PLL1, PLL2, PLL3, PLL7 should not disable the ENABLE bit. + * The output of these PLLs maybe used even if they are bypassed. + */ + if (clk == &pll4_audio_main_clk || clk == &pll5_video_main_clk || + clk == &pll6_enet_main_clk) + reg &= ~ANADIG_PLL_ENABLE; __raw_writel(reg, pllbase); @@ -505,7 +521,7 @@ static int _clk_pll1_main_set_rate(struct clk *clk, unsigned long rate) /* Wait for PLL1 to lock */ if (!WAIT((__raw_readl(PLL1_SYS_BASE_ADDR) & ANADIG_PLL_LOCK), SPIN_DELAY)) - panic("pll1 enable failed\n"); + panic("pll1 set rate failed\n"); return 0; } @@ -531,8 +547,7 @@ static void _clk_pll1_main_disable(struct clk *clk) * requires PLL1 to be enabled. */ reg = __raw_readl(pllbase); - reg |= ANADIG_PLL_BYPASS; - + reg |= (ANADIG_PLL_BYPASS | ANADIG_PLL_POWER_DOWN); __raw_writel(reg, pllbase); } @@ -1140,6 +1155,11 @@ static int _clk_arm_set_rate(struct clk *clk, unsigned long rate) if (i >= cpu_op_nr) return -EINVAL; + if (clk_get_rate(&ahb_clk) == 24000000) { + printk(KERN_INFO "we should not be here!!!!! AHB is at 24MHz....cpu_rate requested = %ld\n", rate); + dump_stack(); + BUG(); + } spin_lock_irqsave(&mx6sl_clk_lock, flags); if (rate <= clk_get_rate(&pll2_pfd2_400M)) { @@ -1147,15 +1167,27 @@ static int _clk_arm_set_rate(struct clk *clk, unsigned long rate) * PLL2_PFD2_400M. */ if (pll1_sw_clk.parent != &pll2_pfd2_400M) { - pll2_pfd2_400M.enable(&pll2_pfd2_400M); + if (pll2_pfd2_400M.usecount == 0) { + /* Check if PLL2 needs to be enabled also. */ + if (pll2_528_bus_main_clk.usecount == 0) + pll2_528_bus_main_clk.enable(&pll2_528_bus_main_clk); + /* Ensure parent usecount is + * also incremented. + */ + pll2_528_bus_main_clk.usecount++; + pll2_pfd2_400M.enable(&pll2_pfd2_400M); + } arm_needs_pll2_400 = true; + pll2_pfd2_400M.usecount++; pll1_sw_clk.set_parent(&pll1_sw_clk, &pll2_pfd2_400M); pll1_sw_clk.parent = &pll2_pfd2_400M; } } else { /* Make sure PLL1 is enabled */ - if (!pll1_enabled) + if (!pll1_enabled) { pll1_sys_main_clk.enable(&pll1_sys_main_clk); + pll1_sys_main_clk.usecount = 1; + } if (cpu_op_tbl[i].pll_rate != clk_get_rate(&pll1_sys_main_clk)) { if (pll1_sw_clk.parent == &pll1_sys_main_clk) { /* Change the PLL1 rate. */ @@ -1173,9 +1205,20 @@ static int _clk_arm_set_rate(struct clk *clk, unsigned long rate) } pll1_sw_clk.set_parent(&pll1_sw_clk, &pll1_sys_main_clk); pll1_sw_clk.parent = &pll1_sys_main_clk; + + if (arm_needs_pll2_400) { + pll2_pfd2_400M.usecount--; + if (pll2_pfd2_400M.usecount == 0) { + pll2_pfd2_400M.disable(&pll2_pfd2_400M); + /* Ensure parent usecount is + * also decremented. + */ + pll2_528_bus_main_clk.usecount--; + if (pll2_528_bus_main_clk.usecount == 0) + pll2_528_bus_main_clk.disable(&pll2_528_bus_main_clk); + } + } arm_needs_pll2_400 = false; - if (pll2_pfd2_400M.usecount == 0) - pll2_pfd2_400M.disable(&pll2_pfd2_400M); } parent_rate = clk_get_rate(clk->parent); div = parent_rate / rate; @@ -1211,8 +1254,10 @@ static int _clk_arm_set_rate(struct clk *clk, unsigned long rate) while (__raw_readl(MXC_CCM_CDHIPR)) ; - if (pll1_sys_main_clk.usecount == 1 && arm_needs_pll2_400) + if (pll1_sys_main_clk.usecount == 1 && arm_needs_pll2_400) { pll1_sys_main_clk.disable(&pll1_sys_main_clk); + pll1_sys_main_clk.usecount = 0; + } spin_unlock_irqrestore(&mx6sl_clk_lock, flags); @@ -1266,7 +1311,7 @@ static int _clk_periph_set_parent(struct clk *clk, struct clk *parent) reg &= ~MXC_CCM_CBCMR_PRE_PERIPH_CLK_SEL_MASK; reg |= mux << MXC_CCM_CBCMR_PRE_PERIPH_CLK_SEL_OFFSET; __raw_writel(reg, MXC_CCM_CBCMR); - + udelay(5); /* Set the periph_clk_sel multiplexer. */ reg = __raw_readl(MXC_CCM_CBCDR); reg &= ~MXC_CCM_CBCDR_PERIPH_CLK_SEL; @@ -1433,6 +1478,7 @@ static int _clk_ahb_set_rate(struct clk *clk, unsigned long rate) div = parent_rate / rate; if (div == 0) div++; + if (((parent_rate / div) != rate) || (div > 8)) return -EINVAL; @@ -2080,6 +2126,7 @@ static struct clk usdhc1_clk = { .round_rate = _clk_usdhc_round_rate, .set_rate = _clk_usdhc1_set_rate, .get_rate = _clk_usdhc1_get_rate, + .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE, }; static int _clk_usdhc2_set_parent(struct clk *clk, struct clk *parent) @@ -2137,6 +2184,7 @@ static struct clk usdhc2_clk = { .round_rate = _clk_usdhc_round_rate, .set_rate = _clk_usdhc2_set_rate, .get_rate = _clk_usdhc2_get_rate, + .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE, }; static int _clk_usdhc3_set_parent(struct clk *clk, struct clk *parent) @@ -2195,6 +2243,7 @@ static struct clk usdhc3_clk = { .round_rate = _clk_usdhc_round_rate, .set_rate = _clk_usdhc3_set_rate, .get_rate = _clk_usdhc3_get_rate, + .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE, }; static int _clk_usdhc4_set_parent(struct clk *clk, struct clk *parent) @@ -2253,6 +2302,7 @@ static struct clk usdhc4_clk = { .round_rate = _clk_usdhc_round_rate, .set_rate = _clk_usdhc4_set_rate, .get_rate = _clk_usdhc4_get_rate, + .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE, }; static unsigned long _clk_ssi_round_rate(struct clk *clk, @@ -2424,7 +2474,7 @@ static struct clk ssi1_clk = { #else .secondary = &mmdc_ch1_axi_clk[0], #endif - .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE, + .flags = AHB_AUDIO_SET_POINT | CPU_FREQ_TRIG_UPDATE, }; static unsigned long _clk_ssi2_get_rate(struct clk *clk) @@ -2498,7 +2548,7 @@ static struct clk ssi2_clk = { #else .secondary = &mmdc_ch1_axi_clk[0], #endif - .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE, + .flags = AHB_AUDIO_SET_POINT | CPU_FREQ_TRIG_UPDATE, }; static unsigned long _clk_ssi3_get_rate(struct clk *clk) @@ -2571,7 +2621,7 @@ static struct clk ssi3_clk = { #else .secondary = &mmdc_ch1_axi_clk[0], #endif - .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE, + .flags = AHB_AUDIO_SET_POINT | CPU_FREQ_TRIG_UPDATE, }; static unsigned long _clk_epdc_lcdif_pix_round_rate(struct clk *clk, @@ -2908,7 +2958,7 @@ static struct clk lcdif_pix_clk = { .set_rate = _clk_lcdif_pix_set_rate, .round_rate = _clk_epdc_lcdif_pix_round_rate, .get_rate = _clk_lcdif_pix_get_rate, - .flags = AHB_MED_SET_POINT | CPU_FREQ_TRIG_UPDATE, + .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE, }; static struct clk epdc_pix_clk = { @@ -2923,7 +2973,7 @@ static struct clk epdc_pix_clk = { .set_rate = _clk_epdc_pix_set_rate, .round_rate = _clk_epdc_lcdif_pix_round_rate, .get_rate = _clk_epdc_pix_get_rate, - .flags = AHB_MED_SET_POINT | CPU_FREQ_TRIG_UPDATE, + .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE, }; static unsigned long _clk_spdif_round_rate(struct clk *clk, unsigned long rate) @@ -3321,6 +3371,10 @@ static unsigned long _clk_uart_get_rate(struct clk *clk) div = (reg >> MXC_CCM_CSCDR1_UART_CLK_PODF_OFFSET) + 1; val = clk_get_rate(clk->parent) / div; + /* If the parent is OSC, there is an in-built divide by 6. */ + if (clk->parent == &osc_clk) + val = val / 6; + return val; } @@ -3335,7 +3389,7 @@ static int _clk_uart_set_parent(struct clk *clk, struct clk *parent) else mux = 0; /* osc */ - reg |= mux << MXC_CCM_CSCDR2_ECSPI_CLK_SEL_OFFSET; + reg |= mux << MXC_CCM_CSCDR1_UART_CLK_SEL_OFFSET; __raw_writel(reg, MXC_CCM_CSCDR1); @@ -3960,6 +4014,8 @@ int __init mx6sl_clocks_init(unsigned long ckil, unsigned long osc, unsigned long ckih1, unsigned long ckih2) { int i; + u32 parent_rate, rate; + unsigned long ipg_clk_rate, max_arm_wait_clk; external_low_reference = ckil; external_high_reference = ckih1; @@ -3978,6 +4034,12 @@ int __init mx6sl_clocks_init(unsigned long ckil, unsigned long osc, * should be from OSC24M */ clk_set_parent(&ipg_perclk, &osc_clk); + /* Need to set IPG_PERCLK to 3MHz, so that we can + * satisfy the 2.5:1 AHB:IPG_PERCLK ratio. Since AHB + * can be dropped to as low as 8MHz in low power mode. + */ + clk_set_rate(&ipg_perclk, 3000000); + gpt_clk[0].parent = &ipg_perclk; gpt_clk[0].get_rate = NULL; @@ -4024,7 +4086,6 @@ int __init mx6sl_clocks_init(unsigned long ckil, unsigned long osc, 3 << MXC_CCM_CCGRx_CG0_OFFSET, MXC_CCM_CCGR0); } else { __raw_writel(1 << MXC_CCM_CCGRx_CG11_OFFSET | - 3 << MXC_CCM_CCGRx_CG2_OFFSET | 3 << MXC_CCM_CCGRx_CG1_OFFSET | 3 << MXC_CCM_CCGRx_CG0_OFFSET, MXC_CCM_CCGR0); } @@ -4032,9 +4093,9 @@ int __init mx6sl_clocks_init(unsigned long ckil, unsigned long osc, 3 << MXC_CCM_CCGRx_CG11_OFFSET, MXC_CCM_CCGR1); __raw_writel(1 << MXC_CCM_CCGRx_CG12_OFFSET | 1 << MXC_CCM_CCGRx_CG11_OFFSET | - 3 << MXC_CCM_CCGRx_CG10_OFFSET | - 3 << MXC_CCM_CCGRx_CG9_OFFSET | - 3 << MXC_CCM_CCGRx_CG8_OFFSET, MXC_CCM_CCGR2); + 1 << MXC_CCM_CCGRx_CG10_OFFSET | + 1 << MXC_CCM_CCGRx_CG9_OFFSET | + 1 << MXC_CCM_CCGRx_CG8_OFFSET, MXC_CCM_CCGR2); __raw_writel(1 << MXC_CCM_CCGRx_CG14_OFFSET | 3 << MXC_CCM_CCGRx_CG13_OFFSET | 3 << MXC_CCM_CCGRx_CG12_OFFSET | @@ -4067,6 +4128,20 @@ int __init mx6sl_clocks_init(unsigned long ckil, unsigned long osc, lp_high_freq = 0; lp_med_freq = 0; + /* Get current ARM_PODF value */ + rate = clk_get_rate(&cpu_clk); + parent_rate = clk_get_rate(&pll1_sw_clk); + cur_arm_podf = parent_rate / rate; + + /* Calculate the ARM_PODF to be applied when the system + * enters WAIT state. + * The max ARM clk is decided by the ipg_clk and has to + * follow the ratio of ARM_CLK:IPG_CLK of 12:5. + */ + ipg_clk_rate = clk_get_rate(&ipg_clk); + max_arm_wait_clk = (12 * ipg_clk_rate) / 5; + wait_mode_arm_podf = parent_rate / max_arm_wait_clk; + return 0; } diff --git a/arch/arm/mach-mx6/cpu_op-mx6.c b/arch/arm/mach-mx6/cpu_op-mx6.c index b8d06e2ad09a..7e054c1d743c 100644 --- a/arch/arm/mach-mx6/cpu_op-mx6.c +++ b/arch/arm/mach-mx6/cpu_op-mx6.c @@ -24,70 +24,127 @@ extern u32 arm_max_freq; static int num_cpu_op; /* working point(wp): 0 - 1.2GHz; 1 - 792MHz, 2 - 498MHz 3 - 396MHz */ -static struct cpu_op mx6_cpu_op_1_2G[] = { +static struct cpu_op mx6q_cpu_op_1_2G[] = { { .pll_rate = 1200000000, .cpu_rate = 1200000000, .cpu_podf = 0, - .pu_voltage = 1250000, - .soc_voltage = 1250000, + .pu_voltage = 1275000, + .soc_voltage = 1275000, .cpu_voltage = 1275000,}, { .pll_rate = 792000000, .cpu_rate = 792000000, .cpu_podf = 0, - .pu_voltage = 1150000, - .soc_voltage = 1150000, - .cpu_voltage = 1100000,}, +#ifdef CONFIG_MX6_VPU_352M + /*VPU 352Mhz need voltage 1.25V*/ + .pu_voltage = 1250000, + .soc_voltage = 1250000, +#else + .pu_voltage = 1175000, + .soc_voltage = 1175000, +#endif + .cpu_voltage = 1150000,}, +#ifdef CONFIG_MX6_VPU_352M + /*pll2_pfd_400M will be fix on 352M,to avoid modify other code + which assume ARM clock sourcing from pll2_pfd_400M, change cpu + freq from 396M to 352M.*/ + { + .pll_rate = 352000000, + .cpu_rate = 352000000, + .cpu_podf = 0, + .pu_voltage = 1250000, + .soc_voltage = 1250000, + .cpu_voltage = 950000,}, +#else { .pll_rate = 396000000, .cpu_rate = 396000000, .cpu_podf = 0, - .pu_voltage = 1150000, - .soc_voltage = 1150000, - .cpu_voltage = 925000,}, + .pu_voltage = 1175000, + .soc_voltage = 1175000, + .cpu_voltage = 950000,}, +#endif }; /* working point(wp): 0 - 1GHz; 1 - 792MHz, 2 - 498MHz 3 - 396MHz */ -static struct cpu_op mx6_cpu_op_1G[] = { +static struct cpu_op mx6q_cpu_op_1G[] = { { .pll_rate = 996000000, .cpu_rate = 996000000, .cpu_podf = 0, - .pu_voltage = 1200000, - .soc_voltage = 1200000, - .cpu_voltage = 1225000,}, + .pu_voltage = 1250000, + .soc_voltage = 1250000, + .cpu_voltage = 1250000,}, { .pll_rate = 792000000, .cpu_rate = 792000000, .cpu_podf = 0, - .pu_voltage = 1150000, - .soc_voltage = 1150000, - .cpu_voltage = 1100000,}, +#ifdef CONFIG_MX6_VPU_352M + /*VPU 352Mhz need voltage 1.25V*/ + .pu_voltage = 1250000, + .soc_voltage = 1250000, +#else + .pu_voltage = 1175000, + .soc_voltage = 1175000, +#endif + .cpu_voltage = 1150000,}, +#ifdef CONFIG_MX6_VPU_352M + /*pll2_pfd_400M will be fix on 352M,to avoid modify other code + which assume ARM clock sourcing from pll2_pfd_400M, change cpu + freq from 396M to 352M.*/ + { + .pll_rate = 352000000, + .cpu_rate = 352000000, + .cpu_podf = 0, + .pu_voltage = 1250000, + .soc_voltage = 1250000, + .cpu_voltage = 950000,}, +#else { .pll_rate = 396000000, .cpu_rate = 396000000, .cpu_podf = 0, - .pu_voltage = 1150000, - .soc_voltage = 1150000, - .cpu_voltage = 925000,}, + .pu_voltage = 1175000, + .soc_voltage = 1175000, + .cpu_voltage = 950000,}, +#endif }; -static struct cpu_op mx6_cpu_op[] = { +static struct cpu_op mx6q_cpu_op[] = { { .pll_rate = 792000000, .cpu_rate = 792000000, .cpu_podf = 0, - .pu_voltage = 1150000, - .soc_voltage = 1150000, - .cpu_voltage = 1100000,}, +#ifdef CONFIG_MX6_VPU_352M + /*VPU 352Mhz need voltage 1.25V*/ + .pu_voltage = 1250000, + .soc_voltage = 1250000, +#else + .pu_voltage = 1175000, + .soc_voltage = 1175000, +#endif + .cpu_voltage = 1150000,}, +#ifdef CONFIG_MX6_VPU_352M + /*pll2_pfd_400M will be fix on 352M,to avoid modify other code + which assume ARM clock sourcing from pll2_pfd_400M, change cpu + freq from 396M to 352M.*/ + { + .pll_rate = 352000000, + .cpu_rate = 352000000, + .cpu_podf = 0, + .pu_voltage = 1250000, + .soc_voltage = 1250000, + .cpu_voltage = 950000,}, +#else { .pll_rate = 396000000, .cpu_rate = 396000000, .cpu_podf = 0, - .pu_voltage = 1150000, - .soc_voltage = 1150000, - .cpu_voltage = 925000,}, + .pu_voltage = 1175000, + .soc_voltage = 1175000, + .cpu_voltage = 950000,}, +#endif }; /* working point(wp): 0 - 1.2GHz; 1 - 800MHz, 2 - 400MHz, 3 - 200MHz */ @@ -96,23 +153,23 @@ static struct cpu_op mx6dl_cpu_op_1_2G[] = { .pll_rate = 1200000000, .cpu_rate = 1200000000, .cpu_podf = 0, - .pu_voltage = 1250000, - .soc_voltage = 1250000, + .pu_voltage = 1275000, + .soc_voltage = 1275000, .cpu_voltage = 1275000,}, { .pll_rate = 792000000, .cpu_rate = 792000000, .cpu_podf = 0, - .pu_voltage = 1150000, - .soc_voltage = 1150000, - .cpu_voltage = 1100000,}, + .pu_voltage = 1175000, + .soc_voltage = 1175000, + .cpu_voltage = 1150000,}, { .pll_rate = 396000000, .cpu_rate = 396000000, .cpu_podf = 0, - .pu_voltage = 1150000, - .soc_voltage = 1150000, - .cpu_voltage = 1025000,}, + .pu_voltage = 1175000, + .soc_voltage = 1175000, + .cpu_voltage = 1075000,}, }; /* working point(wp): 0 - 1GHz; 1 - 800MHz, 2 - 400MHz, 3 - 200MHz */ static struct cpu_op mx6dl_cpu_op_1G[] = { @@ -120,39 +177,98 @@ static struct cpu_op mx6dl_cpu_op_1G[] = { .pll_rate = 996000000, .cpu_rate = 996000000, .cpu_podf = 0, - .pu_voltage = 1200000, - .soc_voltage = 1200000, - .cpu_voltage = 1225000,}, + .pu_voltage = 1250000, + .soc_voltage = 1250000, + .cpu_voltage = 1250000,}, { .pll_rate = 792000000, .cpu_rate = 792000000, .cpu_podf = 0, - .pu_voltage = 1150000, - .soc_voltage = 1150000, - .cpu_voltage = 1100000,}, + .pu_voltage = 1175000, + .soc_voltage = 1175000, + .cpu_voltage = 1150000,}, { .pll_rate = 396000000, .cpu_rate = 396000000, .cpu_podf = 0, - .pu_voltage = 1150000, - .soc_voltage = 1150000, - .cpu_voltage = 1025000,}, + .pu_voltage = 1175000, + .soc_voltage = 1175000, + .cpu_voltage = 1075000,}, }; static struct cpu_op mx6dl_cpu_op[] = { { .pll_rate = 792000000, .cpu_rate = 792000000, .cpu_podf = 0, + .pu_voltage = 1175000, + .soc_voltage = 1175000, + .cpu_voltage = 1150000,}, + { + .pll_rate = 396000000, + .cpu_rate = 396000000, + .cpu_podf = 0, + .pu_voltage = 1175000, + .soc_voltage = 1175000, + .cpu_voltage = 1075000,}, +}; + +static struct cpu_op mx6sl_cpu_op_1G[] = { + { + .pll_rate = 996000000, + .cpu_rate = 996000000, + .cpu_podf = 0, + .pu_voltage = 1225000, + .soc_voltage = 1225000, + .cpu_voltage = 1275000,}, + { + .pll_rate = 792000000, + .cpu_rate = 792000000, + .cpu_podf = 0, .pu_voltage = 1150000, .soc_voltage = 1150000, + .cpu_voltage = 1200000,}, + { + .pll_rate = 396000000, + .pll_lpm_rate = 792000000, + .cpu_rate = 396000000, + .cpu_podf = 0, + .pu_voltage = 1050000, + .soc_voltage = 1050000, .cpu_voltage = 1100000,}, { .pll_rate = 396000000, + .pll_lpm_rate = 792000000, + .cpu_rate = 198000000, + .cpu_podf = 1, + .pu_voltage = 1050000, + .soc_voltage = 1050000, + .cpu_voltage = 1050000,}, +}; + +static struct cpu_op mx6sl_cpu_op[] = { + { + .pll_rate = 792000000, + .cpu_rate = 792000000, + .cpu_podf = 0, + .pu_voltage = 1150000, + .soc_voltage = 1150000, + .cpu_voltage = 1200000,}, + { + .pll_rate = 396000000, + .pll_lpm_rate = 792000000, .cpu_rate = 396000000, .cpu_podf = 0, - .pu_voltage = 1150000, - .soc_voltage = 1150000, - .cpu_voltage = 1025000,}, + .pu_voltage = 1050000, + .soc_voltage = 1050000, + .cpu_voltage = 1100000,}, + { + .pll_rate = 396000000, + .pll_lpm_rate = 792000000, + .cpu_rate = 198000000, + .cpu_podf = 1, + .pu_voltage = 1050000, + .soc_voltage = 1050000, + .cpu_voltage = 1050000,}, }; static struct dvfs_op dvfs_core_setpoint_1_2G[] = { @@ -201,16 +317,24 @@ struct cpu_op *mx6_get_cpu_op(int *op) *op = num_cpu_op = ARRAY_SIZE(mx6dl_cpu_op); return mx6dl_cpu_op; } - } else { + } else if (cpu_is_mx6q()) { if (arm_max_freq == CPU_AT_1_2GHz) { - *op = num_cpu_op = ARRAY_SIZE(mx6_cpu_op_1_2G); - return mx6_cpu_op_1_2G; + *op = num_cpu_op = ARRAY_SIZE(mx6q_cpu_op_1_2G); + return mx6q_cpu_op_1_2G; } else if (arm_max_freq == CPU_AT_1GHz) { - *op = num_cpu_op = ARRAY_SIZE(mx6_cpu_op_1G); - return mx6_cpu_op_1G; + *op = num_cpu_op = ARRAY_SIZE(mx6q_cpu_op_1G); + return mx6q_cpu_op_1G; + } else { + *op = num_cpu_op = ARRAY_SIZE(mx6q_cpu_op); + return mx6q_cpu_op; + } + } else { + if (arm_max_freq == CPU_AT_1GHz) { + *op = num_cpu_op = ARRAY_SIZE(mx6sl_cpu_op_1G); + return mx6sl_cpu_op_1G; } else { - *op = num_cpu_op = ARRAY_SIZE(mx6_cpu_op); - return mx6_cpu_op; + *op = num_cpu_op = ARRAY_SIZE(mx6sl_cpu_op); + return mx6sl_cpu_op; } } } diff --git a/arch/arm/mach-mx6/devices-imx6q.h b/arch/arm/mach-mx6/devices-imx6q.h index 105e1f6d0a0e..bd948cecbcd2 100644 --- a/arch/arm/mach-mx6/devices-imx6q.h +++ b/arch/arm/mach-mx6/devices-imx6q.h @@ -158,10 +158,6 @@ extern const struct imx_imx_asrc_data imx6q_imx_asrc_data[] __initconst; #define imx6q_add_asrc(pdata) \ imx_add_imx_asrc(imx6q_imx_asrc_data, pdata) -extern const struct imx_spi_imx_data imx6q_ecspi_data[] __initconst; -#define imx6q_add_ecspi(id, pdata) \ - imx_add_spi_imx(&imx6q_ecspi_data[id], pdata) - extern const struct imx_dvfs_core_data imx6q_dvfs_core_data __initconst; #define imx6q_add_dvfs_core(pdata) \ imx_add_dvfs_core(&imx6q_dvfs_core_data, pdata) @@ -220,6 +216,9 @@ extern const struct imx_pxp_data imx6dl_pxp_data __initconst; #define imx6dl_add_imx_pxp_client() \ imx_add_imx_pxp_client() +#define imx6sl_add_imx_pxp_v4l2() \ + imx_add_imx_pxp_v4l2() + extern const struct imx_epdc_data imx6dl_epdc_data __initconst; #define imx6dl_add_imx_epdc(pdata) \ imx_add_imx_epdc(&imx6dl_epdc_data, pdata) diff --git a/arch/arm/mach-mx6/irq.c b/arch/arm/mach-mx6/irq.c index 5131eae3a040..0498cd90e8e8 100644 --- a/arch/arm/mach-mx6/irq.c +++ b/arch/arm/mach-mx6/irq.c @@ -65,6 +65,14 @@ static struct irq_tuner mxc_irq_tuner[] = { .up_threshold = 0, .enable = 0,}, { + .irq_number = 42, /* GPU 2D */ + .up_threshold = 40, + .enable = 1,}, + { + .irq_number = 43, /* GPU VG */ + .up_threshold = 0, + .enable = 1,}, + { .irq_number = 54, /* uSDHC1 */ .up_threshold = 4, .enable = 1,}, @@ -103,6 +111,7 @@ void mx6_init_irq(void) void __iomem *gpc_base = IO_ADDRESS(GPC_BASE_ADDR); struct irq_desc *desc; unsigned int i; + u32 reg; /* start offset if private timer irq id, which is 29. * ID table: @@ -121,6 +130,13 @@ void mx6_init_irq(void) __raw_writel(0x20000000, gpc_base + 0x10); } +#ifdef CONFIG_MX6_INTER_LDO_BYPASS + /* Mask the ANATOP brown out interrupt in the GPC. */ + reg = __raw_readl(gpc_base + 0x14); + reg |= 0x80000000; + __raw_writel(reg, gpc_base + 0x14); +#endif + for (i = MXC_INT_START; i <= MXC_INT_END; i++) { desc = irq_to_desc(i); desc->irq_data.chip->irq_set_wake = mx6_gic_irq_set_wake; diff --git a/arch/arm/mach-mx6/mx6_anatop_regulator.c b/arch/arm/mach-mx6/mx6_anatop_regulator.c index 06755dc7a4ee..945adbdb759a 100644 --- a/arch/arm/mach-mx6/mx6_anatop_regulator.c +++ b/arch/arm/mach-mx6/mx6_anatop_regulator.c @@ -125,10 +125,12 @@ static int pu_enable(struct anatop_regulator *sreg) reg |= ANADIG_ANA_MISC2_REG1_BO_EN; __raw_writel(reg, ANA_MISC2_BASE_ADDR); +#ifndef CONFIG_MX6_INTER_LDO_BYPASS /* Unmask the ANATOP brown out interrupt in the GPC. */ reg = __raw_readl(gpc_base + 0x14); reg &= ~0x80000000; __raw_writel(reg, gpc_base + 0x14); +#endif return 0; } @@ -162,10 +164,12 @@ static int pu_disable(struct anatop_regulator *sreg) while (__raw_readl(gpc_base + GPC_CNTR_OFFSET) & 0x1) ; +#ifndef CONFIG_MX6_INTER_LDO_BYPASS /* Mask the ANATOP brown out interrupt in the GPC. */ reg = __raw_readl(gpc_base + 0x14); reg |= 0x80000000; __raw_writel(reg, gpc_base + 0x14); +#endif /* PU power gating. */ reg = __raw_readl(ANADIG_REG_CORE); diff --git a/arch/arm/mach-mx6/mx6_suspend.S b/arch/arm/mach-mx6/mx6_suspend.S index 59b676038427..a9b7e30cd85a 100644 --- a/arch/arm/mach-mx6/mx6_suspend.S +++ b/arch/arm/mach-mx6/mx6_suspend.S @@ -85,8 +85,7 @@ r2: suspend_iram_base ldr r4, [r1, #0x330] /* DRAM_SDCKE0 */ ldr r5, [r1, #0x334] /* DRAM_SDCKE1 */ ldr r6, [r1, #0x320] /* DRAM_RESET */ - ldr r7, [r1, #0x5c8] /* GPR_CTLDS */ - stmfd r0!, {r4-r7} + stmfd r0!, {r4-r6} .endm @@ -122,11 +121,10 @@ r2: suspend_iram_base str r6, [r1, #0x33c] /* DRAM_SODT0*/ str r7, [r1, #0x340] /* DRAM_SODT1*/ - ldmea r0!, {r4-r7} + ldmea r0!, {r4-r6} str r4, [r1, #0x330] /* DRAM_SDCKE0 */ str r5, [r1, #0x334] /* DRAM_SDCKE1 */ str r6, [r1, #0x320] /* DRAM_RESET */ - str r7, [r1, #0x5c8] /* GPR_CTLDS */ .endm @@ -138,6 +136,13 @@ r2: suspend_iram_base str r0, [r1, #0x314] /* DRAM_DQM2 */ str r0, [r1, #0x318] /* DRAM_DQM3 */ + /* Make sure the Pull Ups are enabled. + * So only reduce the drive stength, but + * leave the pull-ups in the original state. + * This is required for LPDDR2. + */ + ldr r0, [r1, #0x344] + orr r0, r0, #0x3000 str r0, [r1, #0x344] /* DRAM_SDQS0 */ str r0, [r1, #0x348] /* DRAM_SDQS1 */ str r0, [r1, #0x34c] /* DRAM_SDQS2 */ @@ -158,7 +163,6 @@ r2: suspend_iram_base str r0, [r1, #0x33c] /* DRAM_SODT0*/ str r0, [r1, #0x340] /* DRAM_SODT1*/ - str r0, [r1, #0x5c8] /* GPR_CTLDS */ mov r0, #0x80000 str r0, [r1, #0x320] /* DRAM_RESET */ mov r0, #0x1000 diff --git a/arch/arm/mach-mx6/mx6q_sabreauto_pmic_pfuze100.c b/arch/arm/mach-mx6/mx6q_sabreauto_pmic_pfuze100.c index cc12a0224ab2..8cb4ffcc78fa 100644 --- a/arch/arm/mach-mx6/mx6q_sabreauto_pmic_pfuze100.c +++ b/arch/arm/mach-mx6/mx6q_sabreauto_pmic_pfuze100.c @@ -41,13 +41,13 @@ /*SWBST*/ #define PFUZE100_SW1ASTANDBY 33 -#define PFUZE100_SW1ASTANDBY_STBY_VAL (0x18) +#define PFUZE100_SW1ASTANDBY_STBY_VAL (0x19) #define PFUZE100_SW1ASTANDBY_STBY_M (0x3f<<0) #define PFUZE100_SW1BSTANDBY 40 -#define PFUZE100_SW1BSTANDBY_STBY_VAL (0x18) +#define PFUZE100_SW1BSTANDBY_STBY_VAL (0x19) #define PFUZE100_SW1BSTANDBY_STBY_M (0x3f<<0) #define PFUZE100_SW1CSTANDBY 47 -#define PFUZE100_SW1CSTANDBY_STBY_VAL (0x18) +#define PFUZE100_SW1CSTANDBY_STBY_VAL (0x19) #define PFUZE100_SW1CSTANDBY_STBY_M (0x3f<<0) #define PFUZE100_SW2STANDBY 54 #define PFUZE100_SW2STANDBY_STBY_VAL 0x0 diff --git a/arch/arm/mach-mx6/mx6q_sabresd_pmic_pfuze100.c b/arch/arm/mach-mx6/mx6q_sabresd_pmic_pfuze100.c index f7e7099468c1..69daddf14000 100644 --- a/arch/arm/mach-mx6/mx6q_sabresd_pmic_pfuze100.c +++ b/arch/arm/mach-mx6/mx6q_sabresd_pmic_pfuze100.c @@ -48,13 +48,13 @@ #define PFUZE100_SW1CVOL 46 #define PFUZE100_SW1CVOL_VSEL_M (0x3f<<0) #define PFUZE100_SW1ASTANDBY 33 -#define PFUZE100_SW1ASTANDBY_STBY_VAL (0x18) +#define PFUZE100_SW1ASTANDBY_STBY_VAL (0x19) #define PFUZE100_SW1ASTANDBY_STBY_M (0x3f<<0) #define PFUZE100_SW1BSTANDBY 40 -#define PFUZE100_SW1BSTANDBY_STBY_VAL (0x18) +#define PFUZE100_SW1BSTANDBY_STBY_VAL (0x19) #define PFUZE100_SW1BSTANDBY_STBY_M (0x3f<<0) #define PFUZE100_SW1CSTANDBY 47 -#define PFUZE100_SW1CSTANDBY_STBY_VAL (0x18) +#define PFUZE100_SW1CSTANDBY_STBY_VAL (0x19) #define PFUZE100_SW1CSTANDBY_STBY_M (0x3f<<0) #define PFUZE100_SW2STANDBY 54 #define PFUZE100_SW2STANDBY_STBY_VAL 0x0 @@ -74,6 +74,9 @@ #define PFUZE100_SW1ACON 36 #define PFUZE100_SW1ACON_SPEED_VAL (0x1<<6) /*default */ #define PFUZE100_SW1ACON_SPEED_M (0x3<<6) +#define PFUZE100_SW1CCON 49 +#define PFUZE100_SW1CCON_SPEED_VAL (0x1<<6) /*default */ +#define PFUZE100_SW1CCON_SPEED_M (0x3<<6) extern u32 arm_max_freq; @@ -83,6 +86,11 @@ static struct regulator_consumer_supply sw1_consumers[] = { .supply = "VDDCORE", } }; +static struct regulator_consumer_supply sw1c_consumers[] = { + { + .supply = "VDDSOC", + }, +}; #endif static struct regulator_consumer_supply sw2_consumers[] = { @@ -160,10 +168,10 @@ static struct regulator_init_data sw1a_init = { .always_on = 1, }, - #ifdef CONFIG_MX6_INTER_LDO_BYPASS +#ifdef CONFIG_MX6_INTER_LDO_BYPASS .num_consumer_supplies = ARRAY_SIZE(sw1_consumers), .consumer_supplies = sw1_consumers, - #endif +#endif }; static struct regulator_init_data sw1b_init = { @@ -188,6 +196,10 @@ static struct regulator_init_data sw1c_init = { .always_on = 1, .boot_on = 1, }, +#ifdef CONFIG_MX6_INTER_LDO_BYPASS + .num_consumer_supplies = ARRAY_SIZE(sw1c_consumers), + .consumer_supplies = sw1c_consumers, +#endif }; static struct regulator_init_data sw2_init = { @@ -421,12 +433,17 @@ static int pfuze100_init(struct mc_pfuze *pfuze) PFUZE100_SW1CSTANDBY_STBY_VAL); if (ret) goto err; - /*set SW1ABDVSPEED as 25mV step each 4us,quick than 16us before.*/ + /*set SW1AB/1C DVSPEED as 25mV step each 4us,quick than 16us before.*/ ret = pfuze_reg_rmw(pfuze, PFUZE100_SW1ACON, PFUZE100_SW1ACON_SPEED_M, PFUZE100_SW1ACON_SPEED_VAL); if (ret) goto err; + ret = pfuze_reg_rmw(pfuze, PFUZE100_SW1CCON, + PFUZE100_SW1CCON_SPEED_M, + PFUZE100_SW1CCON_SPEED_VAL); + if (ret) + goto err; return 0; err: printk(KERN_ERR "pfuze100 init error!\n"); diff --git a/arch/arm/mach-mx6/mx6sl_arm2_pmic_pfuze100.c b/arch/arm/mach-mx6/mx6sl_arm2_pmic_pfuze100.c index 0c3f1b20d361..134700a6d200 100644 --- a/arch/arm/mach-mx6/mx6sl_arm2_pmic_pfuze100.c +++ b/arch/arm/mach-mx6/mx6sl_arm2_pmic_pfuze100.c @@ -66,6 +66,9 @@ #define PFUZE100_SW1ACON 36 #define PFUZE100_SW1ACON_SPEED_VAL (0x1<<6) /*default */ #define PFUZE100_SW1ACON_SPEED_M (0x3<<6) +#define PFUZE100_SW1CCON 49 +#define PFUZE100_SW1CCON_SPEED_VAL (0x1<<6) /*default */ +#define PFUZE100_SW1CCON_SPEED_M (0x3<<6) #ifdef CONFIG_MX6_INTER_LDO_BYPASS @@ -74,6 +77,11 @@ static struct regulator_consumer_supply sw1_consumers[] = { .supply = "VDDCORE", } }; +static struct regulator_consumer_supply sw1c_consumers[] = { + { + .supply = "VDDSOC", + }, +}; #endif static struct regulator_consumer_supply sw2_consumers[] = { @@ -151,10 +159,10 @@ static struct regulator_init_data sw1a_init = { .boot_on = 1, .always_on = 1, }, - #ifdef CONFIG_MX6_INTER_LDO_BYPASS +#ifdef CONFIG_MX6_INTER_LDO_BYPASS .num_consumer_supplies = ARRAY_SIZE(sw1_consumers), .consumer_supplies = sw1_consumers, - #endif +#endif }; static struct regulator_init_data sw1b_init = { @@ -179,6 +187,10 @@ static struct regulator_init_data sw1c_init = { .always_on = 1, .boot_on = 1, }, + #ifdef CONFIG_MX6_INTER_LDO_BYPASS + .num_consumer_supplies = ARRAY_SIZE(sw1c_consumers), + .consumer_supplies = sw1c_consumers, + #endif }; static struct regulator_init_data sw2_init = { @@ -298,8 +310,8 @@ static struct regulator_init_data vgen1_init = { .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS, .valid_modes_mask = 0, - .always_on = 0, - .boot_on = 0, + .always_on = 1, + .boot_on = 1, }, .num_consumer_supplies = ARRAY_SIZE(vgen1_consumers), .consumer_supplies = vgen1_consumers, @@ -345,6 +357,8 @@ static struct regulator_init_data vgen4_init = { .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS, .valid_modes_mask = 0, + .always_on = 1, + .boot_on = 1, }, .num_consumer_supplies = ARRAY_SIZE(vgen4_consumers), .consumer_supplies = vgen4_consumers, @@ -389,12 +403,17 @@ static int pfuze100_init(struct mc_pfuze *pfuze) PFUZE100_SW1CSTANDBY_STBY_VAL); if (ret) goto err; - /*set SW1ABDVSPEED as 25mV step each 4us,quick than 16us before.*/ + /*set SW1AB/SW1C DVSPEED as 25mV step each 4us,quick than 16us before.*/ ret = pfuze_reg_rmw(pfuze, PFUZE100_SW1ACON, PFUZE100_SW1ACON_SPEED_M, PFUZE100_SW1ACON_SPEED_VAL); if (ret) goto err; + ret = pfuze_reg_rmw(pfuze, PFUZE100_SW1CCON, + PFUZE100_SW1CCON_SPEED_M, + PFUZE100_SW1CCON_SPEED_VAL); + if (ret) + goto err; return 0; err: printk(KERN_ERR "pfuze100 init error!\n"); diff --git a/arch/arm/mach-mx6/mx6sl_ddr.S b/arch/arm/mach-mx6/mx6sl_ddr.S new file mode 100644 index 000000000000..3059f3aa3c8c --- /dev/null +++ b/arch/arm/mach-mx6/mx6sl_ddr.S @@ -0,0 +1,432 @@ +/* + * Copyright (C) 2012 Freescale Semiconductor, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include <linux/linkage.h> +#include <mach/hardware.h> + + + .macro mx6sl_switch_to_24MHz + + /* Set MMDC clock to be sourced from PLL3. */ + /* Ensure first periph2_clk2 is sourced from PLL3. */ + /* Set the PERIPH2_CLK2_PODF to divide by 2. */ + ldr r6, [r2, #0x14] + bic r6, r6, #0x7 + orr r6, r6, #0x1 + str r6, [r2, #0x14] + + /* Select PLL3 to source MMDC. */ + ldr r6, [r2, #0x18] + bic r6, r6, #0x100000 + str r6, [r2, #0x18] + + /* Swtich periph2_clk_sel to run from PLL3. */ + ldr r6, [r2, #0x14] + orr r6, r6, #0x4000000 + str r6, [r2, #0x14] + +periph2_clk_switch1: + ldr r6, [r2, #0x48] + cmp r6, #0 + bne periph2_clk_switch1 + + /* Need to clock gate the 528 PFDs before + * powering down PLL2. + * Only the PLL2_PFD2_400M should be ON + * as it feeds the MMDC + */ + ldr r6, [r3, #0x100] + orr r6, r6, #0x800000 + str r6, [r3, #0x100] + + /* Set PLL2 to bypass state. We should be here + *only if MMDC is not sourced from PLL2.*/ + ldr r6, [r3, #0x30] + orr r6, r6, #0x10000 + str r6, [r3, #0x30] + + ldr r6, [r3, #0x30] + orr r6, r6, #0x1000 + str r6, [r3, #0x30] + + /* Ensure pre_periph2_clk_mux is set to pll2 */ + ldr r6, [r2, #0x18] + bic r6, r6, #0x600000 + str r6, [r2, #0x18] + + /* Set MMDC clock to be sourced from the bypassed PLL2. */ + ldr r6, [r2, #0x14] + bic r6, r6, #0x4000000 + str r6, [r2, #0x14] + +periph2_clk_switch2: + ldr r6, [r2, #0x48] + cmp r6, #0 + bne periph2_clk_switch2 + + /* Now move MMDC back to periph2_clk2 source. + * after selecting PLL2 as the option. + */ + /* Select PLL2 as the source. */ + ldr r6, [r2, #0x18] + orr r6, r6, #0x100000 + str r6, [r2, #0x18] + + /* set periph2_clk2_podf to divide by 1. */ + ldr r6, [r2, #0x14] + bic r6, r6, #0x7 + str r6, [r2, #0x14] + + /* Now move periph2_clk to periph2_clk2 source */ + ldr r6, [r2, #0x14] + orr r6, r6, #0x4000000 + str r6, [r2, #0x14] + +periph2_clk_switch3: + ldr r6, [r2, #0x48] + cmp r6, #0 + bne periph2_clk_switch3 + + /* Now set the MMDC PODF back to 1.*/ + ldr r6, [r2, #0x14] + bic r6, r6, #0x38 + str r6, [r2, #0x14] + +mmdc_podf0: + ldr r6, [r2, #0x48] + cmp r6, #0 + bne mmdc_podf0 + + .endm + + .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 + cmp r6, #0x10000 + beq pll3_in_bypass + /* Set MMDC divder to divide by 2. */ + ldr r6, [r2, #0x14] + bic r6, r6, #0x38 + orr r6, r6, #0x8 + str r6, [r2, #0x14] + +mmdc_podf: + ldr r6, [r2, #0x48] + cmp r6, #0 + bne mmdc_podf + +pll3_in_bypass: + + /* Ensure that MMDC is sourced from PLL2 mux first. */ + ldr r6, [r2, #0x14] + bic r6, r6, #0x4000000 + str r6, [r2, #0x14] + +periph2_clk_switch4: + ldr r6, [r2, #0x48] + cmp r6, #0 + bne periph2_clk_switch4 + + /* Now ensure periph2_clk2_sel mux is set to PLL3 */ + ldr r6, [r2, #0x18] + bic r6, r6, #0x100000 + str r6, [r2, #0x18] + + /* Now switch MMDC to PLL3. */ + ldr r6, [r2, #0x14] + orr r6, r6, #0x4000000 + str r6, [r2, #0x14] + +periph2_clk_switch5: + ldr r6, [r2, #0x48] + cmp r6, #0 + bne periph2_clk_switch5 + + /* Now power up PLL2 and unbypass it. */ + ldr r6, [r3, #0x30] + bic r6, r6, #0x1000 + str r6, [r3, #0x30] + + /* Make sure PLL2 has locked.*/ +wait_for_pll_lock: + ldr r6, [r3, #0x30] + and r6, r6, #0x80000000 + cmp r6, #0x80000000 + bne wait_for_pll_lock + + ldr r6, [r3, #0x30] + bic r6, r6, #0x10000 + str r6, [r3, #0x30] + + /* Need to enable the 528 PFDs after + * powering up PLL2. + * Only the PLL2_PFD2_400M should be ON + * as it feeds the MMDC. Rest should have + * been managed by clock code. + */ + ldr r6, [r3, #0x100] + bic r6, r6, #0x800000 + str r6, [r3, #0x100] + + /* Now switch MMDC clk back to pll2_mux option. */ + /* Ensure pre_periph2_clk2 is set to pll2_pfd_400M */ + ldr r6, [r2, #0x18] + bic r6, r6, #0x600000 + orr r6, r6, #0x200000 + str r6, [r2, #0x18] + + ldr r6, [r2, #0x14] + bic r6, r6, #0x4000000 + str r6, [r2, #0x14] + +periph2_clk_switch6: + ldr r6, [r2, #0x48] + cmp r6, #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 + cmp r6, r0 + blt Div_Found + add r4, r4, #1 + bgt Loop2 + + /* Shift divider into correct offset. */ + lsl r4, r4, #3 +Div_Found: + /* Set the MMDC PODF. */ + ldr r6, [r2, #0x14] + bic r6, r6, #0x38 + orr r6, r6, r4 + str r6, [r2, #0x14] + +mmdc_podf1: + ldr r6, [r2, #0x48] + cmp r6, #0 + bne mmdc_podf1 + + .endm + + .macro mmdc_clk_lower_100MHz + + /* Prior to reducing the DDR frequency (at 528/400 MHz), + read the Measure unit count bits (MU_UNIT_DEL_NUM) */ + ldr r5, =0x8B8 + ldr r6, [r8, r5] + /* Original MU unit count */ + mov r6, r6, LSR #16 + ldr r4, =0x3FF + and r6, r6, r4 + /* Original MU unit count * 2 */ + mov r7, r6, LSL #1 + /* Bypass the automatic measure unit when below 100 MHz + by setting the Measure unit bypass enable bit (MU_BYP_EN) */ + ldr r6, [r8, r5] + orr r6, r6, #0x400 + str r6, [r8, r5] + /* Double the measure count value read in step 1 and program it in the + * measurement bypass bits (MU_BYP_VAL) of the MMDC PHY Measure Unit + * Register for the reduced frequency operation below 100 MHz + */ + ldr r6, [r8, r5] + ldr r4, =0x3FF + bic r6, r6, r4 + orr r6, r6, r7 + str r6, [r8, r5] + /* Now perform a Force Measurement. */ + ldr r6, [r8, r5] + orr r6, r6, #0x800 + str r6, [r8, r5] + /* Wait for FRC_MSR to clear. */ +force_measure: + ldr r6, [r8, r5] + and r6, r6, #0x800 + cmp r6, #0x0 + bne force_measure + + .endm + + .macro mmdc_clk_above_100MHz + + /* Make sure that the PHY measurement unit is NOT in bypass mode */ + ldr r5, =0x8B8 + ldr r6, [r8, r5] + bic r6, r6, #0x400 + str r6, [r8, r5] + /* Now perform a Force Measurement. */ + ldr r6, [r8, r5] + orr r6, r6, #0x800 + str r6, [r8, r5] + /* Wait for FRC_MSR to clear. */ +force_measure1: + ldr r6, [r8, r5] + and r6, r6, #0x800 + cmp r6, #0x0 + bne force_measure1 + .endm + +/* + * mx6sl_ddr_iram + * + * Idle the processor (eg, wait for interrupt). + * Make sure DDR is in self-refresh. + * IRQs are already disabled. + * r0 : DDR freq. + * r1: low_bus_freq_mode flag + */ +ENTRY(mx6sl_ddr_iram) + + push {r4, r5, r6, r7, r8, r9, r10 } + +mx6sl_ddr_freq_change: + ldr r3, =ANATOP_BASE_ADDR + add r3, r3, #PERIPBASE_VIRT + + ldr r2, =CCM_BASE_ADDR + add r2, r2, #PERIPBASE_VIRT + + ldr r8, =MMDC_P0_BASE_ADDR + add r8, r8, #PERIPBASE_VIRT + + /* Prime all TLB entries. */ + adr r7, mx6sl_ddr_freq_change @Address in this function. + + ldr r6, [r7] + ldr r6, [r8] + ldr r6, [r3] + ldr r6, [r2] + + dsb + isb + + /* Disable Automatic power savings. */ + ldr r6, [r8, #0x404] + orr r6, r6, #0x01 + str r6, [r8, #0x404] + + /* Disable MMDC power down timer. */ + /*MMDC0_MDPDC disable power down timer */ + ldr r6, [r8, #0x4] + bic r6, r6, #0xff00 + str r6, [r8, #0x4] + + /* Delay for a while */ + ldr r10, =10 +delay1: + ldr r7, =0 +cont1: + ldr r6, [r8, r7] + add r7, r7, #4 + cmp r7, #16 + bne cont1 + sub r10, r10, #1 + cmp r10, #0 + bgt delay1 + + /* Make the DDR explicitly enter self-refresh. */ + ldr r6, [r8, #0x404] + orr r6, r6, #0x200000 + str r6, [r8, #0x404] + +poll_dvfs_set_1: + ldr r6, [r8, #0x404] + and r6, r6, #0x2000000 + cmp r6, #0x2000000 + bne poll_dvfs_set_1 + + /* set SBS step-by-step mode */ + ldr r6, [r8, #0x410] + orr r6, r6, #0x100 + str r6, [r8, #0x410] + + ldr r10, =100000000 + cmp r0, r10 + bgt set_ddr_mu_above_100 + mmdc_clk_lower_100MHz + +set_ddr_mu_above_100: + ldr r10, =24000000 + cmp r0, r10 + beq set_to_24MHz + + ddr_switch_400MHz + ldr r10, =100000000 + cmp r0, r10 + blt done + mmdc_clk_above_100MHz + b done + +set_to_24MHz: + mx6sl_switch_to_24MHz + +done: + /* clear DVFS - exit from self refresh mode */ + ldr r6, [r8, #0x404] + bic r6, r6, #0x200000 + str r6, [r8, #0x404] + +poll_dvfs_clear_1: + ldr r6, [r8, #0x404] + and r6, r6, #0x2000000 + cmp r6, #0x2000000 + beq poll_dvfs_clear_1 + + /* Enable Automatic power savings. */ + ldr r6, [r8, #0x404] + bic r6, r6, #0x01 + str r6, [r8, #0x404] + + ldr r10, =24000000 + cmp r0, r10 + beq skip_power_down + + /* Enable MMDC power down timer. */ + ldr r6, [r8, #0x4] + orr r6, r6, #0x5500 + str r6, [r8, #0x4] + +skip_power_down: + /* clear SBS - unblock DDR accesses */ + ldr r6, [r8, #0x410] + bic r6, r6, #0x100 + str r6, [r8, #0x410] + + pop {r4,r5, r6, r7, r8, r9, r10} + + /* Restore registers */ + mov pc, lr + + .type mx6sl_ddr_do_iram, #object +ENTRY(mx6sl_ddr_do_iram) + .word mx6sl_ddr_iram + .size mx6sl_ddr_iram, . - mx6sl_ddr_iram diff --git a/arch/arm/mach-mx6/mx6sl_evk_pmic_pfuze100.c b/arch/arm/mach-mx6/mx6sl_evk_pmic_pfuze100.c new file mode 100644 index 000000000000..ee66541f8bff --- /dev/null +++ b/arch/arm/mach-mx6/mx6sl_evk_pmic_pfuze100.c @@ -0,0 +1,464 @@ +/* + * Copyright (C) 2012 Freescale Semiconductor, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <linux/module.h> +#include <linux/init.h> +#include <linux/platform_device.h> +#include <linux/err.h> +#include <linux/i2c.h> +#include <linux/gpio.h> +#include <linux/regulator/machine.h> +#include <linux/mfd/pfuze.h> +#include <mach/irqs.h> + +/* + * Convenience conversion. + * Here atm, maybe there is somewhere better for this. + */ +#define mV_to_uV(mV) (mV * 1000) +#define uV_to_mV(uV) (uV / 1000) +#define V_to_uV(V) (mV_to_uV(V * 1000)) +#define uV_to_V(uV) (uV_to_mV(uV) / 1000) + +#define PFUZE100_I2C_DEVICE_NAME "pfuze100" +/* 7-bit I2C bus slave address */ +#define PFUZE100_I2C_ADDR (0x08) + /*SWBST*/ +#define PFUZE100_SW1ASTANDBY 33 +#define PFUZE100_SW1ASTANDBY_STBY_VAL (0x16) +#define PFUZE100_SW1ASTANDBY_STBY_M (0x3f<<0) +#define PFUZE100_SW1BSTANDBY 40 +#define PFUZE100_SW1BSTANDBY_STBY_VAL (0x16) +#define PFUZE100_SW1BSTANDBY_STBY_M (0x3f<<0) +#define PFUZE100_SW1CSTANDBY 47 +#define PFUZE100_SW1CSTANDBY_STBY_VAL (0x16) +#define PFUZE100_SW1CSTANDBY_STBY_M (0x3f<<0) +#define PFUZE100_SW2STANDBY 54 +#define PFUZE100_SW2STANDBY_STBY_VAL 0x0 +#define PFUZE100_SW2STANDBY_STBY_M (0x3f<<0) +#define PFUZE100_SW3ASTANDBY 61 +#define PFUZE100_SW3ASTANDBY_STBY_VAL 0x0 +#define PFUZE100_SW3ASTANDBY_STBY_M (0x3f<<0) +#define PFUZE100_SW3BSTANDBY 68 +#define PFUZE100_SW3BSTANDBY_STBY_VAL 0x0 +#define PFUZE100_SW3BSTANDBY_STBY_M (0x3f<<0) +#define PFUZE100_SW4STANDBY 75 +#define PFUZE100_SW4STANDBY_STBY_VAL 0 +#define PFUZE100_SW4STANDBY_STBY_M (0x3f<<0) +#define PFUZE100_SWBSTCON1 102 +#define PFUZE100_SWBSTCON1_SWBSTMOD_VAL (0x1<<2) +#define PFUZE100_SWBSTCON1_SWBSTMOD_M (0x3<<2) +#define PFUZE100_SW1ACON 36 +#define PFUZE100_SW1ACON_SPEED_VAL (0x1<<6) /*default */ +#define PFUZE100_SW1ACON_SPEED_M (0x3<<6) +#define PFUZE100_SW1CCON 49 +#define PFUZE100_SW1CCON_SPEED_VAL (0x1<<6) /*default */ +#define PFUZE100_SW1CCON_SPEED_M (0x3<<6) + +#ifdef CONFIG_MX6_INTER_LDO_BYPASS +static struct regulator_consumer_supply sw1_consumers[] = { + { + .supply = "VDDCORE", + } +}; +static struct regulator_consumer_supply sw1c_consumers[] = { + { + .supply = "VDDSOC", + }, +}; +#endif + +static struct regulator_consumer_supply sw2_consumers[] = { + { + .supply = "MICVDD", + .dev_name = "1-001a", + } +}; +static struct regulator_consumer_supply sw4_consumers[] = { + { + .supply = "AUD_1V8", + } +}; +static struct regulator_consumer_supply swbst_consumers[] = { + { + .supply = "SWBST_5V", + } +}; +static struct regulator_consumer_supply vgen1_consumers[] = { + { + .supply = "VGEN1_1V5", + } +}; +static struct regulator_consumer_supply vgen2_consumers[] = { + { + .supply = "VGEN2_1V5", + } +}; +static struct regulator_consumer_supply vgen3_consumers[] = { + { + .supply = "AVDD", + .dev_name = "1-001a", + }, + { + .supply = "DCVDD", + .dev_name = "1-001a", + }, + { + .supply = "CPVDD", + .dev_name = "1-001a", + }, + { + .supply = "PLLVDD", + .dev_name = "1-001a", + }, + { + .supply = "DBVDD", + .dev_name = "1-001a", + } +}; +static struct regulator_consumer_supply vgen4_consumers[] = { + { + .supply = "VGEN4_1V8", + } +}; +static struct regulator_consumer_supply vgen5_consumers[] = { + { + .supply = "VGEN5_2V8", + } +}; +static struct regulator_consumer_supply vgen6_consumers[] = { + { + .supply = "VGEN6_3V3", + } +}; + +static struct regulator_init_data sw1a_init = { + .constraints = { + .name = "PFUZE100_SW1A", +#ifdef PFUZE100_FIRST_VERSION + .min_uV = 650000, + .max_uV = 1437500, +#else + .min_uV = 300000, + .max_uV = 1875000, +#endif + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE, + .valid_modes_mask = 0, + .boot_on = 1, + .always_on = 1, + }, +#ifdef CONFIG_MX6_INTER_LDO_BYPASS + .num_consumer_supplies = ARRAY_SIZE(sw1_consumers), + .consumer_supplies = sw1_consumers, +#endif +}; + +static struct regulator_init_data sw1b_init = { + .constraints = { + .name = "PFUZE100_SW1B", + .min_uV = 300000, + .max_uV = 1875000, + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE, + .valid_modes_mask = 0, + .always_on = 1, + .boot_on = 1, + }, +}; + +static struct regulator_init_data sw1c_init = { + .constraints = { + .name = "PFUZE100_SW1C", + .min_uV = 300000, + .max_uV = 1875000, + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE, + .valid_modes_mask = 0, + .always_on = 1, + .boot_on = 1, + }, +#ifdef CONFIG_MX6_INTER_LDO_BYPASS + .num_consumer_supplies = ARRAY_SIZE(sw1c_consumers), + .consumer_supplies = sw1c_consumers, +#endif +}; + +static struct regulator_init_data sw2_init = { + .constraints = { + .name = "PFUZE100_SW2", +#if PFUZE100_SW2_VOL6 + .min_uV = 800000, + .max_uV = 3950000, +#else + .min_uV = 400000, + .max_uV = 1975000, +#endif + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE, + .valid_modes_mask = 0, + .always_on = 1, + .boot_on = 1, + }, + .num_consumer_supplies = ARRAY_SIZE(sw2_consumers), + .consumer_supplies = sw2_consumers, +}; + +static struct regulator_init_data sw3a_init = { + .constraints = { + .name = "PFUZE100_SW3A", +#if PFUZE100_SW3_VOL6 + .min_uV = 800000, + .max_uV = 3950000, +#else + .min_uV = 400000, + .max_uV = 1975000, +#endif + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE, + .valid_modes_mask = 0, + .always_on = 1, + .boot_on = 1, + }, +}; + +static struct regulator_init_data sw3b_init = { + .constraints = { + .name = "PFUZE100_SW3B", +#if PFUZE100_SW3_VOL6 + .min_uV = 800000, + .max_uV = 3950000, +#else + .min_uV = 400000, + .max_uV = 1975000, +#endif + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE, + .valid_modes_mask = 0, + .always_on = 1, + .boot_on = 1, + }, +}; + +static struct regulator_init_data sw4_init = { + .constraints = { + .name = "PFUZE100_SW4", +#if PFUZE100_SW4_VOL6 + .min_uV = 800000, + .max_uV = 3950000, +#else + .min_uV = 400000, + .max_uV = 1975000, +#endif + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE, + .valid_modes_mask = 0, + }, + .num_consumer_supplies = ARRAY_SIZE(sw4_consumers), + .consumer_supplies = sw4_consumers, +}; + +static struct regulator_init_data swbst_init = { + .constraints = { + .name = "PFUZE100_SWBST", + .min_uV = 5000000, + .max_uV = 5150000, + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE, + .valid_modes_mask = 0, + .always_on = 1, + .boot_on = 1, + }, + .num_consumer_supplies = ARRAY_SIZE(swbst_consumers), + .consumer_supplies = swbst_consumers, +}; + +static struct regulator_init_data vsnvs_init = { + .constraints = { + .name = "PFUZE100_VSNVS", + .min_uV = 1200000, + .max_uV = 3000000, + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE, + .valid_modes_mask = 0, + .always_on = 1, + .boot_on = 1, + }, +}; + +static struct regulator_init_data vrefddr_init = { + .constraints = { + .name = "PFUZE100_VREFDDR", + .always_on = 1, + .boot_on = 1, + }, +}; + +static struct regulator_init_data vgen1_init = { + .constraints = { + .name = "PFUZE100_VGEN1", +#ifdef PFUZE100_FIRST_VERSION + .min_uV = 1200000, + .max_uV = 1550000, +#else + .min_uV = 800000, + .max_uV = 1550000, +#endif + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE | + REGULATOR_CHANGE_STATUS, + .valid_modes_mask = 0, + .always_on = 1, + .boot_on = 1, + }, + .num_consumer_supplies = ARRAY_SIZE(vgen1_consumers), + .consumer_supplies = vgen1_consumers, +}; + +static struct regulator_init_data vgen2_init = { + .constraints = { + .name = "PFUZE100_VGEN2", +#ifdef PFUZE100_FIRST_VERSION + .min_uV = 1200000, + .max_uV = 1550000, +#else + .min_uV = 800000, + .max_uV = 1550000, +#endif + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE | + REGULATOR_CHANGE_STATUS, + .valid_modes_mask = 0, + }, + .num_consumer_supplies = ARRAY_SIZE(vgen2_consumers), + .consumer_supplies = vgen2_consumers, + +}; + +static struct regulator_init_data vgen3_init = { + .constraints = { + .name = "PFUZE100_VGEN3", + .min_uV = 1800000, + .max_uV = 3300000, + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE | + REGULATOR_CHANGE_STATUS, + .valid_modes_mask = 0, + .always_on = 0, + .boot_on = 0, + }, + .num_consumer_supplies = ARRAY_SIZE(vgen3_consumers), + .consumer_supplies = vgen3_consumers, +}; + +static struct regulator_init_data vgen4_init = { + .constraints = { + .name = "PFUZE100_VGEN4", + .min_uV = 1800000, + .max_uV = 3300000, + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE | + REGULATOR_CHANGE_STATUS, + .valid_modes_mask = 0, + .always_on = 1, + .boot_on = 1, + }, + .num_consumer_supplies = ARRAY_SIZE(vgen4_consumers), + .consumer_supplies = vgen4_consumers, +}; + +static struct regulator_init_data vgen5_init = { + .constraints = { + .name = "PFUZE100_VGEN5", + .min_uV = 1800000, + .max_uV = 3300000, + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE | + REGULATOR_CHANGE_STATUS, + .valid_modes_mask = 0, + }, + .num_consumer_supplies = ARRAY_SIZE(vgen5_consumers), + .consumer_supplies = vgen5_consumers, +}; + +static struct regulator_init_data vgen6_init = { + .constraints = { + .name = "PFUZE100_VGEN6", + .min_uV = 1800000, + .max_uV = 3300000, + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE | + REGULATOR_CHANGE_STATUS, + .valid_modes_mask = 0, + }, + .num_consumer_supplies = ARRAY_SIZE(vgen6_consumers), + .consumer_supplies = vgen6_consumers, +}; + +static int pfuze100_init(struct mc_pfuze *pfuze) +{ + int ret; + ret = pfuze_reg_rmw(pfuze, PFUZE100_SW1ASTANDBY, + PFUZE100_SW1ASTANDBY_STBY_M, + PFUZE100_SW1ASTANDBY_STBY_VAL); + if (ret) + goto err; + ret = pfuze_reg_rmw(pfuze, PFUZE100_SW1CSTANDBY, + PFUZE100_SW1CSTANDBY_STBY_M, + PFUZE100_SW1CSTANDBY_STBY_VAL); + if (ret) + goto err; + /*set SW1AB/SW1CDVSPEED as 25mV step each 4us,quick than 16us before.*/ + ret = pfuze_reg_rmw(pfuze, PFUZE100_SW1ACON, + PFUZE100_SW1ACON_SPEED_M, + PFUZE100_SW1ACON_SPEED_VAL); + if (ret) + goto err; + ret = pfuze_reg_rmw(pfuze, PFUZE100_SW1CCON, + PFUZE100_SW1CCON_SPEED_M, + PFUZE100_SW1CCON_SPEED_VAL); + if (ret) + goto err; + return 0; +err: + printk(KERN_ERR "pfuze100 init error!\n"); + return -1; +} + +static struct pfuze_regulator_init_data mx6q_sabreauto_pfuze100_regulators[] = { + {.id = PFUZE100_SW1A, .init_data = &sw1a_init}, + {.id = PFUZE100_SW1B, .init_data = &sw1b_init}, + {.id = PFUZE100_SW1C, .init_data = &sw1c_init}, + {.id = PFUZE100_SW2, .init_data = &sw2_init}, + {.id = PFUZE100_SW3A, .init_data = &sw3a_init}, + {.id = PFUZE100_SW3B, .init_data = &sw3b_init}, + {.id = PFUZE100_SW4, .init_data = &sw4_init}, + {.id = PFUZE100_SWBST, .init_data = &swbst_init}, + {.id = PFUZE100_VSNVS, .init_data = &vsnvs_init}, + {.id = PFUZE100_VREFDDR, .init_data = &vrefddr_init}, + {.id = PFUZE100_VGEN1, .init_data = &vgen1_init}, + {.id = PFUZE100_VGEN2, .init_data = &vgen2_init}, + {.id = PFUZE100_VGEN3, .init_data = &vgen3_init}, + {.id = PFUZE100_VGEN4, .init_data = &vgen4_init}, + {.id = PFUZE100_VGEN5, .init_data = &vgen5_init}, + {.id = PFUZE100_VGEN6, .init_data = &vgen6_init}, +}; + +static struct pfuze_platform_data pfuze100_plat = { + .flags = PFUZE_USE_REGULATOR, + .num_regulators = ARRAY_SIZE(mx6q_sabreauto_pfuze100_regulators), + .regulators = mx6q_sabreauto_pfuze100_regulators, + .pfuze_init = pfuze100_init, +}; + +static struct i2c_board_info __initdata pfuze100_i2c_device = { + I2C_BOARD_INFO(PFUZE100_I2C_DEVICE_NAME, PFUZE100_I2C_ADDR), + .platform_data = &pfuze100_plat, +}; + +int __init mx6sl_evk_init_pfuze100(u32 int_gpio) +{ + if (int_gpio) + pfuze100_i2c_device.irq = gpio_to_irq(int_gpio); /*update INT gpio */ + return i2c_register_board_info(0, &pfuze100_i2c_device, 1); +} diff --git a/arch/arm/mach-mx6/mx6sl_wfi.S b/arch/arm/mach-mx6/mx6sl_wfi.S new file mode 100644 index 000000000000..89fe4e292352 --- /dev/null +++ b/arch/arm/mach-mx6/mx6sl_wfi.S @@ -0,0 +1,412 @@ +/* + * Copyright (C) 2012 Freescale Semiconductor, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include <linux/linkage.h> +#include <mach/hardware.h> +#define IRAM_WAIT_SIZE (1 << 11) + + + .macro sl_ddr_io_save + + ldr r4, [r1, #0x30c] /* DRAM_DQM0 */ + ldr r5, [r1, #0x310] /* DRAM_DQM1 */ + ldr r6, [r1, #0x314] /* DRAM_DQM2 */ + ldr r7, [r1, #0x318] /* DRAM_DQM3 */ + stmfd r9!, {r4-r7} + + ldr r4, [r1, #0x344] /* DRAM_SDQS0 */ + ldr r5, [r1, #0x348] /* DRAM_SDQS1 */ + ldr r6, [r1, #0x34c] /* DRAM_SDQS2 */ + ldr r7, [r1, #0x350] /* DRAM_SDQS3 */ + stmfd r9!, {r4-r7} + + ldr r4, [r1, #0x5c4] /* GPR_B0DS */ + ldr r5, [r1, #0x5cc] /* GPR_B1DS */ + ldr r6, [r1, #0x5d4] /* GPR_B2DS */ + ldr r7, [r1, #0x5d8] /* GPR_B3DS */ + stmfd r9!, {r4-r7} + + ldr r4, [r1, #0x300] /* DRAM_CAS */ + ldr r5, [r1, #0x31c] /* DRAM_RAS */ + ldr r6, [r1, #0x338] /* DRAM_SDCLK_0 */ + ldr r7, [r1, #0x5ac] /* GPR_ADDS*/ + stmfd r9!, {r4-r7} + + ldr r4, [r1, #0x5b0] /* DDRMODE_CTL */ + ldr r5, [r1, #0x5c0] /* DDRMODE */ + ldr r6, [r1, #0x33c] /* DRAM_SODT0*/ + ldr r7, [r1, #0x340] /* DRAM_SODT1*/ + stmfd r9!, {r4-r7} + + ldr r4, [r1, #0x330] /* DRAM_SDCKE0 */ + ldr r5, [r1, #0x334] /* DRAM_SDCKE1 */ + ldr r6, [r1, #0x320] /* DRAM_RESET */ + ldr r7, [r1, #0x5c8] /* GPR_CTLDS */ + stmfd r9!, {r4-r7} + + .endm + + .macro sl_ddr_io_restore + + ldmea r9!, {r4-r7} + str r4, [r1, #0x30c] /* DRAM_DQM0 */ + str r5, [r1, #0x310] /* DRAM_DQM1 */ + str r6, [r1, #0x314] /* DRAM_DQM2 */ + str r7, [r1, #0x318] /* DRAM_DQM3 */ + + ldmea r9!, {r4-r7} + str r4, [r1, #0x344] /* DRAM_SDQS0 */ + str r5, [r1, #0x348] /* DRAM_SDQS1 */ + str r6, [r1, #0x34c] /* DRAM_SDQS2 */ + str r7, [r1, #0x350] /* DRAM_SDQS3 */ + + ldmea r9!, {r4-r7} + str r4, [r1, #0x5c4] /* GPR_B0DS */ + str r5, [r1, #0x5cc] /* GPR_B1DS */ + str r6, [r1, #0x5d4] /* GPR_B2DS */ + str r7, [r1, #0x5d8] /* GPR_B3DS */ + + ldmea r9!, {r4-r7} + str r4, [r1, #0x300] /* DRAM_CAS */ + str r5, [r1, #0x31c] /* DRAM_RAS */ + str r6, [r1, #0x338] /* DRAM_SDCLK_0 */ + str r7, [r1, #0x5ac] /* GPR_ADDS*/ + + ldmea r9!, {r4-r7} + str r4, [r1, #0x5b0] /* DDRMODE_CTL */ + str r5, [r1, #0x5c0] /* DDRMODE */ + str r6, [r1, #0x33c] /* DRAM_SODT0*/ + str r7, [r1, #0x340] /* DRAM_SODT1*/ + + ldmea r9!, {r4-r7} + str r4, [r1, #0x330] /* DRAM_SDCKE0 */ + str r5, [r1, #0x334] /* DRAM_SDCKE1 */ + str r6, [r1, #0x320] /* DRAM_RESET */ + str r7, [r1, #0x5c8] /* GPR_CTLDS */ + + .endm + + .macro sl_ddr_io_set_lpm + + mov r4, #0 + str r4, [r1, #0x30c] /* DRAM_DQM0 */ + str r4, [r1, #0x310] /* DRAM_DQM1 */ + str r4, [r1, #0x314] /* DRAM_DQM2 */ + str r4, [r1, #0x318] /* DRAM_DQM3 */ + + /* Make sure the Pull Ups are enabled. + * So only reduce the drive stength, but + * leave the pull-ups in the original state. + * This is required for LPDDR2. + */ + ldr r4, [r1, #0x344] + orr r4, r4, #0x3000 + str r4, [r1, #0x344] /* DRAM_SDQS0 */ + str r4, [r1, #0x348] /* DRAM_SDQS1 */ + str r4, [r1, #0x34c] /* DRAM_SDQS2 */ + str r4, [r1, #0x350] /* DRAM_SDQS3 */ + + str r4, [r1, #0x5c4] /* GPR_B0DS */ + str r4, [r1, #0x5cc] /* GPR_B1DS */ + str r4, [r1, #0x5d4] /* GPR_B2DS */ + str r4, [r1, #0x5d8] /* GPR_B3DS */ + + str r4, [r1, #0x300] /* DRAM_CAS */ + str r4, [r1, #0x31c] /* DRAM_RAS */ + str r4, [r1, #0x338] /* DRAM_SDCLK_0 */ + str r4, [r1, #0x5ac] /* GPR_ADDS*/ + + str r4, [r1, #0x5b0] /* DDRMODE_CTL */ + str r4, [r1, #0x5c0] /* DDRMODE */ + str r4, [r1, #0x33c] /* DRAM_SODT0*/ + str r4, [r1, #0x340] /* DRAM_SODT1*/ + + mov r4, #0x80000 + str r4, [r1, #0x320] /* DRAM_RESET */ + mov r4, #0x1000 + str r4, [r1, #0x330] /* DRAM_SDCKE0 */ + str r4, [r1, #0x334] /* DRAM_SDCKE1 */ + + .endm + +/* + * mx6sl_wait + * + * Idle the processor (eg, wait for interrupt). + * Make sure DDR is in self-refresh. + * IRQs are already disabled. + * r0 : arm_podf before WFI is entered + * r1: WFI IRAMcode base address. + */ +ENTRY(mx6sl_wait) + + push {r4, r5, r6, r7, r8, r9, r10} + +mx6sl_lpm_wfi: + /* Get the IRAM data storage address. */ + mov r10, r1 + mov r9, r1 /* get suspend_iram_base */ + add r9, r9, #IRAM_WAIT_SIZE /* 4K */ + + ldr r1, =MX6Q_IOMUXC_BASE_ADDR + add r1, r1, #PERIPBASE_VIRT + + /* Save the DDR IO state. */ + sl_ddr_io_save + + ldr r3, =ANATOP_BASE_ADDR + add r3, r3, #PERIPBASE_VIRT + + ldr r2, =CCM_BASE_ADDR + add r2, r2, #PERIPBASE_VIRT + + ldr r8, =MMDC_P0_BASE_ADDR + add r8, r8, #PERIPBASE_VIRT + + + /* Prime all TLB entries. */ + adr r7, mx6sl_lpm_wfi @Address in this function. + + ldr r6, [r7] + + ldr r6, [r8] + ldr r6, [r3] + ldr r6, [r2] + ldr r6, [r1] + + dsb + + /* Disable Automatic power savings. */ + ldr r6, [r8, #0x404] + orr r6, r6, #0x01 + str r6, [r8, #0x404] + + /* Make the DDR explicitly enter self-refresh. */ + ldr r6, [r8, #0x404] + orr r6, r6, #0x200000 + str r6, [r8, #0x404] + +poll_dvfs_set_1: + ldr r6, [r8, #0x404] + and r6, r6, #0x2000000 + cmp r6, #0x2000000 + bne poll_dvfs_set_1 + + /* set SBS step-by-step mode */ + ldr r6, [r8, #0x410] + orr r6, r6, #0x100 + str r6, [r8, #0x410] + + /* Now set DDR rate to 1MHz. */ + /* DDR is from bypassed PLL2 on periph2_clk2 path. + * Set the periph2_clk2_podf to divide by 8. + */ + ldr r6, [r2, #0x14] + orr r6, r6, #0x07 + str r6, [r2, #0x14] + + /* Now set MMDC PODF to divide by 3. */ + ldr r6, [r2, #0x14] + bic r6, r6, #0x38 + orr r6, r6, #0x10 + str r6, [r2, #0x14] + + /* Loop till podf is accepted. */ +mmdc_podf: + ldr r6, [r2, #0x48] + cmp r6, #0x0 + bne mmdc_podf + + /* Set the DDR IO in LPM state. */ + sl_ddr_io_set_lpm + + /* Set AHB to 8MHz., AXI to 3MHz */ + /* We want to ensure IPG_PERCLK to AHB + * clk ratio is 1:2.5 + */ + /* Store the AXI/AHB podfs. */ + ldr r9, [r2, #0x14] + mov r6, r9 + bic r6, r6, #0x1c00 + orr r6, r6, #0x800 + orr r6, r6, #0x70000 + str r6, [r2, #0x14] + + /* Loop till podf is accepted. */ +ahb_podf: + ldr r6, [r2, #0x48] + cmp r6, #0x0 + bne podf_loop + + /* Now set ARM to 24MHz. */ + /* Move ARM to be sourced from STEP_CLK + * after setting STEP_CLK to 24MHz. + */ + ldr r6, [r2, #0xc] + bic r6, r6, #0x100 + str r6, [r2, #0x0c] + /* Now PLL1_SW_CLK to step_clk. */ + ldr r6, [r2, #0x0c] + orr r6, r6, #0x4 + str r6, [r2, #0x0c] + + /* Bypass PLL1 and power it down. */ + ldr r6, =(1 << 16) + orr r6, r6, #0x1000 + str r6, [r3, #0x04] + + /* Set the ARM PODF to divide by 8. */ + /* IPG is at 4MHz here, we need ARM to + * run at the 12:5 ratio (WAIT mode issue). + */ + ldr r6, =0x7 + str r6, [r2, #0x10] + + /* Loop till podf is accepted. */ +podf_loop: + ldr r6, [r2, #0x48] + cmp r6, #0x0 + bne podf_loop + + /* Now do WFI. */ + dsb + + wfi + + /* Set original ARM PODF back. */ + str r0, [r2, #0x10] + + /* Loop till podf is accepted. */ +podf_loop1: + ldr r6, [r2, #0x48] + cmp r6, #0x0 + bne podf_loop1 + + /* Power up PLL1 and un-bypass it. */ + ldr r6, =(1 << 12) + str r6, [r3, #0x08] + + /* Wait for PLL1 to relock. */ +wait_for_pll_lock: + ldr r6, [r3, #0x0] + and r6, r6, #0x80000000 + cmp r6, #0x80000000 + bne wait_for_pll_lock + + ldr r6, =(1 << 16) + str r6, [r3, #0x08] + + /* Set PLL1_sw_clk back to PLL1. */ + ldr r6, [r2, #0x0c] + bic r6, r6, #0x4 + str r6, [r2, #0xc] + + /* Restore AHB/AXI back. */ + str r9, [r2, #0x14] + + /* Loop till podf is accepted. */ +ahb_podf1: + ldr r6, [r2, #0x48] + cmp r6, #0x0 + bne podf_loop1 + + 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 + + /* Set MMDC back to 24MHz. */ + /* Set periph2_clk2_podf to divide by 1. */ + /* Now set MMDC PODF to divide by 1. */ + ldr r6, [r2, #0x14] + bic r6, r6, #0x3f + str r6, [r2, #0x14] + +mmdc_podf1: + ldr r6, [r2, #0x48] + cmp r6, #0x0 + bne mmdc_podf1 + + /* clear DVFS - exit from self refresh mode */ + ldr r6, [r8, #0x404] + bic r6, r6, #0x200000 + str r6, [r8, #0x404] + +poll_dvfs_clear_1: + ldr r6, [r8, #0x404] + and r6, r6, #0x2000000 + cmp r6, #0x2000000 + beq poll_dvfs_clear_1 + + /* Add these nops so that the + * prefetcher will not try to get + * any instructions from DDR. + * The prefetch depth is about 23 + * on A9, so adding 25 nops. + */ + nop + nop + nop + nop + nop + + nop + nop + nop + nop + nop + + nop + nop + nop + nop + nop + + nop + nop + nop + nop + nop + + nop + nop + nop + nop + nop + + /* Enable Automatic power savings. */ + ldr r6, [r8, #0x404] + bic r6, r6, #0x01 + str r6, [r8, #0x404] + + /* clear SBS - unblock DDR accesses */ + ldr r6, [r8, #0x410] + bic r6, r6, #0x100 + str r6, [r8, #0x410] + + + pop {r4,r5, r6, r7, r8, r9, r10} + + /* Restore registers */ + mov pc, lr + + .type mx6sl_do_wait, #object +ENTRY(mx6sl_do_wait) + .word mx6sl_wait + .size mx6sl_wait, . - mx6sl_wait diff --git a/arch/arm/mach-mx6/pm.c b/arch/arm/mach-mx6/pm.c index b1d91e311b5e..c19d895139cf 100644 --- a/arch/arm/mach-mx6/pm.c +++ b/arch/arm/mach-mx6/pm.c @@ -38,6 +38,7 @@ #endif #include "crm_regs.h" #include "src-reg.h" +#include "regs-anadig.h" #define SCU_CTRL_OFFSET 0x00 #define GPC_IMR1_OFFSET 0x08 @@ -118,6 +119,11 @@ static void usb_power_down_handler(void) { u32 temp; bool usb_oh3_clk_already_on; + if ((__raw_readl(anatop_base + HW_ANADIG_ANA_MISC0) + & BM_ANADIG_ANA_MISC0_STOP_MODE_CONFIG) != 0) { + usb_vbus_wakeup_enabled = false; + return; + } /* enable usb oh3 clock if needed*/ temp = __raw_readl(MXC_CCM_CCGR6); usb_oh3_clk_already_on = \ diff --git a/arch/arm/mach-mx6/system.c b/arch/arm/mach-mx6/system.c index 57dee5f4c4c0..800c7cc4e8bd 100644 --- a/arch/arm/mach-mx6/system.c +++ b/arch/arm/mach-mx6/system.c @@ -52,14 +52,14 @@ extern unsigned int gpc_wake_irq[4]; static void __iomem *gpc_base = IO_ADDRESS(GPC_BASE_ADDR); -int wait_mode_arm_podf; volatile unsigned int num_cpu_idle; volatile unsigned int num_cpu_idle_lock = 0x0; int wait_mode_arm_podf; int cur_arm_podf; -bool arm_mem_clked_in_wait; void arch_idle_with_workaround(int cpu); +extern void *mx6sl_wfi_iram_base; +extern void (*mx6sl_wfi_iram)(int arm_podf, unsigned long wfi_iram_addr); 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; @@ -78,6 +78,7 @@ void gpc_set_wakeup(unsigned int irq[4]) return; } + /* set cpu low power mode before WFI instruction */ void mxc_cpu_lp_set(enum mxc_cpu_pwr_mode mode) { @@ -194,7 +195,7 @@ void mxc_cpu_lp_set(enum mxc_cpu_pwr_mode mode) __raw_writel(__raw_readl(MXC_CCM_CCR) & (~MXC_CCM_CCR_WB_COUNT_MASK) & (~MXC_CCM_CCR_REG_BYPASS_CNT_MASK), MXC_CCM_CCR); - udelay(60); + udelay(80); /* Reconfigurate WB and RBC counter */ __raw_writel(__raw_readl(MXC_CCM_CCR) | (0x1 << MXC_CCM_CCR_WB_COUNT_OFFSET) | @@ -251,25 +252,54 @@ void arch_idle_single_core(void) ca9_do_idle(); } else { - /* - * Implement the 12:5 ARM:IPG_CLK ratio - * workaround for the WAIT mode issue. - * We can directly use the divider to drop the ARM - * core freq in a single core environment. - * Set the ARM_PODF to get the max freq possible - * to avoid the WAIT mode issue when IPG is at 66MHz. - */ - if (cpu_is_mx6sl()) { - reg = __raw_readl(MXC_CCM_CGPR); - reg |= MXC_CCM_CGPR_MEM_IPG_STOP_MASK; - __raw_writel(reg, MXC_CCM_CGPR); - } - __raw_writel(wait_mode_arm_podf, MXC_CCM_CACRR); - while (__raw_readl(MXC_CCM_CDHIPR)) - ; - ca9_do_idle(); + if (low_bus_freq_mode || audio_bus_freq_mode) { + if (cpu_is_mx6sl() && low_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 + * at 24MHz. It will also set DDR to 1MHz to + * reduce power. + */ + u32 org_arm_podf = __raw_readl(MXC_CCM_CACRR); - __raw_writel(cur_arm_podf - 1, MXC_CCM_CACRR); + /* Need to run WFI code from IRAM so that + * we can lower DDR freq. + */ + mx6sl_wfi_iram(org_arm_podf, + (unsigned long)mx6sl_wfi_iram_base); + } else { + /* Need to set ARM to run at 24MHz since IPG + * is at 12MHz. This is valid for audio mode on + * MX6SL, and all low power modes on MX6DLS. + */ + /* PLL1_SW_CLK is sourced from PLL2_PFD2400MHz + * at this point. Move it to bypassed PLL1. + */ + reg = __raw_readl(MXC_CCM_CCSR); + reg &= ~MXC_CCM_CCSR_PLL1_SW_CLK_SEL; + __raw_writel(reg, MXC_CCM_CCSR); + + ca9_do_idle(); + + reg |= MXC_CCM_CCSR_PLL1_SW_CLK_SEL; + __raw_writel(reg, MXC_CCM_CCSR); + } + } else { + /* + * Implement the 12:5 ARM:IPG_CLK ratio + * workaround for the WAIT mode issue. + * We can directly use the divider to drop the ARM + * core freq in a single core environment. + * Set the ARM_PODF to get the max freq possible + * to avoid the WAIT mode issue when IPG is at 66MHz. + */ + __raw_writel(wait_mode_arm_podf, MXC_CCM_CACRR); + while (__raw_readl(MXC_CCM_CDHIPR)) + ; + ca9_do_idle(); + + __raw_writel(cur_arm_podf - 1, MXC_CCM_CACRR); + } } } @@ -331,7 +361,7 @@ void arch_idle(void) { if (enable_wait_mode) { mxc_cpu_lp_set(WAIT_UNCLOCKED_POWER_OFF); - if ((mem_clk_on_in_wait || arm_mem_clked_in_wait)) { + if (mem_clk_on_in_wait) { u32 reg; /* * MX6SL, MX6Q (TO1.2 or later) and diff --git a/arch/arm/mach-mx6/usb.h b/arch/arm/mach-mx6/usb.h index f796e7dad87c..6914246826f6 100644 --- a/arch/arm/mach-mx6/usb.h +++ b/arch/arm/mach-mx6/usb.h @@ -30,6 +30,9 @@ extern void gpio_usbotg_utmi_inactive(void); extern void __init mx6_usb_dr_init(void); extern bool usb_icbug_swfix_need(void); +extern int usb_stop_mode_refcount(bool enable); +extern void usb_stop_mode_lock(void); +extern void usb_stop_mode_unlock(void); extern void __init mx6_usb_h2_init(void); extern void __init mx6_usb_h3_init(void); diff --git a/arch/arm/mach-mx6/usb_dr.c b/arch/arm/mach-mx6/usb_dr.c index 1efac33aa7fc..8fe9700a658f 100644 --- a/arch/arm/mach-mx6/usb_dr.c +++ b/arch/arm/mach-mx6/usb_dr.c @@ -173,6 +173,9 @@ static int usb_phy_enable(struct fsl_usb2_platform_data *pdata) static int usbotg_init_ext(struct platform_device *pdev) { struct clk *usb_clk; +#ifdef CONFIG_USB_EHCI_ARC_OTG + void __iomem *anatop_base_addr = MX6_IO_ADDRESS(ANATOP_BASE_ADDR); +#endif u32 ret; /* at mx6q: this clock is AHB clock for usb core */ @@ -198,6 +201,12 @@ static int usbotg_init_ext(struct platform_device *pdev) mdelay(3); } otg_used++; +#ifdef CONFIG_USB_EHCI_ARC_OTG + usb_stop_mode_lock(); + if (usb_stop_mode_refcount(true) == 1) + __raw_writel(BM_ANADIG_ANA_MISC0_STOP_MODE_CONFIG, anatop_base_addr + HW_ANADIG_ANA_MISC0_SET); + usb_stop_mode_unlock(); +#endif return ret; } @@ -205,6 +214,9 @@ static int usbotg_init_ext(struct platform_device *pdev) static void usbotg_uninit_ext(struct platform_device *pdev) { struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data; +#ifdef CONFIG_USB_EHCI_ARC_OTG + void __iomem *anatop_base_addr = MX6_IO_ADDRESS(ANATOP_BASE_ADDR); +#endif clk_disable(usb_phy1_clk); clk_put(usb_phy1_clk); @@ -214,6 +226,12 @@ static void usbotg_uninit_ext(struct platform_device *pdev) usbotg_uninit(pdata); otg_used--; +#ifdef CONFIG_USB_EHCI_ARC_OTG + usb_stop_mode_lock(); + if (usb_stop_mode_refcount(false) == 0) + __raw_writel(BM_ANADIG_ANA_MISC0_STOP_MODE_CONFIG, anatop_base_addr + HW_ANADIG_ANA_MISC0_CLR); + usb_stop_mode_unlock(); +#endif } static void usbotg_clock_gate(bool on) @@ -424,18 +442,18 @@ static void _host_platform_rh_resume_swfix(struct fsl_usb2_platform_data *pdata) { u32 index = 0; - if ((UOG_PORTSC1 & (3 << 26)) != (2 << 26)) + if ((UOG_PORTSC1 & (PORTSC_PORT_SPEED_MASK)) != PORTSC_PORT_SPEED_HIGH) return ; - while ((UOG_PORTSC1 & PORTSC_PORT_FORCE_RESUME) && (index < 1000)) { udelay(500); index++; } - if (index >= 1000) - printk(KERN_INFO "%s big error\n", __func__); - + printk(KERN_ERR "failed to wait for the resume finished in %s() line:%d\n", + __func__, __LINE__); + /* We should add some delay to wait for the device switch to + * High-Speed 45ohm termination resistors mode. */ udelay(500); fsl_platform_otg_set_usb_phy_dis(pdata, 1); } @@ -451,9 +469,24 @@ static void _host_platform_rh_suspend(struct fsl_usb2_platform_data *pdata) static void _host_platform_rh_resume(struct fsl_usb2_platform_data *pdata) { + u32 index = 0; + /*for mx6sl ,we do not need any sw fix*/ if (cpu_is_mx6sl()) return ; + if ((UOG_PORTSC1 & (PORTSC_PORT_SPEED_MASK)) != PORTSC_PORT_SPEED_HIGH) + return ; + while ((UOG_PORTSC1 & PORTSC_PORT_FORCE_RESUME) + && (index < 1000)) { + udelay(500); + index++; + } + if (index >= 1000) + printk(KERN_ERR "failed to wait for the resume finished in %s() line:%d\n", + __func__, __LINE__); + /* We should add some delay to wait for the device switch to + * High-Speed 45ohm termination resistors mode. */ + udelay(500); __raw_writel(BM_USBPHY_CTRL_ENHOSTDISCONDETECT, MX6_IO_ADDRESS(pdata->phy_regs) + HW_USBPHY_CTRL_SET); diff --git a/arch/arm/mach-mx6/usb_h1.c b/arch/arm/mach-mx6/usb_h1.c index 92ef0ec3c3f5..bece29f7d44b 100644 --- a/arch/arm/mach-mx6/usb_h1.c +++ b/arch/arm/mach-mx6/usb_h1.c @@ -134,6 +134,7 @@ static int fsl_usb_host_init_ext(struct platform_device *pdev) { int ret; struct clk *usb_clk; + void __iomem *anatop_base_addr = MX6_IO_ADDRESS(ANATOP_BASE_ADDR); usb_clk = clk_get(NULL, "usboh3_clk"); clk_enable(usb_clk); usb_oh3_clk = usb_clk; @@ -145,19 +146,25 @@ static int fsl_usb_host_init_ext(struct platform_device *pdev) } usbh1_internal_phy_clock_gate(true); usb_phy_enable(pdev->dev.platform_data); - + usb_stop_mode_lock(); + if (usb_stop_mode_refcount(true) == 1) + __raw_writel(BM_ANADIG_ANA_MISC0_STOP_MODE_CONFIG, anatop_base_addr + HW_ANADIG_ANA_MISC0_SET); + usb_stop_mode_unlock(); return 0; } static void fsl_usb_host_uninit_ext(struct platform_device *pdev) { struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data; - + void __iomem *anatop_base_addr = MX6_IO_ADDRESS(ANATOP_BASE_ADDR); fsl_usb_host_uninit(pdata); clk_disable(usb_oh3_clk); clk_put(usb_oh3_clk); - + usb_stop_mode_lock(); + if (usb_stop_mode_refcount(false) == 0) + __raw_writel(BM_ANADIG_ANA_MISC0_STOP_MODE_CONFIG, anatop_base_addr + HW_ANADIG_ANA_MISC0_CLR); + usb_stop_mode_unlock(); } static void usbh1_clock_gate(bool on) @@ -237,18 +244,18 @@ static void usbh1_platform_rh_resume_swfix(struct fsl_usb2_platform_data *pdata) { u32 index = 0; - if ((UH1_PORTSC1 & (3 << 26)) != (2 << 26)) + if ((UOG_PORTSC1 & (PORTSC_PORT_SPEED_MASK)) != PORTSC_PORT_SPEED_HIGH) return ; - while ((UH1_PORTSC1 & PORTSC_PORT_FORCE_RESUME) && (index < 1000)) { udelay(500); index++; } - if (index >= 1000) - printk(KERN_INFO "%s big error\n", __func__); - + printk(KERN_ERR "failed to wait for the resume finished in %s() line:%d\n", + __func__, __LINE__); + /* We should add some delay to wait for the device switch to + * High-Speed 45ohm termination resistors mode. */ udelay(500); fsl_platform_h1_set_usb_phy_dis(pdata, 1); } @@ -265,9 +272,24 @@ static void usbh1_platform_rh_suspend(struct fsl_usb2_platform_data *pdata) static void usbh1_platform_rh_resume(struct fsl_usb2_platform_data *pdata) { + u32 index = 0; + /*for mx6sl ,we do not need any sw fix*/ if (cpu_is_mx6sl()) return ; + if ((UOG_PORTSC1 & (PORTSC_PORT_SPEED_MASK)) != PORTSC_PORT_SPEED_HIGH) + return ; + while ((UH1_PORTSC1 & PORTSC_PORT_FORCE_RESUME) + && (index < 1000)) { + udelay(500); + index++; + } + if (index >= 1000) + printk(KERN_ERR "failed to wait for the resume finished in %s() line:%d\n", + __func__, __LINE__); + /* We should add some delay to wait for the device switch to + * High-Speed 45ohm termination resistors mode. */ + udelay(500); __raw_writel(BM_USBPHY_CTRL_ENHOSTDISCONDETECT, MX6_IO_ADDRESS(pdata->phy_regs) + HW_USBPHY_CTRL_SET); diff --git a/arch/arm/mach-mx6/usb_h2.c b/arch/arm/mach-mx6/usb_h2.c index 24083fd52d72..37cad034d173 100644 --- a/arch/arm/mach-mx6/usb_h2.c +++ b/arch/arm/mach-mx6/usb_h2.c @@ -227,9 +227,16 @@ void __init mx6_usb_h2_init(void) struct platform_device *pdev, *pdev_wakeup; static void __iomem *anatop_base_addr = MX6_IO_ADDRESS(ANATOP_BASE_ADDR); usbh2_config.wakeup_pdata = &usbh2_wakeup_config; - pdev = imx6q_add_fsl_ehci_hs(2, &usbh2_config); + if (cpu_is_mx6sl()) + pdev = imx6sl_add_fsl_ehci_hs(2, &usbh2_config); + else + pdev = imx6q_add_fsl_ehci_hs(2, &usbh2_config); + usbh2_wakeup_config.usb_pdata[0] = pdev->dev.platform_data; - pdev_wakeup = imx6q_add_fsl_usb2_hs_wakeup(2, &usbh2_wakeup_config); + if (cpu_is_mx6sl()) + pdev_wakeup = imx6sl_add_fsl_usb2_hs_wakeup(2, &usbh2_wakeup_config); + else + pdev_wakeup = imx6q_add_fsl_usb2_hs_wakeup(2, &usbh2_wakeup_config); ((struct fsl_usb2_platform_data *)(pdev->dev.platform_data))->wakeup_pdata = pdev_wakeup->dev.platform_data; /* Some phy and power's special controls for host2 |