From: Uwe Kleine-König Date: Wed, 30 Jun 2010 10:16:24 +0000 (+0200) Subject: Merge branch 'imx/for-2.6.36' of git://git.pengutronix.de/git/ukl/linux-2.6 into... X-Git-Tag: MMI-PSA29.97-13-9~23112^2^2~1^2~26 X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=2dcf78c0eeae3bd07082821557014f25f02ca2e9;p=GitHub%2FMotorolaMobilityLLC%2Fkernel-slsi.git Merge branch 'imx/for-2.6.36' of git://git.pengutronix.de/git/ukl/linux-2.6 into HEAD There are some more conflicts than detected by git, namely support for the newly added cpuimx machines needed to be converted to dynamic device registration. Signed-off-by: Uwe Kleine-König Conflicts: arch/arm/mach-imx/Makefile arch/arm/mach-imx/devices.c arch/arm/mach-imx/devices.h arch/arm/mach-imx/eukrea_mbimx27-baseboard.c arch/arm/mach-mx2/Kconfig arch/arm/mach-mx25/Makefile arch/arm/mach-mx25/devices.c arch/arm/plat-mxc/include/mach/mx25.h arch/arm/plat-mxc/include/mach/mxc_nand.h --- 2dcf78c0eeae3bd07082821557014f25f02ca2e9 diff --cc arch/arm/mach-imx/Kconfig index 000000000000,3da53557c665..c5c0369bb481 mode 000000,100644..100644 --- a/arch/arm/mach-imx/Kconfig +++ b/arch/arm/mach-imx/Kconfig @@@ -1,0 -1,186 +1,193 @@@ + config IMX_HAVE_DMA_V1 + bool + + if ARCH_MX1 + + config SOC_IMX1 + select CPU_ARM920T + select IMX_HAVE_DMA_V1 + select IMX_HAVE_IOMUX_V1 + bool + + comment "MX1 platforms:" + config MACH_MXLADS + bool + + config ARCH_MX1ADS + bool "MX1ADS platform" + select MACH_MXLADS + select IMX_HAVE_PLATFORM_IMX_I2C + select IMX_HAVE_PLATFORM_IMX_UART + help + Say Y here if you are using Motorola MX1ADS/MXLADS boards + + config MACH_SCB9328 + bool "Synertronixx scb9328" + select IMX_HAVE_PLATFORM_IMX_UART + help + Say Y here if you are using a Synertronixx scb9328 board + + endif + + if ARCH_MX2 + + config SOC_IMX21 + select CPU_ARM926T + select ARCH_MXC_AUDMUX_V1 + select IMX_HAVE_DMA_V1 + select IMX_HAVE_IOMUX_V1 + bool + + config SOC_IMX27 + select CPU_ARM926T + select ARCH_MXC_AUDMUX_V1 + select IMX_HAVE_DMA_V1 + select IMX_HAVE_IOMUX_V1 + bool + + choice + prompt "CPUs:" + default MACH_MX21 + + config MACH_MX21 + bool "i.MX21 support" + select SOC_IMX21 + help + This enables support for Freescale's MX2 based i.MX21 processor. + + config MACH_MX27 + bool "i.MX27 support" + select SOC_IMX27 + help + This enables support for Freescale's MX2 based i.MX27 processor. + + endchoice + + endif + + if MACH_MX21 + + comment "MX21 platforms:" + + config MACH_MX21ADS + bool "MX21ADS platform" + select IMX_HAVE_PLATFORM_IMX_UART + select IMX_HAVE_PLATFORM_MXC_NAND + help + Include support for MX21ADS platform. This includes specific + configurations for the board and its peripherals. + + endif + + if MACH_MX27 + + comment "MX27 platforms:" + + config MACH_MX27ADS + bool "MX27ADS platform" + select IMX_HAVE_PLATFORM_IMX_I2C + select IMX_HAVE_PLATFORM_IMX_UART + select IMX_HAVE_PLATFORM_MXC_NAND + help + Include support for MX27ADS platform. This includes specific + configurations for the board and its peripherals. + + config MACH_PCM038 + bool "Phytec phyCORE-i.MX27 CPU module (pcm038)" + select IMX_HAVE_PLATFORM_IMX_I2C + select IMX_HAVE_PLATFORM_IMX_UART + select IMX_HAVE_PLATFORM_MXC_NAND + select IMX_HAVE_PLATFORM_SPI_IMX + select MXC_ULPI if USB_ULPI + help + Include support for phyCORE-i.MX27 (aka pcm038) platform. This + includes specific configurations for the module and its peripherals. + + choice + prompt "Baseboard" + depends on MACH_PCM038 + default MACH_PCM970_BASEBOARD + + config MACH_PCM970_BASEBOARD + prompt "PHYTEC PCM970 development board" + bool + help + This adds board specific devices that can be found on Phytec's + PCM970 evaluation board. + + endchoice + + config MACH_CPUIMX27 + bool "Eukrea CPUIMX27 module" + select IMX_HAVE_PLATFORM_IMX_I2C + select IMX_HAVE_PLATFORM_IMX_UART + select IMX_HAVE_PLATFORM_MXC_NAND + help + Include support for Eukrea CPUIMX27 platform. This includes + specific configurations for the module and its peripherals. + + config MACH_EUKREA_CPUIMX27_USESDHC2 + bool "CPUIMX27 integrates SDHC2 module" + depends on MACH_CPUIMX27 + help - This adds support for the internal SDHC2 used on CPUIMX27 used ++ This adds support for the internal SDHC2 used on CPUIMX27 + for wifi or eMMC. + ++config MACH_EUKREA_CPUIMX27_USEUART4 ++ bool "CPUIMX27 integrates UART4 module" ++ depends on MACH_CPUIMX27 ++ help ++ This adds support for the internal UART4 used on CPUIMX27 ++ for bluetooth. ++ + choice + prompt "Baseboard" + depends on MACH_CPUIMX27 + default MACH_EUKREA_MBIMX27_BASEBOARD + + config MACH_EUKREA_MBIMX27_BASEBOARD + prompt "Eukrea MBIMX27 development board" + bool + select IMX_HAVE_PLATFORM_IMX_UART + select IMX_HAVE_PLATFORM_SPI_IMX + help + This adds board specific devices that can be found on Eukrea's + MBIMX27 evaluation board. + + endchoice + + config MACH_MX27_3DS + bool "MX27PDK platform" + select IMX_HAVE_PLATFORM_IMX_UART + help + Include support for MX27PDK platform. This includes specific + configurations for the board and its peripherals. + + config MACH_IMX27LITE + bool "LogicPD MX27 LITEKIT platform" + select IMX_HAVE_PLATFORM_IMX_UART + help + Include support for MX27 LITEKIT platform. This includes specific + configurations for the board and its peripherals. + + config MACH_PCA100 + bool "Phytec phyCARD-s (pca100)" + select IMX_HAVE_PLATFORM_IMX_I2C + select IMX_HAVE_PLATFORM_IMX_UART + select IMX_HAVE_PLATFORM_MXC_NAND + select IMX_HAVE_PLATFORM_SPI_IMX + select MXC_ULPI if USB_ULPI + help + Include support for phyCARD-s (aka pca100) platform. This + includes specific configurations for the module and its peripherals. + + config MACH_MXT_TD60 + bool "Maxtrack i-MXT TD60" + select IMX_HAVE_PLATFORM_IMX_I2C + select IMX_HAVE_PLATFORM_IMX_UART + select IMX_HAVE_PLATFORM_MXC_NAND + help + Include support for i-MXT (aka td60) platform. This + includes specific configurations for the module and its peripherals. + + endif diff --cc arch/arm/mach-imx/Makefile index 000000000000,86b53e6bc94e..46a9fdfbbd15 mode 000000,100644..100644 --- a/arch/arm/mach-imx/Makefile +++ b/arch/arm/mach-imx/Makefile @@@ -1,0 -1,33 +1,33 @@@ + # + # Makefile for the linux kernel. + # + + # Object file lists. + + obj-y := devices.o + + obj-$(CONFIG_IMX_HAVE_DMA_V1) += dma-v1.o + + obj-$(CONFIG_ARCH_MX1) += clock-imx1.o mm-imx1.o + obj-$(CONFIG_MACH_MX21) += clock-imx21.o mm-imx21.o + -obj-$(CONFIG_MACH_MX27) += cpu-imx27.o ++obj-$(CONFIG_MACH_MX27) += cpu-imx27.o pm-imx27.o + obj-$(CONFIG_MACH_MX27) += clock-imx27.o mm-imx27.o + + # Support for CMOS sensor interface + obj-$(CONFIG_MX1_VIDEO) += mx1-camera-fiq.o mx1-camera-fiq-ksym.o + + obj-$(CONFIG_ARCH_MX1ADS) += mach-mx1ads.o + obj-$(CONFIG_MACH_SCB9328) += mach-scb9328.o + + obj-$(CONFIG_MACH_MX21ADS) += mach-mx21ads.o + + obj-$(CONFIG_MACH_MX27ADS) += mach-mx27ads.o + obj-$(CONFIG_MACH_PCM038) += mach-pcm038.o + obj-$(CONFIG_MACH_PCM970_BASEBOARD) += pcm970-baseboard.o + obj-$(CONFIG_MACH_MX27_3DS) += mach-mx27_3ds.o + obj-$(CONFIG_MACH_IMX27LITE) += mach-imx27lite.o + obj-$(CONFIG_MACH_CPUIMX27) += mach-cpuimx27.o + obj-$(CONFIG_MACH_EUKREA_MBIMX27_BASEBOARD) += eukrea_mbimx27-baseboard.o + obj-$(CONFIG_MACH_PCA100) += mach-pca100.o + obj-$(CONFIG_MACH_MXT_TD60) += mach-mxt_td60.o diff --cc arch/arm/mach-imx/clock-imx27.c index 000000000000,0f0823c8b170..5a1aa15c8a16 mode 000000,100644..100644 --- a/arch/arm/mach-imx/clock-imx27.c +++ b/arch/arm/mach-imx/clock-imx27.c @@@ -1,0 -1,763 +1,763 @@@ + /* + * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright 2008 Juergen Beisert, kernel@pengutronix.de + * Copyright 2008 Martin Fuzzey, mfuzzey@gmail.com + * + * 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 + #include + #include + + #include + #include + + #include + #include + #include + + #define IO_ADDR_CCM(off) (MX27_IO_ADDRESS(MX27_CCM_BASE_ADDR + (off))) + + /* Register offsets */ + #define CCM_CSCR IO_ADDR_CCM(0x0) + #define CCM_MPCTL0 IO_ADDR_CCM(0x4) + #define CCM_MPCTL1 IO_ADDR_CCM(0x8) + #define CCM_SPCTL0 IO_ADDR_CCM(0xc) + #define CCM_SPCTL1 IO_ADDR_CCM(0x10) + #define CCM_OSC26MCTL IO_ADDR_CCM(0x14) + #define CCM_PCDR0 IO_ADDR_CCM(0x18) + #define CCM_PCDR1 IO_ADDR_CCM(0x1c) + #define CCM_PCCR0 IO_ADDR_CCM(0x20) + #define CCM_PCCR1 IO_ADDR_CCM(0x24) + #define CCM_CCSR IO_ADDR_CCM(0x28) + #define CCM_PMCTL IO_ADDR_CCM(0x2c) + #define CCM_PMCOUNT IO_ADDR_CCM(0x30) + #define CCM_WKGDCTL IO_ADDR_CCM(0x34) + + #define CCM_CSCR_UPDATE_DIS (1 << 31) + #define CCM_CSCR_SSI2 (1 << 23) + #define CCM_CSCR_SSI1 (1 << 22) + #define CCM_CSCR_VPU (1 << 21) + #define CCM_CSCR_MSHC (1 << 20) + #define CCM_CSCR_SPLLRES (1 << 19) + #define CCM_CSCR_MPLLRES (1 << 18) + #define CCM_CSCR_SP (1 << 17) + #define CCM_CSCR_MCU (1 << 16) + #define CCM_CSCR_OSC26MDIV (1 << 4) + #define CCM_CSCR_OSC26M (1 << 3) + #define CCM_CSCR_FPM (1 << 2) + #define CCM_CSCR_SPEN (1 << 1) + #define CCM_CSCR_MPEN (1 << 0) + + /* i.MX27 TO 2+ */ + #define CCM_CSCR_ARM_SRC (1 << 15) + + #define CCM_SPCTL1_LF (1 << 15) + #define CCM_SPCTL1_BRMO (1 << 6) + + static struct clk mpll_main1_clk, mpll_main2_clk; + + static int clk_pccr_enable(struct clk *clk) + { + unsigned long reg; + + if (!clk->enable_reg) + return 0; + + reg = __raw_readl(clk->enable_reg); + reg |= 1 << clk->enable_shift; + __raw_writel(reg, clk->enable_reg); + + return 0; + } + + static void clk_pccr_disable(struct clk *clk) + { + unsigned long reg; + + if (!clk->enable_reg) + return; + + reg = __raw_readl(clk->enable_reg); + reg &= ~(1 << clk->enable_shift); + __raw_writel(reg, clk->enable_reg); + } + + static int clk_spll_enable(struct clk *clk) + { + unsigned long reg; + + reg = __raw_readl(CCM_CSCR); + reg |= CCM_CSCR_SPEN; + __raw_writel(reg, CCM_CSCR); + + while (!(__raw_readl(CCM_SPCTL1) & CCM_SPCTL1_LF)); + + return 0; + } + + static void clk_spll_disable(struct clk *clk) + { + unsigned long reg; + + reg = __raw_readl(CCM_CSCR); + reg &= ~CCM_CSCR_SPEN; + __raw_writel(reg, CCM_CSCR); + } + + static int clk_cpu_set_parent(struct clk *clk, struct clk *parent) + { + int cscr = __raw_readl(CCM_CSCR); + + if (clk->parent == parent) + return 0; + + if (mx27_revision() >= CHIP_REV_2_0) { + if (parent == &mpll_main1_clk) { + cscr |= CCM_CSCR_ARM_SRC; + } else { + if (parent == &mpll_main2_clk) + cscr &= ~CCM_CSCR_ARM_SRC; + else + return -EINVAL; + } + __raw_writel(cscr, CCM_CSCR); + clk->parent = parent; + return 0; + } + return -ENODEV; + } + + static unsigned long round_rate_cpu(struct clk *clk, unsigned long rate) + { + int div; + unsigned long parent_rate; + + parent_rate = clk_get_rate(clk->parent); + + div = parent_rate / rate; + if (parent_rate % rate) + div++; + + if (div > 4) + div = 4; + + return parent_rate / div; + } + + static int set_rate_cpu(struct clk *clk, unsigned long rate) + { + unsigned int div; + uint32_t reg; + unsigned long parent_rate; + + parent_rate = clk_get_rate(clk->parent); + + div = parent_rate / rate; + + if (div > 4 || div < 1 || ((parent_rate / div) != rate)) + return -EINVAL; + + div--; + + reg = __raw_readl(CCM_CSCR); + if (mx27_revision() >= CHIP_REV_2_0) { + reg &= ~(3 << 12); + reg |= div << 12; + reg &= ~(CCM_CSCR_FPM | CCM_CSCR_SPEN); + __raw_writel(reg | CCM_CSCR_UPDATE_DIS, CCM_CSCR); + } else { + printk(KERN_ERR "Can't set CPU frequency!\n"); + } + + return 0; + } + + static unsigned long round_rate_per(struct clk *clk, unsigned long rate) + { + u32 div; + unsigned long parent_rate; + + parent_rate = clk_get_rate(clk->parent); + + div = parent_rate / rate; + if (parent_rate % rate) + div++; + + if (div > 64) + div = 64; + + return parent_rate / div; + } + + static int set_rate_per(struct clk *clk, unsigned long rate) + { + u32 reg; + u32 div; + unsigned long parent_rate; + + parent_rate = clk_get_rate(clk->parent); + + if (clk->id < 0 || clk->id > 3) + return -EINVAL; + + div = parent_rate / rate; + if (div > 64 || div < 1 || ((parent_rate / div) != rate)) + return -EINVAL; + div--; + + reg = __raw_readl(CCM_PCDR1) & ~(0x3f << (clk->id << 3)); + reg |= div << (clk->id << 3); + __raw_writel(reg, CCM_PCDR1); + + return 0; + } + + static unsigned long get_rate_usb(struct clk *clk) + { + unsigned long usb_pdf; + unsigned long parent_rate; + + parent_rate = clk_get_rate(clk->parent); + + usb_pdf = (__raw_readl(CCM_CSCR) >> 28) & 0x7; + + return parent_rate / (usb_pdf + 1U); + } + + static unsigned long get_rate_ssix(struct clk *clk, unsigned long pdf) + { + unsigned long parent_rate; + + parent_rate = clk_get_rate(clk->parent); + + if (mx27_revision() >= CHIP_REV_2_0) + pdf += 4; /* MX27 TO2+ */ + else + pdf = (pdf < 2) ? 124UL : pdf; /* MX21 & MX27 TO1 */ + + return 2UL * parent_rate / pdf; + } + + static unsigned long get_rate_ssi1(struct clk *clk) + { + return get_rate_ssix(clk, (__raw_readl(CCM_PCDR0) >> 16) & 0x3f); + } + + static unsigned long get_rate_ssi2(struct clk *clk) + { + return get_rate_ssix(clk, (__raw_readl(CCM_PCDR0) >> 26) & 0x3f); + } + + static unsigned long get_rate_nfc(struct clk *clk) + { + unsigned long nfc_pdf; + unsigned long parent_rate; + + parent_rate = clk_get_rate(clk->parent); + + if (mx27_revision() >= CHIP_REV_2_0) + nfc_pdf = (__raw_readl(CCM_PCDR0) >> 6) & 0xf; + else + nfc_pdf = (__raw_readl(CCM_PCDR0) >> 12) & 0xf; + + return parent_rate / (nfc_pdf + 1); + } + + static unsigned long get_rate_vpu(struct clk *clk) + { + unsigned long vpu_pdf; + unsigned long parent_rate; + + parent_rate = clk_get_rate(clk->parent); + + if (mx27_revision() >= CHIP_REV_2_0) { + vpu_pdf = (__raw_readl(CCM_PCDR0) >> 10) & 0x3f; + vpu_pdf += 4; + } else { + vpu_pdf = (__raw_readl(CCM_PCDR0) >> 8) & 0xf; + vpu_pdf = (vpu_pdf < 2) ? 124 : vpu_pdf; + } + + return 2UL * parent_rate / vpu_pdf; + } + + static unsigned long round_rate_parent(struct clk *clk, unsigned long rate) + { + return clk->parent->round_rate(clk->parent, rate); + } + + static unsigned long get_rate_parent(struct clk *clk) + { + return clk_get_rate(clk->parent); + } + + static int set_rate_parent(struct clk *clk, unsigned long rate) + { + return clk->parent->set_rate(clk->parent, rate); + } + + /* in Hz */ + static unsigned long external_high_reference = 26000000; + + static unsigned long get_rate_high_reference(struct clk *clk) + { + return external_high_reference; + } + + /* in Hz */ + static unsigned long external_low_reference = 32768; + + static unsigned long get_rate_low_reference(struct clk *clk) + { + return external_low_reference; + } + + static unsigned long get_rate_fpm(struct clk *clk) + { + return clk_get_rate(clk->parent) * 1024; + } + + static unsigned long get_rate_mpll(struct clk *clk) + { + return mxc_decode_pll(__raw_readl(CCM_MPCTL0), + clk_get_rate(clk->parent)); + } + + static unsigned long get_rate_mpll_main(struct clk *clk) + { + unsigned long parent_rate; + + parent_rate = clk_get_rate(clk->parent); + + /* i.MX27 TO2: + * clk->id == 0: arm clock source path 1 which is from 2 * MPLL / 2 + * clk->id == 1: arm clock source path 2 which is from 2 * MPLL / 3 + */ + if (mx27_revision() >= CHIP_REV_2_0 && clk->id == 1) + return 2UL * parent_rate / 3UL; + + return parent_rate; + } + + static unsigned long get_rate_spll(struct clk *clk) + { + uint32_t reg; + unsigned long rate; + + rate = clk_get_rate(clk->parent); + + reg = __raw_readl(CCM_SPCTL0); + + /* On TO2 we have to write the value back. Otherwise we + * read 0 from this register the next time. + */ + if (mx27_revision() >= CHIP_REV_2_0) + __raw_writel(reg, CCM_SPCTL0); + + return mxc_decode_pll(reg, rate); + } + + static unsigned long get_rate_cpu(struct clk *clk) + { + u32 div; + unsigned long rate; + + if (mx27_revision() >= CHIP_REV_2_0) + div = (__raw_readl(CCM_CSCR) >> 12) & 0x3; + else + div = (__raw_readl(CCM_CSCR) >> 13) & 0x7; + + rate = clk_get_rate(clk->parent); + return rate / (div + 1); + } + + static unsigned long get_rate_ahb(struct clk *clk) + { + unsigned long rate, bclk_pdf; + + if (mx27_revision() >= CHIP_REV_2_0) + bclk_pdf = (__raw_readl(CCM_CSCR) >> 8) & 0x3; + else + bclk_pdf = (__raw_readl(CCM_CSCR) >> 9) & 0xf; + + rate = clk_get_rate(clk->parent); + return rate / (bclk_pdf + 1); + } + + static unsigned long get_rate_ipg(struct clk *clk) + { + unsigned long rate, ipg_pdf; + + if (mx27_revision() >= CHIP_REV_2_0) + return clk_get_rate(clk->parent); + else + ipg_pdf = (__raw_readl(CCM_CSCR) >> 8) & 1; + + rate = clk_get_rate(clk->parent); + return rate / (ipg_pdf + 1); + } + + static unsigned long get_rate_per(struct clk *clk) + { + unsigned long perclk_pdf, parent_rate; + + parent_rate = clk_get_rate(clk->parent); + + if (clk->id < 0 || clk->id > 3) + return 0; + + perclk_pdf = (__raw_readl(CCM_PCDR1) >> (clk->id << 3)) & 0x3f; + + return parent_rate / (perclk_pdf + 1); + } + + /* + * the high frequency external clock reference + * Default case is 26MHz. Could be changed at runtime + * with a call to change_external_high_reference() + */ + static struct clk ckih_clk = { + .get_rate = get_rate_high_reference, + }; + + static struct clk mpll_clk = { + .parent = &ckih_clk, + .get_rate = get_rate_mpll, + }; + + /* For i.MX27 TO2, it is the MPLL path 1 of ARM core + * It provides the clock source whose rate is same as MPLL + */ + static struct clk mpll_main1_clk = { + .id = 0, + .parent = &mpll_clk, + .get_rate = get_rate_mpll_main, + }; + + /* For i.MX27 TO2, it is the MPLL path 2 of ARM core + * It provides the clock source whose rate is same MPLL * 2 / 3 + */ + static struct clk mpll_main2_clk = { + .id = 1, + .parent = &mpll_clk, + .get_rate = get_rate_mpll_main, + }; + + static struct clk ahb_clk = { + .parent = &mpll_main2_clk, + .get_rate = get_rate_ahb, + }; + + static struct clk ipg_clk = { + .parent = &ahb_clk, + .get_rate = get_rate_ipg, + }; + + static struct clk cpu_clk = { + .parent = &mpll_main2_clk, + .set_parent = clk_cpu_set_parent, + .round_rate = round_rate_cpu, + .get_rate = get_rate_cpu, + .set_rate = set_rate_cpu, + }; + + static struct clk spll_clk = { + .parent = &ckih_clk, + .get_rate = get_rate_spll, + .enable = clk_spll_enable, + .disable = clk_spll_disable, + }; + + /* + * the low frequency external clock reference + * Default case is 32.768kHz. + */ + static struct clk ckil_clk = { + .get_rate = get_rate_low_reference, + }; + + /* Output of frequency pre multiplier */ + static struct clk fpm_clk = { + .parent = &ckil_clk, + .get_rate = get_rate_fpm, + }; + + #define PCCR0 CCM_PCCR0 + #define PCCR1 CCM_PCCR1 + + #define DEFINE_CLOCK(name, i, er, es, gr, s, p) \ + static struct clk name = { \ + .id = i, \ + .enable_reg = er, \ + .enable_shift = es, \ + .get_rate = gr, \ + .enable = clk_pccr_enable, \ + .disable = clk_pccr_disable, \ + .secondary = s, \ + .parent = p, \ + } + + #define DEFINE_CLOCK1(name, i, er, es, getsetround, s, p) \ + static struct clk name = { \ + .id = i, \ + .enable_reg = er, \ + .enable_shift = es, \ + .get_rate = get_rate_##getsetround, \ + .set_rate = set_rate_##getsetround, \ + .round_rate = round_rate_##getsetround, \ + .enable = clk_pccr_enable, \ + .disable = clk_pccr_disable, \ + .secondary = s, \ + .parent = p, \ + } + + /* Forward declaration to keep the following list in order */ + static struct clk slcdc_clk1, sahara2_clk1, rtic_clk1, fec_clk1, emma_clk1, + dma_clk1, lcdc_clk2, vpu_clk1; + + /* All clocks we can gate through PCCRx in the order of PCCRx bits */ + DEFINE_CLOCK(ssi2_clk1, 1, PCCR0, 0, NULL, NULL, &ipg_clk); + DEFINE_CLOCK(ssi1_clk1, 0, PCCR0, 1, NULL, NULL, &ipg_clk); + DEFINE_CLOCK(slcdc_clk, 0, PCCR0, 2, NULL, &slcdc_clk1, &ahb_clk); + DEFINE_CLOCK(sdhc3_clk1, 0, PCCR0, 3, NULL, NULL, &ipg_clk); + DEFINE_CLOCK(sdhc2_clk1, 0, PCCR0, 4, NULL, NULL, &ipg_clk); + DEFINE_CLOCK(sdhc1_clk1, 0, PCCR0, 5, NULL, NULL, &ipg_clk); + DEFINE_CLOCK(scc_clk, 0, PCCR0, 6, NULL, NULL, &ipg_clk); + DEFINE_CLOCK(sahara2_clk, 0, PCCR0, 7, NULL, &sahara2_clk1, &ahb_clk); + DEFINE_CLOCK(rtic_clk, 0, PCCR0, 8, NULL, &rtic_clk1, &ahb_clk); + DEFINE_CLOCK(rtc_clk, 0, PCCR0, 9, NULL, NULL, &ipg_clk); + DEFINE_CLOCK(pwm_clk1, 0, PCCR0, 11, NULL, NULL, &ipg_clk); + DEFINE_CLOCK(owire_clk, 0, PCCR0, 12, NULL, NULL, &ipg_clk); + DEFINE_CLOCK(mstick_clk1, 0, PCCR0, 13, NULL, NULL, &ipg_clk); + DEFINE_CLOCK(lcdc_clk1, 0, PCCR0, 14, NULL, &lcdc_clk2, &ipg_clk); + DEFINE_CLOCK(kpp_clk, 0, PCCR0, 15, NULL, NULL, &ipg_clk); + DEFINE_CLOCK(iim_clk, 0, PCCR0, 16, NULL, NULL, &ipg_clk); + DEFINE_CLOCK(i2c2_clk, 1, PCCR0, 17, NULL, NULL, &ipg_clk); + DEFINE_CLOCK(i2c1_clk, 0, PCCR0, 18, NULL, NULL, &ipg_clk); + DEFINE_CLOCK(gpt6_clk1, 0, PCCR0, 29, NULL, NULL, &ipg_clk); + DEFINE_CLOCK(gpt5_clk1, 0, PCCR0, 20, NULL, NULL, &ipg_clk); + DEFINE_CLOCK(gpt4_clk1, 0, PCCR0, 21, NULL, NULL, &ipg_clk); + DEFINE_CLOCK(gpt3_clk1, 0, PCCR0, 22, NULL, NULL, &ipg_clk); + DEFINE_CLOCK(gpt2_clk1, 0, PCCR0, 23, NULL, NULL, &ipg_clk); + DEFINE_CLOCK(gpt1_clk1, 0, PCCR0, 24, NULL, NULL, &ipg_clk); + DEFINE_CLOCK(gpio_clk, 0, PCCR0, 25, NULL, NULL, &ipg_clk); + DEFINE_CLOCK(fec_clk, 0, PCCR0, 26, NULL, &fec_clk1, &ahb_clk); + DEFINE_CLOCK(emma_clk, 0, PCCR0, 27, NULL, &emma_clk1, &ahb_clk); + DEFINE_CLOCK(dma_clk, 0, PCCR0, 28, NULL, &dma_clk1, &ahb_clk); + DEFINE_CLOCK(cspi13_clk1, 0, PCCR0, 29, NULL, NULL, &ipg_clk); + DEFINE_CLOCK(cspi2_clk1, 0, PCCR0, 30, NULL, NULL, &ipg_clk); + DEFINE_CLOCK(cspi1_clk1, 0, PCCR0, 31, NULL, NULL, &ipg_clk); + + DEFINE_CLOCK(mstick_clk, 0, PCCR1, 2, NULL, &mstick_clk1, &ipg_clk); + DEFINE_CLOCK(nfc_clk, 0, PCCR1, 3, get_rate_nfc, NULL, &cpu_clk); + DEFINE_CLOCK(ssi2_clk, 1, PCCR1, 4, get_rate_ssi2, &ssi2_clk1, &mpll_main2_clk); + DEFINE_CLOCK(ssi1_clk, 0, PCCR1, 5, get_rate_ssi1, &ssi1_clk1, &mpll_main2_clk); + DEFINE_CLOCK(vpu_clk, 0, PCCR1, 6, get_rate_vpu, &vpu_clk1, &mpll_main2_clk); + DEFINE_CLOCK1(per4_clk, 3, PCCR1, 7, per, NULL, &mpll_main2_clk); + DEFINE_CLOCK1(per3_clk, 2, PCCR1, 8, per, NULL, &mpll_main2_clk); + DEFINE_CLOCK1(per2_clk, 1, PCCR1, 9, per, NULL, &mpll_main2_clk); + DEFINE_CLOCK1(per1_clk, 0, PCCR1, 10, per, NULL, &mpll_main2_clk); + DEFINE_CLOCK(usb_clk1, 0, PCCR1, 11, NULL, NULL, &ahb_clk); + DEFINE_CLOCK(slcdc_clk1, 0, PCCR1, 12, NULL, NULL, &ahb_clk); + DEFINE_CLOCK(sahara2_clk1, 0, PCCR1, 13, NULL, NULL, &ahb_clk); + DEFINE_CLOCK(rtic_clk1, 0, PCCR1, 14, NULL, NULL, &ahb_clk); + DEFINE_CLOCK(lcdc_clk2, 0, PCCR1, 15, NULL, NULL, &ahb_clk); + DEFINE_CLOCK(vpu_clk1, 0, PCCR1, 16, NULL, NULL, &ahb_clk); + DEFINE_CLOCK(fec_clk1, 0, PCCR1, 17, NULL, NULL, &ahb_clk); + DEFINE_CLOCK(emma_clk1, 0, PCCR1, 18, NULL, NULL, &ahb_clk); + DEFINE_CLOCK(emi_clk, 0, PCCR1, 19, NULL, NULL, &ahb_clk); + DEFINE_CLOCK(dma_clk1, 0, PCCR1, 20, NULL, NULL, &ahb_clk); + DEFINE_CLOCK(csi_clk1, 0, PCCR1, 21, NULL, NULL, &ahb_clk); + DEFINE_CLOCK(brom_clk, 0, PCCR1, 22, NULL, NULL, &ahb_clk); + DEFINE_CLOCK(ata_clk, 0, PCCR1, 23, NULL, NULL, &ahb_clk); + DEFINE_CLOCK(wdog_clk, 0, PCCR1, 24, NULL, NULL, &ipg_clk); + DEFINE_CLOCK(usb_clk, 0, PCCR1, 25, get_rate_usb, &usb_clk1, &spll_clk); + DEFINE_CLOCK(uart6_clk1, 0, PCCR1, 26, NULL, NULL, &ipg_clk); + DEFINE_CLOCK(uart5_clk1, 0, PCCR1, 27, NULL, NULL, &ipg_clk); + DEFINE_CLOCK(uart4_clk1, 0, PCCR1, 28, NULL, NULL, &ipg_clk); + DEFINE_CLOCK(uart3_clk1, 0, PCCR1, 29, NULL, NULL, &ipg_clk); + DEFINE_CLOCK(uart2_clk1, 0, PCCR1, 30, NULL, NULL, &ipg_clk); + DEFINE_CLOCK(uart1_clk1, 0, PCCR1, 31, NULL, NULL, &ipg_clk); + + /* Clocks we cannot directly gate, but drivers need their rates */ + DEFINE_CLOCK(cspi1_clk, 0, 0, 0, NULL, &cspi1_clk1, &per2_clk); + DEFINE_CLOCK(cspi2_clk, 1, 0, 0, NULL, &cspi2_clk1, &per2_clk); + DEFINE_CLOCK(cspi3_clk, 2, 0, 0, NULL, &cspi13_clk1, &per2_clk); + DEFINE_CLOCK(sdhc1_clk, 0, 0, 0, NULL, &sdhc1_clk1, &per2_clk); + DEFINE_CLOCK(sdhc2_clk, 1, 0, 0, NULL, &sdhc2_clk1, &per2_clk); + DEFINE_CLOCK(sdhc3_clk, 2, 0, 0, NULL, &sdhc3_clk1, &per2_clk); + DEFINE_CLOCK(pwm_clk, 0, 0, 0, NULL, &pwm_clk1, &per1_clk); + DEFINE_CLOCK(gpt1_clk, 0, 0, 0, NULL, &gpt1_clk1, &per1_clk); + DEFINE_CLOCK(gpt2_clk, 1, 0, 0, NULL, &gpt2_clk1, &per1_clk); + DEFINE_CLOCK(gpt3_clk, 2, 0, 0, NULL, &gpt3_clk1, &per1_clk); + DEFINE_CLOCK(gpt4_clk, 3, 0, 0, NULL, &gpt4_clk1, &per1_clk); + DEFINE_CLOCK(gpt5_clk, 4, 0, 0, NULL, &gpt5_clk1, &per1_clk); + DEFINE_CLOCK(gpt6_clk, 5, 0, 0, NULL, &gpt6_clk1, &per1_clk); + DEFINE_CLOCK(uart1_clk, 0, 0, 0, NULL, &uart1_clk1, &per1_clk); + DEFINE_CLOCK(uart2_clk, 1, 0, 0, NULL, &uart2_clk1, &per1_clk); + DEFINE_CLOCK(uart3_clk, 2, 0, 0, NULL, &uart3_clk1, &per1_clk); + DEFINE_CLOCK(uart4_clk, 3, 0, 0, NULL, &uart4_clk1, &per1_clk); + DEFINE_CLOCK(uart5_clk, 4, 0, 0, NULL, &uart5_clk1, &per1_clk); + DEFINE_CLOCK(uart6_clk, 5, 0, 0, NULL, &uart6_clk1, &per1_clk); + DEFINE_CLOCK1(lcdc_clk, 0, 0, 0, parent, &lcdc_clk1, &per3_clk); + DEFINE_CLOCK1(csi_clk, 0, 0, 0, parent, &csi_clk1, &per4_clk); + + #define _REGISTER_CLOCK(d, n, c) \ + { \ + .dev_id = d, \ + .con_id = n, \ + .clk = &c, \ + }, + + static struct clk_lookup lookups[] = { + _REGISTER_CLOCK("imx-uart.0", NULL, uart1_clk) + _REGISTER_CLOCK("imx-uart.1", NULL, uart2_clk) + _REGISTER_CLOCK("imx-uart.2", NULL, uart3_clk) + _REGISTER_CLOCK("imx-uart.3", NULL, uart4_clk) + _REGISTER_CLOCK("imx-uart.4", NULL, uart5_clk) + _REGISTER_CLOCK("imx-uart.5", NULL, uart6_clk) + _REGISTER_CLOCK(NULL, "gpt1", gpt1_clk) + _REGISTER_CLOCK(NULL, "gpt2", gpt2_clk) + _REGISTER_CLOCK(NULL, "gpt3", gpt3_clk) + _REGISTER_CLOCK(NULL, "gpt4", gpt4_clk) + _REGISTER_CLOCK(NULL, "gpt5", gpt5_clk) + _REGISTER_CLOCK(NULL, "gpt6", gpt6_clk) + _REGISTER_CLOCK("mxc_pwm.0", NULL, pwm_clk) + _REGISTER_CLOCK("mxc-mmc.0", NULL, sdhc1_clk) + _REGISTER_CLOCK("mxc-mmc.1", NULL, sdhc2_clk) + _REGISTER_CLOCK("mxc-mmc.2", NULL, sdhc3_clk) + _REGISTER_CLOCK("spi_imx.0", NULL, cspi1_clk) + _REGISTER_CLOCK("spi_imx.1", NULL, cspi2_clk) + _REGISTER_CLOCK("spi_imx.2", NULL, cspi3_clk) + _REGISTER_CLOCK("imx-fb.0", NULL, lcdc_clk) - _REGISTER_CLOCK(NULL, "csi", csi_clk) ++ _REGISTER_CLOCK("mx2-camera.0", NULL, csi_clk) + _REGISTER_CLOCK("fsl-usb2-udc", "usb", usb_clk) + _REGISTER_CLOCK("fsl-usb2-udc", "usb_ahb", usb_clk1) + _REGISTER_CLOCK("mxc-ehci.0", "usb", usb_clk) + _REGISTER_CLOCK("mxc-ehci.0", "usb_ahb", usb_clk1) + _REGISTER_CLOCK("mxc-ehci.1", "usb", usb_clk) + _REGISTER_CLOCK("mxc-ehci.1", "usb_ahb", usb_clk1) + _REGISTER_CLOCK("mxc-ehci.2", "usb", usb_clk) + _REGISTER_CLOCK("mxc-ehci.2", "usb_ahb", usb_clk1) + _REGISTER_CLOCK("imx-ssi.0", NULL, ssi1_clk) + _REGISTER_CLOCK("imx-ssi.1", NULL, ssi2_clk) + _REGISTER_CLOCK("mxc_nand.0", NULL, nfc_clk) + _REGISTER_CLOCK(NULL, "vpu", vpu_clk) + _REGISTER_CLOCK(NULL, "dma", dma_clk) + _REGISTER_CLOCK(NULL, "rtic", rtic_clk) + _REGISTER_CLOCK(NULL, "brom", brom_clk) + _REGISTER_CLOCK(NULL, "emma", emma_clk) + _REGISTER_CLOCK(NULL, "slcdc", slcdc_clk) + _REGISTER_CLOCK("fec.0", NULL, fec_clk) + _REGISTER_CLOCK(NULL, "emi", emi_clk) + _REGISTER_CLOCK(NULL, "sahara2", sahara2_clk) + _REGISTER_CLOCK(NULL, "ata", ata_clk) + _REGISTER_CLOCK(NULL, "mstick", mstick_clk) + _REGISTER_CLOCK("imx-wdt.0", NULL, wdog_clk) + _REGISTER_CLOCK(NULL, "gpio", gpio_clk) + _REGISTER_CLOCK("imx-i2c.0", NULL, i2c1_clk) + _REGISTER_CLOCK("imx-i2c.1", NULL, i2c2_clk) + _REGISTER_CLOCK(NULL, "iim", iim_clk) + _REGISTER_CLOCK(NULL, "kpp", kpp_clk) + _REGISTER_CLOCK("mxc_w1.0", NULL, owire_clk) + _REGISTER_CLOCK(NULL, "rtc", rtc_clk) + _REGISTER_CLOCK(NULL, "scc", scc_clk) + }; + + /* Adjust the clock path for TO2 and later */ + static void __init to2_adjust_clocks(void) + { + unsigned long cscr = __raw_readl(CCM_CSCR); + + if (mx27_revision() >= CHIP_REV_2_0) { + if (cscr & CCM_CSCR_ARM_SRC) + cpu_clk.parent = &mpll_main1_clk; + + if (!(cscr & CCM_CSCR_SSI2)) + ssi1_clk.parent = &spll_clk; + + if (!(cscr & CCM_CSCR_SSI1)) + ssi1_clk.parent = &spll_clk; + + if (!(cscr & CCM_CSCR_VPU)) + vpu_clk.parent = &spll_clk; + } else { + cpu_clk.parent = &mpll_clk; + cpu_clk.set_parent = NULL; + cpu_clk.round_rate = NULL; + cpu_clk.set_rate = NULL; + ahb_clk.parent = &mpll_clk; + + per1_clk.parent = &mpll_clk; + per2_clk.parent = &mpll_clk; + per3_clk.parent = &mpll_clk; + per4_clk.parent = &mpll_clk; + + ssi1_clk.parent = &mpll_clk; + ssi2_clk.parent = &mpll_clk; + + vpu_clk.parent = &mpll_clk; + } + } + + /* + * must be called very early to get information about the + * available clock rate when the timer framework starts + */ + int __init mx27_clocks_init(unsigned long fref) + { + u32 cscr = __raw_readl(CCM_CSCR); + + external_high_reference = fref; + + /* detect clock reference for both system PLLs */ + if (cscr & CCM_CSCR_MCU) + mpll_clk.parent = &ckih_clk; + else + mpll_clk.parent = &fpm_clk; + + if (cscr & CCM_CSCR_SP) + spll_clk.parent = &ckih_clk; + else + spll_clk.parent = &fpm_clk; + + to2_adjust_clocks(); + + clkdev_add_table(lookups, ARRAY_SIZE(lookups)); + + /* Turn off all clocks we do not need */ + __raw_writel(0, CCM_PCCR0); + __raw_writel((1 << 10) | (1 << 19), CCM_PCCR1); + + spll_clk.disable(&spll_clk); + + /* enable basic clocks */ + clk_enable(&per1_clk); + clk_enable(&gpio_clk); + clk_enable(&emi_clk); + clk_enable(&iim_clk); + + #if defined(CONFIG_DEBUG_LL) && !defined(CONFIG_DEBUG_ICEDCC) + clk_enable(&uart1_clk); + #endif + + mxc_timer_init(&gpt1_clk, MX27_IO_ADDRESS(MX27_GPT1_BASE_ADDR), + MX27_INT_GPT1); + + return 0; + } + diff --cc arch/arm/mach-imx/devices.c index 000000000000,9510687c4be3..9c271a752b84 mode 000000,100644..100644 --- a/arch/arm/mach-imx/devices.c +++ b/arch/arm/mach-imx/devices.c @@@ -1,0 -1,557 +1,609 @@@ + /* + * Author: MontaVista Software, Inc. + * + * + * Based on the OMAP devices.c + * + * 2005 (c) MontaVista Software, Inc. This file is licensed under the + * terms of the GNU General Public License version 2. This program is + * licensed "as is" without any warranty of any kind, whether express + * or implied. + * + * Copyright 2006-2007 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright 2008 Juergen Beisert, kernel@pengutronix.de + * Copyright 2008 Sascha Hauer, kernel@pengutronix.de + * Copyright (c) 2008 Paulius Zaleckas + * Copyright (c) 2008 Darius Augulis + * + * 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 + #include + #include + #include + #include + #include + #include + + #include + #include + #include + #include + + #include "devices.h" + + #if defined(CONFIG_ARCH_MX1) + static struct resource imx1_camera_resources[] = { + { + .start = 0x00224000, + .end = 0x00224010, + .flags = IORESOURCE_MEM, + }, { + .start = MX1_CSI_INT, + .end = MX1_CSI_INT, + .flags = IORESOURCE_IRQ, + }, + }; + + static u64 imx1_camera_dmamask = DMA_BIT_MASK(32); + + struct platform_device imx1_camera_device = { + .name = "mx1-camera", + .id = 0, /* This is used to put cameras on this interface */ + .dev = { + .dma_mask = &imx1_camera_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(32), + }, + .resource = imx1_camera_resources, + .num_resources = ARRAY_SIZE(imx1_camera_resources), + }; + + static struct resource imx_rtc_resources[] = { + { + .start = 0x00204000, + .end = 0x00204024, + .flags = IORESOURCE_MEM, + }, { + .start = MX1_RTC_INT, + .end = MX1_RTC_INT, + .flags = IORESOURCE_IRQ, + }, { + .start = MX1_RTC_SAMINT, + .end = MX1_RTC_SAMINT, + .flags = IORESOURCE_IRQ, + }, + }; + + struct platform_device imx_rtc_device = { + .name = "rtc-imx", + .id = 0, + .resource = imx_rtc_resources, + .num_resources = ARRAY_SIZE(imx_rtc_resources), + }; + + static struct resource imx_wdt_resources[] = { + { + .start = 0x00201000, + .end = 0x00201008, + .flags = IORESOURCE_MEM, + }, { + .start = MX1_WDT_INT, + .end = MX1_WDT_INT, + .flags = IORESOURCE_IRQ, + }, + }; + + struct platform_device imx_wdt_device = { + .name = "imx-wdt", + .id = 0, + .resource = imx_wdt_resources, + .num_resources = ARRAY_SIZE(imx_wdt_resources), + }; + + static struct resource imx_usb_resources[] = { + { + .start = 0x00212000, + .end = 0x00212148, + .flags = IORESOURCE_MEM, + }, { + .start = MX1_USBD_INT0, + .end = MX1_USBD_INT0, + .flags = IORESOURCE_IRQ, + }, { + .start = MX1_USBD_INT1, + .end = MX1_USBD_INT1, + .flags = IORESOURCE_IRQ, + }, { + .start = MX1_USBD_INT2, + .end = MX1_USBD_INT2, + .flags = IORESOURCE_IRQ, + }, { + .start = MX1_USBD_INT3, + .end = MX1_USBD_INT3, + .flags = IORESOURCE_IRQ, + }, { + .start = MX1_USBD_INT4, + .end = MX1_USBD_INT4, + .flags = IORESOURCE_IRQ, + }, { + .start = MX1_USBD_INT5, + .end = MX1_USBD_INT5, + .flags = IORESOURCE_IRQ, + }, { + .start = MX1_USBD_INT6, + .end = MX1_USBD_INT6, + .flags = IORESOURCE_IRQ, + }, + }; + + struct platform_device imx_usb_device = { + .name = "imx_udc", + .id = 0, + .num_resources = ARRAY_SIZE(imx_usb_resources), + .resource = imx_usb_resources, + }; + + /* GPIO port description */ + static struct mxc_gpio_port imx_gpio_ports[] = { + { + .chip.label = "gpio-0", + .base = (void __iomem *)MX1_IO_ADDRESS(MX1_GPIO_BASE_ADDR), + .irq = MX1_GPIO_INT_PORTA, + .virtual_irq_start = MXC_GPIO_IRQ_START, + }, { + .chip.label = "gpio-1", + .base = (void __iomem *)MX1_IO_ADDRESS(MX1_GPIO_BASE_ADDR + 0x100), + .irq = MX1_GPIO_INT_PORTB, + .virtual_irq_start = MXC_GPIO_IRQ_START + 32, + }, { + .chip.label = "gpio-2", + .base = (void __iomem *)MX1_IO_ADDRESS(MX1_GPIO_BASE_ADDR + 0x200), + .irq = MX1_GPIO_INT_PORTC, + .virtual_irq_start = MXC_GPIO_IRQ_START + 64, + }, { + .chip.label = "gpio-3", + .base = (void __iomem *)MX1_IO_ADDRESS(MX1_GPIO_BASE_ADDR + 0x300), + .irq = MX1_GPIO_INT_PORTD, + .virtual_irq_start = MXC_GPIO_IRQ_START + 96, + } + }; + + int __init imx1_register_gpios(void) + { + return mxc_gpio_init(imx_gpio_ports, ARRAY_SIZE(imx_gpio_ports)); + } + #endif + + #if defined(CONFIG_MACH_MX21) || defined(CONFIG_MACH_MX27) ++ ++#ifdef CONFIG_MACH_MX27 ++static struct resource mx27_camera_resources[] = { ++ { ++ .start = MX27_CSI_BASE_ADDR, ++ .end = MX27_CSI_BASE_ADDR + 0x1f, ++ .flags = IORESOURCE_MEM, ++ }, { ++ .start = MX27_EMMA_PRP_BASE_ADDR, ++ .end = MX27_EMMA_PRP_BASE_ADDR + 0x1f, ++ .flags = IORESOURCE_MEM, ++ }, { ++ .start = MX27_INT_CSI, ++ .end = MX27_INT_CSI, ++ .flags = IORESOURCE_IRQ, ++ },{ ++ .start = MX27_INT_EMMAPRP, ++ .end = MX27_INT_EMMAPRP, ++ .flags = IORESOURCE_IRQ, ++ }, ++}; ++struct platform_device mx27_camera_device = { ++ .name = "mx2-camera", ++ .id = 0, ++ .num_resources = ARRAY_SIZE(mx27_camera_resources), ++ .resource = mx27_camera_resources, ++ .dev = { ++ .coherent_dma_mask = 0xffffffff, ++ }, ++}; ++#endif ++ + /* + * General Purpose Timer + * - i.MX21: 3 timers + * - i.MX27: 6 timers + */ + #define DEFINE_IMX_GPT_DEVICE(n, baseaddr, irq) \ + static struct resource timer ## n ##_resources[] = { \ + { \ + .start = baseaddr, \ + .end = baseaddr + SZ_4K - 1, \ + .flags = IORESOURCE_MEM, \ + }, { \ + .start = irq, \ + .end = irq, \ + .flags = IORESOURCE_IRQ, \ + } \ + }; \ + \ + struct platform_device mxc_gpt ## n = { \ + .name = "imx_gpt", \ + .id = n, \ + .num_resources = ARRAY_SIZE(timer ## n ## _resources), \ + .resource = timer ## n ## _resources, \ + } + + /* We use gpt1 as system timer, so do not add a device for this one */ + DEFINE_IMX_GPT_DEVICE(1, MX2x_GPT2_BASE_ADDR, MX2x_INT_GPT2); + DEFINE_IMX_GPT_DEVICE(2, MX2x_GPT3_BASE_ADDR, MX2x_INT_GPT3); + + #ifdef CONFIG_MACH_MX27 + DEFINE_IMX_GPT_DEVICE(3, MX27_GPT4_BASE_ADDR, MX27_INT_GPT4); + DEFINE_IMX_GPT_DEVICE(4, MX27_GPT5_BASE_ADDR, MX27_INT_GPT5); + DEFINE_IMX_GPT_DEVICE(5, MX27_GPT6_BASE_ADDR, MX27_INT_GPT6); + #endif + + /* Watchdog: i.MX1 has seperate driver, i.MX21 and i.MX27 are equal */ + static struct resource mxc_wdt_resources[] = { + { + .start = MX2x_WDOG_BASE_ADDR, + .end = MX2x_WDOG_BASE_ADDR + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, + }; + + struct platform_device mxc_wdt = { + .name = "imx2-wdt", + .id = 0, + .num_resources = ARRAY_SIZE(mxc_wdt_resources), + .resource = mxc_wdt_resources, + }; + + static struct resource mxc_w1_master_resources[] = { + { + .start = MX2x_OWIRE_BASE_ADDR, + .end = MX2x_OWIRE_BASE_ADDR + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, + }; + + struct platform_device mxc_w1_master_device = { + .name = "mxc_w1", + .id = 0, + .num_resources = ARRAY_SIZE(mxc_w1_master_resources), + .resource = mxc_w1_master_resources, + }; + + /* + * lcdc: + * - i.MX1: the basic controller + * - i.MX21: to be checked + * - i.MX27: like i.MX1, with slightly variations + */ + static struct resource mxc_fb[] = { + { + .start = MX2x_LCDC_BASE_ADDR, + .end = MX2x_LCDC_BASE_ADDR + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, { + .start = MX2x_INT_LCDC, + .end = MX2x_INT_LCDC, + .flags = IORESOURCE_IRQ, + } + }; + + /* mxc lcd driver */ + struct platform_device mxc_fb_device = { + .name = "imx-fb", + .id = 0, + .num_resources = ARRAY_SIZE(mxc_fb), + .resource = mxc_fb, + .dev = { + .coherent_dma_mask = DMA_BIT_MASK(32), + }, + }; + + #ifdef CONFIG_MACH_MX27 + static struct resource mxc_fec_resources[] = { + { + .start = MX27_FEC_BASE_ADDR, + .end = MX27_FEC_BASE_ADDR + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, { + .start = MX27_INT_FEC, + .end = MX27_INT_FEC, + .flags = IORESOURCE_IRQ, + }, + }; + + struct platform_device mxc_fec_device = { + .name = "fec", + .id = 0, + .num_resources = ARRAY_SIZE(mxc_fec_resources), + .resource = mxc_fec_resources, + }; + #endif + + static struct resource mxc_pwm_resources[] = { + { + .start = MX2x_PWM_BASE_ADDR, + .end = MX2x_PWM_BASE_ADDR + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, { + .start = MX2x_INT_PWM, + .end = MX2x_INT_PWM, + .flags = IORESOURCE_IRQ, + } + }; + + struct platform_device mxc_pwm_device = { + .name = "mxc_pwm", + .id = 0, + .num_resources = ARRAY_SIZE(mxc_pwm_resources), + .resource = mxc_pwm_resources, + }; + + #define DEFINE_MXC_MMC_DEVICE(n, baseaddr, irq, dmareq) \ + static struct resource mxc_sdhc_resources ## n[] = { \ + { \ + .start = baseaddr, \ + .end = baseaddr + SZ_4K - 1, \ + .flags = IORESOURCE_MEM, \ + }, { \ + .start = irq, \ + .end = irq, \ + .flags = IORESOURCE_IRQ, \ + }, { \ + .start = dmareq, \ + .end = dmareq, \ + .flags = IORESOURCE_DMA, \ + }, \ + }; \ + \ + static u64 mxc_sdhc ## n ## _dmamask = DMA_BIT_MASK(32); \ + \ + struct platform_device mxc_sdhc_device ## n = { \ + .name = "mxc-mmc", \ + .id = n, \ + .dev = { \ + .dma_mask = &mxc_sdhc ## n ## _dmamask, \ + .coherent_dma_mask = DMA_BIT_MASK(32), \ + }, \ + .num_resources = ARRAY_SIZE(mxc_sdhc_resources ## n), \ + .resource = mxc_sdhc_resources ## n, \ + } + + DEFINE_MXC_MMC_DEVICE(0, MX2x_SDHC1_BASE_ADDR, MX2x_INT_SDHC1, MX2x_DMA_REQ_SDHC1); + DEFINE_MXC_MMC_DEVICE(1, MX2x_SDHC2_BASE_ADDR, MX2x_INT_SDHC2, MX2x_DMA_REQ_SDHC2); + + #ifdef CONFIG_MACH_MX27 + static struct resource otg_resources[] = { + { + .start = MX27_USBOTG_BASE_ADDR, + .end = MX27_USBOTG_BASE_ADDR + 0x1ff, + .flags = IORESOURCE_MEM, + }, { + .start = MX27_INT_USB3, + .end = MX27_INT_USB3, + .flags = IORESOURCE_IRQ, + }, + }; + + static u64 otg_dmamask = DMA_BIT_MASK(32); + + /* OTG gadget device */ + struct platform_device mxc_otg_udc_device = { + .name = "fsl-usb2-udc", + .id = -1, + .dev = { + .dma_mask = &otg_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(32), + }, + .resource = otg_resources, + .num_resources = ARRAY_SIZE(otg_resources), + }; + + /* OTG host */ + struct platform_device mxc_otg_host = { + .name = "mxc-ehci", + .id = 0, + .dev = { + .coherent_dma_mask = DMA_BIT_MASK(32), + .dma_mask = &otg_dmamask, + }, + .resource = otg_resources, + .num_resources = ARRAY_SIZE(otg_resources), + }; + + /* USB host 1 */ + + static u64 usbh1_dmamask = DMA_BIT_MASK(32); + + static struct resource mxc_usbh1_resources[] = { + { + .start = MX27_USBOTG_BASE_ADDR + 0x200, + .end = MX27_USBOTG_BASE_ADDR + 0x3ff, + .flags = IORESOURCE_MEM, + }, { + .start = MX27_INT_USB1, + .end = MX27_INT_USB1, + .flags = IORESOURCE_IRQ, + }, + }; + + struct platform_device mxc_usbh1 = { + .name = "mxc-ehci", + .id = 1, + .dev = { + .coherent_dma_mask = DMA_BIT_MASK(32), + .dma_mask = &usbh1_dmamask, + }, + .resource = mxc_usbh1_resources, + .num_resources = ARRAY_SIZE(mxc_usbh1_resources), + }; + + /* USB host 2 */ + static u64 usbh2_dmamask = DMA_BIT_MASK(32); + + static struct resource mxc_usbh2_resources[] = { + { + .start = MX27_USBOTG_BASE_ADDR + 0x400, + .end = MX27_USBOTG_BASE_ADDR + 0x5ff, + .flags = IORESOURCE_MEM, + }, { + .start = MX27_INT_USB2, + .end = MX27_INT_USB2, + .flags = IORESOURCE_IRQ, + }, + }; + + struct platform_device mxc_usbh2 = { + .name = "mxc-ehci", + .id = 2, + .dev = { + .coherent_dma_mask = DMA_BIT_MASK(32), + .dma_mask = &usbh2_dmamask, + }, + .resource = mxc_usbh2_resources, + .num_resources = ARRAY_SIZE(mxc_usbh2_resources), + }; + #endif + + #define DEFINE_IMX_SSI_DMARES(_name, ssin, suffix) \ + { \ + .name = _name, \ + .start = MX2x_DMA_REQ_SSI ## ssin ## _ ## suffix, \ + .end = MX2x_DMA_REQ_SSI ## ssin ## _ ## suffix, \ + .flags = IORESOURCE_DMA, \ + } + + #define DEFINE_IMX_SSI_DEVICE(n, ssin, baseaddr, irq) \ + static struct resource imx_ssi_resources ## n[] = { \ + { \ + .start = MX2x_SSI ## ssin ## _BASE_ADDR, \ + .end = MX2x_SSI ## ssin ## _BASE_ADDR + 0x6f, \ + .flags = IORESOURCE_MEM, \ + }, { \ + .start = MX2x_INT_SSI1, \ + .end = MX2x_INT_SSI1, \ + .flags = IORESOURCE_IRQ, \ + }, \ + DEFINE_IMX_SSI_DMARES("tx0", ssin, TX0), \ + DEFINE_IMX_SSI_DMARES("rx0", ssin, RX0), \ + DEFINE_IMX_SSI_DMARES("tx1", ssin, TX1), \ + DEFINE_IMX_SSI_DMARES("rx1", ssin, RX1), \ + }; \ + \ + struct platform_device imx_ssi_device ## n = { \ + .name = "imx-ssi", \ + .id = n, \ + .num_resources = ARRAY_SIZE(imx_ssi_resources ## n), \ + .resource = imx_ssi_resources ## n, \ + } + + DEFINE_IMX_SSI_DEVICE(0, 1, MX2x_SSI1_BASE_ADDR, MX2x_INT_SSI1); + DEFINE_IMX_SSI_DEVICE(1, 2, MX2x_SSI1_BASE_ADDR, MX2x_INT_SSI1); + + /* GPIO port description */ + #define DEFINE_MXC_GPIO_PORT_IRQ(SOC, n, _irq) \ + { \ + .chip.label = "gpio-" #n, \ + .irq = _irq, \ + .base = SOC ## _IO_ADDRESS(MX2x_GPIO_BASE_ADDR + \ + n * 0x100), \ + .virtual_irq_start = MXC_GPIO_IRQ_START + n * 32, \ + } + + #define DEFINE_MXC_GPIO_PORT(SOC, n) \ + { \ + .chip.label = "gpio-" #n, \ + .base = SOC ## _IO_ADDRESS(MX2x_GPIO_BASE_ADDR + \ + n * 0x100), \ + .virtual_irq_start = MXC_GPIO_IRQ_START + n * 32, \ + } + + #define DEFINE_MXC_GPIO_PORTS(SOC, pfx) \ + static struct mxc_gpio_port pfx ## _gpio_ports[] = { \ + DEFINE_MXC_GPIO_PORT_IRQ(SOC, 0, SOC ## _INT_GPIO), \ + DEFINE_MXC_GPIO_PORT(SOC, 1), \ + DEFINE_MXC_GPIO_PORT(SOC, 2), \ + DEFINE_MXC_GPIO_PORT(SOC, 3), \ + DEFINE_MXC_GPIO_PORT(SOC, 4), \ + DEFINE_MXC_GPIO_PORT(SOC, 5), \ + } + + #ifdef CONFIG_MACH_MX21 + DEFINE_MXC_GPIO_PORTS(MX21, imx21); + + int __init imx21_register_gpios(void) + { + return mxc_gpio_init(imx21_gpio_ports, ARRAY_SIZE(imx21_gpio_ports)); + } + #endif + + #ifdef CONFIG_MACH_MX27 + DEFINE_MXC_GPIO_PORTS(MX27, imx27); + + int __init imx27_register_gpios(void) + { + return mxc_gpio_init(imx27_gpio_ports, ARRAY_SIZE(imx27_gpio_ports)); + } + #endif + + #ifdef CONFIG_MACH_MX21 + static struct resource mx21_usbhc_resources[] = { + { + .start = MX21_USBOTG_BASE_ADDR, + .end = MX21_USBOTG_BASE_ADDR + SZ_8K - 1, + .flags = IORESOURCE_MEM, + }, + { + .start = MX21_INT_USBHOST, + .end = MX21_INT_USBHOST, + .flags = IORESOURCE_IRQ, + }, + }; + + struct platform_device mx21_usbhc_device = { + .name = "imx21-hcd", + .id = 0, + .dev = { + .dma_mask = &mx21_usbhc_device.dev.coherent_dma_mask, + .coherent_dma_mask = DMA_BIT_MASK(32), + }, + .num_resources = ARRAY_SIZE(mx21_usbhc_resources), + .resource = mx21_usbhc_resources, + }; + #endif ++ ++static struct resource imx_kpp_resources[] = { ++ { ++ .start = MX2x_KPP_BASE_ADDR, ++ .end = MX2x_KPP_BASE_ADDR + 0xf, ++ .flags = IORESOURCE_MEM ++ }, { ++ .start = MX2x_INT_KPP, ++ .end = MX2x_INT_KPP, ++ .flags = IORESOURCE_IRQ, ++ }, ++}; ++ ++struct platform_device imx_kpp_device = { ++ .name = "imx-keypad", ++ .id = -1, ++ .num_resources = ARRAY_SIZE(imx_kpp_resources), ++ .resource = imx_kpp_resources, ++}; ++ + #endif diff --cc arch/arm/mach-imx/devices.h index 000000000000,109f26cd3b1b..efd4527506a5 mode 000000,100644..100644 --- a/arch/arm/mach-imx/devices.h +++ b/arch/arm/mach-imx/devices.h @@@ -1,0 -1,30 +1,32 @@@ + #ifdef CONFIG_ARCH_MX1 + extern struct platform_device imx1_camera_device; + extern struct platform_device imx_rtc_device; + extern struct platform_device imx_wdt_device; + extern struct platform_device imx_usb_device; + #endif + + #if defined(CONFIG_MACH_MX21) || defined(CONFIG_MACH_MX27) + extern struct platform_device mxc_gpt1; + extern struct platform_device mxc_gpt2; + #ifdef CONFIG_MACH_MX27 + extern struct platform_device mxc_gpt3; + extern struct platform_device mxc_gpt4; + extern struct platform_device mxc_gpt5; + #endif + extern struct platform_device mxc_wdt; + extern struct platform_device mxc_w1_master_device; + extern struct platform_device mxc_fb_device; + extern struct platform_device mxc_fec_device; + extern struct platform_device mxc_pwm_device; + extern struct platform_device mxc_sdhc_device0; + extern struct platform_device mxc_sdhc_device1; + extern struct platform_device mxc_otg_udc_device; ++extern struct platform_device mx27_camera_device; + extern struct platform_device mxc_otg_host; + extern struct platform_device mxc_usbh1; + extern struct platform_device mxc_usbh2; + extern struct platform_device mx21_usbhc_device; + extern struct platform_device imx_ssi_device0; + extern struct platform_device imx_ssi_device1; ++extern struct platform_device imx_kpp_device; + #endif diff --cc arch/arm/mach-imx/eukrea_mbimx27-baseboard.c index 000000000000,1fb34f375b22..27e7226ec9d4 mode 000000,100644..100644 --- a/arch/arm/mach-imx/eukrea_mbimx27-baseboard.c +++ b/arch/arm/mach-imx/eukrea_mbimx27-baseboard.c @@@ -1,0 -1,244 +1,392 @@@ + /* - * Copyright (C) 2009 Eric Benard - eric@eukrea.com ++ * Copyright (C) 2009-2010 Eric Benard - eric@eukrea.com + * + * Based on pcm970-baseboard.c which is : + * Copyright (C) 2008 Juergen Beisert (kernel@pengutronix.de) + * + * 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 + #include + #include + #include + #include ++#include ++#include