diff options
37 files changed, 600 insertions, 34 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 93d595a7477..4f8f3a4e4e0 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -365,6 +365,7 @@ config ARCH_MXC select GENERIC_CLOCKEVENTS select ARCH_REQUIRE_GPIOLIB select CLKDEV_LOOKUP + select HAVE_SCHED_CLOCK help Support for Freescale MXC/iMX-based family of processors diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig index 5eec099e0c7..56b930a1344 100644 --- a/arch/arm/mach-imx/Kconfig +++ b/arch/arm/mach-imx/Kconfig @@ -255,6 +255,7 @@ config MACH_IMX27_VISSTRIM_M10 bool "Vista Silicon i.MX27 Visstrim_m10" select SOC_IMX27 select IMX_HAVE_PLATFORM_IMX_I2C + select IMX_HAVE_PLATFORM_IMX_SSI select IMX_HAVE_PLATFORM_IMX_UART select IMX_HAVE_PLATFORM_MXC_MMC select IMX_HAVE_PLATFORM_MXC_EHCI diff --git a/arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c b/arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c index cb705c28de0..6269053505f 100644 --- a/arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c +++ b/arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c @@ -34,6 +34,7 @@ #include <mach/mx25.h> #include <mach/imx-uart.h> #include <mach/audmux.h> +#include <mach/esdhc.h> #include "devices-imx25.h" @@ -242,6 +243,11 @@ struct imx_ssi_platform_data eukrea_mbimxsd_ssi_pdata __initconst = { .flags = IMX_SSI_SYN | IMX_SSI_NET | IMX_SSI_USE_I2S_SLAVE, }; +static struct esdhc_platform_data sd1_pdata = { + .cd_gpio = GPIO_SD1CD, + .wp_gpio = -EINVAL, +}; + /* * system init for baseboard usage. Will be called by cpuimx25 init. * @@ -275,7 +281,7 @@ void __init eukrea_mbimxsd25_baseboard_init(void) imx25_add_imx_ssi(0, &eukrea_mbimxsd_ssi_pdata); imx25_add_flexcan1(NULL); - imx25_add_sdhci_esdhc_imx(0, NULL); + imx25_add_sdhci_esdhc_imx(0, &sd1_pdata); gpio_request(GPIO_LED1, "LED1"); gpio_direction_output(GPIO_LED1, 1); diff --git a/arch/arm/mach-mx3/eukrea_mbimxsd-baseboard.c b/arch/arm/mach-mx3/eukrea_mbimxsd-baseboard.c index 80761474c0f..2e288b38b4a 100644 --- a/arch/arm/mach-mx3/eukrea_mbimxsd-baseboard.c +++ b/arch/arm/mach-mx3/eukrea_mbimxsd-baseboard.c @@ -43,6 +43,7 @@ #include <mach/ipu.h> #include <mach/mx3fb.h> #include <mach/audmux.h> +#include <mach/esdhc.h> #include "devices-imx35.h" #include "devices.h" @@ -163,11 +164,14 @@ static iomux_v3_cfg_t eukrea_mbimxsd_pads[] = { MX35_PAD_SD1_DATA1__ESDHC1_DAT1, MX35_PAD_SD1_DATA2__ESDHC1_DAT2, MX35_PAD_SD1_DATA3__ESDHC1_DAT3, + /* SD1 CD */ + MX35_PAD_LD18__GPIO3_24, }; #define GPIO_LED1 IMX_GPIO_NR(3, 29) #define GPIO_SWITCH1 IMX_GPIO_NR(3, 25) -#define GPIO_LCDPWR (4) +#define GPIO_LCDPWR IMX_GPIO_NR(1, 4) +#define GPIO_SD1CD IMX_GPIO_NR(3, 24) static void eukrea_mbimxsd_lcd_power_set(struct plat_lcd_data *pd, unsigned int power) @@ -254,6 +258,11 @@ struct imx_ssi_platform_data eukrea_mbimxsd_ssi_pdata __initconst = { .flags = IMX_SSI_SYN | IMX_SSI_NET | IMX_SSI_USE_I2S_SLAVE, }; +static struct esdhc_platform_data sd1_pdata = { + .cd_gpio = GPIO_SD1CD, + .wp_gpio = -EINVAL, +}; + /* * system init for baseboard usage. Will be called by cpuimx35 init. * @@ -289,7 +298,7 @@ void __init eukrea_mbimxsd35_baseboard_init(void) imx35_add_imx_ssi(0, &eukrea_mbimxsd_ssi_pdata); imx35_add_flexcan1(NULL); - imx35_add_sdhci_esdhc_imx(0, NULL); + imx35_add_sdhci_esdhc_imx(0, &sd1_pdata); gpio_request(GPIO_LED1, "LED1"); gpio_direction_output(GPIO_LED1, 1); @@ -301,7 +310,6 @@ void __init eukrea_mbimxsd35_baseboard_init(void) gpio_request(GPIO_LCDPWR, "LCDPWR"); gpio_direction_output(GPIO_LCDPWR, 1); - gpio_free(GPIO_LCDPWR); i2c_register_board_info(0, eukrea_mbimxsd_i2c_devices, ARRAY_SIZE(eukrea_mbimxsd_i2c_devices)); diff --git a/arch/arm/mach-mx3/mach-pcm043.c b/arch/arm/mach-mx3/mach-pcm043.c index b3ecfb22d24..036ba1a4704 100644 --- a/arch/arm/mach-mx3/mach-pcm043.c +++ b/arch/arm/mach-mx3/mach-pcm043.c @@ -40,6 +40,7 @@ #include <mach/mx3fb.h> #include <mach/ulpi.h> #include <mach/audmux.h> +#include <mach/esdhc.h> #include "devices-imx35.h" #include "devices.h" @@ -217,11 +218,15 @@ static iomux_v3_cfg_t pcm043_pads[] = { MX35_PAD_SD1_DATA1__ESDHC1_DAT1, MX35_PAD_SD1_DATA2__ESDHC1_DAT2, MX35_PAD_SD1_DATA3__ESDHC1_DAT3, + MX35_PAD_ATA_DATA10__GPIO2_23, /* WriteProtect */ + MX35_PAD_ATA_DATA11__GPIO2_24, /* CardDetect */ }; #define AC97_GPIO_TXFS IMX_GPIO_NR(2, 31) #define AC97_GPIO_TXD IMX_GPIO_NR(2, 28) #define AC97_GPIO_RESET IMX_GPIO_NR(2, 0) +#define SD1_GPIO_WP IMX_GPIO_NR(2, 23) +#define SD1_GPIO_CD IMX_GPIO_NR(2, 24) static void pcm043_ac97_warm_reset(struct snd_ac97 *ac97) { @@ -346,6 +351,11 @@ static int __init pcm043_otg_mode(char *options) } __setup("otg_mode=", pcm043_otg_mode); +static struct esdhc_platform_data sd1_pdata = { + .wp_gpio = SD1_GPIO_WP, + .cd_gpio = SD1_GPIO_CD, +}; + /* * Board specific initialization. */ @@ -395,7 +405,7 @@ static void __init pcm043_init(void) imx35_add_fsl_usb2_udc(&otg_device_pdata); imx35_add_flexcan1(NULL); - imx35_add_sdhci_esdhc_imx(0, NULL); + imx35_add_sdhci_esdhc_imx(0, &sd1_pdata); } static void __init pcm043_timer_init(void) diff --git a/arch/arm/mach-mx5/Kconfig b/arch/arm/mach-mx5/Kconfig index 83ee08847d4..159340da919 100644 --- a/arch/arm/mach-mx5/Kconfig +++ b/arch/arm/mach-mx5/Kconfig @@ -165,6 +165,7 @@ config MACH_MX53_LOCO select IMX_HAVE_PLATFORM_IMX_I2C select IMX_HAVE_PLATFORM_IMX_UART select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX + select IMX_HAVE_PLATFORM_GPIO_KEYS help Include support for MX53 LOCO platform. This includes specific configurations for the board and its peripherals. diff --git a/arch/arm/mach-mx5/Makefile b/arch/arm/mach-mx5/Makefile index 4f63048be3c..0b9338cec51 100644 --- a/arch/arm/mach-mx5/Makefile +++ b/arch/arm/mach-mx5/Makefile @@ -3,7 +3,7 @@ # # Object file lists. -obj-y := cpu.o mm.o clock-mx51-mx53.o devices.o ehci.o +obj-y := cpu.o mm.o clock-mx51-mx53.o devices.o ehci.o system.o obj-$(CONFIG_SOC_IMX50) += mm-mx50.o obj-$(CONFIG_CPU_FREQ_IMX) += cpu_op-mx51.o diff --git a/arch/arm/mach-mx5/board-mx51_babbage.c b/arch/arm/mach-mx5/board-mx51_babbage.c index b2ecd194e76..bea4e4135f9 100644 --- a/arch/arm/mach-mx5/board-mx51_babbage.c +++ b/arch/arm/mach-mx5/board-mx51_babbage.c @@ -228,13 +228,12 @@ static inline void babbage_fec_reset(void) int ret; /* reset FEC PHY */ - ret = gpio_request(BABBAGE_FEC_PHY_RESET, "fec-phy-reset"); + ret = gpio_request_one(BABBAGE_FEC_PHY_RESET, + GPIOF_OUT_INIT_LOW, "fec-phy-reset"); if (ret) { printk(KERN_ERR"failed to get GPIO_FEC_PHY_RESET: %d\n", ret); return; } - gpio_direction_output(BABBAGE_FEC_PHY_RESET, 0); - gpio_set_value(BABBAGE_FEC_PHY_RESET, 0); msleep(1); gpio_set_value(BABBAGE_FEC_PHY_RESET, 1); } diff --git a/arch/arm/mach-mx5/board-mx53_evk.c b/arch/arm/mach-mx5/board-mx53_evk.c index 7b5735c5ea5..2af3f43f74d 100644 --- a/arch/arm/mach-mx5/board-mx53_evk.c +++ b/arch/arm/mach-mx5/board-mx53_evk.c @@ -34,7 +34,7 @@ #include <mach/imx-uart.h> #include <mach/iomux-mx53.h> -#define SMD_FEC_PHY_RST IMX_GPIO_NR(7, 6) +#define MX53_EVK_FEC_PHY_RST IMX_GPIO_NR(7, 6) #define EVK_ECSPI1_CS0 IMX_GPIO_NR(2, 30) #define EVK_ECSPI1_CS1 IMX_GPIO_NR(3, 19) @@ -82,15 +82,14 @@ static inline void mx53_evk_fec_reset(void) int ret; /* reset FEC PHY */ - ret = gpio_request(SMD_FEC_PHY_RST, "fec-phy-reset"); + ret = gpio_request_one(MX53_EVK_FEC_PHY_RST, GPIOF_OUT_INIT_LOW, + "fec-phy-reset"); if (ret) { printk(KERN_ERR"failed to get GPIO_FEC_PHY_RESET: %d\n", ret); return; } - gpio_direction_output(SMD_FEC_PHY_RST, 0); - gpio_set_value(SMD_FEC_PHY_RST, 0); msleep(1); - gpio_set_value(SMD_FEC_PHY_RST, 1); + gpio_set_value(MX53_EVK_FEC_PHY_RST, 1); } static struct fec_platform_data mx53_evk_fec_pdata = { diff --git a/arch/arm/mach-mx5/board-mx53_loco.c b/arch/arm/mach-mx5/board-mx53_loco.c index 0a18f8d23eb..10a1bea1054 100644 --- a/arch/arm/mach-mx5/board-mx53_loco.c +++ b/arch/arm/mach-mx5/board-mx53_loco.c @@ -36,6 +36,9 @@ #include "crm_regs.h" #include "devices-imx53.h" +#define MX53_LOCO_POWER IMX_GPIO_NR(1, 8) +#define MX53_LOCO_UI1 IMX_GPIO_NR(2, 14) +#define MX53_LOCO_UI2 IMX_GPIO_NR(2, 15) #define LOCO_FEC_PHY_RST IMX_GPIO_NR(7, 6) static iomux_v3_cfg_t mx53_loco_pads[] = { @@ -180,6 +183,27 @@ static iomux_v3_cfg_t mx53_loco_pads[] = { MX53_PAD_GPIO_8__GPIO1_8, }; +#define GPIO_BUTTON(gpio_num, ev_code, act_low, descr, wake) \ +{ \ + .gpio = gpio_num, \ + .type = EV_KEY, \ + .code = ev_code, \ + .active_low = act_low, \ + .desc = "btn " descr, \ + .wakeup = wake, \ +} + +static const struct gpio_keys_button loco_buttons[] __initconst = { + GPIO_BUTTON(MX53_LOCO_POWER, KEY_POWER, 1, "power", 0), + GPIO_BUTTON(MX53_LOCO_UI1, KEY_VOLUMEUP, 1, "volume-up", 0), + GPIO_BUTTON(MX53_LOCO_UI2, KEY_VOLUMEDOWN, 1, "volume-down", 0), +}; + +static const struct gpio_keys_platform_data loco_button_data __initconst = { + .buttons = loco_buttons, + .nbuttons = ARRAY_SIZE(loco_buttons), +}; + static inline void mx53_loco_fec_reset(void) { int ret; @@ -215,6 +239,7 @@ static void __init mx53_loco_board_init(void) imx53_add_imx_i2c(1, &mx53_loco_i2c_data); imx53_add_sdhci_esdhc_imx(0, NULL); imx53_add_sdhci_esdhc_imx(2, NULL); + imx_add_gpio_keys(&loco_button_data); } static void __init mx53_loco_timer_init(void) diff --git a/arch/arm/mach-mx5/clock-mx51-mx53.c b/arch/arm/mach-mx5/clock-mx51-mx53.c index 652ace41382..fdbc05ed551 100644 --- a/arch/arm/mach-mx5/clock-mx51-mx53.c +++ b/arch/arm/mach-mx5/clock-mx51-mx53.c @@ -865,6 +865,13 @@ static struct clk aips_tz2_clk = { .disable = _clk_ccgr_disable_inwait, }; +static struct clk gpc_dvfs_clk = { + .enable_reg = MXC_CCM_CCGR5, + .enable_shift = MXC_CCM_CCGRx_CG12_OFFSET, + .enable = _clk_ccgr_enable, + .disable = _clk_ccgr_disable, +}; + static struct clk gpt_32k_clk = { .id = 0, .parent = &ckil_clk, @@ -1448,6 +1455,7 @@ static struct clk_lookup mx51_lookups[] = { _REGISTER_CLOCK("imx-ipuv3", NULL, ipu_clk) _REGISTER_CLOCK("imx-ipuv3", "di0", ipu_di0_clk) _REGISTER_CLOCK("imx-ipuv3", "di1", ipu_di1_clk) + _REGISTER_CLOCK(NULL, "gpc_dvfs", gpc_dvfs_clk) }; static struct clk_lookup mx53_lookups[] = { @@ -1511,6 +1519,7 @@ int __init mx51_clocks_init(unsigned long ckil, unsigned long osc, clk_enable(&iim_clk); mx51_revision(); clk_disable(&iim_clk); + mx51_display_revision(); /* move usb_phy_clk to 24MHz */ clk_set_parent(&usb_phy1_clk, &osc_clk); diff --git a/arch/arm/mach-mx5/cpu.c b/arch/arm/mach-mx5/cpu.c index df46b5e6085..472bdfab2e5 100644 --- a/arch/arm/mach-mx5/cpu.c +++ b/arch/arm/mach-mx5/cpu.c @@ -21,6 +21,7 @@ static int cpu_silicon_rev = -1; #define IIM_SREV 0x24 +#define MX50_HW_ADADIG_DIGPROG 0xB0 static int get_mx51_srev(void) { @@ -51,6 +52,26 @@ int mx51_revision(void) } EXPORT_SYMBOL(mx51_revision); +void mx51_display_revision(void) +{ + int rev; + char *srev; + rev = mx51_revision(); + + switch (rev) { + case IMX_CHIP_REVISION_2_0: + srev = IMX_CHIP_REVISION_2_0_STRING; + break; + case IMX_CHIP_REVISION_3_0: + srev = IMX_CHIP_REVISION_3_0_STRING; + break; + default: + srev = IMX_CHIP_REVISION_UNKNOWN_STRING; + } + printk(KERN_INFO "CPU identified as i.MX51, silicon rev %s\n", srev); +} +EXPORT_SYMBOL(mx51_display_revision); + #ifdef CONFIG_NEON /* @@ -107,6 +128,44 @@ int mx53_revision(void) } EXPORT_SYMBOL(mx53_revision); +static int get_mx50_srev(void) +{ + void __iomem *anatop = ioremap(MX50_ANATOP_BASE_ADDR, SZ_8K); + u32 rev; + + if (!anatop) { + cpu_silicon_rev = -EINVAL; + return 0; + } + + rev = readl(anatop + MX50_HW_ADADIG_DIGPROG); + rev &= 0xff; + + iounmap(anatop); + if (rev == 0x0) + return IMX_CHIP_REVISION_1_0; + else if (rev == 0x1) + return IMX_CHIP_REVISION_1_1; + return 0; +} + +/* + * Returns: + * the silicon revision of the cpu + * -EINVAL - not a mx50 + */ +int mx50_revision(void) +{ + if (!cpu_is_mx50()) + return -EINVAL; + + if (cpu_silicon_rev == -1) + cpu_silicon_rev = get_mx50_srev(); + + return cpu_silicon_rev; +} +EXPORT_SYMBOL(mx50_revision); + static int __init post_cpu_init(void) { unsigned int reg; diff --git a/arch/arm/mach-mx5/eukrea_mbimxsd-baseboard.c b/arch/arm/mach-mx5/eukrea_mbimxsd-baseboard.c index c372a437369..e6c1119c20a 100644 --- a/arch/arm/mach-mx5/eukrea_mbimxsd-baseboard.c +++ b/arch/arm/mach-mx5/eukrea_mbimxsd-baseboard.c @@ -67,6 +67,10 @@ static iomux_v3_cfg_t eukrea_mbimxsd_pads[] = { MX51_PAD_SD1_DATA1__SD1_DATA1, MX51_PAD_SD1_DATA2__SD1_DATA2, MX51_PAD_SD1_DATA3__SD1_DATA3, + /* SD1 CD */ + _MX51_PAD_GPIO1_0__SD1_CD | MUX_PAD_CTRL(PAD_CTL_PUS_22K_UP | + PAD_CTL_PKE | PAD_CTL_SRE_FAST | + PAD_CTL_DSE_HIGH | PAD_CTL_PUE | PAD_CTL_HYS), }; #define GPIO_LED1 IMX_GPIO_NR(3, 30) diff --git a/arch/arm/mach-mx5/mx51_efika.c b/arch/arm/mach-mx5/mx51_efika.c index 51a67fc7f0e..d0c7075937c 100644 --- a/arch/arm/mach-mx5/mx51_efika.c +++ b/arch/arm/mach-mx5/mx51_efika.c @@ -42,7 +42,6 @@ #include <asm/mach-types.h> #include <asm/mach/arch.h> #include <asm/mach/time.h> -#include <asm/mach-types.h> #include "devices-imx51.h" #include "devices.h" @@ -572,8 +571,10 @@ static struct mc13xxx_regulator_init_data mx51_efika_regulators[] = { static struct mc13xxx_platform_data mx51_efika_mc13892_data = { .flags = MC13XXX_USE_RTC | MC13XXX_USE_REGULATOR, - .num_regulators = ARRAY_SIZE(mx51_efika_regulators), - .regulators = mx51_efika_regulators, + .regulators = { + .num_regulators = ARRAY_SIZE(mx51_efika_regulators), + .regulators = mx51_efika_regulators, + }, }; static struct spi_board_info mx51_efika_spi_board_info[] __initdata = { diff --git a/arch/arm/mach-mx5/system.c b/arch/arm/mach-mx5/system.c new file mode 100644 index 00000000000..76ae8dc33e0 --- /dev/null +++ b/arch/arm/mach-mx5/system.c @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved. + */ + +/* + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ +#include <linux/platform_device.h> +#include <linux/io.h> +#include <mach/hardware.h> +#include "crm_regs.h" + +/* set cpu low power mode before WFI instruction. This function is called + * mx5 because it can be used for mx50, mx51, and mx53.*/ +void mx5_cpu_lp_set(enum mxc_cpu_pwr_mode mode) +{ + u32 plat_lpc, arm_srpgcr, ccm_clpcr; + u32 empgc0, empgc1; + int stop_mode = 0; + + /* always allow platform to issue a deep sleep mode request */ + plat_lpc = __raw_readl(MXC_CORTEXA8_PLAT_LPC) & + ~(MXC_CORTEXA8_PLAT_LPC_DSM); + ccm_clpcr = __raw_readl(MXC_CCM_CLPCR) & ~(MXC_CCM_CLPCR_LPM_MASK); + arm_srpgcr = __raw_readl(MXC_SRPG_ARM_SRPGCR) & ~(MXC_SRPGCR_PCR); + empgc0 = __raw_readl(MXC_SRPG_EMPGC0_SRPGCR) & ~(MXC_SRPGCR_PCR); + empgc1 = __raw_readl(MXC_SRPG_EMPGC1_SRPGCR) & ~(MXC_SRPGCR_PCR); + + switch (mode) { + case WAIT_CLOCKED: + break; + case WAIT_UNCLOCKED: + ccm_clpcr |= 0x1 << MXC_CCM_CLPCR_LPM_OFFSET; + break; + case WAIT_UNCLOCKED_POWER_OFF: + case STOP_POWER_OFF: + plat_lpc |= MXC_CORTEXA8_PLAT_LPC_DSM + | MXC_CORTEXA8_PLAT_LPC_DBG_DSM; + if (mode == WAIT_UNCLOCKED_POWER_OFF) { + ccm_clpcr |= 0x1 << MXC_CCM_CLPCR_LPM_OFFSET; + ccm_clpcr &= ~MXC_CCM_CLPCR_VSTBY; + ccm_clpcr &= ~MXC_CCM_CLPCR_SBYOS; + stop_mode = 0; + } else { + ccm_clpcr |= 0x2 << MXC_CCM_CLPCR_LPM_OFFSET; + ccm_clpcr |= 0x3 << MXC_CCM_CLPCR_STBY_COUNT_OFFSET; + ccm_clpcr |= MXC_CCM_CLPCR_VSTBY; + ccm_clpcr |= MXC_CCM_CLPCR_SBYOS; + stop_mode = 1; + } + arm_srpgcr |= MXC_SRPGCR_PCR; + + if (tzic_enable_wake(1) != 0) + return; + break; + case STOP_POWER_ON: + ccm_clpcr |= 0x2 << MXC_CCM_CLPCR_LPM_OFFSET; + break; + default: + printk(KERN_WARNING "UNKNOWN cpu power mode: %d\n", mode); + return; + } + + __raw_writel(plat_lpc, MXC_CORTEXA8_PLAT_LPC); + __raw_writel(ccm_clpcr, MXC_CCM_CLPCR); + __raw_writel(arm_srpgcr, MXC_SRPG_ARM_SRPGCR); + + /* Enable NEON SRPG for all but MX50TO1.0. */ + if (mx50_revision() != IMX_CHIP_REVISION_1_0) + __raw_writel(arm_srpgcr, MXC_SRPG_NEON_SRPGCR); + + if (stop_mode) { + empgc0 |= MXC_SRPGCR_PCR; + empgc1 |= MXC_SRPGCR_PCR; + + __raw_writel(empgc0, MXC_SRPG_EMPGC0_SRPGCR); + __raw_writel(empgc1, MXC_SRPG_EMPGC1_SRPGCR); + } +} diff --git a/arch/arm/mach-mxs/Kconfig b/arch/arm/mach-mxs/Kconfig index 4f6f174af6c..4522fbb235d 100644 --- a/arch/arm/mach-mxs/Kconfig +++ b/arch/arm/mach-mxs/Kconfig @@ -22,6 +22,7 @@ config MACH_MX23EVK select SOC_IMX23 select MXS_HAVE_AMBA_DUART select MXS_HAVE_PLATFORM_AUART + select MXS_HAVE_PLATFORM_MXS_MMC select MXS_HAVE_PLATFORM_MXSFB default y help @@ -35,6 +36,7 @@ config MACH_MX28EVK select MXS_HAVE_PLATFORM_AUART select MXS_HAVE_PLATFORM_FEC select MXS_HAVE_PLATFORM_FLEXCAN + select MXS_HAVE_PLATFORM_MXS_MMC select MXS_HAVE_PLATFORM_MXSFB select MXS_OCOTP default y diff --git a/arch/arm/mach-mxs/clock-mx23.c b/arch/arm/mach-mxs/clock-mx23.c index d133c7f3094..c3577ea789a 100644 --- a/arch/arm/mach-mxs/clock-mx23.c +++ b/arch/arm/mach-mxs/clock-mx23.c @@ -521,6 +521,15 @@ static int clk_misc_init(void) __raw_writel(BM_CLKCTRL_CPU_INTERRUPT_WAIT, CLKCTRL_BASE_ADDR + HW_CLKCTRL_CPU_SET); + /* + * 480 MHz seems too high to be ssp clock source directly, + * so set frac to get a 288 MHz ref_io. + */ + reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_FRAC); + reg &= ~BM_CLKCTRL_FRAC_IOFRAC; + reg |= 30 << BP_CLKCTRL_FRAC_IOFRAC; + __raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_FRAC); + return 0; } @@ -528,6 +537,12 @@ int __init mx23_clocks_init(void) { clk_misc_init(); + /* + * source ssp clock from ref_io than ref_xtal, + * as ref_xtal only provides 24 MHz as maximum. + */ + clk_set_parent(&ssp_clk, &ref_io_clk); + clk_enable(&cpu_clk); clk_enable(&hbus_clk); clk_enable(&xbus_clk); diff --git a/arch/arm/mach-mxs/clock-mx28.c b/arch/arm/mach-mxs/clock-mx28.c index 5e489a2b202..1ad97fed1e9 100644 --- a/arch/arm/mach-mxs/clock-mx28.c +++ b/arch/arm/mach-mxs/clock-mx28.c @@ -618,6 +618,8 @@ static struct clk_lookup lookups[] = { _REGISTER_CLOCK("pll2", NULL, pll2_clk) _REGISTER_CLOCK("mxs-dma-apbh", NULL, hbus_clk) _REGISTER_CLOCK("mxs-dma-apbx", NULL, xbus_clk) + _REGISTER_CLOCK("mxs-mmc.0", NULL, ssp0_clk) + _REGISTER_CLOCK("mxs-mmc.1", NULL, ssp1_clk) _REGISTER_CLOCK("flexcan.0", NULL, can0_clk) _REGISTER_CLOCK("flexcan.1", NULL, can1_clk) _REGISTER_CLOCK(NULL, "usb0", usb0_clk) @@ -737,6 +739,15 @@ static int clk_misc_init(void) reg |= BM_CLKCTRL_ENET_CLK_OUT_EN; __raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_ENET); + /* + * 480 MHz seems too high to be ssp clock source directly, + * so set frac0 to get a 288 MHz ref_io0. + */ + reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_FRAC0); + reg &= ~BM_CLKCTRL_FRAC0_IO0FRAC; + reg |= 30 << BP_CLKCTRL_FRAC0_IO0FRAC; + __raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_FRAC0); + return 0; } @@ -744,6 +755,13 @@ int __init mx28_clocks_init(void) { clk_misc_init(); + /* + * source ssp clock from ref_io0 than ref_xtal, + * as ref_xtal only provides 24 MHz as maximum. + */ + clk_set_parent(&ssp0_clk, &ref_io0_clk); + clk_set_parent(&ssp1_clk, &ref_io0_clk); + clk_enable(&cpu_clk); clk_enable(&hbus_clk); clk_enable(&xbus_clk); diff --git a/arch/arm/mach-mxs/devices-mx23.h b/arch/arm/mach-mxs/devices-mx23.h index c7e14f4e366..c6f345febd3 100644 --- a/arch/arm/mach-mxs/devices-mx23.h +++ b/arch/arm/mach-mxs/devices-mx23.h @@ -21,6 +21,10 @@ extern const struct mxs_auart_data mx23_auart_data[] __initconst; #define mx23_add_auart0() mx23_add_auart(0) #define mx23_add_auart1() mx23_add_auart(1) +extern const struct mxs_mxs_mmc_data mx23_mxs_mmc_data[] __initconst; +#define mx23_add_mxs_mmc(id, pdata) \ + mxs_add_mxs_mmc(&mx23_mxs_mmc_data[id], pdata) + #define mx23_add_mxs_pwm(id) mxs_add_mxs_pwm(MX23_PWM_BASE_ADDR, id) struct platform_device *__init mx23_add_mxsfb( diff --git a/arch/arm/mach-mxs/devices-mx28.h b/arch/arm/mach-mxs/devices-mx28.h index 9d08555c4cf..c473eddce8c 100644 --- a/arch/arm/mach-mxs/devices-mx28.h +++ b/arch/arm/mach-mxs/devices-mx28.h @@ -37,6 +37,10 @@ extern const struct mxs_flexcan_data mx28_flexcan_data[] __initconst; extern const struct mxs_i2c_data mx28_mxs_i2c_data[] __initconst; #define mx28_add_mxs_i2c(id) mxs_add_mxs_i2c(&mx28_mxs_i2c_data[id]) +extern const struct mxs_mxs_mmc_data mx28_mxs_mmc_data[] __initconst; +#define mx28_add_mxs_mmc(id, pdata) \ + mxs_add_mxs_mmc(&mx28_mxs_mmc_data[id], pdata) + #define mx28_add_mxs_pwm(id) mxs_add_mxs_pwm(MX28_PWM_BASE_ADDR, id) struct platform_device *__init mx28_add_mxsfb( diff --git a/arch/arm/mach-mxs/devices/Kconfig b/arch/arm/mach-mxs/devices/Kconfig index 1451ad060d8..acf9eea124c 100644 --- a/arch/arm/mach-mxs/devices/Kconfig +++ b/arch/arm/mach-mxs/devices/Kconfig @@ -15,6 +15,9 @@ config MXS_HAVE_PLATFORM_FLEXCAN config MXS_HAVE_PLATFORM_MXS_I2C bool +config MXS_HAVE_PLATFORM_MXS_MMC + bool + config MXS_HAVE_PLATFORM_MXS_PWM bool diff --git a/arch/arm/mach-mxs/devices/Makefile b/arch/arm/mach-mxs/devices/Makefile index 0d9bea30b0a..324f2824d38 100644 --- a/arch/arm/mach-mxs/devices/Makefile +++ b/arch/arm/mach-mxs/devices/Makefile @@ -4,5 +4,6 @@ obj-y += platform-dma.o obj-$(CONFIG_MXS_HAVE_PLATFORM_FEC) += platform-fec.o obj-$(CONFIG_MXS_HAVE_PLATFORM_FLEXCAN) += platform-flexcan.o obj-$(CONFIG_MXS_HAVE_PLATFORM_MXS_I2C) += platform-mxs-i2c.o +obj-$(CONFIG_MXS_HAVE_PLATFORM_MXS_MMC) += platform-mxs-mmc.o obj-$(CONFIG_MXS_HAVE_PLATFORM_MXS_PWM) += platform-mxs-pwm.o obj-$(CONFIG_MXS_HAVE_PLATFORM_MXSFB) += platform-mxsfb.o diff --git a/arch/arm/mach-mxs/devices/platform-mxs-mmc.c b/arch/arm/mach-mxs/devices/platform-mxs-mmc.c new file mode 100644 index 00000000000..382dacbeca2 --- /dev/null +++ b/arch/arm/mach-mxs/devices/platform-mxs-mmc.c @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2010 Pengutronix + * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de> + * + * Copyright 2011 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 version 2 as published by the + * Free Software Foundation. + */ + +#include <linux/compiler.h> +#include <linux/err.h> +#include <linux/init.h> + +#include <mach/mx23.h> +#include <mach/mx28.h> +#include <mach/devices-common.h> + +#define mxs_mxs_mmc_data_entry_single(soc, _id, hwid) \ + { \ + .id = _id, \ + .iobase = soc ## _SSP ## hwid ## _BASE_ADDR, \ + .dma = soc ## _DMA_SSP ## hwid, \ + .irq_err = soc ## _INT_SSP ## hwid ## _ERROR, \ + .irq_dma = soc ## _INT_SSP ## hwid ## _DMA, \ + } + +#define mxs_mxs_mmc_data_entry(soc, _id, hwid) \ + [_id] = mxs_mxs_mmc_data_entry_single(soc, _id, hwid) + + +#ifdef CONFIG_SOC_IMX23 +const struct mxs_mxs_mmc_data mx23_mxs_mmc_data[] __initconst = { + mxs_mxs_mmc_data_entry(MX23, 0, 1), + mxs_mxs_mmc_data_entry(MX23, 1, 2), +}; +#endif + +#ifdef CONFIG_SOC_IMX28 +const struct mxs_mxs_mmc_data mx28_mxs_mmc_data[] __initconst = { + mxs_mxs_mmc_data_entry(MX28, 0, 0), + mxs_mxs_mmc_data_entry(MX28, 1, 1), +}; +#endif + +struct platform_device *__init mxs_add_mxs_mmc( + const struct mxs_mxs_mmc_data *data, + const struct mxs_mmc_platform_data *pdata) +{ + struct resource res[] = { + { + .start = data->iobase, + .end = data->iobase + SZ_8K - 1, + .flags = IORESOURCE_MEM, + }, { + .start = data->dma, + .end = data->dma, + .flags = IORESOURCE_DMA, + }, { + .start = data->irq_err, + .end = data->irq_err, + .flags = IORESOURCE_IRQ, + }, { + .start = data->irq_dma, + .end = data->irq_dma, + .flag |