diff options
Diffstat (limited to 'arch/arm/mach-mx27')
26 files changed, 8017 insertions, 0 deletions
diff --git a/arch/arm/mach-mx27/Kconfig b/arch/arm/mach-mx27/Kconfig new file mode 100644 index 000000000000..979c557085e6 --- /dev/null +++ b/arch/arm/mach-mx27/Kconfig @@ -0,0 +1,43 @@ +menu "MX27 Options" + depends on ARCH_MX27 + +config MX27_OPTIONS + bool + default y + select CPU_ARM926T + select MXC_EMMA + select USB_ARCH_HAS_EHCI + +config MACH_MX27ADS + bool "Support MX27ADS platforms" + default y + help + Include support for MX27ADS platform. This includes specific + configurations for the board and its peripherals. + +config ARCH_MXC_HAS_NFC_V1 + bool "MXC NFC Hardware Version 1" + default y + help + This selects the Freescale MXC Nand Flash Controller Hardware Version 1 + If unsure, say N. + +menu "Device options" + +config I2C_MXC_SELECT1 + bool "Enable I2C1 module" + default y + depends on I2C_MXC + help + Enable MX31 I2C1 module. + +config I2C_MXC_SELECT2 + bool "Enable I2C2 module" + default n + depends on I2C_MXC + help + Enable MX31 I2C2 module. + +endmenu + +endmenu diff --git a/arch/arm/mach-mx27/Makefile b/arch/arm/mach-mx27/Makefile new file mode 100644 index 000000000000..80a0ae7c4322 --- /dev/null +++ b/arch/arm/mach-mx27/Makefile @@ -0,0 +1,18 @@ +# +# Makefile for the linux kernel. +# + +# Object file lists. + +obj-y := mm.o dma.o gpio_mux.o clock.o devices.o serial.o system.o cpu.o dptc.o +obj-$(CONFIG_MACH_MX27ADS) += mx27ads.o mx27ads_gpio.o + +# power management +obj-$(CONFIG_PM) += pm.o mxc_pm.o + +obj-$(CONFIG_USB_EHCI_ARC_H1) += usb_h1.o +obj-$(CONFIG_USB_EHCI_ARC_H2) += usb_h2.o + +ifneq ($(strip $(CONFIG_USB_GADGET_ARC) $(CONFIG_USB_EHCI_ARC_OTG)),) + obj-y += usb_dr.o +endif diff --git a/arch/arm/mach-mx27/Makefile.boot b/arch/arm/mach-mx27/Makefile.boot new file mode 100644 index 000000000000..696831dcd485 --- /dev/null +++ b/arch/arm/mach-mx27/Makefile.boot @@ -0,0 +1,3 @@ + zreladdr-y := 0xA0008000 +params_phys-y := 0xA0000100 +initrd_phys-y := 0xA0800000 diff --git a/arch/arm/mach-mx27/board-mx27ads.h b/arch/arm/mach-mx27/board-mx27ads.h new file mode 100644 index 000000000000..fd152caef71b --- /dev/null +++ b/arch/arm/mach-mx27/board-mx27ads.h @@ -0,0 +1,385 @@ +/* + * Copyright 2005-2009 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 + */ + +#ifndef __ASM_ARCH_MXC_BOARD_MX27ADS_H__ +#define __ASM_ARCH_MXC_BOARD_MX27ADS_H__ + +/*! + * @defgroup BRDCFG_MX27 Board Configuration Options + * @ingroup MSL_MX27 + */ + +/*! + * @file mach-mx27/board-mx27ads.h + * + * @brief This file contains all the board level configuration options. + * + * It currently hold the options defined for MX27 ADS Platform. + * + * @ingroup BRDCFG_MX27 + */ + +/* + * Include Files + */ +#include <mach/mxc_uart.h> + +/*! + * @name MXC UART EVB board level configurations + */ +/*! @{ */ +/*! + * Specifies if the Irda transmit path is inverting + */ +#define MXC_IRDA_TX_INV 0 +/*! + * Specifies if the Irda receive path is inverting + */ +#define MXC_IRDA_RX_INV 0 +/* UART 1 configuration */ +/*! + * This define specifies if the UART port is configured to be in DTE or + * DCE mode. There exists a define like this for each UART port. Valid + * values that can be used are \b MODE_DTE or \b MODE_DCE. + */ +#define UART1_MODE MODE_DCE +/*! + * This define specifies if the UART is to be used for IRDA. There exists a + * define like this for each UART port. Valid values that can be used are + * \b IRDA or \b NO_IRDA. + */ +#define UART1_IR NO_IRDA +/*! + * This define is used to enable or disable a particular UART port. If + * disabled, the UART will not be registered in the file system and the user + * will not be able to access it. There exists a define like this for each UART + * port. Specify a value of 1 to enable the UART and 0 to disable it. + */ +#define UART1_ENABLED 1 +/*! @} */ +/* UART 2 configuration */ +#define UART2_MODE MODE_DCE +#define UART2_IR NO_IRDA +#define UART2_ENABLED 1 +/* UART 3 configuration */ +#define UART3_MODE MODE_DCE +#define UART3_IR IRDA +#define UART3_ENABLED 1 +/* UART 4 configuration */ +#define UART4_MODE MODE_DTE +#define UART4_IR NO_IRDA +#define UART4_ENABLED 0 /* Disable UART 4 as its pins are shared with ATA */ +/* UART 5 configuration */ +#define UART5_MODE MODE_DTE +#define UART5_IR NO_IRDA +#define UART5_ENABLED 1 +/* UART 6 configuration */ +#define UART6_MODE MODE_DTE +#define UART6_IR NO_IRDA +#define UART6_ENABLED 1 + +#define MXC_LL_EXTUART_PADDR (CS4_BASE_ADDR + 0x20000) +#define MXC_LL_EXTUART_VADDR (CS4_BASE_ADDR_VIRT + 0x20000) +#define MXC_LL_EXTUART_16BIT_BUS + +#define MXC_LL_UART_PADDR UART1_BASE_ADDR +#define MXC_LL_UART_VADDR AIPI_IO_ADDRESS(UART1_BASE_ADDR) + +/*! + * @name PBC Controller parameters + */ +/*! @{ */ +/*! + * Base address of PBC controller, CS4 + */ +#define PBC_BASE_ADDRESS IO_ADDRESS(CS4_BASE_ADDR) +#define PBC_REG_ADDR(offset) (PBC_BASE_ADDRESS + (offset)) + +/*! + * PBC Interupt name definitions + */ +#define PBC_GPIO1_0 0 +#define PBC_GPIO1_1 1 +#define PBC_GPIO1_2 2 +#define PBC_GPIO1_3 3 +#define PBC_GPIO1_4 4 +#define PBC_GPIO1_5 5 + +#define PBC_INTR_MAX_NUM 6 +#define PBC_INTR_SHARED_MAX_NUM 8 + +/* When the PBC address connection is fixed in h/w, defined as 1 */ +#define PBC_ADDR_SH 0 + +/* Offsets for the PBC Controller register */ +/*! + * PBC Board version register offset + */ +#define PBC_VERSION_REG PBC_REG_ADDR(0x00000 >> PBC_ADDR_SH) +/*! + * PBC Board control register 1 set address. + */ +#define PBC_BCTRL1_SET_REG PBC_REG_ADDR(0x00008 >> PBC_ADDR_SH) +/*! + * PBC Board control register 1 clear address. + */ +#define PBC_BCTRL1_CLEAR_REG PBC_REG_ADDR(0x0000C >> PBC_ADDR_SH) +/*! + * PBC Board control register 2 set address. + */ +#define PBC_BCTRL2_SET_REG PBC_REG_ADDR(0x00010 >> PBC_ADDR_SH) +/*! + * PBC Board control register 2 clear address. + */ +#define PBC_BCTRL2_CLEAR_REG PBC_REG_ADDR(0x00014 >> PBC_ADDR_SH) +/*! + * PBC Board control register 3 set address. + */ +#define PBC_BCTRL3_SET_REG PBC_REG_ADDR(0x00018 >> PBC_ADDR_SH) +/*! + * PBC Board control register 3 clear address. + */ +#define PBC_BCTRL3_CLEAR_REG PBC_REG_ADDR(0x0001C >> PBC_ADDR_SH) +/*! + * PBC Board control register 3 set address. + */ +#define PBC_BCTRL4_SET_REG PBC_REG_ADDR(0x00020 >> PBC_ADDR_SH) +/*! + * PBC Board control register 4 clear address. + */ +#define PBC_BCTRL4_CLEAR_REG PBC_REG_ADDR(0x00024 >> PBC_ADDR_SH) +/*!PBC_ADDR_SH + * PBC Board status register 1. + */ +#define PBC_BSTAT1_REG PBC_REG_ADDR(0x00028 >> PBC_ADDR_SH) +/*! + * PBC Board interrupt status register. + */ +#define PBC_INTSTATUS_REG PBC_REG_ADDR(0x0002C >> PBC_ADDR_SH) +/*! + * PBC Board interrupt current status register. + */ +#define PBC_INTCURR_STATUS_REG PBC_REG_ADDR(0x00034 >> PBC_ADDR_SH) +/*! + * PBC Interrupt mask register set address. + */ +#define PBC_INTMASK_SET_REG PBC_REG_ADDR(0x00038 >> PBC_ADDR_SH) +/*! + * PBC Interrupt mask register clear address. + */ +#define PBC_INTMASK_CLEAR_REG PBC_REG_ADDR(0x0003C >> PBC_ADDR_SH) +/*! + * External UART A. + */ +#define PBC_SC16C652_UARTA_REG PBC_REG_ADDR(0x20000 >> PBC_ADDR_SH) +/*! + * UART 4 Expanding Signal Status. + */ +#define PBC_UART_STATUS_REG PBC_REG_ADDR(0x22000 >> PBC_ADDR_SH) +/*! + * UART 4 Expanding Signal Control Set. + */ +#define PBC_UCTRL_SET_REG PBC_REG_ADDR(0x24000 >> PBC_ADDR_SH) +/*! + * UART 4 Expanding Signal Control Clear. + */ +#define PBC_UCTRL_CLR_REG PBC_REG_ADDR(0x26000 >> PBC_ADDR_SH) +/*! + * Ethernet Controller IO base address. + */ +#define PBC_CS8900A_IOBASE_REG PBC_REG_ADDR(0x40000 >> PBC_ADDR_SH) +/*! + * Ethernet Controller Memory base address. + */ +#define PBC_CS8900A_MEMBASE_REG PBC_REG_ADDR(0x42000 >> PBC_ADDR_SH) +/*! + * Ethernet Controller DMA base address. + */ +#define PBC_CS8900A_DMABASE_REG PBC_REG_ADDR(0x44000 >> PBC_ADDR_SH) + +/* PBC Board Version Register bit definition */ +#define PBC_VERSION_ADS 0x8000 /* Bit15=1 means version for ads */ +#define PBC_VERSION_EVB_REVB 0x4000 /* BIT14=1 means version for evb revb */ + +/* PBC Board Control Register 1 bit definitions */ +#define PBC_BCTRL1_ERST 0x0001 /* Ethernet Reset */ +#define PBC_BCTRL1_URST 0x0002 /* Reset External UART controller */ +#define PBC_BCTRL1_FRST 0x0004 /* FEC Reset */ +#define PBC_BCTRL1_ESLEEP 0x0010 /* Enable ethernet Sleep */ +#define PBC_BCTRL1_LCDON 0x0800 /* Enable the LCD */ + +/* PBC Board Control Register 2 bit definitions */ +#define PBC_BCTRL2_VCC_EN 0x0004 /* Enable VCC */ +#define PBC_BCTRL2_VPP_EN 0x0008 /* Enable Vpp */ +#define PBC_BCTRL2_ATAFEC_EN 0X0010 +#define PBC_BCTRL2_ATAFEC_SEL 0X0020 +#define PBC_BCTRL2_ATA_EN 0X0040 +#define PBC_BCTRL2_IRDA_SD 0X0080 +#define PBC_BCTRL2_IRDA_EN 0X0100 +#define PBC_BCTRL2_CCTL10 0X0200 +#define PBC_BCTRL2_CCTL11 0X0400 + +/* PBC Board Control Register 3 bit definitions */ +#define PBC_BCTRL3_HSH_EN 0X0020 +#define PBC_BCTRL3_FSH_MOD 0X0040 +#define PBC_BCTRL3_OTG_HS_EN 0X0080 +#define PBC_BCTRL3_OTG_VBUS_EN 0X0100 +#define PBC_BCTRL3_FSH_VBUS_EN 0X0200 +#define PBC_BCTRL3_USB_OTG_ON 0X0800 +#define PBC_BCTRL3_USB_FSH_ON 0X1000 + +/* PBC Board Control Register 4 bit definitions */ +#define PBC_BCTRL4_REGEN_SEL 0X0001 +#define PBC_BCTRL4_USER_OFF 0X0002 +#define PBC_BCTRL4_VIB_EN 0X0004 +#define PBC_BCTRL4_PWRGT1_EN 0X0008 +#define PBC_BCTRL4_PWRGT2_EN 0X0010 +#define PBC_BCTRL4_STDBY_PRI 0X0020 + +#ifndef __ASSEMBLY__ +/*! + * Enumerations for SD cards and memory stick card. This corresponds to + * the card EN bits in the IMR: SD1_EN | MS_EN | SD3_EN | SD2_EN. + */ +enum mxc_card_no { + MXC_CARD_SD2 = 0, + MXC_CARD_SD3, + MXC_CARD_MS, + MXC_CARD_SD1, + MXC_CARD_MIN = MXC_CARD_SD2, + MXC_CARD_MAX = MXC_CARD_SD1, +}; +#endif + +#define MXC_CPLD_VER_1_50 0x01 + +/*! + * PBC BSTAT Register bit definitions + */ +#define PBC_BSTAT_PRI_INT 0X0001 +#define PBC_BSTAT_USB_BYP 0X0002 +#define PBC_BSTAT_ATA_IOCS16 0X0004 +#define PBC_BSTAT_ATA_CBLID 0X0008 +#define PBC_BSTAT_ATA_DASP 0X0010 +#define PBC_BSTAT_PWR_RDY 0X0020 +#define PBC_BSTAT_SD3_WP 0X0100 +#define PBC_BSTAT_SD2_WP 0X0200 +#define PBC_BSTAT_SD1_WP 0X0400 +#define PBC_BSTAT_SD3_DET 0X0800 +#define PBC_BSTAT_SD2_DET 0X1000 +#define PBC_BSTAT_SD1_DET 0X2000 +#define PBC_BSTAT_MS_DET 0X4000 +#define PBC_BSTAT_SD3_DET_BIT 11 +#define PBC_BSTAT_SD2_DET_BIT 12 +#define PBC_BSTAT_SD1_DET_BIT 13 +#define PBC_BSTAT_MS_DET_BIT 14 +#define MXC_BSTAT_BIT(n) ((n == MXC_CARD_SD2) ? PBC_BSTAT_SD2_DET : \ + ((n == MXC_CARD_SD3) ? PBC_BSTAT_SD3_DET : \ + ((n == MXC_CARD_SD1) ? PBC_BSTAT_SD1_DET : \ + ((n == MXC_CARD_MS) ? PBC_BSTAT_MS_DET : 0x0)))) + +/*! + * PBC UART Control Register bit definitions + */ +#define PBC_UCTRL_DCE_DCD 0X0001 +#define PBC_UCTRL_DCE_DSR 0X0002 +#define PBC_UCTRL_DCE_RI 0X0004 +#define PBC_UCTRL_DTE_DTR 0X0100 + +/*! + * PBC UART Status Register bit definitions + */ +#define PBC_USTAT_DTE_DCD 0X0001 +#define PBC_USTAT_DTE_DSR 0X0002 +#define PBC_USTAT_DTE_RI 0X0004 +#define PBC_USTAT_DCE_DTR 0X0100 + +/*! + * PBC Interupt mask register bit definitions + */ +#define PBC_INTR_SD3_R_EN_BIT 4 +#define PBC_INTR_SD2_R_EN_BIT 0 +#define PBC_INTR_SD1_R_EN_BIT 6 +#define PBC_INTR_MS_R_EN_BIT 5 +#define PBC_INTR_SD3_EN_BIT 13 +#define PBC_INTR_SD2_EN_BIT 12 +#define PBC_INTR_MS_EN_BIT 14 +#define PBC_INTR_SD1_EN_BIT 15 + +#define PBC_INTR_SD2_R_EN 0x0001 +#define PBC_INTR_LOW_BAT 0X0002 +#define PBC_INTR_OTG_FSOVER 0X0004 +#define PBC_INTR_FSH_OVER 0X0008 +#define PBC_INTR_SD3_R_EN 0x0010 +#define PBC_INTR_MS_R_EN 0x0020 +#define PBC_INTR_SD1_R_EN 0x0040 +#define PBC_INTR_FEC_INT 0X0080 +#define PBC_INTR_ENET_INT 0X0100 +#define PBC_INTR_OTGFS_INT 0X0200 +#define PBC_INTR_XUART_INT 0X0400 +#define PBC_INTR_CCTL12 0X0800 +#define PBC_INTR_SD2_EN 0x1000 +#define PBC_INTR_SD3_EN 0x2000 +#define PBC_INTR_MS_EN 0x4000 +#define PBC_INTR_SD1_EN 0x8000 + +/*! @} */ + +#define CKIH_27MHZ_BIT_SET (1 << 3) + +/* For interrupts like xuart, enet etc */ +#define EXPIO_PARENT_INT IOMUX_TO_IRQ(MX27_PIN_TIN) + +/* + * This corresponds to PBC_INTMASK_SET_REG at offset 0x38. + * + */ +#define EXPIO_INT_LOW_BAT (MXC_EXP_IO_BASE + 1) +#define EXPIO_INT_OTG_FS_OVR (MXC_EXP_IO_BASE + 2) +#define EXPIO_INT_FSH_OVR (MXC_EXP_IO_BASE + 3) +#define EXPIO_INT_RES4 (MXC_EXP_IO_BASE + 4) +#define EXPIO_INT_RES5 (MXC_EXP_IO_BASE + 5) +#define EXPIO_INT_RES6 (MXC_EXP_IO_BASE + 6) +#define EXPIO_INT_FEC (MXC_EXP_IO_BASE + 7) +#define EXPIO_INT_ENET_INT (MXC_EXP_IO_BASE + 8) +#define EXPIO_INT_OTG_FS_INT (MXC_EXP_IO_BASE + 9) +#define EXPIO_INT_XUART_INTA (MXC_EXP_IO_BASE + 10) +#define EXPIO_INT_CCTL12_INT (MXC_EXP_IO_BASE + 11) +#define EXPIO_INT_SD2_EN (MXC_EXP_IO_BASE + 12) +#define EXPIO_INT_SD3_EN (MXC_EXP_IO_BASE + 13) +#define EXPIO_INT_MS_EN (MXC_EXP_IO_BASE + 14) +#define EXPIO_INT_SD1_EN (MXC_EXP_IO_BASE + 15) + +/*! This is System IRQ used by CS8900A for interrupt generation taken from platform.h */ +#define CS8900AIRQ EXPIO_INT_ENET_INT +/*! This is I/O Base address used to access registers of CS8900A on MXC ADS */ +#define CS8900A_BASE_ADDRESS (PBC_CS8900A_IOBASE_REG + 0x300) + +#define MXC_PMIC_INT_LINE IOMUX_TO_IRQ(MX27_PIN_TOUT) + +/*! +* This is used to detect if the CPLD version is for mx27 evb board rev-a +*/ +#define PBC_CPLD_VERSION_IS_REVA() \ + ((__raw_readw(PBC_VERSION_REG) & \ + (PBC_VERSION_ADS | PBC_VERSION_EVB_REVB))\ + == 0) + +#define MXC_BD_LED1 (1 << 5) +#define MXC_BD_LED2 (1 << 6) +#define MXC_BD_LED_ON(led) \ + __raw_writew(led, PBC_BCTRL1_SET_REG) +#define MXC_BD_LED_OFF(led) \ + __raw_writew(led, PBC_BCTRL1_CLEAR_REG) + +#endif /* __ASM_ARCH_MXC_BOARD_MX27ADS_H__ */ diff --git a/arch/arm/mach-mx27/clock.c b/arch/arm/mach-mx27/clock.c new file mode 100644 index 000000000000..49444a21902a --- /dev/null +++ b/arch/arm/mach-mx27/clock.c @@ -0,0 +1,1530 @@ +/* + * Copyright 2004-2009 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/module.h> +#include <linux/spinlock.h> +#include <linux/clk.h> +#include <linux/io.h> +#include <mach/clock.h> +#include "crm_regs.h" + +#define CKIH_CLK_FREQ 26000000 /* 26M reference clk */ +#define CKIH_CLK_FREQ_27MHZ 27000000 +#define CKIL_CLK_FREQ 32768 /* 32.768k oscillator in */ + +static struct clk ckil_clk; +static struct clk mpll_clk; +static struct clk mpll_main_clk[]; +static struct clk spll_clk; + +static int _clk_enable(struct clk *clk) +{ + unsigned long reg; + + reg = __raw_readl(clk->enable_reg); + reg |= 1 << clk->enable_shift; + __raw_writel(reg, clk->enable_reg); + + return 0; +} + +static void _clk_disable(struct clk *clk) +{ + unsigned long reg; + + 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) == 0) ; + + 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 void _clk_pccr01_enable(unsigned long mask0, unsigned long mask1) +{ + unsigned long reg; + + reg = __raw_readl(CCM_PCCR0); + reg |= mask0; + __raw_writel(reg, CCM_PCCR0); + + reg = __raw_readl(CCM_PCCR1); + reg |= mask1; + __raw_writel(reg, CCM_PCCR1); + +} + +static void _clk_pccr01_disable(unsigned long mask0, unsigned long mask1) +{ + unsigned long reg; + + reg = __raw_readl(CCM_PCCR0); + reg &= ~mask0; + __raw_writel(reg, CCM_PCCR0); + + reg = __raw_readl(CCM_PCCR1); + reg &= ~mask1; + __raw_writel(reg, CCM_PCCR1); +} + +static void _clk_pccr10_enable(unsigned long mask1, unsigned long mask0) +{ + unsigned long reg; + + reg = __raw_readl(CCM_PCCR1); + reg |= mask1; + __raw_writel(reg, CCM_PCCR1); + + reg = __raw_readl(CCM_PCCR0); + reg |= mask0; + __raw_writel(reg, CCM_PCCR0); +} + +static void _clk_pccr10_disable(unsigned long mask1, unsigned long mask0) +{ + unsigned long reg; + + reg = __raw_readl(CCM_PCCR1); + reg &= ~mask1; + __raw_writel(reg, CCM_PCCR1); + + reg = __raw_readl(CCM_PCCR0); + reg &= ~mask0; + __raw_writel(reg, CCM_PCCR0); +} + +static int _clk_dma_enable(struct clk *clk) +{ + _clk_pccr01_enable(CCM_PCCR0_DMA_MASK, CCM_PCCR1_HCLK_DMA_MASK); + + return 0; +} + +static void _clk_dma_disable(struct clk *clk) +{ + _clk_pccr01_disable(CCM_PCCR0_DMA_MASK, CCM_PCCR1_HCLK_DMA_MASK); +} + +static int _clk_rtic_enable(struct clk *clk) +{ + _clk_pccr01_enable(CCM_PCCR0_RTIC_MASK, CCM_PCCR1_HCLK_RTIC_MASK); + + return 0; +} + +static void _clk_rtic_disable(struct clk *clk) +{ + _clk_pccr01_disable(CCM_PCCR0_RTIC_MASK, CCM_PCCR1_HCLK_RTIC_MASK); +} + +static int _clk_emma_enable(struct clk *clk) +{ + _clk_pccr01_enable(CCM_PCCR0_EMMA_MASK, CCM_PCCR1_HCLK_EMMA_MASK); + + return 0; +} + +static void _clk_emma_disable(struct clk *clk) +{ + _clk_pccr01_disable(CCM_PCCR0_EMMA_MASK, CCM_PCCR1_HCLK_EMMA_MASK); +} + +static int _clk_slcdc_enable(struct clk *clk) +{ + _clk_pccr01_enable(CCM_PCCR0_SLCDC_MASK, CCM_PCCR1_HCLK_SLCDC_MASK); + + return 0; +} + +static void _clk_slcdc_disable(struct clk *clk) +{ + _clk_pccr01_disable(CCM_PCCR0_SLCDC_MASK, CCM_PCCR1_HCLK_SLCDC_MASK); +} + +static int _clk_fec_enable(struct clk *clk) +{ + _clk_pccr01_enable(CCM_PCCR0_FEC_MASK, CCM_PCCR1_HCLK_FEC_MASK); + + return 0; +} + +static void _clk_fec_disable(struct clk *clk) +{ + _clk_pccr01_disable(CCM_PCCR0_FEC_MASK, CCM_PCCR1_HCLK_FEC_MASK); +} + +static int _clk_vpu_enable(struct clk *clk) +{ + unsigned long reg; + + reg = __raw_readl(CCM_PCCR1); + reg |= CCM_PCCR1_VPU_BAUD_MASK | CCM_PCCR1_HCLK_VPU_MASK; + __raw_writel(reg, CCM_PCCR1); + + return 0; +} + +static void _clk_vpu_disable(struct clk *clk) +{ + unsigned long reg; + + reg = __raw_readl(CCM_PCCR1); + reg &= ~(CCM_PCCR1_VPU_BAUD_MASK | CCM_PCCR1_HCLK_VPU_MASK); + __raw_writel(reg, CCM_PCCR1); +} + +static int _clk_sahara2_enable(struct clk *clk) +{ + _clk_pccr01_enable(CCM_PCCR0_SAHARA_MASK, CCM_PCCR1_HCLK_SAHARA_MASK); + + return 0; +} + +static void _clk_sahara2_disable(struct clk *clk) +{ + _clk_pccr01_disable(CCM_PCCR0_SAHARA_MASK, CCM_PCCR1_HCLK_SAHARA_MASK); +} + +static int _clk_mstick1_enable(struct clk *clk) +{ + _clk_pccr10_enable(CCM_PCCR1_MSHC_BAUD_MASK, CCM_PCCR0_MSHC_MASK); + + return 0; +} + +static void _clk_mstick1_disable(struct clk *clk) +{ + _clk_pccr10_disable(CCM_PCCR1_MSHC_BAUD_MASK, CCM_PCCR0_MSHC_MASK); +} + +#define CSCR() (__raw_readl(CCM_CSCR)) +#define PCDR0() (__raw_readl(CCM_PCDR0)) +#define PCDR1() (__raw_readl(CCM_PCDR1)) + +static void _clk_pll_recalc(struct clk *clk) +{ + unsigned long mfi = 0, mfn = 0, mfd = 0, pdf = 0; + unsigned long ref_clk; + unsigned long reg; + unsigned long long temp; + + ref_clk = clk->parent->rate; + if (clk->parent == &ckil_clk) { + ref_clk *= 1024; + } + + if (clk == &mpll_clk) { + reg = __raw_readl(CCM_MPCTL0); + pdf = (reg & CCM_MPCTL0_PD_MASK) >> CCM_MPCTL0_PD_OFFSET; + mfd = (reg & CCM_MPCTL0_MFD_MASK) >> CCM_MPCTL0_MFD_OFFSET; + mfi = (reg & CCM_MPCTL0_MFI_MASK) >> CCM_MPCTL0_MFI_OFFSET; + mfn = (reg & CCM_MPCTL0_MFN_MASK) >> CCM_MPCTL0_MFN_OFFSET; + } else if (clk == &spll_clk) { + reg = __raw_readl(CCM_SPCTL0); + /*TODO: This is TO2 Bug */ + if (cpu_is_mx27_rev(CHIP_REV_2_0) == 1) { + __raw_writel(reg, CCM_SPCTL0); + } + pdf = (reg & CCM_SPCTL0_PD_MASK) >> CCM_SPCTL0_PD_OFFSET; + mfd = (reg & CCM_SPCTL0_MFD_MASK) >> CCM_SPCTL0_MFD_OFFSET; + mfi = (reg & CCM_SPCTL0_MFI_MASK) >> CCM_SPCTL0_MFI_OFFSET; + mfn = (reg & CCM_SPCTL0_MFN_MASK) >> CCM_SPCTL0_MFN_OFFSET; + } else { + BUG(); /* oops */ + } + + mfi = (mfi <= 5) ? 5 : mfi; + temp = 2LL * ref_clk * mfn; + do_div(temp, mfd + 1); + temp = 2LL * ref_clk * mfi + temp; + do_div(temp, pdf + 1); + + clk->rate = temp; +} + +static void _clk_mpll_main_recalc(struct clk *clk) +{ + /* i.MX27 TO2: + * clk->id == 0: arm clock source path 1 which is from 2*MPLL/DIV_2 + * clk->id == 1: arm clock source path 2 which is from 2*MPLL/DIV_3 + */ + switch (clk->id) { + case 0: + clk->rate = clk->parent->rate; + break; + case 1: + clk->rate = 2 * clk->parent->rate / 3; + } +} + +static int _clk_cpu_set_parent(struct clk *clk, struct clk *parent) +{ + int cscr = CSCR(); + + if (clk->parent == parent) + return 0; + + if (cpu_is_mx27_rev(CHIP_REV_2_0) > 0) { + if (parent == &mpll_main_clk[0]) { + cscr |= CCM_CSCR_ARM_SRC; + } else { + if (parent == &mpll_main_clk[1]) { + cscr &= ~CCM_CSCR_ARM_SRC; + } else { + return -EINVAL; + } + } + __raw_writel(cscr, CCM_CSCR); + } else { + return -ENODEV; + } + clk->parent = parent; + return 0; +} + +static unsigned long _clk_cpu_round_rate(struct clk *clk, unsigned long rate) +{ + int div; + div = clk->parent->rate / rate; + if (clk->parent->rate % rate) { + div++; + } + + if (div > 4) { + div = 4; + } + return clk->parent->rate / div; +} + +static int _clk_cpu_set_rate(struct clk *clk, unsigned long rate) +{ + int div, reg; + div = clk->parent->rate / rate; + + if (div > 4 || div < 1 || ((clk->parent->rate / div) != rate)) { + return -EINVAL; + } + div--; + + reg = (CSCR() & ~CCM_CSCR_ARM_MASK) | (div << CCM_CSCR_ARM_OFFSET); + __raw_writel(reg, CCM_CSCR); + clk->rate = rate; + return 0; +} + +static void _clk_cpu_recalc(struct clk *clk) +{ + unsigned long div; + + if (cpu_is_mx27_rev(CHIP_REV_2_0) > 0) { + div = (CSCR() & CCM_CSCR_ARM_MASK) >> CCM_CSCR_ARM_OFFSET; + } else { + div = (CSCR() & CCM_CSCR_PRESC_MASK) >> CCM_CSCR_PRESC_OFFSET; + } + + clk->rate = clk->parent->rate / (div + 1); +} + +static void _clk_ahb_recalc(struct clk *clk) +{ + unsigned long bclk_pdf; + + if (cpu_is_mx27_rev(CHIP_REV_2_0) > 0) { + bclk_pdf = (CSCR() & CCM_CSCR_AHB_MASK) >> CCM_CSCR_AHB_OFFSET; + } else { + bclk_pdf = + (CSCR() & CCM_CSCR_BCLK_MASK) >> CCM_CSCR_BCLK_OFFSET; + } + clk->rate = clk->parent->rate / (bclk_pdf + 1); +} + +static void _clk_perclkx_recalc(struct clk *clk) +{ + unsigned long perclk_pdf; + + if (clk->id < 0 || clk->id > 3) + return; + + perclk_pdf = (PCDR1() >> (clk->id << 3)) & CCM_PCDR1_PERDIV1_MASK; + + clk->rate = clk->parent->rate / (perclk_pdf + 1); +} + +static unsigned long _clk_perclkx_round_rate(struct clk *clk, + unsigned long rate) +{ + u32 div; + + div = clk->parent->rate / rate; + if (clk->parent->rate % rate) + div++; + + if (div > 64) { + div = 64; + } + + return clk->parent->rate / div; +} + +static int _clk_perclkx_set_rate(struct clk *clk, unsigned long rate) +{ + u32 reg; + u32 div; + + if (clk->id < 0 || clk->id > 3) + return -EINVAL; + + div = clk->parent->rate / rate; + if (div > 64 || div < 1 || ((clk->parent->rate / div) != rate)) { + return -EINVAL; + } + div--; + + reg = + __raw_readl(CCM_PCDR1) & ~(CCM_PCDR1_PERDIV1_MASK << + (clk->id << 3)); + reg |= div << (clk->id << 3); + __raw_writel(reg, CCM_PCDR1); + + clk->rate = rate; + + return 0; +} + +static void _clk_usb_recalc(struct clk *clk) +{ + unsigned long usb_pdf; + + usb_pdf = (CSCR() & CCM_CSCR_USB_MASK) >> CCM_CSCR_USB_OFFSET; + + clk->rate = clk->parent->rate / (usb_pdf + 1); +} + +static void _clk_ssi1_recalc(struct clk *clk) +{ + unsigned long ssi1_pdf; + + ssi1_pdf = (PCDR0() & CCM_PCDR0_SSI1BAUDDIV_MASK) >> + CCM_PCDR0_SSI1BAUDDIV_OFFSET; + + if (cpu_is_mx27_rev(CHIP_REV_2_0) > 0) { + ssi1_pdf += 4; + } else { + ssi1_pdf = (ssi1_pdf < 2) ? 124 : ssi1_pdf; + } + + clk->rate = 2 * clk->parent->rate / ssi1_pdf; +} + +static void _clk_ssi2_recalc(struct clk *clk) +{ + unsigned long ssi2_pdf; + + ssi2_pdf = (PCDR0() & CCM_PCDR0_SSI2BAUDDIV_MASK) >> + CCM_PCDR0_SSI2BAUDDIV_OFFSET; + + if (cpu_is_mx27_rev(CHIP_REV_2_0) > 0) { + ssi2_pdf += 4; + } else { + ssi2_pdf = (ssi2_pdf < 2) ? 124 : ssi2_pdf; + } + + clk->rate = 2 * clk->parent->rate / ssi2_pdf; +} + +static void _clk_nfc_recalc(struct clk *clk) +{ + unsigned long nfc_pdf; + + if (cpu_is_mx27_rev(CHIP_REV_2_0) > 0) { + nfc_pdf = + (PCDR0() & CCM_PCDR0_NFCDIV2_MASK) >> + CCM_PCDR0_NFCDIV2_OFFSET; + } else { + nfc_pdf = + (PCDR0() & CCM_PCDR0_NFCDIV_MASK) >> + CCM_PCDR0_NFCDIV_OFFSET; + } + + clk->rate = clk->parent->rate / (nfc_pdf + 1); +} + +static void _clk_vpu_recalc(struct clk *clk) +{ + unsigned long vpu_pdf; + + if (cpu_is_mx27_rev(CHIP_REV_2_0) > 0) { + vpu_pdf = + (PCDR0() & CCM_PCDR0_VPUDIV2_MASK) >> + CCM_PCDR0_VPUDIV2_OFFSET; + vpu_pdf += 4; + } else { + vpu_pdf = + (PCDR0() & CCM_PCDR0_VPUDIV_MASK) >> + CCM_PCDR0_VPUDIV_OFFSET; + vpu_pdf = (vpu_pdf < 2) ? 124 : vpu_pdf; + } + clk->rate = 2 * clk->parent->rate / vpu_pdf; +} + +static void _clk_ipg_recalc(struct clk *clk) +{ + unsigned long ipg_pdf; + + if (cpu_is_mx27_rev(CHIP_REV_2_0) > 0) { + ipg_pdf = 1; + } else { + ipg_pdf = (CSCR() & CCM_CSCR_IPDIV) >> CCM_CSCR_IPDIV_OFFSET; + } + + clk->rate = clk->parent->rate / (ipg_pdf + 1); +} + +static unsigned long _clk_parent_round_rate(struct clk *clk, unsigned long rate) +{ + return clk->parent->round_rate(clk->parent, rate); +} + +static int _clk_parent_set_rate(struct clk *clk, unsigned long rate) +{ + int ret; + if ((ret = clk->parent->set_rate(clk->parent, rate)) == 0) + clk->rate = rate; + return ret; +} + +static struct clk ckih_clk = { + .name = "ckih", + .rate = 0, /* determined at boot time (26 or 27 MHz) */ + .flags = RATE_PROPAGATES, +}; + +static struct clk ckil_clk = { + .name = "ckil", + .rate = CKIL_CLK_FREQ, + .flags = RATE_PROPAGATES, +}; + +static struct clk mpll_clk = { + .name = "mpll", + .parent = &ckih_clk, + .recalc = _clk_pll_recalc, + .flags = RATE_PROPAGATES, +}; + +static struct clk mpll_main_clk[] = { + { + /* For i.MX27 TO2, it is the MPLL path 1 of ARM core + * It provide the clock source whose rate is same as MPLL + */ + .name = "mpll_main", + .id = 0, + .parent = &mpll_clk, + .recalc = _clk_mpll_main_recalc,}, + { + /* For i.MX27 TO2, it is the MPLL path 1 of ARM core + * It provide the clock source whose rate is same as MPLL + */ + .name = "mpll_main", + .id = 1, + .parent = &mpll_clk, + .recalc = _clk_mpll_main_recalc,} +}; + +static struct clk spll_clk = { + .name = "spll", + .parent = &ckih_clk, + .recalc = _clk_pll_recalc, + .enable = _clk_spll_enable, + .disable = _clk_spll_disable, + .flags = RATE_PROPAGATES, +}; + +static struct clk cpu_clk = { + .name = "cpu_clk", + .parent = &mpll_main_clk[1], + .set_parent = _clk_cpu_set_parent, + .round_rate = _clk_cpu_round_rate, + .set_rate = _clk_cpu_set_rate, + .recalc = _clk_cpu_recalc, + .flags = RATE_PROPAGATES, +}; + +static struct clk ahb_clk = { + .name = "ahb_clk", + .parent = &mpll_main_clk[1], + .recalc = _clk_ahb_recalc, + .flags = RATE_PROPAGATES, +}; + +static struct clk ipg_clk = { + .name = "ipg_clk", + .parent = &ahb_clk, + .recalc = _clk_ipg_recalc, + .flags = RATE_PROPAGATES, +}; + +static struct clk per_clk[] = { + { + .name = "per_clk", + .id = 0, + .parent = &mpll_main_clk[1], + .recalc = _clk_perclkx_recalc, + .enable = _clk_enable, + .enable_reg = CCM_PCCR1, + .enable_shift = CCM_PCCR1_PERCLK1_OFFSET, + .disable = _clk_disable, + .flags = RATE_PROPAGATES,}, + { + .name = "per_clk", + .id = 1, + .parent = &mpll_main_clk[1], + .recalc = _clk_perclkx_recalc, + .enable = _clk_enable, + .enable_reg = CCM_PCCR1, + .enable_shift = CCM_PCCR1_PERCLK2_OFFSET, + .disable = _clk_disable, + .flags = RATE_PROPAGATES,}, + { + .name = "per_clk", + .id = 2, + .parent = &mpll_main_clk[1], + .round_rate = _clk_perclkx_round_rate, + .set_rate = _clk_perclkx_set_rate, + .recalc = _clk_perclkx_recalc, + .enable = _clk_enable, + .enable_reg = CCM_PCCR1, + .enable_shift = CCM_PCCR1_PERCLK3_OFFSET, + .disable = _clk_disable, + .flags = RATE_PROPAGATES,}, + { + .name = "per_clk", + .id = 3, + .parent = &mpll_main_clk[1], + .round_rate = _clk_perclkx_round_rate, + .set_rate = _clk_perclkx_set_rate, + .recalc = _clk_perclkx_recalc, + .enable = _clk_enable, + .enable_reg = CCM_PCCR1, + .enable_shift = CCM_PCCR1_PERCLK4_OFFSET, + .disable = _clk_disable, + .flags = RATE_PROPAGATES,}, +}; + +struct clk uart1_clk[] = { + { + .name = "uart_clk", + .id = 0, + .parent = &per_clk[0], + .secondary = &uart1_clk[1],}, + { + .name = "uart_ipg_clk", + .id = 0, + .parent = &ipg_clk, + .enable = _clk_enable, + .enable_reg = CCM_PCCR1, + .enable_shift = CCM_PCCR1_UART1_OFFSET, + .disable = _clk_disable,}, +}; + +struct clk uart2_clk[] = { + { + .name = "uart_clk", + .id = 1, + .parent = &per_clk[0], + .secondary = &uart2_clk[1],}, + { + .name = "uart_ipg_clk", + .id = 1, + .parent = &ipg_clk, + .enable = _clk_enable, + .enable_reg = CCM_PCCR1, + .enable_shift = CCM_PCCR1_UART2_OFFSET, + .disable = _clk_disable,}, +}; + +struct clk uart3_clk[] = { + { + .name = "uart_clk", + .id = 2, + .parent = &per_clk[0], + .secondary = &uart3_clk[1],}, + { + .name = "uart_ipg_clk", + .id = 2, + .parent = &ipg_clk, + .enable = _clk_enable, + .enable_reg = CCM_PCCR1, + .enable_shift = CCM_PCCR1_UART3_OFFSET, + .disable = _clk_disable,}, +}; + +struct clk uart4_clk[] = { + { + .name = "uart_clk", + .id = 3, + .parent = &per_clk[0], + .secondary = &uart4_clk[1],}, + { + .name = "uart_ipg_clk", + .id = 3, + .parent = &ipg_clk, + .enable = _clk_enable, + .enable_reg = CCM_PCCR1, + .enable_shift = CCM_PCCR1_UART4_OFFSET, + .disable = _clk_disable,}, +}; + +struct clk uart5_clk[] = { + { + .name = "uart_clk", + .id = 4, + .parent = &per_clk[0], + .secondary = &uart5_clk[1],}, + { + .name = "uart_ipg_clk", + .id = 4, + .parent = &ipg_clk, + .enable = _clk_enable, + .enable_reg = CCM_PCCR1, + .enable_shift = CCM_PCCR1_UART5_OFFSET, + .disable = _clk_disable,}, +}; + +struct clk uart6_clk[] = { + { + .name = "uart_clk", + .id = 5, + .parent = &per_clk[0], + .secondary = &uart6_clk[1],}, + { + .name = "uart_ipg_clk", + .id = 5, + .parent = &ipg_clk, + .enable = _clk_enable, + .enable_reg = CCM_PCCR1, + .enable_shift = CCM_PCCR1_UART6_OFFSET, + .disable = _clk_disable,}, +}; + +static struct clk gpt1_clk[] = { + { + .name = "gpt_clk", + .id = 0, + .parent = &per_clk[0], + .secondary = &gpt1_clk[1],}, + { + .name = "gpt_ipg_clk", + .id = 0, + .parent = &ipg_clk, + .enable = _clk_enable, + .enable_reg = CCM_PCCR0, + .enable_shift = CCM_PCCR0_GPT1_OFFSET, + .disable = _clk_disable,}, +}; + +static struct clk gpt2_clk[] = { + { + .name = "gpt_clk", + .id = 1, + .parent = &per_clk[0], + .secondary = &gpt2_clk[1],}, + { + .name = "gpt_ipg_clk", + .id = 1, + .parent = &ipg_clk, + .enable = _clk_enable, + .enable_reg = CCM_PCCR0, + .enable_shift = CCM_PCCR0_GPT2_OFFSET, + .disable = _clk_disable,}, +}; + +static struct clk gpt3_clk[] = { + { + .name = "gpt_clk", + .id = 2, + .parent = &per_clk[0], + .secondary = &gpt3_clk[1],}, + { + .name = "gpt_ipg_clk", + .id = 2, + .parent = &ipg_clk, + .enable = _clk_enable, + .enable_reg = CCM_PCCR0, + .enable_shift = CCM_PCCR0_GPT3_OFFSET, + .disable = _clk_disable,}, +}; + +static struct clk gpt4_clk[] = { + { + .name = "gpt_clk", + .id = 3, + .parent = &per_clk[0], + .secondary = &gpt4_clk[1],}, + { + .name = "gpt_ipg_clk", + .id = 3, + .parent = &ipg_clk, + .enable = _clk_enable, + .enable_reg = CCM_PCCR0, + .enable_shift = CCM_PCCR0_GPT4_OFFSET, + .disable = _clk_disable,}, +}; + +static struct clk gpt5_clk[] = { + { + .name = "gpt_clk", + .id = 4, + .parent = &per_clk[0], + .secondary = &gpt5_clk[1],}, + { + .name = "gpt_ipg_clk", + .id = 4, + .parent = &ipg_clk, + .enable = _clk_enable, + .enable_reg = CCM_PCCR0, + .enable_shift = CCM_PCCR0_GPT5_OFFSET, + .disable = _clk_disable,}, +}; + +static struct clk gpt6_clk[] = { + { + .name = "gpt_clk", + .id = 5, + .parent = &per_clk[0], + .secondary = &gpt6_clk[1],}, + { + .name = "gpt_ipg_clk", + .id = 5, + .parent = &ipg_clk, + .enable = _clk_enable, + .enable_reg = CCM_PCCR0, + .enable_shift = CCM_PCCR0_GPT6_OFFSET, + .disable = _clk_disable,}, +}; + +static struct clk pwm_clk[] = { + { + .name = "pwm_clk", + .parent = &per_clk[0], + .secondary = &pwm_clk[1],}, + { + .name = "pwm_clk", + .parent = &ipg_clk, + .enable = _clk_enable, + .enable_reg = CCM_PCCR0, + .enable_shift = CCM_PCCR0_PWM_OFFSET, + .disable = _clk_disable,}, +}; + +static struct clk sdhc1_clk[] = { + { + .name = "sdhc_clk", + .id = 0, + .parent = &per_clk[1], + .secondary = &sdhc1_clk[1],}, + { + .name = "sdhc_ipg_clk", + .id = 0, + .parent = &ipg_clk, + .enable = _clk_enable, + .enable_reg = CCM_PCCR0, + .enable_shift = CCM_PCCR0_SDHC1_OFFSET, + .disable = _clk_disable,}, +}; + +static struct clk sdhc2_clk[] = { + { + .name = "sdhc_clk", + .id = 1, + .parent = &per_clk[1], + .secondary = &sdhc2_clk[1],}, + { + .name = "sdhc_ipg_clk", + .id = 1, + .parent = &ipg_clk, + .enable = _clk_enable, + .enable_reg = CCM_PCCR0, + .enable_shift = CCM_PCCR0_SDHC2_OFFSET, + .disable = _clk_disable,}, +}; + +static struct clk sdhc3_clk[] = { + { + .name = "sdhc_clk", + .id = 2, + .parent = &per_clk[1], + .secondary = &sdhc3_clk[1],}, + { + .name = "sdhc_ipg_clk", + .id = 2, + .parent = &ipg_clk, + .enable = _clk_enable, + .enable_reg = CCM_PCCR0, + .enable_shift = CCM_PCCR0_SDHC3_OFFSET, + .disable = _clk_disable,}, +}; + +static struct clk cspi1_clk[] = { + { + .name = "cspi_clk", + .id = 0, + .parent = &per_clk[1], + .secondary = &cspi1_clk[1],}, + { + .name = "cspi_ipg_clk", + .id = 0, + .parent = &ipg_clk, + .enable = _clk_enable, + .enable_reg = CCM_PCCR0, + .enable_shift = CCM_PCCR0_CSPI1_OFFSET, + .disable = _clk_disable,}, +}; + +static struct clk cspi2_clk[] = { + { + .name = "cspi_clk", + .id = 1, + .parent = &per_clk[1], + .secondary = &cspi2_clk[1],}, + { + .name = "cspi_ipg_clk", + .id = 1, + .parent = &ipg_clk, + .enable = _clk_enable, + .enable_reg = CCM_PCCR0, + .enable_shift = CCM_PCCR0_CSPI2_OFFSET, + .disable = _clk_disable,}, +}; + +static struct clk cspi3_clk[] = { + { + .name = "cspi_clk", + .id = 2, + .parent = &per_clk[1], + .secondary = &cspi3_clk[1],}, + { + .name = "cspi_ipg_clk", + .id = 2, + .parent = &ipg_clk, + .enable = _clk_enable, + .enable_reg = CCM_PCCR0, + .enable_shift = CCM_PCCR0_CSPI3_OFFSET, + .disable = _clk_disable,}, +}; + +static struct clk lcdc_clk[] = { + { + .name = "lcdc_clk", + .parent = &per_clk[2], + .secondary = &lcdc_clk[1], + .round_rate = _clk_parent_round_rate, + .set_rate = _clk_parent_set_rate,}, + { + .name = "lcdc_ipg_clk", + .parent = &ipg_clk, + .secondary = &lcdc_clk[2], + .enable = _clk_enable, + .enable_reg = CCM_PCCR0, + .enable_shift = CCM_PCCR0_LCDC_OFFSET, + .disable = _clk_disable,}, + { + .name = "lcdc_ahb_clk", + .parent = &ahb_clk, + .enable = _clk_enable, + .enable_reg = CCM_PCCR1, + .enable_shift = CCM_PCCR1_HCLK_LCDC_OFFSET, + .disable = _clk_disable,}, +}; + +static struct clk csi_clk[] = { + { + .name = "csi_perclk", + .parent = &per_clk[3], + .secondary = &csi_clk[1], + .round_rate = _clk_parent_round_rate, + .set_rate = _clk_parent_set_rate,}, + { + .name = "csi_ahb_clk", + .parent = &ahb_clk, + .enable = _clk_enable, + .enable_reg = CCM_PCCR1, + .enable_shift = CCM_PCCR1_HCLK_CSI_OFFSET, + .disable = _clk_disable,}, +}; + +static struct clk usb_clk[] = { + { + .name = "usb_clk", + .parent = &spll_clk, + .recalc = _clk_usb_recalc, + .enable = _clk_enable, + .enable_reg = CCM_PCCR1, + .enable_shift = CCM_PCCR1_USBOTG_OFFSET, + .disable = _clk_disable,}, + { + .name = "usb_ahb_clk", + .parent = &ahb_clk, + .enable = _clk_enable, + .enable_reg = CCM_PCCR1, + .enable_shift = CCM_PCCR1_HCLK_USBOTG_OFFSET, + .disable = _clk_disable,} +}; + +static struct clk ssi1_clk[] = { + { + .name = "ssi_clk", + .id = 0, + .parent = &mpll_main_clk[1], + .secondary = &ssi1_clk[1], + .recalc = _clk_ssi1_recalc, + .enable = _clk_enable, + .enable_reg = CCM_PCCR1, + .enable_shift = CCM_PCCR1_SSI1_BAUD_OFFSET, + .disable = _clk_disable,}, + { + .name = "ssi_ipg_clk", + .id = 0, + .parent = &ipg_clk, + .enable = _clk_enable, + .enable_reg = CCM_PCCR0, + .enable_shift = CCM_PCCR0_SSI1_IPG_OFFSET, + .disable = _clk_disable,}, +}; + +static struct clk ssi2_clk[] = { + { + .name = "ssi_clk", + .id = 1, + .parent = &mpll_main_clk[1], + .secondary = &ssi2_clk[1], + .recalc = _clk_ssi2_recalc, + .enable = _clk_enable, + .enable_reg = CCM_PCCR1, + .enable_shift = CCM_PCCR1_SSI2_BAUD_OFFSET, + .disable = _clk_disable,}, + { + .name = "ssi_ipg_clk", + .id = 1, + .parent = &ipg_clk, + .enable = _clk_enable, + .enable_reg = CCM_PCCR0, + .enable_shift = CCM_PCCR0_SSI2_IPG_OFFSET, + .disable = _clk_disable,}, +}; + +static struct clk nfc_clk = { + .name = "nfc_clk", + .parent = &cpu_clk, + .recalc = _clk_nfc_recalc, + .enable = _clk_enable, + .enable_reg = CCM_PCCR1, + .enable_shift = CCM_PCCR1_NFC_BAUD_OFFSET, + .disable = _clk_disable, +}; + +static struct clk vpu_clk = { + .name = "vpu_clk", + .parent = &mpll_main_clk[1], + .recalc = _clk_vpu_recalc, + .enable = _clk_vpu_enable, + .disable = _clk_vpu_disable, +}; + +static struct clk dma_clk = { + .name = "dma_clk", + .parent = &ahb_clk, + .enable = _clk_dma_enable, + .disable = _clk_dma_disable, +}; + +static struct clk rtic_clk = { + .name = "rtic_clk", + .parent = &ahb_clk, + .enable = _clk_rtic_enable, + .disable = _clk_rtic_disable, +}; + +static struct clk brom_clk = { + .name = "brom_clk", + .parent = &ahb_clk, + .enable = _clk_enable, + .enable_reg = CCM_PCCR1, + .enable_shift = CCM_PCCR1_HCLK_BROM_OFFSET, + .disable = _clk_disable, +}; + +static struct clk emma_clk = { + .name = "emma_clk", + .parent = &ahb_clk, + .enable = _clk_emma_enable, + .disable = _clk_emma_disable, +}; + +static struct clk slcdc_clk = { + .name = "slcdc_clk", + .parent = &ahb_clk, + .enable = _clk_slcdc_enable, + .disable = _clk_slcdc_disable, +}; + +static struct clk fec_clk = { + .name = "fec_clk", + .parent = &ahb_clk, + .enable = _clk_fec_enable, + .disable = _clk_fec_disable, +}; + +static struct clk emi_clk = { + .name = "emi_clk", + .parent = &ahb_clk, + .enable = _clk_enable, + .enable_reg = CCM_PCCR1, + .enable_shift = CCM_PCCR1_HCLK_EMI_OFFSET, + .disable = _clk_disable, +}; + +static struct clk sahara2_clk = { + .name = "sahara_clk", + .parent = &ahb_clk, + .enable = _clk_sahara2_enable, + .disable = _clk_sahara2_disable, +}; + +static struct clk ata_clk = { + .name = "ata_clk", + .parent = &ahb_clk, + .enable = _clk_enable, + .enable_reg = CCM_PCCR1, + .enable_shift = CCM_PCCR1_HCLK_ATA_OFFSET, + .disable = _clk_disable, +}; + +static struct clk mstick1_clk = { + .name = "mstick1_clk", + .parent = &ipg_clk, + .enable = _clk_mstick1_enable, + .disable = _clk_mstick1_disable, +}; + +static struct clk wdog_clk = { + .name = "wdog_clk", + .parent = &ipg_clk, + .enable = _clk_enable, + .enable_reg = CCM_PCCR1, + .enable_shift = CCM_PCCR1_WDT_OFFSET, + .disable = _clk_disable, +}; + +static struct clk gpio_clk = { + .name = "gpio_clk", + .parent = &ipg_clk, + .enable = _clk_enable, + .enable_reg = CCM_PCCR1, + .enable_shift = CCM_PCCR0_GPIO_OFFSET, + .disable = _clk_disable, +}; + +static struct clk i2c_clk[] = { + { + .name = "i2c_clk", + .id = 0, + .parent = &ipg_clk, + .enable = _clk_enable, + .enable_reg = CCM_PCCR0, + .enable_shift = CCM_PCCR0_I2C1_OFFSET, + .disable = _clk_disable,}, + { + .name = "i2c_clk", + .id = 1, + .parent = &ipg_clk, + .enable = _clk_enable, + .enable_reg = CCM_PCCR0, + .enable_shift = CCM_PCCR0_I2C2_OFFSET, + .disable = _clk_disable,}, +}; + +static struct clk iim_clk = { + .name = "iim_clk", + .parent = &ipg_clk, + .enable = _clk_enable, + .enable_reg = CCM_PCCR0, + .enable_shift = CCM_PCCR0_IIM_OFFSET, + .disable = _clk_disable, +}; + +static struct clk kpp_clk = { + .name = "kpp_clk", + .parent = &ipg_clk, + .enable = _clk_enable, + .enable_reg = CCM_PCCR0, + .enable_shift = CCM_PCCR0_KPP_OFFSET, + .disable = _clk_disable, +}; + +static struct clk owire_clk = { + .name = "owire_clk", + .parent = &ipg_clk, + .enable = _clk_enable, + .enable_reg = CCM_PCCR0, + .enable_shift = CCM_PCCR0_OWIRE_OFFSET, + .disable = _clk_disable, +}; + +static struct clk rtc_clk = { + .name = "rtc_clk", + .parent = &ipg_clk, + .enable = _clk_enable, + .enable_reg = CCM_PCCR0, + .enable_shift = CCM_PCCR0_RTC_OFFSET, + .disable = _clk_disable, +}; + +static struct clk scc_clk = { + .name = "scc_clk", + .parent = &ipg_clk, + .enable = _clk_enable, + .enable_reg = CCM_PCCR0, + .enable_shift = CCM_PCCR0_SCC_OFFSET, + .disable = _clk_disable, +}; + +static unsigned long _clk_clko_round_rate(struct clk *clk, unsigned long rate) +{ + u32 div; + + div = clk->parent->rate / rate; + if (clk->parent->rate % rate) + div++; + + if (div > 8) { + div = 8; + } + + return clk->parent->rate / div; +} + +static int _clk_clko_set_rate(struct clk *clk, unsigned long rate) +{ + u32 reg; + u32 div; + + div = clk->parent->rate / rate; + + if (div > 8 || div < 1 || ((clk->parent->rate / div) != rate)) { + return -EINVAL; + } + div--; + + reg = __raw_readl(CCM_PCDR0) & ~CCM_PCDR0_CLKODIV_MASK; + reg |= div << CCM_PCDR0_CLKODIV_OFFSET; + __raw_writel(reg, CCM_PCDR0); + + clk->rate = rate; + + return 0; +} + +static void _clk_clko_recalc(struct clk *clk) +{ + u32 div; + + div = __raw_readl(CCM_PCDR0) & CCM_PCDR0_CLKODIV_MASK >> + CCM_PCDR0_CLKODIV_OFFSET; + div++; + + clk->rate = clk->parent->rate / div; +} + +static int _clk_clko_set_parent(struct clk *clk, struct clk *parent) +{ + u32 reg; + + reg = __raw_readl(CCM_CCSR) & ~CCM_CCSR_CLKOSEL_MASK; + + if (parent == &ckil_clk) { + reg |= 0 << CCM_CCSR_CLKOSEL_OFFSET; + } else if (parent == &ckih_clk) { + reg |= 2 << CCM_CCSR_CLKOSEL_OFFSET; + } else if (parent == mpll_clk.parent) { + reg |= 3 << CCM_CCSR_CLKOSEL_OFFSET; + } else if (parent == spll_clk.parent) { + reg |= 4 << CCM_CCSR_CLKOSEL_OFFSET; + } else if (parent == &mpll_clk) { + reg |= 5 << CCM_CCSR_CLKOSEL_OFFSET; + } else if (parent == &spll_clk) { + reg |= 6 << CCM_CCSR_CLKOSEL_OFFSET; + } else if (parent == &cpu_clk) { + reg |= 7 << CCM_CCSR_CLKOSEL_OFFSET; + } else if (parent == &ahb_clk) { + reg |= 8 << CCM_CCSR_CLKOSEL_OFFSET; + } else if (parent == &ipg_clk) { + reg |= 9 << CCM_CCSR_CLKOSEL_OFFSET; + } else if (parent == &per_clk[0]) { + reg |= 0xA << CCM_CCSR_CLKOSEL_OFFSET; + } else if (parent == &per_clk[1]) { + reg |= 0xB << CCM_CCSR_CLKOSEL_OFFSET; + } else if (parent == &per_clk[2]) { + reg |= 0xC << CCM_CCSR_CLKOSEL_OFFSET; + } else if (parent == &per_clk[3]) { + reg |= 0xD << CCM_CCSR_CLKOSEL_OFFSET; + } else if (parent == &ssi1_clk[0]) { + reg |= 0xE << CCM_CCSR_CLKOSEL_OFFSET; + } else if (parent == &ssi2_clk[0]) { + reg |= 0xF << CCM_CCSR_CLKOSEL_OFFSET; + } else if (parent == &nfc_clk) { + reg |= 0x10 << CCM_CCSR_CLKOSEL_OFFSET; + } else if (parent == &mstick1_clk) { + reg |= 0x11 << CCM_CCSR_CLKOSEL_OFFSET; + } else if (parent == &vpu_clk) { + reg |= 0x12 << CCM_CCSR_CLKOSEL_OFFSET; + } else if (parent == &usb_clk[0]) { + reg |= 0x15 << CCM_CCSR_CLKOSEL_OFFSET; + } else { + return -EINVAL; + } + + __raw_writel(reg, CCM_CCSR); + + return 0; +} + +static int _clk_clko_enable(struct clk *clk) +{ + u32 reg; + + reg = __raw_readl(CCM_PCDR0) | CCM_PCDR0_CLKO_EN; + __raw_writel(reg, CCM_PCDR0); + + return 0; +} + +static void _clk_clko_disable(struct clk *clk) +{ + u32 reg; + + reg = __raw_readl(CCM_PCDR0) & ~CCM_PCDR0_CLKO_EN; + __raw_writel(reg, CCM_PCDR0); +} + +static struct clk clko_clk = { + .name = "clko_clk", + .recalc = _clk_clko_recalc, + .set_rate = _clk_clko_set_rate, + .round_rate = _clk_clko_round_rate, + .set_parent = _clk_clko_set_parent, + .enable = _clk_clko_enable, + .disable = _clk_clko_disable, +}; + +static struct clk *mxc_clks[] = { + &ckih_clk, + &ckil_clk, + &mpll_clk, + &mpll_main_clk[0], + &mpll_main_clk[1], + &spll_clk, + &cpu_clk, + &ahb_clk, + &ipg_clk, + &per_clk[0], + &per_clk[1], + &per_clk[2], + &per_clk[3], + &clko_clk, + &uart1_clk[0], + &uart1_clk[1], + &uart2_clk[0], + &uart2_clk[1], + &uart3_clk[0], + &uart3_clk[1], + &uart4_clk[0], + &uart4_clk[1], + &uart5_clk[0], + &uart5_clk[1], + &uart6_clk[0], + &uart6_clk[1], + &gpt1_clk[0], + &gpt1_clk[1], + &gpt2_clk[0], + &gpt2_clk[1], + &gpt3_clk[0], + &gpt3_clk[1], + &gpt4_clk[0], + &gpt4_clk[1], + &gpt5_clk[0], + &gpt5_clk[1], + &gpt6_clk[0], + &gpt6_clk[1], + &pwm_clk[0], + &pwm_clk[1], + &sdhc1_clk[0], + &sdhc1_clk[1], + &sdhc2_clk[0], + &sdhc2_clk[1], + &sdhc3_clk[0], + &sdhc3_clk[1], + &cspi1_clk[0], + &cspi1_clk[1], + &cspi2_clk[0], + &cspi2_clk[1], + &cspi3_clk[0], + &cspi3_clk[1], + &lcdc_clk[0], + &lcdc_clk[1], + &lcdc_clk[2], + &csi_clk[0], + &csi_clk[1], + &usb_clk[0], + &usb_clk[1], + &ssi1_clk[0], + &ssi1_clk[1], + &ssi2_clk[0], + &ssi2_clk[1], + &nfc_clk, + &vpu_clk, + &dma_clk, + &rtic_clk, + &brom_clk, + &emma_clk, + &slcdc_clk, + &fec_clk, + &emi_clk, + &sahara2_clk, + &ata_clk, + &mstick1_clk, + &wdog_clk, + &gpio_clk, + &i2c_clk[0], + &i2c_clk[1], + &iim_clk, + &kpp_clk, + &owire_clk, + &rtc_clk, + &scc_clk, +}; + +static void probe_mxc_clocks(void) +{ + int i; + + if (cpu_is_mx27_rev(CHIP_REV_2_0) > 0) { + if (CSCR() & 0x8000) { + cpu_clk.parent = &mpll_main_clk[0]; + } + + if (!(CSCR() & 0x00800000)) { + ssi2_clk[0].parent = &spll_clk; + } + + if (!(CSCR() & 0x00400000)) { + ssi1_clk[0].parent = &spll_clk; + } + + if (!(CSCR() & 0x00200000)) { + 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; + + for (i = 0; i < sizeof(per_clk) / sizeof(per_clk[0]); i++) { + per_clk[i].parent = &mpll_clk; + } + + ssi1_clk[0].parent = &mpll_clk; + ssi2_clk[0].parent = &mpll_clk; + + vpu_clk.parent = &mpll_clk; + } +} + +extern void propagate_rate(struct clk *tclk); + +int __init mxc_clocks_init(unsigned long ckil, unsigned long osc, unsigned long ckih1, unsigned long ckih2) +{ + u32 cscr; + struct clk **clkp; + + /* Determine which high frequency clock source is coming in */ + ckih_clk.rate = ckih1; + + if (CSCR() & CCM_CSCR_MCU) { + mpll_clk.parent = &ckih_clk; + } else { + mpll_clk.parent = &ckil_clk; + } + + probe_mxc_clocks(); + + for (clkp = mxc_clks; clkp < mxc_clks + ARRAY_SIZE(mxc_clks); clkp++) { + if (*clkp == &mpll_main_clk[0] || *clkp == &mpll_main_clk[1]) { + if (cpu_is_mx27_rev(CHIP_REV_1_0) == 1) + continue; + } + clk_register(*clkp); + } + + /* Turn off all possible clocks */ + __raw_writel(CCM_PCCR0_GPT1_MASK, CCM_PCCR0); + __raw_writel(CCM_PCCR1_PERCLK1_MASK | CCM_PCCR1_HCLK_EMI_MASK, + CCM_PCCR1); + spll_clk.disable(&spll_clk); + + cscr = CSCR(); + if (cscr & CCM_CSCR_MCU) { + mpll_clk.parent = &ckih_clk; + } else { + mpll_clk.parent = &ckil_clk; + } + if (cscr & CCM_CSCR_SP) { + spll_clk.parent = &ckih_clk; + } else { + spll_clk.parent = &ckil_clk; + } + + pr_info("Clock input source is %ld\n", ckih_clk.rate); + + /* This will propagate to all children and init all the clock rates */ + propagate_rate(&ckih_clk); + propagate_rate(&ckil_clk); + + clk_enable(&emi_clk); + clk_enable(&gpio_clk); + clk_enable(&iim_clk); + clk_enable(&gpt1_clk[0]); + + return 0; +} diff --git a/arch/arm/mach-mx27/cpu.c b/arch/arm/mach-mx27/cpu.c new file mode 100644 index 000000000000..55d4a4c2d8e8 --- /dev/null +++ b/arch/arm/mach-mx27/cpu.c @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2001 Deep Blue Solutions Ltd. + * Copyright 2007-2009 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. + * + */ + +/*! + * @file mach-mx27/cpu.c + * + * @brief This file contains the CPU initialization code. + * + * @ingroup MSL_MX27 + */ + +#include <linux/types.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <mach/hardware.h> + +/*! + * CPU initialization. It is called by fixup_mxc_board() + */ +void __init mxc_cpu_init(void) +{ + if (!system_rev) { + mxc_set_system_rev(0x27, CHIP_REV_2_0); + } +} diff --git a/arch/arm/mach-mx27/crm_regs.h b/arch/arm/mach-mx27/crm_regs.h new file mode 100644 index 000000000000..3a0ab35d9be7 --- /dev/null +++ b/arch/arm/mach-mx27/crm_regs.h @@ -0,0 +1,284 @@ +/* + * Copyright 2004-2009 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 + */ + +#ifndef __ARCH_ARM_MACH_MX27_CRM_REGS_H__ +#define __ARCH_ARM_MACH_MX27_CRM_REGS_H__ + +#include <mach/hardware.h> + +#define SYSCTRL_BASE IO_ADDRESS(SYSCTRL_BASE_ADDR) +#define MXC_CCM_BASE ((char *)IO_ADDRESS(CCM_BASE_ADDR)) + +/* Register offsets */ +#define CCM_CSCR (MXC_CCM_BASE + 0x0) +#define CCM_MPCTL0 (MXC_CCM_BASE + 0x4) +#define CCM_MPCTL1 (MXC_CCM_BASE + 0x8) +#define CCM_SPCTL0 (MXC_CCM_BASE + 0xC) +#define CCM_SPCTL1 (MXC_CCM_BASE + 0x10) +#define CCM_OSC26MCTL (MXC_CCM_BASE + 0x14) +#define CCM_PCDR0 (MXC_CCM_BASE + 0x18) +#define CCM_PCDR1 (MXC_CCM_BASE + 0x1c) +#define CCM_PCCR0 (MXC_CCM_BASE + 0x20) +#define CCM_PCCR1 (MXC_CCM_BASE + 0x24) +#define CCM_CCSR (MXC_CCM_BASE + 0x28) +#define CCM_PMCTL (MXC_CCM_BASE + 0x2c) +#define CCM_PMCOUNT (MXC_CCM_BASE + 0x30) +#define CCM_WKGDCTL (MXC_CCM_BASE + 0x34) +#define MXC_CCM_PMCR0 (SYSCTRL_BASE + 0x60) +#define MXC_CCM_DCVR0 (SYSCTRL_BASE + 0x64) +#define MXC_CCM_DCVR1 (SYSCTRL_BASE + 0x68) +#define MXC_CCM_DCVR2 (SYSCTRL_BASE + 0x72) +#define MXC_CCM_DCVR3 (SYSCTRL_BASE + 0x76) +#define MXC_CCM_PMCR0_DPTEN 0x00000001 +#define MXC_CCM_DIE 0x00000002 +#define MXC_CCM_DIM 0x0000000C +#define MXC_CCM_DCR 0x00000200 +#define MXC_CCM_PMCR0_DRCE0 0x00000010 +#define MXC_CCM_PMCR0_DRCE1 0x00000020 +#define MXC_CCM_PMCR0_DRCE2 0x00000040 +#define MXC_CCM_PMCR0_DRCE3 0x00000080 +#define MXC_CCM_PMCR0_PTVAIM MXC_CCM_DIM + +#define CCM_CSCR_USB_OFFSET 28 +#define CCM_CSCR_USB_MASK (0x7 << 28) +#define CCM_CSCR_SD_OFFSET 24 +#define CCM_CSCR_SD_MASK (0x3 << 24) +#define CCM_CSCR_SSI2 (1 << 23) +#define CCM_CSCR_SSI2_OFFSET 23 +#define CCM_CSCR_SSI1 (1 << 22) +#define CCM_CSCR_SSI1_OFFSET 22 +#define CCM_CSCR_VPU (1 << 21) +#define CCM_CSCR_VPU_OFFSET 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) +/* CCM_CSCR_ARM_xxx just be avaliable on i.MX27 TO2*/ +#define CCM_CSCR_ARM_SRC (1 << 15) +#define CCM_CSCR_ARM_OFFSET 12 +#define CCM_CSCR_ARM_MASK (0x3 << 12) +/* CCM_CSCR_ARM_xxx just be avaliable on i.MX27 TO2*/ +#define CCM_CSCR_PRESC_OFFSET 13 +#define CCM_CSCR_PRESC_MASK (0x7 << 13) +#define CCM_CSCR_BCLK_OFFSET 9 +#define CCM_CSCR_BCLK_MASK (0xf << 9) +#define CCM_CSCR_IPDIV_OFFSET 8 +#define CCM_CSCR_IPDIV (1 << 8) +/* CCM_CSCR_AHB_xxx just be avaliable on i.MX27 TO2*/ +#define CCM_CSCR_AHB_OFFSET 8 +#define CCM_CSCR_AHB_MASK (0x3 << 8) +/* CCM_CSCR_AHB_xxx just be avaliable on i.MX27 TO2*/ +#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 + +#define CCM_MPCTL0_CPLM (1 << 31) +#define CCM_MPCTL0_PD_OFFSET 26 +#define CCM_MPCTL0_PD_MASK (0xf << 26) +#define CCM_MPCTL0_MFD_OFFSET 16 +#define CCM_MPCTL0_MFD_MASK (0x3ff << 16) +#define CCM_MPCTL0_MFI_OFFSET 10 +#define CCM_MPCTL0_MFI_MASK (0xf << 10) +#define CCM_MPCTL0_MFN_OFFSET 0 +#define CCM_MPCTL0_MFN_MASK 0x3ff + +#define CCM_MPCTL1_LF (1 << 15) +#define CCM_MPCTL1_BRMO (1 << 6) + +#define CCM_SPCTL0_CPLM (1 << 31) +#define CCM_SPCTL0_PD_OFFSET 26 +#define CCM_SPCTL0_PD_MASK (0xf << 26) +#define CCM_SPCTL0_MFD_OFFSET 16 +#define CCM_SPCTL0_MFD_MASK (0x3ff << 16) +#define CCM_SPCTL0_MFI_OFFSET 10 +#define CCM_SPCTL0_MFI_MASK (0xf << 10) +#define CCM_SPCTL0_MFN_OFFSET 0 +#define CCM_SPCTL0_MFN_MASK 0x3ff + +#define CCM_SPCTL1_LF (1 << 15) +#define CCM_SPCTL1_BRMO (1 << 6) + +#define CCM_OSC26MCTL_PEAK_OFFSET 16 +#define CCM_OSC26MCTL_PEAK_MASK (0x3 << 16) +#define CCM_OSC26MCTL_AGC_OFFSET 8 +#define CCM_OSC26MCTL_AGC_MASK (0x3f << 8) +#define CCM_OSC26MCTL_ANATEST_OFFSET 0 +#define CCM_OSC26MCTL_ANATEST_MASK 0x3f + +#define CCM_PCDR0_SSI2BAUDDIV_OFFSET 26 +#define CCM_PCDR0_SSI2BAUDDIV_MASK (0x3f << 26) +#define CCM_PCDR0_CLKO_EN 25 +#define CCM_PCDR0_CLKODIV_OFFSET 22 +#define CCM_PCDR0_CLKODIV_MASK (0x7 << 22) +#define CCM_PCDR0_SSI1BAUDDIV_OFFSET 16 +#define CCM_PCDR0_SSI1BAUDDIV_MASK (0x3f << 16) +/*The difinition for i.MX27 TO2*/ +#define CCM_PCDR0_VPUDIV2_OFFSET 10 +#define CCM_PCDR0_VPUDIV2_MASK (0x3f << 10) +#define CCM_PCDR0_NFCDIV2_OFFSET 6 +#define CCM_PCDR0_NFCDIV2_MASK (0xf << 6) +#define CCM_PCDR0_MSHCDIV2_MASK 0x3f +/*The difinition for i.MX27 TO2*/ +#define CCM_PCDR0_NFCDIV_OFFSET 12 +#define CCM_PCDR0_NFCDIV_MASK (0xf << 12) +#define CCM_PCDR0_VPUDIV_OFFSET 8 +#define CCM_PCDR0_VPUDIV_MASK (0xf << 8) +#define CCM_PCDR0_MSHCDIV_OFFSET 0 +#define CCM_PCDR0_MSHCDIV_MASK 0x1f + +#define CCM_PCDR1_PERDIV4_OFFSET 24 +#define CCM_PCDR1_PERDIV4_MASK (0x3f << 24) +#define CCM_PCDR1_PERDIV3_OFFSET 16 +#define CCM_PCDR1_PERDIV3_MASK (0x3f << 16) +#define CCM_PCDR1_PERDIV2_OFFSET 8 +#define CCM_PCDR1_PERDIV2_MASK (0x3f << 8) +#define CCM_PCDR1_PERDIV1_OFFSET 0 +#define CCM_PCDR1_PERDIV1_MASK 0x3f + +#define CCM_PCCR0_CSPI1_OFFSET 31 +#define CCM_PCCR0_CSPI1_MASK (1 << 31) +#define CCM_PCCR0_CSPI2_OFFSET 30 +#define CCM_PCCR0_CSPI2_MASK (1 << 30) +#define CCM_PCCR0_CSPI3_OFFSET 29 +#define CCM_PCCR0_CSPI3_MASK (1 << 29) +#define CCM_PCCR0_DMA_OFFSET 28 +#define CCM_PCCR0_DMA_MASK (1 << 28) +#define CCM_PCCR0_EMMA_OFFSET 27 +#define CCM_PCCR0_EMMA_MASK (1 << 27) +#define CCM_PCCR0_FEC_OFFSET 26 +#define CCM_PCCR0_FEC_MASK (1 << 26) +#define CCM_PCCR0_GPIO_OFFSET 25 +#define CCM_PCCR0_GPIO_MASK (1 << 25) +#define CCM_PCCR0_GPT1_OFFSET 24 +#define CCM_PCCR0_GPT1_MASK (1 << 24) +#define CCM_PCCR0_GPT2_OFFSET 23 +#define CCM_PCCR0_GPT2_MASK (1 << 23) +#define CCM_PCCR0_GPT3_OFFSET 22 +#define CCM_PCCR0_GPT3_MASK (1 << 22) +#define CCM_PCCR0_GPT4_OFFSET 21 +#define CCM_PCCR0_GPT4_MASK (1 << 21) +#define CCM_PCCR0_GPT5_OFFSET 20 +#define CCM_PCCR0_GPT5_MASK (1 << 20) +#define CCM_PCCR0_GPT6_OFFSET 19 +#define CCM_PCCR0_GPT6_MASK (1 << 19) +#define CCM_PCCR0_I2C1_OFFSET 18 +#define CCM_PCCR0_I2C1_MASK (1 << 18) +#define CCM_PCCR0_I2C2_OFFSET 17 +#define CCM_PCCR0_I2C2_MASK (1 << 17) +#define CCM_PCCR0_IIM_OFFSET 16 +#define CCM_PCCR0_IIM_MASK (1 << 16) +#define CCM_PCCR0_KPP_OFFSET 15 +#define CCM_PCCR0_KPP_MASK (1 << 15) +#define CCM_PCCR0_LCDC_OFFSET 14 +#define CCM_PCCR0_LCDC_MASK (1 << 14) +#define CCM_PCCR0_MSHC_OFFSET 13 +#define CCM_PCCR0_MSHC_MASK (1 << 13) +#define CCM_PCCR0_OWIRE_OFFSET 12 +#define CCM_PCCR0_OWIRE_MASK (1 << 12) +#define CCM_PCCR0_PWM_OFFSET 11 +#define CCM_PCCR0_PWM_MASK (1 << 11) +#define CCM_PCCR0_RTC_OFFSET 9 +#define CCM_PCCR0_RTC_MASK (1 << 9) +#define CCM_PCCR0_RTIC_OFFSET 8 +#define CCM_PCCR0_RTIC_MASK (1 << 8) +#define CCM_PCCR0_SAHARA_OFFSET 7 +#define CCM_PCCR0_SAHARA_MASK (1 << 7) +#define CCM_PCCR0_SCC_OFFSET 6 +#define CCM_PCCR0_SCC_MASK (1 << 6) +#define CCM_PCCR0_SDHC1_OFFSET 5 +#define CCM_PCCR0_SDHC1_MASK (1 << 5) +#define CCM_PCCR0_SDHC2_OFFSET 4 +#define CCM_PCCR0_SDHC2_MASK (1 << 4) +#define CCM_PCCR0_SDHC3_OFFSET 3 +#define CCM_PCCR0_SDHC3_MASK (1 << 3) +#define CCM_PCCR0_SLCDC_OFFSET 2 +#define CCM_PCCR0_SLCDC_MASK (1 << 2) +#define CCM_PCCR0_SSI1_IPG_OFFSET 1 +#define CCM_PCCR0_SSI1_IPG_MASK (1 << 1) +#define CCM_PCCR0_SSI2_IPG_OFFSET 0 +#define CCM_PCCR0_SSI2_IPG_MASK (1 << 0) + +#define CCM_PCCR1_UART1_OFFSET 31 +#define CCM_PCCR1_UART1_MASK (1 << 31) +#define CCM_PCCR1_UART2_OFFSET 30 +#define CCM_PCCR1_UART2_MASK (1 << 30) +#define CCM_PCCR1_UART3_OFFSET 29 +#define CCM_PCCR1_UART3_MASK (1 << 29) +#define CCM_PCCR1_UART4_OFFSET 28 +#define CCM_PCCR1_UART4_MASK (1 << 28) +#define CCM_PCCR1_UART5_OFFSET 27 +#define CCM_PCCR1_UART5_MASK (1 << 27) +#define CCM_PCCR1_UART6_OFFSET 26 +#define CCM_PCCR1_UART6_MASK (1 << 26) +#define CCM_PCCR1_USBOTG_OFFSET 25 +#define CCM_PCCR1_USBOTG_MASK (1 << 25) +#define CCM_PCCR1_WDT_OFFSET 24 +#define CCM_PCCR1_WDT_MASK (1 << 24) +#define CCM_PCCR1_HCLK_ATA_OFFSET 23 +#define CCM_PCCR1_HCLK_ATA_MASK (1 << 23) +#define CCM_PCCR1_HCLK_BROM_OFFSET 22 +#define CCM_PCCR1_HCLK_BROM_MASK (1 << 22) +#define CCM_PCCR1_HCLK_CSI_OFFSET 21 +#define CCM_PCCR1_HCLK_CSI_MASK (1 << 21) +#define CCM_PCCR1_HCLK_DMA_OFFSET 20 +#define CCM_PCCR1_HCLK_DMA_MASK (1 << 20) +#define CCM_PCCR1_HCLK_EMI_OFFSET 19 +#define CCM_PCCR1_HCLK_EMI_MASK (1 << 19) +#define CCM_PCCR1_HCLK_EMMA_OFFSET 18 +#define CCM_PCCR1_HCLK_EMMA_MASK (1 << 18) +#define CCM_PCCR1_HCLK_FEC_OFFSET 17 +#define CCM_PCCR1_HCLK_FEC_MASK (1 << 17) +#define CCM_PCCR1_HCLK_VPU_OFFSET 16 +#define CCM_PCCR1_HCLK_VPU_MASK (1 << 16) +#define CCM_PCCR1_HCLK_LCDC_OFFSET 15 +#define CCM_PCCR1_HCLK_LCDC_MASK (1 << 15) +#define CCM_PCCR1_HCLK_RTIC_OFFSET 14 +#define CCM_PCCR1_HCLK_RTIC_MASK (1 << 14) +#define CCM_PCCR1_HCLK_SAHARA_OFFSET 13 +#define CCM_PCCR1_HCLK_SAHARA_MASK (1 << 13) +#define CCM_PCCR1_HCLK_SLCDC_OFFSET 12 +#define CCM_PCCR1_HCLK_SLCDC_MASK (1 << 12) +#define CCM_PCCR1_HCLK_USBOTG_OFFSET 11 +#define CCM_PCCR1_HCLK_USBOTG_MASK (1 << 11) +#define CCM_PCCR1_PERCLK1_OFFSET 10 +#define CCM_PCCR1_PERCLK1_MASK (1 << 10) +#define CCM_PCCR1_PERCLK2_OFFSET 9 +#define CCM_PCCR1_PERCLK2_MASK (1 << 9) +#define CCM_PCCR1_PERCLK3_OFFSET 8 +#define CCM_PCCR1_PERCLK3_MASK (1 << 8) +#define CCM_PCCR1_PERCLK4_OFFSET 7 +#define CCM_PCCR1_PERCLK4_MASK (1 << 7) +#define CCM_PCCR1_VPU_BAUD_OFFSET 6 +#define CCM_PCCR1_VPU_BAUD_MASK (1 << 6) +#define CCM_PCCR1_SSI1_BAUD_OFFSET 5 +#define CCM_PCCR1_SSI1_BAUD_MASK (1 << 5) +#define CCM_PCCR1_SSI2_BAUD_OFFSET 4 +#define CCM_PCCR1_SSI2_BAUD_MASK (1 << 4) +#define CCM_PCCR1_NFC_BAUD_OFFSET 3 +#define CCM_PCCR1_NFC_BAUD_MASK (1 << 3) +#define CCM_PCCR1_MSHC_BAUD_OFFSET 2 +#define CCM_PCCR1_MSHC_BAUD_MASK (1 << 2) + +#define CCM_CCSR_32KSR (1 << 15) +#define CCM_CCSR_CLKMODE1 (1 << 9) +#define CCM_CCSR_CLKMODE0 (1 << 8) +#define CCM_CCSR_CLKOSEL_OFFSET 0 +#define CCM_CCSR_CLKOSEL_MASK 0x1f + +#define SYS_FMCR 0x14 /* Functional Muxing Control Reg */ +#define SYS_CHIP_ID 0x00 /* The offset of CHIP ID register */ + +#endif /* __ARCH_ARM_MACH_MX27_CRM_REGS_H__ */ diff --git a/arch/arm/mach-mx27/devices.c b/arch/arm/mach-mx27/devices.c new file mode 100644 index 000000000000..ad933d92d8d3 --- /dev/null +++ b/arch/arm/mach-mx27/devices.c @@ -0,0 +1,709 @@ +/* + * Author: MontaVista Software, Inc. + * <source@mvista.com> + * + * 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-2009 Freescale Semiconductor, Inc. All Rights Reserved. + */ +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/io.h> +#include <linux/platform_device.h> +#include <linux/clk.h> +#include <linux/pmic_external.h> + +#include <linux/spi/spi.h> + +#include <mach/gpio.h> +#include <mach/hardware.h> +#include <mach/mmc.h> +#include <mach/mxc_dptc.h> + + /*! + * @file mach-mx27/devices.c + * @brief device configurations including nor/nand/watchdog for mx27. + * + * @ingroup MSL_MX27 + */ + +#ifndef CONFIG_MX27_DPTC +extern struct dptc_wp dptc_wp_allfreq[DPTC_WP_SUPPORTED]; +#endif + +static void mxc_nop_release(struct device *dev) +{ + /* Nothing */ +} + +#if defined(CONFIG_W1_MASTER_MXC) || defined(CONFIG_W1_MASTER_MXC_MODULE) +static struct mxc_w1_config mxc_w1_data = { + .search_rom_accelerator = 0, +}; + +static struct platform_device mxc_w1_devices = { + .name = "mxc_w1", + .dev = { + .release = mxc_nop_release, + .platform_data = &mxc_w1_data, + }, + .id = 0 +}; + +static void mxc_init_owire(void) +{ + (void)platform_device_register(&mxc_w1_devices); +} +#else +static inline void mxc_init_owire(void) +{ +} +#endif + +#if defined(CONFIG_RTC_MXC) || defined(CONFIG_RTC_MXC_MODULE) +static struct resource rtc_resources[] = { + { + .start = RTC_BASE_ADDR, + .end = RTC_BASE_ADDR + 0x30, + .flags = IORESOURCE_MEM, + }, + { + .start = MXC_INT_RTC, + .flags = IORESOURCE_IRQ, + }, +}; +static struct platform_device mxc_rtc_device = { + .name = "mxc_rtc", + .id = 0, + .dev = { + .release = mxc_nop_release, + }, + .num_resources = ARRAY_SIZE(rtc_resources), + .resource = rtc_resources, +}; +static void mxc_init_rtc(void) +{ + (void)platform_device_register(&mxc_rtc_device); +} +#else +static inline void mxc_init_rtc(void) +{ +} +#endif +#if defined(CONFIG_MXC_WATCHDOG) || defined(CONFIG_MXC_WATCHDOG_MODULE) + +static struct resource wdt_resources[] = { + { + .start = WDOG1_BASE_ADDR, + .end = WDOG1_BASE_ADDR + 0x30, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device mxc_wdt_device = { + .name = "mxc_wdt", + .id = 0, + .dev = { + .release = mxc_nop_release, + }, + .num_resources = ARRAY_SIZE(wdt_resources), + .resource = wdt_resources, +}; + +static void mxc_init_wdt(void) +{ + (void)platform_device_register(&mxc_wdt_device); +} +#else +static inline void mxc_init_wdt(void) +{ +} +#endif +/*! + * This is platform device structure for adding SCC + */ +#if defined(CONFIG_MXC_SECURITY_SCC) || defined(CONFIG_MXC_SECURITY_SCC_MODULE) +static struct platform_device mxc_scc_device = { + .name = "mxc_scc", + .id = 0, +}; + +static void mxc_init_scc(void) +{ + platform_device_register(&mxc_scc_device); +} +#else +static inline void mxc_init_scc(void) +{ +} +#endif +/* MMC device data */ + +#if defined(CONFIG_MMC_MXC) || defined(CONFIG_MMC_MXC_MODULE) + +extern unsigned int sdhc_get_card_det_status(struct device *dev); +extern int sdhc_init_card_det(int id); + +static struct mxc_mmc_platform_data mmc_data = { + .ocr_mask = MMC_VDD_27_28 | MMC_VDD_28_29 | MMC_VDD_29_30, + .min_clk = 150000, + .max_clk = 25000000, + .card_inserted_state = 0, + .status = sdhc_get_card_det_status, +}; + +/*! + * Resource definition for the SDHC1 + */ +static struct resource mxcsdhc1_resources[] = { + [0] = { + .start = SDHC1_BASE_ADDR, + .end = SDHC1_BASE_ADDR + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = MXC_INT_SDHC1, + .end = MXC_INT_SDHC1, + .flags = IORESOURCE_IRQ, + }, + [2] = { + .start = 0, + .end = 0, + .flags = IORESOURCE_IRQ, + }, +}; + +/*! + * Resource definition for the SDHC2 + */ +static struct resource mxcsdhc2_resources[] = { + [0] = { + .start = SDHC2_BASE_ADDR, + .end = SDHC2_BASE_ADDR + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = MXC_INT_SDHC2, + .end = MXC_INT_SDHC2, + .flags = IORESOURCE_IRQ, + }, + [2] = { + .start = 0, + .end = 0, + .flags = IORESOURCE_IRQ, + }, +}; + +/*! Device Definition for MXC SDHC1 */ +static struct platform_device mxcsdhc1_device = { + .name = "mxcmci", + .id = 0, + .dev = { + .release = mxc_nop_release, + .platform_data = &mmc_data, + }, + .num_resources = ARRAY_SIZE(mxcsdhc1_resources), + .resource = mxcsdhc1_resources, +}; + +/*! Device Definition for MXC SDHC2 */ +static struct platform_device mxcsdhc2_device = { + .name = "mxcmci", + .id = 1, + .dev = { + .release = mxc_nop_release, + .platform_data = &mmc_data, + }, + .num_resources = ARRAY_SIZE(mxcsdhc2_resources), + .resource = mxcsdhc2_resources, +}; + +#ifdef CONFIG_MXC_SDHC3 +/*! + * Resource definition for the SDHC3 + */ +static struct resource mxcsdhc3_resources[] = { + [0] = { + .start = SDHC3_BASE_ADDR, + .end = SDHC3_BASE_ADDR + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = MXC_INT_SDHC3, + .end = MXC_INT_SDHC3, + .flags = IORESOURCE_IRQ, + }, + [2] = { + .start = 0, + .end = 0, + .flags = IORESOURCE_IRQ, + }, + [3] = { + .start = MXC_SDIO3_CARD_IRQ, + .end = MXC_SDIO3_CARD_IRQ, + .flags = IORESOURCE_IRQ, + }, +}; + +/*! Device Definition for MXC SDHC3 */ +static struct platform_device mxcsdhc3_device = { + .name = "mxcmci", + .id = 2, + .dev = { + .release = mxc_nop_release, + .platform_data = &mmc_data, + }, + .num_resources = ARRAY_SIZE(mxcsdhc3_resources), + .resource = mxcsdhc3_resources, +}; +#endif + +static inline void mxc_init_mmc(void) +{ + int cd_irq; + + cd_irq = sdhc_init_card_det(0); + if (cd_irq) { + mxcsdhc1_device.resource[2].start = cd_irq; + mxcsdhc1_device.resource[2].end = cd_irq; + } + cd_irq = sdhc_init_card_det(1); + if (cd_irq) { + mxcsdhc2_device.resource[2].start = cd_irq; + mxcsdhc2_device.resource[2].end = cd_irq; + } + + (void)platform_device_register(&mxcsdhc1_device); + (void)platform_device_register(&mxcsdhc2_device); +#ifdef CONFIG_MXC_SDHC3 + (void)platform_device_register(&mxcsdhc3_device); +#endif +} +#else +static inline void mxc_init_mmc(void) +{ +} +#endif + +/* SPI controller and device data */ +#if defined(CONFIG_SPI_MXC) || defined(CONFIG_SPI_MXC_MODULE) + +#ifdef CONFIG_SPI_MXC_SELECT1 +/*! + * Resource definition for the CSPI1 + */ +static struct resource mxcspi1_resources[] = { + [0] = { + .start = CSPI1_BASE_ADDR, + .end = CSPI1_BASE_ADDR + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = MXC_INT_CSPI1, + .end = MXC_INT_CSPI1, + .flags = IORESOURCE_IRQ, + }, +}; + +/*! Platform Data for MXC CSPI1 */ +static struct mxc_spi_master mxcspi1_data = { + .maxchipselect = 4, + .spi_version = 0, +}; + +/*! Device Definition for MXC CSPI1 */ +static struct platform_device mxcspi1_device = { + .name = "mxc_spi", + .id = 0, + .dev = { + .release = mxc_nop_release, + .platform_data = &mxcspi1_data, + }, + .num_resources = ARRAY_SIZE(mxcspi1_resources), + .resource = mxcspi1_resources, +}; + +#endif /* CONFIG_SPI_MXC_SELECT1 */ + +#ifdef CONFIG_SPI_MXC_SELECT2 +/*! + * Resource definition for the CSPI2 + */ +static struct resource mxcspi2_resources[] = { + [0] = { + .start = CSPI2_BASE_ADDR, + .end = CSPI2_BASE_ADDR + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = MXC_INT_CSPI2, + .end = MXC_INT_CSPI2, + .flags = IORESOURCE_IRQ, + }, +}; + +/*! Platform Data for MXC CSPI2 */ +static struct mxc_spi_master mxcspi2_data = { + .maxchipselect = 4, + .spi_version = 0, +}; + +/*! Device Definition for MXC CSPI2 */ +static struct platform_device mxcspi2_device = { + .name = "mxc_spi", + .id = 1, + .dev = { + .release = mxc_nop_release, + .platform_data = &mxcspi2_data, + }, + .num_resources = ARRAY_SIZE(mxcspi2_resources), + .resource = mxcspi2_resources, +}; +#endif /* CONFIG_SPI_MXC_SELECT2 */ + +#ifdef CONFIG_SPI_MXC_SELECT3 +/*! + * Resource definition for the CSPI3 + */ +static struct resource mxcspi3_resources[] = { + [0] = { + .start = CSPI3_BASE_ADDR, + .end = CSPI3_BASE_ADDR + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = MXC_INT_CSPI3, + .end = MXC_INT_CSPI3, + .flags = IORESOURCE_IRQ, + }, +}; + +/*! Platform Data for MXC CSPI3 */ +static struct mxc_spi_master mxcspi3_data = { + .maxchipselect = 4, + .spi_version = 0, +}; + +/*! Device Definition for MXC CSPI3 */ +static struct platform_device mxcspi3_device = { + .name = "mxc_spi", + .id = 2, + .dev = { + .release = mxc_nop_release, + .platform_data = &mxcspi3_data, + }, + .num_resources = ARRAY_SIZE(mxcspi3_resources), + .resource = mxcspi3_resources, +}; +#endif /* CONFIG_SPI_MXC_SELECT3 */ + +static inline void mxc_init_spi(void) +{ +#ifdef CONFIG_SPI_MXC_SELECT1 + if (platform_device_register(&mxcspi1_device) < 0) + printk(KERN_ERR "Registering the SPI Controller_1\n"); +#endif /* CONFIG_SPI_MXC_SELECT1 */ +#ifdef CONFIG_SPI_MXC_SELECT2 + if (platform_device_register(&mxcspi2_device) < 0) + printk(KERN_ERR "Registering the SPI Controller_2\n"); +#endif /* CONFIG_SPI_MXC_SELECT2 */ +#ifdef CONFIG_SPI_MXC_SELECT3 + if (platform_device_register(&mxcspi3_device) < 0) + printk(KERN_ERR "Registering the SPI Controller_3\n"); +#endif /* CONFIG_SPI_MXC_SELECT3 */ +} +#else +static inline void mxc_init_spi(void) +{ +} +#endif + +#if defined(CONFIG_SND_MXC_PMIC) || defined(CONFIG_SND_MXC_PMIC_MODULE) +static struct mxc_audio_platform_data mxc_audio_data; + +static struct platform_device mxc_alsa_device = { + .name = "mxc_alsa", + .id = 0, + .dev = { + .release = mxc_nop_release, + .platform_data = &mxc_audio_data, + }, + +}; + +static void mxc_init_audio(void) +{ + mxc_audio_data.ssi_clk[0] = clk_get(NULL, "ssi_clk.0"); + clk_put(mxc_audio_data.ssi_clk[0]); + mxc_audio_data.ssi_clk[1] = clk_get(NULL, "ssi_clk.1"); + clk_put(mxc_audio_data.ssi_clk[1]); + mxc_audio_data.ssi_num = 2; + mxc_audio_data.src_port = 0; + platform_device_register(&mxc_alsa_device); +} +#else + +static void mxc_init_audio(void) +{ +} +#endif + +#if defined(CONFIG_MXC_SSI) || defined(CONFIG_MXC_SSI_MODULE) +/*! + * Resource definition for the SSI + */ +static struct resource mxcssi2_resources[] = { + [0] = { + .start = SSI2_BASE_ADDR, + .end = SSI2_BASE_ADDR + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, +}; + +static struct resource mxcssi1_resources[] = { + [0] = { + .start = SSI1_BASE_ADDR, + .end = SSI1_BASE_ADDR + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, +}; + +/*! Device Definition for MXC SSI */ +static struct platform_device mxc_ssi1_device = { + .name = "mxc_ssi", + .id = 0, + .dev = { + .release = mxc_nop_release, + .platform_data = &mxc_audio_data, + }, + .num_resources = ARRAY_SIZE(mxcssi1_resources), + .resource = mxcssi1_resources, +}; + +static struct platform_device mxc_ssi2_device = { + .name = "mxc_ssi", + .id = 1, + .dev = { + .release = mxc_nop_release, + .platform_data = &mxc_audio_data, + }, + .num_resources = ARRAY_SIZE(mxcssi2_resources), + .resource = mxcssi2_resources, +}; + +static void mxc_init_ssi(void) +{ + platform_device_register(&mxc_ssi1_device); + platform_device_register(&mxc_ssi2_device); +} +#else + +static void mxc_init_ssi(void) +{ +} +#endif + +/* I2C controller and device data */ +#if defined(CONFIG_I2C_MXC) || defined(CONFIG_I2C_MXC_MODULE) + +#ifdef CONFIG_I2C_MXC_SELECT1 +/*! + * Resource definition for the I2C1 + */ +static struct resource mxci2c1_resources[] = { + [0] = { + .start = I2C_BASE_ADDR, + .end = I2C_BASE_ADDR + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = MXC_INT_I2C, + .end = MXC_INT_I2C, + .flags = IORESOURCE_IRQ, + }, +}; + +/*! Platform Data for MXC I2C */ +static struct mxc_i2c_platform_data mxci2c1_data = { + .i2c_clk = 100000, +}; +#endif + +#ifdef CONFIG_I2C_MXC_SELECT2 +/*! + * Resource definition for the I2C2 + */ +static struct resource mxci2c2_resources[] = { + [0] = { + .start = I2C2_BASE_ADDR, + .end = I2C2_BASE_ADDR + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = MXC_INT_I2C2, + .end = MXC_INT_I2C2, + .flags = IORESOURCE_IRQ, + }, +}; + +/*! Platform Data for MXC I2C */ +static struct mxc_i2c_platform_data mxci2c2_data = { + .i2c_clk = 100000, +}; +#endif + +/*! Device Definition for MXC I2C */ +static struct platform_device mxci2c_devices[] = { +#ifdef CONFIG_I2C_MXC_SELECT1 + { + .name = "mxc_i2c", + .id = 0, + .dev = { + .release = mxc_nop_release, + .platform_data = &mxci2c1_data, + }, + .num_resources = ARRAY_SIZE(mxci2c1_resources), + .resource = mxci2c1_resources,}, +#endif +#ifdef CONFIG_I2C_MXC_SELECT2 + { + .name = "mxc_i2c", + .id = 1, + .dev = { + .release = mxc_nop_release, + .platform_data = &mxci2c2_data, + }, + .num_resources = ARRAY_SIZE(mxci2c2_resources), + .resource = mxci2c2_resources,}, +#endif +}; + +static inline void mxc_init_i2c(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(mxci2c_devices); i++) { + if (platform_device_register(&mxci2c_devices[i]) < 0) + dev_err(&mxci2c_devices[i].dev, + "Unable to register I2C device\n"); + } +} +#else +static inline void mxc_init_i2c(void) +{ +} +#endif + +#ifdef CONFIG_MXC_VPU +/*! Platform Data for MXC VPU */ +static struct platform_device mxcvpu_device = { + .name = "mxc_vpu", + .dev = { + .release = mxc_nop_release, + }, + .id = 0, +}; + +static inline void mxc_init_vpu(void) +{ + if (platform_device_register(&mxcvpu_device) < 0) + printk(KERN_ERR "Error: Registering the VPU.\n"); +} +#else +static inline void mxc_init_vpu(void) +{ +} +#endif + +struct mxc_gpio_port mxc_gpio_ports[GPIO_PORT_NUM] = { + [0] = { + .chip.label = "gpio-0", + .base = IO_ADDRESS(GPIO_BASE_ADDR), + .irq = MXC_INT_GPIO, + .irq_high = 0, + .virtual_irq_start = MXC_GPIO_INT_BASE + }, + [1] = { + .chip.label = "gpio-1", + .base = IO_ADDRESS(GPIO_BASE_ADDR) + 0x100, + .irq = MXC_INT_GPIO, + .irq_high = 0, + .virtual_irq_start = MXC_GPIO_INT_BASE + GPIO_NUM_PIN + }, + [2] = { + .chip.label = "gpio-2", + .base = IO_ADDRESS(GPIO_BASE_ADDR) + 0x200, + .irq = MXC_INT_GPIO, + .irq_high = 0, + .virtual_irq_start = MXC_GPIO_INT_BASE + GPIO_NUM_PIN * 2 + }, + [3] = { + .chip.label = "gpio-3", + .base = IO_ADDRESS(GPIO_BASE_ADDR) + 0x300, + .irq = MXC_INT_GPIO, + .irq_high = 0, + .virtual_irq_start = MXC_GPIO_INT_BASE + GPIO_NUM_PIN * 3 + }, + [4] = { + .chip.label = "gpio-4", + .base = IO_ADDRESS(GPIO_BASE_ADDR) + 0x400, + .irq = MXC_INT_GPIO, + .irq_high = 0, + .virtual_irq_start = MXC_GPIO_INT_BASE + GPIO_NUM_PIN * 4 + }, + [5] = { + .chip.label = "gpio-5", + .base = IO_ADDRESS(GPIO_BASE_ADDR) + 0x500, + .irq = MXC_INT_GPIO, + .irq_high = 0, + .virtual_irq_start = MXC_GPIO_INT_BASE + GPIO_NUM_PIN * 5 + } +}; + +int __init mxc_register_gpios(void) +{ + return mxc_gpio_init(mxc_gpio_ports, ARRAY_SIZE(mxc_gpio_ports)); +} + +#ifndef CONFIG_MX27_DPTC +/*! Device Definition for DPTC */ +static struct platform_device mxc_dptc_device = { + .name = "mxc_dptc", + .dev = { + .release = mxc_nop_release, + .platform_data = &dptc_wp_allfreq, + }, +}; + +static inline void mxc_init_dptc(void) +{ + (void)platform_device_register(&mxc_dptc_device); +} +#endif + +static int __init mxc_init_devices(void) +{ + mxc_init_wdt(); + mxc_init_mmc(); + mxc_init_spi(); + mxc_init_i2c(); + mxc_init_rtc(); + mxc_init_ssi(); + mxc_init_audio(); + mxc_init_scc(); + mxc_init_owire(); + mxc_init_vpu(); +#ifndef CONFIG_MX27_DPTC + mxc_init_dptc(); +#endif + + return 0; +} + +arch_initcall(mxc_init_devices); diff --git a/arch/arm/mach-mx27/dma.c b/arch/arm/mach-mx27/dma.c new file mode 100644 index 000000000000..a48e070a6a44 --- /dev/null +++ b/arch/arm/mach-mx27/dma.c @@ -0,0 +1,553 @@ +/* + * Copyright 2004-2007 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 + */ + +/*! + *@file mach-mx27/dma.c + *@brief This file contains the dma parameter which is depend on the platform . + * @ingroup DMA_MX27 + */ + +#include <linux/module.h> +#include <linux/init.h> +#include <asm/dma.h> + +#define MXC_SOUND_PLAYBACK_CHAIN_DMA 1 +#define MXC_SOUND_CAPTURE_CHAIN_DMA 1 + +/*! + * @brief the structure stored device_id and dma_info pointer + */ +typedef struct dma_info_entry_s { + mxc_dma_device_t device; + /* if there are two dma_info , first is for reading, another is for writing */ + mx2_dma_info_t *info; +} dma_info_entry_t; + +/*! + * @brief dma_info from memory to memory for dma testing + */ +static mx2_dma_info_t ram2ram_dma_info = { + .dma_chan = MXC_DMA_DYNAMIC_CHANNEL, + .mode = 0, + .rto_en = 0, + .dir = 0, + .dma_chaining = 0,.ren = 0, + .burstLength = 4,.request = 0,.busuntils = 0, + .sourceType = DMA_TYPE_LINEAR,.sourcePort = TRANSFER_32BIT, + .destType = DMA_TYPE_LINEAR,.destPort = TRANSFER_32BIT, + .M2D_Valid = 0 +}; + +/*! + * @brief dma_info from 2D memory to 2D memory for dma testing + */ +static mx2_dma_info_t ram2d2ram2d_dma_info = { + .dma_chan = MXC_DMA_DYNAMIC_CHANNEL, + .mode = 0, + .rto_en = 0, + .dir = 0, + .rto_en = 0, + .dma_chaining = 0,.ren = 0, + .burstLength = 4,.request = 0,.busuntils = 0, + .sourceType = DMA_TYPE_2D,.sourcePort = TRANSFER_32BIT, + .destType = DMA_TYPE_2D,.destPort = TRANSFER_32BIT, + .M2D_Valid = 1,.msel = 0,.W = 0x80,.X = 0x40,.Y = 0x10 +}; + +/*! + * @brief dma_info from memory to 2D memory for dma testing + */ +static mx2_dma_info_t ram2ram2d_dma_info = { + .dma_chan = MXC_DMA_DYNAMIC_CHANNEL, + .mode = 0, + .rto_en = 0, + .dir = 0, + .dma_chaining = 0,.ren = 0, + .burstLength = 4,.request = 0,.busuntils = 0, + .sourceType = DMA_TYPE_LINEAR,.sourcePort = TRANSFER_32BIT, + .destType = DMA_TYPE_2D,.destPort = TRANSFER_32BIT, + .M2D_Valid = 1,.msel = 0,.W = 0x100,.X = 0x80,.Y = 0x10 +}; + +/*! + * @brief dma_info from 2D memory to memory for dma testing + */ +static mx2_dma_info_t ram2d2ram_dma_info = { + .dma_chan = MXC_DMA_DYNAMIC_CHANNEL, + .mode = 0, + .rto_en = 0, + .dir = 0, + .dma_chaining = 0,.ren = 0, + .burstLength = 4,.request = 0,.busuntils = 0, + .sourceType = DMA_TYPE_2D,.sourcePort = TRANSFER_32BIT, + .destType = DMA_TYPE_LINEAR,.destPort = TRANSFER_32BIT, + .M2D_Valid = 1,.msel = 0,.W = 0x100,.X = 0x100,.Y = 0x10 +}; + +/*! + * @brief dma_info with dma chaining feature for dma testing + */ +static mx2_dma_info_t hw_chaining_dma_info = { + .dma_chan = MXC_DMA_DYNAMIC_CHANNEL, + .mode = 0, + .rto_en = 0, + .dir = 0, + .dma_chaining = 1,.ren = 0, + .burstLength = 4,.request = 0,.busuntils = 0, + .sourceType = DMA_TYPE_LINEAR,.sourcePort = TRANSFER_32BIT, + .destType = DMA_TYPE_LINEAR,.destPort = TRANSFER_32BIT, + .M2D_Valid = 0, +}; + +/*! + * @brief dma_info without dma chaining feature for dma testing + */ +static mx2_dma_info_t sw_chaining_dma_info = { + .dma_chan = MXC_DMA_DYNAMIC_CHANNEL, + .mode = 0, + .rto_en = 0, + .dir = 0, + .dma_chaining = 0,.ren = 0, + .burstLength = 4,.request = 0,.busuntils = 0, + .sourceType = DMA_TYPE_LINEAR,.sourcePort = TRANSFER_32BIT, + .destType = DMA_TYPE_LINEAR,.destPort = TRANSFER_32BIT, + .M2D_Valid = 0, +}; + +/*! + * @brief dma_info for ATA recieveing + */ +static mx2_dma_info_t ata_rx_dma_info = { + .dma_chan = MXC_DMA_DYNAMIC_CHANNEL, + .mode = 0, + .rto_en = 0, + .dir = 0, + .dma_chaining = 0,.ren = 1, + .burstLength = 32,.request = 29,.busuntils = 0, + .sourceType = DMA_TYPE_FIFO,.sourcePort = TRANSFER_32BIT, + .destType = DMA_TYPE_LINEAR,.destPort = TRANSFER_32BIT, + .per_address = (ATA_BASE_ADDR + 0x18), + .M2D_Valid = 0, +}; + +/*! + * @brief: dma_info for ATA transmitting + */ +static mx2_dma_info_t ata_tx_dma_info = { + .dma_chan = MXC_DMA_DYNAMIC_CHANNEL, + .mode = 1, + .rto_en = 0, + .dir = 0, + .dma_chaining = 0,.ren = 1, + .burstLength = 32,.request = 28,.busuntils = 0, + .sourceType = DMA_TYPE_FIFO,.sourcePort = TRANSFER_32BIT, + .destType = DMA_TYPE_LINEAR,.destPort = TRANSFER_32BIT, + .per_address = (ATA_BASE_ADDR + 0x18), + .M2D_Valid = 0, +}; + +/*! + * @brief dma_info for UART1 recieveing + */ +static mx2_dma_info_t uart1_rx_dma_info = { + .dma_chan = MXC_DMA_DYNAMIC_CHANNEL, + .mode = 0, + .rto_en = 1, + .dir = 0, + .dma_chaining = 0,.ren = 1, + .burstLength = 1,.request = 26,.busuntils = 8, + .sourceType = DMA_TYPE_FIFO,.sourcePort = TRANSFER_8BIT, + .destType = DMA_TYPE_LINEAR,.destPort = TRANSFER_8BIT, + .per_address = (UART1_BASE_ADDR), + .M2D_Valid = 0, +}; + +/*! + * @brief: dma_info for UART1 transmitting + */ +static mx2_dma_info_t uart1_tx_dma_info = { + .dma_chan = MXC_DMA_DYNAMIC_CHANNEL, + .mode = 1, + .rto_en = 0, + .dir = 0, + .dma_chaining = 0,.ren = 1, + .burstLength = 1,.request = 27,.busuntils = 0, + .sourceType = DMA_TYPE_FIFO,.sourcePort = TRANSFER_8BIT, + .destType = DMA_TYPE_LINEAR,.destPort = TRANSFER_8BIT, + .per_address = (UART1_BASE_ADDR + 0x40), + .M2D_Valid = 0, +}; + +/*! + * @brief dma_info for UART2 recieveing + */ +static mx2_dma_info_t uart2_rx_dma_info = { + .dma_chan = MXC_DMA_DYNAMIC_CHANNEL, + .mode = 0, + .rto_en = 0, + .dir = 0, + .dma_chaining = 0,.ren = 1, + .burstLength = 1,.request = 24,.busuntils = 0, + .sourceType = DMA_TYPE_FIFO,.sourcePort = TRANSFER_8BIT, + .destType = DMA_TYPE_LINEAR,.destPort = TRANSFER_8BIT, + .per_address = (UART2_BASE_ADDR), + .M2D_Valid = 0, +}; + +/*! + * @brief: dma_info for UART2 transmitting + */ +static mx2_dma_info_t uart2_tx_dma_info = { + .dma_chan = MXC_DMA_DYNAMIC_CHANNEL, + .mode = 1, + .rto_en = 0, + .dir = 0, + .dma_chaining = 0,.ren = 1, + .burstLength = 1,.request = 25,.busuntils = 0, + .sourceType = DMA_TYPE_FIFO,.sourcePort = TRANSFER_8BIT, + .destType = DMA_TYPE_LINEAR,.destPort = TRANSFER_8BIT, + .per_address = (UART2_BASE_ADDR + 0x40), + .M2D_Valid = 0, +}; + +/*! + * @brief dma_info for UART3 recieveing + */ +static mx2_dma_info_t uart3_rx_dma_info = { + .dma_chan = MXC_DMA_DYNAMIC_CHANNEL, + .mode = 0, + .rto_en = 0, + .dir = 0, + .dma_chaining = 0,.ren = 1, + .burstLength = 1,.request = 22,.busuntils = 0, + .sourceType = DMA_TYPE_FIFO,.sourcePort = TRANSFER_8BIT, + .destType = DMA_TYPE_LINEAR,.destPort = TRANSFER_8BIT, + .per_address = (UART3_BASE_ADDR), + .M2D_Valid = 0, +}; + +/*! + * @brief: dma_info for UART3 transmitting + */ +static mx2_dma_info_t uart3_tx_dma_info = { + .dma_chan = MXC_DMA_DYNAMIC_CHANNEL, + .mode = 1, + .rto_en = 0, + .dir = 0, + .dma_chaining = 0,.ren = 1, + .burstLength = 1,.request = 23,.busuntils = 0, + .sourceType = DMA_TYPE_FIFO,.sourcePort = TRANSFER_8BIT, + .destType = DMA_TYPE_LINEAR,.destPort = TRANSFER_8BIT, + .per_address = (UART3_BASE_ADDR + 0x40), + .M2D_Valid = 0, +}; + +/*! + * @brief dma_info for UART4 recieveing + */ +static mx2_dma_info_t uart4_rx_dma_info = { + .dma_chan = MXC_DMA_DYNAMIC_CHANNEL, + .mode = 0, + .rto_en = 0, + .dir = 0, + .dma_chaining = 0,.ren = 1, + .burstLength = 1,.request = 20,.busuntils = 0, + .sourceType = DMA_TYPE_FIFO,.sourcePort = TRANSFER_8BIT, + .destType = DMA_TYPE_LINEAR,.destPort = TRANSFER_8BIT, + .per_address = (UART4_BASE_ADDR), + .M2D_Valid = 0, +}; + +/*! + * @brief: dma_info for UART4transmitting + */ +static mx2_dma_info_t uart4_tx_dma_info = { + .dma_chan = MXC_DMA_DYNAMIC_CHANNEL, + .mode = 1, + .rto_en = 0, + .dir = 0, + .dma_chaining = 0,.ren = 1, + .burstLength = 1,.request = 21,.busuntils = 0, + .sourceType = DMA_TYPE_FIFO,.sourcePort = TRANSFER_8BIT, + .destType = DMA_TYPE_LINEAR,.destPort = TRANSFER_8BIT, + .per_address = (UART4_BASE_ADDR + 0x40), + .M2D_Valid = 0, +}; + +/*! + * @brief dma_info for UART5 recieveing + */ +static mx2_dma_info_t uart5_rx_dma_info = { + .dma_chan = MXC_DMA_DYNAMIC_CHANNEL, + .mode = 0, + .rto_en = 0, + .dir = 0, + .dma_chaining = 0,.ren = 1, + .burstLength = 1,.request = 32,.busuntils = 0, + .sourceType = DMA_TYPE_FIFO,.sourcePort = TRANSFER_8BIT, + .destType = DMA_TYPE_LINEAR,.destPort = TRANSFER_8BIT, + .per_address = (UART5_BASE_ADDR), + .M2D_Valid = 0, +}; + +/*! + * @brief: dma_info for UART5 transmitting + */ +static mx2_dma_info_t uart5_tx_dma_info = { + .dma_chan = MXC_DMA_DYNAMIC_CHANNEL, + .mode = 1, + .rto_en = 0, + .dir = 0, + .dma_chaining = 0,.ren = 1, + .burstLength = 1,.request = 33,.busuntils = 0, + .sourceType = DMA_TYPE_FIFO,.sourcePort = TRANSFER_8BIT, + .destType = DMA_TYPE_LINEAR,.destPort = TRANSFER_8BIT, + .per_address = (UART5_BASE_ADDR + 0x40), + .M2D_Valid = 0, +}; + +/*! + * @brief dma_info for UART6 recieveing + */ +static mx2_dma_info_t uart6_rx_dma_info = { + .dma_chan = MXC_DMA_DYNAMIC_CHANNEL, + .mode = 0, + .rto_en = 0, + .dir = 0, + .dma_chaining = 0,.ren = 1, + .burstLength = 1,.request = 34,.busuntils = 0, + .sourceType = DMA_TYPE_FIFO,.sourcePort = TRANSFER_8BIT, + .destType = DMA_TYPE_LINEAR,.destPort = TRANSFER_8BIT, + .per_address = (UART6_BASE_ADDR), + .M2D_Valid = 0, +}; + +/*! + * @brief: dma_info for UART6 transmitting + */ +static mx2_dma_info_t uart6_tx_dma_info = { + .dma_chan = MXC_DMA_DYNAMIC_CHANNEL, + .mode = 1, + .rto_en = 0, + .dir = 0, + .dma_chaining = 0,.ren = 1, + .burstLength = 1,.request = 35,.busuntils = 0, + .sourceType = DMA_TYPE_FIFO,.sourcePort = TRANSFER_8BIT, + .destType = DMA_TYPE_LINEAR,.destPort = TRANSFER_8BIT, + .per_address = (UART6_BASE_ADDR + 0x40), + .M2D_Valid = 0, +}; + +static mx2_dma_info_t ssi1_16bit_rx0_dma_info = { + .dma_chan = MXC_DMA_DYNAMIC_CHANNEL, + .mode = 0, + .rto_en = 0, + .dir = 0, + .dma_chaining = MXC_SOUND_CAPTURE_CHAIN_DMA,.ren = 1, + .burstLength = 8,.request = DMA_REQ_SSI1_RX0,.busuntils = 0, + .sourceType = DMA_TYPE_FIFO,.sourcePort = DMA_MEM_SIZE_16, + .destType = DMA_TYPE_LINEAR,.destPort = DMA_MEM_SIZE_32, + .per_address = (SSI1_BASE_ADDR + 0x08), + .M2D_Valid = 0, +}; + +static mx2_dma_info_t ssi1_16bit_tx0_dma_info = { + .dma_chan = MXC_DMA_DYNAMIC_CHANNEL, + .mode = 1, + .rto_en = 0, + .dir = 0, + .dma_chaining = MXC_SOUND_PLAYBACK_CHAIN_DMA,.ren = 1, + .burstLength = 8,.request = DMA_REQ_SSI1_TX0,.busuntils = 0, + .sourceType = DMA_TYPE_FIFO,.sourcePort = DMA_MEM_SIZE_16, + .destType = DMA_TYPE_LINEAR,.destPort = DMA_MEM_SIZE_32, + .per_address = (SSI1_BASE_ADDR), + .M2D_Valid = 0, +}; + +static mx2_dma_info_t ssi2_16bit_rx0_dma_info = { + .dma_chan = MXC_DMA_DYNAMIC_CHANNEL, + .mode = 0, + .rto_en = 0, + .dir = 0, + .dma_chaining = MXC_SOUND_CAPTURE_CHAIN_DMA,.ren = 1, + .burstLength = 8,.request = DMA_REQ_SSI2_RX0,.busuntils = 0, + .sourceType = DMA_TYPE_FIFO,.sourcePort = DMA_MEM_SIZE_16, + .destType = DMA_TYPE_LINEAR,.destPort = DMA_MEM_SIZE_32, + .per_address = (SSI2_BASE_ADDR + 0x08), + .M2D_Valid = 0, +}; + +static mx2_dma_info_t ssi2_16bit_tx0_dma_info = { + .dma_chan = MXC_DMA_DYNAMIC_CHANNEL, + .mode = 1, + .rto_en = 0, + .dir = 0, + .dma_chaining = MXC_SOUND_PLAYBACK_CHAIN_DMA,.ren = 1, + .burstLength = 8,.request = DMA_REQ_SSI2_TX0,.busuntils = 0, + .sourceType = DMA_TYPE_FIFO,.sourcePort = DMA_MEM_SIZE_16, + .destType = DMA_TYPE_LINEAR,.destPort = DMA_MEM_SIZE_32, + .per_address = (SSI2_BASE_ADDR), + .M2D_Valid = 0, +}; + +static mx2_dma_info_t mmc1_width1_dma_info = { + .dma_chan = MXC_DMA_DYNAMIC_CHANNEL, + .mode = 0, + .rto_en = 0, + .dir = 0, + .dma_chaining = 0,.ren = 1, + .burstLength = 16,.request = DMA_REQ_SDHC1,.busuntils = 0, + .sourceType = DMA_TYPE_FIFO,.sourcePort = DMA_MEM_SIZE_32, + .destType = DMA_TYPE_LINEAR,.destPort = DMA_MEM_SIZE_32, + .per_address = (SDHC1_BASE_ADDR + 0x38), + .M2D_Valid = 0, +}; + +static mx2_dma_info_t mmc1_width4_dma_info = { + .dma_chan = MXC_DMA_DYNAMIC_CHANNEL, + .mode = 0, + .rto_en = 0, + .dir = 0, + .dma_chaining = 0,.ren = 1, + .burstLength = 0,.request = DMA_REQ_SDHC1,.busuntils = 0, + .sourceType = DMA_TYPE_FIFO,.sourcePort = DMA_MEM_SIZE_32, + .destType = DMA_TYPE_LINEAR,.destPort = DMA_MEM_SIZE_32, + .per_address = (SDHC1_BASE_ADDR + 0x38), + .M2D_Valid = 0, +}; + +static mx2_dma_info_t mmc2_width1_dma_info = { + .dma_chan = MXC_DMA_DYNAMIC_CHANNEL, + .mode = 0, + .rto_en = 0, + .dir = 0, + .dma_chaining = 0,.ren = 1, + .burstLength = 16,.request = DMA_REQ_SDHC2,.busuntils = 0, + .sourceType = DMA_TYPE_FIFO,.sourcePort = DMA_MEM_SIZE_32, + .destType = DMA_TYPE_LINEAR,.destPort = DMA_MEM_SIZE_32, + .per_address = (SDHC2_BASE_ADDR + 0x38), + .M2D_Valid = 0, +}; + +static mx2_dma_info_t mmc2_width4_dma_info = { + .dma_chan = MXC_DMA_DYNAMIC_CHANNEL, + .mode = 0, + .rto_en = 0, + .dir = 0, + .dma_chaining = 0,.ren = 1, + .burstLength = 0,.request = DMA_REQ_SDHC2,.busuntils = 0, + .sourceType = DMA_TYPE_FIFO,.sourcePort = DMA_MEM_SIZE_32, + .destType = DMA_TYPE_LINEAR,.destPort = DMA_MEM_SIZE_32, + .per_address = (SDHC2_BASE_ADDR + 0x38), + .M2D_Valid = 0, +}; + +static mx2_dma_info_t csi_rx_dma_info = { + .dma_chan = MXC_DMA_DYNAMIC_CHANNEL, + .mode = 0, + .rto_en = 0, + .dir = 0, + .dma_chaining = 1,.ren = 1, + .burstLength = 64,.request = DMA_REQ_CSI_RX,.busuntils = 0, + .sourceType = DMA_TYPE_FIFO,.sourcePort = DMA_MEM_SIZE_32, + .destType = DMA_TYPE_LINEAR,.destPort = DMA_MEM_SIZE_32, + .per_address = (CSI_BASE_ADDR + 0x10), + .M2D_Valid = 0, +}; + +/*! + * @brief dma info array which is actived + * DEVICE_ID RX/(RX&TX) TX + */ +static dma_info_entry_t active_dma_info[] = { + {MXC_DMA_TEST_RAM2RAM, &ram2ram_dma_info}, + {MXC_DMA_TEST_RAM2D2RAM2D, &ram2d2ram2d_dma_info}, + {MXC_DMA_TEST_RAM2RAM2D, &ram2ram2d_dma_info}, + {MXC_DMA_TEST_RAM2D2RAM, &ram2d2ram_dma_info}, + {MXC_DMA_TEST_HW_CHAINING, &hw_chaining_dma_info}, + {MXC_DMA_TEST_SW_CHAINING, &sw_chaining_dma_info}, + {MXC_DMA_ATA_RX, &ata_rx_dma_info}, + {MXC_DMA_ATA_TX, &ata_tx_dma_info}, + {MXC_DMA_UART1_RX, &uart1_rx_dma_info}, + {MXC_DMA_UART1_TX, &uart1_tx_dma_info}, + {MXC_DMA_UART2_RX, &uart2_rx_dma_info}, + {MXC_DMA_UART2_TX, &uart2_tx_dma_info}, + {MXC_DMA_UART3_RX, &uart3_rx_dma_info}, + {MXC_DMA_UART3_TX, &uart3_tx_dma_info}, + {MXC_DMA_UART4_RX, &uart4_rx_dma_info}, + {MXC_DMA_UART4_TX, &uart4_tx_dma_info}, + {MXC_DMA_UART5_RX, &uart5_rx_dma_info}, + {MXC_DMA_UART5_TX, &uart5_tx_dma_info}, + {MXC_DMA_UART6_RX, &uart6_rx_dma_info}, + {MXC_DMA_UART6_TX, &uart6_tx_dma_info}, + {MXC_DMA_SSI1_16BIT_RX0, &ssi1_16bit_rx0_dma_info}, + {MXC_DMA_SSI1_16BIT_TX0, &ssi1_16bit_tx0_dma_info}, + {MXC_DMA_SSI2_16BIT_RX0, &ssi2_16bit_rx0_dma_info}, + {MXC_DMA_SSI2_16BIT_TX0, &ssi2_16bit_tx0_dma_info}, + {MXC_DMA_MMC1_WIDTH_1, &mmc1_width1_dma_info}, + {MXC_DMA_MMC1_WIDTH_4, &mmc1_width4_dma_info}, + {MXC_DMA_MMC2_WIDTH_1, &mmc2_width1_dma_info}, + {MXC_DMA_MMC2_WIDTH_4, &mmc2_width4_dma_info}, + {MXC_DMA_CSI_RX, &csi_rx_dma_info}, +}; + +/*! + * @brief the number of actived dma info + */ +static int dma_info_entrys = + sizeof(active_dma_info) / sizeof(active_dma_info[0]); + +/*! + * @brief get the dma info by channel_id + */ +mx2_dma_info_t *mxc_dma_get_info(mxc_dma_device_t channel_id) +{ + dma_info_entry_t *p = active_dma_info; + int i; + for (i = 0; i < dma_info_entrys; i++, p++) { + if (p->device == channel_id) + return p->info; + } + return NULL; +} + +/*! + * @brief: scan dma parameter list . And collect information about which channels are dynamic . + */ +void mxc_dma_load_info(mxc_dma_channel_t * dma) +{ + int i, idx; + dma_info_entry_t *p = active_dma_info; + + BUG_ON(dma == NULL); + BUG_ON(p == NULL); + + for (i = 0; i < MXC_DMA_CHANNELS; i++) { + dma[i].dynamic = 1; + } + + for (i = 0; i < dma_info_entrys; i++, p++) { + BUG_ON((p->info == NULL)); + + idx = p->info->dma_chan; + + BUG_ON(((idx >= MAX_DMA_CHANNELS) + && (idx != MXC_DMA_DYNAMIC_CHANNEL))); + if ((idx < 0) || (idx == MXC_DMA_DYNAMIC_CHANNEL)) + continue; + dma[idx].dynamic = 0; + } +} + +EXPORT_SYMBOL(mxc_dma_get_info); +EXPORT_SYMBOL(mxc_dma_load_info); diff --git a/arch/arm/mach-mx27/dptc.c b/arch/arm/mach-mx27/dptc.c new file mode 100644 index 000000000000..deb058c23272 --- /dev/null +++ b/arch/arm/mach-mx27/dptc.c @@ -0,0 +1,49 @@ +/* + * Copyright 2005-2009 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 + */ + +/*! + * @file dptc.c + * + * @brief DPTC table for the Freescale Semiconductor MXC DPTC module. + * + * @ingroup PM + */ + +#include <mach/hardware.h> +#include <mach/mxc_dptc.h> + +struct dptc_wp dptc_wp_allfreq[DPTC_WP_SUPPORTED] = { + /* 532MHz */ + /* dcvr0 dcvr1 dcvr2 dcvr3 voltage */ + /* wp0 */ + {0xffe00000, 0x18e2e85b, 0xffe00000, 0x25c4688a, 1600}, + {0xffe00000, 0x18e2e85b, 0xffe00000, 0x25c4688a, 1575}, + {0xffe00000, 0x1902e85b, 0xffe00000, 0x25e4688a, 1550}, + {0xffe00000, 0x1922e85b, 0xffe00000, 0x25e4688a, 1525}, + {0xffe00000, 0x1942ec5b, 0xffe00000, 0x2604688a, 1500}, + /* wp5 */ + {0xffe00000, 0x1942ec5b, 0xffe00000, 0x26646c8a, 1475}, + {0xffe00000, 0x1962ec5b, 0xffe00000, 0x26c4708b, 1450}, + {0xffe00000, 0x1962ec5b, 0xffe00000, 0x26e4708b, 1425}, + {0xffe00000, 0x1982f05c, 0xffe00000, 0x2704748b, 1400}, + {0xffe00000, 0x19c2f05c, 0xffe00000, 0x2744748b, 1375}, + /* wp10 */ + {0xffe00000, 0x1a02f45c, 0xffe00000, 0x2784788b, 1350}, + {0xffe00000, 0x1a42f45c, 0xffe00000, 0x27c47c8b, 1325}, + {0xffe00000, 0x1a82f85c, 0xffe00000, 0x2824808c, 1300}, + {0xffe00000, 0x1aa2f85c, 0xffe00000, 0x2884848c, 1275}, + {0xffe00000, 0x1ac2fc5c, 0xffe00000, 0x28e4888c, 1250}, + /* wp15 */ + {0xffe00000, 0x1ae2fc5c, 0xffe00000, 0x2924888c, 1225}, + {0xffe00000, 0x1b23005d, 0xffe00000, 0x29648c8c, 1200}, +}; diff --git a/arch/arm/mach-mx27/gpio_mux.c b/arch/arm/mach-mx27/gpio_mux.c new file mode 100644 index 000000000000..500ebcc48a04 --- /dev/null +++ b/arch/arm/mach-mx27/gpio_mux.c @@ -0,0 +1,308 @@ +/* + * Copyright 2004-2009 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 + */ + +/*! + * @defgroup GPIO_MX27 Board GPIO and Muxing Setup + * @ingroup MSL_MX27 + */ +/*! + * @file mach-mx27/gpio_mux.c + * + * @brief I/O Muxing control functions + * + * @ingroup GPIO_MX27 + */ + +#include <linux/kernel.h> +#include <linux/cache.h> +#include <linux/spinlock.h> + +#include <linux/io.h> +#include <mach/hardware.h> +#include <mach/gpio.h> +#include "gpio_mux.h" + +/*! + * This structure defines the offset of registers in gpio module. + */ +enum gpio_reg { + GPIO_GIUS = 0x20, + GPIO_GPR = 0x38, + GPIO_PUEN = 0x40, + GPIO_DDIR = 0x00, + GPIO_OCR1 = 0x04, + GPIO_OCR2 = 0x08, + GPIO_ICONFA1 = 0x0C, + GPIO_ICONFA2 = 0x10, + GPIO_ICONFB1 = 0x14, + GPIO_ICONFB2 = 0x18, +}; + +/*! + * This enumeration data type defines the configuration for input mode. + */ +typedef enum { + GPIO_INPUT_GPIO = 0x00, + GPIO_INPUT_INTR = 0x01, + GPIO_INPUT_LOW = 0x02, + GPIO_INPUT_HIGH = 0x03 +} gpio_input_cfg_t; + +/*! + * This enumeration data type defines the configuration for output mode. + */ +typedef enum { + GPIO_OUTPUT_A = 0x00, + GPIO_OUTPUT_B = 0x01, + GPIO_OUTPUT_C = 0x02, + GPIO_OUTPUT_DR = 0x03 +} gpio_output_cfg_t; + +extern struct mxc_gpio_port mxc_gpio_ports[]; + +/*! + * defines a spinlock to protected the accessing to gpio pin. + */ +DEFINE_SPINLOCK(gpio_mux_lock); + +/*! + * This function enable or disable the pullup feature to the pin. + * @param port a pointer of gpio port + * @param index the index of the pin in the port + * @param en 0 if disable pullup, otherwise enable it. + * @return none + */ +static inline void _gpio_set_puen(struct mxc_gpio_port *port, u32 index, + bool en) +{ + u32 reg; + + reg = __raw_readl(port->base + GPIO_PUEN); + if (en) { + reg |= 1 << index; + } else { + reg &= ~(1 << index); + } + __raw_writel(reg, port->base + GPIO_PUEN); +} + +/*! + * This function set the input configuration A. + * @param port a pointer of gpio port + * @param index the index of the pin in the port + * @param config a mode as define in \b #gpio_input_cfg_t + * @return none + */ +static inline void _gpio_set_iconfa(struct mxc_gpio_port *port, u32 index, + gpio_input_cfg_t config) +{ + u32 reg, val; + u32 mask; + + mask = 0x3 << ((index % 16) << 1); + + if (index >= 16) { + reg = port->base + GPIO_ICONFA2; + val = config << ((index - 16) * 2); + } else { + reg = port->base + GPIO_ICONFA1; + val = config << (index * 2); + } + val |= __raw_readl(reg) & ~(mask); + __raw_writel(val, reg); +} + +/*! + * This function set the input configuration B. + * @param port a pointer of gpio port + * @param index the index of the pin in the port + * @param config a mode as define in \b #gpio_input_cfg_t + * @return none + */ +static inline void _gpio_set_iconfb(struct mxc_gpio_port *port, u32 index, + gpio_input_cfg_t config) +{ + u32 reg, val; + u32 mask; + + mask = 0x3 << ((index % 16) << 1); + + if (index >= 16) { + reg = port->base + GPIO_ICONFB2; + val = config << ((index - 16) * 2); + } else { + reg = port->base + GPIO_ICONFB1; + val = config << (index * 2); + } + val |= __raw_readl(reg) & (~mask); + __raw_writel(val, reg); +} + +/*! + * This function set the output configuration. + * @param port a pointer of gpio port + * @param index the index of the pin in the port + * @param config a mode as define in \b #gpio_output_cfg_t + * @return none + */ +static inline void _gpio_set_ocr(struct mxc_gpio_port *port, u32 index, + gpio_output_cfg_t config) +{ + u32 reg, val; + u32 mask; + + mask = 0x3 << ((index % 16) << 1); + if (index >= 16) { + reg = port->base + GPIO_OCR2; + val = config << ((index - 16) * 2); + } else { + reg = port->base + GPIO_OCR1; + val = config << (index * 2); + } + val |= __raw_readl(reg) & (~mask); + __raw_writel(val, reg); +} + +/*! + *@brief gpio_config_mux - just configure the mode of the gpio pin. + *@param pin a pin number as defined in \b #iomux_pin_name_t + *@param mode a module as define in \b #gpio_mux_mode_t; + * GPIO_MUX_PRIMARY set pin to work as primary function. + * GPIO_MUX_ALT set pin to work as alternate function. + * GPIO_MUX_GPIO set pin to work as output function based the data register + * GPIO_MUX_INPUT1 set pin to work as input function connected with A_OUT + * GPIO_MUX_INPUT2 set pin to work as input function connected with B_OUT + * GPIO_MUX_OUTPUT1 set pin to work as output function connected with A_IN + * GPIO_MUX_OUTPUT2 set pin to work as output function connected with B_IN + * GPIO_MUX_OUTPUT3 set pin to work as output function connected with C_IN + *@return 0 if successful, Non-zero otherwise + */ + +int gpio_config_mux(iomux_pin_name_t pin, gpio_mux_mode_t mode) +{ + unsigned long lock_flags; + u32 gius_reg, gpr_reg; + struct mxc_gpio_port *port; + u32 index, gpio = IOMUX_TO_GPIO(pin); + + port = &(mxc_gpio_ports[GPIO_TO_PORT(gpio)]); + index = GPIO_TO_INDEX(gpio); + + pr_debug("%s: Configuring PORT %c, bit %d\n", + __func__, GPIO_TO_PORT(gpio) + 'A', index); + + spin_lock_irqsave(&gpio_mux_lock, lock_flags); + + gius_reg = __raw_readl(port->base + GPIO_GIUS); + gpr_reg = __raw_readl(port->base + GPIO_GPR); + + switch (mode) { + case GPIO_MUX_PRIMARY: + gius_reg &= ~(1L << index); + gpr_reg &= ~(1L << index); + break; + case GPIO_MUX_ALT: + gius_reg &= ~(1L << index); + gpr_reg |= (1L << index); + break; + case GPIO_MUX_GPIO: + gius_reg |= (1L << index); + _gpio_set_ocr(port, index, GPIO_OUTPUT_DR); + break; + case GPIO_MUX_INPUT1: + gius_reg |= (1L << index); + _gpio_set_iconfa(port, index, GPIO_INPUT_GPIO); + break; + case GPIO_MUX_INPUT2: + gius_reg |= (1L << index); + _gpio_set_iconfb(port, index, GPIO_INPUT_GPIO); + break; + case GPIO_MUX_OUTPUT1: + gius_reg |= (1L << index); + _gpio_set_ocr(port, index, GPIO_OUTPUT_A); + break; + case GPIO_MUX_OUTPUT2: + gius_reg |= (1L << index); + _gpio_set_ocr(port, index, GPIO_OUTPUT_B); + break; + case GPIO_MUX_OUTPUT3: + gius_reg |= (1L << index); + _gpio_set_ocr(port, index, GPIO_OUTPUT_C); + break; + default: + spin_unlock_irqrestore(&gpio_mux_lock, lock_flags); + return -1; + } + + __raw_writel(gius_reg, port->base + GPIO_GIUS); + __raw_writel(gpr_reg, port->base + GPIO_GPR); + + spin_unlock_irqrestore(&gpio_mux_lock, lock_flags); + return 0; +} + +/*! + * This function is just used to enable or disable the pull up feature . + * @param pin a pin number as defined in \b #iomux_pin_name_t + * @param en 0 if disable, Non-zero enable + * @return 0 if successful, Non-zero otherwise + */ +int gpio_set_puen(iomux_pin_name_t pin, bool en) +{ + unsigned long lock_flags; + + struct mxc_gpio_port *port; + u32 index, gpio = IOMUX_TO_GPIO(pin); + + port = &(mxc_gpio_ports[GPIO_TO_PORT(gpio)]); + index = GPIO_TO_INDEX(gpio); + + pr_debug("%s: Configuring output mode of PORT %c, bit %d\n", + __func__, GPIO_TO_PORT(gpio) + 'A', index); + + spin_lock_irqsave(&gpio_mux_lock, lock_flags); + + _gpio_set_puen(port, index, en); + spin_unlock_irqrestore(&gpio_mux_lock, lock_flags); + return 0; + +} + +/*! + * This function is just used to request a pin and configure it. + * @param pin a pin number as defined in \b #iomux_pin_name_t + * @param mode a module as define in \b #gpio_mux_mode_t; + * @return 0 if successful, Non-zero otherwise + */ +int gpio_request_mux(iomux_pin_name_t pin, gpio_mux_mode_t mode) +{ + int ret; + ret = gpio_request(IOMUX_TO_GPIO(pin), NULL); + if (ret == 0) { + ret = gpio_config_mux(pin, mode); + if (ret) { + gpio_free(IOMUX_TO_GPIO(pin)); + } + } + return ret; +} + +/*! + * This function is just used to release a pin. + * @param pin a pin number as defined in \b #iomux_pin_name_t + * @return none + */ +void gpio_free_mux(iomux_pin_name_t pin) +{ + gpio_free(IOMUX_TO_GPIO(pin)); +} diff --git a/arch/arm/mach-mx27/gpio_mux.h b/arch/arm/mach-mx27/gpio_mux.h new file mode 100644 index 000000000000..0c8db21c766a --- /dev/null +++ b/arch/arm/mach-mx27/gpio_mux.h @@ -0,0 +1,80 @@ +/* + * Copyright 2004-2009 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 + */ + +/*! + *@file mach-mx27/gpio_mux.h + *@brief This file contains the private definition . + * @ingroup GPIO_MX27 + */ + +#ifndef __ARCH_ARM_MACH_MX27_GPIO_MUX_H__ +#define __ARCH_ARM_MACH_MX27_GPIO_MUX_H__ + +#include "mx27_pins.h" + +typedef unsigned int iomux_pin_name_t; + +/*! + * This enumeration data type defines the modes of the pin . + * GPIO_MUX_PRIMARY is the primary mode. + * GPIO_MUX_ALT is the alternate mode. + * GPIO_MUX_GPIO is the output mode and the signal source is data register. + * GPIO_MUX_INPUT1 is the input mode and the signal destination is A_OUT. + * GPIO_MUX_INPUT2 is the input mode and the signal destination is B_OUT. + * GPIO_MUX_OUTPUT1 is the output mode and the signal destination is A_IN. + * GPIO_MUX_OUTPUT2 is the output mode and the signal destination is B_IN. + * GPIO_MUX_OUTPUT3 is the output mode and the signal destination is C_IN. + */ +typedef enum { + GPIO_MUX_PRIMARY, + GPIO_MUX_ALT, + GPIO_MUX_GPIO, + GPIO_MUX_INPUT1, + GPIO_MUX_INPUT2, + GPIO_MUX_OUTPUT1, + GPIO_MUX_OUTPUT2, + GPIO_MUX_OUTPUT3, +} gpio_mux_mode_t; + +/*! + * This function is just used to request a pin and configure it. + * @param pin a pin number as defined in \b #iomux_pin_name_t + * @param mode a module as define in \b #gpio_mux_mode_t; + * @return 0 if successful, Non-zero otherwise + */ +extern int gpio_request_mux(iomux_pin_name_t pin, gpio_mux_mode_t mode); + +/*! + * This function is just used to configure a pin . + * @param pin a pin number as defined in \b #iomux_pin_name_t + * @param mode a module as define in \b #gpio_mux_mode_t; + * @return 0 if successful, Non-zero otherwise + */ +extern int gpio_config_mux(iomux_pin_name_t pin, gpio_mux_mode_t mode); + +/*! + * This function is just used to enable or disable the pull up feature . + * @param pin a pin number as defined in \b #iomux_pin_name_t + * @param en 0 if disable, Non-zero enable + * @return 0 if successful, Non-zero otherwise + */ +extern int gpio_set_puen(iomux_pin_name_t pin, bool en); + +/*! + * This function is just used to release a pin. + * @param pin a pin number as defined in \b #iomux_pin_name_t + * @return none + */ +extern void gpio_free_mux(iomux_pin_name_t pin); + +#endif /* __ARCH_ARM_MACH_MX27_GPIO_MUX_H__ */ diff --git a/arch/arm/mach-mx27/mm.c b/arch/arm/mach-mx27/mm.c new file mode 100644 index 000000000000..9f673b6687a2 --- /dev/null +++ b/arch/arm/mach-mx27/mm.c @@ -0,0 +1,62 @@ +/* + * Copyright 2004-2009 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/mm.h> +#include <linux/init.h> +#include <mach/hardware.h> +#include <asm/pgtable.h> +#include <asm/mach/map.h> + +/*! + * @file mach-mx27/mm.c + * + * @brief This file creates static mapping between physical to virtual memory. + * + * @ingroup Memory_MX27 + */ + +/*! + * This structure defines the MX27 memory map. + */ +static struct map_desc mxc_io_desc[] __initdata = { + { + .virtual = AIPI_BASE_ADDR_VIRT, + .pfn = __phys_to_pfn(AIPI_BASE_ADDR), + .length = AIPI_SIZE, + .type = MT_DEVICE}, + { + .virtual = SAHB1_BASE_ADDR_VIRT, + .pfn = __phys_to_pfn(SAHB1_BASE_ADDR), + .length = SAHB1_SIZE, + .type = MT_DEVICE}, + { + .virtual = X_MEMC_BASE_ADDR_VIRT, + .pfn = __phys_to_pfn(X_MEMC_BASE_ADDR), + .length = X_MEMC_SIZE, + .type = MT_DEVICE}, + { + .virtual = CS4_BASE_ADDR_VIRT, + .pfn = __phys_to_pfn(CS4_BASE_ADDR), + .length = CS4_SIZE, + .type = MT_DEVICE} +}; + +/*! + * This function initializes the memory map. It is called during the + * system startup to create static physical to virtual memory map for + * the IO modules. + */ +void __init mxc_map_io(void) +{ + iotable_init(mxc_io_desc, ARRAY_SIZE(mxc_io_desc)); +} diff --git a/arch/arm/mach-mx27/mx27_pins.h b/arch/arm/mach-mx27/mx27_pins.h new file mode 100644 index 000000000000..40ff1be1febc --- /dev/null +++ b/arch/arm/mach-mx27/mx27_pins.h @@ -0,0 +1,207 @@ +/* + * Copyright 2004-2008 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 + */ + +#ifndef __ASM_ARCH_MXC_MX27_PINS_H__ +#define __ASM_ARCH_MXC_MX27_PINS_H__ + +/*! + * @file arch-mxc/mx27_pins.h + * + * @brief MX27 I/O Pin List + * + * @ingroup GPIO_MX27 + */ + +#ifndef __ASSEMBLY__ + +#define _MX27_BUILD_PIN(gp,gi) (((gp) << MUX_IO_P) | ((gi) << MUX_IO_I)) + +enum iomux_pins { + MX27_PIN_USBH2_CLK = _MX27_BUILD_PIN(0, 0), + MX27_PIN_USBH2_DIR = _MX27_BUILD_PIN(0, 1), + MX27_PIN_USBH2_DATA7 = _MX27_BUILD_PIN(0, 2), + MX27_PIN_USBH2_NXT = _MX27_BUILD_PIN(0, 3), + MX27_PIN_USBH2_STP = _MX27_BUILD_PIN(0, 4), + MX27_PIN_LSCLK = _MX27_BUILD_PIN(0, 5), + MX27_PIN_LD0 = _MX27_BUILD_PIN(0, 6), + MX27_PIN_LD1 = _MX27_BUILD_PIN(0, 7), + MX27_PIN_LD2 = _MX27_BUILD_PIN(0, 8), + MX27_PIN_LD3 = _MX27_BUILD_PIN(0, 9), + MX27_PIN_LD4 = _MX27_BUILD_PIN(0, 10), + MX27_PIN_LD5 = _MX27_BUILD_PIN(0, 11), + MX27_PIN_LD6 = _MX27_BUILD_PIN(0, 12), + MX27_PIN_LD7 = _MX27_BUILD_PIN(0, 13), + MX27_PIN_LD8 = _MX27_BUILD_PIN(0, 14), + MX27_PIN_LD9 = _MX27_BUILD_PIN(0, 15), + MX27_PIN_LD10 = _MX27_BUILD_PIN(0, 16), + MX27_PIN_LD11 = _MX27_BUILD_PIN(0, 17), + MX27_PIN_LD12 = _MX27_BUILD_PIN(0, 18), + MX27_PIN_LD13 = _MX27_BUILD_PIN(0, 19), + MX27_PIN_LD14 = _MX27_BUILD_PIN(0, 20), + MX27_PIN_LD15 = _MX27_BUILD_PIN(0, 21), + MX27_PIN_LD16 = _MX27_BUILD_PIN(0, 22), + MX27_PIN_LD17 = _MX27_BUILD_PIN(0, 23), + MX27_PIN_REV = _MX27_BUILD_PIN(0, 24), + MX27_PIN_CLS = _MX27_BUILD_PIN(0, 25), + MX27_PIN_PS = _MX27_BUILD_PIN(0, 26), + MX27_PIN_SPL_SPR = _MX27_BUILD_PIN(0, 27), + MX27_PIN_HSYNC = _MX27_BUILD_PIN(0, 28), + MX27_PIN_VSYNC = _MX27_BUILD_PIN(0, 29), + MX27_PIN_CONTRAST = _MX27_BUILD_PIN(0, 30), + MX27_PIN_OE_ACD = _MX27_BUILD_PIN(0, 31), + + MX27_PIN_SD2_D0 = _MX27_BUILD_PIN(1, 4), + MX27_PIN_SD2_D1 = _MX27_BUILD_PIN(1, 5), + MX27_PIN_SD2_D2 = _MX27_BUILD_PIN(1, 6), + MX27_PIN_SD2_D3 = _MX27_BUILD_PIN(1, 7), + MX27_PIN_SD2_CMD = _MX27_BUILD_PIN(1, 8), + MX27_PIN_SD2_CLK = _MX27_BUILD_PIN(1, 9), + MX27_PIN_CSI_D0 = _MX27_BUILD_PIN(1, 10), + MX27_PIN_CSI_D1 = _MX27_BUILD_PIN(1, 11), + MX27_PIN_CSI_D2 = _MX27_BUILD_PIN(1, 12), + MX27_PIN_CSI_D3 = _MX27_BUILD_PIN(1, 13), + MX27_PIN_CSI_D4 = _MX27_BUILD_PIN(1, 14), + MX27_PIN_CSI_MCLK = _MX27_BUILD_PIN(1, 15), + MX27_PIN_CSI_PIXCLK = _MX27_BUILD_PIN(1, 16), + MX27_PIN_CSI_D5 = _MX27_BUILD_PIN(1, 17), + MX27_PIN_CSI_D6 = _MX27_BUILD_PIN(1, 18), + MX27_PIN_CSI_D7 = _MX27_BUILD_PIN(1, 19), + MX27_PIN_CSI_VSYNC = _MX27_BUILD_PIN(1, 20), + MX27_PIN_CSI_HSYNC = _MX27_BUILD_PIN(1, 21), + MX27_PIN_USBH1_SUSP = _MX27_BUILD_PIN(1, 22), + MX27_PIN_USB_PWR = _MX27_BUILD_PIN(1, 23), + MX27_PIN_USB_OC_B = _MX27_BUILD_PIN(1, 24), + MX27_PIN_USBH1_RCV = _MX27_BUILD_PIN(1, 25), + MX27_PIN_USBH1_FS = _MX27_BUILD_PIN(1, 26), + MX27_PIN_USBH1_OE_B = _MX27_BUILD_PIN(1, 27), + MX27_PIN_USBH1_TXDM = _MX27_BUILD_PIN(1, 28), + MX27_PIN_USBH1_TXDP = _MX27_BUILD_PIN(1, 29), + MX27_PIN_USBH1_RXDM = _MX27_BUILD_PIN(1, 30), + MX27_PIN_USBH1_RXDP = _MX27_BUILD_PIN(1, 31), + + MX27_PIN_I2C2_SDA = _MX27_BUILD_PIN(2, 5), + MX27_PIN_I2C2_SCL = _MX27_BUILD_PIN(2, 6), + MX27_PIN_USBOTG_DATA5 = _MX27_BUILD_PIN(2, 7), + MX27_PIN_USBOTG_DATA6 = _MX27_BUILD_PIN(2, 8), + MX27_PIN_USBOTG_DATA0 = _MX27_BUILD_PIN(2, 9), + MX27_PIN_USBOTG_DATA2 = _MX27_BUILD_PIN(2, 10), + MX27_PIN_USBOTG_DATA1 = _MX27_BUILD_PIN(2, 11), + MX27_PIN_USBOTG_DATA4 = _MX27_BUILD_PIN(2, 12), + MX27_PIN_USBOTG_DATA3 = _MX27_BUILD_PIN(2, 13), + MX27_PIN_TOUT = _MX27_BUILD_PIN(2, 14), + MX27_PIN_TIN = _MX27_BUILD_PIN(2, 15), + MX27_PIN_SSI4_FS = _MX27_BUILD_PIN(2, 16), + MX27_PIN_SSI4_RXDAT = _MX27_BUILD_PIN(2, 17), + MX27_PIN_SSI4_TXDAT = _MX27_BUILD_PIN(2, 18), + MX27_PIN_SSI4_CLK = _MX27_BUILD_PIN(2, 19), + MX27_PIN_SSI1_FS = _MX27_BUILD_PIN(2, 20), + MX27_PIN_SSI1_RXDAT = _MX27_BUILD_PIN(2, 21), + MX27_PIN_SSI1_TXDAT = _MX27_BUILD_PIN(2, 22), + MX27_PIN_SSI1_CLK = _MX27_BUILD_PIN(2, 23), + MX27_PIN_SSI2_FS = _MX27_BUILD_PIN(2, 24), + MX27_PIN_SSI2_RXDAT = _MX27_BUILD_PIN(2, 25), + MX27_PIN_SSI2_TXDAT = _MX27_BUILD_PIN(2, 26), + MX27_PIN_SSI2_CLK = _MX27_BUILD_PIN(2, 27), + MX27_PIN_SSI3_FS = _MX27_BUILD_PIN(2, 28), + MX27_PIN_SSI3_RXDAT = _MX27_BUILD_PIN(2, 29), + MX27_PIN_SSI3_TXDAT = _MX27_BUILD_PIN(2, 30), + MX27_PIN_SSI3_CLK = _MX27_BUILD_PIN(2, 31), + + MX27_PIN_SD3_CMD = _MX27_BUILD_PIN(3, 0), + MX27_PIN_SD3_CLK = _MX27_BUILD_PIN(3, 1), + MX27_PIN_ATA_DATA0 = _MX27_BUILD_PIN(3, 2), + MX27_PIN_ATA_DATA1 = _MX27_BUILD_PIN(3, 3), + MX27_PIN_ATA_DATA2 = _MX27_BUILD_PIN(3, 4), + MX27_PIN_ATA_DATA3 = _MX27_BUILD_PIN(3, 5), + MX27_PIN_ATA_DATA4 = _MX27_BUILD_PIN(3, 6), + MX27_PIN_ATA_DATA5 = _MX27_BUILD_PIN(3, 7), + MX27_PIN_ATA_DATA6 = _MX27_BUILD_PIN(3, 8), + MX27_PIN_ATA_DATA7 = _MX27_BUILD_PIN(3, 9), + MX27_PIN_ATA_DATA8 = _MX27_BUILD_PIN(3, 10), + MX27_PIN_ATA_DATA9 = _MX27_BUILD_PIN(3, 11), + MX27_PIN_ATA_DATA10 = _MX27_BUILD_PIN(3, 12), + MX27_PIN_ATA_DATA11 = _MX27_BUILD_PIN(3, 13), + MX27_PIN_ATA_DATA12 = _MX27_BUILD_PIN(3, 14), + MX27_PIN_ATA_DATA13 = _MX27_BUILD_PIN(3, 15), + MX27_PIN_ATA_DATA14 = _MX27_BUILD_PIN(3, 16), + MX27_PIN_I2C_DATA = _MX27_BUILD_PIN(3, 17), + MX27_PIN_I2C_CLK = _MX27_BUILD_PIN(3, 18), + MX27_PIN_CSPI2_SS2 = _MX27_BUILD_PIN(3, 19), + MX27_PIN_CSPI2_SS1 = _MX27_BUILD_PIN(3, 20), + MX27_PIN_CSPI2_SS0 = _MX27_BUILD_PIN(3, 21), + MX27_PIN_CSPI2_SCLK = _MX27_BUILD_PIN(3, 22), + MX27_PIN_CSPI2_MISO = _MX27_BUILD_PIN(3, 23), + MX27_PIN_CSPI2_MOSI = _MX27_BUILD_PIN(3, 24), + MX27_PIN_CSPI1_RDY = _MX27_BUILD_PIN(3, 25), + MX27_PIN_CSPI1_SS2 = _MX27_BUILD_PIN(3, 26), + MX27_PIN_CSPI1_SS1 = _MX27_BUILD_PIN(3, 27), + MX27_PIN_CSPI1_SS0 = _MX27_BUILD_PIN(3, 28), + MX27_PIN_CSPI1_SCLK = _MX27_BUILD_PIN(3, 29), + MX27_PIN_CSPI1_MISO = _MX27_BUILD_PIN(3, 30), + MX27_PIN_CSPI1_MOSI = _MX27_BUILD_PIN(3, 31), + + MX27_PIN_USBOTG_NXT = _MX27_BUILD_PIN(4, 0), + MX27_PIN_USBOTG_STP = _MX27_BUILD_PIN(4, 1), + MX27_PIN_USBOTG_DIR = _MX27_BUILD_PIN(4, 2), + MX27_PIN_UART2_CTS = _MX27_BUILD_PIN(4, 3), + MX27_PIN_UART2_RTS = _MX27_BUILD_PIN(4, 4), + MX27_PIN_PWMO = _MX27_BUILD_PIN(4, 5), + MX27_PIN_UART2_TXD = _MX27_BUILD_PIN(4, 6), + MX27_PIN_UART2_RXD = _MX27_BUILD_PIN(4, 7), + MX27_PIN_UART3_TXD = _MX27_BUILD_PIN(4, 8), + MX27_PIN_UART3_RXD = _MX27_BUILD_PIN(4, 9), + MX27_PIN_UART3_CTS = _MX27_BUILD_PIN(4, 10), + MX27_PIN_UART3_RTS = _MX27_BUILD_PIN(4, 11), + MX27_PIN_UART1_TXD = _MX27_BUILD_PIN(4, 12), + MX27_PIN_UART1_RXD = _MX27_BUILD_PIN(4, 13), + MX27_PIN_UART1_CTS = _MX27_BUILD_PIN(4, 14), + MX27_PIN_UART1_RTS = _MX27_BUILD_PIN(4, 15), + MX27_PIN_RTCK = _MX27_BUILD_PIN(4, 16), + MX27_PIN_RESET_OUT_B = _MX27_BUILD_PIN(4, 17), + MX27_PIN_SD1_D0 = _MX27_BUILD_PIN(4, 18), + MX27_PIN_SD1_D1 = _MX27_BUILD_PIN(4, 19), + MX27_PIN_SD1_D2 = _MX27_BUILD_PIN(4, 20), + MX27_PIN_SD1_D3 = _MX27_BUILD_PIN(4, 21), + MX27_PIN_SD1_CMD = _MX27_BUILD_PIN(4, 22), + MX27_PIN_SD1_CLK = _MX27_BUILD_PIN(4, 23), + MX27_PIN_USBOTG_CLK = _MX27_BUILD_PIN(4, 24), + MX27_PIN_USBOTG_DATA7 = _MX27_BUILD_PIN(4, 25), + + MX27_PIN_NFRB = _MX27_BUILD_PIN(5, 0), + MX27_PIN_NFCLE = _MX27_BUILD_PIN(5, 1), + MX27_PIN_NFWP_B = _MX27_BUILD_PIN(5, 2), + MX27_PIN_NFCE_B = _MX27_BUILD_PIN(5, 3), + MX27_PIN_NFALE = _MX27_BUILD_PIN(5, 4), + MX27_PIN_NFRE_B = _MX27_BUILD_PIN(5, 5), + MX27_PIN_NFWE_B = _MX27_BUILD_PIN(5, 6), + MX27_PIN_PC_POE = _MX27_BUILD_PIN(5, 7), + MX27_PIN_PC_RW_B = _MX27_BUILD_PIN(5, 8), + MX27_PIN_IOIS16 = _MX27_BUILD_PIN(5, 9), + MX27_PIN_PC_RST = _MX27_BUILD_PIN(5, 10), + MX27_PIN_PC_BVD2 = _MX27_BUILD_PIN(5, 11), + MX27_PIN_PC_BVD1 = _MX27_BUILD_PIN(5, 12), + MX27_PIN_PC_VS2 = _MX27_BUILD_PIN(5, 13), + MX27_PIN_PC_VS1 = _MX27_BUILD_PIN(5, 14), + MX27_PIN_CLKO = _MX27_BUILD_PIN(5, 15), + MX27_PIN_PC_PWRON = _MX27_BUILD_PIN(5, 16), + MX27_PIN_PC_READY = _MX27_BUILD_PIN(5, 17), + MX27_PIN_PC_WAIT_B = _MX27_BUILD_PIN(5, 18), + MX27_PIN_PC_CD2_B = _MX27_BUILD_PIN(5, 19), + MX27_PIN_PC_CD1_B = _MX27_BUILD_PIN(5, 20), + MX27_PIN_CS4_B = _MX27_BUILD_PIN(5, 21), + MX27_PIN_CS5_B = _MX27_BUILD_PIN(5, 22), + MX27_PIN_ATA_DATA15 = _MX27_BUILD_PIN(5, 23), +}; + +#endif /* __ASSEMBLY__ */ +#endif /* __ASM_ARCH_MXC_MX27_PINS_H__ */ diff --git a/arch/arm/mach-mx27/mx27ads.c b/arch/arm/mach-mx27/mx27ads.c new file mode 100644 index 000000000000..5568fb175e49 --- /dev/null +++ b/arch/arm/mach-mx27/mx27ads.c @@ -0,0 +1,833 @@ +/* + * Copyright (C) 2000 Deep Blue Solutions Ltd + * Copyright (C) 2002 Shane Nay (shane@minirl.com) + * Copyright 2006-2009 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/types.h> +#include <linux/sched.h> +#include <linux/interrupt.h> +#include <linux/init.h> +#include <linux/ioport.h> +#include <linux/device.h> +#include <linux/input.h> +#include <linux/nodemask.h> +#include <linux/clk.h> +#include <linux/spi/spi.h> +#include <linux/serial_8250.h> +#if defined(CONFIG_MTD) || defined(CONFIG_MTD_MODULE) +#include <linux/mtd/mtd.h> +#include <linux/mtd/map.h> +#include <linux/mtd/partitions.h> + +#include <asm/mach/flash.h> +#endif + +#include <mach/hardware.h> +#include <mach/common.h> +#include <mach/memory.h> +#include <mach/gpio.h> +#include <asm/irq.h> +#include <asm/setup.h> +#include <asm/mach-types.h> +#include <asm/mach/arch.h> +#include <asm/mach/irq.h> +#include <asm/mach/keypad.h> +#include <asm/mach/time.h> +#include "gpio_mux.h" +#include "board-mx27ads.h" + +/*! + * @file mach-mx27/mx27ads.c + * @brief This file contains the board specific initialization routines. + * + * @ingroup MSL_MX27 + */ + +extern void mxc_map_io(void); +extern void mxc_init_irq(void); +extern void mxc_cpu_init(void) __init; +extern void mxc_cpu_common_init(void); +extern void __init early_console_setup(char *); + +static char command_line[COMMAND_LINE_SIZE]; +static int mxc_card_status; +int mxc_board_is_ads = 1; + +static void mxc_nop_release(struct device *dev) +{ + /* Nothing */ +} + +unsigned long board_get_ckih_rate(void) +{ + if ((__raw_readw(PBC_VERSION_REG) & CKIH_27MHZ_BIT_SET) == 0) { + return 27000000; + } + return 26000000; +} + +#if defined(CONFIG_CS89x0) || defined(CONFIG_CS89x0_MODULE) +/*! Null terminated portlist used to probe for the CS8900A device on ISA Bus + * Add 3 to reset the page window before probing (fixes eth probe when deployed + * using nand_boot) + */ +unsigned int netcard_portlist[] = { CS8900A_BASE_ADDRESS + 3, 0 }; + +EXPORT_SYMBOL(netcard_portlist); +/*! + * The CS8900A has 4 IRQ pins, which is software selectable, CS8900A interrupt + * pin 0 is used for interrupt generation. + */ +unsigned int cs8900_irq_map[] = { CS8900AIRQ, 0, 0, 0 }; + +EXPORT_SYMBOL(cs8900_irq_map); +#endif + +#if defined(CONFIG_FEC) || defined(CONFIG_FEC_MODULE) +unsigned int expio_intr_fec = MXC_EXP_IO_BASE + 7; + +EXPORT_SYMBOL(expio_intr_fec); +#endif + +#if defined(CONFIG_KEYBOARD_MXC) || defined(CONFIG_KEYBOARD_MXC_MODULE) + +/*! + * This array is used for mapping mx27 ADS keypad scancodes to input keyboard + * keycodes. + */ +static u16 mxckpd_keycodes[] = { + KEY_KP9, KEY_LEFTSHIFT, KEY_0, KEY_KPASTERISK, KEY_RECORD, KEY_POWER, + KEY_KP8, KEY_9, KEY_8, KEY_7, KEY_KP5, KEY_VOLUMEDOWN, + KEY_KP7, KEY_6, KEY_5, KEY_4, KEY_KP4, KEY_VOLUMEUP, + KEY_KP6, KEY_3, KEY_2, KEY_1, KEY_KP3, KEY_DOWN, + KEY_BACK, KEY_RIGHT, KEY_ENTER, KEY_LEFT, KEY_HOME, KEY_KP2, + KEY_END, KEY_F2, KEY_UP, KEY_F1, KEY_F4, KEY_KP1, +}; + +static struct keypad_data evb_6_by_6_keypad = { + .rowmax = 6, + .colmax = 6, + .irq = MXC_INT_KPP, + .learning = 0, + .delay = 2, + .matrix = mxckpd_keycodes, +}; + +static struct resource mxc_kpp_resources[] = { + [0] = { + .start = MXC_INT_KPP, + .end = MXC_INT_KPP, + .flags = IORESOURCE_IRQ, + } +}; + +/* mxc keypad driver */ +static struct platform_device mxc_keypad_device = { + .name = "mxc_keypad", + .id = 0, + .num_resources = ARRAY_SIZE(mxc_kpp_resources), + .resource = mxc_kpp_resources, + .dev = { + .release = mxc_nop_release, + .platform_data = &evb_6_by_6_keypad, + }, +}; + +static void mxc_init_keypad(void) +{ + (void)platform_device_register(&mxc_keypad_device); +} +#else +static inline void mxc_init_keypad(void) +{ +} +#endif + +/* MTD NOR flash */ + +#if defined(CONFIG_MTD_MXC) || defined(CONFIG_MTD_MXC_MODULE) + +static struct mtd_partition mxc_nor_partitions[] = { + { + .name = "Bootloader", + .size = 512 * 1024, + .offset = 0x00000000, + .mask_flags = MTD_WRITEABLE /* force read-only */ + }, + { + .name = "nor.Kernel", + .size = 2 * 1024 * 1024, + .offset = MTDPART_OFS_APPEND, + .mask_flags = 0}, + { + .name = "nor.userfs", + .size = 14 * 1024 * 1024, + .offset = MTDPART_OFS_APPEND, + .mask_flags = 0}, + { + .name = "nor.rootfs", + .size = 12 * 1024 * 1024, + .offset = MTDPART_OFS_APPEND, + .mask_flags = MTD_WRITEABLE}, + { + .name = "FIS directory", + .size = 12 * 1024, + .offset = 0x01FE0000, + .mask_flags = MTD_WRITEABLE /* force read-only */ + }, + { + .name = "Redboot config", + .size = MTDPART_SIZ_FULL, + .offset = 0x01FFF000, + .mask_flags = MTD_WRITEABLE /* force read-only */ + }, +}; + +static struct flash_platform_data mxc_flash_data = { + .map_name = "cfi_probe", + .width = 2, + .parts = mxc_nor_partitions, + .nr_parts = ARRAY_SIZE(mxc_nor_partitions), +}; + +static struct resource mxc_flash_resource = { + .start = 0xc0000000, + .end = 0xc0000000 + 0x02000000 - 1, + .flags = IORESOURCE_MEM, + +}; + +static struct platform_device mxc_nor_mtd_device = { + .name = "mxc_nor_flash", + .id = 0, + .dev = { + .release = mxc_nop_release, + .platform_data = &mxc_flash_data, + }, + .num_resources = 1, + .resource = &mxc_flash_resource, +}; + +static void mxc_init_nor_mtd(void) +{ + (void)platform_device_register(&mxc_nor_mtd_device); +} +#else +static void mxc_init_nor_mtd(void) +{ +} +#endif + +/* MTD NAND flash */ + +#if defined(CONFIG_MTD_NAND_MXC) || defined(CONFIG_MTD_NAND_MXC_MODULE) + +static struct mtd_partition mxc_nand_partitions[4] = { + { + .name = "nand.bootloader", + .offset = 0, + .size = 1024 * 1024}, + { + .name = "nand.kernel", + .offset = MTDPART_OFS_APPEND, + .size = 5 * 1024 * 1024}, + { + .name = "nand.rootfs", + .offset = MTDPART_OFS_APPEND, + .size = 22 * 1024 * 1024}, + { + .name = "nand.userfs", + .offset = MTDPART_OFS_APPEND, + .size = MTDPART_SIZ_FULL}, +}; + +static struct flash_platform_data mxc_nand_data = { + .parts = mxc_nand_partitions, + .nr_parts = ARRAY_SIZE(mxc_nand_partitions), + .width = 1, +}; + +static struct platform_device mxc_nand_mtd_device = { + .name = "mxc_nand_flash", + .id = 0, + .dev = { + .release = mxc_nop_release, + .platform_data = &mxc_nand_data, + }, +}; + +static void mxc_init_nand_mtd(void) +{ + (void)platform_device_register(&mxc_nand_mtd_device); +} +#else +static inline void mxc_init_nand_mtd(void) +{ +} +#endif + +#if defined(CONFIG_FB_MXC_SYNC_PANEL) || defined(CONFIG_FB_MXC_SYNC_PANEL_MODULE) +static const char fb_default_mode[] = "Sharp-QVGA"; + +/* mxc lcd driver */ +static struct platform_device mxc_fb_device = { + .name = "mxc_sdc_fb", + .id = 0, + .dev = { + .release = mxc_nop_release, + .platform_data = &fb_default_mode, + .coherent_dma_mask = 0xFFFFFFFF, + }, +}; + +static void mxc_init_fb(void) +{ + (void)platform_device_register(&mxc_fb_device); +} +#else +static inline void mxc_init_fb(void) +{ +} +#endif + +#if defined(CONFIG_BACKLIGHT_MXC) +static struct platform_device mxcbl_devices[] = { +#if defined(CONFIG_BACKLIGHT_MXC_PMIC) || defined(CONFIG_BACKLIGHT_MXC_PMIC_MODULE) + { + .name = "mxc_pmic_bl", + .id = 0, + .dev = { + .platform_data = (void *)-1, /* DISP # for this backlight */ + }, + }, + { + .name = "mxc_pmic_bl", + .id = 1, + .dev = { + .platform_data = (void *)0, /* DISP # for this backlight */ + }, + }, +#endif +#if defined(CONFIG_BACKLIGHT_MXC_LCDC) || defined(CONFIG_BACKLIGHT_MXC_LCDC_MODULE) + { + .name = "mxc_lcdc_bl", + .id = 0, + .dev = { + .platform_data = (void *)3, /* DISP # for this backlight */ + }, + }, +#endif +}; +static inline void mxc_init_bl(void) +{ + int i; + for (i = 0; i < ARRAY_SIZE(mxcbl_devices); i++) { + platform_device_register(&mxcbl_devices[i]); + } +} +#else +static inline void mxc_init_bl(void) +{ +} +#endif + +static struct spi_board_info mxc_spi_board_info[] __initdata = { + { + .modalias = "pmic_spi", + .irq = IOMUX_TO_IRQ(MX27_PIN_TOUT), + .max_speed_hz = 4000000, + .bus_num = 1, + .chip_select = 0, + }, +}; + +#if 0 +#define MXC_CARD_DEBUG +#endif + +static const int pbc_card_bit[4][3] = { + /* BSTAT IMR enable IMR removal */ + {PBC_BSTAT_SD2_DET, PBC_INTR_SD2_EN, PBC_INTR_SD2_R_EN}, + {PBC_BSTAT_SD3_DET, PBC_INTR_SD3_EN, PBC_INTR_SD3_R_EN}, + {PBC_BSTAT_MS_DET, PBC_INTR_MS_EN, PBC_INTR_MS_R_EN}, + {PBC_BSTAT_SD1_DET, PBC_INTR_SD1_EN, PBC_INTR_SD1_R_EN}, +}; + +/*! + * Check if a SD card has been inserted or not. + * + * @param num a card number as defined in \b enum \b mxc_card_no + * @return 0 if a card is not present; non-zero otherwise. + */ +int mxc_card_detected(enum mxc_card_no num) +{ + u32 status; + + status = __raw_readw(PBC_BSTAT1_REG); + return ((status & MXC_BSTAT_BIT(num)) == 0); +} + +/* + * Check if there is any state change by reading the IMR register and the + * previous and current states of the board status register (offset 0x28). + * A state change is defined to be card insertion OR removal. So the driver + * may have to call the mxc_card_detected() function to see if it is card + * insertion or removal. + * + * @param mask current IMR value + * @param s0 previous status register value (offset 0x28) + * @param s1 current status register value (offset 0x28) + * + * @return 0 if no card status change OR the corresponding bits in the IMR + * (passed in as 'mask') is NOT set. + * A non-zero value indicates some card state changes. For example, + * 0b0001 means SD3 has a card state change (bit0 is set) AND its + * associated insertion or removal bits in IMR is SET. + * 0b0100 means SD1 has a card state change (bit2 is set) AND its + * associated insertion or removal bits in IMR is SET. + * 0b1001 means both MS and SD3 have state changes + */ +static u32 mxc_card_state_changed(u32 mask, u32 s0, u32 s1) +{ + u32 i, retval = 0; + u32 stat = (s0 ^ s1) & 0x7800; + + if (stat == 0) + return 0; + + for (i = MXC_CARD_MIN; i <= MXC_CARD_MAX; i++) { + if ((stat & pbc_card_bit[i][0]) != 0 && + (mask & (pbc_card_bit[i][1] | pbc_card_bit[i][2])) != 0) { + retval |= 1 << i; + } + } +#ifdef MXC_CARD_DEBUG + printk(KERN_INFO "\nmask=%x, s0=%x, s1=%x\n", mask, s0, s1); + printk(KERN_INFO "retval=%x, stat=%x\n", retval, stat); +#endif + return retval; +} + +/*! + * Interrupt handler for the expio (CPLD) to deal with interrupts from + * FEC, external UART, CS8900 Ethernet and SD cards, etc. + */ +static void mxc_expio_irq_handler(u32 irq, struct irq_desc *desc) +{ + u32 imr, card_int, i; + u32 int_valid; + u32 expio_irq; + u32 stat = __raw_readw(PBC_BSTAT1_REG); + + desc->chip->mask(irq); /* irq = gpio irq number */ + + imr = __raw_readw(PBC_INTMASK_SET_REG); + + card_int = mxc_card_state_changed(imr, mxc_card_status, stat); + mxc_card_status = stat; + + if (card_int != 0) { + for (i = MXC_CARD_MIN; i <= MXC_CARD_MAX; i++) { + if ((card_int & (1 << i)) != 0) { + pr_debug("card no %d state changed\n", i); + } + } + } + + /* Bits defined in PBC_INTSTATUS_REG at 0x2C */ + int_valid = __raw_readw(PBC_INTSTATUS_REG) & imr; + /* combined with the card interrupt valid information */ + int_valid = (int_valid & 0x0F8E) | (card_int << PBC_INTR_SD2_EN_BIT); + + if (unlikely(!int_valid)) { + pr_debug("\nEXPIO: Spurious interrupt:0x%0x\n\n", int_valid); + pr_debug("CPLD IMR(0x38)=0x%x, BSTAT1(0x28)=0x%x\n", imr, stat); + goto out; + } + + expio_irq = MXC_EXP_IO_BASE; + for (; int_valid != 0; int_valid >>= 1, expio_irq++) { + struct irq_desc *d; + if ((int_valid & 1) == 0) + continue; + d = irq_desc + expio_irq; + if (unlikely(!(d->handle_irq))) { + printk(KERN_ERR "\nEXPIO irq: %d unhandeled\n", + expio_irq); + BUG(); /* oops */ + } + d->handle_irq(expio_irq, d); + } + + out: + desc->chip->ack(irq); + desc->chip->unmask(irq); +} + +#ifdef MXC_CARD_DEBUG + +static irqreturn_t mxc_sd_test_handler(int irq, void *desc) +{ + int s = -1; + + printk(KERN_INFO "%s(irq=%d) for ", __FUNCTION__, irq); + if (irq == EXPIO_INT_SD1_EN) { + printk(KERN_INFO "SD1"); + s = MXC_CARD_SD1; + } else if (irq == EXPIO_INT_SD2_EN) { + printk(KERN_INFO "SD2"); + s = MXC_CARD_SD2; + } else if (irq == EXPIO_INT_SD3_EN) { + printk(KERN_INFO "SD3"); + s = MXC_CARD_SD3; + } else if (irq == EXPIO_INT_MS_EN) { + printk(KERN_INFO "MS"); + s = MXC_CARD_MS; + } else { + printk(KERN_INFO "None!!!!"); + } + if (mxc_card_detected(s)) { + printk(KERN_INFO " inserted\n"); + } else { + printk(KERN_INFO " removed\n"); + } + + return IRQ_HANDLED; +} +#endif /* MXC_CARD_DEBUG */ + +/* + * Disable an expio pin's interrupt by setting the bit in the imr. + * @param irq an expio virtual irq number + */ +static void expio_mask_irq(u32 irq) +{ + u32 expio = MXC_IRQ_TO_EXPIO(irq); + + /* mask the interrupt */ + if (irq < EXPIO_INT_SD2_EN) { + __raw_writew(1 << expio, PBC_INTMASK_CLEAR_REG); + } else { + irq -= EXPIO_INT_SD2_EN; + /* clear both SDx_EN and SDx_R_EN bits */ + __raw_writew((pbc_card_bit[irq][1] | pbc_card_bit[irq][2]), + PBC_INTMASK_CLEAR_REG); + } +} + +/* + * Acknowledge an expanded io pin's interrupt by clearing the bit in the isr. + * @param irq an expanded io virtual irq number + */ +static void expio_ack_irq(u32 irq) +{ + u32 expio = MXC_IRQ_TO_EXPIO(irq); + /* clear the interrupt status */ + __raw_writew(1 << expio, PBC_INTSTATUS_REG); + /* mask the interrupt */ + expio_mask_irq(irq); +} + +/* + * Enable a expio pin's interrupt by clearing the bit in the imr. + * @param irq an expio virtual irq number + */ +static void expio_unmask_irq(u32 irq) +{ + u32 expio = MXC_IRQ_TO_EXPIO(irq); + + /* unmask the interrupt */ + if (irq < EXPIO_INT_SD2_EN) { + if (irq == EXPIO_INT_XUART_INTA) { + /* Set 8250 MCR register bit 3 - Forces the INT (A-B + * outputs to the active mode and sets OP2 to logic 0. + * This is needed to avoid spurious int caused by the + * internal CPLD pull-up for the interrupt pin. + */ + u16 val = __raw_readw(MXC_LL_EXTUART_VADDR + 8); + __raw_writew(val | 0x8, MXC_LL_EXTUART_VADDR + 8); + } + __raw_writew(1 << expio, PBC_INTMASK_SET_REG); + } else { + irq -= EXPIO_INT_SD2_EN; + + if (mxc_card_detected(irq)) { + __raw_writew(pbc_card_bit[irq][2], PBC_INTMASK_SET_REG); + } else { + __raw_writew(pbc_card_bit[irq][1], PBC_INTMASK_SET_REG); + } + } +} + +static struct irq_chip expio_irq_chip = { + .ack = expio_ack_irq, + .mask = expio_mask_irq, + .unmask = expio_unmask_irq, +}; + +static int __init mxc_expio_init(void) +{ + int i, ver; + + ver = (__raw_readw(PBC_VERSION_REG) >> 8) & 0xFF; + if ((ver & 0x80) != 0) { + pr_info("MX27 ADS EXPIO(CPLD) hardware\n"); + pr_info("CPLD version: 0x%x\n", ver); + } else { + mxc_board_is_ads = 0; + ver &= 0x0F; + pr_info("MX27 EVB EXPIO(CPLD) hardware\n"); + if (ver == 0xF || ver <= MXC_CPLD_VER_1_50) + pr_info("Wrong CPLD version: %d\n", ver); + else { + pr_info("CPLD version: %d\n", ver); + } + } + + mxc_card_status = __raw_readw(PBC_BSTAT1_REG); + +#ifdef MXC_CARD_DEBUG + for (i = MXC_CARD_MIN; i <= MXC_CARD_MAX; i++) { + if (mxc_card_detected(i)) { + pr_info("Card %d is detected\n", 3 - i); + } + } +#endif + /* + * Configure INT line as GPIO input + */ + gpio_config_mux(MX27_PIN_TIN, GPIO_MUX_GPIO); + gpio_request(IOMUX_TO_GPIO(MX27_PIN_TIN), NULL); + gpio_direction_input(IOMUX_TO_GPIO(MX27_PIN_TIN)); + + /* disable the interrupt and clear the status */ + __raw_writew(0xFFFF, PBC_INTMASK_CLEAR_REG); + __raw_writew(0xFFFF, PBC_INTSTATUS_REG); + + for (i = MXC_EXP_IO_BASE; i < (MXC_EXP_IO_BASE + MXC_MAX_EXP_IO_LINES); + i++) { + set_irq_chip(i, &expio_irq_chip); + set_irq_handler(i, handle_level_irq); + set_irq_flags(i, IRQF_VALID); + } + set_irq_type(EXPIO_PARENT_INT, IRQF_TRIGGER_HIGH); + set_irq_chained_handler(EXPIO_PARENT_INT, mxc_expio_irq_handler); + + return 0; +} + +#if defined(CONFIG_SERIAL_8250) || defined(CONFIG_SERIAL_8250_MODULE) + +/*! + * The serial port definition structure. The fields contain: + * {UART, CLK, PORT, IRQ, FLAGS} + */ +static struct plat_serial8250_port serial_platform_data[] = { + { + .membase = (void __iomem *)(CS4_BASE_ADDR_VIRT + 0x20000), + .mapbase = (unsigned long)(CS4_BASE_ADDR + 0x20000), + .irq = EXPIO_INT_XUART_INTA, + .uartclk = 3686400, + .regshift = 1, + .iotype = UPIO_MEM, + .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_AUTO_IRQ, + /*.pm = serial_platform_pm, */ + }, + {}, +}; + +/*! + * REVISIT: document me + */ +static struct platform_device serial_device = { + .name = "serial8250", + .id = 0, + .dev = { + .platform_data = &serial_platform_data[0], + }, +}; + +/*! + * REVISIT: document me + */ +static int __init mxc_init_extuart(void) +{ + int value; + /*reset ext uart in cpld */ + __raw_writew(PBC_BCTRL1_URST, PBC_BCTRL1_SET_REG); + /*delay some time for reset finish */ + for (value = 0; value < 1000; value++) ; + __raw_writew(PBC_BCTRL1_URST, PBC_BCTRL1_CLEAR_REG); + return platform_device_register(&serial_device); +} +#else +static inline int mxc_init_extuart(void) +{ + return 0; +} +#endif + +#if (defined(CONFIG_MXC_PMIC_MC13783) || \ + defined(CONFIG_MXC_PMIC_MC13783_MODULE)) \ + && (defined(CONFIG_SND_MXC_PMIC) || defined(CONFIG_SND_MXC_PMIC_MODULE)) +extern void gpio_ssi_active(int ssi_num); + +static void __init mxc_init_pmic_audio(void) +{ + struct clk *ckih_clk; + struct clk *cko_clk; + + /* Enable 26 mhz clock on CKO1 for PMIC audio */ + ckih_clk = clk_get(NULL, "ckih"); + cko_clk = clk_get(NULL, "clko_clk"); + if (IS_ERR(ckih_clk) || IS_ERR(cko_clk)) { + printk(KERN_ERR "Unable to set CLKO output to CKIH\n"); + } else { + clk_set_parent(cko_clk, ckih_clk); + clk_set_rate(cko_clk, clk_get_rate(ckih_clk)); + clk_enable(cko_clk); + } + clk_put(ckih_clk); + clk_put(cko_clk); + + gpio_ssi_active(0); + gpio_ssi_active(1); +} +#else +static void __inline mxc_init_pmic_audio(void) +{ +} +#endif + +/* IDE device data */ +#if defined(CONFIG_BLK_DEV_IDE_MXC) || defined(CONFIG_BLK_DEV_IDE_MXC_MODULE) + +/*! Platform Data for MXC IDE */ +static struct mxc_ide_platform_data mxc_ide_data = { + .power_drive = NULL, + .power_io = NULL, +}; + +static struct platform_device mxc_ide_device = { + .name = "mxc_ide", + .id = 0, + .dev = { + .release = mxc_nop_release, + .platform_data = &mxc_ide_data, + }, +}; + +static inline void mxc_init_ide(void) +{ + if (platform_device_register(&mxc_ide_device) < 0) + printk(KERN_ERR "Error: Registering the ide.\n"); +} +#else +static inline void mxc_init_ide(void) +{ +} +#endif + +static __init void mxc_board_init(void) +{ + pr_info("AIPI VA base: 0x%x\n", IO_ADDRESS(AIPI_BASE_ADDR)); + mxc_cpu_common_init(); + early_console_setup(saved_command_line); + mxc_register_gpios(); + mxc_expio_init(); + mxc_init_keypad(); + mxc_init_nor_mtd(); + mxc_init_nand_mtd(); + mxc_init_extuart(); + mxc_init_pmic_audio(); +#ifdef MXC_CARD_DEBUG + request_irq(EXPIO_INT_SD1_EN, mxc_sd_test_handler, 0, "SD_card1", NULL); + request_irq(EXPIO_INT_SD2_EN, mxc_sd_test_handler, 0, "SD_card2", NULL); + request_irq(EXPIO_INT_SD3_EN, mxc_sd_test_handler, 0, "SD_card3", NULL); + request_irq(EXPIO_INT_MS_EN, mxc_sd_test_handler, 0, "MS_card", NULL); +#endif + + spi_register_board_info(mxc_spi_board_info, + ARRAY_SIZE(mxc_spi_board_info)); + + mxc_init_fb(); + mxc_init_bl(); + mxc_init_ide(); +} + +static void __init fixup_mxc_board(struct machine_desc *desc, struct tag *tags, + char **cmdline, struct meminfo *mi) +{ +#ifdef CONFIG_KGDB_8250 + int i; + for (i = 0; + i < + (sizeof(serial_platform_data) / sizeof(serial_platform_data[0])); + i += 1) + kgdb8250_add_platform_port(i, &serial_platform_data[i]); +#endif + + mxc_cpu_init(); + /* Store command line for use on mxc_board_init */ + strcpy(command_line, *cmdline); + +#ifdef CONFIG_DISCONTIGMEM + do { + int nid; + mi->nr_banks = MXC_NUMNODES; + for (nid = 0; nid < mi->nr_banks; nid++) { + SET_NODE(mi, nid); + } + } while (0); +#endif +} + +EXPORT_SYMBOL(mxc_card_detected); +EXPORT_SYMBOL(mxc_board_is_ads); + +static void __init mx27ads_timer_init(void) +{ + mxc_clocks_init(32768, 0, board_get_ckih_rate(), 0); + mxc_timer_init("gpt_clk.0"); +} + +static struct sys_timer mxc_timer = { + .init = mx27ads_timer_init, +}; + +/* + * The following uses standard kernel macros define in arch.h in order to + * initialize __mach_desc_MX27ADS data structure. + */ +/* *INDENT-OFF* */ +MACHINE_START(MX27ADS, "Freescale i.MX27ADS") + /* maintainer: Freescale Semiconductor, Inc. */ +#ifdef CONFIG_SERIAL_8250_CONSOLE + .phys_io = CS4_BASE_ADDR, + .io_pg_offst = ((CS4_BASE_ADDR_VIRT) >> 18) & 0xfffc, +#else + .phys_io = AIPI_BASE_ADDR, + .io_pg_offst = ((AIPI_BASE_ADDR_VIRT) >> 18) & 0xfffc, +#endif + .boot_params = PHYS_OFFSET + 0x100, + .fixup = fixup_mxc_board, + .map_io = mxc_map_io, + .init_irq = mxc_init_irq, + .init_machine = mxc_board_init, + .timer = &mxc_timer, +MACHINE_END diff --git a/arch/arm/mach-mx27/mx27ads_gpio.c b/arch/arm/mach-mx27/mx27ads_gpio.c new file mode 100644 index 000000000000..a71d15725d0b --- /dev/null +++ b/arch/arm/mach-mx27/mx27ads_gpio.c @@ -0,0 +1,1266 @@ +/* + * Copyright 2004-2009 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/errno.h> +#include <linux/module.h> +#include <linux/device.h> +#include <linux/io.h> +#include <mach/hardware.h> +#include <mach/gpio.h> + +#include "board-mx27ads.h" +#include "gpio_mux.h" +#include "crm_regs.h" + +static int g_uart_activated[MXC_UART_NR] = { 0, 0, 0, 0, 0, 0 }; + +/*! + * @file mach-mx27/mx27ads_gpio.c + * + * @brief This file contains all the GPIO setup functions for the board. + * + * @ingroup GPIO_MX27 + */ + +/*! + * Setup GPIO for a UART port to be active + * + * @param port a UART port + * @param no_irda indicates if the port is used for SIR + */ +void gpio_uart_active(int port, int no_irda) +{ + if (port < 0 || port >= MXC_UART_NR) { + pr_info("Wrong port number: %d\n", port); + BUG(); + } + + if (g_uart_activated[port]) { + pr_info("UART %d has been activated multi-times\n", port + 1); + return; + } + g_uart_activated[port] = 1; + + switch (port) { + case 0: + gpio_request_mux(MX27_PIN_UART1_TXD, GPIO_MUX_PRIMARY); + gpio_request_mux(MX27_PIN_UART1_RXD, GPIO_MUX_PRIMARY); + gpio_request_mux(MX27_PIN_UART1_CTS, GPIO_MUX_PRIMARY); + gpio_request_mux(MX27_PIN_UART1_RTS, GPIO_MUX_PRIMARY); + break; + case 1: + gpio_request_mux(MX27_PIN_UART2_TXD, GPIO_MUX_PRIMARY); + gpio_request_mux(MX27_PIN_UART2_RXD, GPIO_MUX_PRIMARY); + gpio_request_mux(MX27_PIN_UART2_CTS, GPIO_MUX_PRIMARY); + gpio_request_mux(MX27_PIN_UART2_RTS, GPIO_MUX_PRIMARY); + break; + case 2: + gpio_request_mux(MX27_PIN_UART3_TXD, GPIO_MUX_PRIMARY); + gpio_request_mux(MX27_PIN_UART3_RXD, GPIO_MUX_PRIMARY); + gpio_request_mux(MX27_PIN_UART3_CTS, GPIO_MUX_PRIMARY); + gpio_request_mux(MX27_PIN_UART3_RTS, GPIO_MUX_PRIMARY); + + /* Enable IRDA in CPLD */ + __raw_writew(PBC_BCTRL2_IRDA_EN, PBC_BCTRL2_CLEAR_REG); + break; + case 3: + gpio_request_mux(MX27_PIN_USBH1_TXDM, GPIO_MUX_ALT); + gpio_request_mux(MX27_PIN_USBH1_RXDP, GPIO_MUX_ALT); + gpio_request_mux(MX27_PIN_USBH1_TXDP, GPIO_MUX_ALT); + gpio_request_mux(MX27_PIN_USBH1_FS, GPIO_MUX_ALT); + break; + case 4: + gpio_request_mux(MX27_PIN_CSI_D6, GPIO_MUX_ALT); + gpio_request_mux(MX27_PIN_CSI_D7, GPIO_MUX_ALT); + gpio_request_mux(MX27_PIN_CSI_VSYNC, GPIO_MUX_ALT); + gpio_request_mux(MX27_PIN_CSI_HSYNC, GPIO_MUX_ALT); + break; + case 5: + gpio_request_mux(MX27_PIN_CSI_D0, GPIO_MUX_ALT); + gpio_request_mux(MX27_PIN_CSI_D1, GPIO_MUX_ALT); + gpio_request_mux(MX27_PIN_CSI_D2, GPIO_MUX_ALT); + gpio_request_mux(MX27_PIN_CSI_D3, GPIO_MUX_ALT); + break; + default: + break; + } +} + +/*! + * Setup GPIO for a UART port to be inactive + * + * @param port a UART port + * @param no_irda indicates if the port is used for SIR + */ +void gpio_uart_inactive(int port, int no_irda) +{ + if (port < 0 || port >= MXC_UART_NR) { + pr_info("Wrong port number: %d\n", port); + BUG(); + } + + if (g_uart_activated[port] == 0) { + pr_info("UART %d has not been activated \n", port + 1); + return; + } + g_uart_activated[port] = 0; + + switch (port) { + case 0: + gpio_free_mux(MX27_PIN_UART1_TXD); + gpio_free_mux(MX27_PIN_UART1_RXD); + gpio_free_mux(MX27_PIN_UART1_CTS); + gpio_free_mux(MX27_PIN_UART1_RTS); + break; + case 1: + gpio_free_mux(MX27_PIN_UART2_TXD); + gpio_free_mux(MX27_PIN_UART2_RXD); + gpio_free_mux(MX27_PIN_UART2_CTS); + gpio_free_mux(MX27_PIN_UART2_RTS); + break; + case 2: + gpio_free_mux(MX27_PIN_UART3_TXD); + gpio_free_mux(MX27_PIN_UART3_RXD); + gpio_free_mux(MX27_PIN_UART3_CTS); + gpio_free_mux(MX27_PIN_UART3_RTS); + + /* Disable IRDA in CPLD */ + __raw_writew(PBC_BCTRL2_IRDA_EN, PBC_BCTRL2_SET_REG); + break; + case 3: + gpio_free_mux(MX27_PIN_USBH1_TXDM); + gpio_free_mux(MX27_PIN_USBH1_RXDP); + gpio_free_mux(MX27_PIN_USBH1_TXDP); + gpio_free_mux(MX27_PIN_USBH1_FS); + break; + case 4: + gpio_free_mux(MX27_PIN_CSI_D6); + gpio_free_mux(MX27_PIN_CSI_D7); + gpio_free_mux(MX27_PIN_CSI_VSYNC); + gpio_free_mux(MX27_PIN_CSI_HSYNC); + break; + case 5: + gpio_free_mux(MX27_PIN_CSI_D0); + gpio_free_mux(MX27_PIN_CSI_D1); + gpio_free_mux(MX27_PIN_CSI_D2); + gpio_free_mux(MX27_PIN_CSI_D3); + break; + default: + break; + } +} + +void gpio_power_key_active(void) +{ +} +EXPORT_SYMBOL(gpio_power_key_active); + +/*! + * Configure the IOMUX GPR register to receive shared SDMA UART events + * + * @param port a UART port + */ +void config_uartdma_event(int port) +{ + return; +} + +static int usbh1_hs_active; +/*! + * Setup GPIO for USB, Total 34 signals + * PIN Configuration for USBOTG: High/Full speed OTG + * PE2,PE1,PE0,PE24,PE25 -- PRIMARY + PC7 - PC13 -- PRIMARY + PB23,PB24 -- PRIMARY + + * PIN Configuration for USBH2: : High/Full/Low speed host + * PA0 - PA4 -- PRIMARY + PD19, PD20,PD21,PD22,PD23,PD24,PD26 --Alternate (SECONDARY) + + * PIN Configuration for USBH1: Full/low speed host + * PB25 - PB31 -- PRIMARY + PB22 -- PRIMARY + */ +int gpio_usbh1_active(void) +{ + if (usbh1_hs_active) + return 0; + + if (gpio_request_mux(MX27_PIN_USBH1_SUSP, GPIO_MUX_PRIMARY) || + gpio_request_mux(MX27_PIN_USBH1_RCV, GPIO_MUX_PRIMARY) || + gpio_request_mux(MX27_PIN_USBH1_FS, GPIO_MUX_PRIMARY) || + gpio_request_mux(MX27_PIN_USBH1_OE_B, GPIO_MUX_PRIMARY) || + gpio_request_mux(MX27_PIN_USBH1_TXDM, GPIO_MUX_PRIMARY) || + gpio_request_mux(MX27_PIN_USBH1_TXDP, GPIO_MUX_PRIMARY) || + gpio_request_mux(MX27_PIN_USBH1_RXDM, GPIO_MUX_PRIMARY) || + gpio_request_mux(MX27_PIN_USBH1_RXDP, GPIO_MUX_PRIMARY)) + return -EINVAL; + + __raw_writew(PBC_BCTRL3_FSH_MOD, PBC_BCTRL3_CLEAR_REG); + __raw_writew(PBC_BCTRL3_FSH_VBUS_EN, PBC_BCTRL3_CLEAR_REG); + usbh1_hs_active = 1; + return 0; +} +void gpio_usbh1_inactive(void) +{ + if (usbh1_hs_active == 0) + return; + + gpio_free_mux(MX27_PIN_USBH1_SUSP); + gpio_free_mux(MX27_PIN_USBH1_RCV); + gpio_free_mux(MX27_PIN_USBH1_FS); + gpio_free_mux(MX27_PIN_USBH1_OE_B); + gpio_free_mux(MX27_PIN_USBH1_TXDM); + gpio_free_mux(MX27_PIN_USBH1_TXDP); + gpio_free_mux(MX27_PIN_USBH1_RXDM); + gpio_free_mux(MX27_PIN_USBH1_RXDP); + __raw_writew(PBC_BCTRL3_FSH_VBUS_EN, PBC_BCTRL3_SET_REG); + + usbh1_hs_active = 0; +} + +static int usbh2_hs_active; +/* + * conflicts with CSPI1 (MC13783) and CSPI2 (Connector) + */ +int gpio_usbh2_active(void) +{ + if (usbh2_hs_active) + return 0; + + if (gpio_set_puen(MX27_PIN_USBH2_CLK, 0) || + gpio_set_puen(MX27_PIN_USBH2_DIR, 0) || + gpio_set_puen(MX27_PIN_USBH2_DATA7, 0) || + gpio_set_puen(MX27_PIN_USBH2_NXT, 0) || + gpio_set_puen(MX27_PIN_USBH2_STP, 0) || + gpio_set_puen(MX27_PIN_CSPI2_SS2, 0) || + gpio_set_puen(MX27_PIN_CSPI2_SS1, 0) || + gpio_set_puen(MX27_PIN_CSPI2_SS0, 0) || + gpio_set_puen(MX27_PIN_CSPI2_SCLK, 0) || + gpio_set_puen(MX27_PIN_CSPI2_MISO, 0) || + gpio_set_puen(MX27_PIN_CSPI2_MOSI, 0) || + gpio_set_puen(MX27_PIN_CSPI1_SS2, 0)) + return -EINVAL; + + if (gpio_request_mux(MX27_PIN_USBH2_CLK, GPIO_MUX_PRIMARY) || + gpio_request_mux(MX27_PIN_USBH2_DIR, GPIO_MUX_PRIMARY) || + gpio_request_mux(MX27_PIN_USBH2_DATA7, GPIO_MUX_PRIMARY) || + gpio_request_mux(MX27_PIN_USBH2_NXT, GPIO_MUX_PRIMARY) || + gpio_request_mux(MX27_PIN_USBH2_STP, GPIO_MUX_PRIMARY) || + gpio_request_mux(MX27_PIN_CSPI2_SS2, GPIO_MUX_ALT) || + gpio_request_mux(MX27_PIN_CSPI2_SS1, GPIO_MUX_ALT) || + gpio_request_mux(MX27_PIN_CSPI2_SS0, GPIO_MUX_ALT) || + gpio_request_mux(MX27_PIN_CSPI2_SCLK, GPIO_MUX_ALT) || + gpio_request_mux(MX27_PIN_CSPI2_MISO, GPIO_MUX_ALT) || + gpio_request_mux(MX27_PIN_CSPI2_MOSI, GPIO_MUX_ALT) || + gpio_request_mux(MX27_PIN_CSPI1_SS2, GPIO_MUX_ALT)) + return -EINVAL; + + __raw_writew(PBC_BCTRL3_HSH_EN, PBC_BCTRL3_CLEAR_REG); + usbh2_hs_active = 1; + return 0; +} +void gpio_usbh2_inactive(void) +{ + if (usbh2_hs_active == 0) + return; + + gpio_free_mux(MX27_PIN_USBH2_CLK); + gpio_free_mux(MX27_PIN_USBH2_DIR); + gpio_free_mux(MX27_PIN_USBH2_DATA7); + gpio_free_mux(MX27_PIN_USBH2_NXT); + gpio_free_mux(MX27_PIN_USBH2_STP); + + gpio_free_mux(MX27_PIN_CSPI2_SS2); + gpio_free_mux(MX27_PIN_CSPI2_SS1); + gpio_free_mux(MX27_PIN_CSPI2_SS0); + gpio_free_mux(MX27_PIN_CSPI2_SCLK); + gpio_free_mux(MX27_PIN_CSPI2_MISO); + gpio_free_mux(MX27_PIN_CSPI2_MOSI); + gpio_free_mux(MX27_PIN_CSPI1_SS2); + + gpio_set_puen(MX27_PIN_USBH2_CLK, 1); + gpio_set_puen(MX27_PIN_USBH2_DIR, 1); + gpio_set_puen(MX27_PIN_USBH2_DATA7, 1); + gpio_set_puen(MX27_PIN_USBH2_NXT, 1); + gpio_set_puen(MX27_PIN_USBH2_STP, 1); + gpio_set_puen(MX27_PIN_CSPI2_SS2, 1); + gpio_set_puen(MX27_PIN_CSPI2_SS1, 1); + gpio_set_puen(MX27_PIN_CSPI2_SS0, 1); + gpio_set_puen(MX27_PIN_CSPI2_SCLK, 1); + gpio_set_puen(MX27_PIN_CSPI2_MISO, 1); + gpio_set_puen(MX27_PIN_CSPI2_MOSI, 1); + gpio_set_puen(MX27_PIN_CSPI1_SS2, 1); + __raw_writew(PBC_BCTRL3_HSH_EN, PBC_BCTRL3_SET_REG); + + usbh2_hs_active = 0; +} + +static int usbotg_hs_active; +int gpio_usbotg_hs_active(void) +{ + if (usbotg_hs_active) + return 0; + + if (gpio_request_mux(MX27_PIN_USBOTG_DATA5, GPIO_MUX_PRIMARY) || + gpio_request_mux(MX27_PIN_USBOTG_DATA6, GPIO_MUX_PRIMARY) || + gpio_request_mux(MX27_PIN_USBOTG_DATA0, GPIO_MUX_PRIMARY) || + gpio_request_mux(MX27_PIN_USBOTG_DATA2, GPIO_MUX_PRIMARY) || + gpio_request_mux(MX27_PIN_USBOTG_DATA1, GPIO_MUX_PRIMARY) || + gpio_request_mux(MX27_PIN_USBOTG_DATA3, GPIO_MUX_PRIMARY) || + gpio_request_mux(MX27_PIN_USBOTG_DATA4, GPIO_MUX_PRIMARY) || + + gpio_request_mux(MX27_PIN_USBOTG_DIR, GPIO_MUX_PRIMARY) || + gpio_request_mux(MX27_PIN_USBOTG_STP, GPIO_MUX_PRIMARY) || + gpio_request_mux(MX27_PIN_USBOTG_NXT, GPIO_MUX_PRIMARY) || + gpio_request_mux(MX27_PIN_USBOTG_CLK, GPIO_MUX_PRIMARY) || + gpio_request_mux(MX27_PIN_USBOTG_DATA7, GPIO_MUX_PRIMARY) || + + gpio_request_mux(MX27_PIN_USB_OC_B, GPIO_MUX_PRIMARY) || + gpio_request_mux(MX27_PIN_USB_PWR, GPIO_MUX_PRIMARY)) + return -EINVAL; + + __raw_writew(PBC_BCTRL3_OTG_HS_EN, PBC_BCTRL3_CLEAR_REG); + __raw_writew(PBC_BCTRL3_OTG_VBUS_EN, PBC_BCTRL3_CLEAR_REG); + + usbotg_hs_active = 1; + return 0; +} + +void gpio_usbotg_hs_inactive(void) +{ + if (usbotg_hs_active == 0) + return; + + gpio_free_mux(MX27_PIN_USBOTG_DATA5); + gpio_free_mux(MX27_PIN_USBOTG_DATA6); + gpio_free_mux(MX27_PIN_USBOTG_DATA0); + gpio_free_mux(MX27_PIN_USBOTG_DATA2); + gpio_free_mux(MX27_PIN_USBOTG_DATA1); + gpio_free_mux(MX27_PIN_USBOTG_DATA3); + gpio_free_mux(MX27_PIN_USBOTG_DATA4); + + gpio_free_mux(MX27_PIN_USBOTG_DIR); + gpio_free_mux(MX27_PIN_USBOTG_STP); + gpio_free_mux(MX27_PIN_USBOTG_NXT); + gpio_free_mux(MX27_PIN_USBOTG_CLK); + gpio_free_mux(MX27_PIN_USBOTG_DATA7); + + gpio_free_mux(MX27_PIN_USB_OC_B); + gpio_free_mux(MX27_PIN_USB_PWR); + __raw_writew(PBC_BCTRL3_OTG_HS_EN, PBC_BCTRL3_SET_REG); + + usbotg_hs_active = 0; +} + +int gpio_usbotg_fs_active(void) +{ + return gpio_usbotg_hs_active(); +} + +void gpio_usbotg_fs_inactive(void) +{ + gpio_usbotg_hs_inactive(); +} + +/*! + * end Setup GPIO for USB + * + */ + +/************************************************************************/ +/* for i2c gpio */ +/* I2C1: PD17,PD18 -- Primary */ +/* I2C2: PC5,PC6 -- Primary */ +/************************************************************************/ +/*! +* Setup GPIO for an I2C device to be active +* +* @param i2c_num an I2C device +*/ +void gpio_i2c_active(int i2c_num) +{ + switch (i2c_num) { + case 0: + gpio_request_mux(MX27_PIN_I2C_CLK, GPIO_MUX_PRIMARY); + gpio_request_mux(MX27_PIN_I2C_DATA, GPIO_MUX_PRIMARY); + break; + case 1: + gpio_request_mux(MX27_PIN_I2C2_SCL, GPIO_MUX_PRIMARY); + gpio_request_mux(MX27_PIN_I2C2_SDA, GPIO_MUX_PRIMARY); + break; + default: + printk(KERN_ERR "gpio_i2c_active no compatible I2C adapter\n"); + break; + } +} + +/*! + * * Setup GPIO for an I2C device to be inactive + * * + * * @param i2c_num an I2C device + */ +void gpio_i2c_inactive(int i2c_num) +{ + switch (i2c_num) { + case 0: + gpio_free_mux(MX27_PIN_I2C_CLK); + gpio_free_mux(MX27_PIN_I2C_DATA); + break; + case 1: + gpio_free_mux(MX27_PIN_I2C2_SCL); + gpio_free_mux(MX27_PIN_I2C2_SDA); + break; + default: + break; + } +} + +/*! + * Setup GPIO for a CSPI device to be active + * + * @param cspi_mod an CSPI device + */ +void gpio_spi_active(int cspi_mod) +{ + switch (cspi_mod) { + case 0: + /* SPI1 */ + gpio_request_mux(MX27_PIN_CSPI1_MOSI, GPIO_MUX_PRIMARY); + gpio_request_mux(MX27_PIN_CSPI1_MISO, GPIO_MUX_PRIMARY); + gpio_request_mux(MX27_PIN_CSPI1_SCLK, GPIO_MUX_PRIMARY); + gpio_request_mux(MX27_PIN_CSPI1_RDY, GPIO_MUX_PRIMARY); + gpio_request_mux(MX27_PIN_CSPI1_SS0, GPIO_MUX_PRIMARY); + gpio_request_mux(MX27_PIN_CSPI1_SS1, GPIO_MUX_PRIMARY); + gpio_request_mux(MX27_PIN_CSPI1_SS2, GPIO_MUX_PRIMARY); + break; + case 1: + /*SPI2 */ + gpio_request_mux(MX27_PIN_CSPI2_MOSI, GPIO_MUX_PRIMARY); + gpio_request_mux(MX27_PIN_CSPI2_MISO, GPIO_MUX_PRIMARY); + gpio_request_mux(MX27_PIN_CSPI2_SCLK, GPIO_MUX_PRIMARY); + gpio_request_mux(MX27_PIN_CSPI2_SS0, GPIO_MUX_PRIMARY); + gpio_request_mux(MX27_PIN_CSPI2_SS1, GPIO_MUX_PRIMARY); + gpio_request_mux(MX27_PIN_CSPI2_SS2, GPIO_MUX_PRIMARY); + break; + case 2: + /*SPI3 */ + gpio_request_mux(MX27_PIN_SD1_D0, GPIO_MUX_ALT); + gpio_request_mux(MX27_PIN_SD1_CMD, GPIO_MUX_ALT); + gpio_request_mux(MX27_PIN_SD1_CLK, GPIO_MUX_ALT); + gpio_request_mux(MX27_PIN_SD1_D3, GPIO_MUX_ALT); + break; + + default: + break; + } +} + +/*! + * Setup GPIO for a CSPI device to be inactive + * + * @param cspi_mod a CSPI device + */ +void gpio_spi_inactive(int cspi_mod) +{ + switch (cspi_mod) { + case 0: + /* SPI1 */ + gpio_free_mux(MX27_PIN_CSPI1_MOSI); + gpio_free_mux(MX27_PIN_CSPI1_MISO); + gpio_free_mux(MX27_PIN_CSPI1_SCLK); + gpio_free_mux(MX27_PIN_CSPI1_RDY); + gpio_free_mux(MX27_PIN_CSPI1_SS0); + gpio_free_mux(MX27_PIN_CSPI1_SS1); + gpio_free_mux(MX27_PIN_CSPI1_SS2); + break; + case 1: + /*SPI2 */ + gpio_free_mux(MX27_PIN_CSPI2_MOSI); + gpio_free_mux(MX27_PIN_CSPI2_MISO); + gpio_free_mux(MX27_PIN_CSPI2_SCLK); + gpio_free_mux(MX27_PIN_CSPI2_SS0); + gpio_free_mux(MX27_PIN_CSPI2_SS1); + gpio_free_mux(MX27_PIN_CSPI2_SS2); + break; + case 2: + /*SPI3 */ + gpio_free_mux(MX27_PIN_SD1_D0); + gpio_free_mux(MX27_PIN_SD1_CMD); + gpio_free_mux(MX27_PIN_SD1_CLK); + gpio_free_mux(MX27_PIN_SD1_D3); + break; + + default: + break; + } +} + +/*! + * Setup GPIO for a nand flash device to be active + * + */ +void gpio_nand_active(void) +{ + unsigned long reg; + reg = __raw_readl(IO_ADDRESS(SYSCTRL_BASE_ADDR) + SYS_FMCR); + reg &= ~(1 << 4); + __raw_writel(reg, IO_ADDRESS(SYSCTRL_BASE_ADDR) + SYS_FMCR); + + gpio_request_mux(MX27_PIN_NFRB, GPIO_MUX_PRIMARY); + gpio_request_mux(MX27_PIN_NFCE_B, GPIO_MUX_PRIMARY); + gpio_request_mux(MX27_PIN_NFWP_B, GPIO_MUX_PRIMARY); + gpio_request_mux(MX27_PIN_NFCLE, GPIO_MUX_PRIMARY); + gpio_request_mux(MX27_PIN_NFALE, GPIO_MUX_PRIMARY); + gpio_request_mux(MX27_PIN_NFRE_B, GPIO_MUX_PRIMARY); + gpio_request_mux(MX27_PIN_NFWE_B, GPIO_MUX_PRIMARY); +} + +/*! + * Setup GPIO for a nand flash device to be inactive + * + */ +void gpio_nand_inactive(void) +{ + gpio_free_mux(MX27_PIN_NFRB); + gpio_free_mux(MX27_PIN_NFCE_B); + gpio_free_mux(MX27_PIN_NFWP_B); + gpio_free_mux(MX27_PIN_NFCLE); + gpio_free_mux(MX27_PIN_NFALE); + gpio_free_mux(MX27_PIN_NFRE_B); + gpio_free_mux(MX27_PIN_NFWE_B); +} + +/*! + * Setup GPIO for CSI device to be active + * + */ +void gpio_sensor_active(void) +{ + gpio_request_mux(MX27_PIN_CSI_D0, GPIO_MUX_PRIMARY); + gpio_request_mux(MX27_PIN_CSI_D1, GPIO_MUX_PRIMARY); + gpio_request_mux(MX27_PIN_CSI_D2, GPIO_MUX_PRIMARY); + gpio_request_mux(MX27_PIN_CSI_D3, GPIO_MUX_PRIMARY); + gpio_request_mux(MX27_PIN_CSI_D4, GPIO_MUX_PRIMARY); + gpio_request_mux(MX27_PIN_CSI_MCLK, GPIO_MUX_PRIMARY); + gpio_request_mux(MX27_PIN_CSI_PIXCLK, GPIO_MUX_PRIMARY); + gpio_request_mux(MX27_PIN_CSI_D5, GPIO_MUX_PRIMARY); + gpio_request_mux(MX27_PIN_CSI_D6, GPIO_MUX_PRIMARY); + gpio_request_mux(MX27_PIN_CSI_D7, GPIO_MUX_PRIMARY); + gpio_request_mux(MX27_PIN_CSI_VSYNC, GPIO_MUX_PRIMARY); + gpio_request_mux(MX27_PIN_CSI_HSYNC, GPIO_MUX_PRIMARY); + +#ifdef CONFIG_MXC_CAMERA_MC521DA + __raw_writew(0x100, PBC_BCTRL2_SET_REG); +#else + __raw_writew(0x400, PBC_BCTRL2_SET_REG); +#endif +} + +void gpio_sensor_inactive(void) +{ + gpio_free_mux(MX27_PIN_CSI_D0); + gpio_free_mux(MX27_PIN_CSI_D1); + gpio_free_mux(MX27_PIN_CSI_D2); + gpio_free_mux(MX27_PIN_CSI_D3); + gpio_free_mux(MX27_PIN_CSI_D4); + gpio_free_mux(MX27_PIN_CSI_MCLK); + gpio_free_mux(MX27_PIN_CSI_PIXCLK); + gpio_free_mux(MX27_PIN_CSI_D5); + gpio_free_mux(MX27_PIN_CSI_D6); + gpio_free_mux(MX27_PIN_CSI_D7); + gpio_free_mux(MX27_PIN_CSI_VSYNC); + gpio_free_mux(MX27_PIN_CSI_HSYNC); + +#ifdef CONFIG_MXC_CAMERA_MC521DA + __raw_writew(0x100, PBC_BCTRL2_CLEAR_REG); +#else + __raw_writew(0x400, PBC_BCTRL2_CLEAR_REG); +#endif +} + +void gpio_sensor_reset(bool flag) +{ + u16 temp; + + if (flag) { + temp = 0x200; + __raw_writew(temp, PBC_BCTRL2_CLEAR_REG); + } else { + temp = 0x200; + __raw_writew(temp, PBC_BCTRL2_SET_REG); + } +} + +/*! + * Setup GPIO for LCDC device to be active + * + */ +void gpio_lcdc_active(void) +{ + gpio_request_mux(MX27_PIN_LSCLK, GPIO_MUX_PRIMARY); + gpio_request_mux(MX27_PIN_LD0, GPIO_MUX_PRIMARY); + gpio_request_mux(MX27_PIN_LD1, GPIO_MUX_PRIMARY); + gpio_request_mux(MX27_PIN_LD2, GPIO_MUX_PRIMARY); + gpio_request_mux(MX27_PIN_LD3, GPIO_MUX_PRIMARY); + gpio_request_mux(MX27_PIN_LD4, GPIO_MUX_PRIMARY); + gpio_request_mux(MX27_PIN_LD5, GPIO_MUX_PRIMARY); + gpio_request_mux(MX27_PIN_LD6, GPIO_MUX_PRIMARY); + gpio_request_mux(MX27_PIN_LD7, GPIO_MUX_PRIMARY); + gpio_request_mux(MX27_PIN_LD8, GPIO_MUX_PRIMARY); + gpio_request_mux(MX27_PIN_LD9, GPIO_MUX_PRIMARY); + gpio_request_mux(MX27_PIN_LD10, GPIO_MUX_PRIMARY); + gpio_request_mux(MX27_PIN_LD11, GPIO_MUX_PRIMARY); + gpio_request_mux(MX27_PIN_LD12, GPIO_MUX_PRIMARY); + gpio_request_mux(MX27_PIN_LD13, GPIO_MUX_PRIMARY); + gpio_request_mux(MX27_PIN_LD14, GPIO_MUX_PRIMARY); + gpio_request_mux(MX27_PIN_LD15, GPIO_MUX_PRIMARY); + gpio_request_mux(MX27_PIN_LD16, GPIO_MUX_PRIMARY); + gpio_request_mux(MX27_PIN_LD17, GPIO_MUX_PRIMARY); + gpio_request_mux(MX27_PIN_REV, GPIO_MUX_PRIMARY); + gpio_request_mux(MX27_PIN_CLS, GPIO_MUX_PRIMARY); + gpio_request_mux(MX27_PIN_PS, GPIO_MUX_PRIMARY); + gpio_request_mux(MX27_PIN_SPL_SPR, GPIO_MUX_PRIMARY); + gpio_request_mux(MX27_PIN_HSYNC, GPIO_MUX_PRIMARY); + gpio_request_mux(MX27_PIN_VSYNC, GPIO_MUX_PRIMARY); + gpio_request_mux(MX27_PIN_CONTRAST, GPIO_MUX_PRIMARY); + gpio_request_mux(MX27_PIN_OE_ACD, GPIO_MUX_PRIMARY); +} + +/*! + * Setup GPIO for LCDC device to be inactive + * + */ +void gpio_lcdc_inactive(void) +{ + gpio_free_mux(MX27_PIN_LSCLK); + gpio_free_mux(MX27_PIN_LD0); + gpio_free_mux(MX27_PIN_LD1); + gpio_free_mux(MX27_PIN_LD2); + gpio_free_mux(MX27_PIN_LD3); + gpio_free_mux(MX27_PIN_LD4); + gpio_free_mux(MX27_PIN_LD5); + gpio_free_mux(MX27_PIN_LD6); + gpio_free_mux(MX27_PIN_LD7); + gpio_free_mux(MX27_PIN_LD8); + gpio_free_mux(MX27_PIN_LD9); + gpio_free_mux(MX27_PIN_LD10); + gpio_free_mux(MX27_PIN_LD11); + gpio_free_mux(MX27_PIN_LD12); + gpio_free_mux(MX27_PIN_LD13); + gpio_free_mux(MX27_PIN_LD14); + gpio_free_mux(MX27_PIN_LD15); + gpio_free_mux(MX27_PIN_LD16); + gpio_free_mux(MX27_PIN_LD17); + gpio_free_mux(MX27_PIN_REV); + gpio_free_mux(MX27_PIN_CLS); + gpio_free_mux(MX27_PIN_PS); + gpio_free_mux(MX27_PIN_SPL_SPR); + gpio_free_mux(MX27_PIN_HSYNC); + gpio_free_mux(MX27_PIN_VSYNC); + gpio_free_mux(MX27_PIN_CONTRAST); + gpio_free_mux(MX27_PIN_OE_ACD); +} + +/*! + * Setup GPIO PA25 low to start hard reset FS453 TV encoder + * + */ +void gpio_fs453_reset_low(void) +{ + gpio_free_mux(MX27_PIN_CLS); + if (gpio_request_mux(MX27_PIN_CLS, GPIO_MUX_GPIO)) { + printk(KERN_ERR "bug: request GPIO PA25 failed.\n"); + return; + } + + /* PA25 (CLS) as output */ + gpio_request(IOMUX_TO_GPIO(MX27_PIN_CLS), "cls"); + gpio_direction_output(IOMUX_TO_GPIO(MX27_PIN_CLS), 0); + gpio_config_mux(MX27_PIN_CLS, GPIO_MUX_GPIO); + gpio_set_value(IOMUX_TO_GPIO(MX27_PIN_CLS), 0); +} + +/*! + * Setup GPIO PA25 high to end hard reset FS453 TV encoder + * + */ +void gpio_fs453_reset_high(void) +{ + gpio_free_mux(MX27_PIN_CLS); + if (gpio_request_mux(MX27_PIN_CLS, GPIO_MUX_GPIO)) { + printk(KERN_ERR "bug: request GPIO PA25 failed.\n"); + return; + } + + /* PA25 (CLS) as output */ + gpio_request(IOMUX_TO_GPIO(MX27_PIN_CLS), "cls"); + gpio_direction_output(IOMUX_TO_GPIO(MX27_PIN_CLS), 0); + gpio_config_mux(MX27_PIN_CLS, GPIO_MUX_GPIO); + gpio_set_value(IOMUX_TO_GPIO(MX27_PIN_CLS), 1); +} + +/*! + * This function configures the IOMux block for PMIC standard operations. + * + */ +void gpio_pmic_active(void) +{ + gpio_config_mux(MX27_PIN_TOUT, GPIO_MUX_GPIO); + gpio_request(IOMUX_TO_GPIO(MX27_PIN_TOUT), "tout"); + gpio_direction_input(IOMUX_TO_GPIO(MX27_PIN_TOUT)); +} + +/*! + * GPIO settings not required for keypad + * + */ +void gpio_keypad_active(void) +{ +} + +/*! + * GPIO settings not required for keypad + * + */ +void gpio_keypad_inactive(void) +{ +} + +/*! + * Setup GPIO for ATA device to be active + * + */ +void gpio_ata_active(void) +{ + gpio_request_mux(MX27_PIN_ATA_DATA0, GPIO_MUX_PRIMARY); + gpio_request_mux(MX27_PIN_ATA_DATA1, GPIO_MUX_PRIMARY); + gpio_request_mux(MX27_PIN_ATA_DATA2, GPIO_MUX_PRIMARY); + gpio_request_mux(MX27_PIN_ATA_DATA3, GPIO_MUX_PRIMARY); + gpio_request_mux(MX27_PIN_ATA_DATA4, GPIO_MUX_PRIMARY); + gpio_request_mux(MX27_PIN_ATA_DATA5, GPIO_MUX_PRIMARY); + gpio_request_mux(MX27_PIN_ATA_DATA6, GPIO_MUX_PRIMARY); + gpio_request_mux(MX27_PIN_ATA_DATA7, GPIO_MUX_PRIMARY); + gpio_request_mux(MX27_PIN_ATA_DATA8, GPIO_MUX_PRIMARY); + gpio_request_mux(MX27_PIN_ATA_DATA9, GPIO_MUX_PRIMARY); + gpio_request_mux(MX27_PIN_ATA_DATA10, GPIO_MUX_PRIMARY); + gpio_request_mux(MX27_PIN_ATA_DATA11, GPIO_MUX_PRIMARY); + gpio_request_mux(MX27_PIN_ATA_DATA12, GPIO_MUX_PRIMARY); + gpio_request_mux(MX27_PIN_ATA_DATA13, GPIO_MUX_PRIMARY); + gpio_request_mux(MX27_PIN_ATA_DATA14, GPIO_MUX_PRIMARY); + gpio_request_mux(MX27_PIN_ATA_DATA15, GPIO_MUX_PRIMARY); + + gpio_request_mux(MX27_PIN_PC_CD1_B, GPIO_MUX_ALT); + gpio_request_mux(MX27_PIN_PC_CD2_B, GPIO_MUX_ALT); + gpio_request_mux(MX27_PIN_PC_WAIT_B, GPIO_MUX_ALT); + gpio_request_mux(MX27_PIN_PC_READY, GPIO_MUX_ALT); + gpio_request_mux(MX27_PIN_PC_PWRON, GPIO_MUX_ALT); + gpio_request_mux(MX27_PIN_PC_VS1, GPIO_MUX_ALT); + gpio_request_mux(MX27_PIN_PC_VS2, GPIO_MUX_ALT); + gpio_request_mux(MX27_PIN_PC_BVD1, GPIO_MUX_ALT); + gpio_request_mux(MX27_PIN_PC_BVD2, GPIO_MUX_ALT); + gpio_request_mux(MX27_PIN_PC_RST, GPIO_MUX_ALT); + gpio_request_mux(MX27_PIN_IOIS16, GPIO_MUX_ALT); + gpio_request_mux(MX27_PIN_PC_RW_B, GPIO_MUX_ALT); + gpio_request_mux(MX27_PIN_PC_POE, GPIO_MUX_ALT); + + __raw_writew(PBC_BCTRL2_ATAFEC_EN | PBC_BCTRL2_ATAFEC_SEL | + PBC_BCTRL2_ATA_EN, PBC_BCTRL2_CLEAR_REG); +} + +/*! + * Setup GPIO for ATA device to be inactive + * + */ +void gpio_ata_inactive(void) +{ + __raw_writew(PBC_BCTRL2_ATAFEC_EN | PBC_BCTRL2_ATAFEC_SEL | + PBC_BCTRL2_ATA_EN, PBC_BCTRL2_SET_REG); + + gpio_free_mux(MX27_PIN_ATA_DATA0); + gpio_free_mux(MX27_PIN_ATA_DATA1); + gpio_free_mux(MX27_PIN_ATA_DATA2); + gpio_free_mux(MX27_PIN_ATA_DATA3); + gpio_free_mux(MX27_PIN_ATA_DATA4); + gpio_free_mux(MX27_PIN_ATA_DATA5); + gpio_free_mux(MX27_PIN_ATA_DATA6); + gpio_free_mux(MX27_PIN_ATA_DATA7); + gpio_free_mux(MX27_PIN_ATA_DATA8); + gpio_free_mux(MX27_PIN_ATA_DATA9); + gpio_free_mux(MX27_PIN_ATA_DATA10); + gpio_free_mux(MX27_PIN_ATA_DATA11); + gpio_free_mux(MX27_PIN_ATA_DATA12); + gpio_free_mux(MX27_PIN_ATA_DATA13); + gpio_free_mux(MX27_PIN_ATA_DATA14); + gpio_free_mux(MX27_PIN_ATA_DATA15); + + gpio_free_mux(MX27_PIN_PC_CD1_B); + gpio_free_mux(MX27_PIN_PC_CD2_B); + gpio_free_mux(MX27_PIN_PC_WAIT_B); + gpio_free_mux(MX27_PIN_PC_READY); + gpio_free_mux(MX27_PIN_PC_PWRON); + gpio_free_mux(MX27_PIN_PC_VS1); + gpio_free_mux(MX27_PIN_PC_VS2); + gpio_free_mux(MX27_PIN_PC_BVD1); + gpio_free_mux(MX27_PIN_PC_BVD2); + gpio_free_mux(MX27_PIN_PC_RST); + gpio_free_mux(MX27_PIN_IOIS16); + gpio_free_mux(MX27_PIN_PC_RW_B); + gpio_free_mux(MX27_PIN_PC_POE); +} + +/*! + * Setup GPIO for FEC device to be active + * + */ +void gpio_fec_active(void) +{ + gpio_request_mux(MX27_PIN_ATA_DATA15, GPIO_MUX_OUTPUT1); + gpio_request(IOMUX_TO_GPIO(MX27_PIN_ATA_DATA15), "ata_data15"); + gpio_direction_output(IOMUX_TO_GPIO(MX27_PIN_ATA_DATA15), 0); + gpio_request_mux(MX27_PIN_ATA_DATA14, GPIO_MUX_OUTPUT1); + gpio_request(IOMUX_TO_GPIO(MX27_PIN_ATA_DATA14), "ata_data14"); + gpio_direction_output(IOMUX_TO_GPIO(MX27_PIN_ATA_DATA14), 0); + gpio_request_mux(MX27_PIN_ATA_DATA13, GPIO_MUX_INPUT1); + gpio_request(IOMUX_TO_GPIO(MX27_PIN_ATA_DATA13), "ata_data13"); + gpio_direction_input(IOMUX_TO_GPIO(MX27_PIN_ATA_DATA13)); + gpio_request_mux(MX27_PIN_ATA_DATA12, GPIO_MUX_INPUT1); + gpio_request(IOMUX_TO_GPIO(MX27_PIN_ATA_DATA12), "ata_data12"); + gpio_direction_input(IOMUX_TO_GPIO(MX27_PIN_ATA_DATA12)); + gpio_request_mux(MX27_PIN_ATA_DATA11, GPIO_MUX_INPUT1); + gpio_request(IOMUX_TO_GPIO(MX27_PIN_ATA_DATA11), "ata_data11"); + gpio_direction_input(IOMUX_TO_GPIO(MX27_PIN_ATA_DATA11)); + gpio_request_mux(MX27_PIN_ATA_DATA10, GPIO_MUX_INPUT1); + gpio_request(IOMUX_TO_GPIO(MX27_PIN_ATA_DATA10), "ata_data10"); + gpio_direction_input(IOMUX_TO_GPIO(MX27_PIN_ATA_DATA10)); + gpio_request_mux(MX27_PIN_ATA_DATA9, GPIO_MUX_INPUT1); + gpio_request(IOMUX_TO_GPIO(MX27_PIN_ATA_DATA9), "ata_data9"); + gpio_direction_input(IOMUX_TO_GPIO(MX27_PIN_ATA_DATA9)); + gpio_request_mux(MX27_PIN_ATA_DATA8, GPIO_MUX_INPUT1); + gpio_request(IOMUX_TO_GPIO(MX27_PIN_ATA_DATA8), "ata_data8"); + gpio_direction_input(IOMUX_TO_GPIO(MX27_PIN_ATA_DATA8)); + gpio_request_mux(MX27_PIN_ATA_DATA7, GPIO_MUX_OUTPUT1); + gpio_request(IOMUX_TO_GPIO(MX27_PIN_ATA_DATA7), "ata_data7"); + gpio_direction_output(IOMUX_TO_GPIO(MX27_PIN_ATA_DATA7), 0); + + gpio_request_mux(MX27_PIN_ATA_DATA6, GPIO_MUX_ALT); + gpio_request_mux(MX27_PIN_ATA_DATA5, GPIO_MUX_INPUT1); + gpio_request(IOMUX_TO_GPIO(MX27_PIN_ATA_DATA5), "ata_data5"); + gpio_direction_input(IOMUX_TO_GPIO(MX27_PIN_ATA_DATA5)); + gpio_request_mux(MX27_PIN_ATA_DATA4, GPIO_MUX_INPUT1); + gpio_request(IOMUX_TO_GPIO(MX27_PIN_ATA_DATA4), "ata_data4"); + gpio_direction_input(IOMUX_TO_GPIO(MX27_PIN_ATA_DATA4)); + gpio_request_mux(MX27_PIN_ATA_DATA3, GPIO_MUX_INPUT1); + gpio_request(IOMUX_TO_GPIO(MX27_PIN_ATA_DATA3), "ata_data3"); + gpio_direction_input(IOMUX_TO_GPIO(MX27_PIN_ATA_DATA3)); + gpio_request_mux(MX27_PIN_ATA_DATA2, GPIO_MUX_INPUT1); + gpio_request(IOMUX_TO_GPIO(MX27_PIN_ATA_DATA2), "ata_data2"); + gpio_direction_input(IOMUX_TO_GPIO(MX27_PIN_ATA_DATA2)); + gpio_request_mux(MX27_PIN_ATA_DATA1, GPIO_MUX_OUTPUT1); + gpio_request(IOMUX_TO_GPIO(MX27_PIN_ATA_DATA1), "ata_data1"); + gpio_direction_output(IOMUX_TO_GPIO(MX27_PIN_ATA_DATA1), 0); + gpio_request_mux(MX27_PIN_ATA_DATA0, GPIO_MUX_OUTPUT1); + gpio_request(IOMUX_TO_GPIO(MX27_PIN_ATA_DATA0), "ata_data0"); + gpio_direction_output(IOMUX_TO_GPIO(MX27_PIN_ATA_DATA0), 0); + gpio_request_mux(MX27_PIN_SD3_CLK, GPIO_MUX_OUTPUT1); + gpio_request(IOMUX_TO_GPIO(MX27_PIN_SD3_CLK), "sd3_clk"); + gpio_direction_output(IOMUX_TO_GPIO(MX27_PIN_SD3_CLK), 0); + gpio_request_mux(MX27_PIN_SD3_CMD, GPIO_MUX_OUTPUT1); + gpio_request(IOMUX_TO_GPIO(MX27_PIN_SD3_CMD), "sd3_cmd"); + gpio_direction_output(IOMUX_TO_GPIO(MX27_PIN_SD3_CMD), 0); + + __raw_writew(PBC_BCTRL2_ATAFEC_EN, PBC_BCTRL2_CLEAR_REG); + __raw_writew(PBC_BCTRL2_ATAFEC_SEL, PBC_BCTRL2_SET_REG); +} + +/*! + * Setup GPIO for FEC device to be inactive + * + */ +void gpio_fec_inactive(void) +{ + gpio_free(MX27_PIN_ATA_DATA0); + gpio_free(MX27_PIN_ATA_DATA1); + gpio_free(MX27_PIN_ATA_DATA2); + gpio_free(MX27_PIN_ATA_DATA3); + gpio_free(MX27_PIN_ATA_DATA4); + gpio_free(MX27_PIN_ATA_DATA5); + gpio_free(MX27_PIN_ATA_DATA6); + gpio_free(MX27_PIN_ATA_DATA7); + gpio_free(MX27_PIN_ATA_DATA8); + gpio_free(MX27_PIN_ATA_DATA9); + gpio_free(MX27_PIN_ATA_DATA10); + gpio_free(MX27_PIN_ATA_DATA11); + gpio_free(MX27_PIN_ATA_DATA12); + gpio_free(MX27_PIN_ATA_DATA13); + gpio_free(MX27_PIN_ATA_DATA14); + gpio_free(MX27_PIN_ATA_DATA15); + + gpio_free(MX27_PIN_SD3_CMD); + gpio_free(MX27_PIN_SD3_CLK); + + gpio_free_mux(MX27_PIN_ATA_DATA0); + gpio_free_mux(MX27_PIN_ATA_DATA1); + gpio_free_mux(MX27_PIN_ATA_DATA2); + gpio_free_mux(MX27_PIN_ATA_DATA3); + gpio_free_mux(MX27_PIN_ATA_DATA4); + gpio_free_mux(MX27_PIN_ATA_DATA5); + gpio_free_mux(MX27_PIN_ATA_DATA6); + gpio_free_mux(MX27_PIN_ATA_DATA7); + gpio_free_mux(MX27_PIN_ATA_DATA8); + gpio_free_mux(MX27_PIN_ATA_DATA9); + gpio_free_mux(MX27_PIN_ATA_DATA10); + gpio_free_mux(MX27_PIN_ATA_DATA11); + gpio_free_mux(MX27_PIN_ATA_DATA12); + gpio_free_mux(MX27_PIN_ATA_DATA13); + gpio_free_mux(MX27_PIN_ATA_DATA14); + gpio_free_mux(MX27_PIN_ATA_DATA15); + + gpio_free_mux(MX27_PIN_SD3_CMD); + gpio_free_mux(MX27_PIN_SD3_CLK); +} + +/*! + * Setup GPIO for SLCDC device to be active + * + */ +void gpio_slcdc_active(int type) +{ + switch (type) { + case 0: + gpio_request_mux(MX27_PIN_SSI3_CLK, GPIO_MUX_ALT); /* CLK */ + gpio_request_mux(MX27_PIN_SSI3_TXDAT, GPIO_MUX_ALT); /* CS */ + gpio_request_mux(MX27_PIN_SSI3_RXDAT, GPIO_MUX_ALT); /* RS */ + gpio_request_mux(MX27_PIN_SSI3_FS, GPIO_MUX_ALT); /* D0 */ + break; + + case 1: + gpio_request_mux(MX27_PIN_SD2_D1, GPIO_MUX_GPIO); /* CLK */ + gpio_request_mux(MX27_PIN_SD2_D2, GPIO_MUX_GPIO); /* D0 */ + gpio_request_mux(MX27_PIN_SD2_D3, GPIO_MUX_GPIO); /* RS */ + gpio_request_mux(MX27_PIN_SD2_CMD, GPIO_MUX_GPIO); /* CS */ + break; + + case 2: + gpio_request_mux(MX27_PIN_LD0, GPIO_MUX_GPIO); + gpio_request_mux(MX27_PIN_LD1, GPIO_MUX_GPIO); + gpio_request_mux(MX27_PIN_LD2, GPIO_MUX_GPIO); + gpio_request_mux(MX27_PIN_LD3, GPIO_MUX_GPIO); + gpio_request_mux(MX27_PIN_LD4, GPIO_MUX_GPIO); + gpio_request_mux(MX27_PIN_LD5, GPIO_MUX_GPIO); + gpio_request_mux(MX27_PIN_LD6, GPIO_MUX_GPIO); + gpio_request_mux(MX27_PIN_LD7, GPIO_MUX_GPIO); + gpio_request_mux(MX27_PIN_LD8, GPIO_MUX_GPIO); + gpio_request_mux(MX27_PIN_LD9, GPIO_MUX_GPIO); + gpio_request_mux(MX27_PIN_LD10, GPIO_MUX_GPIO); + gpio_request_mux(MX27_PIN_LD11, GPIO_MUX_GPIO); + gpio_request_mux(MX27_PIN_LD12, GPIO_MUX_GPIO); + gpio_request_mux(MX27_PIN_LD13, GPIO_MUX_GPIO); + gpio_request_mux(MX27_PIN_LD14, GPIO_MUX_GPIO); + gpio_request_mux(MX27_PIN_LD15, GPIO_MUX_GPIO); + break; + + default: + break; + } + + return; +} + +/*! + * Setup GPIO for SLCDC device to be inactive + * + */ +void gpio_slcdc_inactive(int type) +{ + switch (type) { + case 0: + gpio_free_mux(MX27_PIN_SSI3_CLK); /* CLK */ + gpio_free_mux(MX27_PIN_SSI3_TXDAT); /* CS */ + gpio_free_mux(MX27_PIN_SSI3_RXDAT); /* RS */ + gpio_free_mux(MX27_PIN_SSI3_FS); /* D0 */ + break; + + case 1: + gpio_free_mux(MX27_PIN_SD2_D1); /* CLK */ + gpio_free_mux(MX27_PIN_SD2_D2); /* D0 */ + gpio_free_mux(MX27_PIN_SD2_D3); /* RS */ + gpio_free_mux(MX27_PIN_SD2_CMD); /* CS */ + break; + + case 2: + gpio_free_mux(MX27_PIN_LD0); + gpio_free_mux(MX27_PIN_LD1); + gpio_free_mux(MX27_PIN_LD2); + gpio_free_mux(MX27_PIN_LD3); + gpio_free_mux(MX27_PIN_LD4); + gpio_free_mux(MX27_PIN_LD5); + gpio_free_mux(MX27_PIN_LD6); + gpio_free_mux(MX27_PIN_LD7); + gpio_free_mux(MX27_PIN_LD8); + gpio_free_mux(MX27_PIN_LD9); + gpio_free_mux(MX27_PIN_LD10); + gpio_free_mux(MX27_PIN_LD11); + gpio_free_mux(MX27_PIN_LD12); + gpio_free_mux(MX27_PIN_LD13); + gpio_free_mux(MX27_PIN_LD14); + gpio_free_mux(MX27_PIN_LD15); + break; + + default: + break; + } + + return; +} + +void gpio_ssi_active(int ssi_num) +{ + switch (ssi_num) { + case 0: + gpio_request_mux(MX27_PIN_SSI1_FS, GPIO_MUX_PRIMARY); + gpio_request_mux(MX27_PIN_SSI1_RXDAT, GPIO_MUX_PRIMARY); + gpio_request_mux(MX27_PIN_SSI1_TXDAT, GPIO_MUX_PRIMARY); + gpio_request_mux(MX27_PIN_SSI1_CLK, GPIO_MUX_PRIMARY); + gpio_set_puen(MX27_PIN_SSI1_FS, 0); + gpio_set_puen(MX27_PIN_SSI1_RXDAT, 0); + gpio_set_puen(MX27_PIN_SSI1_TXDAT, 0); + gpio_set_puen(MX27_PIN_SSI1_CLK, 0); + break; + case 1: + gpio_request_mux(MX27_PIN_SSI2_FS, GPIO_MUX_PRIMARY); + gpio_request_mux(MX27_PIN_SSI2_RXDAT, GPIO_MUX_PRIMARY); + gpio_request_mux(MX27_PIN_SSI2_TXDAT, GPIO_MUX_PRIMARY); + gpio_request_mux(MX27_PIN_SSI2_CLK, GPIO_MUX_PRIMARY); + gpio_set_puen(MX27_PIN_SSI2_FS, 0); + gpio_set_puen(MX27_PIN_SSI2_RXDAT, 0); + gpio_set_puen(MX27_PIN_SSI2_TXDAT, 0); + gpio_set_puen(MX27_PIN_SSI2_CLK, 0); + break; + default: + break; + } + return; +} + +/*! + * * Setup GPIO for a SSI port to be inactive + * * + * * @param ssi_num an SSI port num + */ + +void gpio_ssi_inactive(int ssi_num) +{ + switch (ssi_num) { + case 0: + gpio_free_mux(MX27_PIN_SSI1_FS); + gpio_free_mux(MX27_PIN_SSI1_RXDAT); + gpio_free_mux(MX27_PIN_SSI1_TXDAT); + gpio_free_mux(MX27_PIN_SSI1_CLK); + break; + case 1: + gpio_free_mux(MX27_PIN_SSI2_FS); + gpio_free_mux(MX27_PIN_SSI2_RXDAT); + gpio_free_mux(MX27_PIN_SSI2_TXDAT); + gpio_free_mux(MX27_PIN_SSI2_CLK); + break; + default: + break; + } + return; +} + +/*! + * Setup GPIO for SDHC to be active + * + * @param module SDHC module number + */ +void gpio_sdhc_active(int module) +{ + u16 data; + switch (module) { + case 0: + gpio_request_mux(MX27_PIN_SD1_CLK, GPIO_MUX_PRIMARY); + gpio_request_mux(MX27_PIN_SD1_CMD, GPIO_MUX_PRIMARY); + gpio_request_mux(MX27_PIN_SD1_D0, GPIO_MUX_PRIMARY); + gpio_request_mux(MX27_PIN_SD1_D1, GPIO_MUX_PRIMARY); + gpio_request_mux(MX27_PIN_SD1_D2, GPIO_MUX_PRIMARY); + gpio_request_mux(MX27_PIN_SD1_D3, GPIO_MUX_PRIMARY); + /* 22k pull up for sd1 dat3 pins */ + data = __raw_readw(IO_ADDRESS(SYSCTRL_BASE_ADDR + 0x54)); + data |= 0x0c; + __raw_writew(data, IO_ADDRESS(SYSCTRL_BASE_ADDR + 0x54)); + /*mxc_clks_enable(SDHC1_CLK); + mxc_clks_enable(PERCLK2); */ + break; + case 1: + gpio_request_mux(MX27_PIN_SD2_CLK, GPIO_MUX_PRIMARY); + gpio_request_mux(MX27_PIN_SD2_CMD, GPIO_MUX_PRIMARY); + gpio_request_mux(MX27_PIN_SD2_D0, GPIO_MUX_PRIMARY); + gpio_request_mux(MX27_PIN_SD2_D1, GPIO_MUX_PRIMARY); + gpio_request_mux(MX27_PIN_SD2_D2, GPIO_MUX_PRIMARY); + gpio_request_mux(MX27_PIN_SD2_D3, GPIO_MUX_PRIMARY); + /* 22k pull up for sd2 pins */ + data = __raw_readw(IO_ADDRESS(SYSCTRL_BASE_ADDR + 0x54)); + data &= ~0xfff0; + data |= 0xfff0; + __raw_writew(data, IO_ADDRESS(SYSCTRL_BASE_ADDR + 0x54)); + /*mxc_clks_enable(SDHC2_CLK); + mxc_clks_enable(PERCLK2); */ + break; + case 2: + gpio_request_mux(MX27_PIN_SD3_CLK, GPIO_MUX_PRIMARY); + gpio_request_mux(MX27_PIN_SD3_CMD, GPIO_MUX_PRIMARY); + gpio_request_mux(MX27_PIN_ATA_DATA0, GPIO_MUX_ALT); + gpio_request_mux(MX27_PIN_ATA_DATA1, GPIO_MUX_ALT); + gpio_request_mux(MX27_PIN_ATA_DATA2, GPIO_MUX_ALT); + gpio_request_mux(MX27_PIN_ATA_DATA3, GPIO_MUX_ALT); + /*mxc_clks_enable(SDHC3_CLK); + mxc_clks_enable(PERCLK2); */ + break; + default: + break; + } +} + +/*! + * Setup GPIO for SDHC1 to be inactive + * + * @param module SDHC module number + */ +void gpio_sdhc_inactive(int module) +{ + switch (module) { + case 0: + gpio_free_mux(MX27_PIN_SD1_CLK); + gpio_free_mux(MX27_PIN_SD1_CMD); + gpio_free_mux(MX27_PIN_SD1_D0); + gpio_free_mux(MX27_PIN_SD1_D1); + gpio_free_mux(MX27_PIN_SD1_D2); + gpio_free_mux(MX27_PIN_SD1_D3); + /*mxc_clks_disable(SDHC1_CLK); */ + break; + case 1: + gpio_free_mux(MX27_PIN_SD2_CLK); + gpio_free_mux(MX27_PIN_SD2_CMD); + gpio_free_mux(MX27_PIN_SD2_D0); + gpio_free_mux(MX27_PIN_SD2_D1); + gpio_free_mux(MX27_PIN_SD2_D2); + gpio_free_mux(MX27_PIN_SD2_D3); + /*mxc_clks_disable(SDHC2_CLK); */ + break; + case 2: + gpio_free_mux(MX27_PIN_SD3_CLK); + gpio_free_mux(MX27_PIN_SD3_CMD); + gpio_free_mux(MX27_PIN_ATA_DATA0); + gpio_free_mux(MX27_PIN_ATA_DATA1); + gpio_free_mux(MX27_PIN_ATA_DATA2); + gpio_free_mux(MX27_PIN_ATA_DATA3); + /*mxc_clks_disable(SDHC3_CLK); */ + break; + default: + break; + } +} + +/* + * Probe for the card. If present the GPIO data would be set. + */ +int sdhc_get_card_det_status(struct device *dev) +{ + return 0; +} + +/* + * Return the card detect pin. + */ +int sdhc_init_card_det(int id) +{ + int ret = 0; + switch (id) { + case 0: + ret = EXPIO_INT_SD1_EN; + break; + case 1: + ret = EXPIO_INT_SD2_EN; + break; + default: + ret = 0; + break; + } + return ret; +} + +/* + * Power on/off Sharp QVGA panel. + */ +void board_power_lcd(int on) +{ + if (on) + __raw_writew(PBC_BCTRL1_LCDON, PBC_BCTRL1_SET_REG); + else + __raw_writew(PBC_BCTRL1_LCDON, PBC_BCTRL1_CLEAR_REG); +} + +void gpio_owire_active(void) +{ + gpio_request_mux(MX27_PIN_RTCK, GPIO_MUX_ALT); +} + +void gpio_owire_inactive(void) +{ + gpio_request_mux(MX27_PIN_RTCK, GPIO_MUX_PRIMARY); +} + +EXPORT_SYMBOL(gpio_uart_active); +EXPORT_SYMBOL(gpio_uart_inactive); +EXPORT_SYMBOL(config_uartdma_event); +EXPORT_SYMBOL(gpio_usbh1_active); +EXPORT_SYMBOL(gpio_usbh1_inactive); +EXPORT_SYMBOL(gpio_usbh2_active); +EXPORT_SYMBOL(gpio_usbh2_inactive); +EXPORT_SYMBOL(gpio_usbotg_hs_active); +EXPORT_SYMBOL(gpio_usbotg_hs_inactive); +EXPORT_SYMBOL(gpio_usbotg_fs_active); +EXPORT_SYMBOL(gpio_usbotg_fs_inactive); +EXPORT_SYMBOL(gpio_i2c_active); +EXPORT_SYMBOL(gpio_i2c_inactive); +EXPORT_SYMBOL(gpio_spi_active); +EXPORT_SYMBOL(gpio_spi_inactive); +EXPORT_SYMBOL(gpio_nand_active); +EXPORT_SYMBOL(gpio_nand_inactive); +EXPORT_SYMBOL(gpio_sensor_active); +EXPORT_SYMBOL(gpio_sensor_inactive); +EXPORT_SYMBOL(gpio_sensor_reset); +EXPORT_SYMBOL(gpio_lcdc_active); +EXPORT_SYMBOL(gpio_lcdc_inactive); +EXPORT_SYMBOL(gpio_fs453_reset_low); +EXPORT_SYMBOL(gpio_fs453_reset_high); +EXPORT_SYMBOL(gpio_pmic_active); +EXPORT_SYMBOL(gpio_keypad_active); +EXPORT_SYMBOL(gpio_keypad_inactive); +EXPORT_SYMBOL(gpio_ata_active); +EXPORT_SYMBOL(gpio_ata_inactive); +EXPORT_SYMBOL(gpio_fec_active); +EXPORT_SYMBOL(gpio_fec_inactive); +EXPORT_SYMBOL(gpio_slcdc_active); +EXPORT_SYMBOL(gpio_slcdc_inactive); +EXPORT_SYMBOL(gpio_ssi_active); +EXPORT_SYMBOL(gpio_ssi_inactive); +EXPORT_SYMBOL(gpio_sdhc_active); +EXPORT_SYMBOL(gpio_sdhc_inactive); +EXPORT_SYMBOL(sdhc_get_card_det_status); +EXPORT_SYMBOL(sdhc_init_card_det); +EXPORT_SYMBOL(board_power_lcd); +EXPORT_SYMBOL(gpio_owire_active); +EXPORT_SYMBOL(gpio_owire_inactive); diff --git a/arch/arm/mach-mx27/mxc_pm.c b/arch/arm/mach-mx27/mxc_pm.c new file mode 100644 index 000000000000..4cad42238477 --- /dev/null +++ b/arch/arm/mach-mx27/mxc_pm.c @@ -0,0 +1,459 @@ +/* + * Copyright 2004-2009 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 + */ + +/*! + * @defgroup DPM_MX27 Power Management + * @ingroup MSL_MX27 + */ +/*! + * @file mach-mx27/mxc_pm.c + * + * @brief This file contains the implementation of the Low-level power + * management driver. It modifies the registers of the PLL and clock module + * of the i.MX27. + * + * @ingroup DPM_MX27 + */ + +/* + * Include Files + */ +#include <linux/module.h> +#include <linux/interrupt.h> +#include <linux/io.h> +#include <linux/delay.h> +#include <mach/mxc_pm.h> +#include <mach/mxc.h> +#include <mach/system.h> +#include <asm/irq.h> +#include "crm_regs.h" + +/* Local defines */ +#define MAX_ARM_FREQ 400000000 +#define MAX_AHB_FREQ 133000000 +#define MAX_IPG_FREQ 66500000 +#define FREQ_COMP_TOLERANCE 100 /* tolerance percentage times 100 */ +#define MX27_LLPM_DEBUG 0 + +/* + * Global variables + */ +#if 0 +/*! + * These variables hold the various clock values when the module is loaded. + * This is needed because these clocks are derived from MPLL and when MPLL + * output changes, these clocks need to be adjusted. + */ +static u32 perclk1, perclk2, perclk3, perclk4, nfcclk, cpuclk; + +/*! + * Compare two frequences using allowable tolerance + * + * The MX27 PLL can generate many frequencies. This function + * compares the generated frequency to the requested frequency + * and determines it they are within and acceptable tolerance. + * + * @param freq1 desired frequency + * @param freq2 generated frequency + * + * @return Returns 0 is frequencies are within talerance + * and non-zero is they are not. + */ +static s32 freq_equal(u32 freq1, u32 freq2) +{ + if (freq1 > freq2) { + return (freq1 - freq2) <= (freq1 / FREQ_COMP_TOLERANCE); + } + return (freq2 - freq1) <= (freq1 / FREQ_COMP_TOLERANCE); +} + +/*! + * Select the PLL frequency based on the desired ARM frequency. + * + * The MPLL will be configured to output three frequencies, 400/333/266 MHz. + * + * @param armfreq Desired ARM frequency + * + * @return Returns one of the selected PLL frequency (400/333/266 MHz). + * Returns -1 on error. + * + */ +static s32 select_freq_pll(u32 armfreq) +{ + u32 div; + + div = 266000000 / armfreq; + if ((div == 0) || (!freq_equal(armfreq, 266000000 / div))) { + div = 400000000 / armfreq; + if ((div == 0) || (!freq_equal(armfreq, 400000000 / div))) { + return -1; + } + + return 400000000; + } + + return 266000000; +} + +/*! + * Check whether the desired ARM and AHB frequencies are valid. + * + * @param armfreq Desired ARM frequency + * @param ahbfreq Desired AHB frequency + * + * @return Returns 0 on success + * Return -1 on error + */ +static s32 mx27_pm_check_parameters(u32 armfreq, u32 ahbfreq) +{ + u32 ahbdiv; + + /* No idea about minimum frequencies.. just a guess! */ + if ((armfreq < 1000000) || (ahbfreq < 1000000)) { + printk("arm or ahb frequencies are less\n"); + return -1; + } + + if ((armfreq > MAX_ARM_FREQ) || (ahbfreq > MAX_AHB_FREQ)) { + printk("arm or ahb freq. are too much\n"); + return -1; + } + + /* AHB divider value is restricted to less than 8 */ + ahbdiv = armfreq / ahbfreq; + if ((ahbdiv == 0) || (ahbdiv > 8)) { + printk("Invalid ahb frequency\n"); + return -1; + } + + return 0; +} + +/*! + * Integer clock scaling + * + * Change the main ARM clock frequencies without changing the MPLL. + * The integer dividers (PRESC and BCLKDIV) are changed to obtain the + * desired frequency. Since NFC clock is derived from ARM frequency, + * NFCDIV is also adjusted. + * + * @param arm_freq Desired ARM frequency + * @param ahb_freq Desired AHB frequency + * @param pll_freq Current PLL frequency + * + * @return Returns 0 + */ +static s32 mx27_pm_intscale(u32 arm_freq, u32 ahb_freq, s32 pll_freq) +{ + u32 pre_div, bclk_div, nfc_div; + + /* Calculate ARM divider */ + pre_div = pll_freq / arm_freq; + if (pre_div == 0) + pre_div = 1; + + /* Calculate AHB divider */ + bclk_div = arm_freq / ahb_freq; + if (bclk_div == 0) + bclk_div = 1; + + if ((arm_freq / bclk_div) > ahb_freq) + bclk_div++; + + /* NFC clock is dependent on ARM clock */ + nfc_div = arm_freq / nfcclk; + if ((arm_freq / nfc_div) > nfcclk) + nfc_div++; + + /* Adjust NFC divider */ + mxc_set_clocks_div(NFC_CLK, nfc_div); + +#if MX27_LLPM_DEBUG + printk("DIVIDERS: PreDiv = %d BCLKDIV = %d \n", pre_div, bclk_div); + printk("Integer scaling\n"); + printk("PLL = %d : ARM = %d: AHB = %d\n", pll_freq, arm_freq, ahb_freq); +#endif + + /* + * This part is tricky. What to adjust first (PRESC or BCLKDIV)? + * After trial and error, if current ARM frequency is greater than + * desired ARM frequency, then adjust PRESC first, else if current + * ARM frequency is less than desired ARM frequency, then adjust + * BCLKDIV first. + */ + if (cpuclk > arm_freq) { + mxc_set_clocks_div(CPU_CLK, pre_div); + mxc_set_clocks_div(AHB_CLK, bclk_div); + } else { + mxc_set_clocks_div(AHB_CLK, bclk_div); + mxc_set_clocks_div(CPU_CLK, pre_div); + } + + cpuclk = arm_freq; + mdelay(50); + return 0; +} + +/*! + * Set dividers for various peripheral clocks. + * + * PERCLK1, PERCLK2, PERCLK3 and PERCLK4 are adjusted based on the MPLL + * output frequency. + * + * @param pll_freq Desired MPLL output frequency + */ +static void mx27_set_dividers(u32 pll_freq) +{ + s32 perdiv1, perdiv2, perdiv3, perdiv4; + + perdiv1 = pll_freq / perclk1; + if ((pll_freq / perdiv1) > perclk1) + perdiv1++; + + perdiv2 = pll_freq / perclk2; + if ((pll_freq / perdiv2) > perclk2) + perdiv2++; + + perdiv3 = pll_freq / perclk3; + if ((pll_freq / perdiv3) > perclk3) + perdiv3++; + + perdiv4 = pll_freq / perclk4; + if ((pll_freq / perdiv4) > perclk4) + perdiv4++; + + mxc_set_clocks_div(PERCLK1, perdiv1); + mxc_set_clocks_div(PERCLK2, perdiv2); + mxc_set_clocks_div(PERCLK3, perdiv3); + mxc_set_clocks_div(PERCLK4, perdiv4); +} + +/*! + * Change MPLL output frequency and adjust derived clocks to produce the + * desired frequencies. + * + * @param arm_freq Desired ARM frequency + * @param ahb_freq Desired AHB frequency + * @param org_pll Current PLL frequency + * + * @return Returns 0 on success + * Returns -1 on error + */ +static s32 mx27_pm_pllscale(u32 arm_freq, u32 ahb_freq, s32 org_pll) +{ + u32 mfi, mfn, mfd, pd = 1, cscr; + s32 pll_freq; + + /* Obtain the PLL frequency for the desired ARM frequency */ + pll_freq = select_freq_pll(arm_freq); + if (pll_freq == -1) { + return -1; + } + + /* The MPCTL0 register values are programmed based on the oscillator */ + cscr = __raw_readl(IO_ADDRESS(CCM_BASE_ADDR) + CCM_CSCR); + if ((cscr & CCM_CSCR_OSC26M) == 0) { + /* MPCTL0 register values are programmed for 400/266 MHz */ + switch (pll_freq) { + case 400000000: + mfi = 7; + mfn = 9; + mfd = 12; + pd = 0; + break; + + case 266000000: + mfi = 10; + mfn = 6; + mfd = 25; + break; + + default: + return -1; + } + } else { + /* MPCTL0 register values are programmed for 400/266 MHz */ + switch (pll_freq) { + case 400000000: + mfi = 12; + mfn = 2; + mfd = 3; + break; + + case 266000000: + mfi = 8; + mfn = 10; + mfd = 31; + break; + + default: + return -1; + } + } + +#if MX27_LLPM_DEBUG + printk("PLL scaling\n"); + printk("PLL = %d : ARM = %d: AHB = %d\n", pll_freq, arm_freq, ahb_freq); +#endif + + /* Adjust the peripheral clock dividers for new PLL frequency */ + mx27_set_dividers(pll_freq); + + if (pll_freq > org_pll) { + /* Set the dividers first */ + mx27_pm_intscale(arm_freq, ahb_freq, pll_freq); + + /* Set the PLL */ + mxc_pll_set(MCUPLL, mfi, pd, mfd, mfn); + mdelay(50); + } else { + /* Set the PLL first */ + mxc_pll_set(MCUPLL, mfi, pd, mfd, mfn); + mdelay(50); + + /* Set the dividers later */ + mx27_pm_intscale(arm_freq, ahb_freq, pll_freq); + } + + return 0; +} +#endif +/*! + * Implement steps required to transition to low-power modes. + * + * @param mode The desired low-power mode. Possible values are, + * DOZE_MODE + * WAIT_MODE + * STOP_MODE + * DSM_MODE + */ +void mxc_pm_lowpower(s32 mode) +{ + u32 cscr; + + local_irq_disable(); + + /* WAIT and DOZE execute WFI only */ + switch (mode) { + case STOP_MODE: + case DSM_MODE: + /* Clear MPEN and SPEN to disable MPLL/SPLL */ + cscr = __raw_readl(CCM_CSCR); + cscr &= 0xFFFFFFFC; + __raw_writel(cscr, CCM_CSCR); + break; + } + + /* Executes WFI */ + arch_idle(); + + local_irq_enable(); +} + +#if 0 +/*! + * Called to change the core frequency. This function internally decides + * whether to do integer scaling or pll scaling. + * + * @param arm_freq Desired ARM frequency + * @param ahb_freq Desired AHB frequency + * @param ipg_freq Desired IP frequency, constant AHB / 2 always. + * + * @return Returns 0 on success + * Returns -1 on error + */ +int mxc_pm_dvfs(unsigned long arm_freq, long ahb_freq, long ipg_freq) +{ + u32 divider; + s32 pll_freq, ret; + unsigned long flags; + + if (mx27_pm_check_parameters(arm_freq, ahb_freq) != 0) { + return -1; + } + + local_irq_save(flags); + + /* Get the current PLL frequency */ + pll_freq = mxc_pll_clock(MCUPLL); + +#if MX27_LLPM_DEBUG + printk("MCU PLL frequency is %d\n", pll_freq); +#endif + + /* Decide whether to do integer scaling or pll scaling */ + if (arm_freq > pll_freq) { + /* Do PLL scaling */ + ret = mx27_pm_pllscale(arm_freq, ahb_freq, pll_freq); + } else { + /* We need integer divider values */ + divider = pll_freq / arm_freq; + if (!freq_equal(arm_freq, pll_freq / divider)) { + /* Do PLL scaling */ + ret = mx27_pm_pllscale(arm_freq, ahb_freq, pll_freq); + } else { + /* Do integer scaling */ + ret = mx27_pm_intscale(arm_freq, ahb_freq, pll_freq); + } + } + + local_irq_restore(flags); + return ret; +} +#endif +/* + * This API is not supported on i.MX27 + */ +int mxc_pm_intscale(long armfreq, long ahbfreq, long ipfreq) +{ + return -MXC_PM_API_NOT_SUPPORTED; +} + +/* + * This API is not supported on i.MX27 + */ +int mxc_pm_pllscale(long armfreq, long ahbfreq, long ipfreq) +{ + return -MXC_PM_API_NOT_SUPPORTED; +} + +/*! + * This function is used to load the module. + * + * @return Returns an Integer on success + */ +static int __init mxc_pm_init_module(void) +{ + printk(KERN_INFO "MX27: Power management module initialized\n"); + return 0; +} + +/*! + * This function is used to unload the module + */ +static void __exit mxc_pm_cleanup_module(void) +{ + printk(KERN_INFO "MX27: Power management module exit\n"); +} + +module_init(mxc_pm_init_module); +module_exit(mxc_pm_cleanup_module); + +EXPORT_SYMBOL(mxc_pm_lowpower); +//EXPORT_SYMBOL(mxc_pm_dvfs); +EXPORT_SYMBOL(mxc_pm_pllscale); +EXPORT_SYMBOL(mxc_pm_intscale); + +MODULE_AUTHOR("Freescale Semiconductor"); +MODULE_DESCRIPTION("i.MX27 low level PM driver"); +MODULE_LICENSE("GPL"); diff --git a/arch/arm/mach-mx27/pm.c b/arch/arm/mach-mx27/pm.c new file mode 100644 index 000000000000..10909a72ee1b --- /dev/null +++ b/arch/arm/mach-mx27/pm.c @@ -0,0 +1,102 @@ +/* + * linux/arch/arm/mach-mx27/pm.c + * + * MX27 Power Management Routines + * + * Original code for the SA11x0: + * Copyright (c) 2001 Cliff Brake <cbrake@accelent.com> + * + * Modified for the PXA250 by Nicolas Pitre: + * Copyright (c) 2002 Monta Vista Software, Inc. + * + * Modified for the OMAP1510 by David Singleton: + * Copyright (c) 2002 Monta Vista Software, Inc. + * + * Cleanup 2004 for OMAP1510/1610 by Dirk Behme <dirk.behme@de.bosch.com> + * + * Modified for the MX27 + * Copyright 2007-2009 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <linux/kernel.h> +#include <linux/suspend.h> + +#include <mach/mxc_pm.h> + +/* + * TODO: whatta save? + */ + +static int mx27_suspend_enter(suspend_state_t state) +{ + pr_debug("Hi, from mx27_pm_enter\n"); + switch (state) { + case PM_SUSPEND_STANDBY: + mxc_pm_lowpower(STOP_MODE); + break; + case PM_SUSPEND_MEM: + mxc_pm_lowpower(DSM_MODE); + break; + default: + return -1; + } + return 0; +} + +/* + * Called after processes are frozen, but before we shut down devices. + */ +static int mx27_suspend_prepare(void) +{ + return 0; +} + +/* + * Called after devices are re-setup, but before processes are thawed. + */ +static void mx27_suspend_finish(void) +{ + return; +} + +static int mx27_pm_valid(suspend_state_t state) +{ + return (state > PM_SUSPEND_ON && state <= PM_SUSPEND_MAX); +} + +struct platform_suspend_ops mx27_suspend_ops = { + .valid = mx27_pm_valid, + .prepare = mx27_suspend_prepare, + .enter = mx27_suspend_enter, + .finish = mx27_suspend_finish, +}; + +static int __init mx27_pm_init(void) +{ + pr_debug("Power Management for Freescale MX27\n"); + suspend_set_ops(&mx27_suspend_ops); + + return 0; +} + +late_initcall(mx27_pm_init); diff --git a/arch/arm/mach-mx27/serial.c b/arch/arm/mach-mx27/serial.c new file mode 100644 index 000000000000..a18cf0630c47 --- /dev/null +++ b/arch/arm/mach-mx27/serial.c @@ -0,0 +1,275 @@ +/* + * Copyright 2006-2009 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 + */ +/*! + * @file mach-mx27/serial.c + * + * @brief This file contains the UART initiliazation. + * + * @ingroup MSL_MX27 + */ +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/serial.h> +#include <mach/hardware.h> +#include <mach/mxc_uart.h> +#include "serial.h" +#include "board-mx27ads.h" + +#if defined(CONFIG_SERIAL_MXC) || defined(CONFIG_SERIAL_MXC_MODULE) + +/*! + * This is an array where each element holds information about a UART port, + * like base address of the UART, interrupt numbers etc. This structure is + * passed to the serial_core.c file. Based on which UART is used, the core file + * passes back the appropriate port structure as an argument to the control + * functions. + */ +static uart_mxc_port mxc_ports[] = { + [0] = { + .port = { + .membase = (void *)IO_ADDRESS(UART1_BASE_ADDR), + .mapbase = UART1_BASE_ADDR, + .iotype = SERIAL_IO_MEM, + .irq = UART1_INT1, + .fifosize = 32, + .flags = ASYNC_BOOT_AUTOCONF, + .line = 0, + }, + .ints_muxed = UART1_MUX_INTS, + .irqs = {UART1_INT2, UART1_INT3}, + .mode = UART1_MODE, + .ir_mode = UART1_IR, + .enabled = UART1_ENABLED, + .hardware_flow = UART1_HW_FLOW, + .cts_threshold = UART1_UCR4_CTSTL, + .dma_enabled = UART1_DMA_ENABLE, + .dma_rxbuf_size = UART1_DMA_RXBUFSIZE, + .rx_threshold = UART1_UFCR_RXTL, + .tx_threshold = UART1_UFCR_TXTL, + .shared = UART1_SHARED_PERI, + .dma_tx_id = MXC_DMA_UART1_TX, + .dma_rx_id = MXC_DMA_UART1_RX, + .rxd_mux = MXC_UART_RXDMUX, + .ir_tx_inv = MXC_IRDA_TX_INV, + .ir_rx_inv = MXC_IRDA_RX_INV, + }, + [1] = { + .port = { + .membase = (void *)IO_ADDRESS(UART2_BASE_ADDR), + .mapbase = UART2_BASE_ADDR, + .iotype = SERIAL_IO_MEM, + .irq = UART2_INT1, + .fifosize = 32, + .flags = ASYNC_BOOT_AUTOCONF, + .line = 1, + }, + .ints_muxed = UART2_MUX_INTS, + .irqs = {UART2_INT2, UART2_INT3}, + .mode = UART2_MODE, + .ir_mode = UART2_IR, + .enabled = UART2_ENABLED, + .hardware_flow = UART2_HW_FLOW, + .cts_threshold = UART2_UCR4_CTSTL, + .dma_enabled = UART2_DMA_ENABLE, + .dma_rxbuf_size = UART2_DMA_RXBUFSIZE, + .rx_threshold = UART2_UFCR_RXTL, + .tx_threshold = UART2_UFCR_TXTL, + .shared = UART2_SHARED_PERI, + .dma_tx_id = MXC_DMA_UART2_TX, + .dma_rx_id = MXC_DMA_UART2_RX, + .rxd_mux = MXC_UART_RXDMUX, + .ir_tx_inv = MXC_IRDA_TX_INV, + .ir_rx_inv = MXC_IRDA_RX_INV, + }, + [2] = { + .port = { + .membase = (void *)IO_ADDRESS(UART3_BASE_ADDR), + .mapbase = UART3_BASE_ADDR, + .iotype = SERIAL_IO_MEM, + .irq = UART3_INT1, + .fifosize = 32, + .flags = ASYNC_BOOT_AUTOCONF, + .line = 2, + }, + .ints_muxed = UART3_MUX_INTS, + .irqs = {UART3_INT2, UART3_INT3}, + .mode = UART3_MODE, + .ir_mode = UART3_IR, + .enabled = UART3_ENABLED, + .hardware_flow = UART3_HW_FLOW, + .cts_threshold = UART3_UCR4_CTSTL, + .dma_enabled = UART3_DMA_ENABLE, + .dma_rxbuf_size = UART3_DMA_RXBUFSIZE, + .rx_threshold = UART3_UFCR_RXTL, + .tx_threshold = UART3_UFCR_TXTL, + .shared = UART3_SHARED_PERI, + .dma_tx_id = MXC_DMA_UART3_TX, + .dma_rx_id = MXC_DMA_UART3_RX, + .rxd_mux = MXC_UART_IR_RXDMUX, + .ir_tx_inv = MXC_IRDA_TX_INV, + .ir_rx_inv = MXC_IRDA_RX_INV, + }, + [3] = { + .port = { + .membase = (void *)IO_ADDRESS(UART4_BASE_ADDR), + .mapbase = UART4_BASE_ADDR, + .iotype = SERIAL_IO_MEM, + .irq = UART4_INT1, + .fifosize = 32, + .flags = ASYNC_BOOT_AUTOCONF, + .line = 3, + }, + .ints_muxed = UART4_MUX_INTS, + .irqs = {UART4_INT2, UART4_INT3}, + .mode = UART4_MODE, + .ir_mode = UART4_IR, + .enabled = UART4_ENABLED, + .hardware_flow = UART4_HW_FLOW, + .cts_threshold = UART4_UCR4_CTSTL, + .dma_enabled = UART4_DMA_ENABLE, + .dma_rxbuf_size = UART4_DMA_RXBUFSIZE, + .rx_threshold = UART4_UFCR_RXTL, + .tx_threshold = UART4_UFCR_TXTL, + .shared = UART4_SHARED_PERI, + .dma_tx_id = MXC_DMA_UART4_TX, + .dma_rx_id = MXC_DMA_UART4_RX, + .rxd_mux = MXC_UART_RXDMUX, + .ir_tx_inv = MXC_IRDA_TX_INV, + .ir_rx_inv = MXC_IRDA_RX_INV, + }, + [4] = { + .port = { + .membase = (void *)IO_ADDRESS(UART5_BASE_ADDR), + .mapbase = UART5_BASE_ADDR, + .iotype = SERIAL_IO_MEM, + .irq = UART5_INT1, + .fifosize = 32, + .flags = ASYNC_BOOT_AUTOCONF, + .line = 4, + }, + .ints_muxed = UART5_MUX_INTS, + .irqs = {UART5_INT2, UART5_INT3}, + .mode = UART5_MODE, + .ir_mode = UART5_IR, + .enabled = UART5_ENABLED, + .hardware_flow = UART5_HW_FLOW, + .cts_threshold = UART5_UCR4_CTSTL, + .dma_enabled = UART5_DMA_ENABLE, + .dma_rxbuf_size = UART5_DMA_RXBUFSIZE, + .rx_threshold = UART5_UFCR_RXTL, + .tx_threshold = UART5_UFCR_TXTL, + .shared = UART5_SHARED_PERI, + .dma_tx_id = MXC_DMA_UART5_TX, + .dma_rx_id = MXC_DMA_UART5_RX, + .rxd_mux = MXC_UART_RXDMUX, + .ir_tx_inv = MXC_IRDA_TX_INV, + .ir_rx_inv = MXC_IRDA_RX_INV, + }, + [5] = { + .port = { + .membase = (void *)IO_ADDRESS(UART6_BASE_ADDR), + .mapbase = UART6_BASE_ADDR, + .iotype = SERIAL_IO_MEM, + .irq = UART6_INT1, + .fifosize = 32, + .flags = ASYNC_BOOT_AUTOCONF, + .line = 5, + }, + .ints_muxed = UART6_MUX_INTS, + .irqs = {UART6_INT2, UART6_INT3}, + .mode = UART6_MODE, + .ir_mode = UART6_IR, + .enabled = UART6_ENABLED, + .hardware_flow = UART6_HW_FLOW, + .cts_threshold = UART6_UCR4_CTSTL, + .dma_enabled = UART6_DMA_ENABLE, + .dma_rxbuf_size = UART6_DMA_RXBUFSIZE, + .rx_threshold = UART6_UFCR_RXTL, + .tx_threshold = UART6_UFCR_TXTL, + .shared = UART6_SHARED_PERI, + .dma_tx_id = MXC_DMA_UART6_TX, + .dma_rx_id = MXC_DMA_UART6_RX, + .rxd_mux = MXC_UART_RXDMUX, + .ir_tx_inv = MXC_IRDA_TX_INV, + .ir_rx_inv = MXC_IRDA_RX_INV, + }, +}; + +static struct platform_device mxc_uart_device1 = { + .name = "mxcintuart", + .id = 0, + .dev = { + .platform_data = &mxc_ports[0], + }, +}; + +static struct platform_device mxc_uart_device2 = { + .name = "mxcintuart", + .id = 1, + .dev = { + .platform_data = &mxc_ports[1], + }, +}; + +static struct platform_device mxc_uart_device3 = { + .name = "mxcintuart", + .id = 2, + .dev = { + .platform_data = &mxc_ports[2], + }, +}; + +static struct platform_device mxc_uart_device4 = { + .name = "mxcintuart", + .id = 3, + .dev = { + .platform_data = &mxc_ports[3], + }, +}; +static struct platform_device mxc_uart_device5 = { + .name = "mxcintuart", + .id = 4, + .dev = { + .platform_data = &mxc_ports[4], + }, +}; +static struct platform_device mxc_uart_device6 = { + .name = "mxcintuart", + .id = 5, + .dev = { + .platform_data = &mxc_ports[5], + }, +}; + +static int __init mxc_init_uart(void) +{ + /* Register all the MXC UART platform device structures */ + platform_device_register(&mxc_uart_device1); + platform_device_register(&mxc_uart_device2); + platform_device_register(&mxc_uart_device3); + + platform_device_register(&mxc_uart_device4); + + platform_device_register(&mxc_uart_device5); + platform_device_register(&mxc_uart_device6); + return 0; +} + +#else +static int __init mxc_init_uart(void) +{ + return 0; +} +#endif + +arch_initcall(mxc_init_uart); diff --git a/arch/arm/mach-mx27/serial.h b/arch/arm/mach-mx27/serial.h new file mode 100644 index 000000000000..11604c44cebe --- /dev/null +++ b/arch/arm/mach-mx27/serial.h @@ -0,0 +1,170 @@ +/* + * Copyright 2004-2009 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 + */ + +#ifndef __ARCH_ARM_MACH_MX27_SERIAL_H__ +#define __ARCH_ARM_MACH_MX27_SERIAL_H__ + +/*! + * @file mach-mx27/serial.h + * + * @ingroup MSL_MX27 + */ +#include <mach/mxc_uart.h> + +/* UART 1 configuration */ +/*! + * This option allows to choose either an interrupt-driven software controlled + * hardware flow control (set this option to 0) or hardware-driven hardware + * flow control (set this option to 1). + */ +#define UART1_HW_FLOW 1 +/*! + * This specifies the threshold at which the CTS pin is deasserted by the + * RXFIFO. Set this value in Decimal to anything from 0 to 32 for + * hardware-driven hardware flow control. Read the HW spec while specifying + * this value. When using interrupt-driven software controlled hardware + * flow control set this option to -1. + */ +#define UART1_UCR4_CTSTL 16 +/*! + * This is option to enable (set this option to 1) or disable DMA data transfer + */ +#define UART1_DMA_ENABLE 0 +/*! + * Specify the size of the DMA receive buffer. The buffer size should be same with + * sub buffer size which is defined in mxc_uart.c for all data can be transfered. + */ +#define UART1_DMA_RXBUFSIZE 128 +/*! + * Specify the MXC UART's Receive Trigger Level. This controls the threshold at + * which a maskable interrupt is generated by the RxFIFO. Set this value in + * Decimal to anything from 0 to 32. Read the HW spec while specifying this + * value. + */ +#define UART1_UFCR_RXTL 16 +/*! + * Specify the MXC UART's Transmit Trigger Level. This controls the threshold at + * which a maskable interrupt is generated by the TxFIFO. Set this value in + * Decimal to anything from 0 to 32. Read the HW spec while specifying this + * value. + */ +#define UART1_UFCR_TXTL 16 +/* UART 2 configuration */ +#define UART2_HW_FLOW 1 +#define UART2_UCR4_CTSTL 16 +#define UART2_DMA_ENABLE 0 +#define UART2_DMA_RXBUFSIZE 512 +#define UART2_UFCR_RXTL 16 +#define UART2_UFCR_TXTL 16 +/* UART 3 configuration */ +#define UART3_HW_FLOW 0 +#define UART3_UCR4_CTSTL -1 +#define UART3_DMA_ENABLE 0 +#define UART3_DMA_RXBUFSIZE 512 +#define UART3_UFCR_RXTL 16 +#define UART3_UFCR_TXTL 16 +/* UART 4 configuration */ +#define UART4_HW_FLOW 1 +#define UART4_UCR4_CTSTL 16 +#define UART4_DMA_ENABLE 0 +#define UART4_DMA_RXBUFSIZE 512 +#define UART4_UFCR_RXTL 16 +#define UART4_UFCR_TXTL 16 +/* UART 5 configuration */ +#define UART5_HW_FLOW 1 +#define UART5_UCR4_CTSTL 16 +#define UART5_DMA_ENABLE 0 +#define UART5_DMA_RXBUFSIZE 512 +#define UART5_UFCR_RXTL 16 +#define UART5_UFCR_TXTL 16 +/* UART 6 configuration */ +#define UART6_HW_FLOW 1 +#define UART6_UCR4_CTSTL 16 +#define UART6_DMA_ENABLE 0 +#define UART6_DMA_RXBUFSIZE 512 +#define UART6_UFCR_RXTL 16 +#define UART6_UFCR_TXTL 16 +/* + * UART Chip level Configuration that a user may not have to edit. These + * configuration vary depending on how the UART module is integrated with + * the ARM core + */ +/* + * Is the MUXED interrupt output sent to the ARM core + */ +#define INTS_NOTMUXED 0 +#define INTS_MUXED 1 +/* UART 1 configuration */ +/*! + * This define specifies whether the muxed ANDed interrupt line or the + * individual interrupts from the UART port is integrated with the ARM core. + * There exists a define like this for each UART port. Valid values that can + * be used are \b INTS_NOTMUXED or \b INTS_MUXED. + */ +#define UART1_MUX_INTS INTS_MUXED +/*! + * This define specifies the transmitter interrupt number or the interrupt + * number of the ANDed interrupt in case the interrupts are muxed. There exists + * a define like this for each UART port. + */ +#define UART1_INT1 MXC_INT_UART1 +/*! + * This define specifies the receiver interrupt number. If the interrupts of + * the UART are muxed, then we specify here a dummy value -1. There exists a + * define like this for each UART port. + */ +#define UART1_INT2 -1 +/*! + * This specifies the master interrupt number. If the interrupts of the UART + * are muxed, then we specify here a dummy value of -1. There exists a define + * like this for each UART port. + */ +#define UART1_INT3 -1 +/*! + * This specifies if the UART is a shared peripheral. It holds the shared + * peripheral number if it is shared or -1 if it is not shared. There exists + * a define like this for each UART port. + */ +#define UART1_SHARED_PERI -1 +/* UART 2 configuration */ +#define UART2_MUX_INTS INTS_MUXED +#define UART2_INT1 MXC_INT_UART2 +#define UART2_INT2 -1 +#define UART2_INT3 -1 +#define UART2_SHARED_PERI -1 +/* UART 3 configuration */ +#define UART3_MUX_INTS INTS_MUXED +#define UART3_INT1 MXC_INT_UART3 +#define UART3_INT2 -1 +#define UART3_INT3 -1 +#define UART3_SHARED_PERI -1 +/* UART 4 configuration */ +#define UART4_MUX_INTS INTS_MUXED +#define UART4_INT1 MXC_INT_UART4 +#define UART4_INT2 -1 +#define UART4_INT3 -1 +#define UART4_SHARED_PERI -1 +/* UART 5 configuration */ +#define UART5_MUX_INTS INTS_MUXED +#define UART5_INT1 MXC_INT_UART5 +#define UART5_INT2 -1 +#define UART5_INT3 -1 +#define UART5_SHARED_PERI -1 +/* UART 6 configuration */ +#define UART6_MUX_INTS INTS_MUXED +#define UART6_INT1 MXC_INT_UART6 +#define UART6_INT2 -1 +#define UART6_INT3 -1 +#define UART6_SHARED_PERI -1 + +#endif /* __ARCH_ARM_MACH_MX27_SERIAL_H__ */ diff --git a/arch/arm/mach-mx27/system.c b/arch/arm/mach-mx27/system.c new file mode 100644 index 000000000000..fb8fc6bb0f0b --- /dev/null +++ b/arch/arm/mach-mx27/system.c @@ -0,0 +1,60 @@ +/* + * Copyright (C) 1999 ARM Limited + * Copyright (C) 2000 Deep Blue Solutions Ltd + * Copyright 2006-2009 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/clk.h> +#include <linux/io.h> +#include <mach/hardware.h> +#include <asm/proc-fns.h> +#include <asm/system.h> + +/*! + * @defgroup MSL_MX27 i.MX27 Machine Specific Layer (MSL) + */ + +/*! + * @file mach-mx27/system.c + * @brief This file contains idle and reset functions. + * + * @ingroup MSL_MX27 + */ + +/*! + * This function puts the CPU into idle mode. It is called by default_idle() + * in process.c file. + */ +void arch_idle(void) +{ + /* + * This should do all the clock switching + * and wait for interrupt tricks. + */ + cpu_do_idle(); +} + +/* + * This function resets the system. It is called by machine_restart(). + * + * @param mode indicates different kinds of resets + */ +void arch_reset(char mode) +{ + /* Assert Watchdog Reset signal */ + mxc_wd_reset(); +} diff --git a/arch/arm/mach-mx27/time.c b/arch/arm/mach-mx27/time.c new file mode 100644 index 000000000000..79a4894bc9f6 --- /dev/null +++ b/arch/arm/mach-mx27/time.c @@ -0,0 +1,240 @@ +/* + * Copyright 2004-2009 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 + */ + +/* System Timer Interrupt reconfigured to run in free-run mode. + * Author: Vitaly Wool + * Copyright 2004 MontaVista Software Inc. + */ + +/*! + * @defgroup Timers_MX27 OS Tick Timer + * @ingroup MSL_MX27 + */ +/*! + * @file mach-mx27/time.c + * @brief This file contains OS tick timer implementation. + * + * This file contains OS tick timer implementation. + * + * @ingroup Timers_MX27 + */ + +#include <linux/module.h> +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/irq.h> +#include <linux/io.h> +#include <linux/clocksource.h> +#include <linux/clockchips.h> +#include <linux/mtd/xip.h> +#include <mach/hardware.h> +#include <asm/mach/time.h> + +/*! + * GPT register address definitions + */ +#define GPT_BASE_ADDR (IO_ADDRESS(GPT1_BASE_ADDR)) +#define MXC_GPT_GPTCR (GPT_BASE_ADDR + 0x00) +#define MXC_GPT_GPTPR (GPT_BASE_ADDR + 0x04) +#define MXC_GPT_GPTOCR1 (GPT_BASE_ADDR + 0x08) +#define MXC_GPT_GPTICR1 (GPT_BASE_ADDR + 0x0C) +#define MXC_GPT_GPTCNT (GPT_BASE_ADDR + 0x10) +#define MXC_GPT_GPTSR (GPT_BASE_ADDR + 0x14) + +/*! + * GPT Control register bit definitions + */ +#define GPTCR_COMPEN (1 << 4) +#define GPTCR_SWR (1 << 15) +#define GPTCR_FRR (1 << 8) + +#define GPTCR_CLKSRC_SHIFT 1 +#define GPTCR_CLKSRC_MASK (7 << GPTCR_CLKSRC_SHIFT) +#define GPTCR_CLKSRC_NOCLOCK (0 << GPTCR_CLKSRC_SHIFT) +#define GPTCR_CLKSRC_HIGHFREQ (1 << GPTCR_CLKSRC_SHIFT) +#define GPTCR_CLKSRC_CLKIN (3 << GPTCR_CLKSRC_SHIFT) +#define GPTCR_CLKSRC_CLK32K (4 << GPTCR_CLKSRC_SHIFT) + +#define GPTCR_ENABLE (1 << 0) + +#define GPTSR_OF1 (1 << 0) + +extern unsigned long clk_early_get_timer_rate(void); + +static int mxc_gpt_set_next_event(unsigned long cycles, + struct clock_event_device *evt) +{ + unsigned long now, expires; + u32 reg; + + now = __raw_readl(MXC_GPT_GPTCNT); + expires = now + cycles; + __raw_writel(expires, MXC_GPT_GPTOCR1); + __raw_writel(GPTSR_OF1, MXC_GPT_GPTSR); + + /* enable interrupt */ + reg = __raw_readl(MXC_GPT_GPTCR); + reg |= GPTCR_COMPEN; + __raw_writel(reg, MXC_GPT_GPTCR); + + return 0; +} + +static void mxc_gpt_set_mode(enum clock_event_mode mode, + struct clock_event_device *evt) +{ + u32 reg; + switch (mode) { + case CLOCK_EVT_MODE_PERIODIC: + panic("MXC GPT: CLOCK_EVT_MODE_PERIODIC not supported\n"); + break; + case CLOCK_EVT_MODE_ONESHOT: + break; + case CLOCK_EVT_MODE_UNUSED: + case CLOCK_EVT_MODE_SHUTDOWN: + /* Disable interrupts */ + reg = __raw_readl(MXC_GPT_GPTCR); + reg &= ~GPTCR_COMPEN; + __raw_writel(reg, MXC_GPT_GPTCR); + break; + case CLOCK_EVT_MODE_RESUME: + break; + } +} + +static struct clock_event_device gpt_clockevent = { + .name = "mxc_gpt", + .features = CLOCK_EVT_FEAT_ONESHOT, + .rating = 300, + .shift = 32, + .set_next_event = mxc_gpt_set_next_event, + .set_mode = mxc_gpt_set_mode, +}; + +/*! + * This is the timer interrupt service routine to do required tasks. + * It also services the WDOG timer at the frequency of twice per WDOG + * timeout value. For example, if the WDOG's timeout value is 4 (2 + * seconds since the WDOG runs at 0.5Hz), it will be serviced once + * every 2/2=1 second. + * + * @param irq GPT interrupt source number (not used) + * @param dev_id this parameter is not used + * @return always returns \b IRQ_HANDLED as defined in + * include/linux/interrupt.h. + */ +static irqreturn_t mxc_timer_interrupt(int irq, void *dev_id) +{ + unsigned int gptsr; + u32 reg; + + gptsr = __raw_readl(MXC_GPT_GPTSR); + if (gptsr & GPTSR_OF1) { + /* Disable interrupt */ + reg = __raw_readl(MXC_GPT_GPTCR); + reg &= ~GPTCR_COMPEN; + __raw_writel(reg, MXC_GPT_GPTCR); + /* Clear interrupt */ + __raw_writel(GPTSR_OF1, MXC_GPT_GPTSR); + + gpt_clockevent.event_handler(&gpt_clockevent); + } + + return IRQ_HANDLED; +} + +/*! + * The clockevents timer interrupt structure. + */ +static struct irqaction timer_irq = { + .name = "gpt-irq", + .flags = IRQF_DISABLED, + .handler = mxc_timer_interrupt, +}; + +static cycle_t __xipram mxc_gpt_read(void) +{ + return __raw_readl(MXC_GPT_GPTCNT); +} + +static struct clocksource gpt_clocksrc = { + .name = "mxc_gpt", + .rating = 300, + .read = mxc_gpt_read, + .mask = CLOCKSOURCE_MASK(32), + .shift = 24, + .flags = CLOCK_SOURCE_IS_CONTINUOUS | CLOCK_SOURCE_VALID_FOR_HRES, +}; + +/*! + * This function is used to initialize the GPT as a clocksource and clockevent. + * It is called by the start_kernel() during system startup. + */ +void __init mxc_init_time(void) +{ + int ret; + unsigned long rate; + u32 reg, div; + + /* Reset GPT */ + __raw_writel(GPTCR_SWR, MXC_GPT_GPTCR); + while ((__raw_readl(MXC_GPT_GPTCR) & GPTCR_SWR) != 0) + mb(); + + /* Normal clk api are not yet initialized, so use early verion */ + rate = clk_early_get_timer_rate(); + if (rate == 0) + panic("MXC GPT: Can't get timer clock rate\n"); + +#ifdef CLOCK_TICK_RATE + div = rate / CLOCK_TICK_RATE; + WARN_ON((div * CLOCK_TICK_RATE) != rate); +#else /* Hopefully CLOCK_TICK_RATE will go away soon */ + div = 1; + while ((rate / div) > 20000000) { + div++; + } +#endif + rate /= div; + __raw_writel(div - 1, MXC_GPT_GPTPR); + + reg = GPTCR_FRR | GPTCR_CLKSRC_HIGHFREQ | GPTCR_ENABLE; + __raw_writel(reg, MXC_GPT_GPTCR); + + gpt_clocksrc.mult = clocksource_hz2mult(rate, gpt_clocksrc.shift); + ret = clocksource_register(&gpt_clocksrc); + if (ret < 0) { + goto err; + } + + gpt_clockevent.mult = div_sc(rate, NSEC_PER_SEC, gpt_clockevent.shift); + gpt_clockevent.max_delta_ns = clockevent_delta2ns(-1, &gpt_clockevent); + gpt_clockevent.min_delta_ns = clockevent_delta2ns(1, &gpt_clockevent); + + gpt_clockevent.cpumask = cpumask_of_cpu(0); + clockevents_register_device(&gpt_clockevent); + + ret = setup_irq(MXC_INT_GPT, &timer_irq); + if (ret < 0) { + goto err; + } + + pr_info("MXC GPT timer initialized, rate = %lu\n", rate); + return; + err: + panic("Unable to initialize timer\n"); +} + +struct sys_timer mxc_timer = { + .init = mxc_init_time, +}; diff --git a/arch/arm/mach-mx27/usb.h b/arch/arm/mach-mx27/usb.h new file mode 100644 index 000000000000..7824814a6ecd --- /dev/null +++ b/arch/arm/mach-mx27/usb.h @@ -0,0 +1,116 @@ +/* + * Copyright 2005-2008 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 + */ + + +extern int usbotg_init(struct platform_device *pdev); +extern void usbotg_uninit(struct fsl_usb2_platform_data *pdata); +extern int gpio_usbotg_fs_active(void); +extern void gpio_usbotg_fs_inactive(void); +extern int gpio_usbotg_hs_active(void); +extern void gpio_usbotg_hs_inactive(void); +extern struct platform_device *host_pdev_register(struct resource *res, + int n_res, struct fsl_usb2_platform_data *config); + +extern int fsl_usb_host_init(struct platform_device *pdev); +extern void fsl_usb_host_uninit(struct fsl_usb2_platform_data *pdata); +extern int gpio_usbh1_active(void); +extern void gpio_usbh1_inactive(void); +extern int gpio_usbh2_active(void); +extern void gpio_usbh2_inactive(void); + +/* + * Determine which platform_data struct to use, based on which + * transceiver is configured. + * PDATA is a pointer to it. + */ +#if defined(CONFIG_ISP1504_MXC) +static struct fsl_usb2_platform_data __maybe_unused dr_1504_config; +#define PDATA (&dr_1504_config) +#elif defined(CONFIG_ISP1301_MXC) +static struct fsl_usb2_platform_data __maybe_unused dr_1301_config; +#define PDATA (&dr_1301_config) +#elif defined(CONFIG_MC13783_MXC) +static struct fsl_usb2_platform_data __maybe_unused dr_13783_config; +#define PDATA (&dr_13783_config) +#endif + + +/* + * Used to set pdata->operating_mode before registering the platform_device. + * If OTG is configured, the controller operates in OTG mode, + * otherwise it's either host or device. + */ +#ifdef CONFIG_USB_OTG +#define DR_UDC_MODE FSL_USB2_DR_OTG +#define DR_HOST_MODE FSL_USB2_DR_OTG +#else +#define DR_UDC_MODE FSL_USB2_DR_DEVICE +#define DR_HOST_MODE FSL_USB2_DR_HOST +#endif + + +#ifdef CONFIG_USB_EHCI_ARC_OTG +static inline void dr_register_host(struct resource *r, int rs) +{ + PDATA->operating_mode = DR_HOST_MODE; + host_pdev_register(r, rs, PDATA); +} +#else +static inline void dr_register_host(struct resource *r, int rs) +{ +} +#endif + +#ifdef CONFIG_USB_GADGET_ARC +static struct platform_device dr_udc_device; + +static inline void dr_register_udc(void) +{ + PDATA->operating_mode = DR_UDC_MODE; + dr_udc_device.dev.platform_data = PDATA; + + if (platform_device_register(&dr_udc_device)) + printk(KERN_ERR "usb: can't register DR gadget\n"); + else + printk(KERN_INFO "usb: DR gadget (%s) registered\n", + PDATA->transceiver); +} +#else +static inline void dr_register_udc(void) +{ +} +#endif + +#ifdef CONFIG_USB_OTG +static struct platform_device dr_otg_device; + +/* + * set the proper operating_mode and + * platform_data pointer, then register the + * device. + */ +static inline void dr_register_otg(void) +{ + PDATA->operating_mode = FSL_USB2_DR_OTG; + dr_otg_device.dev.platform_data = PDATA; + + if (platform_device_register(&dr_otg_device)) + printk(KERN_ERR "usb: can't register otg device\n"); + else + printk(KERN_INFO "usb: DR OTG registered\n"); +} +#else +static inline void dr_register_otg(void) +{ +} +#endif diff --git a/arch/arm/mach-mx27/usb_dr.c b/arch/arm/mach-mx27/usb_dr.c new file mode 100644 index 000000000000..e67bee726412 --- /dev/null +++ b/arch/arm/mach-mx27/usb_dr.c @@ -0,0 +1,126 @@ +#define DEBUG +/* + * Copyright 2005-2009 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/kernel.h> +#include <linux/types.h> +#include <linux/platform_device.h> +#include <linux/fsl_devices.h> +#include <mach/arc_otg.h> +#include "usb.h" + +/* + * platform data structs + * - Which one to use is determined by CONFIG options in usb.h + * - operating_mode plugged at run time + */ +static struct fsl_usb2_platform_data __maybe_unused dr_13783_config = { + .name = "DR", + .platform_init = usbotg_init, + .platform_uninit = usbotg_uninit, + .phy_mode = FSL_USB2_PHY_SERIAL, + .power_budget = 500, /* 500 mA max power */ + .gpio_usb_active = gpio_usbotg_fs_active, + .gpio_usb_inactive = gpio_usbotg_fs_inactive, + .transceiver = "mc13783", +}; + +static struct fsl_usb2_platform_data __maybe_unused dr_1301_config = { + .name = "DR", + .platform_init = usbotg_init, + .platform_uninit = usbotg_uninit, + .phy_mode = FSL_USB2_PHY_SERIAL, + .power_budget = 500, /* 500 mA max power */ + .gpio_usb_active = gpio_usbotg_fs_active, + .gpio_usb_inactive = gpio_usbotg_fs_inactive, + .transceiver = "isp1301", +}; + +static struct fsl_usb2_platform_data __maybe_unused dr_1504_config = { + .name = "DR", + .platform_init = usbotg_init, + .platform_uninit = usbotg_uninit, + .phy_mode = FSL_USB2_PHY_ULPI, + .power_budget = 500, /* 500 mA max power */ + .gpio_usb_active = gpio_usbotg_hs_active, + .gpio_usb_inactive = gpio_usbotg_hs_inactive, + .transceiver = "isp1504", +}; + + +/* + * resources + */ +static struct resource otg_resources[] = { + [0] = { + .start = (u32)(USB_OTGREGS_BASE), + .end = (u32)(USB_OTGREGS_BASE + 0x1ff), + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = MXC_INT_USB3, + .flags = IORESOURCE_IRQ, + }, +}; + + +static u64 dr_udc_dmamask = ~(u32) 0; +static void dr_udc_release(struct device *dev) +{ +} + +static u64 dr_otg_dmamask = ~(u32) 0; +static void dr_otg_release(struct device *dev) +{ +} + +/* + * platform device structs + * dev.platform_data field plugged at run time + */ +static struct platform_device __maybe_unused dr_udc_device = { + .name = "fsl-usb2-udc", + .id = -1, + .dev = { + .release = dr_udc_release, + .dma_mask = &dr_udc_dmamask, + .coherent_dma_mask = 0xffffffff, + }, + .resource = otg_resources, + .num_resources = ARRAY_SIZE(otg_resources), +}; + +static struct platform_device __maybe_unused dr_otg_device = { + .name = "fsl-usb2-otg", + .id = -1, + .dev = { + .release = dr_otg_release, + .dma_mask = &dr_otg_dmamask, + .coherent_dma_mask = 0xffffffff, + }, + .resource = otg_resources, + .num_resources = ARRAY_SIZE(otg_resources), +}; + +static int __init usb_dr_init(void) +{ + pr_debug("%s: \n", __func__); + + dr_register_otg(); + dr_register_host(otg_resources, ARRAY_SIZE(otg_resources)); + dr_register_udc(); + + return 0; +} + +module_init(usb_dr_init); diff --git a/arch/arm/mach-mx27/usb_h1.c b/arch/arm/mach-mx27/usb_h1.c new file mode 100644 index 000000000000..5c6c9c59fb3b --- /dev/null +++ b/arch/arm/mach-mx27/usb_h1.c @@ -0,0 +1,53 @@ +/* + * Copyright 2005-2009 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/kernel.h> +#include <linux/types.h> +#include <linux/platform_device.h> +#include <linux/fsl_devices.h> +#include <mach/arc_otg.h> +#include "usb.h" + +static struct fsl_usb2_platform_data usbh1_config = { + .name = "Host 1", + .platform_init = fsl_usb_host_init, + .platform_uninit = fsl_usb_host_uninit, + .operating_mode = FSL_USB2_MPH_HOST, + .phy_mode = FSL_USB2_PHY_SERIAL, + .power_budget = 500, /* 500 mA max power */ + .gpio_usb_active = gpio_usbh1_active, + .gpio_usb_inactive = gpio_usbh1_inactive, + .transceiver = "serial", +}; + +static struct resource usbh1_resources[] = { + [0] = { + .start = (u32) (USB_H1REGS_BASE), + .end = (u32) (USB_H1REGS_BASE + 0x1ff), + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = MXC_INT_USB1, + .flags = IORESOURCE_IRQ, + }, +}; + +static int __init usbh1_init(void) +{ + pr_debug("%s: \n", __func__); + + host_pdev_register(usbh1_resources, ARRAY_SIZE(usbh1_resources), + &usbh1_config); + return 0; +} +module_init(usbh1_init); diff --git a/arch/arm/mach-mx27/usb_h2.c b/arch/arm/mach-mx27/usb_h2.c new file mode 100644 index 000000000000..028941a7b47c --- /dev/null +++ b/arch/arm/mach-mx27/usb_h2.c @@ -0,0 +1,53 @@ +/* + * Copyright 2005-2009 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/kernel.h> +#include <linux/types.h> +#include <linux/platform_device.h> +#include <linux/fsl_devices.h> +#include <mach/arc_otg.h> +#include "usb.h" + +static struct fsl_usb2_platform_data usbh2_config = { + .name = "Host 2", + .platform_init = fsl_usb_host_init, + .platform_uninit = fsl_usb_host_uninit, + .operating_mode = FSL_USB2_MPH_HOST, + .phy_mode = FSL_USB2_PHY_ULPI, + .power_budget = 500, /* 500 mA max power */ + .gpio_usb_active = gpio_usbh2_active, + .gpio_usb_inactive = gpio_usbh2_inactive, + .transceiver = "isp1504", +}; + +static struct resource usbh2_resources[] = { + [0] = { + .start = (u32) (USB_H2REGS_BASE), + .end = (u32) (USB_H2REGS_BASE + 0x1ff), + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = MXC_INT_USB2, + .flags = IORESOURCE_IRQ, + }, +}; + +static int __init usbh2_init(void) +{ + pr_debug("%s: \n", __func__); + + host_pdev_register(usbh2_resources, ARRAY_SIZE(usbh2_resources), + &usbh2_config); + return 0; +} +module_init(usbh2_init); |