diff options
Diffstat (limited to 'arch/arm/mach-mx51')
40 files changed, 17309 insertions, 0 deletions
diff --git a/arch/arm/mach-mx51/Kconfig b/arch/arm/mach-mx51/Kconfig new file mode 100644 index 000000000000..5510ec5d5638 --- /dev/null +++ b/arch/arm/mach-mx51/Kconfig @@ -0,0 +1,146 @@ +menu "MX51 Options" + depends on ARCH_MX51 + +config FORCE_MAX_ZONEORDER + int "MAX_ORDER" + default "13" + +config MX51_OPTIONS + bool + default y + select CPU_V7 + select USB_ARCH_HAS_EHCI + select MXC_TZIC + +config MACH_MX51_3DS + bool "Support MX51 3-Stack platforms" + default y + help + Include support for MX51 3-Stack platform. This includes specific + configurations for the board and its peripherals. + +config MACH_MX51_BABBAGE + bool "Support MX51 BABBAGE platforms" + help + Include support for MX51 Babbage platform. This includes specific + configurations for the board and its peripherals. + +config MACH_CCWMX51JS + bool "Support for the ConnectCore Wi-MX51 module, on the JSK base board" + help + Include support for the Digi ConnectCore Wi-MX51 Embedded Module, on the + JumpStart Kit base board. This includes specific configurations for the + peripherals on that base board. + +config MACH_CCMX51JS + bool "Support for the ConnectCore MX51 module, on the JSK base board" + help + Include support for the Digi ConnectCore MX51 Embedded Module, on the + JumpStart Kit base board. This includes specific configurations for the + peripherals on that base board. + +config MACH_CCWMX51 + bool "Support for the ConnectCore Wi-MX51 module" + help + Include support for the Digi ConnectCore Wi-MX51 Embedded Module, on a + custom board. The machine file should be modified to include support for + the interfaces available in that board. + +config MACH_CCMX51 + bool "Support for the ConnectCore MX51 module" + help + Include support for the Digi ConnectCore Wi-MX51 Embedded Module, on a + custom board. The machine file should be modified to include support for + the interfaces available in that board. + +config MXC_SDMA_API + bool "Use SDMA API" + default y + help + This selects the Freescale MXC SDMA API. + If unsure, say N. + +config ARCH_MXC_HAS_NFC_V3 + bool "MXC NFC Hardware Version 3" + depends on ARCH_MX51 + default y + help + This selects the Freescale MXC Nand Flash Controller Hardware Version 3 + If unsure, say N. + +config ARCH_MXC_HAS_NFC_V3_2 + bool "MXC NFC Hardware Version 3.2" + depends on ARCH_MXC_HAS_NFC_V3 + default y + help + This selects the Freescale MXC Nand Flash Controller Hardware Version 3.2 + If unsure, say N. + +menu "SDMA options" + depends on MXC_SDMA_API + +config SDMA_IRAM + bool "Use Internal RAM for SDMA transfer" + default n + help + Support Internal RAM as SDMA buffer or control structures + +config SDMA_IRAM_SIZE + hex "Reserved bytes of IRAM for SDMA (0x800-0x1000)" + range 0x800 0x1000 + depends on SDMA_IRAM + default "0x1000" + help + Set the size of IRAM for SDMA. It must be a multiple of 512bytes. +endmenu + +menu "I2C Options" + +config I2C_MXC_SELECT1 + bool "Enable I2C1 module" + default y + depends on I2C_MXC + help + Enable MX51 I2C1 module. + +config I2C_MXC_SELECT2 + bool "Enable I2C2 module" + default n + depends on I2C_MXC + help + Enable MX51 I2C2 module. + +config I2C_MXC_SELECT3 + bool "Enable I2C3 module" + default n + depends on I2C_MXC + help + Enable MX51 I2C3 module. + +endmenu + +menu "Serial Port Options" +config UART1_ENABLED + bool "Enable UART1" + default y + depends on SERIAL_MXC + help + Enable the MX51 UART1 interface + +config UART2_ENABLED + bool "Enable UART2" + default y + depends on SERIAL_MXC + help + Enable the MX51 UART2 interface + +config UART3_ENABLED + bool "Enable UART3" + default y + depends on SERIAL_MXC + help + Enable the MX51 UART3 interface +endmenu + +endmenu + diff --git a/arch/arm/mach-mx51/Makefile b/arch/arm/mach-mx51/Makefile new file mode 100644 index 000000000000..f0a4070bb26b --- /dev/null +++ b/arch/arm/mach-mx51/Makefile @@ -0,0 +1,23 @@ +# +# Makefile for the linux kernel. +# + +# Object file lists. + + +obj-y := system.o iomux.o cpu.o mm.o clock.o devices.o serial.o dma.o lpmodes.o pm.o sdram_autogating.o bus_freq.o + +obj-y += dummy_gpio.o + +obj-$(CONFIG_CPU_V7) += wfi.o suspend.o +obj-$(CONFIG_MACH_MX51_3DS) += mx51_3stack.o mx51_3stack_gpio.o mx51_3stack_pmic_mc13892.o +obj-$(CONFIG_MACH_MX51_BABBAGE) += mx51_babbage.o mx51_babbage_gpio.o mx51_babbage_pmic_mc13892.o +obj-$(CONFIG_MACH_CCWMX51JS) += mx51_ccwmx51js.o mx51_ccwmx51js_gpio.o mx51_ccwmx51js_pmic_mc13892.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-mx51/Makefile.boot b/arch/arm/mach-mx51/Makefile.boot new file mode 100644 index 000000000000..9939a19d99a1 --- /dev/null +++ b/arch/arm/mach-mx51/Makefile.boot @@ -0,0 +1,3 @@ + zreladdr-y := 0x90008000 +params_phys-y := 0x90000100 +initrd_phys-y := 0x90800000 diff --git a/arch/arm/mach-mx51/board-ccwmx51.h b/arch/arm/mach-mx51/board-ccwmx51.h new file mode 100644 index 000000000000..6696c27c5c36 --- /dev/null +++ b/arch/arm/mach-mx51/board-ccwmx51.h @@ -0,0 +1,56 @@ +/* + * Copyright 2010 Digi International, 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_CCWMX51_H__ +#define __ASM_ARCH_MXC_BOARD_CCWMX51_H__ + +#include <mach/mxc_uart.h> + +/* UART 1 configuration */ +#if defined CONFIG_UART1_ENABLED +#define UART1_ENABLED 1 +#else +#define UART1_ENABLED 0 +#endif +#define UART1_MODE MODE_DCE +#define UART1_IR NO_IRDA + +/* UART 2 configuration */ +#if defined CONFIG_UART2_ENABLED +#define UART2_ENABLED 1 +#else +#define UART2_ENABLED 0 +#endif +#define UART2_MODE MODE_DCE +#define UART2_IR NO_IRDA + +/* UART 3 configuration */ +#if defined CONFIG_UART3_ENABLED +#define UART3_ENABLED 1 +#else +#define UART3_ENABLED 0 +#endif +#define UART3_MODE MODE_DCE +#define UART3_IR NO_IRDA + +/*! + * 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 + +#define MXC_LL_UART_PADDR UART1_BASE_ADDR +#define MXC_LL_UART_VADDR AIPS1_IO_ADDRESS(UART1_BASE_ADDR) + +#endif /* __ASM_ARCH_MXC_BOARD_CCWMX51_H__ */ diff --git a/arch/arm/mach-mx51/board-mx51_3stack.h b/arch/arm/mach-mx51/board-mx51_3stack.h new file mode 100644 index 000000000000..52f99e01f40d --- /dev/null +++ b/arch/arm/mach-mx51/board-mx51_3stack.h @@ -0,0 +1,125 @@ +/* + * Copyright 2008-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_MX51_3STACK_H__ +#define __ASM_ARCH_MXC_BOARD_MX51_3STACK_H__ + +/*! + * @defgroup BRDCFG_MX51 Board Configuration Options + * @ingroup MSL_MX51 + */ + +/*! + * @file mach-mx51/board-mx51_3stack.h + * + * @brief This file contains all the board level configuration options. + * + * It currently hold the options defined for MX51 3Stack Platform. + * + * @ingroup BRDCFG_MX51 + */ + +/* + * Include Files + */ +#include <mach/mxc_uart.h> + +/*! + * @name MXC UART 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 NO_IRDA +#define UART3_ENABLED 1 + +#define MXC_LL_UART_PADDR UART1_BASE_ADDR +#define MXC_LL_UART_VADDR AIPS1_IO_ADDRESS(UART1_BASE_ADDR) + +#define DEBUG_BOARD_BASE_ADDRESS(n) (n) +/* LAN9217 ethernet base address */ +#define LAN9217_BASE_ADDR(n) (DEBUG_BOARD_BASE_ADDRESS(n)) +/* External UART */ +#define UARTA_BASE_ADDR(n) (DEBUG_BOARD_BASE_ADDRESS(n) + 0x8000) +#define UARTB_BASE_ADDR(n) (DEBUG_BOARD_BASE_ADDRESS(n) + 0x10000) + +#define BOARD_IO_ADDR(n) (DEBUG_BOARD_BASE_ADDRESS(n) + 0x20000) +/* LED switchs */ +#define LED_SWITCH_REG 0x00 +/* buttons */ +#define SWITCH_BUTTONS_REG 0x08 +/* status, interrupt */ +#define INTR_STATUS_REG 0x10 +#define INTR_MASK_REG 0x38 +#define INTR_RESET_REG 0x20 +/* magic word for debug CPLD */ +#define MAGIC_NUMBER1_REG 0x40 +#define MAGIC_NUMBER2_REG 0x48 +/* CPLD code version */ +#define CPLD_CODE_VER_REG 0x50 +/* magic word for debug CPLD */ +#define MAGIC_NUMBER3_REG 0x58 +/* module reset register*/ +#define MODULE_RESET_REG 0x60 +/* CPU ID and Personality ID */ +#define MCU_BOARD_ID_REG 0x68 + +/* interrupts like external uart , external ethernet etc*/ +#define EXPIO_PARENT_INT IOMUX_TO_IRQ(MX51_PIN_GPIO1_6) + +#define EXPIO_INT_ENET (MXC_EXP_IO_BASE + 0) +#define EXPIO_INT_XUART_A (MXC_EXP_IO_BASE + 1) +#define EXPIO_INT_XUART_B (MXC_EXP_IO_BASE + 2) +#define EXPIO_INT_BUTTON_A (MXC_EXP_IO_BASE + 3) +#define EXPIO_INT_BUTTON_B (MXC_EXP_IO_BASE + 4) + +/*! This is System IRQ used by LAN9217 */ +#define LAN9217_IRQ EXPIO_INT_ENET + +extern int __init mx51_3stack_init_mc13892(void); + +#endif /* __ASM_ARCH_MXC_BOARD_MX51_3STACK_H__ */ diff --git a/arch/arm/mach-mx51/board-mx51_babbage.h b/arch/arm/mach-mx51/board-mx51_babbage.h new file mode 100644 index 000000000000..1e6c7c8e849e --- /dev/null +++ b/arch/arm/mach-mx51/board-mx51_babbage.h @@ -0,0 +1,85 @@ +/* + * Copyright 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_MX51_BABBAGE_H__ +#define __ASM_ARCH_MXC_BOARD_MX51_BABBAGE_H__ + +/*! + * @defgroup BRDCFG_MX51 Board Configuration Options + * @ingroup MSL_MX51 + */ + +/*! + * @file mach-mx51/board-mx51_babbage.h + * + * @brief This file contains all the board level configuration options. + * + * It currently hold the options defined for MX51 Babbage Platform. + * + * @ingroup BRDCFG_MX51 + */ + +/* + * Include Files + */ +#include <mach/mxc_uart.h> + +/*! + * @name MXC UART 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 IRDA +#define UART2_ENABLED 1 +/* UART 3 configuration */ +#define UART3_MODE MODE_DTE +#define UART3_IR NO_IRDA +#define UART3_ENABLED 1 + +#define MXC_LL_UART_PADDR UART1_BASE_ADDR +#define MXC_LL_UART_VADDR AIPS1_IO_ADDRESS(UART1_BASE_ADDR) + +extern int __init mx51_babbage_init_mc13892(void); + +#endif /* __ASM_ARCH_MXC_BOARD_MX51_BABBAGE_H__ */ diff --git a/arch/arm/mach-mx51/board.h b/arch/arm/mach-mx51/board.h new file mode 100644 index 000000000000..e269ab46fb5a --- /dev/null +++ b/arch/arm/mach-mx51/board.h @@ -0,0 +1,24 @@ +/* + * Copyright 2010 Digi International, 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_H__ +#define __ASM_ARCH_MXC_BOARD_H__ + +#if defined(CONFIG_MACH_CCWMX51JS) || defined(CONFIG_MACH_CCMX51JS) || \ + defined(CONFIG_MACH_CCWMX51) || defined(CONFIG_MACH_CCMX51) +#include "board-ccwmx51.h" +#elif defined(MACH_MX51_3DS) +#include "board-3stack.h" +#elif defined(MACH_MX51_BABBAGE) +#include "board-mx51_babbage.h" +#endif + +#endif /* __ASM_ARCH_MXC_BOARD_H__ */ diff --git a/arch/arm/mach-mx51/bus_freq.c b/arch/arm/mach-mx51/bus_freq.c new file mode 100644 index 000000000000..a1c4777ede6a --- /dev/null +++ b/arch/arm/mach-mx51/bus_freq.c @@ -0,0 +1,579 @@ +/* + * Copyright 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 bus_freq.c + * + * @brief A common API for the Freescale Semiconductor i.MXC CPUfreq module + * and DVFS CORE module. + * + * The APIs are for setting bus frequency to low or high. + * + * @ingroup PM + */ +#include <asm/io.h> +#include <linux/proc_fs.h> +#include <linux/clk.h> +#include <linux/delay.h> +#include <linux/platform_device.h> +#include <linux/regulator/consumer.h> +#include <mach/hardware.h> +#include <mach/clock.h> +#include <mach/mxc_dvfs.h> +#include "crm_regs.h" + +#define LP_NORMAL_CLK 133000000 +#define LP_MED_CLK 83125000 +#define LP_APM_CLK 24000000 +#define NAND_LP_APM_CLK 12000000 +#define DDR_LOW_FREQ_CLK 133000000 +#define DDR_NORMAL_CLK 200000000 +#define AXI_A_NORMAL_CLK 166250000 +#define AXI_A_CLK_NORMAL_DIV 4 +#define AXI_B_CLK_NORMAL_DIV 5 +#define AHB_CLK_NORMAL_DIV AXI_B_CLK_NORMAL_DIV +#define EMI_SLOW_CLK_NORMAL_DIV AXI_B_CLK_NORMAL_DIV +#define NFC_CLK_NORMAL_DIV 4 + +static struct clk *ddr_clk; +static struct clk *pll2; +static struct clk *main_bus_clk; +static struct clk *axi_a_clk; +static struct clk *axi_b_clk; +static struct clk *cpu_clk; +static struct clk *ddr_hf_clk; +static struct clk *nfc_clk; +static struct clk *ahb_clk; +static struct clk *vpu_clk; +static struct clk *vpu_core_clk; +static struct clk *emi_slow_clk; +static struct clk *ddr_clk; +static struct clk *ipu_clk; +static struct clk *periph_apm_clk; +static struct clk *lp_apm; +static struct clk *osc; +static struct clk *gpc_dvfs_clk; +static struct clk *mipi_hsp_clk; +struct regulator *lp_regulator; +int low_bus_freq_mode; +int high_bus_freq_mode; +int bus_freq_scaling_is_active; +char *gp_reg_id = "SW1"; +char *lp_reg_id = "SW2"; + +static struct cpu_wp *cpu_wp_tbl; +static struct device *busfreq_dev; +static int busfreq_suspended; +int sdram_autogating_paused; + +extern int lp_high_freq; +extern int lp_med_freq; +extern int dvfs_core_is_active; +extern struct cpu_wp *(*get_cpu_wp)(int *wp); +extern int cpu_wp_nr; +extern int sdram_autogating_is_active; +extern void enable_sdram_autogating(void); +extern void disable_sdram_autogating(void); + +struct dvfs_wp dvfs_core_setpoint[] = { + {33, 8, 33, 10, 10, 0x08}, + {26, 0, 33, 20, 10, 0x08}, + {28, 8, 33, 20, 30, 0x08}, + {29, 0, 33, 20, 10, 0x08},}; + +#define DISABLE_PLL1 + +int set_low_bus_freq(void) +{ + struct clk *tclk; + u32 reg; + + if (bus_freq_scaling_is_active) { + + if (busfreq_suspended) + return 0; + + if (clk_get_rate(cpu_clk) != cpu_wp_tbl[cpu_wp_nr - 1].cpu_rate) + return 0; + + if (sdram_autogating_is_active) { + disable_sdram_autogating(); + sdram_autogating_paused = 1; + } +#ifdef DISABLE_PLL1 + tclk = clk_get(NULL, "ddr_clk"); + clk_set_parent(tclk, clk_get(NULL, "axi_a_clk")); + + /* Set CPU clock to be derived from PLL2 instead of PLL1 */ + tclk = clk_get(NULL, "pll1_sw_clk"); + clk_set_parent(tclk, clk_get(NULL, "pll2")); + clk_enable(tclk); + + tclk = clk_get(NULL, "ddr_clk"); + clk_set_parent(tclk, clk_get(NULL, "ddr_hf_clk")); +#endif + + /*Change the DDR freq to 133Mhz. */ + clk_set_rate(ddr_hf_clk, + clk_round_rate(ddr_hf_clk, DDR_LOW_FREQ_CLK)); + + clk_enable(gpc_dvfs_clk); + + /* Setup the GPC. */ + reg = __raw_readl(MXC_GPC_VCR); + reg &= ~(MXC_GPCVCR_VINC_MASK | MXC_GPCVCR_VCNTU_MASK | + MXC_GPCVCR_VCNT_MASK); + + reg |= (1 << MXC_GPCVCR_VCNTU_OFFSET) | + (0 << MXC_GPCVCR_VCNT_OFFSET); + __raw_writel(reg, MXC_GPC_VCR); + + reg = __raw_readl(MXC_GPC_CNTR); + reg &= ~(MXC_GPCCNTR_ADU_MASK | MXC_GPCCNTR_FUPD_MASK); + reg |= MXC_GPCCNTR_FUPD; + __raw_writel(reg, MXC_GPC_CNTR); + + /* Enable DVFS-PER */ + reg = __raw_readl(MXC_DVFSPER_PMCR0); + reg &= ~(MXC_DVFSPER_PMCR0_UDCS_MASK | + MXC_DVFSPER_PMCR0_ENABLE_MASK); + reg |= MXC_DVFSPER_PMCR0_ENABLE; + __raw_writel(reg, MXC_DVFSPER_PMCR0); + + /* Set the dvfs-podf to divide by 4. */ + reg = __raw_readl(MXC_CCM_CDCR); + reg &= ~MXC_CCM_CDCR_PERIPH_CLK_DVFS_PODF_MASK; + reg |= 3 << MXC_CCM_CDCR_PERIPH_CLK_DVFS_PODF_OFFSET; + __raw_writel(reg, MXC_CCM_CDCR); + + /* Setup the GPC */ + reg = __raw_readl(MXC_GPC_VCR) & ~MXC_GPCVCR_VINC_MASK; + /* Set VINC to 0. */ + reg |= 0 << MXC_GPCVCR_VINC_OFFSET; + __raw_writel(reg, MXC_GPC_VCR); + + reg = __raw_readl(MXC_GPC_CNTR); + reg |= MXC_GPCCNTR_STRT; + __raw_writel(reg, MXC_GPC_CNTR); + while (__raw_readl(MXC_GPC_CNTR) & MXC_GPCCNTR_STRT) + udelay(10); + + /* Disable DVFS-PER */ + reg = __raw_readl(MXC_DVFSPER_PMCR0); + reg &= ~MXC_DVFSPER_PMCR0_ENABLE; + __raw_writel(reg, MXC_DVFSPER_PMCR0); + + /* Set the dividers to be close to 24Mhz from 166.25MHz*/ + reg = __raw_readl(MXC_CCM_CBCDR); + reg &= ~(MXC_CCM_CBCDR_AXI_A_PODF_MASK + | MXC_CCM_CBCDR_AXI_B_PODF_MASK + | MXC_CCM_CBCDR_AHB_PODF_MASK + | MXC_CCM_CBCDR_EMI_PODF_MASK + | MXC_CCM_CBCDR_NFC_PODF_OFFSET); + reg |= (6 << MXC_CCM_CBCDR_AXI_A_PODF_OFFSET + | 6 << MXC_CCM_CBCDR_AXI_B_PODF_OFFSET + | 6 << MXC_CCM_CBCDR_AHB_PODF_OFFSET + | 6 << MXC_CCM_CBCDR_EMI_PODF_OFFSET + | 3 << MXC_CCM_CBCDR_NFC_PODF_OFFSET); + __raw_writel(reg, MXC_CCM_CBCDR); + + while (__raw_readl(MXC_CCM_CDHIPR) & 0x1F) + udelay(10); + clk_set_parent(main_bus_clk, pll2); + + low_bus_freq_mode = 1; + high_bus_freq_mode = 0; + } + return 0; +} + +int set_high_bus_freq(int high_bus_freq) +{ + u32 dvfs_podf = __raw_readl(MXC_CCM_CDCR) & 0x3; + u32 reg; + struct clk *tclk; + + if (bus_freq_scaling_is_active) { + if (sdram_autogating_is_active) { + disable_sdram_autogating(); + sdram_autogating_paused = 1; + } + + if (dvfs_podf > 1) { + reg = __raw_readl(MXC_CCM_CBCDR); + reg &= ~(MXC_CCM_CBCDR_AXI_A_PODF_MASK + | MXC_CCM_CBCDR_AXI_B_PODF_MASK + | MXC_CCM_CBCDR_AHB_PODF_MASK + | MXC_CCM_CBCDR_EMI_PODF_MASK + | MXC_CCM_CBCDR_NFC_PODF_OFFSET); + reg |= (3 << MXC_CCM_CBCDR_AXI_A_PODF_OFFSET + | 4 << MXC_CCM_CBCDR_AXI_B_PODF_OFFSET + | 4 << MXC_CCM_CBCDR_AHB_PODF_OFFSET + | 4 << MXC_CCM_CBCDR_EMI_PODF_OFFSET + | 3 << MXC_CCM_CBCDR_NFC_PODF_OFFSET); + __raw_writel(reg, MXC_CCM_CBCDR); + while (__raw_readl(MXC_CCM_CDHIPR) & 0x1F) + udelay(10); + + /* Setup the GPC. */ + reg = __raw_readl(MXC_GPC_VCR); + reg &= ~(MXC_GPCVCR_VINC_MASK | MXC_GPCVCR_VCNTU_MASK | + MXC_GPCVCR_VCNT_MASK); + + reg |= (1 << MXC_GPCVCR_VCNTU_OFFSET) | + (0 << MXC_GPCVCR_VCNT_OFFSET); + __raw_writel(reg, MXC_GPC_VCR); + + reg = __raw_readl(MXC_GPC_CNTR); + reg &= ~(MXC_GPCCNTR_ADU_MASK | MXC_GPCCNTR_FUPD_MASK); + reg |= MXC_GPCCNTR_FUPD; + __raw_writel(reg, MXC_GPC_CNTR); + + /* Enable DVFS-PER */ + reg = __raw_readl(MXC_DVFSPER_PMCR0); + reg |= MXC_DVFSPER_PMCR0_UDCS; + reg |= MXC_DVFSPER_PMCR0_ENABLE; + __raw_writel(reg, MXC_DVFSPER_PMCR0); + + /* Set the dvfs-podf to divide by 1. */ + reg = __raw_readl(MXC_CCM_CDCR); + reg &= ~MXC_CCM_CDCR_PERIPH_CLK_DVFS_PODF_MASK; + reg |= 0 << MXC_CCM_CDCR_PERIPH_CLK_DVFS_PODF_OFFSET; + __raw_writel(reg, MXC_CCM_CDCR); + + /* Setup the GPC */ + reg = __raw_readl(MXC_GPC_VCR) & ~MXC_GPCVCR_VINC_MASK; + /* Set VINC to 1. */ + reg |= 1 << MXC_GPCVCR_VINC_OFFSET; + __raw_writel(reg, MXC_GPC_VCR); + + reg = __raw_readl(MXC_GPC_CNTR); + reg |= MXC_GPCCNTR_STRT; + __raw_writel(reg, MXC_GPC_CNTR); + while (__raw_readl(MXC_GPC_CNTR) & MXC_GPCCNTR_STRT) + udelay(10); + + /* Disable DVFS-PER */ + reg = __raw_readl(MXC_DVFSPER_PMCR0); + reg &= ~MXC_DVFSPER_PMCR0_ENABLE; + __raw_writel(reg, MXC_DVFSPER_PMCR0); + + clk_set_parent(main_bus_clk, pll2); + clk_disable(gpc_dvfs_clk); +#ifdef DISABLE_PLL1 + tclk = clk_get(NULL, "ddr_clk"); + clk_set_parent(tclk, clk_get(NULL, "axi_a_clk")); + + /* Set CPU clock to be derived from PLL1 instead of PLL2 */ + tclk = clk_get(NULL, "pll1_sw_clk"); + clk_set_parent(tclk, clk_get(NULL, "pll1_main_clk")); + clk_disable(tclk); + + tclk = clk_get(NULL, "ddr_clk"); + clk_set_parent(tclk, clk_get(NULL, "ddr_hf_clk")); +#endif + /*Change the DDR freq to 200MHz*/ + clk_set_rate(ddr_hf_clk, + clk_round_rate(ddr_hf_clk, DDR_NORMAL_CLK)); + + low_bus_freq_mode = 0; + } + + /* + * If the CPU freq is 800MHz, set the bus to the high setpoint + * (133MHz) and DDR to 200MHz. + */ + if (clk_get_rate(cpu_clk) != cpu_wp_tbl[cpu_wp_nr - 1].cpu_rate) + high_bus_freq = 1; + + if (((clk_get_rate(ahb_clk) == LP_MED_CLK) && lp_high_freq) || + high_bus_freq) { + /* Set to the high setpoint. */ + high_bus_freq_mode = 1; + clk_set_rate(ahb_clk, + clk_round_rate(ahb_clk, LP_NORMAL_CLK)); + clk_set_rate(ddr_hf_clk, + clk_round_rate(ddr_hf_clk, DDR_NORMAL_CLK)); + } + if (!lp_high_freq && !high_bus_freq) { + /* Set to the medium setpoint. */ + high_bus_freq_mode = 0; + low_bus_freq_mode = 0; + clk_set_rate(ddr_hf_clk, + clk_round_rate(ddr_hf_clk, DDR_LOW_FREQ_CLK)); + clk_set_rate(ahb_clk, + clk_round_rate(ahb_clk, LP_MED_CLK)); + } + if (sdram_autogating_paused) { + enable_sdram_autogating(); + sdram_autogating_paused = 0; + } + } + return 0; +} + +int low_freq_bus_used(void) +{ + if ((clk_get_usecount(ipu_clk) == 0) + && (clk_get_usecount(vpu_clk) == 0) + && (lp_high_freq == 0) + && (lp_med_freq == 0)) + return 1; + else + return 0; +} + +void setup_pll(void) +{ +} + +static ssize_t bus_freq_scaling_enable_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + if (bus_freq_scaling_is_active) + return sprintf(buf, "Bus frequency scaling is enabled\n"); + else + return sprintf(buf, "Bus frequency scaling is disabled\n"); +} + +static ssize_t bus_freq_scaling_enable_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + if (strstr(buf, "1") != NULL) + bus_freq_scaling_is_active = 1; + else if (strstr(buf, "0") != NULL) { + if (bus_freq_scaling_is_active) + set_high_bus_freq(1); + bus_freq_scaling_is_active = 0; + } + return size; +} + +static int busfreq_suspend(struct platform_device *pdev, pm_message_t message) +{ + if (low_bus_freq_mode) + set_high_bus_freq(1); + busfreq_suspended = 1; + return 0; +} + +static int busfreq_resume(struct platform_device *pdev) +{ + busfreq_suspended = 0; + return 0; +} + +static DEVICE_ATTR(enable, 0644, bus_freq_scaling_enable_show, + bus_freq_scaling_enable_store); + +/*! + * This is the probe routine for the bus frequency driver. + * + * @param pdev The platform device structure + * + * @return The function returns 0 on success + * + */ +static int __devinit busfreq_probe(struct platform_device *pdev) +{ + int err = 0; + u32 reg; + + busfreq_dev = &pdev->dev; + + main_bus_clk = clk_get(NULL, "main_bus_clk"); + if (IS_ERR(main_bus_clk)) { + printk(KERN_DEBUG "%s: failed to get main_bus_clk\n", + __func__); + return PTR_ERR(main_bus_clk); + } + + pll2 = clk_get(NULL, "pll2"); + if (IS_ERR(pll2)) { + printk(KERN_DEBUG "%s: failed to get pll2\n", __func__); + return PTR_ERR(pll2); + } + + axi_a_clk = clk_get(NULL, "axi_a_clk"); + if (IS_ERR(axi_a_clk)) { + printk(KERN_DEBUG "%s: failed to get axi_a_clk\n", + __func__); + return PTR_ERR(axi_a_clk); + } + + axi_b_clk = clk_get(NULL, "axi_b_clk"); + if (IS_ERR(axi_b_clk)) { + printk(KERN_DEBUG "%s: failed to get axi_b_clk\n", + __func__); + return PTR_ERR(axi_b_clk); + } + + ddr_hf_clk = clk_get(NULL, "ddr_hf_clk"); + if (IS_ERR(ddr_hf_clk)) { + printk(KERN_DEBUG "%s: failed to get ddr_hf_clk\n", + __func__); + return PTR_ERR(ddr_hf_clk); + } + + emi_slow_clk = clk_get(NULL, "emi_slow_clk"); + if (IS_ERR(emi_slow_clk)) { + printk(KERN_DEBUG "%s: failed to get emi_slow_clk\n", + __func__); + return PTR_ERR(emi_slow_clk); + } + + nfc_clk = clk_get(NULL, "nfc_clk"); + if (IS_ERR(nfc_clk)) { + printk(KERN_DEBUG "%s: failed to get nfc_clk\n", + __func__); + return PTR_ERR(nfc_clk); + } + + ahb_clk = clk_get(NULL, "ahb_clk"); + if (IS_ERR(ahb_clk)) { + printk(KERN_DEBUG "%s: failed to get ahb_clk\n", + __func__); + return PTR_ERR(ahb_clk); + } + + vpu_core_clk = clk_get(NULL, "vpu_core_clk"); + if (IS_ERR(vpu_core_clk)) { + printk(KERN_DEBUG "%s: failed to get vpu_core_clk\n", + __func__); + return PTR_ERR(vpu_core_clk); + } + + ddr_clk = clk_get(NULL, "ddr_clk"); + if (IS_ERR(ddr_clk)) { + printk(KERN_DEBUG "%s: failed to get ddr_clk\n", + __func__); + return PTR_ERR(ddr_clk); + } + + cpu_clk = clk_get(NULL, "cpu_clk"); + if (IS_ERR(cpu_clk)) { + printk(KERN_DEBUG "%s: failed to get cpu_clk\n", + __func__); + return PTR_ERR(cpu_clk); + } + + ipu_clk = clk_get(NULL, "ipu_clk"); + if (IS_ERR(ipu_clk)) { + printk(KERN_DEBUG "%s: failed to get ipu_clk\n", + __func__); + return PTR_ERR(ipu_clk); + } + + mipi_hsp_clk = clk_get(NULL, "mipi_hsp_clk"); + if (IS_ERR(mipi_hsp_clk)) { + printk(KERN_DEBUG "%s: failed to get mipi_hsp_clk\n", + __func__); + return PTR_ERR(mipi_hsp_clk); + } + + vpu_clk = clk_get(NULL, "vpu_clk"); + if (IS_ERR(vpu_clk)) { + printk(KERN_DEBUG "%s: failed to get vpu_clk\n", + __func__); + return PTR_ERR(vpu_clk); + } + + periph_apm_clk = clk_get(NULL, "periph_apm_clk"); + if (IS_ERR(periph_apm_clk)) { + printk(KERN_DEBUG "%s: failed to get periph_apm_clk\n", + __func__); + return PTR_ERR(periph_apm_clk); + } + + lp_apm = clk_get(NULL, "lp_apm"); + if (IS_ERR(lp_apm)) { + printk(KERN_DEBUG "%s: failed to get lp_apm\n", + __func__); + return PTR_ERR(lp_apm); + } + + osc = clk_get(NULL, "osc"); + if (IS_ERR(osc)) { + printk(KERN_DEBUG "%s: failed to get osc\n", __func__); + return PTR_ERR(osc); + } + + gpc_dvfs_clk = clk_get(NULL, "gpc_dvfs_clk"); + if (IS_ERR(gpc_dvfs_clk)) { + printk(KERN_DEBUG "%s: failed to get gpc_dvfs_clk\n", __func__); + return PTR_ERR(gpc_dvfs_clk); + } + + err = sysfs_create_file(&busfreq_dev->kobj, &dev_attr_enable.attr); + if (err) { + printk(KERN_ERR + "Unable to register sysdev entry for BUSFREQ"); + return err; + } + + /* Initialize DVFS-PODF to 0. */ + reg = __raw_readl(MXC_CCM_CDCR); + reg &= ~MXC_CCM_CDCR_PERIPH_CLK_DVFS_PODF_MASK; + __raw_writel(reg, MXC_CCM_CDCR); + clk_set_parent(main_bus_clk, pll2); + + cpu_wp_tbl = get_cpu_wp(&cpu_wp_nr); + low_bus_freq_mode = 0; + high_bus_freq_mode = 1; + bus_freq_scaling_is_active = 0; + + return 0; +} + +static struct platform_driver busfreq_driver = { + .driver = { + .name = "busfreq", + }, + .probe = busfreq_probe, + .suspend = busfreq_suspend, + .resume = busfreq_resume, +}; + +/*! + * Initialise the busfreq_driver. + * + * @return The function always returns 0. + */ + +static int __init busfreq_init(void) +{ + if (platform_driver_register(&busfreq_driver) != 0) { + printk(KERN_ERR "busfreq_driver register failed\n"); + return -ENODEV; + } + + printk(KERN_INFO "Bus freq driver module loaded\n"); + return 0; +} + +static void __exit busfreq_cleanup(void) +{ + sysfs_remove_file(&busfreq_dev->kobj, &dev_attr_enable.attr); + + /* Unregister the device structure */ + platform_driver_unregister(&busfreq_driver); +} + +module_init(busfreq_init); +module_exit(busfreq_cleanup); + +MODULE_AUTHOR("Freescale Semiconductor, Inc."); +MODULE_DESCRIPTION("BusFreq driver"); +MODULE_LICENSE("GPL"); + diff --git a/arch/arm/mach-mx51/clock.c b/arch/arm/mach-mx51/clock.c new file mode 100644 index 000000000000..7de58e62778d --- /dev/null +++ b/arch/arm/mach-mx51/clock.c @@ -0,0 +1,3898 @@ +/* + * Copyright 2008-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/init.h> +#include <linux/types.h> +#include <linux/time.h> +#include <linux/hrtimer.h> +#include <linux/mm.h> +#include <linux/errno.h> +#include <linux/delay.h> +#include <linux/clk.h> +#include <asm/io.h> +#include <asm/div64.h> +#include <mach/hardware.h> +#include <mach/clock.h> +#include <mach/spba.h> + +#include "crm_regs.h" + +static unsigned long pll_base[] = { + (unsigned long)MXC_DPLL1_BASE, + (unsigned long)MXC_DPLL2_BASE, + (unsigned long)MXC_DPLL3_BASE, +}; + +static struct clk pll1_main_clk; +static struct clk pll1_sw_clk; +static struct clk pll2_sw_clk; +static struct clk pll3_sw_clk; +static struct clk lp_apm_clk; +static struct clk tve_clk; +static struct clk emi_fast_clk; +static struct clk emi_slow_clk; +static struct clk emi_intr_clk; +static struct clk ddr_clk; +static struct clk ipu_clk[]; +static struct clk axi_a_clk; +static struct clk axi_b_clk; +static struct clk ddr_hf_clk; +static struct clk mipi_hsp_clk; +static struct clk gpu3d_clk; +static struct clk gpu2d_clk; +static struct clk vpu_clk[]; +static int cpu_curr_wp; +static struct cpu_wp *cpu_wp_tbl; + +int cpu_wp_nr; +int lp_high_freq; +int lp_med_freq; + +#define SPIN_DELAY 1000000 /* in nanoseconds */ + +extern int mxc_jtag_enabled; +extern int cpufreq_trig_needed; + +static int cpu_clk_set_wp(int wp); +extern void propagate_rate(struct clk *tclk); +struct cpu_wp *(*get_cpu_wp)(int *wp); +void (*set_num_cpu_wp)(int num); + +static void __calc_pre_post_dividers(u32 div, u32 *pre, u32 *post) +{ + u32 min_pre, temp_pre, old_err, err; + + if (div >= 512) { + *pre = 8; + *post = 64; + } else if (div >= 8) { + min_pre = (div - 1) / 64 + 1; + old_err = 8; + for (temp_pre = 8; temp_pre >= min_pre; temp_pre--) { + err = div % temp_pre; + if (err == 0) { + *pre = temp_pre; + break; + } + err = temp_pre - err; + if (err < old_err) { + old_err = err; + *pre = temp_pre; + } + } + *post = (div + *pre - 1) / *pre; + } else if (div < 8) { + *pre = div; + *post = 1; + } +} + +static int _clk_enable(struct clk *clk) +{ + u32 reg; + reg = __raw_readl(clk->enable_reg); + reg |= MXC_CCM_CCGR_CG_MASK << clk->enable_shift; + __raw_writel(reg, clk->enable_reg); + + if (clk->flags & AHB_HIGH_SET_POINT) + lp_high_freq++; + else if (clk->flags & AHB_MED_SET_POINT) + lp_med_freq++; + + + return 0; +} + +static void _clk_disable(struct clk *clk) +{ + u32 reg; + reg = __raw_readl(clk->enable_reg); + reg &= ~(MXC_CCM_CCGR_CG_MASK << clk->enable_shift); + __raw_writel(reg, clk->enable_reg); + + if (clk->flags & AHB_HIGH_SET_POINT) + lp_high_freq--; + else if (clk->flags & AHB_MED_SET_POINT) + lp_med_freq--; + +} + +static void _clk_disable_inwait(struct clk *clk) +{ + u32 reg; + + reg = __raw_readl(clk->enable_reg); + reg &= ~(MXC_CCM_CCGR_CG_MASK << clk->enable_shift); + reg |= 1 << clk->enable_shift; + __raw_writel(reg, clk->enable_reg); +} + +static int _clk_enable_inwait(struct clk *clk) +{ + _clk_disable_inwait(clk); + return 0; +} + +/* + * For the 4-to-1 muxed input clock + */ +static inline u32 _get_mux(struct clk *parent, struct clk *m0, + struct clk *m1, struct clk *m2, struct clk *m3) +{ + if (parent == m0) + return 0; + else if (parent == m1) + return 1; + else if (parent == m2) + return 2; + else if (parent == m3) + return 3; + else + BUG(); + + return 0; +} + +/* + * For the ddr muxed input clock + */ +static inline u32 _get_mux_ddr(struct clk *parent, struct clk *m0, + struct clk *m1, struct clk *m2, struct clk *m3, struct clk *m4) +{ + if (parent == m0) + return 0; + else if (parent == m1) + return 1; + else if (parent == m2) + return 2; + else if (parent == m3) + return 3; + else if (parent == m4) + return 4; + else + BUG(); + + return 0; +} + +static inline unsigned long _get_pll_base(struct clk *pll) +{ + if (pll == &pll1_main_clk) + return pll_base[0]; + else if (pll == &pll2_sw_clk) + return pll_base[1]; + else if (pll == &pll3_sw_clk) + return pll_base[2]; + else + BUG(); + + return 0; +} + +static struct clk ckih_clk = { + .name = "ckih", + .flags = RATE_PROPAGATES, +}; + +static struct clk ckih2_clk = { + .name = "ckih2", + .flags = RATE_PROPAGATES, +}; + +static struct clk osc_clk = { + .name = "osc", + .flags = RATE_PROPAGATES, +}; + +static struct clk ckil_clk = { + .name = "ckil", + .flags = RATE_PROPAGATES, +}; + +static void _fpm_recalc(struct clk *clk) +{ + clk->rate = ckil_clk.rate * 512; + if ((__raw_readl(MXC_CCM_CCR) & MXC_CCM_CCR_FPM_MULT_MASK) != 0) + clk->rate *= 2; + +} + +static int _fpm_enable(struct clk *clk) +{ + u32 reg = __raw_readl(MXC_CCM_CCR); + reg |= MXC_CCM_CCR_FPM_EN; + __raw_writel(reg, MXC_CCM_CCR); + return 0; +} + +static void _fpm_disable(struct clk *clk) +{ + u32 reg = __raw_readl(MXC_CCM_CCR); + reg &= ~MXC_CCM_CCR_FPM_EN; + __raw_writel(reg, MXC_CCM_CCR); +} + +static struct clk fpm_clk = { + .name = "fpm_clk", + .parent = &ckil_clk, + .recalc = _fpm_recalc, + .enable = _fpm_enable, + .disable = _fpm_disable, + .flags = RATE_PROPAGATES, +}; + +static void _fpm_div2_recalc(struct clk *clk) +{ + clk->rate = clk->parent->rate / 2; +} + +static struct clk fpm_div2_clk = { + .name = "fpm_div2_clk", + .parent = &fpm_clk, + .recalc = _fpm_div2_recalc, + .flags = RATE_PROPAGATES, +}; + +static void _clk_pll_recalc(struct clk *clk) +{ + long mfi, mfn, mfd, pdf, ref_clk, mfn_abs; + unsigned long dp_op, dp_mfd, dp_mfn, dp_ctl, pll_hfsm, dbl; + unsigned long pllbase; + s64 temp; + + pllbase = _get_pll_base(clk); + + dp_ctl = __raw_readl(pllbase + MXC_PLL_DP_CTL); + pll_hfsm = dp_ctl & MXC_PLL_DP_CTL_HFSM; + dbl = dp_ctl & MXC_PLL_DP_CTL_DPDCK0_2_EN; + + if (pll_hfsm == 0) { + dp_op = __raw_readl(pllbase + MXC_PLL_DP_OP); + dp_mfd = __raw_readl(pllbase + MXC_PLL_DP_MFD); + dp_mfn = __raw_readl(pllbase + MXC_PLL_DP_MFN); + } else { + dp_op = __raw_readl(pllbase + MXC_PLL_DP_HFS_OP); + dp_mfd = __raw_readl(pllbase + MXC_PLL_DP_HFS_MFD); + dp_mfn = __raw_readl(pllbase + MXC_PLL_DP_HFS_MFN); + } + pdf = dp_op & MXC_PLL_DP_OP_PDF_MASK; + mfi = (dp_op & MXC_PLL_DP_OP_MFI_MASK) >> MXC_PLL_DP_OP_MFI_OFFSET; + mfi = (mfi <= 5) ? 5 : mfi; + mfd = dp_mfd & MXC_PLL_DP_MFD_MASK; + mfn = mfn_abs = dp_mfn & MXC_PLL_DP_MFN_MASK; + /* Sign extend to 32-bits */ + if (mfn >= 0x04000000) { + mfn |= 0xFC000000; + mfn_abs = -mfn; + } + + ref_clk = 2 * clk->parent->rate; + if (dbl != 0) + ref_clk *= 2; + + ref_clk /= (pdf + 1); + temp = (u64) ref_clk * mfn_abs; + do_div(temp, mfd + 1); + if (mfn < 0) + temp = -temp; + temp = (ref_clk * mfi) + temp; + + clk->rate = temp; +} + +static int _clk_pll_set_rate(struct clk *clk, unsigned long rate) +{ + u32 reg; + u32 pllbase; + + long mfi, pdf, mfn, mfd = 999999; + s64 temp64; + unsigned long quad_parent_rate; + unsigned long pll_hfsm, dp_ctl; + + pllbase = _get_pll_base(clk); + + quad_parent_rate = 4*clk->parent->rate; + pdf = mfi = -1; + while (++pdf < 16 && mfi < 5) + mfi = rate * (pdf+1) / quad_parent_rate; + if (mfi > 15) + return -1; + pdf--; + + temp64 = rate*(pdf+1) - quad_parent_rate*mfi; + do_div(temp64, quad_parent_rate/1000000); + mfn = (long)temp64; + + dp_ctl = __raw_readl(pllbase + MXC_PLL_DP_CTL); + /* use dpdck0_2 */ + __raw_writel(dp_ctl | 0x1000L, pllbase + MXC_PLL_DP_CTL); + pll_hfsm = dp_ctl & MXC_PLL_DP_CTL_HFSM; + if (pll_hfsm == 0) { + reg = mfi<<4 | pdf; + __raw_writel(reg, pllbase + MXC_PLL_DP_OP); + __raw_writel(mfd, pllbase + MXC_PLL_DP_MFD); + __raw_writel(mfn, pllbase + MXC_PLL_DP_MFN); + } else { + reg = mfi<<4 | pdf; + __raw_writel(reg, pllbase + MXC_PLL_DP_HFS_OP); + __raw_writel(mfd, pllbase + MXC_PLL_DP_HFS_MFD); + __raw_writel(mfn, pllbase + MXC_PLL_DP_HFS_MFN); + } + + clk->rate = rate; + return 0; +} + +static int _clk_pll_enable(struct clk *clk) +{ + u32 reg; + u32 pllbase; + struct timespec nstimeofday; + struct timespec curtime; + + pllbase = _get_pll_base(clk); + reg = __raw_readl(pllbase + MXC_PLL_DP_CTL) | MXC_PLL_DP_CTL_UPEN; + __raw_writel(reg, pllbase + MXC_PLL_DP_CTL); + + /* Wait for lock */ + getnstimeofday(&nstimeofday); + while (!(__raw_readl(pllbase + MXC_PLL_DP_CTL) & MXC_PLL_DP_CTL_LRF)) { + getnstimeofday(&curtime); + if (curtime.tv_nsec - nstimeofday.tv_nsec > SPIN_DELAY) + panic("pll relock failed\n"); + } + return 0; +} + +static void _clk_pll_disable(struct clk *clk) +{ + u32 reg; + u32 pllbase; + + pllbase = _get_pll_base(clk); + reg = __raw_readl(pllbase + MXC_PLL_DP_CTL) & ~MXC_PLL_DP_CTL_UPEN; + __raw_writel(reg, pllbase + MXC_PLL_DP_CTL); +} + +static struct clk pll1_main_clk = { + .name = "pll1_main_clk", + .parent = &osc_clk, + .recalc = _clk_pll_recalc, + .enable = _clk_pll_enable, + .disable = _clk_pll_disable, + .flags = RATE_PROPAGATES, +}; + +static int _clk_pll1_sw_set_parent(struct clk *clk, struct clk *parent) +{ + u32 reg, mux; + + reg = __raw_readl(MXC_CCM_CCSR); + + if (parent == &pll1_main_clk) { + reg &= ~MXC_CCM_CCSR_PLL1_SW_CLK_SEL; + __raw_writel(reg, MXC_CCM_CCSR); + /* Set the step_clk parent to be lp_apm, to save power. */ + mux = _get_mux(&lp_apm_clk, &lp_apm_clk, NULL, &pll2_sw_clk, + &pll3_sw_clk); + reg = __raw_readl(MXC_CCM_CCSR); + reg = (reg & ~MXC_CCM_CCSR_STEP_SEL_MASK) | + (mux << MXC_CCM_CCSR_STEP_SEL_OFFSET); + } else { + if (parent == &lp_apm_clk) { + reg |= MXC_CCM_CCSR_PLL1_SW_CLK_SEL; + reg = __raw_readl(MXC_CCM_CCSR); + mux = _get_mux(parent, &lp_apm_clk, NULL, &pll2_sw_clk, + &pll3_sw_clk); + reg = (reg & ~MXC_CCM_CCSR_STEP_SEL_MASK) | + (mux << MXC_CCM_CCSR_STEP_SEL_OFFSET); + } else { + mux = _get_mux(parent, &lp_apm_clk, NULL, &pll2_sw_clk, + &pll3_sw_clk); + reg = (reg & ~MXC_CCM_CCSR_STEP_SEL_MASK) | + (mux << MXC_CCM_CCSR_STEP_SEL_OFFSET); + __raw_writel(reg, MXC_CCM_CCSR); + reg = __raw_readl(MXC_CCM_CCSR); + reg |= MXC_CCM_CCSR_PLL1_SW_CLK_SEL; + + } + } + __raw_writel(reg, MXC_CCM_CCSR); + + return 0; +} + +static void _clk_pll1_sw_recalc(struct clk *clk) +{ + u32 reg, div; + div = 1; + reg = __raw_readl(MXC_CCM_CCSR); + + if (clk->parent == &pll2_sw_clk) { + div = ((reg & MXC_CCM_CCSR_PLL2_PODF_MASK) >> + MXC_CCM_CCSR_PLL2_PODF_OFFSET) + 1; + } else if (clk->parent == &pll3_sw_clk) { + div = ((reg & MXC_CCM_CCSR_PLL3_PODF_MASK) >> + MXC_CCM_CCSR_PLL3_PODF_OFFSET) + 1; + } + clk->rate = clk->parent->rate / div; +} + +/* pll1 switch clock */ +static struct clk pll1_sw_clk = { + .name = "pll1_sw_clk", + .parent = &pll1_main_clk, + .set_parent = _clk_pll1_sw_set_parent, + .recalc = _clk_pll1_sw_recalc, + .flags = RATE_PROPAGATES, +}; + +static int _clk_pll2_sw_set_parent(struct clk *clk, struct clk *parent) +{ + u32 reg; + + reg = __raw_readl(MXC_CCM_CCSR); + + if (parent == &pll2_sw_clk) { + reg &= ~MXC_CCM_CCSR_PLL2_SW_CLK_SEL; + } else { + reg = (reg & ~MXC_CCM_CCSR_PLL2_SW_CLK_SEL); + reg |= MXC_CCM_CCSR_PLL2_SW_CLK_SEL; + } + __raw_writel(reg, MXC_CCM_CCSR); + return 0; +} + +/* same as pll2_main_clk. These two clocks should always be the same */ +static struct clk pll2_sw_clk = { + .name = "pll2", + .parent = &osc_clk, + .recalc = _clk_pll_recalc, + .enable = _clk_pll_enable, + .disable = _clk_pll_disable, + .set_rate = _clk_pll_set_rate, + .set_parent = _clk_pll2_sw_set_parent, + .flags = RATE_PROPAGATES, +}; + +/* same as pll3_main_clk. These two clocks should always be the same */ +static struct clk pll3_sw_clk = { + .name = "pll3", + .parent = &osc_clk, + .set_rate = _clk_pll_set_rate, + .recalc = _clk_pll_recalc, + .enable = _clk_pll_enable, + .disable = _clk_pll_disable, + .flags = RATE_PROPAGATES, +}; + +static int _clk_lp_apm_set_parent(struct clk *clk, struct clk *parent) +{ + u32 reg; + + if (parent == &osc_clk) + reg = __raw_readl(MXC_CCM_CCSR) & ~MXC_CCM_CCSR_LP_APM_SEL; + else if (parent == &fpm_clk) + reg = __raw_readl(MXC_CCM_CCSR) | MXC_CCM_CCSR_LP_APM_SEL; + else + return -EINVAL; + + __raw_writel(reg, MXC_CCM_CCSR); + + return 0; +} + +static struct clk lp_apm_clk = { + .name = "lp_apm", + .parent = &osc_clk, + .set_parent = _clk_lp_apm_set_parent, + .flags = RATE_PROPAGATES, +}; + +static void _clk_arm_recalc(struct clk *clk) +{ + u32 cacrr, div; + + cacrr = __raw_readl(MXC_CCM_CACRR); + div = (cacrr & MXC_CCM_CACRR_ARM_PODF_MASK) + 1; + clk->rate = clk->parent->rate / div; +} + +static int _clk_cpu_set_rate(struct clk *clk, unsigned long rate) +{ + u32 i; + for (i = 0; i < cpu_wp_nr; i++) { + if (rate == cpu_wp_tbl[i].cpu_rate) + break; + } + if (i >= cpu_wp_nr) + return -EINVAL; + cpu_clk_set_wp(i); + + return 0; +} + +static unsigned long _clk_cpu_round_rate(struct clk *clk, + unsigned long rate) +{ + u32 i; + u32 wp; + + for (i = 0; i < cpu_wp_nr; i++) { + if (rate == cpu_wp_tbl[i].cpu_rate) + break; + } + + if (i > cpu_wp_nr) + wp = 0; + + return cpu_wp_tbl[wp].cpu_rate; +} + + +static struct clk cpu_clk = { + .name = "cpu_clk", + .parent = &pll1_sw_clk, + .recalc = _clk_arm_recalc, + .set_rate = _clk_cpu_set_rate, + .round_rate = _clk_cpu_round_rate, +}; + +static int _clk_periph_apm_set_parent(struct clk *clk, struct clk *parent) +{ + u32 reg, mux; + struct timespec nstimeofday; + struct timespec curtime; + + mux = _get_mux(parent, &pll1_sw_clk, &pll3_sw_clk, &lp_apm_clk, NULL); + + reg = __raw_readl(MXC_CCM_CBCMR) & ~MXC_CCM_CBCMR_PERIPH_CLK_SEL_MASK; + reg |= mux << MXC_CCM_CBCMR_PERIPH_CLK_SEL_OFFSET; + __raw_writel(reg, MXC_CCM_CBCMR); + + getnstimeofday(&nstimeofday); + while (__raw_readl(MXC_CCM_CDHIPR) & + MXC_CCM_CDHIPR_PERIPH_CLK_SEL_BUSY) { + getnstimeofday(&curtime); + if (curtime.tv_nsec - nstimeofday.tv_nsec > SPIN_DELAY) + panic("pll _clk_periph_apm_set_parent failed\n"); + } + return 0; +} + +static struct clk periph_apm_clk = { + .name = "periph_apm_clk", + .parent = &pll1_sw_clk, + .set_parent = _clk_periph_apm_set_parent, + .flags = RATE_PROPAGATES, +}; + +/* TODO: Need to sync with GPC to determine if DVFS is in place so that + * the DVFS_PODF divider can be applied in CDCR register. + */ +static void _clk_main_bus_recalc(struct clk *clk) +{ + u32 div; + + div = (__raw_readl(MXC_CCM_CDCR) & 0x3) + 1; + clk->rate = clk->parent->rate / div; +} + +static int _clk_main_bus_set_parent(struct clk *clk, struct clk *parent) +{ + u32 reg; + if (emi_fast_clk.usecount == 0) + emi_fast_clk.enable(&emi_fast_clk); + if (emi_slow_clk.usecount == 0) + emi_slow_clk.enable(&emi_slow_clk); + + if (parent == &pll2_sw_clk) { + reg = __raw_readl(MXC_CCM_CBCDR) & + ~MXC_CCM_CBCDR_PERIPH_CLK_SEL; + } else if (parent == &periph_apm_clk) { + reg = __raw_readl(MXC_CCM_CBCDR) | MXC_CCM_CBCDR_PERIPH_CLK_SEL; + } else { + return -EINVAL; + } + __raw_writel(reg, MXC_CCM_CBCDR); + if (emi_fast_clk.usecount == 0) + emi_fast_clk.disable(&emi_fast_clk); + if (emi_slow_clk.usecount == 0) + emi_slow_clk.disable(&emi_slow_clk); + + return 0; +} + +static struct clk main_bus_clk = { + .name = "main_bus_clk", + .parent = &pll2_sw_clk, + .set_parent = _clk_main_bus_set_parent, + .recalc = _clk_main_bus_recalc, + .flags = RATE_PROPAGATES, +}; + +static void _clk_axi_a_recalc(struct clk *clk) +{ + u32 reg, div; + + reg = __raw_readl(MXC_CCM_CBCDR); + div = ((reg & MXC_CCM_CBCDR_AXI_A_PODF_MASK) >> + MXC_CCM_CBCDR_AXI_A_PODF_OFFSET) + 1; + clk->rate = clk->parent->rate / div; +} + +static int _clk_axi_a_set_rate(struct clk *clk, unsigned long rate) +{ + u32 reg, div; + struct timespec nstimeofday; + struct timespec curtime; + + div = clk->parent->rate / rate; + if (div == 0) + div++; + if (((clk->parent->rate / div) != rate) || (div > 8)) + return -EINVAL; + if (emi_fast_clk.usecount == 0) + emi_fast_clk.enable(&emi_fast_clk); + if (emi_slow_clk.usecount == 0) + emi_slow_clk.enable(&emi_slow_clk); + + reg = __raw_readl(MXC_CCM_CBCDR); + reg &= ~MXC_CCM_CBCDR_AXI_A_PODF_MASK; + reg |= (div - 1) << MXC_CCM_CBCDR_AXI_A_PODF_OFFSET; + __raw_writel(reg, MXC_CCM_CBCDR); + + getnstimeofday(&nstimeofday); + while (__raw_readl(MXC_CCM_CDHIPR) & MXC_CCM_CDHIPR_AXI_A_PODF_BUSY) { + getnstimeofday(&curtime); + if (curtime.tv_nsec - nstimeofday.tv_nsec > SPIN_DELAY) + panic("pll _clk_axi_a_set_rate failed\n"); + } + clk->rate = rate; + if (emi_fast_clk.usecount == 0) + emi_fast_clk.disable(&emi_fast_clk); + if (emi_slow_clk.usecount == 0) + emi_slow_clk.disable(&emi_slow_clk); + + return 0; +} + +static unsigned long _clk_axi_a_round_rate(struct clk *clk, + unsigned long rate) +{ + u32 div; + + div = clk->parent->rate / rate; + if (div > 8) + div = 8; + else if (div == 0) + div++; + return clk->parent->rate / div; +} + + +static struct clk axi_a_clk = { + .name = "axi_a_clk", + .parent = &main_bus_clk, + .recalc = _clk_axi_a_recalc, + .set_rate = _clk_axi_a_set_rate, + .round_rate = _clk_axi_a_round_rate, + .flags = RATE_PROPAGATES, +}; + +static void _clk_ddr_hf_recalc(struct clk *clk) +{ + u32 reg, div; + + reg = __raw_readl(MXC_CCM_CBCDR); + div = ((reg & MXC_CCM_CBCDR_DDR_PODF_MASK) >> + MXC_CCM_CBCDR_DDR_PODF_OFFSET) + 1; + clk->rate = clk->parent->rate / div; +} + +static unsigned long _clk_ddr_hf_round_rate(struct clk *clk, + unsigned long rate) +{ + u32 div; + + div = clk->parent->rate / rate; + if (div > 8) + div = 8; + else if (div == 0) + div++; + return clk->parent->rate / div; +} + +static int _clk_ddr_hf_set_rate(struct clk *clk, unsigned long rate) +{ + u32 reg, div; + struct timespec nstimeofday; + struct timespec curtime; + + div = clk->parent->rate / rate; + if (div == 0) + div++; + if (((clk->parent->rate / div) != rate) || (div > 8)) + return -EINVAL; + if (emi_fast_clk.usecount == 0) + emi_fast_clk.enable(&emi_fast_clk); + if (emi_slow_clk.usecount == 0) + emi_slow_clk.enable(&emi_slow_clk); + + reg = __raw_readl(MXC_CCM_CBCDR); + reg &= ~MXC_CCM_CBCDR_DDR_PODF_MASK; + reg |= (div - 1) << MXC_CCM_CBCDR_DDR_PODF_OFFSET; + __raw_writel(reg, MXC_CCM_CBCDR); + + getnstimeofday(&nstimeofday); + while (__raw_readl(MXC_CCM_CDHIPR) & MXC_CCM_CDHIPR_DDR_PODF_BUSY) { + getnstimeofday(&curtime); + if (curtime.tv_nsec - nstimeofday.tv_nsec > SPIN_DELAY) + panic("clk_ddr_hf_set_rate failed\n"); + } + clk->rate = rate; + if (emi_fast_clk.usecount == 0) + emi_fast_clk.disable(&emi_fast_clk); + if (emi_slow_clk.usecount == 0) + emi_slow_clk.disable(&emi_slow_clk); + + return 0; +} + +static struct clk ddr_hf_clk = { + .name = "ddr_hf_clk", + .parent = &pll1_sw_clk, + .recalc = _clk_ddr_hf_recalc, + .round_rate = _clk_ddr_hf_round_rate, + .set_rate = _clk_ddr_hf_set_rate, + .flags = RATE_PROPAGATES, +}; + +static void _clk_axi_b_recalc(struct clk *clk) +{ + u32 reg, div; + + reg = __raw_readl(MXC_CCM_CBCDR); + div = ((reg & MXC_CCM_CBCDR_AXI_B_PODF_MASK) >> + MXC_CCM_CBCDR_AXI_B_PODF_OFFSET) + 1; + clk->rate = clk->parent->rate / div; +} + +static int _clk_axi_b_set_rate(struct clk *clk, unsigned long rate) +{ + u32 reg, div; + struct timespec nstimeofday; + struct timespec curtime; + + div = clk->parent->rate / rate; + if (div == 0) + div++; + if (((clk->parent->rate / div) != rate) || (div > 8)) + return -EINVAL; + + emi_fast_clk.enable(&emi_fast_clk); + if (emi_slow_clk.usecount == 0) + emi_slow_clk.enable(&emi_slow_clk); + + reg = __raw_readl(MXC_CCM_CBCDR); + reg &= ~MXC_CCM_CBCDR_AXI_B_PODF_MASK; + reg |= (div - 1) << MXC_CCM_CBCDR_AXI_B_PODF_OFFSET; + __raw_writel(reg, MXC_CCM_CBCDR); + + getnstimeofday(&nstimeofday); + while (__raw_readl(MXC_CCM_CDHIPR) & MXC_CCM_CDHIPR_AXI_B_PODF_BUSY) { + getnstimeofday(&curtime); + if (curtime.tv_nsec - nstimeofday.tv_nsec > SPIN_DELAY) + panic("_clk_axi_b_set_rate failed\n"); + } + + clk->rate = rate; + emi_fast_clk.disable(&emi_fast_clk); + if (emi_slow_clk.usecount == 0) + emi_slow_clk.disable(&emi_slow_clk); + + return 0; +} + +static unsigned long _clk_axi_b_round_rate(struct clk *clk, + unsigned long rate) +{ + u32 div; + + div = clk->parent->rate / rate; + if (div > 8) + div = 8; + else if (div == 0) + div++; + return clk->parent->rate / div; +} + + +static struct clk axi_b_clk = { + .name = "axi_b_clk", + .parent = &main_bus_clk, + .recalc = _clk_axi_b_recalc, + .set_rate = _clk_axi_b_set_rate, + .round_rate = _clk_axi_b_round_rate, + .flags = RATE_PROPAGATES, +}; + +static void _clk_ahb_recalc(struct clk *clk) +{ + u32 reg, div; + + reg = __raw_readl(MXC_CCM_CBCDR); + div = ((reg & MXC_CCM_CBCDR_AHB_PODF_MASK) >> + MXC_CCM_CBCDR_AHB_PODF_OFFSET) + 1; + clk->rate = clk->parent->rate / div; +} + + +static int _clk_ahb_set_rate(struct clk *clk, unsigned long rate) +{ + u32 reg, div; + struct timespec nstimeofday; + struct timespec curtime; + + div = clk->parent->rate / rate; + if (div == 0) + div++; + if (((clk->parent->rate / div) != rate) || (div > 8)) + return -EINVAL; + if (emi_fast_clk.usecount == 0) + emi_fast_clk.enable(&emi_fast_clk); + if (emi_slow_clk.usecount == 0) + emi_slow_clk.enable(&emi_slow_clk); + + reg = __raw_readl(MXC_CCM_CBCDR); + reg &= ~MXC_CCM_CBCDR_AHB_PODF_MASK; + reg |= (div - 1) << MXC_CCM_CBCDR_AHB_PODF_OFFSET; + __raw_writel(reg, MXC_CCM_CBCDR); + + getnstimeofday(&nstimeofday); + while (__raw_readl(MXC_CCM_CDHIPR) & MXC_CCM_CDHIPR_AHB_PODF_BUSY) { + getnstimeofday(&curtime); + if (curtime.tv_nsec - nstimeofday.tv_nsec > SPIN_DELAY) + panic("_clk_ahb_set_rate failed\n"); + } + clk->rate = rate; + if (emi_fast_clk.usecount == 0) + emi_fast_clk.disable(&emi_fast_clk); + if (emi_slow_clk.usecount == 0) + emi_slow_clk.disable(&emi_slow_clk); + + return 0; +} + +static unsigned long _clk_ahb_round_rate(struct clk *clk, + unsigned long rate) +{ + u32 div; + + div = clk->parent->rate / rate; + if (div > 8) + div = 8; + else if (div == 0) + div++; + return clk->parent->rate / div; +} + + +static struct clk ahb_clk = { + .name = "ahb_clk", + .parent = &main_bus_clk, + .recalc = _clk_ahb_recalc, + .set_rate = _clk_ahb_set_rate, + .round_rate = _clk_ahb_round_rate, + .flags = RATE_PROPAGATES, +}; + +static int _clk_max_enable(struct clk *clk) +{ + u32 reg; + + _clk_enable(clk); + + /* Handshake with MAX when LPM is entered. */ + reg = __raw_readl(MXC_CCM_CLPCR); + reg &= ~MXC_CCM_CLPCR_BYPASS_MAX_LPM_HS; + __raw_writel(reg, MXC_CCM_CLPCR); + + return 0; +} + + +static void _clk_max_disable(struct clk *clk) +{ + u32 reg; + + _clk_disable_inwait(clk); + + /* No Handshake with MAX when LPM is entered as its disabled. */ + reg = __raw_readl(MXC_CCM_CLPCR); + reg |= MXC_CCM_CLPCR_BYPASS_MAX_LPM_HS; + __raw_writel(reg, MXC_CCM_CLPCR); +} + + +static struct clk ahb_max_clk = { + .name = "max_clk", + .parent = &ahb_clk, + .enable_reg = MXC_CCM_CCGR0, + .enable_shift = MXC_CCM_CCGR0_CG14_OFFSET, + .enable = _clk_max_enable, + .disable = _clk_max_disable, +}; + +static int _clk_emi_slow_set_parent(struct clk *clk, struct clk *parent) +{ + u32 reg; + + if (emi_fast_clk.usecount == 0) + emi_fast_clk.enable(&emi_fast_clk); + if (emi_slow_clk.usecount == 0) + emi_slow_clk.enable(&emi_slow_clk); + + reg = __raw_readl(MXC_CCM_CBCDR); + if (parent == &ahb_clk) { + reg |= MXC_CCM_CBCDR_EMI_CLK_SEL; + } else if (parent == &main_bus_clk) { + reg &= ~MXC_CCM_CBCDR_EMI_CLK_SEL; + } else { + BUG(); + } + __raw_writel(reg, MXC_CCM_CBCDR); + + if (emi_fast_clk.usecount == 0) + emi_fast_clk.disable(&emi_fast_clk); + if (emi_slow_clk.usecount == 0) + emi_slow_clk.disable(&emi_slow_clk); + + return 0; +} + +static void _clk_emi_slow_recalc(struct clk *clk) +{ + u32 reg, div; + + reg = __raw_readl(MXC_CCM_CBCDR); + div = ((reg & MXC_CCM_CBCDR_EMI_PODF_MASK) >> + MXC_CCM_CBCDR_EMI_PODF_OFFSET) + 1; + clk->rate = clk->parent->rate / div; +} + +static int _clk_emi_slow_set_rate(struct clk *clk, unsigned long rate) +{ + u32 reg, div; + struct timespec nstimeofday; + struct timespec curtime; + + div = clk->parent->rate / rate; + if (div == 0) + div++; + if (((clk->parent->rate / div) != rate) || (div > 8)) + return -EINVAL; + if (emi_fast_clk.usecount == 0) + emi_fast_clk.enable(&emi_fast_clk); + reg = __raw_readl(MXC_CCM_CBCDR); + reg &= ~MXC_CCM_CBCDR_EMI_PODF_MASK; + reg |= (div - 1) << MXC_CCM_CBCDR_EMI_PODF_OFFSET; + __raw_writel(reg, MXC_CCM_CBCDR); + getnstimeofday(&nstimeofday); + while (__raw_readl(MXC_CCM_CDHIPR) & MXC_CCM_CDHIPR_EMI_PODF_BUSY) { + getnstimeofday(&curtime); + if ((curtime.tv_nsec - nstimeofday.tv_nsec) > SPIN_DELAY) + panic("_clk_emi_slow_set_rate failed\n"); + } + clk->rate = rate; + + if (emi_fast_clk.usecount == 0) + emi_fast_clk.disable(&emi_fast_clk); + return 0; +} + +static unsigned long _clk_emi_slow_round_rate(struct clk *clk, + unsigned long rate) +{ + u32 div; + + div = clk->parent->rate / rate; + if (div > 8) + div = 8; + else if (div == 0) + div++; + return clk->parent->rate / div; +} + + +static struct clk emi_slow_clk = { + .name = "emi_slow_clk", + .parent = &main_bus_clk, + .set_parent = _clk_emi_slow_set_parent, + .recalc = _clk_emi_slow_recalc, + .set_rate = _clk_emi_slow_set_rate, + .round_rate = _clk_emi_slow_round_rate, + .enable = _clk_enable, + .enable_reg = MXC_CCM_CCGR5, + .enable_shift = MXC_CCM_CCGR5_CG8_OFFSET, + .disable = _clk_disable_inwait, + .flags = RATE_PROPAGATES, +}; + +static struct clk ahbmux1_clk = { + .name = "ahbmux1_clk", + .id = 0, + .parent = &ahb_clk, + .secondary = &ahb_max_clk, + .enable = _clk_enable, + .enable_reg = MXC_CCM_CCGR0, + .enable_shift = MXC_CCM_CCGR0_CG8_OFFSET, + .disable = _clk_disable_inwait, +}; + +static struct clk ahbmux2_clk = { + .name = "ahbmux2_clk", + .id = 0, + .parent = &ahb_clk, + .enable = _clk_enable, + .enable_reg = MXC_CCM_CCGR0, + .enable_shift = MXC_CCM_CCGR0_CG9_OFFSET, + .disable = _clk_disable_inwait, +}; + + +static struct clk emi_fast_clk = { + .name = "emi_fast_clk", + .parent = &ddr_clk, + .enable = _clk_enable, + .enable_reg = MXC_CCM_CCGR5, + .enable_shift = MXC_CCM_CCGR5_CG7_OFFSET, + .disable = _clk_disable_inwait, +}; + +static struct clk emi_intr_clk = { + .name = "emi_intr_clk", + .parent = &ahb_clk, + .secondary = &ahbmux2_clk, + .enable_reg = MXC_CCM_CCGR5, + .enable_shift = MXC_CCM_CCGR5_CG9_OFFSET, +}; + +static void _clk_ipg_recalc(struct clk *clk) +{ + u32 reg, div; + + reg = __raw_readl(MXC_CCM_CBCDR); + div = ((reg & MXC_CCM_CBCDR_IPG_PODF_MASK) >> + MXC_CCM_CBCDR_IPG_PODF_OFFSET) + 1; + clk->rate = clk->parent->rate / div; +} + +static struct clk ipg_clk = { + .name = "ipg_clk", + .parent = &ahb_clk, + .recalc = _clk_ipg_recalc, + .flags = RATE_PROPAGATES, +}; + +static void _clk_ipg_per_recalc(struct clk *clk) +{ + u32 reg, prediv1, prediv2, podf; + + if (clk->parent == &main_bus_clk || clk->parent == &lp_apm_clk) { + /* the main_bus_clk is the one before the DVFS engine */ + reg = __raw_readl(MXC_CCM_CBCDR); + prediv1 = ((reg & MXC_CCM_CBCDR_PERCLK_PRED1_MASK) >> + MXC_CCM_CBCDR_PERCLK_PRED1_OFFSET) + 1; + prediv2 = ((reg & MXC_CCM_CBCDR_PERCLK_PRED2_MASK) >> + MXC_CCM_CBCDR_PERCLK_PRED2_OFFSET) + 1; + podf = ((reg & MXC_CCM_CBCDR_PERCLK_PODF_MASK) >> + MXC_CCM_CBCDR_PERCLK_PODF_OFFSET) + 1; + clk->rate = clk->parent->rate / (prediv1 * prediv2 * podf); + } else if (clk->parent == &ipg_clk) { + clk->rate = ipg_clk.rate; + } else { + BUG(); + } +} + +static int _clk_ipg_per_set_parent(struct clk *clk, struct clk *parent) +{ + u32 reg, mux; + + reg = __raw_readl(MXC_CCM_CBCMR); + mux = _get_mux(parent, &main_bus_clk, &lp_apm_clk, &ipg_clk, NULL); + if (mux == 2) { + reg |= MXC_CCM_CBCMR_PERCLK_IPG_CLK_SEL; + } else { + reg &= ~MXC_CCM_CBCMR_PERCLK_IPG_CLK_SEL; + if (mux == 0) + reg &= ~MXC_CCM_CBCMR_PERCLK_LP_APM_CLK_SEL; + else + reg |= MXC_CCM_CBCMR_PERCLK_LP_APM_CLK_SEL; + } + __raw_writel(reg, MXC_CCM_CBCMR); + + return 0; +} + +static struct clk ipg_perclk = { + .name = "ipg_perclk", + .parent = &lp_apm_clk, + .recalc = _clk_ipg_per_recalc, + .set_parent = _clk_ipg_per_set_parent, + .flags = RATE_PROPAGATES, +}; + +static struct clk aips_tz1_clk = { + .name = "aips_tz1_clk", + .parent = &ahb_clk, + .secondary = &ahb_max_clk, + .enable_reg = MXC_CCM_CCGR0, + .enable_shift = MXC_CCM_CCGR0_CG12_OFFSET, + .enable = _clk_enable, + .disable = _clk_disable_inwait, +}; + +static struct clk aips_tz2_clk = { + .name = "aips_tz2_clk", + .parent = &ahb_clk, + .secondary = &ahb_max_clk, + .enable_reg = MXC_CCM_CCGR0, + .enable_shift = MXC_CCM_CCGR0_CG13_OFFSET, + .enable = _clk_enable, + .disable = _clk_disable_inwait, +}; + +static struct clk gpc_dvfs_clk = { + .name = "gpc_dvfs_clk", + .enable_reg = MXC_CCM_CCGR5, + .enable_shift = MXC_CCM_CCGR5_CG12_OFFSET, + .enable = _clk_enable, + .disable = _clk_disable, +}; + +static int _clk_sdma_enable(struct clk *clk) +{ + u32 reg; + + _clk_enable(clk); + + /* Handshake with SDMA when LPM is entered. */ + reg = __raw_readl(MXC_CCM_CLPCR); + reg &= ~MXC_CCM_CLPCR_BYPASS_SDMA_LPM_HS; + __raw_writel(reg, MXC_CCM_CLPCR); + + return 0; +} + +static void _clk_sdma_disable(struct clk *clk) +{ + u32 reg; + + _clk_disable(clk); + /* No handshake with SDMA as its not enabled. */ + reg = __raw_readl(MXC_CCM_CLPCR); + reg |= MXC_CCM_CLPCR_BYPASS_SDMA_LPM_HS; + __raw_writel(reg, MXC_CCM_CLPCR); +} + + +static struct clk sdma_clk[] = { + { + .name = "sdma_ahb_clk", + .parent = &ahb_clk, + .enable_reg = MXC_CCM_CCGR4, + .enable_shift = MXC_CCM_CCGR4_CG15_OFFSET, + .enable = _clk_sdma_enable, + .disable = _clk_sdma_disable, + }, + { + .name = "sdma_ipg_clk", + .parent = &ipg_clk, +#ifdef CONFIG_SDMA_IRAM + .secondary = &emi_intr_clk, +#endif + }, +}; + +static int _clk_ipu_enable(struct clk *clk) +{ + u32 reg; + + _clk_enable(clk); + /* Handshake with IPU when certain clock rates are changed. */ + reg = __raw_readl(MXC_CCM_CCDR); + reg &= ~MXC_CCM_CCDR_IPU_HS_MASK; + __raw_writel(reg, MXC_CCM_CCDR); + + /* Handshake with IPU when LPM is entered as its enabled. */ + reg = __raw_readl(MXC_CCM_CLPCR); + reg &= ~MXC_CCM_CLPCR_BYPASS_IPU_LPM_HS; + __raw_writel(reg, MXC_CCM_CLPCR); + + + return 0; +} + +static void _clk_ipu_disable(struct clk *clk) +{ + u32 reg; + + _clk_disable(clk); + + /* No handshake with IPU whe dividers are changed + * as its not enabled. */ + reg = __raw_readl(MXC_CCM_CCDR); + reg |= MXC_CCM_CCDR_IPU_HS_MASK; + __raw_writel(reg, MXC_CCM_CCDR); + + /* No handshake with IPU when LPM is entered as its not enabled. */ + reg = __raw_readl(MXC_CCM_CLPCR); + reg |= MXC_CCM_CLPCR_BYPASS_IPU_LPM_HS; + __raw_writel(reg, MXC_CCM_CLPCR); +} + +static int _clk_ipu_set_parent(struct clk *clk, struct clk *parent) +{ + u32 reg, mux; + reg = __raw_readl(MXC_CCM_CBCMR); + mux = _get_mux(parent, &axi_a_clk, &axi_b_clk, &ahb_clk, + &emi_slow_clk); + reg = (reg & ~MXC_CCM_CBCMR_IPU_HSP_CLK_SEL_MASK) | + (mux << MXC_CCM_CBCMR_IPU_HSP_CLK_SEL_OFFSET); + __raw_writel(reg, MXC_CCM_CBCMR); + + return 0; +} + + +static struct clk ipu_clk[] = { + { + .name = "ipu_clk", + .parent = &ahb_clk, + .secondary = &ipu_clk[1], + .enable_reg = MXC_CCM_CCGR5, + .enable_shift = MXC_CCM_CCGR5_CG5_OFFSET, + .enable = _clk_ipu_enable, + .disable = _clk_ipu_disable, + .set_parent = _clk_ipu_set_parent, + .flags = CPU_FREQ_TRIG_UPDATE | AHB_MED_SET_POINT, + }, + { + .name = "ipu_sec_clk", + .parent = &emi_fast_clk, + .secondary = &ahbmux1_clk, + } +}; + +static int _clk_ipu_di_set_parent(struct clk *clk, struct clk *parent) +{ + u32 reg; + + reg = __raw_readl(MXC_CCM_CSCMR2); + reg &= ~MXC_CCM_CSCMR2_DI_CLK_SEL_MASK(clk->id); + if (parent == &pll3_sw_clk) + ; + else if (parent == &osc_clk) + reg |= 1 << MXC_CCM_CSCMR2_DI_CLK_SEL_OFFSET(clk->id); + else if (parent == &ckih_clk) + reg |= 2 << MXC_CCM_CSCMR2_DI_CLK_SEL_OFFSET(clk->id); + else if (parent == &tve_clk) + reg |= 3 << MXC_CCM_CSCMR2_DI_CLK_SEL_OFFSET(clk->id); + else /* Assume any other clock is external clock pin */ + reg |= 4 << MXC_CCM_CSCMR2_DI_CLK_SEL_OFFSET(clk->id); + __raw_writel(reg, MXC_CCM_CSCMR2); + + return 0; +} + +static void _clk_ipu_di_recalc(struct clk *clk) +{ + u32 reg, div, mux; + + reg = __raw_readl(MXC_CCM_CSCMR2); + mux = (reg & MXC_CCM_CSCMR2_DI_CLK_SEL_MASK(clk->id)) >> + MXC_CCM_CSCMR2_DI_CLK_SEL_OFFSET(clk->id); + if (mux == 0) { + reg = __raw_readl(MXC_CCM_CDCDR) & + MXC_CCM_CDCDR_DI_CLK_PRED_MASK; + div = (reg >> MXC_CCM_CDCDR_DI_CLK_PRED_OFFSET) + 1; + clk->rate = clk->parent->rate / div; + } else if (mux == 3) { + clk->rate = clk->parent->rate / 8; + } else { + clk->rate = clk->parent->rate; + } +} + +static int _clk_ipu_di_set_rate(struct clk *clk, unsigned long rate) +{ + u32 reg, div; + + div = clk->parent->rate / rate; + if (div == 0) + div++; + if (((clk->parent->rate / div) != rate) || (div > 8)) + return -EINVAL; + + reg = __raw_readl(MXC_CCM_CDCDR); + reg &= ~MXC_CCM_CDCDR_DI_CLK_PRED_MASK; + reg |= (div - 1) << MXC_CCM_CDCDR_DI_CLK_PRED_OFFSET; + __raw_writel(reg, MXC_CCM_CDCDR); + + clk->rate = rate; + + return 0; +} + +static unsigned long _clk_ipu_di_round_rate(struct clk *clk, + unsigned long rate) +{ + u32 div; + + div = clk->parent->rate / rate; + if (div > 8) + div = 8; + else if (div == 0) + div++; + return clk->parent->rate / div; +} + +static struct clk ipu_di_clk[] = { + { + .name = "ipu_di0_clk", + .id = 0, + .parent = &pll3_sw_clk, + .enable_reg = MXC_CCM_CCGR6, + .enable_shift = MXC_CCM_CCGR6_CG5_OFFSET, + .recalc = _clk_ipu_di_recalc, + .set_parent = _clk_ipu_di_set_parent, + .round_rate = _clk_ipu_di_round_rate, + .set_rate = _clk_ipu_di_set_rate, + .enable = _clk_enable, + .disable = _clk_disable, + }, + { + .name = "ipu_di1_clk", + .id = 1, + .parent = &pll3_sw_clk, + .enable_reg = MXC_CCM_CCGR6, + .enable_shift = MXC_CCM_CCGR6_CG6_OFFSET, + .recalc = _clk_ipu_di_recalc, + .set_parent = _clk_ipu_di_set_parent, + .round_rate = _clk_ipu_di_round_rate, + .set_rate = _clk_ipu_di_set_rate, + .enable = _clk_enable, + .disable = _clk_disable, + }, +}; + +static int _clk_csi0_set_parent(struct clk *clk, struct clk *parent) +{ + u32 reg, mux; + + reg = __raw_readl(MXC_CCM_CSCMR2); + mux = _get_mux(parent, &pll1_sw_clk, &pll2_sw_clk, &pll3_sw_clk, NULL); + reg = (reg & ~MXC_CCM_CSCMR2_CSI_MCLK1_CLK_SEL_MASK) | + (mux << MXC_CCM_CSCMR2_CSI_MCLK1_CLK_SEL_OFFSET); + __raw_writel(reg, MXC_CCM_CSCMR2); + + return 0; +} + +static void _clk_csi0_recalc(struct clk *clk) +{ + u32 reg, pred, podf; + + reg = __raw_readl(MXC_CCM_CSCDR4); + pred = ((reg & MXC_CCM_CSCDR4_CSI_MCLK1_CLK_PRED_MASK) >> + MXC_CCM_CSCDR4_CSI_MCLK1_CLK_PRED_OFFSET) + 1; + podf = ((reg & MXC_CCM_CSCDR4_CSI_MCLK1_CLK_PODF_MASK) >> + MXC_CCM_CSCDR4_CSI_MCLK1_CLK_PODF_OFFSET) + 1; + clk->rate = clk->parent->rate / (pred * podf); +} + +static unsigned long _clk_csi0_round_rate(struct clk *clk, unsigned long rate) +{ + u32 pre, post; + u32 div = clk->parent->rate / rate; + if (clk->parent->rate % rate) + div++; + + __calc_pre_post_dividers(div, &pre, &post); + + return clk->parent->rate / (pre * post); +} + +static int _clk_csi0_set_rate(struct clk *clk, unsigned long rate) +{ + u32 reg; + u32 div; + u32 pre, post; + + div = clk->parent->rate / rate; + + if ((clk->parent->rate / div) != rate) + return -EINVAL; + + __calc_pre_post_dividers(div, &pre, &post); + + /* Set CSI clock divider */ + reg = __raw_readl(MXC_CCM_CSCDR4) & + ~(MXC_CCM_CSCDR4_CSI_MCLK1_CLK_PRED_MASK | + MXC_CCM_CSCDR4_CSI_MCLK1_CLK_PODF_MASK); + reg |= (post - 1) << MXC_CCM_CSCDR4_CSI_MCLK1_CLK_PODF_OFFSET; + reg |= (pre - 1) << MXC_CCM_CSCDR4_CSI_MCLK1_CLK_PRED_OFFSET; + __raw_writel(reg, MXC_CCM_CSCDR4); + + clk->rate = rate; + return 0; +} + +static struct clk csi0_clk = { + .name = "csi_mclk1", + .parent = &pll3_sw_clk, + .set_parent = _clk_csi0_set_parent, + .recalc = _clk_csi0_recalc, + .round_rate = _clk_csi0_round_rate, + .set_rate = _clk_csi0_set_rate, + .enable = _clk_enable, + .enable_reg = MXC_CCM_CCGR6, + .enable_shift = MXC_CCM_CCGR6_CG2_OFFSET, + .disable = _clk_disable, +}; + +static int _clk_csi1_set_parent(struct clk *clk, struct clk *parent) +{ + u32 reg, mux; + + reg = __raw_readl(MXC_CCM_CSCMR2); + mux = _get_mux(parent, &pll1_sw_clk, &pll2_sw_clk, &pll3_sw_clk, NULL); + reg = (reg & ~MXC_CCM_CSCMR2_CSI_MCLK2_CLK_SEL_MASK) | + (mux << MXC_CCM_CSCMR2_CSI_MCLK2_CLK_SEL_OFFSET); + __raw_writel(reg, MXC_CCM_CSCMR2); + + return 0; +} + +static void _clk_csi1_recalc(struct clk *clk) +{ + u32 reg, pred, podf; + + reg = __raw_readl(MXC_CCM_CSCDR4); + pred = ((reg & MXC_CCM_CSCDR4_CSI_MCLK2_CLK_PRED_MASK) >> + MXC_CCM_CSCDR4_CSI_MCLK2_CLK_PRED_OFFSET) + 1; + podf = ((reg & MXC_CCM_CSCDR4_CSI_MCLK2_CLK_PODF_MASK) >> + MXC_CCM_CSCDR4_CSI_MCLK2_CLK_PODF_OFFSET) + 1; + clk->rate = clk->parent->rate / (pred * podf); +} + +static unsigned long _clk_csi1_round_rate(struct clk *clk, unsigned long rate) +{ + u32 pre, post; + u32 div = clk->parent->rate / rate; + if (clk->parent->rate % rate) + div++; + + __calc_pre_post_dividers(div, &pre, &post); + + return clk->parent->rate / (pre * post); +} + +static int _clk_csi1_set_rate(struct clk *clk, unsigned long rate) +{ + u32 reg; + u32 div; + u32 pre, post; + + div = clk->parent->rate / rate; + + if ((clk->parent->rate / div) != rate) + return -EINVAL; + + __calc_pre_post_dividers(div, &pre, &post); + + /* Set CSI clock divider */ + reg = __raw_readl(MXC_CCM_CSCDR4) & + ~(MXC_CCM_CSCDR4_CSI_MCLK2_CLK_PRED_MASK | + MXC_CCM_CSCDR4_CSI_MCLK2_CLK_PODF_MASK); + reg |= (post - 1) << MXC_CCM_CSCDR4_CSI_MCLK2_CLK_PODF_OFFSET; + reg |= (pre - 1) << MXC_CCM_CSCDR4_CSI_MCLK2_CLK_PRED_OFFSET; + __raw_writel(reg, MXC_CCM_CSCDR4); + + clk->rate = rate; + return 0; +} + +static struct clk csi1_clk = { + .name = "csi_mclk2", + .parent = &pll3_sw_clk, + .set_parent = _clk_csi1_set_parent, + .recalc = _clk_csi1_recalc, + .round_rate = _clk_csi1_round_rate, + .set_rate = _clk_csi1_set_rate, + .enable = _clk_enable, + .enable_reg = MXC_CCM_CCGR6, + .enable_shift = MXC_CCM_CCGR6_CG3_OFFSET, + .disable = _clk_disable, +}; + + +static int _clk_hsc_enable(struct clk *clk) +{ + u32 reg; + + _clk_enable(clk); + /* Handshake with IPU when certain clock rates are changed. */ + reg = __raw_readl(MXC_CCM_CCDR); + reg &= ~MXC_CCM_CCDR_HSC_HS_MASK; + __raw_writel(reg, MXC_CCM_CCDR); + + reg = __raw_readl(MXC_CCM_CLPCR); + reg &= ~MXC_CCM_CLPCR_BYPASS_HSC_LPM_HS; + __raw_writel(reg, MXC_CCM_CLPCR); + + return 0; +} + +static void _clk_hsc_disable(struct clk *clk) +{ + u32 reg; + + _clk_disable(clk); + /* No handshake with HSC as its not enabled. */ + reg = __raw_readl(MXC_CCM_CCDR); + reg |= MXC_CCM_CCDR_HSC_HS_MASK; + __raw_writel(reg, MXC_CCM_CCDR); + + reg = __raw_readl(MXC_CCM_CLPCR); + reg |= MXC_CCM_CLPCR_BYPASS_HSC_LPM_HS; + __raw_writel(reg, MXC_CCM_CLPCR); +} + +static struct clk mipi_esc_clk = { + .name = "mipi_esc_clk", + .parent = &pll2_sw_clk, + .enable_reg = MXC_CCM_CCGR4, + .enable_shift = MXC_CCM_CCGR4_CG5_OFFSET, +}; + +static struct clk mipi_hsc2_clk = { + .name = "mipi_hsc2_clk", + .parent = &pll2_sw_clk, + .enable_reg = MXC_CCM_CCGR4, + .enable_shift = MXC_CCM_CCGR4_CG4_OFFSET, + .secondary = &mipi_esc_clk, +}; + +static struct clk mipi_hsc1_clk = { + .name = "mipi_hsc1_clk", + .parent = &pll2_sw_clk, + .enable_reg = MXC_CCM_CCGR4, + .enable_shift = MXC_CCM_CCGR4_CG3_OFFSET, + .secondary = &mipi_hsc2_clk, +}; + +static struct clk mipi_hsp_clk = { + .name = "mipi_hsp_clk", + .parent = &ipu_clk[0], + .enable_reg = MXC_CCM_CCGR4, + .enable_shift = MXC_CCM_CCGR4_CG6_OFFSET, + .enable = _clk_hsc_enable, + .disable = _clk_hsc_disable, + .secondary = &mipi_hsc1_clk, +}; + +static int _clk_tve_set_parent(struct clk *clk, struct clk *parent) +{ + u32 reg; + + reg = __raw_readl(MXC_CCM_CSCMR1); + + if (parent == &pll3_sw_clk) { + reg &= ~(MXC_CCM_CSCMR1_TVE_CLK_SEL); + } else if (parent == &osc_clk) { + reg |= MXC_CCM_CSCMR1_TVE_CLK_SEL; + reg &= MXC_CCM_CSCMR1_TVE_EXT_CLK_SEL; + } else if (parent == &ckih_clk) { + reg |= MXC_CCM_CSCMR1_TVE_CLK_SEL; + reg |= MXC_CCM_CSCMR1_TVE_EXT_CLK_SEL; + } else { + BUG(); + } + + __raw_writel(reg, MXC_CCM_CSCMR1); + return 0; +} + +static void _clk_tve_recalc(struct clk *clk) +{ + u32 reg, div; + + reg = __raw_readl(MXC_CCM_CSCMR1); + if ((reg & MXC_CCM_CSCMR1_TVE_CLK_SEL) == 0) { + reg = __raw_readl(MXC_CCM_CDCDR) & + MXC_CCM_CDCDR_TVE_CLK_PRED_MASK; + div = (reg >> MXC_CCM_CDCDR_TVE_CLK_PRED_OFFSET) + 1; + clk->rate = clk->parent->rate / div; + } else { + clk->rate = clk->parent->rate; + } +} + +static unsigned long _clk_tve_round_rate(struct clk *clk, + unsigned long rate) +{ + u32 reg, div; + + reg = __raw_readl(MXC_CCM_CSCMR1); + if (reg & MXC_CCM_CSCMR1_TVE_CLK_SEL) + return -EINVAL; + + div = clk->parent->rate / rate; + if (div > 8) + div = 8; + else if (div == 0) + div++; + return clk->parent->rate / div; +} + +static int _clk_tve_set_rate(struct clk *clk, unsigned long rate) +{ + u32 reg, div; + + reg = __raw_readl(MXC_CCM_CSCMR1); + if (reg & MXC_CCM_CSCMR1_TVE_CLK_SEL) + return -EINVAL; + + div = clk->parent->rate / rate; + if (div == 0) + div++; + if (((clk->parent->rate / div) != rate) || (div > 8)) + return -EINVAL; + + div--; + reg = __raw_readl(MXC_CCM_CDCDR) & ~MXC_CCM_CDCDR_TVE_CLK_PRED_MASK; + reg |= div << MXC_CCM_CDCDR_TVE_CLK_PRED_OFFSET; + __raw_writel(reg, MXC_CCM_CDCDR); + clk->rate = rate; + return 0; +} + +static struct clk tve_clk = { + .name = "tve_clk", + .parent = &pll3_sw_clk, + .set_parent = _clk_tve_set_parent, + .enable_reg = MXC_CCM_CCGR2, + .enable_shift = MXC_CCM_CCGR2_CG15_OFFSET, + .recalc = _clk_tve_recalc, + .round_rate = _clk_tve_round_rate, + .set_rate = _clk_tve_set_rate, + .enable = _clk_enable, + .disable = _clk_disable, + .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE, +}; + +static struct clk spba_clk = { + .name = "spba_clk", + .parent = &ipg_clk, + .enable_reg = MXC_CCM_CCGR5, + .enable_shift = MXC_CCM_CCGR5_CG0_OFFSET, + .enable = _clk_enable, + .disable = _clk_disable, +}; + +static void _clk_uart_recalc(struct clk *clk) +{ + u32 reg, prediv, podf; + + reg = __raw_readl(MXC_CCM_CSCDR1); + prediv = ((reg & MXC_CCM_CSCDR1_UART_CLK_PRED_MASK) >> + MXC_CCM_CSCDR1_UART_CLK_PRED_OFFSET) + 1; + podf = ((reg & MXC_CCM_CSCDR1_UART_CLK_PODF_MASK) >> + MXC_CCM_CSCDR1_UART_CLK_PODF_OFFSET) + 1; + + clk->rate = clk->parent->rate / (prediv * podf); +} + +static int _clk_uart_set_parent(struct clk *clk, struct clk *parent) +{ + u32 reg, mux; + + mux = _get_mux(parent, &pll1_sw_clk, &pll2_sw_clk, &pll3_sw_clk, + &lp_apm_clk); + reg = __raw_readl(MXC_CCM_CSCMR1) & ~MXC_CCM_CSCMR1_UART_CLK_SEL_MASK; + reg |= mux << MXC_CCM_CSCMR1_UART_CLK_SEL_OFFSET; + __raw_writel(reg, MXC_CCM_CSCMR1); + + return 0; +} + +static struct clk uart_main_clk = { + .name = "uart_main_clk", + .parent = &pll2_sw_clk, + .recalc = _clk_uart_recalc, + .set_parent = _clk_uart_set_parent, + .flags = RATE_PROPAGATES, +}; + +static struct clk uart1_clk[] = { + { + .name = "uart_clk", + .id = 0, + .parent = &uart_main_clk, + .secondary = &uart1_clk[1], + .enable_reg = MXC_CCM_CCGR1, + .enable_shift = MXC_CCM_CCGR1_CG4_OFFSET, + .enable = _clk_enable, + .disable = _clk_disable, +#ifdef UART1_DMA_ENABLE + .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE, +#endif + }, + { + .name = "uart_ipg_clk", + .id = 0, + .parent = &ipg_clk, +#ifdef UART1_DMA_ENABLE + .secondary = &aips_tz1_clk, +#endif + .enable_reg = MXC_CCM_CCGR1, + .enable_shift = MXC_CCM_CCGR1_CG3_OFFSET, + .enable = _clk_enable, + .disable = _clk_disable, + }, +}; + +static struct clk uart2_clk[] = { + { + .name = "uart_clk", + .id = 1, + .parent = &uart_main_clk, + .secondary = &uart2_clk[1], + .enable_reg = MXC_CCM_CCGR1, + .enable_shift = MXC_CCM_CCGR1_CG6_OFFSET, + .enable = _clk_enable, + .disable = _clk_disable, +#ifdef UART2_DMA_ENABLE + .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE, +#endif + }, + { + .name = "uart_ipg_clk", + .id = 1, + .parent = &ipg_clk, +#ifdef UART2_DMA_ENABLE + .secondary = &aips_tz1_clk, +#endif + .enable_reg = MXC_CCM_CCGR1, + .enable_shift = MXC_CCM_CCGR1_CG5_OFFSET, + .enable = _clk_enable, + .disable = _clk_disable, + }, +}; + +static struct clk uart3_clk[] = { + { + .name = "uart_clk", + .id = 2, + .parent = &uart_main_clk, + .secondary = &uart3_clk[1], + .enable_reg = MXC_CCM_CCGR1, + .enable_shift = MXC_CCM_CCGR1_CG8_OFFSET, + .enable = _clk_enable, + .disable = _clk_disable, +#ifdef UART3_DMA_ENABLE + .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE, +#endif + }, + { + .name = "uart_ipg_clk", + .id = 2, + .parent = &ipg_clk, + .secondary = &spba_clk, + .enable_reg = MXC_CCM_CCGR1, + .enable_shift = MXC_CCM_CCGR1_CG7_OFFSET, + .enable = _clk_enable, + .disable = _clk_disable, + }, +}; + +static struct clk gpt_clk[] = { + { + .name = "gpt_clk", + .parent = &ipg_perclk, + .id = 0, + .enable_reg = MXC_CCM_CCGR2, + .enable_shift = MXC_CCM_CCGR2_CG9_OFFSET, + .enable = _clk_enable, + .disable = _clk_disable, + .secondary = &gpt_clk[1], + }, + { + .name = "gpt_ipg_clk", + .id = 0, + .parent = &ipg_clk, + .enable_reg = MXC_CCM_CCGR2, + .enable_shift = MXC_CCM_CCGR2_CG10_OFFSET, + .enable = _clk_enable, + .disable = _clk_disable, + }, + { + .name = "gpt_32k_clk", + .id = 0, + .parent = &ckil_clk, + }, +}; + +static struct clk pwm1_clk[] = { + { + .name = "pwm", + .parent = &ipg_perclk, + .id = 0, + .enable_reg = MXC_CCM_CCGR2, + .enable_shift = MXC_CCM_CCGR2_CG6_OFFSET, + .enable = _clk_enable, + .disable = _clk_disable, + .secondary = &pwm1_clk[1], + }, + { + .name = "pwm_ipg_clk", + .id = 0, + .parent = &ipg_clk, + .enable_reg = MXC_CCM_CCGR2, + .enable_shift = MXC_CCM_CCGR2_CG5_OFFSET, + .enable = _clk_enable_inwait, /*Active only when ARM is running. */ + .disable = _clk_disable, + }, + { + .name = "pwm_32k_clk", + .id = 0, + .parent = &ckil_clk, + }, +}; + +static struct clk pwm2_clk[] = { + { + .name = "pwm", + .parent = &ipg_perclk, + .id = 1, + .enable_reg = MXC_CCM_CCGR2, + .enable_shift = MXC_CCM_CCGR2_CG8_OFFSET, + .enable = _clk_enable, + .disable = _clk_disable, + .secondary = &pwm2_clk[1], + }, + { + .name = "pwm_ipg_clk", + .id = 1, + .parent = &ipg_clk, + .enable_reg = MXC_CCM_CCGR2, + .enable_shift = MXC_CCM_CCGR2_CG7_OFFSET, + .enable = _clk_enable_inwait, /*Active only when ARM is running. */ + .disable = _clk_disable, + }, + { + .name = "pwm_32k_clk", + .id = 1, + .parent = &ckil_clk, + }, +}; + +static struct clk i2c_clk[] = { + { + .name = "i2c_clk", + .id = 0, + .parent = &ipg_perclk, + .enable_reg = MXC_CCM_CCGR1, + .enable_shift = MXC_CCM_CCGR1_CG9_OFFSET, + .enable = _clk_enable, + .disable = _clk_disable, + }, + { + .name = "i2c_clk", + .id = 1, + .parent = &ipg_perclk, + .enable_reg = MXC_CCM_CCGR1, + .enable_shift = MXC_CCM_CCGR1_CG10_OFFSET, + .enable = _clk_enable, + .disable = _clk_disable, + }, +}; + +static void _clk_hsi2c_serial_recalc(struct clk *clk) +{ + u32 reg, prediv, podf; + + reg = __raw_readl(MXC_CCM_CSCDR3); + prediv = ((reg & MXC_CCM_CSCDR3_HSI2C_CLK_PRED_MASK) >> + MXC_CCM_CSCDR3_HSI2C_CLK_PRED_OFFSET) + 1; + podf = ((reg & MXC_CCM_CSCDR3_HSI2C_CLK_PODF_MASK) >> + MXC_CCM_CSCDR3_HSI2C_CLK_PODF_OFFSET) + 1; + + clk->rate = clk->parent->rate / (prediv * podf); +} + +static struct clk hsi2c_serial_clk = { + .name = "hsi2c_serial_clk", + .id = 0, + .parent = &pll3_sw_clk, + .secondary = &spba_clk, + .enable_reg = MXC_CCM_CCGR1, + .enable_shift = MXC_CCM_CCGR1_CG11_OFFSET, + .recalc = _clk_hsi2c_serial_recalc, + .enable = _clk_enable, + .disable = _clk_disable, +}; + +static struct clk hsi2c_clk = { + .name = "hsi2c_clk", + .id = 0, + .parent = &ipg_clk, + .enable_reg = MXC_CCM_CCGR1, + .enable_shift = MXC_CCM_CCGR1_CG12_OFFSET, + .enable = _clk_enable, + .disable = _clk_disable, + .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE, +}; + +static void _clk_cspi_recalc(struct clk *clk) +{ + u32 reg, prediv, podf; + + reg = __raw_readl(MXC_CCM_CSCDR2); + prediv = ((reg & MXC_CCM_CSCDR2_CSPI_CLK_PRED_MASK) >> + MXC_CCM_CSCDR2_CSPI_CLK_PRED_OFFSET) + 1; + if (prediv == 1) + BUG(); + podf = ((reg & MXC_CCM_CSCDR2_CSPI_CLK_PODF_MASK) >> + MXC_CCM_CSCDR2_CSPI_CLK_PODF_OFFSET) + 1; + + clk->rate = clk->parent->rate / (prediv * podf); +} + +static int _clk_cspi_set_parent(struct clk *clk, struct clk *parent) +{ + u32 reg, mux; + + mux = _get_mux(parent, &pll1_sw_clk, &pll2_sw_clk, &pll3_sw_clk, + &lp_apm_clk); + reg = __raw_readl(MXC_CCM_CSCMR1) & ~MXC_CCM_CSCMR1_CSPI_CLK_SEL_MASK; + reg |= mux << MXC_CCM_CSCMR1_CSPI_CLK_SEL_OFFSET; + __raw_writel(reg, MXC_CCM_CSCMR1); + + return 0; +} + +static struct clk cspi_main_clk = { + .name = "cspi_main_clk", + .parent = &pll3_sw_clk, + .recalc = _clk_cspi_recalc, + .set_parent = _clk_cspi_set_parent, + .flags = RATE_PROPAGATES, +}; + +static struct clk cspi1_clk[] = { + { + .name = "cspi_clk", + .id = 0, + .parent = &cspi_main_clk, + .secondary = &cspi1_clk[1], + .enable_reg = MXC_CCM_CCGR4, + .enable_shift = MXC_CCM_CCGR4_CG10_OFFSET, + .enable = _clk_enable, + .disable = _clk_disable, + }, + { + .name = "cspi_ipg_clk", + .id = 0, + .parent = &ipg_clk, + .secondary = &spba_clk, + .enable_reg = MXC_CCM_CCGR4, + .enable_shift = MXC_CCM_CCGR4_CG9_OFFSET, + .enable = _clk_enable_inwait, /*Active only when ARM is running. */ + .disable = _clk_disable, + }, +}; + +static struct clk cspi2_clk[] = { + { + .name = "cspi_clk", + .id = 1, + .parent = &cspi_main_clk, + .secondary = &cspi2_clk[1], + .enable_reg = MXC_CCM_CCGR4, + .enable_shift = MXC_CCM_CCGR4_CG12_OFFSET, + .enable = _clk_enable, + .disable = _clk_disable, + }, + { + .name = "cspi_ipg_clk", + .id = 1, + .parent = &ipg_clk, + .secondary = &aips_tz2_clk, + .enable_reg = MXC_CCM_CCGR4, + .enable_shift = MXC_CCM_CCGR4_CG11_OFFSET, + .enable = _clk_enable_inwait, /*Active only when ARM is running. */ + .disable = _clk_disable, + }, +}; + +static struct clk cspi3_clk[] = { + { + .name = "cspi_clk", + .id = 2, + .parent = &cspi_main_clk, + .enable_reg = MXC_CCM_CCGR4, + .enable_shift = MXC_CCM_CCGR4_CG13_OFFSET, + .enable = _clk_enable, + .disable = _clk_disable, + .secondary = &cspi3_clk[1], + }, + { + .name = "cspi_ipg_clk", + .id = 2, + .parent = &ipg_clk, + .secondary = &aips_tz2_clk, + }, +}; + +static int _clk_ssi_lp_apm_set_parent(struct clk *clk, struct clk *parent) +{ + u32 reg, mux; + + mux = _get_mux(parent, &ckih_clk, &lp_apm_clk, &ckih2_clk, NULL); + reg = __raw_readl(MXC_CCM_CSCMR1) & + ~MXC_CCM_CSCMR1_SSI_APM_CLK_SEL_MASK; + reg |= mux << MXC_CCM_CSCMR1_SSI_APM_CLK_SEL_OFFSET; + __raw_writel(reg, MXC_CCM_CSCMR1); + + return 0; +} + +static struct clk ssi_lp_apm_clk = { + .name = "ssi_lp_apm_clk", + .parent = &ckih_clk, + .set_parent = _clk_ssi_lp_apm_set_parent, +}; + +static void _clk_ssi1_recalc(struct clk *clk) +{ + u32 reg, prediv, podf; + + reg = __raw_readl(MXC_CCM_CS1CDR); + prediv = ((reg & MXC_CCM_CS1CDR_SSI1_CLK_PRED_MASK) >> + MXC_CCM_CS1CDR_SSI1_CLK_PRED_OFFSET) + 1; + if (prediv == 1) + BUG(); + podf = ((reg & MXC_CCM_CS1CDR_SSI1_CLK_PODF_MASK) >> + MXC_CCM_CS1CDR_SSI1_CLK_PODF_OFFSET) + 1; + + clk->rate = clk->parent->rate / (prediv * podf); +} +static int _clk_ssi1_set_parent(struct clk *clk, struct clk *parent) +{ + u32 reg, mux; + + mux = _get_mux(parent, &pll1_sw_clk, &pll2_sw_clk, + &pll3_sw_clk, &ssi_lp_apm_clk); + reg = __raw_readl(MXC_CCM_CSCMR1) & ~MXC_CCM_CSCMR1_SSI1_CLK_SEL_MASK; + reg |= mux << MXC_CCM_CSCMR1_SSI1_CLK_SEL_OFFSET; + __raw_writel(reg, MXC_CCM_CSCMR1); + + return 0; +} + +static struct clk ssi1_clk[] = { + { + .name = "ssi_clk", + .id = 0, + .parent = &pll3_sw_clk, + .set_parent = _clk_ssi1_set_parent, + .secondary = &ssi1_clk[1], + .recalc = _clk_ssi1_recalc, + .enable_reg = MXC_CCM_CCGR3, + .enable_shift = MXC_CCM_CCGR3_CG9_OFFSET, + .enable = _clk_enable, + .disable = _clk_disable, + }, + { + .name = "ssi_ipg_clk", + .id = 0, + .parent = &ipg_clk, + .secondary = &ssi1_clk[2], + .enable_reg = MXC_CCM_CCGR3, + .enable_shift = MXC_CCM_CCGR3_CG8_OFFSET, + .enable = _clk_enable, + .disable = _clk_disable, + }, + { + .name = "ssi_dep_clk", + .id = 0, + .parent = &aips_tz2_clk, +#ifdef CONFIG_SND_MXC_SOC_IRAM + .secondary = &emi_intr_clk, +#else + .secondary = &emi_fast_clk, +#endif + }, +}; + +static void _clk_ssi2_recalc(struct clk *clk) +{ + u32 reg, prediv, podf; + + reg = __raw_readl(MXC_CCM_CS2CDR); + prediv = ((reg & MXC_CCM_CS2CDR_SSI2_CLK_PRED_MASK) >> + MXC_CCM_CS2CDR_SSI2_CLK_PRED_OFFSET) + 1; + if (prediv == 1) + BUG(); + podf = ((reg & MXC_CCM_CS2CDR_SSI2_CLK_PODF_MASK) >> + MXC_CCM_CS2CDR_SSI2_CLK_PODF_OFFSET) + 1; + + clk->rate = clk->parent->rate / (prediv * podf); +} + +static int _clk_ssi2_set_parent(struct clk *clk, struct clk *parent) +{ + u32 reg, mux; + + mux = _get_mux(parent, &pll1_sw_clk, &pll2_sw_clk, + &pll3_sw_clk, &ssi_lp_apm_clk); + reg = __raw_readl(MXC_CCM_CSCMR1) & ~MXC_CCM_CSCMR1_SSI2_CLK_SEL_MASK; + reg |= mux << MXC_CCM_CSCMR1_SSI2_CLK_SEL_OFFSET; + __raw_writel(reg, MXC_CCM_CSCMR1); + + return 0; +} + +static struct clk ssi2_clk[] = { + { + .name = "ssi_clk", + .id = 1, + .parent = &pll3_sw_clk, + .set_parent = _clk_ssi2_set_parent, + .secondary = &ssi2_clk[1], + .recalc = _clk_ssi2_recalc, + .enable_reg = MXC_CCM_CCGR3, + .enable_shift = MXC_CCM_CCGR3_CG11_OFFSET, + .enable = _clk_enable, + .disable = _clk_disable, + }, + { + .name = "ssi_ipg_clk", + .id = 1, + .parent = &ipg_clk, + .secondary = &ssi2_clk[2], + .enable_reg = MXC_CCM_CCGR3, + .enable_shift = MXC_CCM_CCGR3_CG10_OFFSET, + .enable = _clk_enable, + .disable = _clk_disable, + }, + { + .name = "ssi_dep_clk", + .id = 1, + .parent = &spba_clk, +#ifdef CONFIG_SND_MXC_SOC_IRAM + .secondary = &emi_intr_clk, +#else + .secondary = &emi_fast_clk, +#endif + }, +}; + +static void _clk_ssi_ext1_recalc(struct clk *clk) +{ + u32 reg, prediv, podf; + + clk->rate = clk->parent->rate; + reg = __raw_readl(MXC_CCM_CSCMR1); + if ((reg & MXC_CCM_CSCMR1_SSI_EXT1_COM_CLK_SEL) == 0) { + reg = __raw_readl(MXC_CCM_CS1CDR); + prediv = ((reg & MXC_CCM_CS1CDR_SSI_EXT1_CLK_PRED_MASK) >> + MXC_CCM_CS1CDR_SSI_EXT1_CLK_PRED_OFFSET) + 1; + if (prediv == 1) + BUG(); + podf = ((reg & MXC_CCM_CS1CDR_SSI_EXT1_CLK_PODF_MASK) >> + MXC_CCM_CS1CDR_SSI_EXT1_CLK_PODF_OFFSET) + 1; + clk->rate = clk->parent->rate / (prediv * podf); + } +} + +static int _clk_ssi_ext1_set_parent(struct clk *clk, struct clk *parent) +{ + u32 reg, mux; + + reg = __raw_readl(MXC_CCM_CSCMR1); + if (parent == &ssi1_clk[0]) { + reg |= MXC_CCM_CSCMR1_SSI_EXT1_COM_CLK_SEL; + } else { + reg &= ~MXC_CCM_CSCMR1_SSI_EXT1_COM_CLK_SEL; + mux = _get_mux(parent, &pll1_sw_clk, &pll2_sw_clk, &pll3_sw_clk, + &ssi_lp_apm_clk); + reg = (reg & ~MXC_CCM_CSCMR1_SSI_EXT1_CLK_SEL_MASK) | + (mux << MXC_CCM_CSCMR1_SSI_EXT1_CLK_SEL_OFFSET); + } + + __raw_writel(reg, MXC_CCM_CSCMR1); + + return 0; +} + +static struct clk ssi_ext1_clk = { + .name = "ssi_ext1_clk", + .parent = &pll3_sw_clk, + .set_parent = _clk_ssi_ext1_set_parent, + .recalc = _clk_ssi_ext1_recalc, + .enable_reg = MXC_CCM_CCGR3, + .enable_shift = MXC_CCM_CCGR3_CG14_OFFSET, + .enable = _clk_enable, + .disable = _clk_disable, +}; + +static void _clk_ssi_ext2_recalc(struct clk *clk) +{ + u32 reg, prediv, podf; + + clk->rate = clk->parent->rate; + reg = __raw_readl(MXC_CCM_CSCMR1); + if ((reg & MXC_CCM_CSCMR1_SSI_EXT2_COM_CLK_SEL) == 0) { + reg = __raw_readl(MXC_CCM_CS2CDR); + prediv = ((reg & MXC_CCM_CS2CDR_SSI_EXT2_CLK_PRED_MASK) >> + MXC_CCM_CS2CDR_SSI_EXT2_CLK_PRED_OFFSET) + 1; + if (prediv == 1) + BUG(); + podf = ((reg & MXC_CCM_CS2CDR_SSI_EXT2_CLK_PODF_MASK) >> + MXC_CCM_CS2CDR_SSI_EXT2_CLK_PODF_OFFSET) + 1; + clk->rate = clk->parent->rate / (prediv * podf); + } +} + +static int _clk_ssi_ext2_set_parent(struct clk *clk, struct clk *parent) +{ + u32 reg, mux; + + reg = __raw_readl(MXC_CCM_CSCMR1); + if (parent == &ssi2_clk[0]) { + reg |= MXC_CCM_CSCMR1_SSI_EXT2_COM_CLK_SEL; + } else { + reg &= ~MXC_CCM_CSCMR1_SSI_EXT2_COM_CLK_SEL; + mux = _get_mux(parent, &pll1_sw_clk, &pll2_sw_clk, &pll3_sw_clk, + &ssi_lp_apm_clk); + reg = (reg & ~MXC_CCM_CSCMR1_SSI_EXT2_CLK_SEL_MASK) | + (mux << MXC_CCM_CSCMR1_SSI_EXT2_CLK_SEL_OFFSET); + } + + __raw_writel(reg, MXC_CCM_CSCMR1); + + return 0; +} + +static struct clk ssi_ext2_clk = { + .name = "ssi_ext2_clk", + .parent = &pll3_sw_clk, + .set_parent = _clk_ssi_ext2_set_parent, + .recalc = _clk_ssi_ext2_recalc, + .enable_reg = MXC_CCM_CCGR3, + .enable_shift = MXC_CCM_CCGR3_CG15_OFFSET, + .enable = _clk_enable, + .disable = _clk_disable, +}; + +static struct clk iim_clk = { + .name = "iim_clk", + .parent = &ipg_clk, + .secondary = &aips_tz2_clk, + .enable = _clk_enable, + .enable_reg = MXC_CCM_CCGR0, + .enable_shift = MXC_CCM_CCGR0_CG15_OFFSET, + .disable = _clk_disable, +}; + +static struct clk tmax1_clk = { + .name = "tmax1_clk", + .id = 0, + .parent = &ahb_clk, + .secondary = &ahb_max_clk, + .enable = _clk_enable, + .enable_reg = MXC_CCM_CCGR1, + .enable_shift = MXC_CCM_CCGR1_CG0_OFFSET, + .disable = _clk_disable, + }; + +static struct clk tmax2_clk = { + .name = "tmax2_clk", + .id = 0, + .parent = &ahb_clk, + .secondary = &ahb_max_clk, + .enable = _clk_enable, + .enable_reg = MXC_CCM_CCGR1, + .enable_shift = MXC_CCM_CCGR1_CG1_OFFSET, + .disable = _clk_disable, +}; + +static struct clk tmax3_clk = { + .name = "tmax3_clk", + .id = 0, + .parent = &ahb_clk, + .secondary = &ahb_max_clk, + .enable = _clk_enable, + .enable_reg = MXC_CCM_CCGR1, + .enable_shift = MXC_CCM_CCGR1_CG2_OFFSET, + .disable = _clk_disable, +}; + +static void _clk_usboh3_recalc(struct clk *clk) +{ + u32 reg, prediv, podf; + + reg = __raw_readl(MXC_CCM_CSCDR1); + prediv = ((reg & MXC_CCM_CSCDR1_USBOH3_CLK_PRED_MASK) >> + MXC_CCM_CSCDR1_USBOH3_CLK_PRED_OFFSET) + 1; + if (prediv == 1) + BUG(); + podf = ((reg & MXC_CCM_CSCDR1_USBOH3_CLK_PODF_MASK) >> + MXC_CCM_CSCDR1_USBOH3_CLK_PODF_OFFSET) + 1; + + clk->rate = clk->parent->rate / (prediv * podf); +} + +static int _clk_usboh3_set_parent(struct clk *clk, struct clk *parent) +{ + u32 reg, mux; + + mux = _get_mux(parent, &pll1_sw_clk, &pll2_sw_clk, &pll3_sw_clk, + &lp_apm_clk); + reg = __raw_readl(MXC_CCM_CSCMR1) & ~MXC_CCM_CSCMR1_USBOH3_CLK_SEL_MASK; + reg |= mux << MXC_CCM_CSCMR1_USBOH3_CLK_SEL_OFFSET; + __raw_writel(reg, MXC_CCM_CSCMR1); + + return 0; +} + +static struct clk usboh3_clk[] = { + { + .name = "usboh3_clk", + .parent = &pll3_sw_clk, + .set_parent = _clk_usboh3_set_parent, + .recalc = _clk_usboh3_recalc, + .enable = _clk_enable, + .enable_reg = MXC_CCM_CCGR2, + .enable_shift = MXC_CCM_CCGR2_CG14_OFFSET, + .disable = _clk_disable, + .secondary = &usboh3_clk[1], + .flags = AHB_MED_SET_POINT | CPU_FREQ_TRIG_UPDATE, + }, + { + .name = "usb_sec_clk", + .parent = &tmax2_clk, + .secondary = &emi_fast_clk, + }, +}; +static struct clk usb_ahb_clk = { + .name = "usb_ahb_clk", + .parent = &ipg_clk, + .enable = _clk_enable, + .enable_reg = MXC_CCM_CCGR2, + .enable_shift = MXC_CCM_CCGR2_CG13_OFFSET, + .disable = _clk_disable, +}; + +static void _clk_usb_phy_recalc(struct clk *clk) +{ + u32 reg, prediv, podf; + + if (clk->parent == &pll3_sw_clk) { + reg = __raw_readl(MXC_CCM_CDCDR); + prediv = ((reg & MXC_CCM_CDCDR_USB_PHY_PRED_MASK) >> + MXC_CCM_CDCDR_USB_PHY_PRED_OFFSET) + 1; + podf = ((reg & MXC_CCM_CDCDR_USB_PHY_PODF_MASK) >> + MXC_CCM_CDCDR_USB_PHY_PODF_OFFSET) + 1; + + clk->rate = clk->parent->rate / (prediv * podf); + } else + clk->rate = clk->parent->rate; +} + +static int _clk_usb_phy_set_parent(struct clk *clk, struct clk *parent) +{ + u32 reg; + + reg = __raw_readl(MXC_CCM_CSCMR1); + if (parent == &osc_clk) + reg &= ~MXC_CCM_CSCMR1_USB_PHY_CLK_SEL; + else if (parent == &pll3_sw_clk) + reg |= MXC_CCM_CSCMR1_USB_PHY_CLK_SEL; + else + BUG(); + + __raw_writel(reg, MXC_CCM_CSCMR1); + return 0; +} + +static struct clk usb_phy_clk = { + .name = "usb_phy_clk", + .parent = &pll3_sw_clk, + .secondary = &tmax3_clk, + .set_parent = _clk_usb_phy_set_parent, + .recalc = _clk_usb_phy_recalc, + .enable = _clk_enable, + .enable_reg = MXC_CCM_CCGR2, + .enable_shift = MXC_CCM_CCGR2_CG0_OFFSET, + .disable = _clk_disable, +}; + +static struct clk esdhc_dep_clks = { + .name = "sd_dep_clk", + .parent = &spba_clk, + .secondary = &emi_fast_clk, +}; + + +static void _clk_esdhc1_recalc(struct clk *clk) +{ + u32 reg, prediv, podf; + + reg = __raw_readl(MXC_CCM_CSCDR1); + prediv = ((reg & MXC_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PRED_MASK) >> + MXC_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PRED_OFFSET) + 1; + podf = ((reg & MXC_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PODF_MASK) >> + MXC_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PODF_OFFSET) + 1; + + clk->rate = clk->parent->rate / (prediv * podf); +} + +static int _clk_esdhc1_set_parent(struct clk *clk, struct clk *parent) +{ + u32 reg, mux; + + mux = _get_mux(parent, &pll1_sw_clk, &pll2_sw_clk, &pll3_sw_clk, + &lp_apm_clk); + reg = __raw_readl(MXC_CCM_CSCMR1) & + ~MXC_CCM_CSCMR1_ESDHC1_MSHC1_CLK_SEL_MASK; + reg |= mux << MXC_CCM_CSCMR1_ESDHC1_MSHC1_CLK_SEL_OFFSET; + __raw_writel(reg, MXC_CCM_CSCMR1); + + return 0; +} + +static struct clk esdhc1_clk[] = { + { + .name = "esdhc_clk", + .id = 0, + .parent = &pll3_sw_clk, + .set_parent = _clk_esdhc1_set_parent, + .recalc = _clk_esdhc1_recalc, + .enable = _clk_enable, + .enable_reg = MXC_CCM_CCGR3, + .enable_shift = MXC_CCM_CCGR3_CG1_OFFSET, + .disable = _clk_disable, + .secondary = &esdhc1_clk[1], + .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE, + }, + { + .name = "esdhc_ipg_clk", + .id = 0, + .parent = &ipg_clk, + .secondary = &esdhc1_clk[2], + .enable = _clk_enable, + .enable_reg = MXC_CCM_CCGR3, + .enable_shift = MXC_CCM_CCGR3_CG0_OFFSET, + .disable = _clk_disable, + }, + { + .name = "esdhc_sec_clk", + .id = 0, + .parent = &tmax3_clk, + .secondary = &esdhc_dep_clks, + }, + +}; + +static void _clk_esdhc2_recalc(struct clk *clk) +{ + u32 reg, prediv, podf; + + reg = __raw_readl(MXC_CCM_CSCDR1); + prediv = ((reg & MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PRED_MASK) >> + MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PRED_OFFSET) + 1; + podf = ((reg & MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PODF_MASK) >> + MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PODF_OFFSET) + 1; + + clk->rate = clk->parent->rate / (prediv * podf); +} + +static int _clk_esdhc2_set_parent(struct clk *clk, struct clk *parent) +{ + u32 reg, mux; + + mux = _get_mux(parent, &pll1_sw_clk, &pll2_sw_clk, &pll3_sw_clk, + &lp_apm_clk); + reg = __raw_readl(MXC_CCM_CSCMR1) & + ~MXC_CCM_CSCMR1_ESDHC2_MSHC2_CLK_SEL_MASK; + reg |= mux << MXC_CCM_CSCMR1_ESDHC2_MSHC2_CLK_SEL_OFFSET; + __raw_writel(reg, MXC_CCM_CSCMR1); + + return 0; +} + +static struct clk esdhc2_clk[] = { + { + .name = "esdhc_clk", + .id = 1, + .parent = &pll3_sw_clk, + .set_parent = _clk_esdhc2_set_parent, + .recalc = _clk_esdhc2_recalc, + .enable = _clk_enable, + .enable_reg = MXC_CCM_CCGR3, + .enable_shift = MXC_CCM_CCGR3_CG3_OFFSET, + .disable = _clk_disable, + .secondary = &esdhc2_clk[1], + .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE, + }, + { + .name = "esdhc_ipg_clk", + .id = 1, + .parent = &ipg_clk, + .secondary = &esdhc2_clk[2], + .enable = _clk_enable, + .enable_reg = MXC_CCM_CCGR3, + .enable_shift = MXC_CCM_CCGR3_CG2_OFFSET, + .disable = _clk_disable, + }, + { + .name = "esdhc_sec_clk", + .id = 0, + .parent = &tmax2_clk, + .secondary = &esdhc_dep_clks, + }, +}; + +static int _clk_esdhc3_set_parent(struct clk *clk, struct clk *parent) +{ + u32 reg; + + reg = __raw_readl(MXC_CCM_CSCMR1); + if (parent == &esdhc1_clk[0]) + reg &= ~MXC_CCM_CSCMR1_ESDHC3_CLK_SEL; + else if (parent == &esdhc2_clk[0]) + reg |= MXC_CCM_CSCMR1_ESDHC3_CLK_SEL; + else + BUG(); + + __raw_writel(reg, MXC_CCM_CSCMR1); + + return 0; +} + +static struct clk esdhc3_clk[] = { + { + .name = "esdhc_clk", + .id = 2, + .parent = &esdhc1_clk[0], + .set_parent = _clk_esdhc3_set_parent, + .enable = _clk_enable, + .enable_reg = MXC_CCM_CCGR3, + .enable_shift = MXC_CCM_CCGR3_CG5_OFFSET, + .disable = _clk_disable, + .secondary = &esdhc3_clk[1], + .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE, + }, + { + .name = "esdhc_ipg_clk", + .id = 2, + .parent = &ipg_clk, + .secondary = &esdhc3_clk[2], + .enable = _clk_enable, + .enable_reg = MXC_CCM_CCGR3, + .enable_shift = MXC_CCM_CCGR3_CG4_OFFSET, + .disable = _clk_disable, + }, + { + .name = "esdhc_sec_clk", + .id = 0, + .parent = &ahb_max_clk, + .secondary = &esdhc_dep_clks, + }, +}; + + +static int _clk_esdhc4_set_parent(struct clk *clk, struct clk *parent) +{ + u32 reg; + + reg = __raw_readl(MXC_CCM_CSCMR1); + if (parent == &esdhc1_clk[0]) + reg &= ~MXC_CCM_CSCMR1_ESDHC4_CLK_SEL; + else if (parent == &esdhc2_clk[0]) + reg |= MXC_CCM_CSCMR1_ESDHC4_CLK_SEL; + else + BUG(); + + __raw_writel(reg, MXC_CCM_CSCMR1); + + return 0; +} + +static struct clk esdhc4_clk[] = { + { + .name = "esdhc_clk", + .id = 3, + .parent = &esdhc1_clk[0], + .set_parent = _clk_esdhc4_set_parent, + .enable = _clk_enable, + .enable_reg = MXC_CCM_CCGR3, + .enable_shift = MXC_CCM_CCGR3_CG7_OFFSET, + .disable = _clk_disable, + .secondary = &esdhc3_clk[1], + .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE, + }, + { + .name = "esdhc_ipg_clk", + .id = 3, + .parent = &ipg_clk, + .secondary = &esdhc3_clk[2], + .enable = _clk_enable, + .enable_reg = MXC_CCM_CCGR3, + .enable_shift = MXC_CCM_CCGR3_CG6_OFFSET, + .disable = _clk_disable, + }, + { + .name = "esdhc_sec_clk", + .id = 0, + .parent = &tmax3_clk, + .secondary = &esdhc_dep_clks, + }, +}; + +static int _clk_sim_set_parent(struct clk *clk, struct clk *parent) +{ + u32 reg, mux; + + mux = _get_mux(parent, &pll1_sw_clk, &pll2_sw_clk, &pll3_sw_clk, NULL); + reg = __raw_readl(MXC_CCM_CSCMR2) & ~MXC_CCM_CSCMR2_SIM_CLK_SEL_MASK; + reg |= mux << MXC_CCM_CSCMR2_SIM_CLK_SEL_OFFSET; + __raw_writel(reg, MXC_CCM_CSCMR2); + + return 0; +} + +static void _clk_sim_recalc(struct clk *clk) +{ + u32 reg, pred, podf; + + reg = __raw_readl(MXC_CCM_CSCDR2); + pred = ((reg & MXC_CCM_CSCDR2_SIM_CLK_PRED_MASK) >> + MXC_CCM_CSCDR2_SIM_CLK_PRED_OFFSET) + 1; + podf = ((reg & MXC_CCM_CSCDR2_SIM_CLK_PODF_MASK) >> + MXC_CCM_CSCDR2_SIM_CLK_PODF_OFFSET) + 1; + clk->rate = clk->parent->rate / (pred * podf); +} + +static unsigned long _clk_sim_round_rate(struct clk *clk, unsigned long rate) +{ + u32 pre, post; + u32 div = clk->parent->rate / rate; + if (clk->parent->rate % rate) + div++; + + __calc_pre_post_dividers(div, &pre, &post); + + return clk->parent->rate / (pre * post); +} + +static int _clk_sim_set_rate(struct clk *clk, unsigned long rate) +{ + u32 reg; + u32 div; + u32 pre, post; + + div = clk->parent->rate / rate; + + if ((clk->parent->rate / div) != rate) + return -EINVAL; + + __calc_pre_post_dividers(div, &pre, &post); + + /* Set SIM clock divider */ + reg = __raw_readl(MXC_CCM_CSCDR2) & + ~(MXC_CCM_CSCDR2_SIM_CLK_PRED_MASK | + MXC_CCM_CSCDR2_SIM_CLK_PODF_MASK); + reg |= (post - 1) << MXC_CCM_CSCDR2_SIM_CLK_PODF_OFFSET; + reg |= (pre - 1) << MXC_CCM_CSCDR2_SIM_CLK_PRED_OFFSET; + __raw_writel(reg, MXC_CCM_CSCDR2); + + clk->rate = rate; + return 0; + +} + +static struct clk sim_clk[] = { + { + .name = "sim_clk", + .parent = &pll3_sw_clk, + .set_parent = _clk_sim_set_parent, + .secondary = &sim_clk[1], + .recalc = _clk_sim_recalc, + .round_rate = _clk_sim_round_rate, + .set_rate = _clk_sim_set_rate, + .enable = _clk_enable, + .enable_reg = MXC_CCM_CCGR4, + .enable_shift = MXC_CCM_CCGR4_CG2_OFFSET, + .disable = _clk_disable, + .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE, + }, + { + .name = "sim_ipg_clk", + .parent = &ipg_clk, + .enable = _clk_enable, + .enable_reg = MXC_CCM_CCGR4, + .enable_shift = MXC_CCM_CCGR4_CG1_OFFSET, + .disable = _clk_disable, + }, +}; + +static void _clk_nfc_recalc(struct clk *clk) +{ + u32 reg, div; + + reg = __raw_readl(MXC_CCM_CBCDR); + div = ((reg & MXC_CCM_CBCDR_NFC_PODF_MASK) >> + MXC_CCM_CBCDR_NFC_PODF_OFFSET) + 1; + clk->rate = clk->parent->rate / div; +} + +static unsigned long _clk_nfc_round_rate(struct clk *clk, + unsigned long rate) +{ + u32 div; + + /* + * Compute the divider we'd have to use to reach the target rate. + */ + + div = clk->parent->rate / rate; + + /* + * If there's a remainder after the division, then we have to increment + * the divider. There are two reasons for this: + * + * 1) The frequency we round to must be LESS THAN OR EQUAL to the + * target. We aren't allowed to round to a frequency that is higher + * than the target. + * + * 2) This also catches the case where target rate is less than the + * parent rate, which implies a divider of zero. We can't allow a + * divider of zero. + */ + + if (clk->parent->rate % rate) + div++; + + /* + * The divider for this clock is 3 bits wide, so we can't possibly + * divide the parent by more than eight. + */ + + if (div > 8) + return -EINVAL; + + return clk->parent->rate / div; + +} + +static int _clk_nfc_set_rate(struct clk *clk, unsigned long rate) +{ + u32 reg, div; + struct timespec nstimeofday; + struct timespec curtime; + + div = clk->parent->rate / rate; + if (div == 0) + div++; + if (((clk->parent->rate / div) != rate) || (div > 8)) + return -EINVAL; + + if (emi_fast_clk.usecount == 0) + emi_fast_clk.enable(&emi_fast_clk); + if (emi_slow_clk.usecount == 0) + emi_slow_clk.enable(&emi_slow_clk); + + + reg = __raw_readl(MXC_CCM_CBCDR); + reg &= ~MXC_CCM_CBCDR_NFC_PODF_MASK; + reg |= (div - 1) << MXC_CCM_CBCDR_NFC_PODF_OFFSET; + __raw_writel(reg, MXC_CCM_CBCDR); + getnstimeofday(&nstimeofday); + while (__raw_readl(MXC_CCM_CDHIPR) & + MXC_CCM_CDHIPR_NFC_IPG_INT_MEM_PODF_BUSY){ + getnstimeofday(&curtime); + if ((curtime.tv_nsec - nstimeofday.tv_nsec) > SPIN_DELAY) + panic("_clk_nfc_set_rate failed\n"); + } + clk->rate = rate; + if (emi_fast_clk.usecount == 0) + emi_fast_clk.disable(&emi_fast_clk); + if (emi_slow_clk.usecount == 0) + emi_slow_clk.disable(&emi_slow_clk); + + return 0; +} + +static struct clk emi_enfc_clk = { + .name = "nfc_clk", + .parent = &emi_slow_clk, + .enable = _clk_enable, + .enable_reg = MXC_CCM_CCGR5, + .enable_shift = MXC_CCM_CCGR5_CG10_OFFSET, + .disable = _clk_disable_inwait, + .recalc = _clk_nfc_recalc, + .round_rate = _clk_nfc_round_rate, + .set_rate = _clk_nfc_set_rate, +}; + +static int _clk_spdif_xtal_set_parent(struct clk *clk, struct clk *parent) +{ + u32 reg, mux; + + mux = _get_mux(parent, &osc_clk, &ckih_clk, &ckih2_clk, NULL); + reg = __raw_readl(MXC_CCM_CSCMR1) & ~MXC_CCM_CSCMR1_SPDIF_CLK_SEL_MASK; + reg |= mux << MXC_CCM_CSCMR1_SPDIF_CLK_SEL_OFFSET; + __raw_writel(reg, MXC_CCM_CSCMR1); + + return 0; +} + +static struct clk spdif_xtal_clk = { + .name = "spdif_xtal_clk", + .parent = &osc_clk, + .set_parent = _clk_spdif_xtal_set_parent, + .enable = _clk_enable, + .enable_reg = MXC_CCM_CCGR5, + .enable_shift = MXC_CCM_CCGR5_CG15_OFFSET, + .disable = _clk_disable, +}; + +static int _clk_spdif0_set_parent(struct clk *clk, struct clk *parent) +{ + u32 reg, mux; + + reg = __raw_readl(MXC_CCM_CSCMR2); + reg |= MXC_CCM_CSCMR2_SPDIF0_COM; + if (parent != &ssi1_clk[0]) { + reg &= ~MXC_CCM_CSCMR2_SPDIF0_COM; + mux = _get_mux(parent, &pll1_sw_clk, &pll2_sw_clk, &pll3_sw_clk, + &spdif_xtal_clk); + reg = (reg & ~MXC_CCM_CSCMR2_SPDIF0_CLK_SEL_MASK) | + (mux << MXC_CCM_CSCMR2_SPDIF0_CLK_SEL_OFFSET); + } + __raw_writel(reg, MXC_CCM_CSCMR2); + + return 0; +} + +static void _clk_spdif0_recalc(struct clk *clk) +{ + u32 reg, pred, podf; + + if (clk->parent == &ssi1_clk[0]) { + clk->rate = clk->parent->rate; + } else { + reg = __raw_readl(MXC_CCM_CDCDR); + pred = ((reg & MXC_CCM_CDCDR_SPDIF0_CLK_PRED_MASK) >> + MXC_CCM_CDCDR_SPDIF0_CLK_PRED_OFFSET) + 1; + podf = ((reg & MXC_CCM_CDCDR_SPDIF0_CLK_PODF_MASK) >> + MXC_CCM_CDCDR_SPDIF0_CLK_PODF_OFFSET) + 1; + clk->rate = clk->parent->rate / (pred * podf); + } +} + +static struct clk spdif0_clk[] = { + { + .name = "spdif_clk", + .id = 0, + .parent = &pll3_sw_clk, + .set_parent = _clk_spdif0_set_parent, + .recalc = _clk_spdif0_recalc, + .enable = _clk_enable, + .enable_reg = MXC_CCM_CCGR5, + .enable_shift = MXC_CCM_CCGR5_CG13_OFFSET, + .disable = _clk_disable, + .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE, + }, + { + .name = "spdif_ipg_clk", + .id = 0, + .parent = &ipg_clk, + .secondary = &spba_clk, + .enable = _clk_enable, + .enable_reg = MXC_CCM_CCGR5, + .enable_shift = MXC_CCM_CCGR5_CG15_OFFSET, + .disable = _clk_disable, + }, +}; + +static int _clk_spdif1_set_parent(struct clk *clk, struct clk *parent) +{ + u32 reg, mux; + + reg = __raw_readl(MXC_CCM_CSCMR2); + reg |= MXC_CCM_CSCMR2_SPDIF1_COM; + if (parent != &ssi2_clk[0]) { + reg &= ~MXC_CCM_CSCMR2_SPDIF1_COM; + mux = _get_mux(parent, &pll1_sw_clk, &pll2_sw_clk, &pll3_sw_clk, + &spdif_xtal_clk); + reg = (reg & ~MXC_CCM_CSCMR2_SPDIF1_CLK_SEL_MASK) | + (mux << MXC_CCM_CSCMR2_SPDIF1_CLK_SEL_OFFSET); + } + __raw_writel(reg, MXC_CCM_CSCMR2); + + return 0; +} + +static void _clk_spdif1_recalc(struct clk *clk) +{ + u32 reg, pred, podf; + + if (clk->parent == &ssi2_clk[0]) { + clk->rate = clk->parent->rate; + } else { + reg = __raw_readl(MXC_CCM_CDCDR); + pred = ((reg & MXC_CCM_CDCDR_SPDIF1_CLK_PRED_MASK) >> + MXC_CCM_CDCDR_SPDIF1_CLK_PRED_OFFSET) + 1; + podf = ((reg & MXC_CCM_CDCDR_SPDIF1_CLK_PODF_MASK) >> + MXC_CCM_CDCDR_SPDIF1_CLK_PODF_OFFSET) + 1; + clk->rate = clk->parent->rate / (pred * podf); + } +} + +static struct clk spdif1_clk[] = { + { + .name = "spdif_clk", + .id = 1, + .parent = &pll3_sw_clk, + .set_parent = _clk_spdif1_set_parent, + .recalc = _clk_spdif1_recalc, + .enable = _clk_enable, + .enable_reg = MXC_CCM_CCGR5, + .enable_shift = MXC_CCM_CCGR5_CG14_OFFSET, + .disable = _clk_disable, + .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE, + }, + { + .name = "spdif_ipg_clk", + .id = 0, + .parent = &ipg_clk, + .secondary = &spba_clk, + .enable = _clk_enable, + .enable_reg = MXC_CCM_CCGR5, + .enable_shift = MXC_CCM_CCGR5_CG15_OFFSET, + .disable = _clk_disable, + }, +}; + +static int _clk_ddr_set_parent(struct clk *clk, struct clk *parent) +{ + u32 reg, reg2, mux; + struct timespec nstimeofday; + struct timespec curtime; + + reg = __raw_readl(MXC_CCM_CBCMR); + reg2 = __raw_readl(MXC_CCM_CBCDR); + mux = _get_mux_ddr(parent, &axi_a_clk, &axi_b_clk, &emi_slow_clk, &ahb_clk, &ddr_hf_clk); + if (mux < 4) { + reg = (reg & ~MXC_CCM_CBCMR_DDR_CLK_SEL_MASK) | + (mux << MXC_CCM_CBCMR_DDR_CLK_SEL_OFFSET); + __raw_writel(reg, MXC_CCM_CBCMR); + reg2 = (reg2 & ~MXC_CCM_CBCDR_DDR_HF_SEL); + } else { + reg2 = (reg2 & ~MXC_CCM_CBCDR_DDR_HF_SEL) | + (MXC_CCM_CBCDR_DDR_HF_SEL); + } + __raw_writel(reg2, MXC_CCM_CBCDR); + getnstimeofday(&nstimeofday); + while (__raw_readl(MXC_CCM_CDHIPR) & + MXC_CCM_CDHIPR_DDR_HF_CLK_SEL_BUSY){ + getnstimeofday(&curtime); + if ((curtime.tv_nsec - nstimeofday.tv_nsec) > SPIN_DELAY) + panic("_clk_ddr_set_parent failed\n"); + } + return 0; +} + +static struct clk ddr_clk = { + .name = "ddr_clk", + .parent = &ddr_hf_clk, + .set_parent = _clk_ddr_set_parent, + .flags = RATE_PROPAGATES, +}; + +static int _clk_arm_axi_set_parent(struct clk *clk, struct clk *parent) +{ + u32 reg, mux; + reg = __raw_readl(MXC_CCM_CBCMR); + mux = _get_mux(parent, &axi_a_clk, &axi_b_clk, &emi_slow_clk, &ahb_clk); + reg = (reg & ~MXC_CCM_CBCMR_ARM_AXI_CLK_SEL_MASK) | + (mux << MXC_CCM_CBCMR_ARM_AXI_CLK_SEL_OFFSET); + __raw_writel(reg, MXC_CCM_CBCMR); + + return 0; +} + +static struct clk arm_axi_clk = { + .name = "arm_axi_clk", + .parent = &axi_a_clk, + .set_parent = _clk_arm_axi_set_parent, + .enable = _clk_enable, + .enable_reg = MXC_CCM_CCGR0, + .enable_shift = MXC_CCM_CCGR0_CG1_OFFSET, + .disable = _clk_disable, +}; + +static int _clk_vpu_set_parent(struct clk *clk, struct clk *parent) +{ + u32 reg, mux; + reg = __raw_readl(MXC_CCM_CBCMR); + mux = _get_mux(parent, &axi_a_clk, &axi_b_clk, &emi_slow_clk, &ahb_clk); + reg = (reg & ~MXC_CCM_CBCMR_VPU_AXI_CLK_SEL_MASK) | + (mux << MXC_CCM_CBCMR_VPU_AXI_CLK_SEL_OFFSET); + __raw_writel(reg, MXC_CCM_CBCMR); + + return 0; +} + +static int _clk_vpu_enable(struct clk *clk) +{ + /* Set VPU's parent to be axi_a or ahb when its enabled. */ + if (cpu_is_mx51_rev(CHIP_REV_2_0) < 0) { + clk_set_parent(&vpu_clk[0], &ahb_clk); + clk_set_parent(&vpu_clk[1], &ahb_clk); + } else { + clk_set_parent(&vpu_clk[0], &axi_a_clk); + clk_set_parent(&vpu_clk[1], &axi_a_clk); + } + + _clk_enable(clk); + return 0; + +} + +static void _clk_vpu_disable(struct clk *clk) +{ + _clk_disable(clk); + + /* Set VPU's parent to be axi_b when its disabled. */ + clk_set_parent(&vpu_clk[0], &axi_b_clk); + clk_set_parent(&vpu_clk[1], &axi_b_clk); +} + +static struct clk vpu_clk[] = { + { + .name = "vpu_clk", + .set_parent = _clk_vpu_set_parent, + .enable = _clk_enable, + .enable_reg = MXC_CCM_CCGR5, + .enable_shift = MXC_CCM_CCGR5_CG4_OFFSET, + .disable = _clk_disable, + .secondary = &vpu_clk[1], + .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE, + }, + { + .name = "vpu_core_clk", + .set_parent = _clk_vpu_set_parent, + .enable = _clk_vpu_enable, + .enable_reg = MXC_CCM_CCGR5, + .enable_shift = MXC_CCM_CCGR5_CG3_OFFSET, + .disable = _clk_vpu_disable, + .secondary = &vpu_clk[2], + }, + { + .name = "vpu_emi_clk", + .parent = &emi_fast_clk, +#ifdef CONFIG_MXC_VPU_IRAM + .secondary = &emi_intr_clk, +#endif + } +}; + +static int _clk_lpsr_set_parent(struct clk *clk, struct clk *parent) +{ + u32 reg, mux; + reg = __raw_readl(MXC_CCM_CLPCR); + mux = _get_mux(parent, &ckil_clk, &fpm_clk, &fpm_div2_clk, NULL); + reg = (reg & ~MXC_CCM_CLPCR_LPSR_CLK_SEL_MASK) | + (mux << MXC_CCM_CLPCR_LPSR_CLK_SEL_OFFSET); + __raw_writel(reg, MXC_CCM_CLPCR); + + return 0; +} + +static struct clk lpsr_clk = { + .name = "lpsr_clk", + .parent = &ckil_clk, + .set_parent = _clk_lpsr_set_parent, +}; + +static void _clk_pgc_recalc(struct clk *clk) +{ + u32 reg, div; + + reg = __raw_readl(MXC_CCM_CSCDR1); + div = (reg & MXC_CCM_CSCDR1_PGC_CLK_PODF_MASK) >> + MXC_CCM_CSCDR1_PGC_CLK_PODF_OFFSET; + div = 1 >> div; + clk->rate = clk->parent->rate / div; +} + +static struct clk pgc_clk = { + .name = "pgc_clk", + .parent = &ipg_clk, + .recalc = _clk_pgc_recalc, +}; + +/*usb OTG clock */ + +static struct clk usb_clk = { + .name = "usb_clk", + .rate = 60000000, +}; + +static struct clk usb_utmi_clk = { + .name = "usb_utmi_clk", + .enable = _clk_enable, + .enable_reg = MXC_CCM_CSCMR1, + .enable_shift = MXC_CCM_CSCMR1_USB_PHY_CLK_SEL_OFFSET, + .disable = _clk_disable, +}; + +static struct clk rtc_clk = { + .name = "rtc_clk", + .parent = &ckil_clk, + .secondary = &ipg_clk, + .enable = _clk_enable, + .enable_reg = MXC_CCM_CCGR4, + .enable_shift = MXC_CCM_CCGR4_CG14_OFFSET, + .disable = _clk_disable, +}; + +static struct clk ata_clk = { + .name = "ata_clk", + .parent = &ipg_clk, + .secondary = &spba_clk, + .enable = _clk_enable, + .enable_reg = MXC_CCM_CCGR4, + .enable_shift = MXC_CCM_CCGR4_CG0_OFFSET, + .disable = _clk_disable, + .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE, +}; + +static struct clk owire_clk = { + .name = "owire_clk", + .parent = &ipg_perclk, + .enable = _clk_enable, + .enable_reg = MXC_CCM_CCGR2, + .enable_shift = MXC_CCM_CCGR2_CG11_OFFSET, + .disable = _clk_disable, +}; + + +static struct clk fec_clk[] = { + { + .name = "fec_clk", + .parent = &ipg_clk, + .secondary = &fec_clk[1], + .enable = _clk_enable, + .enable_reg = MXC_CCM_CCGR2, + .enable_shift = MXC_CCM_CCGR2_CG12_OFFSET, + .disable = _clk_disable, + .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE, + }, + { + .name = "fec_sec1_clk", + .parent = &tmax2_clk, + .secondary = &fec_clk[2], + }, + { + .name = "fec_sec2_clk", + .parent = &aips_tz2_clk, + .secondary = &emi_fast_clk, + }, +}; + +static struct clk sahara_clk[] = { + { + .name = "sahara_clk", + .parent = &ahb_clk, + .secondary = &sahara_clk[1], + .enable_reg = MXC_CCM_CCGR4, + .enable_shift = MXC_CCM_CCGR4_CG7_OFFSET, + .enable = _clk_enable, + .disable = _clk_disable, + }, + { + .name = "sahara_sec_clk", + .parent = &tmax1_clk, + .secondary = &emi_fast_clk, + } +}; + +static struct clk scc_clk[] = { + { + .name = "scc_clk", + .parent = &ahb_clk, + .secondary = &scc_clk[1], + .enable_reg = MXC_CCM_CCGR1, + .enable_shift = MXC_CCM_CCGR1_CG15_OFFSET, + .enable = _clk_enable, + .disable = _clk_disable, + }, + { + .name = "scc_sec_clk", + .parent = &tmax1_clk, + .secondary = &emi_fast_clk, + } +}; + + +static int _clk_gpu3d_set_parent(struct clk *clk, struct clk *parent) +{ + u32 reg, mux; + + reg = __raw_readl(MXC_CCM_CBCMR); + mux = _get_mux(parent, &axi_a_clk, &axi_b_clk, &emi_slow_clk, &ahb_clk); + reg = (reg & ~MXC_CCM_CBCMR_GPU_CLK_SEL_MASK) | + (mux << MXC_CCM_CBCMR_GPU_CLK_SEL_OFFSET); + __raw_writel(reg, MXC_CCM_CBCMR); + + return 0; +} + +static int _clk_gpu3d_enable(struct clk *clk) +{ + /* Set gPU's parent to be axi_a or ahb when its enabled. */ + clk_set_parent(&gpu3d_clk, &axi_a_clk); + _clk_enable(clk); + return 0; +} + +static void _clk_gpu3d_disable(struct clk *clk) +{ + _clk_disable(clk); + + /* Set GPU's parent to be axi_b when its disabled. */ + clk_set_parent(&gpu3d_clk, &axi_b_clk); +} + + +static struct clk gpu3d_clk = { + .name = "gpu3d_clk", + .parent = &axi_a_clk, + .set_parent = _clk_gpu3d_set_parent, + .enable = _clk_gpu3d_enable, + .enable_reg = MXC_CCM_CCGR5, + .enable_shift = MXC_CCM_CCGR5_CG1_OFFSET, + .disable = _clk_gpu3d_disable, + .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE, +}; + +static struct clk garb_clk = { + .name = "garb_clk", + .parent = &axi_a_clk, + .enable = _clk_enable, + .enable_reg = MXC_CCM_CCGR5, + .enable_shift = MXC_CCM_CCGR5_CG2_OFFSET, + .disable = _clk_disable, +}; + +static struct clk emi_garb_clk = { + .name = "emi_garb_clk", + .parent = &axi_a_clk, + .enable = _clk_enable, + .enable_reg = MXC_CCM_CCGR6, + .enable_shift = MXC_CCM_CCGR6_CG4_OFFSET, + .disable = _clk_disable, +}; + +static int _clk_gpu2d_set_parent(struct clk *clk, struct clk *parent) +{ + u32 reg, mux; + + reg = __raw_readl(MXC_CCM_CBCMR); + mux = _get_mux(parent, &axi_a_clk, &axi_b_clk, &emi_slow_clk, &ahb_clk); + reg = (reg & ~MXC_CCM_CBCMR_GPU2D_CLK_SEL_MASK) | + (mux << MXC_CCM_CBCMR_GPU2D_CLK_SEL_OFFSET); + __raw_writel(reg, MXC_CCM_CBCMR); + + return 0; +} + +static int _clk_gpu2d_enable(struct clk *clk) +{ + /* Set GPU2D's parent to be axi_a or ahb when its enabled. */ + clk_set_parent(&gpu2d_clk, &axi_a_clk); + _clk_enable(clk); + return 0; +} + +static void _clk_gpu2d_disable(struct clk *clk) +{ + _clk_disable(clk); + + /* Set GPU2d's parent to be axi_b when its disabled. */ + clk_set_parent(&gpu2d_clk, &axi_b_clk); +} + +static struct clk gpu2d_clk = { + .name = "gpu2d_clk", + .parent = &axi_a_clk, + .set_parent = _clk_gpu2d_set_parent, + .enable = _clk_gpu2d_enable, + .enable_reg = MXC_CCM_CCGR6, + .enable_shift = MXC_CCM_CCGR6_CG7_OFFSET, + .disable = _clk_gpu2d_disable, + .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE, +}; + +static struct clk *mxc_clks[] = { + &osc_clk, + &ckih_clk, + &ckih2_clk, + &ckil_clk, + &fpm_clk, + &fpm_div2_clk, + &pll1_main_clk, + &pll1_sw_clk, + &pll2_sw_clk, + &pll3_sw_clk, + &gpc_dvfs_clk, + &lp_apm_clk, + &cpu_clk, + &periph_apm_clk, + &main_bus_clk, + &axi_a_clk, + &axi_b_clk, + &ahb_clk, + &ahb_max_clk, + &ipg_clk, + &ipg_perclk, + &ahbmux1_clk, + &ahbmux2_clk, + &aips_tz1_clk, + &aips_tz2_clk, + &sdma_clk[0], + &sdma_clk[1], + &ipu_clk[0], + &ipu_clk[1], + &ipu_di_clk[0], + &ipu_di_clk[1], + &tve_clk, + &csi0_clk, + &csi1_clk, + &uart_main_clk, + &uart1_clk[0], + &uart1_clk[1], + &uart2_clk[0], + &uart2_clk[1], + &uart3_clk[0], + &uart3_clk[1], + &spba_clk, + &i2c_clk[0], + &i2c_clk[1], + &hsi2c_clk, + &hsi2c_serial_clk, + &gpt_clk[0], + &gpt_clk[1], + &gpt_clk[2], + &pwm1_clk[0], + &pwm1_clk[1], + &pwm1_clk[2], + &pwm2_clk[0], + &pwm2_clk[1], + &pwm2_clk[2], + &cspi_main_clk, + &cspi1_clk[0], + &cspi1_clk[1], + &cspi2_clk[0], + &cspi2_clk[1], + &cspi3_clk[0], + &cspi3_clk[1], + &ssi_lp_apm_clk, + &ssi1_clk[0], + &ssi1_clk[1], + &ssi1_clk[2], + &ssi2_clk[0], + &ssi2_clk[1], + &ssi2_clk[2], + &ssi_ext1_clk, + &ssi_ext2_clk, + &iim_clk, + &tmax1_clk, + &tmax2_clk, + &tmax3_clk, + &usboh3_clk[0], + &usboh3_clk[1], + &usb_ahb_clk, + &usb_phy_clk, + &usb_utmi_clk, + &usb_clk, + &esdhc1_clk[0], + &esdhc1_clk[1], + &esdhc2_clk[0], + &esdhc2_clk[1], + &esdhc3_clk[0], + &esdhc3_clk[1], + &esdhc4_clk[0], + &esdhc4_clk[1], + &esdhc_dep_clks, + &sim_clk[0], + &sim_clk[1], + &emi_slow_clk, + &ddr_clk, + &emi_enfc_clk, + &emi_fast_clk, + &emi_intr_clk, + &spdif_xtal_clk, + &spdif0_clk[0], + &spdif0_clk[1], + &spdif1_clk[0], + &spdif1_clk[1], + &arm_axi_clk, + &vpu_clk[0], + &vpu_clk[1], + &vpu_clk[2], + &lpsr_clk, + &pgc_clk, + &rtc_clk, + &ata_clk, + &owire_clk, + &fec_clk[0], + &fec_clk[1], + &fec_clk[2], + &mipi_hsc1_clk, + &mipi_hsc2_clk, + &mipi_esc_clk, + &mipi_hsp_clk, + &sahara_clk[0], + &sahara_clk[1], + &gpu3d_clk, + &garb_clk, + &emi_garb_clk, + &ddr_hf_clk, + &gpu2d_clk, + &scc_clk[0], +}; + +static void clk_tree_init(void) +{ + u32 reg, reg2, dp_ctl; + + ipg_perclk.set_parent(&ipg_perclk, &lp_apm_clk); + + /* + *Initialise the IPG PER CLK dividers to 3. IPG_PER_CLK should be at + * 8MHz, its derived from lp_apm. + */ + reg = __raw_readl(MXC_CCM_CBCDR); + reg &= ~MXC_CCM_CBCDR_PERCLK_PRED1_MASK; + reg &= ~MXC_CCM_CBCDR_PERCLK_PRED2_MASK; + reg &= ~MXC_CCM_CBCDR_PERCLK_PODF_MASK; + reg |= (2 << MXC_CCM_CBCDR_PERCLK_PRED1_OFFSET); + __raw_writel(reg, MXC_CCM_CBCDR); + + /* set pll1_main_clk parent */ + pll1_main_clk.parent = &osc_clk; + dp_ctl = __raw_readl(pll_base[0] + MXC_PLL_DP_CTL); + if ((dp_ctl & MXC_PLL_DP_CTL_REF_CLK_SEL_MASK) == 0) + pll1_main_clk.parent = &fpm_clk; + /* set pll2_sw_clk parent */ + pll2_sw_clk.parent = &osc_clk; + dp_ctl = __raw_readl(pll_base[1] + MXC_PLL_DP_CTL); + if ((dp_ctl & MXC_PLL_DP_CTL_REF_CLK_SEL_MASK) == 0) + pll2_sw_clk.parent = &fpm_clk; + /* set pll3_clk parent */ + pll3_sw_clk.parent = &osc_clk; + dp_ctl = __raw_readl(pll_base[2] + MXC_PLL_DP_CTL); + if ((dp_ctl & MXC_PLL_DP_CTL_REF_CLK_SEL_MASK) == 0) + pll3_sw_clk.parent = &fpm_clk; + + /* set emi_slow_clk parent */ + emi_slow_clk.parent = &main_bus_clk; + reg = __raw_readl(MXC_CCM_CBCDR); + if ((reg & MXC_CCM_CBCDR_EMI_CLK_SEL) != 0) + emi_slow_clk.parent = &ahb_clk; + + /* set ipg_perclk parent */ + ipg_perclk.parent = &lp_apm_clk; + reg = __raw_readl(MXC_CCM_CBCMR); + if ((reg & MXC_CCM_CBCMR_PERCLK_IPG_CLK_SEL) != 0) { + ipg_perclk.parent = &ipg_clk; + } else { + if ((reg & MXC_CCM_CBCMR_PERCLK_LP_APM_CLK_SEL) == 0) + ipg_perclk.parent = &main_bus_clk; + } + + /* set DDR clock parent */ + reg = __raw_readl(MXC_CCM_CBCMR) & MXC_CCM_CBCMR_DDR_CLK_SEL_MASK; + reg >>= MXC_CCM_CBCMR_DDR_CLK_SEL_OFFSET; + reg2 = __raw_readl(MXC_CCM_CBCDR) & MXC_CCM_CBCDR_DDR_HF_SEL; + reg2 >>= MXC_CCM_CBCDR_DDR_HF_SEL_OFFSET; + + if (reg2) { + ddr_clk.parent = &ddr_hf_clk; + } else { + if (reg == 0) { + ddr_clk.parent = &axi_a_clk; + } else if (reg == 1) { + ddr_clk.parent = &axi_b_clk; + } else if (reg == 2) { + ddr_clk.parent = &emi_slow_clk; + } else { + ddr_clk.parent = &ahb_clk; + } + } +} + +int __init mxc_clocks_init(unsigned long ckil, unsigned long osc, unsigned long ckih1, unsigned long ckih2) +{ + struct clk **clkp; + int i = 0, j = 0, reg; + int wp_cnt = 0; + + /* Turn off all possible clocks */ + if (mxc_jtag_enabled) { + __raw_writel(1 << MXC_CCM_CCGR0_CG0_OFFSET | + 1 << MXC_CCM_CCGR0_CG1_OFFSET | + 1 << MXC_CCM_CCGR0_CG2_OFFSET | + 1 << MXC_CCM_CCGR0_CG3_OFFSET | + 3 << MXC_CCM_CCGR0_CG4_OFFSET | + 1 << MXC_CCM_CCGR0_CG8_OFFSET | + 1 << MXC_CCM_CCGR0_CG9_OFFSET | + 1 << MXC_CCM_CCGR0_CG12_OFFSET | + 1 << MXC_CCM_CCGR0_CG13_OFFSET | + 1 << MXC_CCM_CCGR0_CG14_OFFSET, MXC_CCM_CCGR0); + } else { + __raw_writel(1 << MXC_CCM_CCGR0_CG0_OFFSET | + 1 << MXC_CCM_CCGR0_CG1_OFFSET | + 1 << MXC_CCM_CCGR0_CG2_OFFSET | + 1 << MXC_CCM_CCGR0_CG3_OFFSET | + 1 << MXC_CCM_CCGR0_CG8_OFFSET | + 1 << MXC_CCM_CCGR0_CG9_OFFSET | + 1 << MXC_CCM_CCGR0_CG12_OFFSET | + 1 << MXC_CCM_CCGR0_CG13_OFFSET | + 1 << MXC_CCM_CCGR0_CG14_OFFSET, MXC_CCM_CCGR0); + } + __raw_writel(0, MXC_CCM_CCGR1); + __raw_writel(0, MXC_CCM_CCGR2); + __raw_writel(0, MXC_CCM_CCGR3); + __raw_writel(1 << MXC_CCM_CCGR4_CG8_OFFSET, MXC_CCM_CCGR4); + + __raw_writel(1 << MXC_CCM_CCGR5_CG2_OFFSET | + 3 << MXC_CCM_CCGR5_CG6_OFFSET | + 3 << MXC_CCM_CCGR5_CG7_OFFSET | + 1 << MXC_CCM_CCGR5_CG8_OFFSET | + 3 << MXC_CCM_CCGR5_CG9_OFFSET | + 1 << MXC_CCM_CCGR5_CG10_OFFSET | + 3 << MXC_CCM_CCGR5_CG11_OFFSET, MXC_CCM_CCGR5); + + __raw_writel(1 << MXC_CCM_CCGR6_CG4_OFFSET, MXC_CCM_CCGR6); + + ckil_clk.rate = ckil; + osc_clk.rate = osc; + ckih_clk.rate = ckih1; + ckih2_clk.rate = ckih2; + + clk_tree_init(); + + for (clkp = mxc_clks; clkp < mxc_clks + ARRAY_SIZE(mxc_clks); clkp++) + clk_register(*clkp); + + /*Setup the LPM bypass bits */ + reg = __raw_readl(MXC_CCM_CLPCR); + reg |= MXC_CCM_CLPCR_BYPASS_HSC_LPM_HS + | MXC_CCM_CLPCR_BYPASS_IPU_LPM_HS + | MXC_CCM_CLPCR_BYPASS_RTIC_LPM_HS + | MXC_CCM_CLPCR_BYPASS_SCC_LPM_HS + | MXC_CCM_CLPCR_BYPASS_SDMA_LPM_HS; + __raw_writel(reg, MXC_CCM_CLPCR); + + /* Disable the handshake with HSC block as its not + * initialised right now. + */ + reg = __raw_readl(MXC_CCM_CCDR); + reg |= MXC_CCM_CCDR_HSC_HS_MASK; + __raw_writel(reg, MXC_CCM_CCDR); + + /* This will propagate to all children and init all the clock rates */ + propagate_rate(&osc_clk); + propagate_rate(&ckih_clk); + propagate_rate(&ckih2_clk); + propagate_rate(&ckil_clk); + propagate_rate(&pll1_sw_clk); + propagate_rate(&pll2_sw_clk); + + clk_enable(&cpu_clk); + clk_enable(&main_bus_clk); + + reg = __raw_readl(MXC_CCM_CBCDR) & MXC_CCM_CBCDR_DDR_HF_SEL; + reg >>= MXC_CCM_CBCDR_DDR_HF_SEL_OFFSET; + + if (reg) + clk_set_parent(&ddr_clk, &ddr_hf_clk); + else + clk_set_parent(&ddr_clk, &axi_a_clk); + + /* Initialise the parents to be axi_b, parents are set to + * axi_a when the clocks are enabled. + */ + clk_set_parent(&vpu_clk[0], &axi_b_clk); + clk_set_parent(&vpu_clk[1], &axi_b_clk); + clk_set_parent(&gpu3d_clk, &axi_b_clk); + clk_set_parent(&gpu2d_clk, &axi_b_clk); + + /* move cspi to 24MHz */ + clk_set_parent(&cspi_main_clk, &lp_apm_clk); + clk_set_rate(&cspi_main_clk, 12000000); + /*move the spdif0 to spdif_xtal_ckl */ + clk_set_parent(&spdif0_clk[0], &spdif_xtal_clk); + /*set the SPDIF dividers to 1 */ + reg = __raw_readl(MXC_CCM_CDCDR); + reg &= ~MXC_CCM_CDCDR_SPDIF0_CLK_PODF_MASK; + reg &= ~MXC_CCM_CDCDR_SPDIF0_CLK_PRED_MASK; + __raw_writel(reg, MXC_CCM_CDCDR); + + /* move the spdif1 to 24MHz */ + clk_set_parent(&spdif1_clk[0], &spdif_xtal_clk); + /* set the spdif1 dividers to 1 */ + reg = __raw_readl(MXC_CCM_CDCDR); + reg &= ~MXC_CCM_CDCDR_SPDIF1_CLK_PODF_MASK; + reg &= ~MXC_CCM_CDCDR_SPDIF1_CLK_PRED_MASK; + __raw_writel(reg, MXC_CCM_CDCDR); + + /* Move SSI clocks to SSI_LP_APM clock */ + clk_set_parent(&ssi_lp_apm_clk, &lp_apm_clk); + + clk_set_parent(&ssi1_clk[0], &ssi_lp_apm_clk); + /* set the SSI dividers to divide by 2 */ + reg = __raw_readl(MXC_CCM_CS1CDR); + reg &= ~MXC_CCM_CS1CDR_SSI1_CLK_PODF_MASK; + reg &= ~MXC_CCM_CS1CDR_SSI1_CLK_PRED_MASK; + reg |= 1 << MXC_CCM_CS1CDR_SSI1_CLK_PRED_OFFSET; + __raw_writel(reg, MXC_CCM_CS1CDR); + + clk_set_parent(&ssi2_clk[0], &ssi_lp_apm_clk); + reg = __raw_readl(MXC_CCM_CS2CDR); + reg &= ~MXC_CCM_CS2CDR_SSI2_CLK_PODF_MASK; + reg &= ~MXC_CCM_CS2CDR_SSI2_CLK_PRED_MASK; + reg |= 1 << MXC_CCM_CS2CDR_SSI2_CLK_PRED_OFFSET; + __raw_writel(reg, MXC_CCM_CS2CDR); + + /* Change the SSI_EXT1_CLK to be sourced from SSI1_CLK_ROOT */ + clk_set_parent(&ssi_ext1_clk, &ssi1_clk[0]); + clk_set_parent(&ssi_ext2_clk, &ssi2_clk[0]); + + /* move usb_phy_clk to 24MHz */ + clk_set_parent(&usb_phy_clk, &osc_clk); + + /* set usboh3_clk to pll2 */ + clk_set_parent(&usboh3_clk[0], &pll2_sw_clk); + reg = __raw_readl(MXC_CCM_CSCDR1); + reg &= ~MXC_CCM_CSCDR1_USBOH3_CLK_PODF_MASK; + reg &= ~MXC_CCM_CSCDR1_USBOH3_CLK_PRED_MASK; + reg |= 4 << MXC_CCM_CSCDR1_USBOH3_CLK_PRED_OFFSET; + reg |= 1 << MXC_CCM_CSCDR1_USBOH3_CLK_PODF_OFFSET; + __raw_writel(reg, MXC_CCM_CSCDR1); + + /* Set the current working point. */ + cpu_wp_tbl = get_cpu_wp(&cpu_wp_nr); + /* Update the cpu working point table based on the PLL1 freq + * at boot time + */ + if (pll1_main_clk.rate <= cpu_wp_tbl[cpu_wp_nr - 1].cpu_rate) + wp_cnt = 1; + else if (pll1_main_clk.rate <= cpu_wp_tbl[1].cpu_rate && + pll1_main_clk.rate > cpu_wp_tbl[2].cpu_rate) + wp_cnt = cpu_wp_nr - 1; + else + wp_cnt = cpu_wp_nr; + + cpu_wp_tbl[0].cpu_rate = pll1_main_clk.rate; + + if (wp_cnt == 1) { + cpu_wp_tbl[0] = cpu_wp_tbl[cpu_wp_nr - 1]; + memset(&cpu_wp_tbl[cpu_wp_nr - 1], 0, sizeof(struct cpu_wp)); + memset(&cpu_wp_tbl[cpu_wp_nr - 2], 0, sizeof(struct cpu_wp)); + } else if (wp_cnt < cpu_wp_nr) { + for (i = 0; i < wp_cnt; i++) + cpu_wp_tbl[i] = cpu_wp_tbl[i+1]; + memset(&cpu_wp_tbl[i], 0, sizeof(struct cpu_wp)); + } + + if (wp_cnt < cpu_wp_nr) { + set_num_cpu_wp(wp_cnt); + cpu_wp_tbl = get_cpu_wp(&cpu_wp_nr); + } + + + for (j = 0; j < cpu_wp_nr; j++) { + if ((ddr_clk.parent == &ddr_hf_clk)) { + /* Change the CPU podf divider based on the boot up + * pll1 rate. + */ + cpu_wp_tbl[j].cpu_podf = + (pll1_main_clk.rate / cpu_wp_tbl[j].cpu_rate) + - 1; + if (pll1_main_clk.rate/(cpu_wp_tbl[j].cpu_podf + 1) > + cpu_wp_tbl[j].cpu_rate) { + cpu_wp_tbl[j].cpu_podf++; + cpu_wp_tbl[j].cpu_rate = + pll1_main_clk.rate/ + (1000 * (cpu_wp_tbl[j].cpu_podf + 1)); + cpu_wp_tbl[j].cpu_rate *= 1000; + } + if (pll1_main_clk.rate/(cpu_wp_tbl[j].cpu_podf + 1) < + cpu_wp_tbl[j].cpu_rate) { + cpu_wp_tbl[j].cpu_rate = pll1_main_clk.rate; + } + } + cpu_wp_tbl[j].pll_rate = pll1_main_clk.rate; + } + /* Set the current working point. */ + for (i = 0; i < cpu_wp_nr; i++) { + if (clk_get_rate(&cpu_clk) == cpu_wp_tbl[i].cpu_rate) { + cpu_curr_wp = i; + break; + } + } + if (i > cpu_wp_nr) + BUG(); + + propagate_rate(&osc_clk); + propagate_rate(&pll1_sw_clk); + propagate_rate(&pll2_sw_clk); + + /*Allow for automatic gating of the EMI internal clock. + * If this is done, emi_intr CCGR bits should be set to 11. + */ + reg = __raw_readl((IO_ADDRESS(M4IF_BASE_ADDR) + 0x8c)); + reg &= ~0x1; + __raw_writel(reg, (IO_ADDRESS(M4IF_BASE_ADDR) + 0x8c)); + + clk_set_parent(&arm_axi_clk, &axi_a_clk); + clk_set_parent(&ipu_clk[0], &axi_b_clk); + clk_set_parent(&uart_main_clk, &pll2_sw_clk); + + clk_set_parent(&emi_slow_clk, &ahb_clk); + clk_set_rate(&emi_slow_clk, clk_round_rate(&emi_slow_clk, 130000000)); + + /* Change the NFC clock rate to be 1:4 ratio with emi clock. */ + clk_set_rate(&emi_enfc_clk, clk_round_rate(&emi_enfc_clk, + (clk_get_rate(&emi_slow_clk))/4)); + return 0; +} + +/*! + * Setup cpu clock based on working point. + * @param wp cpu freq working point + * @return 0 on success or error code on failure. + */ +static int cpu_clk_set_wp(int wp) +{ + struct cpu_wp *p; + u32 reg; + u32 stat; + + if (wp == cpu_curr_wp) + return 0; + + p = &cpu_wp_tbl[wp]; + + /* + * If DDR clock is sourced from PLL1, we cannot drop PLL1 freq. + * Use the ARM_PODF to change the freq of the core, leave the PLL1 + * freq unchanged. + */ + if (ddr_clk.parent == &ddr_hf_clk) { + reg = __raw_readl(MXC_CCM_CACRR); + reg &= ~MXC_CCM_CACRR_ARM_PODF_MASK; + reg |= cpu_wp_tbl[wp].cpu_podf << MXC_CCM_CACRR_ARM_PODF_OFFSET; + __raw_writel(reg, MXC_CCM_CACRR); + cpu_curr_wp = wp; + cpu_clk.rate = cpu_wp_tbl[wp].cpu_rate; + } else { + struct timespec nstimeofday; + struct timespec curtime; + + /* Change the ARM clock to requested frequency */ + /* First move the ARM clock to step clock which is running + * at 24MHz. + */ + + /* Change the source of pll1_sw_clk to be the step_clk */ + reg = __raw_readl(MXC_CCM_CCSR); + reg |= MXC_CCM_CCSR_PLL1_SW_CLK_SEL; + __raw_writel(reg, MXC_CCM_CCSR); + + /* Stop the PLL */ + reg = __raw_readl(MXC_DPLL1_BASE + MXC_PLL_DP_CTL); + reg &= ~MXC_PLL_DP_CTL_UPEN; + __raw_writel(reg, MXC_DPLL1_BASE + MXC_PLL_DP_CTL); + + /* PDF and MFI */ + reg = p->pdf | p->mfi << MXC_PLL_DP_OP_MFI_OFFSET; + __raw_writel(reg, MXC_DPLL1_BASE + MXC_PLL_DP_OP); + + /* MFD */ + __raw_writel(p->mfd, MXC_DPLL1_BASE + MXC_PLL_DP_MFD); + + /* MFI */ + __raw_writel(p->mfn, MXC_DPLL1_BASE + MXC_PLL_DP_MFN); + + reg = __raw_readl(MXC_DPLL1_BASE + MXC_PLL_DP_CTL); + reg |= MXC_PLL_DP_CTL_UPEN; + /* Set the UPEN bits */ + __raw_writel(reg, MXC_DPLL1_BASE + MXC_PLL_DP_CTL); + /* Forcefully restart the PLL */ + reg |= MXC_PLL_DP_CTL_RST; + __raw_writel(reg, MXC_DPLL1_BASE + MXC_PLL_DP_CTL); + + /* Wait for the PLL to lock */ + getnstimeofday(&nstimeofday); + do { + getnstimeofday(&curtime); + if ((curtime.tv_nsec - nstimeofday.tv_nsec) > SPIN_DELAY) + panic("pll1 relock failed\n"); + stat = __raw_readl(MXC_DPLL1_BASE + MXC_PLL_DP_CTL) & + MXC_PLL_DP_CTL_LRF; + } while (!stat); + + reg = __raw_readl(MXC_CCM_CCSR); + /* Move the PLL1 back to the pll1_main_clk */ + reg &= ~MXC_CCM_CCSR_PLL1_SW_CLK_SEL; + __raw_writel(reg, MXC_CCM_CCSR); + + cpu_curr_wp = wp; + + pll1_sw_clk.rate = cpu_wp_tbl[wp].cpu_rate; + pll1_main_clk.rate = pll1_sw_clk.rate; + cpu_clk.rate = pll1_sw_clk.rate; + } + +#if defined(CONFIG_CPU_FREQ) + cpufreq_trig_needed = 1; +#endif + return 0; +} + diff --git a/arch/arm/mach-mx51/cpu.c b/arch/arm/mach-mx51/cpu.c new file mode 100644 index 000000000000..00a4bb8bbfe7 --- /dev/null +++ b/arch/arm/mach-mx51/cpu.c @@ -0,0 +1,65 @@ +/* + * Copyright 2008-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-mx51/cpu.c + * + * @brief This file contains the CPU initialization code. + * + * @ingroup MSL_MX51 + */ + +#include <linux/types.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <mach/hardware.h> +#include <asm/io.h> +#include "crm_regs.h" + +/*! + * CPU initialization. It is called by fixup_mxc_board() + */ +void __init mxc_cpu_init(void) +{ + if (!system_rev) + mxc_set_system_rev(0x51, CHIP_REV_1_0); +} + +static int __init post_cpu_init(void) +{ + unsigned int base, reg; + + /* Set ALP bits to 000. Set ALP_EN bit in Arm Memory Controller reg. */ + reg = 0x8; + __raw_writel(reg, MXC_CORTEXA8_PLAT_AMC); + + base = IO_ADDRESS(AIPS1_BASE_ADDR); + __raw_writel(0x0, base + 0x40); + __raw_writel(0x0, base + 0x44); + __raw_writel(0x0, base + 0x48); + __raw_writel(0x0, base + 0x4C); + reg = __raw_readl(base + 0x50) & 0x00FFFFFF; + __raw_writel(reg, base + 0x50); + + base = IO_ADDRESS(AIPS2_BASE_ADDR); + __raw_writel(0x0, base + 0x40); + __raw_writel(0x0, base + 0x44); + __raw_writel(0x0, base + 0x48); + __raw_writel(0x0, base + 0x4C); + reg = __raw_readl(base + 0x50) & 0x00FFFFFF; + __raw_writel(reg, base + 0x50); + + return 0; +} + +postcore_initcall(post_cpu_init); diff --git a/arch/arm/mach-mx51/crm_regs.h b/arch/arm/mach-mx51/crm_regs.h new file mode 100644 index 000000000000..37689877e57e --- /dev/null +++ b/arch/arm/mach-mx51/crm_regs.h @@ -0,0 +1,690 @@ +/* + * Copyright 2008-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_MX51_CRM_REGS_H__ +#define __ARCH_ARM_MACH_MX51_CRM_REGS_H__ + +#define MXC_CCM_BASE ((char *)IO_ADDRESS(CCM_BASE_ADDR)) +#define MXC_DPLL1_BASE IO_ADDRESS(PLL1_BASE_ADDR) +#define MXC_DPLL2_BASE IO_ADDRESS(PLL2_BASE_ADDR) +#define MXC_DPLL3_BASE IO_ADDRESS(PLL3_BASE_ADDR) + +/* PLL Register Offsets */ +#define MXC_PLL_DP_CTL 0x00 +#define MXC_PLL_DP_CONFIG 0x04 +#define MXC_PLL_DP_OP 0x08 +#define MXC_PLL_DP_MFD 0x0C +#define MXC_PLL_DP_MFN 0x10 +#define MXC_PLL_DP_MFNMINUS 0x14 +#define MXC_PLL_DP_MFNPLUS 0x18 +#define MXC_PLL_DP_HFS_OP 0x1C +#define MXC_PLL_DP_HFS_MFD 0x20 +#define MXC_PLL_DP_HFS_MFN 0x24 +#define MXC_PLL_DP_MFN_TOGC 0x28 +#define MXC_PLL_DP_DESTAT 0x2c + +/* PLL Register Bit definitions */ +#define MXC_PLL_DP_CTL_MUL_CTRL 0x2000 +#define MXC_PLL_DP_CTL_DPDCK0_2_EN 0x1000 +#define MXC_PLL_DP_CTL_DPDCK0_2_OFFSET 12 +#define MXC_PLL_DP_CTL_ADE 0x800 +#define MXC_PLL_DP_CTL_REF_CLK_DIV 0x400 +#define MXC_PLL_DP_CTL_REF_CLK_SEL_MASK (3 << 8) +#define MXC_PLL_DP_CTL_REF_CLK_SEL_OFFSET 8 +#define MXC_PLL_DP_CTL_HFSM 0x80 +#define MXC_PLL_DP_CTL_PRE 0x40 +#define MXC_PLL_DP_CTL_UPEN 0x20 +#define MXC_PLL_DP_CTL_RST 0x10 +#define MXC_PLL_DP_CTL_RCP 0x8 +#define MXC_PLL_DP_CTL_PLM 0x4 +#define MXC_PLL_DP_CTL_BRM0 0x2 +#define MXC_PLL_DP_CTL_LRF 0x1 + +#define MXC_PLL_DP_CONFIG_BIST 0x8 +#define MXC_PLL_DP_CONFIG_SJC_CE 0x4 +#define MXC_PLL_DP_CONFIG_AREN 0x2 +#define MXC_PLL_DP_CONFIG_LDREQ 0x1 + +#define MXC_PLL_DP_OP_MFI_OFFSET 4 +#define MXC_PLL_DP_OP_MFI_MASK (0xF << 4) +#define MXC_PLL_DP_OP_PDF_OFFSET 0 +#define MXC_PLL_DP_OP_PDF_MASK 0xF + +#define MXC_PLL_DP_MFD_OFFSET 0 +#define MXC_PLL_DP_MFD_MASK 0x07FFFFFF + +#define MXC_PLL_DP_MFN_OFFSET 0x0 +#define MXC_PLL_DP_MFN_MASK 0x07FFFFFF + +#define MXC_PLL_DP_MFN_TOGC_TOG_DIS (1 << 17) +#define MXC_PLL_DP_MFN_TOGC_TOG_EN (1 << 16) +#define MXC_PLL_DP_MFN_TOGC_CNT_OFFSET 0x0 +#define MXC_PLL_DP_MFN_TOGC_CNT_MASK 0xFFFF + +#define MXC_PLL_DP_DESTAT_TOG_SEL (1 << 31) +#define MXC_PLL_DP_DESTAT_MFN 0x07FFFFFF + +/* Register addresses of CCM*/ +#define MXC_CCM_CCR (MXC_CCM_BASE + 0x00) +#define MXC_CCM_CCDR (MXC_CCM_BASE + 0x04) +#define MXC_CCM_CSR (MXC_CCM_BASE + 0x08) +#define MXC_CCM_CCSR (MXC_CCM_BASE + 0x0C) +#define MXC_CCM_CACRR (MXC_CCM_BASE + 0x10) +#define MXC_CCM_CBCDR (MXC_CCM_BASE + 0x14) +#define MXC_CCM_CBCMR (MXC_CCM_BASE + 0x18) +#define MXC_CCM_CSCMR1 (MXC_CCM_BASE + 0x1C) +#define MXC_CCM_CSCMR2 (MXC_CCM_BASE + 0x20) +#define MXC_CCM_CSCDR1 (MXC_CCM_BASE + 0x24) +#define MXC_CCM_CS1CDR (MXC_CCM_BASE + 0x28) +#define MXC_CCM_CS2CDR (MXC_CCM_BASE + 0x2C) +#define MXC_CCM_CDCDR (MXC_CCM_BASE + 0x30) +#define MXC_CCM_CHSCDR (MXC_CCM_BASE + 0x34) +#define MXC_CCM_CSCDR2 (MXC_CCM_BASE + 0x38) +#define MXC_CCM_CSCDR3 (MXC_CCM_BASE + 0x3C) +#define MXC_CCM_CSCDR4 (MXC_CCM_BASE + 0x40) +#define MXC_CCM_CWDR (MXC_CCM_BASE + 0x44) +#define MXC_CCM_CDHIPR (MXC_CCM_BASE + 0x48) +#define MXC_CCM_CDCR (MXC_CCM_BASE + 0x4C) +#define MXC_CCM_CTOR (MXC_CCM_BASE + 0x50) +#define MXC_CCM_CLPCR (MXC_CCM_BASE + 0x54) +#define MXC_CCM_CISR (MXC_CCM_BASE + 0x58) +#define MXC_CCM_CIMR (MXC_CCM_BASE + 0x5C) +#define MXC_CCM_CCOSR (MXC_CCM_BASE + 0x60) +#define MXC_CCM_CGPR (MXC_CCM_BASE + 0x64) +#define MXC_CCM_CCGR0 (MXC_CCM_BASE + 0x68) +#define MXC_CCM_CCGR1 (MXC_CCM_BASE + 0x6C) +#define MXC_CCM_CCGR2 (MXC_CCM_BASE + 0x70) +#define MXC_CCM_CCGR3 (MXC_CCM_BASE + 0x74) +#define MXC_CCM_CCGR4 (MXC_CCM_BASE + 0x78) +#define MXC_CCM_CCGR5 (MXC_CCM_BASE + 0x7C) +#define MXC_CCM_CCGR6 (MXC_CCM_BASE + 0x80) +#define MXC_CCM_CMEOR (MXC_CCM_BASE + 0x84) + +/* Define the bits in register CCR */ +#define MXC_CCM_CCR_COSC_EN (1 << 12) +#define MXC_CCM_CCR_FPM_MULT_MASK (1 << 11) +#define MXC_CCM_CCR_CAMP2_EN (1 << 10) +#define MXC_CCM_CCR_CAMP1_EN (1 << 9) +#define MXC_CCM_CCR_FPM_EN (1 << 8) +#define MXC_CCM_CCR_OSCNT_OFFSET (0) +#define MXC_CCM_CCR_OSCNT_MASK (0xFF) + +/* Define the bits in register CCDR */ +#define MXC_CCM_CCDR_HSC_HS_MASK (0x1 << 18) +#define MXC_CCM_CCDR_IPU_HS_MASK (0x1 << 17) +#define MXC_CCM_CCDR_EMI_HS_MASK (0x1 << 16) + +/* Define the bits in register CSR */ +#define MXC_CCM_CSR_COSR_READY (1 << 5) +#define MXC_CCM_CSR_LVS_VALUE (1 << 4) +#define MXC_CCM_CSR_CAMP2_READY (1 << 3) +#define MXC_CCM_CSR_CAMP1_READY (1 << 2) +#define MXC_CCM_CSR_FPM_READY (1 << 1) +#define MXC_CCM_CSR_REF_EN_B (1 << 0) + +/* Define the bits in register CCSR */ +#define MXC_CCM_CCSR_LP_APM_SEL (0x1 << 9) +#define MXC_CCM_CCSR_STEP_SEL_OFFSET (7) +#define MXC_CCM_CCSR_STEP_SEL_MASK (0x3 << 7) +#define MXC_CCM_CCSR_PLL2_PODF_OFFSET (5) +#define MXC_CCM_CCSR_PLL2_PODF_MASK (0x3 << 5) +#define MXC_CCM_CCSR_PLL3_PODF_OFFSET (3) +#define MXC_CCM_CCSR_PLL3_PODF_MASK (0x3 << 3) +#define MXC_CCM_CCSR_PLL1_SW_CLK_SEL (1 << 2) +#define MXC_CCM_CCSR_PLL2_SW_CLK_SEL (1 << 1) +#define MXC_CCM_CCSR_PLL3_SW_CLK_SEL (1 << 0) + +/* Define the bits in register CACRR */ +#define MXC_CCM_CACRR_ARM_PODF_OFFSET (0) +#define MXC_CCM_CACRR_ARM_PODF_MASK (0x7) + +/* Define the bits in register CBCDR */ +#define MXC_CCM_CBCDR_EMI_CLK_SEL (0x1 << 26) +#define MXC_CCM_CBCDR_PERIPH_CLK_SEL (0x1 << 25) +#define MXC_CCM_CBCDR_DDR_HF_SEL_OFFSET (30) +#define MXC_CCM_CBCDR_DDR_HF_SEL (0x1 << 30) +#define MXC_CCM_CBCDR_DDR_PODF_OFFSET (27) +#define MXC_CCM_CBCDR_DDR_PODF_MASK (0x7 << 27) +#define MXC_CCM_CBCDR_EMI_PODF_OFFSET (22) +#define MXC_CCM_CBCDR_EMI_PODF_MASK (0x7 << 22) +#define MXC_CCM_CBCDR_AXI_B_PODF_OFFSET (19) +#define MXC_CCM_CBCDR_AXI_B_PODF_MASK (0x7 << 19) +#define MXC_CCM_CBCDR_AXI_A_PODF_OFFSET (16) +#define MXC_CCM_CBCDR_AXI_A_PODF_MASK (0x7 << 16) +#define MXC_CCM_CBCDR_NFC_PODF_OFFSET (13) +#define MXC_CCM_CBCDR_NFC_PODF_MASK (0x7 << 13) +#define MXC_CCM_CBCDR_AHB_PODF_OFFSET (10) +#define MXC_CCM_CBCDR_AHB_PODF_MASK (0x7 << 10) +#define MXC_CCM_CBCDR_IPG_PODF_OFFSET (8) +#define MXC_CCM_CBCDR_IPG_PODF_MASK (0x3 << 8) +#define MXC_CCM_CBCDR_PERCLK_PRED1_OFFSET (6) +#define MXC_CCM_CBCDR_PERCLK_PRED1_MASK (0x3 << 6) +#define MXC_CCM_CBCDR_PERCLK_PRED2_OFFSET (3) +#define MXC_CCM_CBCDR_PERCLK_PRED2_MASK (0x7 << 3) +#define MXC_CCM_CBCDR_PERCLK_PODF_OFFSET (0) +#define MXC_CCM_CBCDR_PERCLK_PODF_MASK (0x7) + +/* Define the bits in register CBCMR */ +#define MXC_CCM_CBCMR_VPU_AXI_CLK_SEL_OFFSET (14) +#define MXC_CCM_CBCMR_VPU_AXI_CLK_SEL_MASK (0x3 << 14) +#define MXC_CCM_CBCMR_PERIPH_CLK_SEL_OFFSET (12) +#define MXC_CCM_CBCMR_PERIPH_CLK_SEL_MASK (0x3 << 12) +#define MXC_CCM_CBCMR_DDR_CLK_SEL_OFFSET (10) +#define MXC_CCM_CBCMR_DDR_CLK_SEL_MASK (0x3 << 10) +#define MXC_CCM_CBCMR_ARM_AXI_CLK_SEL_OFFSET (8) +#define MXC_CCM_CBCMR_ARM_AXI_CLK_SEL_MASK (0x3 << 8) +#define MXC_CCM_CBCMR_IPU_HSP_CLK_SEL_OFFSET (6) +#define MXC_CCM_CBCMR_IPU_HSP_CLK_SEL_MASK (0x3 << 6) +#define MXC_CCM_CBCMR_GPU_CLK_SEL_OFFSET (4) +#define MXC_CCM_CBCMR_GPU_CLK_SEL_MASK (0x3 << 4) +#define MXC_CCM_CBCMR_GPU2D_CLK_SEL_OFFSET (14) +#define MXC_CCM_CBCMR_GPU2D_CLK_SEL_MASK (0x3 << 14) +#define MXC_CCM_CBCMR_PERCLK_LP_APM_CLK_SEL (0x1 << 1) +#define MXC_CCM_CBCMR_PERCLK_IPG_CLK_SEL (0x1 << 0) + +/* Define the bits in register CSCMR1 */ +#define MXC_CCM_CSCMR1_SSI_EXT2_CLK_SEL_OFFSET (30) +#define MXC_CCM_CSCMR1_SSI_EXT2_CLK_SEL_MASK (0x3 << 30) +#define MXC_CCM_CSCMR1_SSI_EXT1_CLK_SEL_OFFSET (28) +#define MXC_CCM_CSCMR1_SSI_EXT1_CLK_SEL_MASK (0x3 << 28) +#define MXC_CCM_CSCMR1_USB_PHY_CLK_SEL_OFFSET (26) +#define MXC_CCM_CSCMR1_USB_PHY_CLK_SEL (0x1 << 26) +#define MXC_CCM_CSCMR1_UART_CLK_SEL_OFFSET (24) +#define MXC_CCM_CSCMR1_UART_CLK_SEL_MASK (0x3 << 24) +#define MXC_CCM_CSCMR1_USBOH3_CLK_SEL_OFFSET (22) +#define MXC_CCM_CSCMR1_USBOH3_CLK_SEL_MASK (0x3 << 22) +#define MXC_CCM_CSCMR1_ESDHC1_MSHC1_CLK_SEL_OFFSET (20) +#define MXC_CCM_CSCMR1_ESDHC1_MSHC1_CLK_SEL_MASK (0x3 << 20) +#define MXC_CCM_CSCMR1_ESDHC3_CLK_SEL (0x1 << 19) +#define MXC_CCM_CSCMR1_ESDHC4_CLK_SEL (0x1 << 18) +#define MXC_CCM_CSCMR1_ESDHC2_MSHC2_CLK_SEL_OFFSET (16) +#define MXC_CCM_CSCMR1_ESDHC2_MSHC2_CLK_SEL_MASK (0x3 << 16) +#define MXC_CCM_CSCMR1_SSI1_CLK_SEL_OFFSET (14) +#define MXC_CCM_CSCMR1_SSI1_CLK_SEL_MASK (0x3 << 14) +#define MXC_CCM_CSCMR1_SSI2_CLK_SEL_OFFSET (12) +#define MXC_CCM_CSCMR1_SSI2_CLK_SEL_MASK (0x3 << 12) +#define MXC_CCM_CSCMR1_SSI3_CLK_SEL (0x1 << 11) +#define MXC_CCM_CSCMR1_VPU_RCLK_SEL (0x1 << 10) +#define MXC_CCM_CSCMR1_SSI_APM_CLK_SEL_OFFSET (8) +#define MXC_CCM_CSCMR1_SSI_APM_CLK_SEL_MASK (0x3 << 8) +#define MXC_CCM_CSCMR1_TVE_CLK_SEL (0x1 << 7) +#define MXC_CCM_CSCMR1_TVE_EXT_CLK_SEL (0x1 << 6) +#define MXC_CCM_CSCMR1_CSPI_CLK_SEL_OFFSET (4) +#define MXC_CCM_CSCMR1_CSPI_CLK_SEL_MASK (0x3 << 4) +#define MXC_CCM_CSCMR1_SPDIF_CLK_SEL_OFFSET (2) +#define MXC_CCM_CSCMR1_SPDIF_CLK_SEL_MASK (0x3 << 2) +#define MXC_CCM_CSCMR1_SSI_EXT2_COM_CLK_SEL (0x1 << 1) +#define MXC_CCM_CSCMR1_SSI_EXT1_COM_CLK_SEL (0x1) + +/* Define the bits in register CSCMR2 */ +#define MXC_CCM_CSCMR2_DI_CLK_SEL_OFFSET(n) (26+n*3) +#define MXC_CCM_CSCMR2_DI_CLK_SEL_MASK(n) (0x7 << (26+n*3)) +#define MXC_CCM_CSCMR2_CSI_MCLK2_CLK_SEL_OFFSET (24) +#define MXC_CCM_CSCMR2_CSI_MCLK2_CLK_SEL_MASK (0x3 << 24) +#define MXC_CCM_CSCMR2_CSI_MCLK1_CLK_SEL_OFFSET (22) +#define MXC_CCM_CSCMR2_CSI_MCLK1_CLK_SEL_MASK (0x3 << 22) +#define MXC_CCM_CSCMR2_ESC_CLK_SEL_OFFSET (20) +#define MXC_CCM_CSCMR2_ESC_CLK_SEL_MASK (0x3 << 20) +#define MXC_CCM_CSCMR2_HSC2_CLK_SEL_OFFSET (18) +#define MXC_CCM_CSCMR2_HSC2_CLK_SEL_MASK (0x3 << 18) +#define MXC_CCM_CSCMR2_HSC1_CLK_SEL_OFFSET (16) +#define MXC_CCM_CSCMR2_HSC1_CLK_SEL_MASK (0x3 << 16) +#define MXC_CCM_CSCMR2_HSI2C_CLK_SEL_OFFSET (14) +#define MXC_CCM_CSCMR2_HSI2C_CLK_SEL_MASK (0x3 << 14) +#define MXC_CCM_CSCMR2_FIRI_CLK_SEL_OFFSET (12) +#define MXC_CCM_CSCMR2_FIRI_CLK_SEL_MASK (0x3 << 12) +#define MXC_CCM_CSCMR2_SIM_CLK_SEL_OFFSET (10) +#define MXC_CCM_CSCMR2_SIM_CLK_SEL_MASK (0x3 << 10) +#define MXC_CCM_CSCMR2_SLIMBUS_COM (0x1 << 9) +#define MXC_CCM_CSCMR2_SLIMBUS_CLK_SEL_OFFSET (6) +#define MXC_CCM_CSCMR2_SLIMBUS_CLK_SEL_MASK (0x7 << 6) +#define MXC_CCM_CSCMR2_SPDIF1_COM (1 << 5) +#define MXC_CCM_CSCMR2_SPDIF0_COM (1 << 4) +#define MXC_CCM_CSCMR2_SPDIF1_CLK_SEL_OFFSET (2) +#define MXC_CCM_CSCMR2_SPDIF1_CLK_SEL_MASK (0x3 << 2) +#define MXC_CCM_CSCMR2_SPDIF0_CLK_SEL_OFFSET (0) +#define MXC_CCM_CSCMR2_SPDIF0_CLK_SEL_MASK (0x3) + +/* Define the bits in register CSCDR1 */ +#define MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PRED_OFFSET (22) +#define MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PRED_MASK (0x7 << 22) +#define MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PODF_OFFSET (19) +#define MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PODF_MASK (0x7 << 19) +#define MXC_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PRED_OFFSET (16) +#define MXC_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PRED_MASK (0x7 << 16) +#define MXC_CCM_CSCDR1_PGC_CLK_PODF_OFFSET (14) +#define MXC_CCM_CSCDR1_PGC_CLK_PODF_MASK (0x3 << 14) +#define MXC_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PODF_OFFSET (11) +#define MXC_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PODF_MASK (0x7 << 11) +#define MXC_CCM_CSCDR1_USBOH3_CLK_PRED_OFFSET (8) +#define MXC_CCM_CSCDR1_USBOH3_CLK_PRED_MASK (0x7 << 8) +#define MXC_CCM_CSCDR1_USBOH3_CLK_PODF_OFFSET (6) +#define MXC_CCM_CSCDR1_USBOH3_CLK_PODF_MASK (0x3 << 6) +#define MXC_CCM_CSCDR1_UART_CLK_PRED_OFFSET (3) +#define MXC_CCM_CSCDR1_UART_CLK_PRED_MASK (0x7 << 3) +#define MXC_CCM_CSCDR1_UART_CLK_PODF_OFFSET (0) +#define MXC_CCM_CSCDR1_UART_CLK_PODF_MASK (0x7) + +/* Define the bits in register CS1CDR and CS2CDR */ +#define MXC_CCM_CS1CDR_SSI_EXT1_CLK_PRED_OFFSET (22) +#define MXC_CCM_CS1CDR_SSI_EXT1_CLK_PRED_MASK (0x7 << 22) +#define MXC_CCM_CS1CDR_SSI_EXT1_CLK_PODF_OFFSET (16) +#define MXC_CCM_CS1CDR_SSI_EXT1_CLK_PODF_MASK (0x3F << 16) +#define MXC_CCM_CS1CDR_SSI1_CLK_PRED_OFFSET (6) +#define MXC_CCM_CS1CDR_SSI1_CLK_PRED_MASK (0x7 << 6) +#define MXC_CCM_CS1CDR_SSI1_CLK_PODF_OFFSET (0) +#define MXC_CCM_CS1CDR_SSI1_CLK_PODF_MASK (0x3F) + +#define MXC_CCM_CS2CDR_SSI_EXT2_CLK_PRED_OFFSET (22) +#define MXC_CCM_CS2CDR_SSI_EXT2_CLK_PRED_MASK (0x7 << 22) +#define MXC_CCM_CS2CDR_SSI_EXT2_CLK_PODF_OFFSET (16) +#define MXC_CCM_CS2CDR_SSI_EXT2_CLK_PODF_MASK (0x3F << 16) +#define MXC_CCM_CS2CDR_SSI2_CLK_PRED_OFFSET (6) +#define MXC_CCM_CS2CDR_SSI2_CLK_PRED_MASK (0x7 << 6) +#define MXC_CCM_CS2CDR_SSI2_CLK_PODF_OFFSET (0) +#define MXC_CCM_CS2CDR_SSI2_CLK_PODF_MASK (0x3F) + +/* Define the bits in register CDCDR */ +#define MXC_CCM_CDCDR_TVE_CLK_PRED_OFFSET (28) +#define MXC_CCM_CDCDR_TVE_CLK_PRED_MASK (0x7 << 28) +#define MXC_CCM_CDCDR_SPDIF0_CLK_PRED_OFFSET (25) +#define MXC_CCM_CDCDR_SPDIF0_CLK_PRED_MASK (0x7 << 25) +#define MXC_CCM_CDCDR_SPDIF0_CLK_PODF_OFFSET (19) +#define MXC_CCM_CDCDR_SPDIF0_CLK_PODF_MASK (0x3F << 19) +#define MXC_CCM_CDCDR_SPDIF1_CLK_PRED_OFFSET (16) +#define MXC_CCM_CDCDR_SPDIF1_CLK_PRED_MASK (0x7 << 16) +#define MXC_CCM_CDCDR_SPDIF1_CLK_PODF_OFFSET (9) +#define MXC_CCM_CDCDR_SPDIF1_CLK_PODF_MASK (0x3F << 9) +#define MXC_CCM_CDCDR_DI_CLK_PRED_OFFSET (6) +#define MXC_CCM_CDCDR_DI_CLK_PRED_MASK (0x7 << 6) +#define MXC_CCM_CDCDR_USB_PHY_PRED_OFFSET (3) +#define MXC_CCM_CDCDR_USB_PHY_PRED_MASK (0x7 << 3) +#define MXC_CCM_CDCDR_USB_PHY_PODF_OFFSET (0) +#define MXC_CCM_CDCDR_USB_PHY_PODF_MASK (0x7) + +/* Define the bits in register CHSCCDR */ +#define MXC_CCM_CHSCCDR_ESC_CLK_PRED_OFFSET (12) +#define MXC_CCM_CHSCCDR_ESC_CLK_PRED_MASK (0x7 << 12) +#define MXC_CCM_CHSCCDR_ESC_CLK_PODF_OFFSET (6) +#define MXC_CCM_CHSCCDR_ESC_CLK_PODF_MASK (0x3F << 6) +#define MXC_CCM_CHSCCDR_HSC2_CLK_PODF_OFFSET (3) +#define MXC_CCM_CHSCCDR_HSC2_CLK_PODF_MASK (0x7 << 3) +#define MXC_CCM_CHSCCDR_HSC1_CLK_PODF_OFFSET (0) +#define MXC_CCM_CHSCCDR_HSC1_CLK_PODF_MASK (0x7) + +/* Define the bits in register CSCDR2 */ +#define MXC_CCM_CSCDR2_CSPI_CLK_PRED_OFFSET (25) +#define MXC_CCM_CSCDR2_CSPI_CLK_PRED_MASK (0x7 << 25) +#define MXC_CCM_CSCDR2_CSPI_CLK_PODF_OFFSET (19) +#define MXC_CCM_CSCDR2_CSPI_CLK_PODF_MASK (0x3F << 19) +#define MXC_CCM_CSCDR2_SIM_CLK_PRED_OFFSET (16) +#define MXC_CCM_CSCDR2_SIM_CLK_PRED_MASK (0x7 << 16) +#define MXC_CCM_CSCDR2_SIM_CLK_PODF_OFFSET (9) +#define MXC_CCM_CSCDR2_SIM_CLK_PODF_MASK (0x3F << 9) +#define MXC_CCM_CSCDR2_SLIMBUS_CLK_PRED_OFFSET (6) +#define MXC_CCM_CSCDR2_SLIMBUS_PRED_MASK (0x7 << 6) +#define MXC_CCM_CSCDR2_SLIMBUS_PODF_OFFSET (0) +#define MXC_CCM_CSCDR2_SLIMBUS_PODF_MASK (0x3F) + +/* Define the bits in register CSCDR3 */ +#define MXC_CCM_CSCDR3_HSI2C_CLK_PRED_OFFSET (16) +#define MXC_CCM_CSCDR3_HSI2C_CLK_PRED_MASK (0x7 << 16) +#define MXC_CCM_CSCDR3_HSI2C_CLK_PODF_OFFSET (9) +#define MXC_CCM_CSCDR3_HSI2C_CLK_PODF_MASK (0x3F << 9) +#define MXC_CCM_CSCDR3_FIRI_CLK_PRED_OFFSET (6) +#define MXC_CCM_CSCDR3_FIRI_CLK_PRED_MASK (0x7 << 6) +#define MXC_CCM_CSCDR3_FIRI_CLK_PODF_OFFSET (0) +#define MXC_CCM_CSCDR3_FIRI_CLK_PODF_MASK (0x3F) + +/* Define the bits in register CSCDR4 */ +#define MXC_CCM_CSCDR4_CSI_MCLK2_CLK_PRED_OFFSET (16) +#define MXC_CCM_CSCDR4_CSI_MCLK2_CLK_PRED_MASK (0x7 << 16) +#define MXC_CCM_CSCDR4_CSI_MCLK2_CLK_PODF_OFFSET (9) +#define MXC_CCM_CSCDR4_CSI_MCLK2_CLK_PODF_MASK (0x3F << 9) +#define MXC_CCM_CSCDR4_CSI_MCLK1_CLK_PRED_OFFSET (6) +#define MXC_CCM_CSCDR4_CSI_MCLK1_CLK_PRED_MASK (0x7 << 6) +#define MXC_CCM_CSCDR4_CSI_MCLK1_CLK_PODF_OFFSET (0) +#define MXC_CCM_CSCDR4_CSI_MCLK1_CLK_PODF_MASK (0x3F) + +/* Define the bits in register CDHIPR */ +#define MXC_CCM_CDHIPR_ARM_PODF_BUSY (1 << 16) +#define MXC_CCM_CDHIPR_DDR_HF_CLK_SEL_BUSY (1 << 8) +#define MXC_CCM_CDHIPR_DDR_PODF_BUSY (1 << 7) +#define MXC_CCM_CDHIPR_EMI_CLK_SEL_BUSY (1 << 6) +#define MXC_CCM_CDHIPR_PERIPH_CLK_SEL_BUSY (1 << 5) +#define MXC_CCM_CDHIPR_NFC_IPG_INT_MEM_PODF_BUSY (1 << 4) +#define MXC_CCM_CDHIPR_AHB_PODF_BUSY (1 << 3) +#define MXC_CCM_CDHIPR_EMI_PODF_BUSY (1 << 2) +#define MXC_CCM_CDHIPR_AXI_B_PODF_BUSY (1 << 1) +#define MXC_CCM_CDHIPR_AXI_A_PODF_BUSY (1 << 0) + +/* Define the bits in register CDCR */ +#define MXC_CCM_CDCR_ARM_FREQ_SHIFT_DIVIDER (0x1 << 2) +#define MXC_CCM_CDCR_PERIPH_CLK_DVFS_PODF_OFFSET (0) +#define MXC_CCM_CDCR_PERIPH_CLK_DVFS_PODF_MASK (0x3) + +/* Define the bits in register CLPCR */ +#define MXC_CCM_CLPCR_BYPASS_HSC_LPM_HS (0x1 << 23) +#define MXC_CCM_CLPCR_BYPASS_SCC_LPM_HS (0x1 << 22) +#define MXC_CCM_CLPCR_BYPASS_MAX_LPM_HS (0x1 << 21) +#define MXC_CCM_CLPCR_BYPASS_SDMA_LPM_HS (0x1 << 20) +#define MXC_CCM_CLPCR_BYPASS_EMI_LPM_HS (0x1 << 19) +#define MXC_CCM_CLPCR_BYPASS_IPU_LPM_HS (0x1 << 18) +#define MXC_CCM_CLPCR_BYPASS_RTIC_LPM_HS (0x1 << 17) +#define MXC_CCM_CLPCR_BYPASS_RNGC_LPM_HS (0x1 << 16) +#define MXC_CCM_CLPCR_COSC_PWRDOWN (0x1 << 11) +#define MXC_CCM_CLPCR_STBY_COUNT_OFFSET (9) +#define MXC_CCM_CLPCR_STBY_COUNT_MASK (0x3 << 9) +#define MXC_CCM_CLPCR_VSTBY (0x1 << 8) +#define MXC_CCM_CLPCR_DIS_REF_OSC (0x1 << 7) +#define MXC_CCM_CLPCR_SBYOS (0x1 << 6) +#define MXC_CCM_CLPCR_ARM_CLK_DIS_ON_LPM (0x1 << 5) +#define MXC_CCM_CLPCR_LPSR_CLK_SEL_OFFSET (3) +#define MXC_CCM_CLPCR_LPSR_CLK_SEL_MASK (0x3 << 3) +#define MXC_CCM_CLPCR_LPM_OFFSET (0) +#define MXC_CCM_CLPCR_LPM_MASK (0x3) + +/* Define the bits in register CISR */ +#define MXC_CCM_CISR_ARM_PODF_LOADED (0x1 << 25) +#define MXC_CCM_CISR_NFC_IPG_INT_MEM_PODF_LOADED (0x1 << 21) +#define MXC_CCM_CISR_AHB_PODF_LOADED (0x1 << 20) +#define MXC_CCM_CISR_EMI_PODF_LOADED (0x1 << 19) +#define MXC_CCM_CISR_AXI_B_PODF_LOADED (0x1 << 18) +#define MXC_CCM_CISR_AXI_A_PODF_LOADED (0x1 << 17) +#define MXC_CCM_CISR_DIVIDER_LOADED (0x1 << 16) +#define MXC_CCM_CISR_COSC_READY (0x1 << 6) +#define MXC_CCM_CISR_CKIH2_READY (0x1 << 5) +#define MXC_CCM_CISR_CKIH_READY (0x1 << 4) +#define MXC_CCM_CISR_FPM_READY (0x1 << 3) +#define MXC_CCM_CISR_LRF_PLL3 (0x1 << 2) +#define MXC_CCM_CISR_LRF_PLL2 (0x1 << 1) +#define MXC_CCM_CISR_LRF_PLL1 (0x1) + +/* Define the bits in register CIMR */ +#define MXC_CCM_CIMR_MASK_ARM_PODF_LOADED (0x1 << 25) +#define MXC_CCM_CIMR_MASK_NFC_IPG_INT_MEM_PODF_LOADED (0x1 << 21) +#define MXC_CCM_CIMR_MASK_EMI_PODF_LOADED (0x1 << 20) +#define MXC_CCM_CIMR_MASK_AXI_C_PODF_LOADED (0x1 << 19) +#define MXC_CCM_CIMR_MASK_AXI_B_PODF_LOADED (0x1 << 18) +#define MXC_CCM_CIMR_MASK_AXI_A_PODF_LOADED (0x1 << 17) +#define MXC_CCM_CIMR_MASK_DIVIDER_LOADED (0x1 << 16) +#define MXC_CCM_CIMR_MASK_COSC_READY (0x1 << 5) +#define MXC_CCM_CIMR_MASK_CKIH_READY (0x1 << 4) +#define MXC_CCM_CIMR_MASK_FPM_READY (0x1 << 3) +#define MXC_CCM_CIMR_MASK_LRF_PLL3 (0x1 << 2) +#define MXC_CCM_CIMR_MASK_LRF_PLL2 (0x1 << 1) +#define MXC_CCM_CIMR_MASK_LRF_PLL1 (0x1) + +/* Define the bits in register CCOSR */ +#define MXC_CCM_CCOSR_CKO2_EN_OFFSET (0x1 << 24) +#define MXC_CCM_CCOSR_CKO2_DIV_OFFSET (21) +#define MXC_CCM_CCOSR_CKO2_DIV_MASK (0x7 << 21) +#define MXC_CCM_CCOSR_CKO2_SEL_OFFSET (16) +#define MXC_CCM_CCOSR_CKO2_SEL_MASK (0x1F << 16) +#define MXC_CCM_CCOSR_CKOL_EN (0x1 << 7) +#define MXC_CCM_CCOSR_CKOL_DIV_OFFSET (4) +#define MXC_CCM_CCOSR_CKOL_DIV_MASK (0x7 << 4) +#define MXC_CCM_CCOSR_CKOL_SEL_OFFSET (0) +#define MXC_CCM_CCOSR_CKOL_SEL_MASK (0xF) + +/* Define the bits in registers CGPR */ +#define MXC_CCM_CGPR_EFUSE_PROG_SUPPLY_GATE (0x1 << 4) +#define MXC_CCM_CGPR_FPM_SEL (0x1 << 3) +#define MXC_CCM_CGPR_VL_L2BIST_CLKDIV_OFFSET (0) +#define MXC_CCM_CGPR_VL_L2BIST_CLKDIV_MASK (0x7) + +/* Define the bits in registers CCGRx */ +#define MXC_CCM_CCGR_CG_MASK 0x3 + +#define MXC_CCM_CCGR0_CG15_OFFSET 30 +#define MXC_CCM_CCGR0_CG15_MASK (0x3 << 30) +#define MXC_CCM_CCGR0_CG14_OFFSET 28 +#define MXC_CCM_CCGR0_CG14_MASK (0x3 << 28) +#define MXC_CCM_CCGR0_CG13_OFFSET 26 +#define MXC_CCM_CCGR0_CG13_MASK (0x3 << 26) +#define MXC_CCM_CCGR0_CG12_OFFSET 24 +#define MXC_CCM_CCGR0_CG12_MASK (0x3 << 24) +#define MXC_CCM_CCGR0_CG11_OFFSET 22 +#define MXC_CCM_CCGR0_CG11_MASK (0x3 << 22) +#define MXC_CCM_CCGR0_CG10_OFFSET 20 +#define MXC_CCM_CCGR0_CG10_MASK (0x3 << 20) +#define MXC_CCM_CCGR0_CG9_OFFSET 18 +#define MXC_CCM_CCGR0_CG9_MASK (0x3 << 18) +#define MXC_CCM_CCGR0_CG8_OFFSET 16 +#define MXC_CCM_CCGR0_CG8_MASK (0x3 << 16) +#define MXC_CCM_CCGR0_CG7_OFFSET 14 +#define MXC_CCM_CCGR0_CG6_OFFSET 12 +#define MXC_CCM_CCGR0_CG5_OFFSET 10 +#define MXC_CCM_CCGR0_CG5_MASK (0x3 << 10) +#define MXC_CCM_CCGR0_CG4_OFFSET 8 +#define MXC_CCM_CCGR0_CG4_MASK (0x3 << 8) +#define MXC_CCM_CCGR0_CG3_OFFSET 6 +#define MXC_CCM_CCGR0_CG3_MASK (0x3 << 6) +#define MXC_CCM_CCGR0_CG2_OFFSET 4 +#define MXC_CCM_CCGR0_CG2_MASK (0x3 << 4) +#define MXC_CCM_CCGR0_CG1_OFFSET 2 +#define MXC_CCM_CCGR0_CG1_MASK (0x3 << 2) +#define MXC_CCM_CCGR0_CG0_OFFSET 0 +#define MXC_CCM_CCGR0_CG0_MASK 0x3 + +#define MXC_CCM_CCGR1_CG15_OFFSET 30 +#define MXC_CCM_CCGR1_CG14_OFFSET 28 +#define MXC_CCM_CCGR1_CG13_OFFSET 26 +#define MXC_CCM_CCGR1_CG12_OFFSET 24 +#define MXC_CCM_CCGR1_CG11_OFFSET 22 +#define MXC_CCM_CCGR1_CG10_OFFSET 20 +#define MXC_CCM_CCGR1_CG9_OFFSET 18 +#define MXC_CCM_CCGR1_CG8_OFFSET 16 +#define MXC_CCM_CCGR1_CG7_OFFSET 14 +#define MXC_CCM_CCGR1_CG6_OFFSET 12 +#define MXC_CCM_CCGR1_CG5_OFFSET 10 +#define MXC_CCM_CCGR1_CG4_OFFSET 8 +#define MXC_CCM_CCGR1_CG3_OFFSET 6 +#define MXC_CCM_CCGR1_CG2_OFFSET 4 +#define MXC_CCM_CCGR1_CG1_OFFSET 2 +#define MXC_CCM_CCGR1_CG0_OFFSET 0 + +#define MXC_CCM_CCGR2_CG15_OFFSET 30 +#define MXC_CCM_CCGR2_CG14_OFFSET 28 +#define MXC_CCM_CCGR2_CG13_OFFSET 26 +#define MXC_CCM_CCGR2_CG12_OFFSET 24 +#define MXC_CCM_CCGR2_CG11_OFFSET 22 +#define MXC_CCM_CCGR2_CG10_OFFSET 20 +#define MXC_CCM_CCGR2_CG9_OFFSET 18 +#define MXC_CCM_CCGR2_CG8_OFFSET 16 +#define MXC_CCM_CCGR2_CG7_OFFSET 14 +#define MXC_CCM_CCGR2_CG6_OFFSET 12 +#define MXC_CCM_CCGR2_CG5_OFFSET 10 +#define MXC_CCM_CCGR2_CG4_OFFSET 8 +#define MXC_CCM_CCGR2_CG3_OFFSET 6 +#define MXC_CCM_CCGR2_CG2_OFFSET 4 +#define MXC_CCM_CCGR2_CG1_OFFSET 2 +#define MXC_CCM_CCGR2_CG0_OFFSET 0 + +#define MXC_CCM_CCGR3_CG15_OFFSET 30 +#define MXC_CCM_CCGR3_CG14_OFFSET 28 +#define MXC_CCM_CCGR3_CG13_OFFSET 26 +#define MXC_CCM_CCGR3_CG12_OFFSET 24 +#define MXC_CCM_CCGR3_CG11_OFFSET 22 +#define MXC_CCM_CCGR3_CG10_OFFSET 20 +#define MXC_CCM_CCGR3_CG9_OFFSET 18 +#define MXC_CCM_CCGR3_CG8_OFFSET 16 +#define MXC_CCM_CCGR3_CG7_OFFSET 14 +#define MXC_CCM_CCGR3_CG6_OFFSET 12 +#define MXC_CCM_CCGR3_CG5_OFFSET 10 +#define MXC_CCM_CCGR3_CG4_OFFSET 8 +#define MXC_CCM_CCGR3_CG3_OFFSET 6 +#define MXC_CCM_CCGR3_CG2_OFFSET 4 +#define MXC_CCM_CCGR3_CG1_OFFSET 2 +#define MXC_CCM_CCGR3_CG0_OFFSET 0 + +#define MXC_CCM_CCGR4_CG15_OFFSET 30 +#define MXC_CCM_CCGR4_CG14_OFFSET 28 +#define MXC_CCM_CCGR4_CG13_OFFSET 26 +#define MXC_CCM_CCGR4_CG12_OFFSET 24 +#define MXC_CCM_CCGR4_CG11_OFFSET 22 +#define MXC_CCM_CCGR4_CG10_OFFSET 20 +#define MXC_CCM_CCGR4_CG9_OFFSET 18 +#define MXC_CCM_CCGR4_CG8_OFFSET 16 +#define MXC_CCM_CCGR4_CG7_OFFSET 14 +#define MXC_CCM_CCGR4_CG6_OFFSET 12 +#define MXC_CCM_CCGR4_CG5_OFFSET 10 +#define MXC_CCM_CCGR4_CG4_OFFSET 8 +#define MXC_CCM_CCGR4_CG3_OFFSET 6 +#define MXC_CCM_CCGR4_CG2_OFFSET 4 +#define MXC_CCM_CCGR4_CG1_OFFSET 2 +#define MXC_CCM_CCGR4_CG0_OFFSET 0 + +#define MXC_CCM_CCGR5_CG15_OFFSET 30 +#define MXC_CCM_CCGR5_CG14_OFFSET 28 +#define MXC_CCM_CCGR5_CG14_MASK (0x3 << 28) +#define MXC_CCM_CCGR5_CG13_OFFSET 26 +#define MXC_CCM_CCGR5_CG13_MASK (0x3 << 26) +#define MXC_CCM_CCGR5_CG12_OFFSET 24 +#define MXC_CCM_CCGR5_CG12_MASK (0x3 << 24) +#define MXC_CCM_CCGR5_CG11_OFFSET 22 +#define MXC_CCM_CCGR5_CG11_MASK (0x3 << 22) +#define MXC_CCM_CCGR5_CG10_OFFSET 20 +#define MXC_CCM_CCGR5_CG10_MASK (0x3 << 20) +#define MXC_CCM_CCGR5_CG9_OFFSET 18 +#define MXC_CCM_CCGR5_CG9_MASK (0x3 << 18) +#define MXC_CCM_CCGR5_CG8_OFFSET 16 +#define MXC_CCM_CCGR5_CG8_MASK (0x3 << 16) +#define MXC_CCM_CCGR5_CG7_OFFSET 14 +#define MXC_CCM_CCGR5_CG7_MASK (0x3 << 14) +#define MXC_CCM_CCGR5_CG6_OFFSET 12 +#define MXC_CCM_CCGR5_CG5_OFFSET 10 +#define MXC_CCM_CCGR5_CG4_OFFSET 8 +#define MXC_CCM_CCGR5_CG3_OFFSET 6 +#define MXC_CCM_CCGR5_CG2_OFFSET 4 +#define MXC_CCM_CCGR5_CG2_MASK (0x3 << 4) +#define MXC_CCM_CCGR5_CG1_OFFSET 2 +#define MXC_CCM_CCGR5_CG0_OFFSET 0 +#define MXC_CCM_CCGR6_CG7_OFFSET 14 +#define MXC_CCM_CCGR6_CG7_MASK (0x3 << 14) +#define MXC_CCM_CCGR6_CG6_OFFSET 12 +#define MXC_CCM_CCGR6_CG6_MASK (0x3 << 12) +#define MXC_CCM_CCGR6_CG5_OFFSET 10 +#define MXC_CCM_CCGR6_CG5_MASK (0x3 << 10) +#define MXC_CCM_CCGR6_CG4_OFFSET 8 +#define MXC_CCM_CCGR6_CG4_MASK (0x3 << 8) +#define MXC_CCM_CCGR6_CG3_OFFSET 6 +#define MXC_CCM_CCGR6_CG2_OFFSET 4 +#define MXC_CCM_CCGR6_CG1_OFFSET 2 +#define MXC_CCM_CCGR6_CG0_OFFSET 0 + +#define MXC_CORTEXA8_BASE IO_ADDRESS(ARM_BASE_ADDR) +#define MXC_GPC_BASE IO_ADDRESS(GPC_BASE_ADDR) +#define MXC_DPTC_LP_BASE IO_ADDRESS(GPC_BASE_ADDR + 0x80) +#define MXC_DPTC_GP_BASE IO_ADDRESS(GPC_BASE_ADDR + 0x100) +#define MXC_DVFS_CORE_BASE IO_ADDRESS(GPC_BASE_ADDR + 0x180) +#define MXC_DVFS_PER_BASE IO_ADDRESS(GPC_BASE_ADDR + 0x1C4) +#define MXC_PGC_IPU_BASE IO_ADDRESS(GPC_BASE_ADDR + 0x220) +#define MXC_PGC_VPU_BASE IO_ADDRESS(GPC_BASE_ADDR + 0x240) +#define MXC_PGC_GPU_BASE IO_ADDRESS(GPC_BASE_ADDR + 0x260) +#define MXC_SRPG_NEON_BASE IO_ADDRESS(GPC_BASE_ADDR + 0x280) +#define MXC_SRPG_ARM_BASE IO_ADDRESS(GPC_BASE_ADDR + 0x2A0) +#define MXC_SRPG_EMPGC0_BASE IO_ADDRESS(GPC_BASE_ADDR + 0x2C0) +#define MXC_SRPG_EMPGC1_BASE IO_ADDRESS(GPC_BASE_ADDR + 0x2D0) +#define MXC_SRPG_MEGAMIX_BASE IO_ADDRESS(GPC_BASE_ADDR + 0x2E0) +#define MXC_SRPG_EMI_BASE IO_ADDRESS(GPC_BASE_ADDR + 0x300) + +/* CORTEXA8 platform */ +#define MXC_CORTEXA8_PLAT_PVID (MXC_CORTEXA8_BASE + 0x0) +#define MXC_CORTEXA8_PLAT_GPC (MXC_CORTEXA8_BASE + 0x4) +#define MXC_CORTEXA8_PLAT_PIC (MXC_CORTEXA8_BASE + 0x8) +#define MXC_CORTEXA8_PLAT_LPC (MXC_CORTEXA8_BASE + 0xC) +#define MXC_CORTEXA8_PLAT_NEON_LPC (MXC_CORTEXA8_BASE + 0x10) +#define MXC_CORTEXA8_PLAT_ICGC (MXC_CORTEXA8_BASE + 0x14) +#define MXC_CORTEXA8_PLAT_AMC (MXC_CORTEXA8_BASE + 0x18) +#define MXC_CORTEXA8_PLAT_NMC (MXC_CORTEXA8_BASE + 0x20) +#define MXC_CORTEXA8_PLAT_NMS (MXC_CORTEXA8_BASE + 0x24) + +/* DVFS CORE */ +#define MXC_DVFSTHRS (MXC_DVFS_CORE_BASE + 0x00) +#define MXC_DVFSCOUN (MXC_DVFS_CORE_BASE + 0x04) +#define MXC_DVFSSIG1 (MXC_DVFS_CORE_BASE + 0x08) +#define MXC_DVFSSIG0 (MXC_DVFS_CORE_BASE + 0x0C) +#define MXC_DVFSGPC0 (MXC_DVFS_CORE_BASE + 0x10) +#define MXC_DVFSGPC1 (MXC_DVFS_CORE_BASE + 0x14) +#define MXC_DVFSGPBT (MXC_DVFS_CORE_BASE + 0x18) +#define MXC_DVFSEMAC (MXC_DVFS_CORE_BASE + 0x1C) +#define MXC_DVFSCNTR (MXC_DVFS_CORE_BASE + 0x20) +#define MXC_DVFSLTR0_0 (MXC_DVFS_CORE_BASE + 0x24) +#define MXC_DVFSLTR0_1 (MXC_DVFS_CORE_BASE + 0x28) +#define MXC_DVFSLTR1_0 (MXC_DVFS_CORE_BASE + 0x2C) +#define MXC_DVFSLTR1_1 (MXC_DVFS_CORE_BASE + 0x30) +#define MXC_DVFSPT0 (MXC_DVFS_CORE_BASE + 0x34) +#define MXC_DVFSPT1 (MXC_DVFS_CORE_BASE + 0x38) +#define MXC_DVFSPT2 (MXC_DVFS_CORE_BASE + 0x3C) +#define MXC_DVFSPT3 (MXC_DVFS_CORE_BASE + 0x40) + +/* DVFS PER */ +#define MXC_DVFSPER_LTR0 (MXC_DVFS_PER_BASE) +#define MXC_DVFSPER_LTR1 (MXC_DVFS_PER_BASE + 0x04) +#define MXC_DVFSPER_LTR2 (MXC_DVFS_PER_BASE + 0x08) +#define MXC_DVFSPER_LTR3 (MXC_DVFS_PER_BASE + 0x0C) +#define MXC_DVFSPER_LTBR0 (MXC_DVFS_PER_BASE + 0x10) +#define MXC_DVFSPER_LTBR1 (MXC_DVFS_PER_BASE + 0x14) +#define MXC_DVFSPER_PMCR0 (MXC_DVFS_PER_BASE + 0x18) +#define MXC_DVFSPER_PMCR1 (MXC_DVFS_PER_BASE + 0x1C) + +/* GPC */ +#define MXC_GPC_CNTR (MXC_GPC_BASE + 0x0) +#define MXC_GPC_PGR (MXC_GPC_BASE + 0x4) +#define MXC_GPC_VCR (MXC_GPC_BASE + 0x8) +#define MXC_GPC_ALL_PU (MXC_GPC_BASE + 0xC) +#define MXC_GPC_NEON (MXC_GPC_BASE + 0x10) + +/* PGC */ +#define MXC_PGC_IPU_PGCR (MXC_PGC_IPU_BASE + 0x0) +#define MXC_PGC_IPU_PGSR (MXC_PGC_IPU_BASE + 0xC) +#define MXC_PGC_VPU_PGCR (MXC_PGC_VPU_BASE + 0x0) +#define MXC_PGC_VPU_PGSR (MXC_PGC_VPU_BASE + 0xC) +#define MXC_PGC_GPU_PGCR (MXC_PGC_GPU_BASE + 0x0) +#define MXC_PGC_GPU_PGSR (MXC_PGC_GPU_BASE + 0xC) + +#define MXC_PGCR_PCR 1 +#define MXC_SRPGCR_PCR 1 +#define MXC_EMPGCR_PCR 1 +#define MXC_PGSR_PSR 1 + + +#define MXC_CORTEXA8_PLAT_LPC_DSM (1 << 0) +#define MXC_CORTEXA8_PLAT_LPC_DBG_DSM (1 << 1) + +/* SRPG */ +#define MXC_SRPG_NEON_SRPGCR (MXC_SRPG_NEON_BASE + 0x0) +#define MXC_SRPG_NEON_PUPSCR (MXC_SRPG_NEON_BASE + 0x4) +#define MXC_SRPG_NEON_PDNSCR (MXC_SRPG_NEON_BASE + 0x8) + +#define MXC_SRPG_ARM_SRPGCR (MXC_SRPG_ARM_BASE + 0x0) +#define MXC_SRPG_ARM_PUPSCR (MXC_SRPG_ARM_BASE + 0x4) +#define MXC_SRPG_ARM_PDNSCR (MXC_SRPG_ARM_BASE + 0x8) + +#define MXC_SRPG_EMPGC0_SRPGCR (MXC_SRPG_EMPGC0_BASE + 0x0) +#define MXC_SRPG_EMPGC0_PUPSCR (MXC_SRPG_EMPGC0_BASE + 0x4) +#define MXC_SRPG_EMPGC0_PDNSCR (MXC_SRPG_EMPGC0_BASE + 0x8) + +#define MXC_SRPG_EMPGC1_SRPGCR (MXC_SRPG_EMPGC1_BASE + 0x0) +#define MXC_SRPG_EMPGC1_PUPSCR (MXC_SRPG_EMPGC1_BASE + 0x4) +#define MXC_SRPG_EMPGC1_PDNSCR (MXC_SRPG_EMPGC1_BASE + 0x8) + +#define MXC_SRPG_MEGAMIX_SRPGCR (MXC_SRPG_MEGAMIX_BASE + 0x0) +#define MXC_SRPG_MEGAMIX_PUPSCR (MXC_SRPG_MEGAMIX_BASE + 0x4) +#define MXC_SRPG_MEGAMIX_PDNSCR (MXC_SRPG_MEGAMIX_BASE + 0x8) + +#define MXC_SRPGC_EMI_SRPGCR (MXC_SRPGC_EMI_BASE + 0x0) +#define MXC_SRPGC_EMI_PUPSCR (MXC_SRPGC_EMI_BASE + 0x4) +#define MXC_SRPGC_EMI_PDNSCR (MXC_SRPGC_EMI_BASE + 0x8) + +#endif /* __ARCH_ARM_MACH_MX51_CRM_REGS_H__ */ diff --git a/arch/arm/mach-mx51/devices.c b/arch/arm/mach-mx51/devices.c new file mode 100644 index 000000000000..3496580d807f --- /dev/null +++ b/arch/arm/mach-mx51/devices.c @@ -0,0 +1,1284 @@ +/* + * Copyright 2008-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/kernel.h> +#include <linux/err.h> +#include <linux/init.h> +#include <linux/io.h> +#include <linux/dma-mapping.h> +#include <linux/platform_device.h> +#include <linux/clk.h> +#include <linux/delay.h> +#include <linux/spi/spi.h> +#include <linux/uio_driver.h> +#include <linux/mxc_scc2_driver.h> +#include <linux/pwm_backlight.h> +#include <mach/hardware.h> +#include <mach/spba.h> +#include <asm/mach-types.h> +#include "iomux.h" +#include "crm_regs.h" +#include <mach/sdma.h> +#include "sdma_script_code.h" + +/* Flag used to indicate when IRAM has been initialized */ +int iram_ready; +/* Flag used to indicate if dvfs_core is active. */ +int dvfs_core_is_active; + +void mxc_sdma_get_script_info(sdma_script_start_addrs * sdma_script_addr) +{ + /* AP<->BP */ + sdma_script_addr->mxc_sdma_ap_2_ap_addr = ap_2_ap_ADDR; + sdma_script_addr->mxc_sdma_ap_2_bp_addr = -1; + sdma_script_addr->mxc_sdma_bp_2_ap_addr = -1; + sdma_script_addr->mxc_sdma_ap_2_ap_fixed_addr = -1; + + /*misc */ + sdma_script_addr->mxc_sdma_loopback_on_dsp_side_addr = -1; + sdma_script_addr->mxc_sdma_mcu_interrupt_only_addr = -1; + + /* firi */ + sdma_script_addr->mxc_sdma_firi_2_per_addr = -1; + sdma_script_addr->mxc_sdma_firi_2_mcu_addr = -1; + sdma_script_addr->mxc_sdma_per_2_firi_addr = -1; + sdma_script_addr->mxc_sdma_mcu_2_firi_addr = -1; + + /* uart */ + sdma_script_addr->mxc_sdma_uart_2_per_addr = uart_2_per_ADDR; + sdma_script_addr->mxc_sdma_uart_2_mcu_addr = uart_2_mcu_ADDR; + + /* UART SH */ + sdma_script_addr->mxc_sdma_uartsh_2_per_addr = uartsh_2_per_ADDR; + sdma_script_addr->mxc_sdma_uartsh_2_mcu_addr = uartsh_2_mcu_ADDR; + + /* SHP */ + sdma_script_addr->mxc_sdma_per_2_shp_addr = per_2_shp_ADDR; + sdma_script_addr->mxc_sdma_shp_2_per_addr = shp_2_per_ADDR; + sdma_script_addr->mxc_sdma_mcu_2_shp_addr = mcu_2_shp_ADDR; + sdma_script_addr->mxc_sdma_shp_2_mcu_addr = shp_2_mcu_ADDR; + + /* ATA */ + sdma_script_addr->mxc_sdma_mcu_2_ata_addr = mcu_2_ata_ADDR; + sdma_script_addr->mxc_sdma_ata_2_mcu_addr = ata_2_mcu_ADDR; + + /* app */ + sdma_script_addr->mxc_sdma_app_2_per_addr = app_2_per_ADDR; + sdma_script_addr->mxc_sdma_app_2_mcu_addr = app_2_mcu_ADDR; + sdma_script_addr->mxc_sdma_per_2_app_addr = per_2_app_ADDR; + sdma_script_addr->mxc_sdma_mcu_2_app_addr = mcu_2_app_ADDR; + + /* MSHC */ + sdma_script_addr->mxc_sdma_mshc_2_mcu_addr = -1; + sdma_script_addr->mxc_sdma_mcu_2_mshc_addr = -1; + + /* spdif */ + sdma_script_addr->mxc_sdma_spdif_2_mcu_addr = -1; + sdma_script_addr->mxc_sdma_mcu_2_spdif_addr = mcu_2_spdif_ADDR; + + /* IPU */ + sdma_script_addr->mxc_sdma_ext_mem_2_ipu_addr = ext_mem__ipu_ram_ADDR; + + /* DVFS */ + sdma_script_addr->mxc_sdma_dptc_dvfs_addr = -1; + + /* core */ + sdma_script_addr->mxc_sdma_start_addr = (unsigned short *)sdma_code; + sdma_script_addr->mxc_sdma_ram_code_start_addr = RAM_CODE_START_ADDR; + sdma_script_addr->mxc_sdma_ram_code_size = RAM_CODE_SIZE; +} + +static void mxc_nop_release(struct device *dev) +{ + /* Nothing */ +} + +#if defined(CONFIG_W1_MASTER_MXC) || defined(CONFIG_W1_MASTER_MXC_MODULE) +static struct resource w1_resources[] = { + { + .start = MXC_INT_OWIRE, + .flags = IORESOURCE_IRQ, + } +}; + +static struct mxc_w1_config mxc_w1_data = { + .search_rom_accelerator = 1, +}; + +static struct platform_device mxc_w1_devices = { + .name = "mxc_w1", + .dev = { + .release = mxc_nop_release, + .platform_data = &mxc_w1_data, + }, + .num_resources = ARRAY_SIZE(w1_resources), + .resource = w1_resources, + .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_DRV_MXC_V2) || defined(CONFIG_RTC_DRV_MXC_V2_MODULE) +static struct mxc_srtc_platform_data srtc_data = { + .srtc_sec_mode_addr = 0x83F98840, +}; + +static struct resource rtc_resources[] = { + { + .start = SRTC_BASE_ADDR, + .end = SRTC_BASE_ADDR + 0x40, + .flags = IORESOURCE_MEM, + }, + { + .start = MXC_INT_SRTC_NTZ, + .flags = IORESOURCE_IRQ, + }, +}; +static struct platform_device mxc_rtc_device = { + .name = "mxc_rtc", + .id = 0, + .dev = { + .release = mxc_nop_release, + .platform_data = &srtc_data, + }, + .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 + +#if defined(CONFIG_MXC_PWM) +static struct resource pwm_resources[] = { + { + .start = PWM1_BASE_ADDR, + .end = PWM1_BASE_ADDR + 0x14, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device mxc_pwm_device = { + .name = "mxc_pwm", + .id = 0, + .dev = { + .release = mxc_nop_release, + }, + .num_resources = ARRAY_SIZE(pwm_resources), + .resource = pwm_resources, +}; + +static void mxc_init_pwm(void) +{ + printk(KERN_INFO "mxc_pwm_device registered\n"); + if (platform_device_register(&mxc_pwm_device) < 0) + printk(KERN_ERR "registration of mxc_pwm device failed\n"); +} +#else +static void mxc_init_pwm(void) +{ + +} +#endif + +#if defined(CONFIG_BACKLIGHT_PWM) +static struct platform_pwm_backlight_data mxc_pwm_backlight_data = { + .pwm_id = 0, + .max_brightness = 255, + .dft_brightness = 128, + .pwm_period_ns = 78770, +}; + +static struct platform_device mxc_pwm_backlight_device = { + .name = "pwm-backlight", + .id = -1, + .dev = { + .release = mxc_nop_release, + .platform_data = &mxc_pwm_backlight_data, + }, +}; + +static void mxc_init_pwm_backlight(void) +{ + printk(KERN_INFO "pwm-backlight device registered\n"); + if (platform_device_register(&mxc_pwm_backlight_device) < 0) + printk(KERN_ERR + "registration of pwm-backlight device failed\n"); +} +#else +static void mxc_init_pwm_backlight(void) +{ + +} +#endif + +#if defined(CONFIG_MXC_IPU_V3) || defined(CONFIG_MXC_IPU_V3_MODULE) +static struct mxc_ipu_config mxc_ipu_data = { + .rev = 1, +}; + +static struct resource ipu_resources[] = { + { + .start = IPU_CTRL_BASE_ADDR, + .end = IPU_CTRL_BASE_ADDR + SZ_512M, + .flags = IORESOURCE_MEM, + }, + { + .start = MXC_INT_IPU_SYN, + .flags = IORESOURCE_IRQ, + }, + { + .start = MXC_INT_IPU_ERR, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device mxc_ipu_device = { + .name = "mxc_ipu", + .id = -1, + .dev = { + .release = mxc_nop_release, + .platform_data = &mxc_ipu_data, + }, + .num_resources = ARRAY_SIZE(ipu_resources), + .resource = ipu_resources, +}; + +static void mxc_init_ipu(void) +{ + u32 reg_hsc_mcd = IO_ADDRESS(MIPI_HSC_BASE_ADDR); + u32 reg_hsc_mxt_conf = IO_ADDRESS(MIPI_HSC_BASE_ADDR + 0x800); + struct clk *clk; + uint32_t temp; + + /* Select IPUv3 h/w version */ + if (cpu_is_mx51_rev(CHIP_REV_2_0) > 0) + mxc_ipu_data.rev = 2; + + mxc_ipu_data.di_clk[1] = clk_get(NULL, "ipu_di1_clk"); + clk = clk_get(NULL, "tve_clk"); + clk_set_parent(mxc_ipu_data.di_clk[1], clk); + clk_put(clk); + + /* Temporarily setup MIPI module to legacy mode */ + clk = clk_get(NULL, "mipi_hsp_clk"); + if (!IS_ERR(clk)) { + clk_enable(clk); + + /* Temporarily setup MIPI module to legacy mode */ + __raw_writel(0xF00, reg_hsc_mcd); + + /* CSI mode reserved*/ + temp = __raw_readl(reg_hsc_mxt_conf); + __raw_writel(temp | 0x0FF, reg_hsc_mxt_conf); + + if (cpu_is_mx51_rev(CHIP_REV_2_0) > 0) { + temp = __raw_readl(reg_hsc_mxt_conf); + __raw_writel(temp | 0x10000, reg_hsc_mxt_conf); + } + + clk_disable(clk); + clk_put(clk); + } + platform_device_register(&mxc_ipu_device); +} +#else +static inline void mxc_init_ipu(void) +{ +} +#endif + +#if defined(CONFIG_MXC_VPU) || defined(CONFIG_MXC_VPU_MODULE) +static struct resource vpu_resources[] = { + [0] = { + .start = VPU_IRAM_BASE_ADDR, + .end = VPU_IRAM_BASE_ADDR + VPU_IRAM_SIZE, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IO_ADDRESS(SRC_BASE_ADDR), + .end = IO_ADDRESS(SRC_BASE_ADDR), + .flags = IORESOURCE_MEM, + }, +}; + +/*! Platform Data for MXC VPU */ +static struct platform_device mxcvpu_device = { + .name = "mxc_vpu", + .id = 0, + .dev = { + .release = mxc_nop_release, + }, + .num_resources = ARRAY_SIZE(vpu_resources), + .resource = vpu_resources, +}; + +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 + +/*! + * 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 +#define SCM_RD_DELAY 1000000 /* in nanoseconds */ +#define SEC_TO_NANOSEC 1000000000 /*Second to nanoseconds */ +static inline void mxc_init_scc(void) +{ + uint32_t reg_value; + uint32_t reg_mask = 0; + uint8_t *UMID_base; + uint32_t *MAP_base; + uint8_t i; + uint32_t partition_no; + uint32_t scc_partno; + void *scm_ram_base; + void *scc_base; + uint8_t iram_partitions = 16; + struct timespec stime; + struct timespec curtime; + long scm_rd_timeout = 0; + long cur_ns = 0; + long start_ns = 0; + + if (cpu_is_mx51_rev(CHIP_REV_2_0) < 0) + iram_partitions = 12; + + scc_base = ioremap((uint32_t) SCC_BASE_ADDR, 0x140); + if (scc_base == NULL) { + printk(KERN_ERR "FAILED TO MAP IRAM REGS\n"); + return; + } + scm_ram_base = ioremap((uint32_t) IRAM_BASE_ADDR, IRAM_SIZE); + if (scm_ram_base == NULL) { + printk(KERN_ERR "FAILED TO MAP IRAM\n"); + return; + } + + /* Wait for any running SCC operations to finish or fail */ + getnstimeofday(&stime); + do { + reg_value = __raw_readl(scc_base + SCM_STATUS_REG); + getnstimeofday(&curtime); + if (curtime.tv_nsec > stime.tv_nsec) + scm_rd_timeout = curtime.tv_nsec - stime.tv_nsec; + else{ + /*Converted second to nanosecond and add to + nsec when current nanosec is less than + start time nanosec.*/ + cur_ns = (curtime.tv_sec * SEC_TO_NANOSEC) + + curtime.tv_nsec; + start_ns = (stime.tv_sec * SEC_TO_NANOSEC) + + stime.tv_nsec; + scm_rd_timeout = cur_ns - start_ns; + } + } while (((reg_value & SCM_STATUS_SRS_MASK) != SCM_STATUS_SRS_READY) + && ((reg_value & SCM_STATUS_SRS_MASK) != SCM_STATUS_SRS_FAIL)); + + /* Check for failures */ + if ((reg_value & SCM_STATUS_SRS_MASK) != SCM_STATUS_SRS_READY) { + /* Special message for bad secret key fuses */ + if (reg_value & SCM_STATUS_KST_BAD_KEY) + printk(KERN_ERR "INVALID SCC KEY FUSE PATTERN\n"); + else + printk(KERN_ERR "SECURE RAM FAILURE\n"); + + iounmap(scm_ram_base); + iounmap(scc_base); + return; + } + + scm_rd_timeout = 0; + /* Release final two partitions for SCC2 driver */ + scc_partno = iram_partitions - (SCC_IRAM_SIZE / SZ_8K); + for (partition_no = scc_partno; partition_no < iram_partitions; + partition_no++) { + reg_value = (((partition_no << SCM_ZCMD_PART_SHIFT) & + SCM_ZCMD_PART_MASK) | ((0x03 << SCM_ZCMD_CCMD_SHIFT) & + SCM_ZCMD_CCMD_MASK)); + __raw_writel(reg_value, scc_base + SCM_ZCMD_REG); + udelay(1); + /* Wait for zeroization to complete */ + getnstimeofday(&stime); + do { + reg_value = __raw_readl(scc_base + SCM_STATUS_REG); + getnstimeofday(&curtime); + if (curtime.tv_nsec > stime.tv_nsec) + scm_rd_timeout = curtime.tv_nsec - + stime.tv_nsec; + else { + /*Converted second to nanosecond and add to + nsec when current nanosec is less than + start time nanosec.*/ + cur_ns = (curtime.tv_sec * SEC_TO_NANOSEC) + + curtime.tv_nsec; + start_ns = (stime.tv_sec * SEC_TO_NANOSEC) + + stime.tv_nsec; + scm_rd_timeout = cur_ns - start_ns; + } + } while (((reg_value & SCM_STATUS_SRS_MASK) != + SCM_STATUS_SRS_READY) && ((reg_value & SCM_STATUS_SRS_MASK) != + SCM_STATUS_SRS_FAIL) && (scm_rd_timeout <= SCM_RD_DELAY)); + + if (scm_rd_timeout > SCM_RD_DELAY) + printk(KERN_ERR "SCM Status Register Read timeout" + "for Partition No:%d", partition_no); + + if ((reg_value & SCM_STATUS_SRS_MASK) != SCM_STATUS_SRS_READY) + break; + } + + /*Check all expected partitions released */ + reg_value = __raw_readl(scc_base + SCM_PART_OWNERS_REG); + if ((reg_value & reg_mask) != 0) { + printk(KERN_ERR "FAILED TO RELEASE IRAM PARTITION\n"); + iounmap(scm_ram_base); + iounmap(scc_base); + return; + } + reg_mask = 0; + scm_rd_timeout = 0; + /* Allocate remaining partitions for general use */ + for (partition_no = 0; partition_no < scc_partno; partition_no++) { + /* Supervisor mode claims a partition for it's own use + by writing zero to SMID register.*/ + __raw_writel(0, scc_base + (SCM_SMID0_REG + 8 * partition_no)); + + /* Wait for any zeroization to complete */ + getnstimeofday(&stime); + do { + reg_value = __raw_readl(scc_base + SCM_STATUS_REG); + getnstimeofday(&curtime); + if (curtime.tv_nsec > stime.tv_nsec) + scm_rd_timeout = curtime.tv_nsec - + stime.tv_nsec; + else{ + /*Converted second to nanosecond and add to + nsec when current nanosec is less than + start time nanosec.*/ + cur_ns = (curtime.tv_sec * SEC_TO_NANOSEC) + + curtime.tv_nsec; + start_ns = (stime.tv_sec * SEC_TO_NANOSEC) + + stime.tv_nsec; + scm_rd_timeout = cur_ns - start_ns; + } + } while (((reg_value & SCM_STATUS_SRS_MASK) != + SCM_STATUS_SRS_READY) && ((reg_value & SCM_STATUS_SRS_MASK) != + SCM_STATUS_SRS_FAIL) && (scm_rd_timeout <= SCM_RD_DELAY)); + + if (scm_rd_timeout > SCM_RD_DELAY) + printk(KERN_ERR "SCM Status Register Read timeout" + "for Partition No:%d", partition_no); + + if ((reg_value & SCM_STATUS_SRS_MASK) != SCM_STATUS_SRS_READY) + break; + /* Set UMID=0 and permissions for universal data + read/write access */ + MAP_base = scm_ram_base + (partition_no * 0x2000); + UMID_base = (uint8_t *) MAP_base + 0x10; + for (i = 0; i < 16; i++) + UMID_base[i] = 0; + + MAP_base[0] = (SCM_PERM_NO_ZEROIZE | SCM_PERM_HD_SUP_DISABLE | + SCM_PERM_HD_READ | SCM_PERM_HD_WRITE | + SCM_PERM_HD_EXECUTE | SCM_PERM_TH_READ | + SCM_PERM_TH_WRITE); + reg_mask |= (3 << (2 * (partition_no))); + } + + /* Check all expected partitions allocated */ + reg_value = __raw_readl(scc_base + SCM_PART_OWNERS_REG); + if ((reg_value & reg_mask) != reg_mask) { + printk(KERN_ERR "FAILED TO ACQUIRE IRAM PARTITION\n"); + iounmap(scm_ram_base); + iounmap(scc_base); + return; + } + + iounmap(scm_ram_base); + iounmap(scc_base); + printk(KERN_INFO "IRAM READY\n"); + iram_ready = 1; +} +#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, + }, +}; + +extern void mx51_babbage_gpio_spi_chipselect_active(int cspi_mode, int status, + int chipselect); +extern void mx51_babbage_gpio_spi_chipselect_inactive(int cspi_mode, int status, + int chipselect); +/*! Platform Data for MXC CSPI1 */ +static struct mxc_spi_master mxcspi1_data = { + .maxchipselect = 4, + .spi_version = 23, +}; + +/*! 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 = 23, +}; + +/*! 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_CSPI, + .end = MXC_INT_CSPI, + .flags = IORESOURCE_IRQ, + }, +}; + +/*! Platform Data for MXC CSPI3 */ +static struct mxc_spi_master mxcspi3_data = { + .maxchipselect = 4, + .spi_version = 7, +}; + +/*! 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 */ + +void __init mxc_init_spi(void) +{ + /* SPBA configuration for CSPI2 - MCU is set */ + spba_take_ownership(SPBA_CSPI1, SPBA_MASTER_A); +#ifdef CONFIG_SPI_MXC_SELECT1 + if (machine_is_mx51_babbage()) { + mxcspi1_data.chipselect_active = + mx51_babbage_gpio_spi_chipselect_active; + mxcspi1_data.chipselect_inactive = + mx51_babbage_gpio_spi_chipselect_inactive; + } + if (platform_device_register(&mxcspi1_device) < 0) + printk(KERN_ERR "Error: 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 "Error: 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 "Error: Registering the SPI Controller_3\n"); +#endif /* CONFIG_SPI_MXC_SELECT3 */ +} +#else +void __init mxc_init_spi(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 = I2C1_BASE_ADDR, + .end = I2C1_BASE_ADDR + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = MXC_INT_I2C1, + .end = MXC_INT_I2C1, + .flags = IORESOURCE_IRQ, + }, +}; + +/*! Platform Data for MXC I2C */ +static struct mxc_i2c_platform_data mxci2c1_data = { + .i2c_clk = 400000, +}; +#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 = 400000, +}; +#endif + +#ifdef CONFIG_I2C_MXC_SELECT3 +/*! + * Resource definition for the I2C3 + */ +static struct resource mxci2c3_resources[] = { + [0] = { + .start = I2C3_BASE_ADDR, + .end = I2C3_BASE_ADDR + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = MXC_INT_I2C3, + .end = MXC_INT_I2C3, + .flags = IORESOURCE_IRQ, + }, +}; + +/*! Platform Data for MXC I2C */ +static struct mxc_i2c_platform_data mxci2c3_data = { + .i2c_clk = 100000, +}; +#endif + +/*! Device Definition for MXC I2C1 */ +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 +// Note: AG: The CCWMX51 has not got a third standard I2C port. +#ifdef CONFIG_I2C_MXC_SELECT3 + { + .name = "mxc_i2c", + .id = 2, + .dev = { + .release = mxc_nop_release, + .platform_data = &mxci2c3_data, + }, + .num_resources = ARRAY_SIZE(mxci2c3_resources), + .resource = mxci2c3_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 + +#if defined(CONFIG_I2C_MXC_HS) || defined(CONFIG_I2C_MXC_HS_MODULE) +static struct resource mxci2c_hs_resources[] = { + [0] = { + .start = HSI2C_DMA_BASE_ADDR, + .end = HSI2C_DMA_BASE_ADDR + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = MXC_INT_HS_I2C, + .end = MXC_INT_HS_I2C, + .flags = IORESOURCE_IRQ, + }, +}; + +/*! Platform Data for MXC I2C */ +static struct mxc_i2c_platform_data mxci2c_hs_data = { + .i2c_clk = 400000, +}; + +static struct platform_device mxci2c_hs_device = { + .name = "mxc_i2c_hs", + .id = 3, + .dev = { + .release = mxc_nop_release, + .platform_data = &mxci2c_hs_data, + }, + .num_resources = ARRAY_SIZE(mxci2c_hs_resources), + .resource = mxci2c_hs_resources +}; + +static inline void mxc_init_i2c_hs(void) +{ + if (platform_device_register(&mxci2c_hs_device) < 0) + dev_err(&mxci2c_hs_device.dev, + "Unable to register High Speed I2C device\n"); +} +#else +static inline void mxc_init_i2c_hs(void) +{ +} +#endif + +#if defined(CONFIG_FB_MXC_TVOUT_TVE) || defined(CONFIG_FB_MXC_TVOUT_TVE_MODULE) +static struct resource tve_resources[] = { + { + .start = TVE_BASE_ADDR, + .end = TVE_BASE_ADDR + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, + { + .start = MXC_INT_TVE, + .flags = IORESOURCE_IRQ, + }, +}; +static struct tve_platform_data tve_data = { + .dac_reg = "VVIDEO", + .dig_reg = "VDIG", +}; + +static struct platform_device mxc_tve_device = { + .name = "tve", + .dev = { + .platform_data = &tve_data, + .release = mxc_nop_release, + }, + .num_resources = ARRAY_SIZE(tve_resources), + .resource = tve_resources, +}; + +void __init mxc_init_tve(void) +{ + platform_device_register(&mxc_tve_device); +} +#else +static inline void mxc_init_tve(void) +{ +} +#endif + +/*! + * Resource definition for the DVFS CORE + */ +static struct resource dvfs_core_resources[] = { + [0] = { + .start = MXC_DVFS_CORE_BASE, + .end = MXC_DVFS_CORE_BASE + 4 * SZ_16 - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = MXC_INT_GPC1, + .end = MXC_INT_GPC1, + .flags = IORESOURCE_IRQ, + }, +}; + +/*! Platform Data for DVFS CORE */ +struct mxc_dvfs_platform_data dvfs_core_data = { + .reg_id = "SW1", + .clk1_id = "cpu_clk", + .clk2_id = "gpc_dvfs_clk", + .gpc_cntr_reg_addr = MXC_GPC_CNTR, + .gpc_vcr_reg_addr = MXC_GPC_VCR, + .ccm_cdcr_reg_addr = (unsigned int)MXC_CCM_CDCR, + .ccm_cacrr_reg_addr = (unsigned int)MXC_CCM_CACRR, + .ccm_cdhipr_reg_addr = (unsigned int)MXC_CCM_CDHIPR, + .dvfs_thrs_reg_addr = MXC_DVFSTHRS, + .dvfs_coun_reg_addr = MXC_DVFSCOUN, + .dvfs_emac_reg_addr = MXC_DVFSEMAC, + .dvfs_cntr_reg_addr = MXC_DVFSCNTR, + .prediv_mask = 0x1F800, + .prediv_offset = 11, + .prediv_val = 3, + .div3ck_mask = 0xE0000000, + .div3ck_offset = 29, + .div3ck_val = 2, + .emac_val = 0x08, + .upthr_val = 25, + .dnthr_val = 9, + .pncthr_val = 33, + .upcnt_val = 10, + .dncnt_val = 10, + .delay_time = 30, + .num_wp = 3, +}; + +/*! Device Definition for MXC DVFS core */ +static struct platform_device mxc_dvfs_core_device = { + .name = "mxc_dvfs_core", + .id = 0, + .dev = { + .release = mxc_nop_release, + .platform_data = &dvfs_core_data, + }, + .num_resources = ARRAY_SIZE(dvfs_core_resources), + .resource = dvfs_core_resources, +}; + +static inline void mxc_init_dvfs(void) +{ + if (platform_device_register(&mxc_dvfs_core_device) < 0) + dev_err(&mxc_dvfs_core_device.dev, + "Unable to register DVFS core device\n"); +} + +struct mxc_gpio_port mxc_gpio_ports[GPIO_PORT_NUM] = { + [0] = { + .chip.label = "gpio-0", + .base = IO_ADDRESS(GPIO1_BASE_ADDR), + .irq = MXC_INT_GPIO1_LOW, + .irq_high = MXC_INT_GPIO1_HIGH, + .virtual_irq_start = MXC_GPIO_INT_BASE + }, + [1] = { + .chip.label = "gpio-1", + .base = IO_ADDRESS(GPIO2_BASE_ADDR), + .irq = MXC_INT_GPIO2_LOW, + .irq_high = MXC_INT_GPIO2_HIGH, + .virtual_irq_start = MXC_GPIO_INT_BASE + GPIO_NUM_PIN * 1 + }, + [2] = { + .chip.label = "gpio-2", + .base = IO_ADDRESS(GPIO3_BASE_ADDR), + .irq = MXC_INT_GPIO3_LOW, + .irq_high = MXC_INT_GPIO3_HIGH, + .virtual_irq_start = MXC_GPIO_INT_BASE + GPIO_NUM_PIN * 2 + }, + [3] = { + .chip.label = "gpio-3", + .base = IO_ADDRESS(GPIO4_BASE_ADDR), + .irq = MXC_INT_GPIO4_LOW, + .irq_high = MXC_INT_GPIO4_HIGH, + .virtual_irq_start = MXC_GPIO_INT_BASE + GPIO_NUM_PIN * 3 + } +}; + +int __init mxc_register_gpios(void) +{ + return mxc_gpio_init(mxc_gpio_ports, ARRAY_SIZE(mxc_gpio_ports)); +} + +static struct platform_device mxc_dma_device = { + .name = "mxc_dma", + .id = 0, + .dev = { + .release = mxc_nop_release, + }, +}; + +static inline void mxc_init_dma(void) +{ + (void)platform_device_register(&mxc_dma_device); +} + +static struct resource spdif_resources[] = { + { + .start = SPDIF_BASE_ADDR, + .end = SPDIF_BASE_ADDR + 0x50, + .flags = IORESOURCE_MEM, + }, +}; + +static struct mxc_spdif_platform_data mxc_spdif_data = { + .spdif_tx = 1, + .spdif_rx = 0, + .spdif_clk_44100 = 0, /* spdif_ext_clk source for 44.1KHz */ + .spdif_clk_48000 = 7, /* audio osc source */ + .spdif_clkid = 0, + .spdif_clk = NULL, /* spdif bus clk */ +}; + +static struct platform_device mxc_alsa_spdif_device = { + .name = "mxc_alsa_spdif", + .id = 0, + .dev = { + .release = mxc_nop_release, + .platform_data = &mxc_spdif_data, + }, + .num_resources = ARRAY_SIZE(spdif_resources), + .resource = spdif_resources, +}; + +static inline void mxc_init_spdif(void) +{ + mxc_spdif_data.spdif_core_clk = clk_get(NULL, "spdif_xtal_clk"); + clk_put(mxc_spdif_data.spdif_core_clk); + platform_device_register(&mxc_alsa_spdif_device); +} + +static struct platform_device mx51_lpmode_device = { + .name = "mx51_lpmode", + .id = 0, + .dev = { + .release = mxc_nop_release, + }, +}; + +static inline void mx51_init_lpmode(void) +{ + (void)platform_device_register(&mx51_lpmode_device); +} + +static struct platform_device busfreq_device = { + .name = "busfreq", + .id = 0, + .dev = { + .release = mxc_nop_release, + }, +}; + +static inline void mxc_init_busfreq(void) +{ + (void)platform_device_register(&busfreq_device); +} + +static struct platform_device sdram_autogating_device = { + .name = "sdram_autogating", + .id = 0, + .dev = { + .release = mxc_nop_release, + }, +}; + +static inline void mxc_init_sdram_autogating(void) +{ + (void)platform_device_register(&sdram_autogating_device); +} + +#if defined(CONFIG_MXC_IIM) || defined(CONFIG_MXC_IIM_MODULE) +static struct resource mxc_iim_resources[] = { + { + .start = IIM_BASE_ADDR, + .end = IIM_BASE_ADDR + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device mxc_iim_device = { + .name = "mxc_iim", + .id = 0, + .dev = { + .release = mxc_nop_release, + }, + .num_resources = ARRAY_SIZE(mxc_iim_resources), + .resource = mxc_iim_resources +}; + +static inline void mxc_init_iim(void) +{ + if (platform_device_register(&mxc_iim_device) < 0) + dev_err(&mxc_iim_device.dev, + "Unable to register mxc iim device\n"); +} +#else +static inline void mxc_init_iim(void) +{ +} +#endif + +static struct resource mxc_gpu_resources[] = { + [0] = { + .start = MXC_INT_GPU2_IRQ, + .end = MXC_INT_GPU2_IRQ, + .name = "gpu_2d_irq", + .flags = IORESOURCE_IRQ,}, + [1] = { + .start = MXC_INT_GPU, + .end = MXC_INT_GPU, + .name = "gpu_3d_irq", + .flags = IORESOURCE_IRQ,}, +}; + +static struct platform_device gpu_device = { + .name = "mxc_gpu", + .id = 0, + .dev = { + .release = mxc_nop_release, + }, + .num_resources = ARRAY_SIZE(mxc_gpu_resources), + .resource = mxc_gpu_resources, +}; + +static void __init mxc_init_gpu(void) +{ + platform_device_register(&gpu_device); +} + +static struct resource mxc_gpu2d_resources[] = { + { + .start = GPU2D_BASE_ADDR, + .end = GPU2D_BASE_ADDR + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, + { + .flags = IORESOURCE_MEM, + }, + { + .flags = IORESOURCE_MEM, + }, +}; + +#if defined(CONFIG_UIO_PDRV_GENIRQ) || defined(CONFIG_UIO_PDRV_GENIRQ_MODULE) +static struct clk *gpu_clk; + +int gpu2d_open(struct uio_info *info, struct inode *inode) +{ + gpu_clk = clk_get(NULL, "gpu2d_clk"); + if (IS_ERR(gpu_clk)) + return PTR_ERR(gpu_clk); + + return clk_enable(gpu_clk); +} + +int gpu2d_release(struct uio_info *info, struct inode *inode) +{ + if (IS_ERR(gpu_clk)) + return PTR_ERR(gpu_clk); + + clk_disable(gpu_clk); + clk_put(gpu_clk); + return 0; +} + +static int gpu2d_mmap(struct uio_info *info, struct vm_area_struct *vma) +{ + int mi = vma->vm_pgoff; + if (mi < 0) + return -EINVAL; + + vma->vm_flags |= VM_IO | VM_RESERVED; + vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); + + return remap_pfn_range(vma, + vma->vm_start, + info->mem[mi].addr >> PAGE_SHIFT, + vma->vm_end - vma->vm_start, + vma->vm_page_prot); +} + +static struct uio_info gpu2d_info = { + .name = "imx_gpu2d", + .version = "1", + .irq = MXC_INT_GPU2_IRQ, + .open = gpu2d_open, + .release = gpu2d_release, + .mmap = gpu2d_mmap, +}; + +static struct platform_device mxc_gpu2d_device = { + .name = "uio_pdrv_genirq", + .dev = { + .release = mxc_nop_release, + .platform_data = &gpu2d_info, + .coherent_dma_mask = 0xFFFFFFFF, + }, + .num_resources = ARRAY_SIZE(mxc_gpu2d_resources), + .resource = mxc_gpu2d_resources, +}; + +static inline void mxc_init_gpu2d(void) +{ + dma_alloc_coherent(&mxc_gpu2d_device.dev, SZ_8K, &mxc_gpu2d_resources[1].start, GFP_DMA); + mxc_gpu2d_resources[1].end = mxc_gpu2d_resources[1].start + SZ_8K - 1; + + dma_alloc_coherent(&mxc_gpu2d_device.dev, 88 * SZ_1K, &mxc_gpu2d_resources[2].start, GFP_DMA); + mxc_gpu2d_resources[2].end = mxc_gpu2d_resources[2].start + (88 * SZ_1K) - 1; + + platform_device_register(&mxc_gpu2d_device); +} +#else +static inline void mxc_init_gpu2d(void) +{ +} +#endif + +int __init mxc_init_devices(void) +{ + mxc_init_wdt(); + mxc_init_spi(); + mxc_init_i2c(); + mxc_init_i2c_hs(); + mxc_init_rtc(); + mxc_init_scc(); + mxc_init_dma(); + mxc_init_owire(); + mxc_init_ipu(); + mxc_init_vpu(); + mxc_init_spdif(); + mxc_init_tve(); + mx51_init_lpmode(); + mxc_init_busfreq(); + mxc_init_sdram_autogating(); + mxc_init_dvfs(); + mxc_init_iim(); + mxc_init_gpu(); + mxc_init_gpu2d(); + mxc_init_pwm(); + mxc_init_pwm_backlight(); + return 0; +} diff --git a/arch/arm/mach-mx51/dma.c b/arch/arm/mach-mx51/dma.c new file mode 100644 index 000000000000..a27d7e2a2349 --- /dev/null +++ b/arch/arm/mach-mx51/dma.c @@ -0,0 +1,666 @@ +/* + * Copyright 2008-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/init.h> +#include <linux/device.h> +#include <asm/dma.h> +#include <mach/hardware.h> + +#include "serial.h" + +#define MXC_MMC_BUFFER_ACCESS 0x20 +#define MXC_SDHC_MMC_WML 64 +#define MXC_SDHC_SD_WML 256 +#define MXC_SSI_TX0_REG 0x0 +#define MXC_SSI_TX1_REG 0x4 +#define MXC_SSI_RX0_REG 0x8 +#define MXC_SSI_RX1_REG 0xC +#define MXC_SSI_TXFIFO_WML 0x4 +#define MXC_SSI_RXFIFO_WML 0x6 +#define MXC_SPDIF_TXFIFO_WML 0x8 +#define MXC_SPDIF_TX_REG 0x2C + +typedef struct mxc_sdma_info_entry_s { + mxc_dma_device_t device; + mxc_sdma_channel_params_t *chnl_info; +} mxc_sdma_info_entry_t; + +static mxc_sdma_channel_params_t mxc_sdma_uart1_rx_params = { + .chnl_params = { + .watermark_level = UART1_UFCR_RXTL, + .per_address = UART1_BASE_ADDR, + .peripheral_type = UART, + .transfer_type = per_2_emi, + .event_id = DMA_REQ_UART1_RX, + .bd_number = 32, + .word_size = TRANSFER_8BIT, + }, + .channel_num = MXC_DMA_CHANNEL_UART1_RX, + .chnl_priority = MXC_SDMA_DEFAULT_PRIORITY, +}; + +static mxc_sdma_channel_params_t mxc_sdma_uart1_tx_params = { + .chnl_params = { + .watermark_level = UART1_UFCR_TXTL, + .per_address = UART1_BASE_ADDR + MXC_UARTUTXD, + .peripheral_type = UART, + .transfer_type = emi_2_per, + .event_id = DMA_REQ_UART1_TX, + .bd_number = 32, + .word_size = TRANSFER_8BIT, + }, + .channel_num = MXC_DMA_CHANNEL_UART1_TX, + .chnl_priority = MXC_SDMA_DEFAULT_PRIORITY, +}; + +static mxc_sdma_channel_params_t mxc_sdma_uart2_rx_params = { + .chnl_params = { + .watermark_level = UART2_UFCR_RXTL, + .per_address = UART2_BASE_ADDR, + .peripheral_type = UART, + .transfer_type = per_2_emi, + .event_id = DMA_REQ_UART2_RX, + .bd_number = 32, + .word_size = TRANSFER_8BIT, + }, + .channel_num = MXC_DMA_CHANNEL_UART2_RX, + .chnl_priority = MXC_SDMA_DEFAULT_PRIORITY, +}; + +static mxc_sdma_channel_params_t mxc_sdma_uart2_tx_params = { + .chnl_params = { + .watermark_level = UART2_UFCR_TXTL, + .per_address = UART2_BASE_ADDR + MXC_UARTUTXD, + .peripheral_type = UART, + .transfer_type = emi_2_per, + .event_id = DMA_REQ_UART2_TX, + .bd_number = 32, + .word_size = TRANSFER_8BIT, + }, + .channel_num = MXC_DMA_CHANNEL_UART2_TX, + .chnl_priority = MXC_SDMA_DEFAULT_PRIORITY, +}; + +static mxc_sdma_channel_params_t mxc_sdma_uart3_rx_params = { + .chnl_params = { + .watermark_level = UART3_UFCR_RXTL, + .per_address = UART3_BASE_ADDR, + .peripheral_type = UART_SP, + .transfer_type = per_2_emi, + .event_id = DMA_REQ_UART3_RX, + .bd_number = 32, + .word_size = TRANSFER_8BIT, + }, + .channel_num = MXC_DMA_CHANNEL_UART3_RX, + .chnl_priority = MXC_SDMA_DEFAULT_PRIORITY, +}; + +static mxc_sdma_channel_params_t mxc_sdma_uart3_tx_params = { + .chnl_params = { + .watermark_level = UART3_UFCR_TXTL, + .per_address = UART3_BASE_ADDR + MXC_UARTUTXD, + .peripheral_type = UART_SP, + .transfer_type = emi_2_per, + .event_id = DMA_REQ_UART3_TX, + .bd_number = 32, + .word_size = TRANSFER_8BIT, + }, + .channel_num = MXC_DMA_CHANNEL_UART3_TX, + .chnl_priority = MXC_SDMA_DEFAULT_PRIORITY, +}; + +static mxc_sdma_channel_params_t mxc_sdma_mmc1_width1_params = { + .chnl_params = { + .watermark_level = MXC_SDHC_MMC_WML, + .per_address = + MMC_SDHC1_BASE_ADDR + MXC_MMC_BUFFER_ACCESS, + .peripheral_type = MMC, + .transfer_type = per_2_emi, + .event_id = DMA_REQ_SDHC1, + .bd_number = 32, + .word_size = TRANSFER_32BIT, + }, + .channel_num = MXC_DMA_CHANNEL_MMC1, + .chnl_priority = MXC_SDMA_DEFAULT_PRIORITY, +}; + +static mxc_sdma_channel_params_t mxc_sdma_mmc1_width4_params = { + .chnl_params = { + .watermark_level = MXC_SDHC_SD_WML, + .per_address = + MMC_SDHC1_BASE_ADDR + MXC_MMC_BUFFER_ACCESS, + .peripheral_type = MMC, + .transfer_type = per_2_emi, + .event_id = DMA_REQ_SDHC1, + .bd_number = 32, + .word_size = TRANSFER_32BIT, + }, + .channel_num = MXC_DMA_CHANNEL_MMC1, + .chnl_priority = MXC_SDMA_DEFAULT_PRIORITY, +}; + +static mxc_sdma_channel_params_t mxc_sdma_mmc2_width1_params = { + .chnl_params = { + .watermark_level = MXC_SDHC_MMC_WML, + .per_address = + MMC_SDHC2_BASE_ADDR + MXC_MMC_BUFFER_ACCESS, + .peripheral_type = MMC, + .transfer_type = per_2_emi, + .event_id = DMA_REQ_SDHC2, + .bd_number = 32, + .word_size = TRANSFER_32BIT, + }, + .channel_num = MXC_DMA_CHANNEL_MMC2, + .chnl_priority = MXC_SDMA_DEFAULT_PRIORITY, +}; + +static mxc_sdma_channel_params_t mxc_sdma_mmc2_width4_params = { + .chnl_params = { + .watermark_level = MXC_SDHC_SD_WML, + .per_address = + MMC_SDHC2_BASE_ADDR + MXC_MMC_BUFFER_ACCESS, + .peripheral_type = MMC, + .transfer_type = per_2_emi, + .event_id = DMA_REQ_SDHC2, + .bd_number = 32, + .word_size = TRANSFER_32BIT, + }, + .channel_num = MXC_DMA_CHANNEL_MMC2, + .chnl_priority = MXC_SDMA_DEFAULT_PRIORITY, +}; + +static mxc_sdma_channel_params_t mxc_sdma_ssi1_8bit_rx0_params = { + .chnl_params = { + .watermark_level = MXC_SSI_RXFIFO_WML, + .per_address = SSI1_BASE_ADDR + MXC_SSI_RX0_REG, + .peripheral_type = SSI, + .transfer_type = per_2_emi, + .event_id = DMA_REQ_SSI1_RX1, + .bd_number = 32, + .word_size = TRANSFER_8BIT, + }, + .channel_num = MXC_DMA_CHANNEL_SSI1_RX, + .chnl_priority = 2, +}; + +static mxc_sdma_channel_params_t mxc_sdma_ssi1_8bit_tx0_params = { + .chnl_params = { + .watermark_level = MXC_SSI_TXFIFO_WML, + .per_address = SSI1_BASE_ADDR + MXC_SSI_TX0_REG, + .peripheral_type = SSI, + .transfer_type = emi_2_per, + .event_id = DMA_REQ_SSI1_TX1, + .bd_number = 32, + .word_size = TRANSFER_8BIT, + }, + .channel_num = MXC_DMA_CHANNEL_SSI1_TX, + .chnl_priority = 2, +}; + +static mxc_sdma_channel_params_t mxc_sdma_ssi1_16bit_rx0_params = { + .chnl_params = { + .watermark_level = MXC_SSI_RXFIFO_WML, + .per_address = SSI1_BASE_ADDR + MXC_SSI_RX0_REG, + .peripheral_type = SSI, + .transfer_type = per_2_emi, + .event_id = DMA_REQ_SSI1_RX1, + .bd_number = 32, + .word_size = TRANSFER_16BIT, + }, + .channel_num = MXC_DMA_CHANNEL_SSI1_RX, + .chnl_priority = 2, +}; + +static mxc_sdma_channel_params_t mxc_sdma_ssi1_16bit_tx0_params = { + .chnl_params = { + .watermark_level = MXC_SSI_TXFIFO_WML, + .per_address = SSI1_BASE_ADDR + MXC_SSI_TX0_REG, + .peripheral_type = SSI, + .transfer_type = emi_2_per, + .event_id = DMA_REQ_SSI1_TX1, + .bd_number = 32, + .word_size = TRANSFER_16BIT, + }, + .channel_num = MXC_DMA_CHANNEL_SSI1_TX, + .chnl_priority = 2, +}; + +static mxc_sdma_channel_params_t mxc_sdma_ssi1_24bit_rx0_params = { + .chnl_params = { + .watermark_level = MXC_SSI_RXFIFO_WML, + .per_address = SSI1_BASE_ADDR + MXC_SSI_RX0_REG, + .peripheral_type = SSI, + .transfer_type = per_2_emi, + .event_id = DMA_REQ_SSI1_RX1, + .bd_number = 32, + .word_size = TRANSFER_32BIT, + }, + .channel_num = MXC_DMA_CHANNEL_SSI1_RX, + .chnl_priority = 2, +}; + +static mxc_sdma_channel_params_t mxc_sdma_ssi1_24bit_tx0_params = { + .chnl_params = { + .watermark_level = MXC_SSI_TXFIFO_WML, + .per_address = SSI1_BASE_ADDR + MXC_SSI_TX0_REG, + .peripheral_type = SSI, + .transfer_type = emi_2_per, + .event_id = DMA_REQ_SSI1_TX1, + .bd_number = 32, + .word_size = TRANSFER_32BIT, + }, + .channel_num = MXC_DMA_CHANNEL_SSI1_TX, + .chnl_priority = 2, +}; + +static mxc_sdma_channel_params_t mxc_sdma_ssi1_8bit_rx1_params = { + .chnl_params = { + .watermark_level = MXC_SSI_RXFIFO_WML, + .per_address = SSI1_BASE_ADDR + MXC_SSI_RX1_REG, + .peripheral_type = SSI, + .transfer_type = per_2_emi, + .event_id = DMA_REQ_SSI1_RX2, + .bd_number = 32, + .word_size = TRANSFER_8BIT, + }, + .channel_num = MXC_DMA_CHANNEL_SSI1_RX, + .chnl_priority = 2, +}; + +static mxc_sdma_channel_params_t mxc_sdma_ssi1_8bit_tx1_params = { + .chnl_params = { + .watermark_level = MXC_SSI_TXFIFO_WML, + .per_address = SSI1_BASE_ADDR + MXC_SSI_TX1_REG, + .peripheral_type = SSI, + .transfer_type = emi_2_per, + .event_id = DMA_REQ_SSI1_TX2, + .bd_number = 32, + .word_size = TRANSFER_8BIT, + }, + .channel_num = MXC_DMA_CHANNEL_SSI1_TX, + .chnl_priority = 2, +}; + +static mxc_sdma_channel_params_t mxc_sdma_ssi1_16bit_rx1_params = { + .chnl_params = { + .watermark_level = MXC_SSI_RXFIFO_WML, + .per_address = SSI1_BASE_ADDR + MXC_SSI_RX1_REG, + .peripheral_type = SSI, + .transfer_type = per_2_emi, + .event_id = DMA_REQ_SSI1_RX2, + .bd_number = 32, + .word_size = TRANSFER_16BIT, + }, + .channel_num = MXC_DMA_CHANNEL_SSI1_RX, + .chnl_priority = 2, +}; + +static mxc_sdma_channel_params_t mxc_sdma_ssi1_16bit_tx1_params = { + .chnl_params = { + .watermark_level = MXC_SSI_TXFIFO_WML, + .per_address = SSI1_BASE_ADDR + MXC_SSI_TX1_REG, + .peripheral_type = SSI, + .transfer_type = emi_2_per, + .event_id = DMA_REQ_SSI1_TX2, + .bd_number = 32, + .word_size = TRANSFER_16BIT, + }, + .channel_num = MXC_DMA_CHANNEL_SSI1_TX, + .chnl_priority = 2, +}; + +static mxc_sdma_channel_params_t mxc_sdma_ssi1_24bit_rx1_params = { + .chnl_params = { + .watermark_level = MXC_SSI_RXFIFO_WML, + .per_address = SSI1_BASE_ADDR + MXC_SSI_RX1_REG, + .peripheral_type = SSI, + .transfer_type = per_2_emi, + .event_id = DMA_REQ_SSI1_RX2, + .bd_number = 32, + .word_size = TRANSFER_32BIT, + }, + .channel_num = MXC_DMA_CHANNEL_SSI1_RX, + .chnl_priority = 2, +}; + +static mxc_sdma_channel_params_t mxc_sdma_ssi1_24bit_tx1_params = { + .chnl_params = { + .watermark_level = MXC_SSI_TXFIFO_WML, + .per_address = SSI1_BASE_ADDR + MXC_SSI_TX1_REG, + .peripheral_type = SSI, + .transfer_type = emi_2_per, + .event_id = DMA_REQ_SSI1_TX2, + .bd_number = 32, + .word_size = TRANSFER_32BIT, + }, + .channel_num = MXC_DMA_CHANNEL_SSI1_TX, + .chnl_priority = 2, +}; + +static mxc_sdma_channel_params_t mxc_sdma_ssi2_8bit_rx0_params = { + .chnl_params = { + .watermark_level = MXC_SSI_RXFIFO_WML, + .per_address = SSI2_BASE_ADDR + MXC_SSI_RX0_REG, + .peripheral_type = SSI_SP, + .transfer_type = per_2_emi, + .event_id = DMA_REQ_SSI2_RX1, + .bd_number = 32, + .word_size = TRANSFER_8BIT, + }, + .channel_num = MXC_DMA_CHANNEL_SSI2_RX, + .chnl_priority = 2, +}; + +static mxc_sdma_channel_params_t mxc_sdma_ssi2_8bit_tx0_params = { + .chnl_params = { + .watermark_level = MXC_SSI_TXFIFO_WML, + .per_address = SSI2_BASE_ADDR + MXC_SSI_TX0_REG, + .peripheral_type = SSI_SP, + .transfer_type = emi_2_per, + .event_id = DMA_REQ_SSI2_TX1, + .bd_number = 32, + .word_size = TRANSFER_8BIT, + }, + .channel_num = MXC_DMA_CHANNEL_SSI2_TX, + .chnl_priority = 2, +}; + +static mxc_sdma_channel_params_t mxc_sdma_ssi2_16bit_rx0_params = { + .chnl_params = { + .watermark_level = MXC_SSI_RXFIFO_WML, + .per_address = SSI2_BASE_ADDR + MXC_SSI_RX0_REG, + .peripheral_type = SSI_SP, + .transfer_type = per_2_emi, + .event_id = DMA_REQ_SSI2_RX1, + .bd_number = 32, + .word_size = TRANSFER_16BIT, + }, + .channel_num = MXC_DMA_CHANNEL_SSI2_RX, + .chnl_priority = 2, +}; + +static mxc_sdma_channel_params_t mxc_sdma_ssi2_16bit_tx0_params = { + .chnl_params = { + .watermark_level = MXC_SSI_TXFIFO_WML, + .per_address = SSI2_BASE_ADDR + MXC_SSI_TX0_REG, + .peripheral_type = SSI_SP, + .transfer_type = emi_2_per, + .event_id = DMA_REQ_SSI2_TX1, + .bd_number = 32, + .word_size = TRANSFER_16BIT, + }, + .channel_num = MXC_DMA_CHANNEL_SSI2_TX, + .chnl_priority = 2, +}; + +static mxc_sdma_channel_params_t mxc_sdma_ssi2_24bit_rx0_params = { + .chnl_params = { + .watermark_level = MXC_SSI_RXFIFO_WML, + .per_address = SSI2_BASE_ADDR + MXC_SSI_RX0_REG, + .peripheral_type = SSI_SP, + .transfer_type = per_2_emi, + .event_id = DMA_REQ_SSI2_RX1, + .bd_number = 32, + .word_size = TRANSFER_32BIT, + }, + .channel_num = MXC_DMA_CHANNEL_SSI2_RX, + .chnl_priority = 2, +}; + +static mxc_sdma_channel_params_t mxc_sdma_ssi2_24bit_tx0_params = { + .chnl_params = { + .watermark_level = MXC_SSI_TXFIFO_WML, + .per_address = SSI2_BASE_ADDR + MXC_SSI_TX0_REG, + .peripheral_type = SSI_SP, + .transfer_type = emi_2_per, + .event_id = DMA_REQ_SSI2_TX1, + .bd_number = 32, + .word_size = TRANSFER_32BIT, + }, + .channel_num = MXC_DMA_CHANNEL_SSI2_TX, + .chnl_priority = 2, +}; + +static mxc_sdma_channel_params_t mxc_sdma_ssi2_8bit_rx1_params = { + .chnl_params = { + .watermark_level = MXC_SSI_RXFIFO_WML, + .per_address = SSI2_BASE_ADDR + MXC_SSI_RX1_REG, + .peripheral_type = SSI_SP, + .transfer_type = per_2_emi, + .event_id = DMA_REQ_SSI2_RX2, + .bd_number = 32, + .word_size = TRANSFER_8BIT, + }, + .channel_num = MXC_DMA_CHANNEL_SSI2_RX, + .chnl_priority = 2, +}; + +static mxc_sdma_channel_params_t mxc_sdma_ssi2_8bit_tx1_params = { + .chnl_params = { + .watermark_level = MXC_SSI_TXFIFO_WML, + .per_address = SSI2_BASE_ADDR + MXC_SSI_TX1_REG, + .peripheral_type = SSI_SP, + .transfer_type = emi_2_per, + .event_id = DMA_REQ_SSI2_TX2, + .bd_number = 32, + .word_size = TRANSFER_8BIT, + }, + .channel_num = MXC_DMA_CHANNEL_SSI2_TX, + .chnl_priority = 2, +}; + +static mxc_sdma_channel_params_t mxc_sdma_ssi2_16bit_rx1_params = { + .chnl_params = { + .watermark_level = MXC_SSI_RXFIFO_WML, + .per_address = SSI2_BASE_ADDR + MXC_SSI_RX1_REG, + .peripheral_type = SSI_SP, + .transfer_type = per_2_emi, + .event_id = DMA_REQ_SSI2_RX2, + .bd_number = 32, + .word_size = TRANSFER_16BIT, + }, + .channel_num = MXC_DMA_CHANNEL_SSI2_RX, + .chnl_priority = 2, +}; + +static mxc_sdma_channel_params_t mxc_sdma_ssi2_16bit_tx1_params = { + .chnl_params = { + .watermark_level = MXC_SSI_TXFIFO_WML, + .per_address = SSI2_BASE_ADDR + MXC_SSI_TX1_REG, + .peripheral_type = SSI_SP, + .transfer_type = emi_2_per, + .event_id = DMA_REQ_SSI2_TX2, + .bd_number = 32, + .word_size = TRANSFER_16BIT, + }, + .channel_num = MXC_DMA_CHANNEL_SSI2_TX, + .chnl_priority = 2, +}; + +static mxc_sdma_channel_params_t mxc_sdma_ssi2_24bit_rx1_params = { + .chnl_params = { + .watermark_level = MXC_SSI_RXFIFO_WML, + .per_address = SSI2_BASE_ADDR + MXC_SSI_RX1_REG, + .peripheral_type = SSI_SP, + .transfer_type = per_2_emi, + .event_id = DMA_REQ_SSI2_RX2, + .bd_number = 32, + .word_size = TRANSFER_32BIT, + }, + .channel_num = MXC_DMA_CHANNEL_SSI2_RX, + .chnl_priority = 2, +}; + +static mxc_sdma_channel_params_t mxc_sdma_ssi2_24bit_tx1_params = { + .chnl_params = { + .watermark_level = MXC_SSI_TXFIFO_WML, + .per_address = SSI2_BASE_ADDR + MXC_SSI_TX1_REG, + .peripheral_type = SSI_SP, + .transfer_type = emi_2_per, + .event_id = DMA_REQ_SSI2_TX2, + .bd_number = 32, + .word_size = TRANSFER_32BIT, + }, + .channel_num = MXC_DMA_CHANNEL_SSI2_TX, + .chnl_priority = 2, +}; + +static mxc_sdma_channel_params_t mxc_sdma_memory_params = { + .chnl_params = { + .peripheral_type = MEMORY, + .transfer_type = emi_2_emi, + .bd_number = 32, + .word_size = TRANSFER_32BIT, + }, + .channel_num = MXC_DMA_CHANNEL_MEMORY, + .chnl_priority = MXC_SDMA_DEFAULT_PRIORITY, +}; + +static mxc_sdma_channel_params_t mxc_sdma_ata_rx_params = { + .chnl_params = { + .watermark_level = MXC_IDE_DMA_WATERMARK, + .per_address = ATA_DMA_BASE_ADDR, + .peripheral_type = ATA, + .transfer_type = per_2_emi, + .event_id = DMA_REQ_ATA_TX_END, + .event_id2 = DMA_REQ_ATA_RX, + .bd_number = MXC_IDE_DMA_BD_NR, + .word_size = TRANSFER_32BIT, + }, + .channel_num = MXC_DMA_CHANNEL_ATA_RX, + .chnl_priority = MXC_SDMA_DEFAULT_PRIORITY, +}; + +static mxc_sdma_channel_params_t mxc_sdma_ata_tx_params = { + .chnl_params = { + .watermark_level = MXC_IDE_DMA_WATERMARK, + .per_address = ATA_DMA_BASE_ADDR + 0x18, + .peripheral_type = ATA, + .transfer_type = emi_2_per, + .event_id = DMA_REQ_ATA_TX_END, + .event_id2 = DMA_REQ_ATA_TX, + .bd_number = MXC_IDE_DMA_BD_NR, + .word_size = TRANSFER_32BIT, + }, + .channel_num = MXC_DMA_CHANNEL_ATA_TX, + .chnl_priority = MXC_SDMA_DEFAULT_PRIORITY, +}; + +static mxc_sdma_channel_params_t mxc_sdma_spdif_16bit_tx_params = { + .chnl_params = { + .watermark_level = MXC_SPDIF_TXFIFO_WML, + .per_address = SPDIF_BASE_ADDR + MXC_SPDIF_TX_REG, + .peripheral_type = SPDIF, + .transfer_type = emi_2_per, + .event_id = DMA_REQ_SPDIF, + .bd_number = 32, + .word_size = TRANSFER_16BIT, + }, + .channel_num = MXC_DMA_CHANNEL_SPDIF_TX, + .chnl_priority = MXC_SDMA_DEFAULT_PRIORITY, +}; + +static mxc_sdma_channel_params_t mxc_sdma_spdif_32bit_tx_params = { + .chnl_params = { + .watermark_level = MXC_SPDIF_TXFIFO_WML, + .per_address = SPDIF_BASE_ADDR + MXC_SPDIF_TX_REG, + .peripheral_type = SPDIF, + .transfer_type = emi_2_per, + .event_id = DMA_REQ_SPDIF, + .bd_number = 32, + .word_size = TRANSFER_32BIT, + }, + .channel_num = MXC_DMA_CHANNEL_SPDIF_TX, + .chnl_priority = MXC_SDMA_DEFAULT_PRIORITY, +}; + +static mxc_sdma_info_entry_t mxc_sdma_active_dma_info[] = { + {MXC_DMA_UART1_RX, &mxc_sdma_uart1_rx_params}, + {MXC_DMA_UART1_TX, &mxc_sdma_uart1_tx_params}, + {MXC_DMA_UART2_RX, &mxc_sdma_uart2_rx_params}, + {MXC_DMA_UART2_TX, &mxc_sdma_uart2_tx_params}, + {MXC_DMA_UART3_RX, &mxc_sdma_uart3_rx_params}, + {MXC_DMA_UART3_TX, &mxc_sdma_uart3_tx_params}, + {MXC_DMA_MMC1_WIDTH_1, &mxc_sdma_mmc1_width1_params}, + {MXC_DMA_MMC1_WIDTH_4, &mxc_sdma_mmc1_width4_params}, + {MXC_DMA_MMC2_WIDTH_1, &mxc_sdma_mmc2_width1_params}, + {MXC_DMA_MMC2_WIDTH_4, &mxc_sdma_mmc2_width4_params}, + {MXC_DMA_SSI1_8BIT_RX0, &mxc_sdma_ssi1_8bit_rx0_params}, + {MXC_DMA_SSI1_8BIT_TX0, &mxc_sdma_ssi1_8bit_tx0_params}, + {MXC_DMA_SSI1_16BIT_RX0, &mxc_sdma_ssi1_16bit_rx0_params}, + {MXC_DMA_SSI1_16BIT_TX0, &mxc_sdma_ssi1_16bit_tx0_params}, + {MXC_DMA_SSI1_24BIT_RX0, &mxc_sdma_ssi1_24bit_rx0_params}, + {MXC_DMA_SSI1_24BIT_TX0, &mxc_sdma_ssi1_24bit_tx0_params}, + {MXC_DMA_SSI1_8BIT_RX1, &mxc_sdma_ssi1_8bit_rx1_params}, + {MXC_DMA_SSI1_8BIT_TX1, &mxc_sdma_ssi1_8bit_tx1_params}, + {MXC_DMA_SSI1_16BIT_RX1, &mxc_sdma_ssi1_16bit_rx1_params}, + {MXC_DMA_SSI1_16BIT_TX1, &mxc_sdma_ssi1_16bit_tx1_params}, + {MXC_DMA_SSI1_24BIT_RX1, &mxc_sdma_ssi1_24bit_rx1_params}, + {MXC_DMA_SSI1_24BIT_TX1, &mxc_sdma_ssi1_24bit_tx1_params}, + {MXC_DMA_SSI2_8BIT_RX0, &mxc_sdma_ssi2_8bit_rx0_params}, + {MXC_DMA_SSI2_8BIT_TX0, &mxc_sdma_ssi2_8bit_tx0_params}, + {MXC_DMA_SSI2_16BIT_RX0, &mxc_sdma_ssi2_16bit_rx0_params}, + {MXC_DMA_SSI2_16BIT_TX0, &mxc_sdma_ssi2_16bit_tx0_params}, + {MXC_DMA_SSI2_24BIT_RX0, &mxc_sdma_ssi2_24bit_rx0_params}, + {MXC_DMA_SSI2_24BIT_TX0, &mxc_sdma_ssi2_24bit_tx0_params}, + {MXC_DMA_SSI2_8BIT_RX1, &mxc_sdma_ssi2_8bit_rx1_params}, + {MXC_DMA_SSI2_8BIT_TX1, &mxc_sdma_ssi2_8bit_tx1_params}, + {MXC_DMA_SSI2_16BIT_RX1, &mxc_sdma_ssi2_16bit_rx1_params}, + {MXC_DMA_SSI2_16BIT_TX1, &mxc_sdma_ssi2_16bit_tx1_params}, + {MXC_DMA_SSI2_24BIT_RX1, &mxc_sdma_ssi2_24bit_rx1_params}, + {MXC_DMA_SSI2_24BIT_TX1, &mxc_sdma_ssi2_24bit_tx1_params}, + {MXC_DMA_MEMORY, &mxc_sdma_memory_params}, + {MXC_DMA_ATA_RX, &mxc_sdma_ata_rx_params}, + {MXC_DMA_ATA_TX, &mxc_sdma_ata_tx_params}, + {MXC_DMA_SPDIF_16BIT_TX, &mxc_sdma_spdif_16bit_tx_params}, + {MXC_DMA_SPDIF_32BIT_TX, &mxc_sdma_spdif_32bit_tx_params}, +}; + +static int mxc_sdma_info_entrys = + sizeof(mxc_sdma_active_dma_info) / sizeof(mxc_sdma_active_dma_info[0]); + +/*! + * This functions Returns the SDMA paramaters associated for a module + * + * @param channel_id the ID of the module requesting DMA + * @return returns the sdma parameters structure for the device + */ +mxc_sdma_channel_params_t *mxc_sdma_get_channel_params(mxc_dma_device_t + channel_id) +{ + mxc_sdma_info_entry_t *p = mxc_sdma_active_dma_info; + int i; + + for (i = 0; i < mxc_sdma_info_entrys; i++, p++) { + if (p->device == channel_id) + return p->chnl_info; + + } + return NULL; +} + +/*! + * This functions marks the SDMA channels that are statically allocated + * + * @param chnl the channel array used to store channel information + */ +void mxc_get_static_channels(mxc_dma_channel_t *chnl) +{ +#ifdef CONFIG_SDMA_IRAM + int i; + for (i = MXC_DMA_CHANNEL_IRAM; i < MAX_DMA_CHANNELS; i++) + chnl[i].dynamic = 0; +#endif +} + +EXPORT_SYMBOL(mxc_sdma_get_channel_params); +EXPORT_SYMBOL(mxc_get_static_channels); diff --git a/arch/arm/mach-mx51/dummy_gpio.c b/arch/arm/mach-mx51/dummy_gpio.c new file mode 100644 index 000000000000..bf21862908ac --- /dev/null +++ b/arch/arm/mach-mx51/dummy_gpio.c @@ -0,0 +1,108 @@ +/* + * Copyright 2007-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> + +void gpio_gps_active(void) {} +EXPORT_SYMBOL(gpio_gps_active); + +void gpio_gps_inactive(void) {} +EXPORT_SYMBOL(gpio_gps_inactive); + +void config_uartdma_event(int port) {} +EXPORT_SYMBOL(config_uartdma_event); + +void gpio_spi_active(int cspi_mod) {} +EXPORT_SYMBOL(gpio_spi_active); + +void gpio_spi_inactive(int cspi_mod) {} +EXPORT_SYMBOL(gpio_spi_inactive); + +void gpio_owire_active(void) {} +EXPORT_SYMBOL(gpio_owire_active); + +void gpio_owire_inactive(void) {} +EXPORT_SYMBOL(gpio_owire_inactive); + +void gpio_i2c_active(int i2c_num) {} +EXPORT_SYMBOL(gpio_i2c_active); + +void gpio_i2c_inactive(int i2c_num) {} +EXPORT_SYMBOL(gpio_i2c_inactive); + +void gpio_i2c_hs_active(void) {} +EXPORT_SYMBOL(gpio_i2c_hs_active); + +void gpio_i2c_hs_inactive(void) {} +EXPORT_SYMBOL(gpio_i2c_hs_inactive); + +void gpio_pmic_active(void) {} +EXPORT_SYMBOL(gpio_pmic_active); + +void gpio_activate_audio_ports(void) {} +EXPORT_SYMBOL(gpio_activate_audio_ports); + +void gpio_sdhc_active(int module) {} +EXPORT_SYMBOL(gpio_sdhc_active); + +void gpio_sdhc_inactive(int module) {} +EXPORT_SYMBOL(gpio_sdhc_inactive); + +void gpio_sensor_select(int sensor) {} + +void gpio_sensor_active(unsigned int csi) {} +EXPORT_SYMBOL(gpio_sensor_active); + +void gpio_sensor_inactive(unsigned int csi) {} +EXPORT_SYMBOL(gpio_sensor_inactive); + +void gpio_ata_active(void) {} +EXPORT_SYMBOL(gpio_ata_active); + +void gpio_ata_inactive(void) {} +EXPORT_SYMBOL(gpio_ata_inactive); + +void gpio_nand_active(void) {} +EXPORT_SYMBOL(gpio_nand_active); + +void gpio_nand_inactive(void) {} +EXPORT_SYMBOL(gpio_nand_inactive); + +void gpio_keypad_active(void) {} +EXPORT_SYMBOL(gpio_keypad_active); + +void gpio_keypad_inactive(void) {} +EXPORT_SYMBOL(gpio_keypad_inactive); + +int gpio_usbotg_hs_active(void) +{ + return 0; +} +EXPORT_SYMBOL(gpio_usbotg_hs_active); + +void gpio_usbotg_hs_inactive(void) {} +EXPORT_SYMBOL(gpio_usbotg_hs_inactive); + +void gpio_fec_active(void) {} +EXPORT_SYMBOL(gpio_fec_active); + +void gpio_fec_inactive(void) {} +EXPORT_SYMBOL(gpio_fec_inactive); + +void gpio_spdif_active(void) {} +EXPORT_SYMBOL(gpio_spdif_active); + +void gpio_spdif_inactive(void) {} +EXPORT_SYMBOL(gpio_spdif_inactive); + diff --git a/arch/arm/mach-mx51/iomux.c b/arch/arm/mach-mx51/iomux.c new file mode 100644 index 000000000000..7655ea4a04d4 --- /dev/null +++ b/arch/arm/mach-mx51/iomux.c @@ -0,0 +1,248 @@ +/* + * Copyright 2008-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_MX51 Board GPIO and Muxing Setup + * @ingroup MSL_MX51 + */ +/*! + * @file mach-mx51/iomux.c + * + * @brief I/O Muxing control functions + * + * @ingroup GPIO_MX51 + */ + +#include <linux/io.h> +#include <linux/module.h> +#include <linux/spinlock.h> +#include <mach/hardware.h> +#include <mach/gpio.h> +#include "iomux.h" + +/*! + * IOMUX register (base) addresses + */ +enum iomux_reg_addr { + IOMUXGPR0 = IO_ADDRESS(IOMUXC_BASE_ADDR), + IOMUXGPR1 = IO_ADDRESS(IOMUXC_BASE_ADDR) + 0x004, + IOMUXSW_MUX_CTL = IO_ADDRESS(IOMUXC_BASE_ADDR), + IOMUXSW_MUX_END = IO_ADDRESS(IOMUXC_BASE_ADDR) + MUX_I_END, + IOMUXSW_PAD_CTL = IO_ADDRESS(IOMUXC_BASE_ADDR) + PAD_I_START, + IOMUXSW_INPUT_CTL = IO_ADDRESS(IOMUXC_BASE_ADDR), +}; + +#define MUX_PIN_NUM_MAX ((MUX_I_END >> 2) + 1) + +static u8 iomux_pin_res_table[MUX_PIN_NUM_MAX]; +static DEFINE_SPINLOCK(gpio_mux_lock); + +static inline u32 _get_mux_reg(iomux_pin_name_t pin) +{ + u32 mux_reg = PIN_TO_IOMUX_MUX(pin); + + if (cpu_is_mx51_rev(CHIP_REV_2_0) < 0) { + if ((pin == MX51_PIN_NANDF_RB5) || + (pin == MX51_PIN_NANDF_RB6) || + (pin == MX51_PIN_NANDF_RB7)) + ; /* Do nothing */ + else if (mux_reg >= 0x2FC) + mux_reg += 8; + else if (mux_reg >= 0x130) + mux_reg += 0xC; + } + mux_reg += IOMUXSW_MUX_CTL; + return mux_reg; +} + +static inline u32 _get_pad_reg(iomux_pin_name_t pin) +{ + u32 pad_reg = PIN_TO_IOMUX_PAD(pin); + + if (cpu_is_mx51_rev(CHIP_REV_2_0) < 0) { + if ((pin == MX51_PIN_NANDF_RB5) || + (pin == MX51_PIN_NANDF_RB6) || + (pin == MX51_PIN_NANDF_RB7)) + ; /* Do nothing */ + else if (pad_reg == 0x4D0 - PAD_I_START) + pad_reg += 0x4C; + else if (pad_reg == 0x860 - PAD_I_START) + pad_reg += 0x9C; + else if (pad_reg >= 0x804 - PAD_I_START) + pad_reg += 0xB0; + else if (pad_reg >= 0x7FC - PAD_I_START) + pad_reg += 0xB4; + else if (pad_reg >= 0x4E4 - PAD_I_START) + pad_reg += 0xCC; + else + pad_reg += 8; + } + pad_reg += IOMUXSW_PAD_CTL; + return pad_reg; +} + +static inline u32 _get_mux_end(void) +{ + if (cpu_is_mx51_rev(CHIP_REV_2_0) < 0) + return(IO_ADDRESS(IOMUXC_BASE_ADDR) + (0x3F8 - 4)); + else + return(IO_ADDRESS(IOMUXC_BASE_ADDR) + (0x3F0 - 4)); +} + +/*! + * This function is used to configure a pin through the IOMUX module. + * @param pin a pin number as defined in \b #iomux_pin_name_t + * @param config a configuration as defined in \b #iomux_pin_cfg_t + * + * @return 0 if successful; Non-zero otherwise + */ +static int iomux_config_mux(iomux_pin_name_t pin, iomux_pin_cfg_t config) +{ + u32 ret = 0; + u32 pin_index = PIN_TO_IOMUX_INDEX(pin); + u32 mux_reg = _get_mux_reg(pin); + u32 mux_data = 0; + u8 *rp; + + BUG_ON((mux_reg > _get_mux_end()) || (mux_reg < IOMUXSW_MUX_CTL)); + spin_lock(&gpio_mux_lock); + + if (config == IOMUX_CONFIG_GPIO) + mux_data = PIN_TO_ALT_GPIO(pin); + else + mux_data = config; + + __raw_writel(mux_data, mux_reg); + + /* + * Log a warning if a pin changes ownership + */ + rp = iomux_pin_res_table + pin_index; + if ((mux_data & *rp) && (*rp != mux_data)) { + /* + * Don't call printk if we're tweaking the console uart or + * we'll deadlock. + */ + printk(KERN_ERR "iomux_config_mux: Warning: iomux pin" + " config changed, pin=%d, " + " prev=0x%x new=0x%x\n", mux_reg, *rp, mux_data); + ret = -EINVAL; + } + *rp = mux_data; + spin_unlock(&gpio_mux_lock); + return ret; +} + +/*! + * Request ownership for an IO pin. This function has to be the first one + * being called before that pin is used. The caller has to check the + * return value to make sure it returns 0. + * + * @param pin a name defined by \b iomux_pin_name_t + * @param config a configuration as defined in \b #iomux_pin_cfg_t + * + * @return 0 if successful; Non-zero otherwise + */ +int mxc_request_iomux(iomux_pin_name_t pin, iomux_pin_cfg_t config) +{ + int ret = iomux_config_mux(pin, config); + int gpio_port = GPIO_TO_PORT(IOMUX_TO_GPIO(pin)); + + if (!ret && (gpio_port != NON_GPIO_PORT) + && ((config == IOMUX_CONFIG_GPIO) + || (config == PIN_TO_ALT_GPIO(pin)))) + ret |= gpio_request(IOMUX_TO_GPIO(pin), NULL); + + return ret; +} +EXPORT_SYMBOL(mxc_request_iomux); + +/*! + * Release ownership for an IO pin + * + * @param pin a name defined by \b iomux_pin_name_t + * @param config config as defined in \b #iomux_pin_ocfg_t + */ +void mxc_free_iomux(iomux_pin_name_t pin, iomux_pin_cfg_t config) +{ + u32 pin_index = PIN_TO_IOMUX_INDEX(pin); + u8 *rp = iomux_pin_res_table + pin_index; + int gpio_port = GPIO_TO_PORT(IOMUX_TO_GPIO(pin)); + + *rp = 0; + if ((gpio_port != NON_GPIO_PORT) + && ((config == IOMUX_CONFIG_GPIO) + || (config == PIN_TO_ALT_GPIO(pin)))) + gpio_free(IOMUX_TO_GPIO(pin)); + +} +EXPORT_SYMBOL(mxc_free_iomux); + +/*! + * This function configures the pad value for a IOMUX pin. + * + * @param pin a pin number as defined in \b #iomux_pin_name_t + * @param config the ORed value of elements defined in \b #iomux_pad_config_t + */ +void mxc_iomux_set_pad(iomux_pin_name_t pin, u32 config) +{ + u32 pad_reg = _get_pad_reg(pin); + + BUG_ON(pad_reg < IOMUXSW_PAD_CTL); + __raw_writel(config, pad_reg); +} +EXPORT_SYMBOL(mxc_iomux_set_pad); + +unsigned int mxc_iomux_get_pad(iomux_pin_name_t pin) +{ + u32 pad_reg = _get_pad_reg(pin); + + return __raw_readl(pad_reg); +} +EXPORT_SYMBOL(mxc_iomux_get_pad); + +/*! + * This function configures input path. + * + * @param input index of input select register as defined in \b #iomux_input_select_t + * @param config the binary value of elements defined in \b #iomux_input_config_t + * */ +void mxc_iomux_set_input(iomux_input_select_t input, u32 config) +{ + u32 reg; + + if (cpu_is_mx51_rev(CHIP_REV_2_0) < 0) { + if (input == MUX_IN_IPU_IPP_DI_0_IND_DISPB_SD_D_SELECT_INPUT) + input -= 4; + else if (input == MUX_IN_IPU_IPP_DI_1_IND_DISPB_SD_D_SELECT_INPUT) + input -= 3; + else if (input >= MUX_IN_KPP_IPP_IND_COL_6_SELECT_INPUT) + input -= 2; + else if (input >= MUX_IN_HSC_MIPI_MIX_PAR_SISG_TRIG_SELECT_INPUT) + input -= 5; + else if (input >= MUX_IN_HSC_MIPI_MIX_IPP_IND_SENS1_DATA_EN_SELECT_INPUT) + input -= 3; + else if (input >= MUX_IN_ECSPI2_IPP_IND_SS_B_3_SELECT_INPUT) + input -= 2; + else if (input >= MUX_IN_CCM_PLL1_BYPASS_CLK_SELECT_INPUT) + input -= 1; + + reg = IOMUXSW_INPUT_CTL + (input << 2) + INPUT_CTL_START_TO1; + } else { + reg = IOMUXSW_INPUT_CTL + (input << 2) + INPUT_CTL_START; + } + + BUG_ON(input >= MUX_INPUT_NUM_MUX); + __raw_writel(config, reg); +} +EXPORT_SYMBOL(mxc_iomux_set_input); diff --git a/arch/arm/mach-mx51/iomux.h b/arch/arm/mach-mx51/iomux.h new file mode 100644 index 000000000000..e314ab26ac9b --- /dev/null +++ b/arch/arm/mach-mx51/iomux.h @@ -0,0 +1,246 @@ +/* + * Copyright 2008-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 __MACH_MX51_IOMUX_H__ +#define __MACH_MX51_IOMUX_H__ + +#include <linux/types.h> +#include <mach/gpio.h> +#include "mx51_pins.h" + +/*! + * @file mach-mx51/iomux.h + * + * @brief I/O Muxing control definitions and functions + * + * @ingroup GPIO_MX51 + */ + +typedef unsigned int iomux_pin_name_t; + +/*! + * various IOMUX output functions + */ +typedef enum iomux_config { + IOMUX_CONFIG_ALT0, /*!< used as alternate function 0 */ + IOMUX_CONFIG_ALT1, /*!< used as alternate function 1 */ + IOMUX_CONFIG_ALT2, /*!< used as alternate function 2 */ + IOMUX_CONFIG_ALT3, /*!< used as alternate function 3 */ + IOMUX_CONFIG_ALT4, /*!< used as alternate function 4 */ + IOMUX_CONFIG_ALT5, /*!< used as alternate function 5 */ + IOMUX_CONFIG_ALT6, /*!< used as alternate function 6 */ + IOMUX_CONFIG_ALT7, /*!< used as alternate function 7 */ + IOMUX_CONFIG_GPIO, /*!< added to help user use GPIO mode */ + IOMUX_CONFIG_SION = 0x1 << 4, /*!< used as LOOPBACK:MUX SION bit */ +} iomux_pin_cfg_t; + +/*! + * various IOMUX pad functions + */ +typedef enum iomux_pad_config { + PAD_CTL_SRE_SLOW = 0x0 << 0, + PAD_CTL_SRE_FAST = 0x1 << 0, + PAD_CTL_DRV_LOW = 0x0 << 1, + PAD_CTL_DRV_MEDIUM = 0x1 << 1, + PAD_CTL_DRV_HIGH = 0x2 << 1, + PAD_CTL_DRV_MAX = 0x3 << 1, + PAD_CTL_ODE_OPENDRAIN_NONE = 0x0 << 3, + PAD_CTL_ODE_OPENDRAIN_ENABLE = 0x1 << 3, + PAD_CTL_100K_PD = 0x0 << 4, + PAD_CTL_47K_PU = 0x1 << 4, + PAD_CTL_100K_PU = 0x2 << 4, + PAD_CTL_22K_PU = 0x3 << 4, + PAD_CTL_PUE_KEEPER = 0x0 << 6, + PAD_CTL_PUE_PULL = 0x1 << 6, + PAD_CTL_PKE_NONE = 0x0 << 7, + PAD_CTL_PKE_ENABLE = 0x1 << 7, + PAD_CTL_HYS_NONE = 0x0 << 8, + PAD_CTL_HYS_ENABLE = 0x1 << 8, + PAD_CTL_DDR_INPUT_CMOS = 0x0 << 9, + PAD_CTL_DDR_INPUT_DDR = 0x1 << 9, + PAD_CTL_DRV_VOT_LOW = 0x0 << 13, + PAD_CTL_DRV_VOT_HIGH = 0x1 << 13, +} iomux_pad_config_t; + +/*! + * various IOMUX input select register index + */ +typedef enum iomux_input_select { + MUX_IN_AUDMUX_P4_INPUT_DA_AMX_SELECT_I = 0, + MUX_IN_AUDMUX_P4_INPUT_DB_AMX_SELECT_I, + MUX_IN_AUDMUX_P4_INPUT_TXCLK_AMX_SELECT_INPUT, + MUX_IN_AUDMUX_P4_INPUT_TXFS_AMX_SELECT_INPUT, + MUX_IN_AUDMUX_P5_INPUT_DA_AMX_SELECT_INPUT, + MUX_IN_AUDMUX_P5_INPUT_DB_AMX_SELECT_INPUT, + MUX_IN_AUDMUX_P5_INPUT_RXCLK_AMX_SELECT_INPUT, + MUX_IN_AUDMUX_P5_INPUT_RXFS_AMX_SELECT, + MUX_IN_AUDMUX_P5_INPUT_TXCLK_AMX_SELECT_INPUT, + MUX_IN_AUDMUX_P5_INPUT_TXFS_AMX_SELECT_INPUT, + MUX_IN_AUDMUX_P6_INPUT_DA_AMX_SELECT_INPUT, + MUX_IN_AUDMUX_P6_INPUT_DB_AMX_SELECT_INPUT, + MUX_IN_AUDMUX_P6_INPUT_RXCLK_AMX_SELECT_INPUT, + MUX_IN_AUDMUX_P6_INPUT_RXFS_AMX_SELECT_INPUT, + MUX_IN_AUDMUX_P6_INPUT_TXCLK_AMX_SELECT_INPUT, + MUX_IN_AUDMUX_P6_INPUT_TXFS_AMX_SELECT_INPUT, + MUX_IN_CCM_IPP_DI_CLK_SELECT_INPUT, + /* TO2 */ + MUX_IN_CCM_IPP_DI1_CLK_SELECT_INPUT, + MUX_IN_CCM_PLL1_BYPASS_CLK_SELECT_INPUT, + MUX_IN_CCM_PLL2_BYPASS_CLK_SELECT_INPUT, + MUX_IN_CSPI_IPP_CSPI_CLK_IN_SELECT_INPUT, + MUX_IN_CSPI_IPP_IND_MISO_SELECT_INPUT, + MUX_IN_CSPI_IPP_IND_MOSI_SELECT_INPUT, + MUX_IN_CSPI_IPP_IND_SS_B_1_SELECT_INPUT, + MUX_IN_CSPI_IPP_IND_SS_B_2_SELECT_INPUT, + MUX_IN_CSPI_IPP_IND_SS_B_3_SELECT_INPUT, + MUX_IN_DPLLIP1_L1T_TOG_EN_SELECT_INPUT, + /* TO2 */ + MUX_IN_ECSPI2_IPP_IND_SS_B_1_SELECT_INPUT, + MUX_IN_ECSPI2_IPP_IND_SS_B_3_SELECT_INPUT, + MUX_IN_EMI_IPP_IND_RDY_INT_SELECT_INPUT, + MUX_IN_ESDHC3_IPP_DAT0_IN_SELECT_INPUT, + MUX_IN_ESDHC3_IPP_DAT1_IN_SELECT_INPUT, + MUX_IN_ESDHC3_IPP_DAT2_IN_SELECT_INPUT, + MUX_IN_ESDHC3_IPP_DAT3_IN_SELECT_INPUT, + MUX_IN_FEC_FEC_COL_SELECT_INPUT, + MUX_IN_FEC_FEC_CRS_SELECT_INPUT, + MUX_IN_FEC_FEC_MDI_SELECT_INPUT, + MUX_IN_FEC_FEC_RDATA_0_SELECT_INPUT, + MUX_IN_FEC_FEC_RDATA_1_SELECT_INPUT, + MUX_IN_FEC_FEC_RDATA_2_SELECT_INPUT, + MUX_IN_FEC_FEC_RDATA_3_SELECT_INPUT, + MUX_IN_FEC_FEC_RX_CLK_SELECT_INPUT, + MUX_IN_FEC_FEC_RX_DV_SELECT_INPUT, + MUX_IN_FEC_FEC_RX_ER_SELECT_INPUT, + MUX_IN_FEC_FEC_TX_CLK_SELECT_INPUT, + MUX_IN_GPIO3_IPP_IND_G_IN_1_SELECT_INPUT, + MUX_IN_GPIO3_IPP_IND_G_IN_2_SELECT_INPUT, + MUX_IN_GPIO3_IPP_IND_G_IN_3_SELECT_INPUT, + MUX_IN_GPIO3_IPP_IND_G_IN_4_SELECT_INPUT, + MUX_IN_GPIO3_IPP_IND_G_IN_5_SELECT_INPUT, + MUX_IN_GPIO3_IPP_IND_G_IN_6_SELECT_INPUT, + MUX_IN_GPIO3_IPP_IND_G_IN_7_SELECT_INPUT, + MUX_IN_GPIO3_IPP_IND_G_IN_8_SELECT_INPUT, + /* TO2 */ + MUX_IN_GPIO3_IPP_IND_G_IN_12_SELECT_INPUT, + MUX_IN_HSC_MIPI_MIX_IPP_IND_SENS1_DATA_EN_SELECT_INPUT, + MUX_IN_HSC_MIPI_MIX_IPP_IND_SENS2_DATA_EN_SELECT_INPUT, + /* TO2 */ + MUX_IN_HSC_MIPI_MIX_PAR_VSYNC_SELECT_INPUT, + /* TO2 */ + MUX_IN_HSC_MIPI_MIX_PAR_DI_WAIT_SELECT_INPUT, + MUX_IN_HSC_MIPI_MIX_PAR_SISG_TRIG_SELECT_INPUT, + MUX_IN_I2C1_IPP_SCL_IN_SELECT_INPUT, + MUX_IN_I2C1_IPP_SDA_IN_SELECT_INPUT, + MUX_IN_I2C2_IPP_SCL_IN_SELECT_INPUT, + MUX_IN_I2C2_IPP_SDA_IN_SELECT_INPUT, + + MUX_IN_IPU_IPP_DI_0_IND_DISPB_SD_D_SELECT_INPUT, + + MUX_IN_IPU_IPP_DI_1_IND_DISPB_SD_D_SELECT_INPUT, + + MUX_IN_KPP_IPP_IND_COL_6_SELECT_INPUT, + MUX_IN_KPP_IPP_IND_COL_7_SELECT_INPUT, + MUX_IN_KPP_IPP_IND_ROW_4_SELECT_INPUT, + MUX_IN_KPP_IPP_IND_ROW_5_SELECT_INPUT, + MUX_IN_KPP_IPP_IND_ROW_6_SELECT_INPUT, + MUX_IN_KPP_IPP_IND_ROW_7_SELECT_INPUT, + MUX_IN_UART1_IPP_UART_RTS_B_SELECT_INPUT, + MUX_IN_UART1_IPP_UART_RXD_MUX_SELECT_INPUT, + MUX_IN_UART2_IPP_UART_RTS_B_SELECT_INPUT, + MUX_IN_UART2_IPP_UART_RXD_MUX_SELECT_INPUT, + MUX_IN_UART3_IPP_UART_RTS_B_SELECT_INPUT, + MUX_IN_UART3_IPP_UART_RXD_MUX_SELECT_INPUT, + MUX_IN_USBOH3_IPP_IND_UH3_CLK_SELECT_INPUT, + MUX_IN_USBOH3_IPP_IND_UH3_DATA_0_SELECT_INPUT, + MUX_IN_USBOH3_IPP_IND_UH3_DATA_1_SELECT_INPUT, + MUX_IN_USBOH3_IPP_IND_UH3_DATA_2_SELECT_INPUT, + MUX_IN_USBOH3_IPP_IND_UH3_DATA_3_SELECT_INPUT, + MUX_IN_USBOH3_IPP_IND_UH3_DATA_4_SELECT_INPUT, + MUX_IN_USBOH3_IPP_IND_UH3_DATA_5_SELECT_INPUT, + MUX_IN_USBOH3_IPP_IND_UH3_DATA_6_SELECT_INPUT, + MUX_IN_USBOH3_IPP_IND_UH3_DATA_7_SELECT_INPUT, + MUX_IN_USBOH3_IPP_IND_UH3_DIR_SELECT_INPUT, + MUX_IN_USBOH3_IPP_IND_UH3_NXT_SELECT_INPUT, + MUX_IN_USBOH3_IPP_IND_UH3_STP_SELECT_INPUT, + MUX_INPUT_NUM_MUX, +} iomux_input_select_t; + +/*! + * various IOMUX input functions + */ +typedef enum iomux_input_config { + INPUT_CTL_PATH0 = 0x0, + INPUT_CTL_PATH1, + INPUT_CTL_PATH2, + INPUT_CTL_PATH3, + INPUT_CTL_PATH4, + INPUT_CTL_PATH5, + INPUT_CTL_PATH6, + INPUT_CTL_PATH7, +} iomux_input_config_t; + +struct mxc_iomux_pin_cfg { + iomux_pin_name_t pin; + u8 mux_mode; + u16 pad_cfg; + u8 in_select; + u8 in_mode; +}; + +/*! + * Request ownership for an IO pin. This function has to be the first one + * being called before that pin is used. The caller has to check the + * return value to make sure it returns 0. + * + * @param pin a name defined by \b iomux_pin_name_t + * @param config config as defined in \b #iomux_pin_ocfg_t + * + * @return 0 if successful; Non-zero otherwise + */ +int mxc_request_iomux(iomux_pin_name_t pin, iomux_pin_cfg_t config); + +/*! + * Release ownership for an IO pin + * + * @param pin a name defined by \b iomux_pin_name_t + * @param config config as defined in \b #iomux_pin_ocfg_t + */ +void mxc_free_iomux(iomux_pin_name_t pin, iomux_pin_cfg_t config); + +/*! + * This function configures the pad value for a IOMUX pin. + * + * @param pin a pin number as defined in \b #iomux_pin_name_t + * @param config the ORed value of elements defined in + * \b #iomux_pad_config_t + */ +void mxc_iomux_set_pad(iomux_pin_name_t pin, u32 config); + +/*! + * This function gets the current pad value for a IOMUX pin. + * + * @param pin a pin number as defined in \b #iomux_pin_name_t + * @return current pad value + */ +unsigned int mxc_iomux_get_pad(iomux_pin_name_t pin); + +/*! + * This function configures input path. + * + * @param input index of input select register as defined in + * \b #iomux_input_select_t + * @param config the binary value of elements defined in \b #iomux_input_config_t + */ +void mxc_iomux_set_input(iomux_input_select_t input, u32 config); + +#endif /* __MACH_MX51_IOMUX_H__ */ diff --git a/arch/arm/mach-mx51/lpmodes.c b/arch/arm/mach-mx51/lpmodes.c new file mode 100644 index 000000000000..32af9ccc4f6a --- /dev/null +++ b/arch/arm/mach-mx51/lpmodes.c @@ -0,0 +1,309 @@ +/* + * Copyright 2008-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 mx51_lpmodes.c + * + * @brief Driver for the Freescale Semiconductor MXC low power modes setup. + * + * MX51 is designed to play and video with minimal power consumption. + * This driver enables the platform to enter and exit audio and video low + * power modes. + * + * @ingroup PM + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/fs.h> +#include <linux/interrupt.h> +#include <linux/jiffies.h> +#include <linux/device.h> +#include <linux/delay.h> +#include <linux/clk.h> +#include <linux/workqueue.h> +#include <linux/platform_device.h> +#include <mach/clock.h> +#include <mach/hardware.h> +#include <linux/regulator/machine.h> +#include "crm_regs.h" + +#define ARM_LP_CLK 166250000 +#define GP_LPM_VOLTAGE 775000 +#define GP_NORMAL_VOLTAGE 1050000 + +static int org_cpu_rate; +int lp_video_mode; +int lp_audio_mode; +static struct device *lpmode_dev; +struct regulator *gp_core; + +void enter_lp_video_mode(void) +{ +} + +void exit_lp_video_mode(void) +{ +} + +void enter_lp_audio_mode(void) +{ + struct clk *tclk; + int ret; + + struct clk *p_clk; + struct clk *amode_parent_clk; + + + tclk = clk_get(NULL, "ipu_clk"); + if (clk_get_usecount(tclk) != 0) { + printk(KERN_INFO + "Cannot enter AUDIO LPM mode - display is still active\n"); + return; + } + + tclk = clk_get(NULL, "cpu_clk"); + org_cpu_rate = clk_get_rate(tclk); + +#ifdef CHANGE_DDR2_TO_PLL2 + tclk = clk_get(NULL, "ddr_clk"); + clk_set_parent(tclk, clk_get(NULL, "axi_a_clk")); + + /* Set CPU clock to be derived from PLL2 instead of PLL1 */ + tclk = clk_get(NULL, "pll1_sw_clk"); + clk_set_parent(tclk, clk_get(NULL, "pll2")); + clk_enable(tclk); + + tclk = clk_get(NULL, "ddr_clk"); + clk_set_parent(tclk, clk_get(NULL, "ddr_hf_clk")); +#endif + + /*Change the DDR freq to 133Mhz. */ + tclk = clk_get(NULL, "ddr_hf_clk"); + clk_set_rate(tclk, clk_round_rate(tclk, 133000000)); + + tclk = clk_get(NULL, "cpu_clk"); + ret = clk_set_rate(tclk, ARM_LP_CLK); + if (ret != 0) + printk(KERN_DEBUG "cannot set CPU clock rate\n"); + clk_put(tclk); + /* Set the voltage to 0.775v for the GP domain. */ + ret = regulator_set_voltage(gp_core, GP_LPM_VOLTAGE, GP_LPM_VOLTAGE); + if (ret < 0) + printk(KERN_DEBUG "COULD NOT SET GP VOLTAGE!!!\n"); + + tclk = clk_get(NULL, "periph_apm_clk"); + amode_parent_clk = clk_get(NULL, "lp_apm"); + p_clk = clk_get_parent(tclk); + /* Make sure osc_clk is the parent of lp_apm. */ + clk_set_parent(amode_parent_clk, clk_get(NULL, "osc")); + /* Set the parent of periph_apm_clk to be lp_apm */ + clk_set_parent(tclk, amode_parent_clk); + + amode_parent_clk = tclk; + + tclk = clk_get(NULL, "main_bus_clk"); + p_clk = clk_get_parent(tclk); + /* Set the parent of main_bus_clk to be periph_apm_clk */ + clk_set_parent(tclk, amode_parent_clk); + + clk_set_rate(clk_get(NULL, "axi_a_clk"), 24000000); + clk_set_rate(clk_get(NULL, "axi_b_clk"), 24000000); + clk_set_rate(clk_get(NULL, "ahb_clk"), 24000000); + clk_set_rate(clk_get(NULL, "emi_slow_clk"), 24000000); + clk_set_rate(clk_get(NULL, "nfc_clk"), 12000000); + + /* disable PLL3 */ + tclk = clk_get(NULL, "pll3"); + if (tclk->usecount == 1) + clk_disable(tclk); + + /* disable PLL2 */ + tclk = clk_get(NULL, "pll2"); + if (tclk->usecount == 1) + clk_disable(tclk); + + /* disable PLL1 */ + tclk = clk_get(NULL, "pll1_main_clk"); + if (tclk->usecount == 1) + clk_disable(tclk); + + lp_audio_mode = 1; +} + +void exit_lp_audio_mode(void) +{ + struct clk *tclk; + struct clk *p_clk; + struct clk *rmode_parent_clk; + int ret; + + /* Set the voltage to 1.05v for the GP domain. */ + ret = regulator_set_voltage(gp_core, + GP_NORMAL_VOLTAGE, GP_NORMAL_VOLTAGE); + if (ret < 0) + printk(KERN_DEBUG "COULD NOT SET GP VOLTAGE!!!\n"); + + rmode_parent_clk = clk_get(NULL, "pll2"); + clk_enable(rmode_parent_clk); + + tclk = clk_get(NULL, "main_bus_clk"); + p_clk = clk_get_parent(tclk); + + /* Set the dividers before setting the parent clock. */ + clk_set_rate(clk_get(NULL, "axi_a_clk"), 6000000); + clk_set_rate(clk_get(NULL, "axi_b_clk"), 4800000); + clk_set_rate(clk_get(NULL, "ahb_clk"), 4800000); + clk_set_rate(clk_get(NULL, "emi_slow_clk"), 4800000); + clk_set_rate(clk_get(NULL, "nfc_clk"), 1200000); + /* Set the parent of main_bus_clk to be pll2 */ + clk_set_parent(tclk, rmode_parent_clk); + +#ifdef CHANGE_DDR2_TO_PLL2 + tclk = clk_get(NULL, "ddr_clk"); + clk_set_parent(tclk, clk_get(NULL, "axi_a_clk")); + + /* Set CPU clock to be derived from PLL1 instead of PLL2 */ + tclk = clk_get(NULL, "pll1_sw_clk"); + clk_set_parent(tclk, clk_get(NULL, "pll1_main_clk")); + clk_disable(tclk); + + tclk = clk_get(NULL, "ddr_clk"); + clk_set_parent(tclk, clk_get(NULL, "ddr_hf_clk")); +#endif + + tclk = clk_get(NULL, "cpu_clk"); + ret = clk_set_rate(tclk, org_cpu_rate); + if (ret != 0) + printk(KERN_DEBUG "cannot set CPU clock rate\n"); + clk_put(tclk); + + tclk = clk_get(NULL, "cpu_clk"); + + ret = clk_set_rate(tclk, org_cpu_rate); + if (ret != 0) + printk(KERN_DEBUG "cannot set CPU clock rate\n"); + + + /*Change the DDR freq to 200MHz*/ + tclk = clk_get(NULL, "ddr_hf_clk"); + clk_set_rate(tclk, clk_round_rate(tclk, 200000000)); + lp_audio_mode = 0; + +} + +static ssize_t lp_curr_mode(struct device *dev, + struct device_attribute *attr, char *buf) +{ + if (lp_video_mode) + return sprintf(buf, "in lp_video_mode\n"); + else if (lp_audio_mode) + return sprintf(buf, "in lp_audio_mode\n"); + else + return sprintf(buf, "in normal mode\n"); +} + +static ssize_t set_lp_mode(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + printk(KERN_DEBUG "In set_lp_mode() \n"); + + if (strstr(buf, "enable_lp_video") != NULL) { + if (!lp_video_mode) + enter_lp_video_mode(); + } else if (strstr(buf, "disable_lp_video") != NULL) { + if (lp_video_mode) + exit_lp_video_mode(); + } else if (strstr(buf, "enable_lp_audio") != NULL) { + if (!lp_audio_mode) + enter_lp_audio_mode(); + } else if (strstr(buf, "disable_lp_audio") != NULL) { + if (lp_audio_mode) + exit_lp_audio_mode(); + } + return size; +} + +static DEVICE_ATTR(lp_modes, 0644, lp_curr_mode, set_lp_mode); + +/*! + * This is the probe routine for the lp_mode driver. + * + * @param pdev The platform device structure + * + * @return The function returns 0 on success + * + */ +static int __devinit mx51_lpmode_probe(struct platform_device *pdev) +{ + u32 res = 0; + lpmode_dev = &pdev->dev; + + res = sysfs_create_file(&lpmode_dev->kobj, &dev_attr_lp_modes.attr); + if (res) { + printk(KERN_ERR + "lpmode_dev: Unable to register sysdev entry for lpmode_dev"); + return res; + } + + if (res != 0) { + printk(KERN_ERR "lpmode_dev: Unable to start"); + return res; + } + gp_core = regulator_get(NULL, "SW1"); + lp_video_mode = 0; + lp_audio_mode = 0; + + return 0; +} + +static struct platform_driver mx51_lpmode_driver = { + .driver = { + .name = "mx51_lpmode", + }, + .probe = mx51_lpmode_probe, +}; + +/*! + * Initialise the mx51_lpmode_driver. + * + * @return The function always returns 0. + */ + +static int __init lpmode_init(void) +{ + if (platform_driver_register(&mx51_lpmode_driver) != 0) { + printk(KERN_ERR "mx37_lpmode_driver register failed\n"); + return -ENODEV; + } + + printk(KERN_INFO "LPMode driver module loaded\n"); + return 0; +} + +static void __exit lpmode_cleanup(void) +{ + sysfs_remove_file(&lpmode_dev->kobj, &dev_attr_lp_modes.attr); + + /* Unregister the device structure */ + platform_driver_unregister(&mx51_lpmode_driver); +} + +module_init(lpmode_init); +module_exit(lpmode_cleanup); + +MODULE_AUTHOR("Freescale Semiconductor, Inc."); +MODULE_DESCRIPTION("LPMode driver"); +MODULE_LICENSE("GPL"); diff --git a/arch/arm/mach-mx51/mm.c b/arch/arm/mach-mx51/mm.c new file mode 100644 index 000000000000..7834d02b386a --- /dev/null +++ b/arch/arm/mach-mx51/mm.c @@ -0,0 +1,84 @@ +/* + * Copyright 2008-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-mx51/mm.c + * + * @brief This file creates static mapping between physical to virtual memory. + * + * @ingroup Memory_MX51 + */ + +/*! + * This structure defines the MX51 memory map. + */ +static struct map_desc mxc_io_desc[] __initdata = { + { + .virtual = IRAM_BASE_ADDR_VIRT, + .pfn = __phys_to_pfn(IRAM_BASE_ADDR), + .length = IRAM_SIZE, + .type = MT_DEVICE}, + { + .virtual = DEBUG_BASE_ADDR_VIRT, + .pfn = __phys_to_pfn(DEBUG_BASE_ADDR), + .length = DEBUG_SIZE, + .type = MT_DEVICE}, + { + .virtual = TZIC_BASE_ADDR_VIRT, + .pfn = __phys_to_pfn(TZIC_BASE_ADDR), + .length = TZIC_SIZE, + .type = MT_DEVICE}, + { + .virtual = AIPS1_BASE_ADDR_VIRT, + .pfn = __phys_to_pfn(AIPS1_BASE_ADDR), + .length = AIPS1_SIZE, + .type = MT_DEVICE}, + { + .virtual = SPBA0_BASE_ADDR_VIRT, + .pfn = __phys_to_pfn(SPBA0_BASE_ADDR), + .length = SPBA0_SIZE, + .type = MT_DEVICE}, + { + .virtual = AIPS2_BASE_ADDR_VIRT, + .pfn = __phys_to_pfn(AIPS2_BASE_ADDR), + .length = AIPS2_SIZE, + .type = MT_DEVICE}, + { + .virtual = NFC_BASE_ADDR_AXI_VIRT, + .pfn = __phys_to_pfn(NFC_BASE_ADDR_AXI), + .length = NFC_AXI_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) +{ + u32 tzic_addr; + if (cpu_is_mx51_rev(CHIP_REV_2_0) < 0) + tzic_addr = 0x8FFFC000; + else + tzic_addr = 0xE0003000; + + mxc_io_desc[2].pfn = __phys_to_pfn(tzic_addr); + iotable_init(mxc_io_desc, ARRAY_SIZE(mxc_io_desc)); +} diff --git a/arch/arm/mach-mx51/mx51_3stack.c b/arch/arm/mach-mx51/mx51_3stack.c new file mode 100644 index 000000000000..12e20bf95096 --- /dev/null +++ b/arch/arm/mach-mx51/mx51_3stack.c @@ -0,0 +1,1308 @@ +/* + * Copyright 2008-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/types.h> +#include <linux/sched.h> +#include <linux/delay.h> +#include <linux/interrupt.h> +#include <linux/irq.h> +#include <asm/mach/keypad.h> +#include <linux/init.h> +#include <linux/input.h> +#include <linux/nodemask.h> +#include <linux/clk.h> +#include <linux/platform_device.h> +#include <linux/fsl_devices.h> +#include <linux/spi/spi.h> +#include <linux/i2c.h> +#include <linux/ata.h> +#include <linux/pmic_external.h> +#include <linux/ipu.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 <linux/regulator/consumer.h> +#include <mach/hardware.h> +#include <mach/spba.h> +#include <asm/irq.h> +#include <asm/setup.h> +#include <asm/mach-types.h> +#include <asm/mach/arch.h> +#include <asm/mach/time.h> +#include <mach/common.h> +#include <mach/memory.h> +#include <mach/gpio.h> +#include <mach/mmc.h> + +#include "board-mx51_3stack.h" +#include "iomux.h" +#include "crm_regs.h" + +/*! + * @file mach-mx51/mx51_3stack.c + * + * @brief This file contains the board specific initialization routines. + * + * @ingroup MSL_MX51 + */ +extern void __init mx51_3stack_io_init(void); +extern struct cpu_wp *(*get_cpu_wp)(int *wp); +extern void (*set_num_cpu_wp)(int num); +static int num_cpu_wp = 3; + +/* working point(wp): 0 - 800MHz; 1 - 166.25MHz; */ +static struct cpu_wp cpu_wp_auto[] = { + { + .pll_rate = 1000000000, + .cpu_rate = 1000000000, + .pdf = 0, + .mfi = 10, + .mfd = 11, + .mfn = 5, + .cpu_podf = 0, + .cpu_voltage = 1175000,}, + { + .pll_rate = 800000000, + .cpu_rate = 800000000, + .pdf = 0, + .mfi = 8, + .mfd = 2, + .mfn = 1, + .cpu_podf = 0, + .cpu_voltage = 1100000,}, + { + .pll_rate = 800000000, + .cpu_rate = 166250000, + .pdf = 4, + .mfi = 8, + .mfd = 2, + .mfn = 1, + .cpu_podf = 4, + .cpu_voltage = 850000,}, +}; + +struct cpu_wp *mx51_3stack_get_cpu_wp(int *wp) +{ + *wp = num_cpu_wp; + return cpu_wp_auto; +} + +void mx51_3stack_set_num_cpu_wp(int num) +{ + num_cpu_wp = num; + return; +} + +static void mxc_nop_release(struct device *dev) +{ + /* Nothing */ +} + +#if defined(CONFIG_KEYBOARD_MXC) || defined(CONFIG_KEYBOARD_MXC_MODULE) +static u16 keymapping[24] = { + KEY_1, KEY_2, KEY_3, KEY_F1, KEY_UP, KEY_F2, + KEY_4, KEY_5, KEY_6, KEY_LEFT, KEY_SELECT, KEY_RIGHT, + KEY_7, KEY_8, KEY_9, KEY_F3, KEY_DOWN, KEY_F4, + KEY_0, KEY_OK, KEY_ESC, KEY_ENTER, KEY_MENU, KEY_BACK, +}; + +static struct resource mxc_kpp_resources[] = { + [0] = { + .start = MXC_INT_KPP, + .end = MXC_INT_KPP, + .flags = IORESOURCE_IRQ, + } +}; + +static struct keypad_data keypad_plat_data = { + .rowmax = 4, + .colmax = 6, + .irq = MXC_INT_KPP, + .learning = 0, + .delay = 2, + .matrix = keymapping, +}; + +/* 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 = &keypad_plat_data, + }, +}; + +static void mxc_init_keypad(void) +{ + (void)platform_device_register(&mxc_keypad_device); +} +#else +static inline void mxc_init_keypad(void) +{ +} +#endif + +/* NAND Flash Partitions */ +#ifdef CONFIG_MTD_PARTITIONS + +static struct mtd_partition nand_flash_partitions[] = { + { + .name = "bootloader", + .offset = 0, + .size = 3 * 1024 * 1024}, + { + .name = "nand.kernel", + .offset = MTDPART_OFS_APPEND, + .size = 5 * 1024 * 1024}, + { + .name = "nand.rootfs", + .offset = MTDPART_OFS_APPEND, + .size = 256 * 1024 * 1024}, + { + .name = "nand.userfs1", + .offset = MTDPART_OFS_APPEND, + .size = 256 * 1024 * 1024}, + { + .name = "nand.userfs2", + .offset = MTDPART_OFS_APPEND, + .size = MTDPART_SIZ_FULL}, +}; + +#endif + +/* MTD NAND flash */ +#if defined(CONFIG_MTD_NAND_MXC) \ + || defined(CONFIG_MTD_NAND_MXC_MODULE) \ + || defined(CONFIG_MTD_NAND_MXC_V2) \ + || defined(CONFIG_MTD_NAND_MXC_V2_MODULE) \ + || defined(CONFIG_MTD_NAND_MXC_V3) \ + || defined(CONFIG_MTD_NAND_MXC_V3_MODULE) + +extern void gpio_nand_active(void); +extern void gpio_nand_inactive(void); + +static int nand_init(void) +{ + /* Configure the pins */ + gpio_nand_active(); + return 0; +} + +static void nand_exit(void) +{ + /* Free the pins */ + gpio_nand_inactive(); +} + +static struct flash_platform_data mxc_nand_data = { + #ifdef CONFIG_MTD_PARTITIONS + .parts = nand_flash_partitions, + .nr_parts = ARRAY_SIZE(nand_flash_partitions), + #endif + .width = 1, + .init = nand_init, + .exit = nand_exit, +}; + +static struct platform_device mxc_nandv2_mtd_device = { + .name = "mxc_nandv2_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_nandv2_mtd_device); +} +#else +static inline void mxc_init_nand_mtd(void) +{ +} +#endif + +/* i.MX MTD NAND Flash Controller */ + +#if defined(CONFIG_MTD_NAND_IMX_NFC) || defined(CONFIG_MTD_NAND_IMX_NFC_MODULE) + +/* Resources for this device. */ + +static struct resource imx_nfc_resources[] = { + { + .flags = IORESOURCE_MEM, + .start = NFC_BASE_ADDR_AXI + 0x0000, + .end = NFC_BASE_ADDR_AXI + 0x1200 - 1, + .name = IMX_NFC_BUFFERS_ADDR_RES_NAME, + }, + { + .flags = IORESOURCE_MEM, + .start = NFC_BASE_ADDR_AXI + 0x1E00, + .end = NFC_BASE_ADDR_AXI + 0x1E44 - 1, + .name = IMX_NFC_PRIMARY_REGS_ADDR_RES_NAME, + }, + { + .flags = IORESOURCE_MEM, + .start = NFC_BASE_ADDR + 0x00, + .end = NFC_BASE_ADDR + 0x34 - 1, + .name = IMX_NFC_SECONDARY_REGS_ADDR_RES_NAME, + }, + { + .flags = IORESOURCE_IRQ, + .start = MXC_INT_NFC, + .end = MXC_INT_NFC, + .name = IMX_NFC_INTERRUPT_RES_NAME, + }, +}; + +/* + * Platform-specific information about this device. Some of the details depend + * on the SoC. See imx_init_nfc() below for code that fills in the rest. + */ + +static struct imx_nfc_platform_data imx_nfc_platform_data = { + .nfc_major_version = 3, + .nfc_minor_version = 2, + .force_ce = false, + .target_cycle_in_ns = 30, + .clock_name = "nfc_clk", + .set_page_size = 0, + .interleave = false, + #ifdef CONFIG_MTD_PARTITIONS + .partitions = nand_flash_partitions, + .partition_count = ARRAY_SIZE(nand_flash_partitions), + #endif +}; + +/* The structure that represents the NFC device. */ + +static struct platform_device imx_nfc_device = { + .name = IMX_NFC_DRIVER_NAME, + .id = 0, + .dev = { + .release = mxc_nop_release, + .platform_data = &imx_nfc_platform_data, + }, + .resource = imx_nfc_resources, + .num_resources = ARRAY_SIZE(imx_nfc_resources), +}; + +/** + * imx_init_nfc() - Sets up the NFC for this platform. + * + * This function sets up data structures representing the NFC device on this + * platform and registers the device with the platform management system. + */ + +static void imx_nfc_init(void) +{ + (void)platform_device_register(&imx_nfc_device); +} + +#else + +static inline void imx_nfc_init(void) +{ +} + +#endif /* i.MX MTD NAND Flash Controller */ + +#if defined(CONFIG_FB_MXC_SYNC_PANEL) || \ + defined(CONFIG_FB_MXC_SYNC_PANEL_MODULE) + +static struct mxc_fb_platform_data fb_data[] = { + { + .interface_pix_fmt = IPU_PIX_FMT_RGB666, + }, + { + .interface_pix_fmt = IPU_PIX_FMT_YUV444, + }, +}; + +static struct platform_device mxc_fb_device[] = { + { + .name = "mxc_sdc_fb", + .id = 0, + .dev = { + .release = mxc_nop_release, + .coherent_dma_mask = 0xFFFFFFFF, + .platform_data = &fb_data[0], + }, + }, + { + .name = "mxc_sdc_fb", + .id = 1, + .dev = { + .release = mxc_nop_release, + .coherent_dma_mask = 0xFFFFFFFF, + .platform_data = &fb_data[1], + }, + }, + { + .name = "mxc_sdc_fb", + .id = 2, + .dev = { + .release = mxc_nop_release, + .coherent_dma_mask = 0xFFFFFFFF, + }, + }, +}; + +static void lcd_reset_to2(void) +{ + gpio_set_value(IOMUX_TO_GPIO(MX51_PIN_DI1_D1_CS), 0); + ipu_reset_disp_panel(); + + return; +} + +static void lcd_reset(void) +{ + gpio_set_value(IOMUX_TO_GPIO(MX51_PIN_DISPB2_SER_RS), 0); + gpio_request(IOMUX_TO_GPIO(MX51_PIN_DISPB2_SER_RS), "ser_rs"); + gpio_direction_output(IOMUX_TO_GPIO(MX51_PIN_DISPB2_SER_RS), 0); + /* do reset */ + msleep(10); /* tRES >= 100us */ + gpio_set_value(IOMUX_TO_GPIO(MX51_PIN_DISPB2_SER_RS), 1); + msleep(60); +} + +static struct mxc_lcd_platform_data lcd_data = { + .core_reg = "VIOHI", + .io_reg = "SW4", + .reset = lcd_reset, +}; + +static struct platform_device mxc_lcd_device = { + .name = "lcd_spi", + .dev = { + .release = mxc_nop_release, + .platform_data = &lcd_data, + }, +}; + +static void wvga_reset(void) +{ + gpio_set_value(IOMUX_TO_GPIO(MX51_PIN_DI1_D1_CS), 1); +} + +static struct mxc_lcd_platform_data lcd_wvga_data = { + .reset = wvga_reset, +}; + +static struct platform_device lcd_wvga_device = { + .name = "lcd_claa", + .dev = { + .release = mxc_nop_release, + .platform_data = &lcd_wvga_data, + }, +}; + +static void mxc_init_fb(void) +{ + + if (cpu_is_mx51_rev(CHIP_REV_2_0) > 0) + lcd_data.reset = lcd_reset_to2; + + (void)platform_device_register(&mxc_lcd_device); + (void)platform_device_register(&lcd_wvga_device); + + (void)platform_device_register(&mxc_fb_device[0]); + (void)platform_device_register(&mxc_fb_device[1]); + (void)platform_device_register(&mxc_fb_device[2]); +} +#else +static inline void mxc_init_fb(void) +{ +} +#endif + +static struct platform_device mxcbl_device = { + .name = "mxc_mc13892_bl", +}; + +static inline void mxc_init_bl(void) +{ + platform_device_register(&mxcbl_device); +} + +void si4702_reset(void) +{ + gpio_set_value(IOMUX_TO_GPIO(MX51_PIN_EIM_DTACK), 0); + msleep(100); + gpio_set_value(IOMUX_TO_GPIO(MX51_PIN_EIM_DTACK), 1); + msleep(100); +} + +void si4702_clock_ctl(int flag) +{ +} + +static void si4702_gpio_get(void) +{ + /* reset pin */ + gpio_request(IOMUX_TO_GPIO(MX51_PIN_EIM_DTACK), "eim_dtack"); + gpio_direction_output(IOMUX_TO_GPIO(MX51_PIN_EIM_DTACK), 0); +} + +static void si4702_gpio_put(void) +{ +} + +static struct mxc_fm_platform_data si4702_data = { + .reg_vio = "SW4", + .reg_vdd = "VIOHI", + .gpio_get = si4702_gpio_get, + .gpio_put = si4702_gpio_put, + .reset = si4702_reset, + .clock_ctl = si4702_clock_ctl, + .sksnr = 0, + .skcnt = 0, + .band = 0, + .space = 100, + .seekth = 0xa, +}; + +#if defined(CONFIG_I2C_MXC) || defined(CONFIG_I2C_MXC_MODULE) + +#ifdef CONFIG_I2C_MXC_SELECT1 +static struct i2c_board_info mxc_i2c0_board_info[] __initdata = { +}; +#endif +#ifdef CONFIG_I2C_MXC_SELECT2 +static struct i2c_board_info mxc_i2c1_board_info[] __initdata = { + { + .type = "wm8903-i2c", + .addr = 0x1a, + }, + { + .type = "sgtl5000-i2c", + .addr = 0x0a, + }, + { + .type = "tsc2007", + .addr = 0x48, + .irq = IOMUX_TO_IRQ(MX51_PIN_GPIO1_5), + }, + { + .type = "si4702", + .addr = 0x10, + .platform_data = (void *)&si4702_data, + }, +}; +#endif +#if defined(CONFIG_I2C_MXC_HS) || defined(CONFIG_I2C_MXC_HS_MODULE) +static struct mxc_camera_platform_data camera_data = { + .io_regulator = "SW4", + .analog_regulator = "VIOHI", + .mclk = 24000000, + .csi = 0, +}; +static struct mxc_lightsensor_platform_data ls_data = { + .vdd_reg = NULL, + .rext = 100, +}; + +static struct i2c_board_info mxc_i2c_hs_board_info[] __initdata = { + { + .type = "ov3640", + .addr = 0x3C, + .platform_data = (void *)&camera_data, + }, + { + .type = "isl29003", + .addr = 0x44, + .platform_data = &ls_data, + }, +}; +#endif + +#endif + +static u32 cpld_base_addr; + +/*lan9217 device*/ +#if defined(CONFIG_SMSC911X) || defined(CONFIG_SMSC911X_MODULE) +static struct resource smsc911x_resources[] = { + { + .flags = IORESOURCE_MEM, + }, + { + .start = LAN9217_IRQ, + .end = LAN9217_IRQ, + .flags = IORESOURCE_IRQ, + }, +}; +static struct platform_device smsc_lan9217_device = { + .name = "smsc911x", + .id = 0, + .dev = { + .release = mxc_nop_release, + }, + .num_resources = ARRAY_SIZE(smsc911x_resources), + .resource = smsc911x_resources, +}; +static void mxc_init_enet(void) +{ + if (cpld_base_addr) { + smsc_lan9217_device.resource[0].start = + LAN9217_BASE_ADDR(cpld_base_addr); + smsc_lan9217_device.resource[0].end = + LAN9217_BASE_ADDR(cpld_base_addr) + 0x100; + (void)platform_device_register(&smsc_lan9217_device); + } +} +#else +static inline void mxc_init_enet(void) +{ +} +#endif + +#if defined(CONFIG_IMX_SIM) || defined(CONFIG_IMX_SIM_MODULE) +/* Used to configure the SIM bus */ +static struct mxc_sim_platform_data sim_data = { + .clk_rate = 4000000, + .clock_sim = "sim_clk", + .power_sim = NULL, + .init = NULL, + .exit = NULL, + .detect = 0, +}; + +/*! + * Resource definition for the SIM + */ +static struct resource mxc_sim_resources[] = { + [0] = { + .start = SIM_BASE_ADDR, + .end = SIM_BASE_ADDR + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = MXC_INT_SIM_IPB, + .end = MXC_INT_SIM_IPB, + .flags = IORESOURCE_IRQ, + }, + [2] = { + .start = MXC_INT_SIM_DAT, + .end = MXC_INT_SIM_DAT, + .flags = IORESOURCE_IRQ, + }, +}; + +/*! Device Definition for IMX SIM */ +static struct platform_device mxc_sim_device = { + .name = "mxc_sim", + .id = 0, + .dev = { + .release = mxc_nop_release, + .platform_data = &sim_data, + }, + .num_resources = ARRAY_SIZE(mxc_sim_resources), + .resource = mxc_sim_resources, +}; + +static inline void mxc_init_sim(void) +{ + (void)platform_device_register(&mxc_sim_device); +} +#else +static inline void mxc_init_sim(void) +{ +} +#endif + +#if defined(CONFIG_MMC_IMX_ESDHCI) || defined(CONFIG_MMC_IMX_ESDHCI_MODULE) +/*! + * Get WP pin value to detect write protection + */ +int sdhc_write_protect(struct device *dev) +{ + unsigned short rc = 0; + + if (to_platform_device(dev)->id == 0) + rc = gpio_get_value(IOMUX_TO_GPIO(MX51_PIN_GPIO1_1)); + else + rc = 0; + return rc; +} + +/* + * Probe for the card. If present the GPIO data would be set. + */ +unsigned int sdhc_get_card_det_status(struct device *dev) +{ + int ret; + + if (to_platform_device(dev)->id == 0) { + ret = gpio_get_value(IOMUX_TO_GPIO(MX51_PIN_GPIO1_0)); + return ret; + } else { /* config the det pin for SDHC2 */ + return 0; + } +} + +static struct mxc_mmc_platform_data mmc1_data = { + .ocr_mask = MMC_VDD_32_33, + .caps = MMC_CAP_4_BIT_DATA, + .min_clk = 150000, + .max_clk = 52000000, + .card_inserted_state = 0, + .status = sdhc_get_card_det_status, + .wp_status = sdhc_write_protect, + .clock_mmc = "esdhc_clk", + .power_mmc = NULL, +}; +static struct mxc_mmc_platform_data mmc2_data = { + .ocr_mask = MMC_VDD_27_28 | MMC_VDD_28_29 | MMC_VDD_29_30 | + MMC_VDD_31_32, + .caps = MMC_CAP_4_BIT_DATA, + .min_clk = 150000, + .max_clk = 50000000, + .card_inserted_state = 0, + .status = sdhc_get_card_det_status, + .wp_status = sdhc_write_protect, + .clock_mmc = "esdhc_clk", +}; + +/*! + * Resource definition for the SDHC1 + */ +static struct resource mxcsdhc1_resources[] = { + [0] = { + .start = MMC_SDHC1_BASE_ADDR, + .end = MMC_SDHC1_BASE_ADDR + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = MXC_INT_MMC_SDHC1, + .end = MXC_INT_MMC_SDHC1, + .flags = IORESOURCE_IRQ, + }, + [2] = { + .start = IOMUX_TO_IRQ(MX51_PIN_GPIO1_0), + .end = IOMUX_TO_IRQ(MX51_PIN_GPIO1_0), + .flags = IORESOURCE_IRQ, + }, +}; + +/*! + * Resource definition for the SDHC2 + */ +static struct resource mxcsdhc2_resources[] = { + [0] = { + .start = MMC_SDHC2_BASE_ADDR, + .end = MMC_SDHC2_BASE_ADDR + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = MXC_INT_MMC_SDHC2, + .end = MXC_INT_MMC_SDHC2, + .flags = IORESOURCE_IRQ, + }, + [2] = { + .start = 0, + .end = 0, + .flags = IORESOURCE_IRQ, + }, +}; + +/*! Device Definition for MXC SDHC1 */ +static struct platform_device mxcsdhc1_device = { + .name = "mxsdhci", + .id = 0, + .dev = { + .release = mxc_nop_release, + .platform_data = &mmc1_data, + }, + .num_resources = ARRAY_SIZE(mxcsdhc1_resources), + .resource = mxcsdhc1_resources, +}; + +/*! Device Definition for MXC SDHC2 */ +static struct platform_device mxcsdhc2_device = { + .name = "mxsdhci", + .id = 1, + .dev = { + .release = mxc_nop_release, + .platform_data = &mmc2_data, + }, + .num_resources = ARRAY_SIZE(mxcsdhc2_resources), + .resource = mxcsdhc2_resources, +}; + +static inline void mxc_init_mmc(void) +{ + (void)platform_device_register(&mxcsdhc1_device); + (void)platform_device_register(&mxcsdhc2_device); +} +#else +static inline void mxc_init_mmc(void) +{ +} +#endif + +static u32 brd_io; +static void expio_ack_irq(u32 irq); + +static void mxc_expio_irq_handler(u32 irq, struct irq_desc *desc) +{ + u32 imr_val; + u32 int_valid; + u32 expio_irq; + + desc->chip->mask(irq); /* irq = gpio irq number */ + + imr_val = __raw_readw(brd_io + INTR_MASK_REG); + int_valid = __raw_readw(brd_io + INTR_STATUS_REG) & ~imr_val; + + if (unlikely(!int_valid)) + 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 unhandled\n", + expio_irq); + BUG(); /* oops */ + } + d->handle_irq(expio_irq, d); + } + + out: + desc->chip->ack(irq); + desc->chip->unmask(irq); +} + +/* + * 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) +{ + u16 reg; + u32 expio = MXC_IRQ_TO_EXPIO(irq); + /* mask the interrupt */ + reg = __raw_readw(brd_io + INTR_MASK_REG); + reg |= (1 << expio); + __raw_writew(reg, brd_io + INTR_MASK_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, brd_io + INTR_RESET_REG); + __raw_writew(0, brd_io + INTR_RESET_REG); + /* mask the interrupt */ + expio_mask_irq(irq); +} + +/* + * Enable a expio pin's interrupt by clearing the bit in the imr. + * @param irq a expio virtual irq number + */ +static void expio_unmask_irq(u32 irq) +{ + u16 reg; + u32 expio = MXC_IRQ_TO_EXPIO(irq); + /* unmask the interrupt */ + reg = __raw_readw(brd_io + INTR_MASK_REG); + reg &= ~(1 << expio); + __raw_writew(reg, brd_io + INTR_MASK_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; + + brd_io = (u32) ioremap(BOARD_IO_ADDR(CS5_BASE_ADDR), SZ_4K); + if (brd_io == 0) + return -ENOMEM; + + if ((__raw_readw(brd_io + MAGIC_NUMBER1_REG) != 0xAAAA) || + (__raw_readw(brd_io + MAGIC_NUMBER2_REG) != 0x5555) || + (__raw_readw(brd_io + MAGIC_NUMBER3_REG) != 0xCAFE)) { + pr_info("3-Stack Debug board not detected \n"); + cpld_base_addr = 0; + return -ENODEV; + } else { + cpld_base_addr = CS5_BASE_ADDR; + } + + pr_info("3-Stack Debug board detected, rev = 0x%04X\n", + readw(brd_io + CPLD_CODE_VER_REG)); + + /* + * Configure INT line as GPIO input + */ + gpio_request(IOMUX_TO_GPIO(MX51_PIN_GPIO1_6), "gpio1_6"); + gpio_direction_input(IOMUX_TO_GPIO(MX51_PIN_GPIO1_6)); + + /* disable the interrupt and clear the status */ + __raw_writew(0, brd_io + INTR_MASK_REG); + __raw_writew(0xFFFF, brd_io + INTR_RESET_REG); + __raw_writew(0, brd_io + INTR_RESET_REG); + __raw_writew(0x1F, brd_io + INTR_MASK_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_LOW); + set_irq_chained_handler(EXPIO_PARENT_INT, mxc_expio_irq_handler); + + return 0; +} + +#if defined(CONFIG_PATA_FSL) || defined(CONFIG_PATA_FSL_MODULE) +extern void gpio_ata_active(void); +extern void gpio_ata_inactive(void); + +static int ata_init(struct platform_device *pdev) +{ + /* Configure the pins */ + gpio_ata_active(); + return 0; +} + +static void ata_exit(void) +{ + /* Free the pins */ + gpio_ata_inactive(); +} + +static struct fsl_ata_platform_data ata_data = { + .udma_mask = ATA_UDMA3, + .mwdma_mask = ATA_MWDMA2, + .pio_mask = ATA_PIO4, + .fifo_alarm = MXC_IDE_DMA_WATERMARK / 2, + .max_sg = MXC_IDE_DMA_BD_NR, + .init = ata_init, + .exit = ata_exit, + .core_reg = NULL, + .io_reg = NULL, +}; + +static struct resource pata_fsl_resources[] = { + [0] = { + .start = ATA_BASE_ADDR, + .end = ATA_BASE_ADDR + 0x000000C8, + .flags = IORESOURCE_MEM,}, + [2] = { + .start = MXC_INT_ATA, + .end = MXC_INT_ATA, + .flags = IORESOURCE_IRQ,}, +}; + +static struct platform_device pata_fsl_device = { + .name = "pata_fsl", + .id = -1, + .num_resources = ARRAY_SIZE(pata_fsl_resources), + .resource = pata_fsl_resources, + .dev = { + .platform_data = &ata_data, + .coherent_dma_mask = ~0,}, +}; + +static void __init mxc_init_pata(void) +{ + (void)platform_device_register(&pata_fsl_device); +} +#else /* CONFIG_PATA_FSL */ +static void __init mxc_init_pata(void) +{ +} +#endif /* CONFIG_PATA_FSL */ + +#if defined(CONFIG_TOUCHSCREEN_TSC2007) \ + || defined(CONFIG_TOUCHSCREEN_TSC2007_MODULE) + +static int __init mxc_init_touchscreen(void) +{ + gpio_request(IOMUX_TO_GPIO(MX51_PIN_GPIO1_5), "gpio1_5"); + gpio_direction_input(IOMUX_TO_GPIO(MX51_PIN_GPIO1_5)); + + return 0; +} +#else +static int __init mxc_init_touchscreen(void) +{ + return 0; +} +#endif + +static int __init mxc_init_srpgconfig(void) +{ + struct clk *gpcclk = clk_get(NULL, "gpc_dvfs_clk"); + clk_enable(gpcclk); + + /* Setup the number of clock cycles to wait for SRPG + * power up and power down requests. + */ + __raw_writel(0x010F0201, MXC_SRPG_ARM_PUPSCR); + __raw_writel(0x010F0201, MXC_SRPG_NEON_PUPSCR); + __raw_writel(0x00000008, MXC_SRPG_EMPGC0_PUPSCR); + __raw_writel(0x00000008, MXC_SRPG_EMPGC1_PUPSCR); + + __raw_writel(0x01010101, MXC_SRPG_ARM_PDNSCR); + __raw_writel(0x01010101, MXC_SRPG_NEON_PDNSCR); + __raw_writel(0x00000018, MXC_SRPG_EMPGC0_PDNSCR); + __raw_writel(0x00000018, MXC_SRPG_EMPGC1_PDNSCR); + + clk_disable(gpcclk); + clk_put(gpcclk); + + return 0; +} + +#if defined(CONFIG_SND_SOC_IMX_3STACK_WM8903) \ + || defined(CONFIG_SND_SOC_IMX_3STACK_WM8903_MODULE) +static struct mxc_audio_platform_data wm8903_data; + +static struct platform_device mxc_wm8903_device = { + .name = "imx-3stack-wm8903", + .id = 0, + .dev = { + .release = mxc_nop_release, + .platform_data = &wm8903_data, + }, +}; + +static void __init mxc_init_wm8903(void) +{ + wm8903_data.ssi_clk[0] = clk_get(NULL, "ssi_clk.0"); + clk_put(wm8903_data.ssi_clk[0]); + + wm8903_data.ssi_clk[1] = clk_get(NULL, "ssi_clk.1"); + clk_put(wm8903_data.ssi_clk[1]); + + wm8903_data.ssi_num = 1; + wm8903_data.src_port = 2; + wm8903_data.ext_port = 3; + + (void)platform_device_register(&mxc_wm8903_device); +} +#else +static void __init mxc_init_wm8903(void) +{ +} +#endif + +#if defined(CONFIG_SND_SOC_IMX_3STACK_SGTL5000) \ + || defined(CONFIG_SND_SOC_IMX_3STACK_SGTL5000_MODULE) +static int mxc_sgtl5000_plat_init(void); +static int mxc_sgtl5000_plat_finit(void); +static int mxc_sgtl5000_amp_enable(int enable); + +int headphone_det_status(void) +{ + return gpio_get_value(IOMUX_TO_GPIO(MX51_PIN_EIM_A26)); +} + +static struct mxc_audio_platform_data sgtl5000_data = { + .ssi_num = 1, + .src_port = 2, + .ext_port = 3, + .hp_irq = IOMUX_TO_IRQ(MX51_PIN_EIM_A26), + .hp_status = headphone_det_status, + .amp_enable = mxc_sgtl5000_amp_enable, + .vddio = 1800000, + .vdda = 1800000, + .vddd = 1200000, + .sysclk = 12000000, + .init = mxc_sgtl5000_plat_init, + .finit = mxc_sgtl5000_plat_finit, +}; + +static struct platform_device mxc_sgtl5000_device = { + .name = "imx-3stack-sgtl5000", + .dev = { + .release = mxc_nop_release, + .platform_data = &sgtl5000_data, + }, +}; + +static int mxc_sgtl5000_plat_init(void) +{ + struct regulator *reg; + reg = regulator_get(&mxc_sgtl5000_device.dev, "GPO2"); + if (IS_ERR(reg)) + return -EINVAL; + sgtl5000_data.priv = reg; + return 0; +} + +static int mxc_sgtl5000_plat_finit(void) +{ + struct regulator *reg; + reg = sgtl5000_data.priv; + if (reg) { + regulator_put(reg); + sgtl5000_data.priv = NULL; + } + return 0; +} + +static int mxc_sgtl5000_amp_enable(int enable) +{ + struct regulator *reg; + reg = sgtl5000_data.priv; + + if (!reg) + return -EINVAL; + if (enable) + regulator_enable(reg); + else + regulator_disable(reg); + return 0; +} + +static void mxc_init_sgtl5000(void) +{ + platform_device_register(&mxc_sgtl5000_device); +} +#else +static inline void mxc_init_sgtl5000(void) +{ +} +#endif + +static void bt_reset(void) +{ + gpio_set_value(IOMUX_TO_GPIO(MX51_PIN_EIM_D19), 1); +} + +static struct mxc_bt_platform_data mxc_bt_data = { + .bt_vdd = NULL, + .bt_vdd_parent = NULL, + .bt_vusb = "SW4", + .bt_vusb_parent = NULL, + .bt_reset = bt_reset, +}; + +static struct platform_device mxc_bt_device = { + .name = "mxc_bt", + .id = 0, + .dev = { + .release = mxc_nop_release, + .platform_data = &mxc_bt_data, + }, +}; + +static void mxc_init_bluetooth(void) +{ + (void)platform_device_register(&mxc_bt_device); +} + +static void mxc_unifi_hardreset(int pin_level) +{ + gpio_set_value(IOMUX_TO_GPIO(MX51_PIN_EIM_D19), pin_level & 0x01); +} + +static struct mxc_unifi_platform_data unifi_data = { + .hardreset = mxc_unifi_hardreset, + .reg_vdd_vpa = "VSD", + .reg_1v5_dd = "VGEN1", + .host_id = 1, +}; + +struct mxc_unifi_platform_data *get_unifi_plat_data(void) +{ + return &unifi_data; +} + +EXPORT_SYMBOL(get_unifi_plat_data); + +/*! + * Board specific fixup function. It is called by \b setup_arch() in + * setup.c file very early on during kernel starts. It allows the user to + * statically fill in the proper values for the passed-in parameters. None of + * the parameters is used currently. + * + * @param desc pointer to \b struct \b machine_desc + * @param tags pointer to \b struct \b tag + * @param cmdline pointer to the command line + * @param mi pointer to \b struct \b meminfo + */ +static void __init fixup_mxc_board(struct machine_desc *desc, struct tag *tags, + char **cmdline, struct meminfo *mi) +{ + mxc_cpu_init(); + + get_cpu_wp = mx51_3stack_get_cpu_wp; + set_num_cpu_wp = mx51_3stack_set_num_cpu_wp; +#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 +} + +#if defined(CONFIG_GPS_IOCTRL) || defined(CONFIG_GPS_IOCTRL_MODULE) +static struct mxc_gps_platform_data gps_data = { + .core_reg = "VIOHI", + .analog_reg = "SW4", +}; + +static struct platform_device mxc_gps_device = { + .name = "gps_ioctrl", + .id = -1, + .dev = { + .platform_data = &gps_data, + }, +}; + +static void __init mxc_init_gps(void) +{ + (void)platform_device_register(&mxc_gps_device); +} + +int gpio_gps_access(int para) +{ + iomux_pin_name_t pin; + pin = (para & 0x1) ? MX51_PIN_EIM_CS2 : MX51_PIN_EIM_CRE; + + if (para & 0x4) /* Read GPIO */ + return gpio_get_value(IOMUX_TO_GPIO(pin)); + else if (para & 0x2) /* Write GPIO */ + gpio_set_value(IOMUX_TO_GPIO(pin), 1); + else + gpio_set_value(IOMUX_TO_GPIO(pin), 0); + return 0; +} +EXPORT_SYMBOL(gpio_gps_access); +#else +static void __init mxc_init_gps(void) +{ +} +#endif + +/*! + * Board specific initialization. + */ +static void __init mxc_board_init(void) +{ + int err; + + mxc_cpu_common_init(); + mxc_register_gpios(); + mx51_3stack_io_init(); + early_console_setup(saved_command_line); + mxc_init_devices(); + + mxc_expio_init(); + mxc_init_enet(); + mxc_init_pata(); + mxc_init_fb(); + mxc_init_bl(); + mxc_init_keypad(); + mxc_init_nand_mtd(); + imx_nfc_init(); + mxc_init_mmc(); + mxc_init_sim(); + mxc_init_srpgconfig(); + mx51_3stack_init_mc13892(); + +#if defined(CONFIG_I2C_MXC) || defined(CONFIG_I2C_MXC_MODULE) + +#ifdef CONFIG_I2C_MXC_SELECT1 + i2c_register_board_info(0, mxc_i2c0_board_info, + ARRAY_SIZE(mxc_i2c0_board_info)); +#endif +#ifdef CONFIG_I2C_MXC_SELECT2 + i2c_register_board_info(1, mxc_i2c1_board_info, + ARRAY_SIZE(mxc_i2c1_board_info)); +#endif +#if defined(CONFIG_I2C_MXC_HS) || defined(CONFIG_I2C_MXC_HS_MODULE) + i2c_register_board_info(3, mxc_i2c_hs_board_info, + ARRAY_SIZE(mxc_i2c_hs_board_info)); +#endif + +#endif + mxc_init_touchscreen(); + mxc_init_wm8903(); + mxc_init_sgtl5000(); + mxc_init_bluetooth(); + mxc_init_gps(); + + err = mxc_request_iomux(MX51_PIN_EIM_D19, IOMUX_CONFIG_GPIO); + if (err) + printk(KERN_ERR "Error: bt reset request gpio failed!\n"); + else { + gpio_request(IOMUX_TO_GPIO(MX51_PIN_EIM_D19), "eim_d19"); + gpio_direction_output(IOMUX_TO_GPIO(MX51_PIN_EIM_D19), 0); + } +} + +static void __init mx51_3stack_timer_init(void) +{ + /* Change the CPU voltages for TO2*/ + if (cpu_is_mx51_rev(CHIP_REV_2_0) <= 1) { + cpu_wp_auto[0].cpu_voltage = 1175000; + cpu_wp_auto[1].cpu_voltage = 1100000; + cpu_wp_auto[2].cpu_voltage = 1000000; + } + + mxc_clocks_init(32768, 24000000, 22579200, 24576000); + mxc_timer_init("gpt_clk.0"); +} + +static struct sys_timer mxc_timer = { + .init = mx51_3stack_timer_init, +}; + +/* + * The following uses standard kernel macros define in arch.h in order to + * initialize __mach_desc_MX51_3STACK data structure. + */ +/* *INDENT-OFF* */ +MACHINE_START(MX51_3DS, "Freescale MX51 3-Stack Board") + /* Maintainer: Freescale Semiconductor, Inc. */ + .phys_io = AIPS1_BASE_ADDR, + .io_pg_offst = ((AIPS1_BASE_ADDR_VIRT) >> 18) & 0xfffc, + .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-mx51/mx51_3stack_gpio.c b/arch/arm/mach-mx51/mx51_3stack_gpio.c new file mode 100644 index 000000000000..dfa57920b07b --- /dev/null +++ b/arch/arm/mach-mx51/mx51_3stack_gpio.c @@ -0,0 +1,852 @@ +/* + * Copyright 2008-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/platform_device.h> +#include <linux/delay.h> +#include <asm/io.h> +#include <mach/hardware.h> +#include <mach/clock.h> +#include <mach/gpio.h> + +#include "iomux.h" + +/*! + * @file mach-mx51/mx51_3stack_gpio.c + * + * @brief This file contains all the GPIO setup functions for the board. + * + * @ingroup GPIO + */ +#define ATA_PAD_CONFIG (PAD_CTL_DRV_HIGH | PAD_CTL_DRV_VOT_HIGH) + +static struct mxc_iomux_pin_cfg __initdata mxc_iomux_pins[] = { + /* CSI0 */ + { + MX51_PIN_CSI1_D8, IOMUX_CONFIG_ALT3, + PAD_CTL_PKE_ENABLE, + MUX_IN_GPIO3_IPP_IND_G_IN_12_SELECT_INPUT, + INPUT_CTL_PATH1, + }, + { + MX51_PIN_CSI1_D9, IOMUX_CONFIG_ALT3, + PAD_CTL_PKE_ENABLE, + }, + { + MX51_PIN_CSI1_D10, IOMUX_CONFIG_ALT0, PAD_CTL_HYS_NONE, + }, + { + MX51_PIN_CSI1_D11, IOMUX_CONFIG_ALT0, PAD_CTL_HYS_NONE, + }, + { + MX51_PIN_CSI1_D12, IOMUX_CONFIG_ALT0, PAD_CTL_HYS_NONE, + }, + { + MX51_PIN_CSI1_D13, IOMUX_CONFIG_ALT0, PAD_CTL_HYS_NONE, + }, + { + MX51_PIN_CSI1_D14, IOMUX_CONFIG_ALT0, PAD_CTL_HYS_NONE, + }, + { + MX51_PIN_CSI1_D15, IOMUX_CONFIG_ALT0, PAD_CTL_HYS_NONE, + }, + { + MX51_PIN_CSI1_D16, IOMUX_CONFIG_ALT0, PAD_CTL_HYS_NONE, + }, + { + MX51_PIN_CSI1_D17, IOMUX_CONFIG_ALT0, PAD_CTL_HYS_NONE, + }, + { + MX51_PIN_CSI1_D18, IOMUX_CONFIG_ALT0, PAD_CTL_HYS_NONE, + }, + { + MX51_PIN_CSI1_D19, IOMUX_CONFIG_ALT0, PAD_CTL_HYS_NONE, + }, + { + MX51_PIN_CSI1_VSYNC, IOMUX_CONFIG_ALT0, + (PAD_CTL_HYS_NONE | PAD_CTL_SRE_SLOW), + }, + { + MX51_PIN_CSI1_HSYNC, IOMUX_CONFIG_ALT0, + (PAD_CTL_HYS_NONE | PAD_CTL_SRE_SLOW), + }, + { + MX51_PIN_EIM_A26, IOMUX_CONFIG_ALT5 | IOMUX_CONFIG_SION, + (PAD_CTL_SRE_SLOW | PAD_CTL_DRV_MEDIUM | PAD_CTL_100K_PU | + PAD_CTL_HYS_ENABLE | PAD_CTL_DRV_VOT_HIGH), + MUX_IN_HSC_MIPI_MIX_IPP_IND_SENS2_DATA_EN_SELECT_INPUT, + INPUT_CTL_PATH0, + }, + { /* SPI1 */ + MX51_PIN_CSPI1_MISO, IOMUX_CONFIG_ALT0, + (PAD_CTL_HYS_ENABLE | PAD_CTL_PKE_ENABLE | PAD_CTL_DRV_HIGH | + PAD_CTL_SRE_FAST), + }, + { + MX51_PIN_CSPI1_MOSI, IOMUX_CONFIG_ALT0, + (PAD_CTL_HYS_ENABLE | PAD_CTL_PKE_ENABLE | PAD_CTL_DRV_HIGH | + PAD_CTL_SRE_FAST), + }, + { + MX51_PIN_CSPI1_RDY, IOMUX_CONFIG_ALT0, + (PAD_CTL_HYS_ENABLE | PAD_CTL_PKE_ENABLE | PAD_CTL_DRV_HIGH | + PAD_CTL_SRE_FAST), + }, + { + MX51_PIN_CSPI1_SCLK, IOMUX_CONFIG_ALT0, + (PAD_CTL_HYS_ENABLE | PAD_CTL_PKE_ENABLE | PAD_CTL_DRV_HIGH | + PAD_CTL_SRE_FAST), + }, + { + MX51_PIN_OWIRE_LINE, IOMUX_CONFIG_ALT0, + (PAD_CTL_HYS_ENABLE | PAD_CTL_PKE_ENABLE | + PAD_CTL_ODE_OPENDRAIN_ENABLE | PAD_CTL_DRV_HIGH | + PAD_CTL_SRE_FAST), + }, + { + MX51_PIN_DISP2_DAT15, IOMUX_CONFIG_ALT5, + }, + { + MX51_PIN_DI_GP2, IOMUX_CONFIG_ALT0, + }, + { + MX51_PIN_DI_GP3, IOMUX_CONFIG_ALT0, + }, + { + MX51_PIN_KEY_COL0, IOMUX_CONFIG_ALT0, + }, + { + MX51_PIN_KEY_COL1, IOMUX_CONFIG_ALT0, + }, + { + MX51_PIN_KEY_COL2, IOMUX_CONFIG_ALT0, + }, + { + MX51_PIN_KEY_COL3, IOMUX_CONFIG_ALT0, + }, + { + MX51_PIN_KEY_COL4, IOMUX_CONFIG_ALT0, + }, + { + MX51_PIN_KEY_COL5, IOMUX_CONFIG_ALT0, + }, + { + MX51_PIN_KEY_ROW0, IOMUX_CONFIG_ALT0, + }, + { + MX51_PIN_KEY_ROW1, IOMUX_CONFIG_ALT0, + }, + { + MX51_PIN_KEY_ROW2, IOMUX_CONFIG_ALT0, + }, + { + MX51_PIN_KEY_ROW3, IOMUX_CONFIG_ALT0, + }, + { /* AUD3_TXD */ + MX51_PIN_AUD3_BB_TXD, IOMUX_CONFIG_ALT0, + (PAD_CTL_SRE_FAST | PAD_CTL_DRV_HIGH | + PAD_CTL_ODE_OPENDRAIN_NONE | PAD_CTL_100K_PU | + PAD_CTL_HYS_NONE | PAD_CTL_DDR_INPUT_CMOS | PAD_CTL_DRV_VOT_LOW), + }, + { /* AUD3_RXD */ + MX51_PIN_AUD3_BB_RXD, IOMUX_CONFIG_ALT0, + (PAD_CTL_SRE_FAST | PAD_CTL_DRV_HIGH | + PAD_CTL_ODE_OPENDRAIN_NONE | PAD_CTL_100K_PU | + PAD_CTL_HYS_NONE | PAD_CTL_DDR_INPUT_CMOS | PAD_CTL_DRV_VOT_LOW), + }, + { /* AUD3_CLK */ + MX51_PIN_AUD3_BB_CK, IOMUX_CONFIG_ALT0, + (PAD_CTL_SRE_FAST | PAD_CTL_DRV_HIGH | + PAD_CTL_ODE_OPENDRAIN_NONE | PAD_CTL_100K_PU | + PAD_CTL_HYS_NONE | PAD_CTL_DDR_INPUT_CMOS | PAD_CTL_DRV_VOT_LOW), + }, + { /* AUD3_FS */ + MX51_PIN_AUD3_BB_FS, IOMUX_CONFIG_ALT0, + (PAD_CTL_SRE_FAST | PAD_CTL_DRV_HIGH | + PAD_CTL_ODE_OPENDRAIN_NONE | PAD_CTL_100K_PU | + PAD_CTL_HYS_NONE | PAD_CTL_DDR_INPUT_CMOS | PAD_CTL_DRV_VOT_LOW), + }, + { + MX51_PIN_EIM_D16, IOMUX_CONFIG_ALT1, + (PAD_CTL_DRV_HIGH | PAD_CTL_100K_PU | + PAD_CTL_PKE_ENABLE | PAD_CTL_SRE_FAST), + }, + { + MX51_PIN_EIM_A27, IOMUX_CONFIG_ALT2, + (PAD_CTL_SRE_FAST | PAD_CTL_DRV_HIGH | PAD_CTL_100K_PU | + PAD_CTL_PUE_KEEPER | PAD_CTL_PKE_ENABLE | PAD_CTL_HYS_ENABLE), + }, + { + MX51_PIN_EIM_EB2, IOMUX_CONFIG_ALT1, + PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | PAD_CTL_100K_PD, + }, + { + MX51_PIN_EIM_DTACK, IOMUX_CONFIG_GPIO, + (PAD_CTL_PKE_ENABLE | PAD_CTL_100K_PU), + }, + { + MX51_PIN_EIM_CS2, IOMUX_CONFIG_GPIO, + (PAD_CTL_DRV_HIGH | PAD_CTL_HYS_NONE | PAD_CTL_PUE_KEEPER | + PAD_CTL_100K_PU | PAD_CTL_PKE_ENABLE | PAD_CTL_SRE_FAST), + }, + { + MX51_PIN_EIM_CRE, IOMUX_CONFIG_GPIO, + (PAD_CTL_DRV_HIGH | PAD_CTL_HYS_NONE | PAD_CTL_PUE_KEEPER | + PAD_CTL_100K_PU | PAD_CTL_PKE_ENABLE | PAD_CTL_SRE_FAST), + }, + { + MX51_PIN_DI_GP4, IOMUX_CONFIG_ALT2, + }, + { + MX51_PIN_DISPB2_SER_DIN, IOMUX_CONFIG_GPIO, + 0, + MUX_IN_GPIO3_IPP_IND_G_IN_5_SELECT_INPUT, + INPUT_CTL_PATH1, + }, + { + MX51_PIN_DISPB2_SER_RS, IOMUX_CONFIG_GPIO, + }, + { + MX51_PIN_DISPB2_SER_DIO, IOMUX_CONFIG_GPIO, + }, + { /* TO2 */ + MX51_PIN_DI1_D1_CS, IOMUX_CONFIG_ALT4, + }, + { /* TO2 */ + MX51_PIN_DI1_D0_CS, IOMUX_CONFIG_ALT1, + }, + { /* TO2 */ + MX51_PIN_DI1_PIN11, IOMUX_CONFIG_ALT1, + }, + { /* TO2 */ + MX51_PIN_DI1_PIN12, IOMUX_CONFIG_ALT1, + }, + { /* TO2 */ + MX51_PIN_DI1_PIN13, IOMUX_CONFIG_ALT1, + }, +#ifdef CONFIG_FB_MXC_CLAA_WVGA_SYNC_PANEL + { + MX51_PIN_DISP1_DAT0, IOMUX_CONFIG_ALT0, + (PAD_CTL_HYS_NONE | PAD_CTL_DRV_LOW | PAD_CTL_SRE_FAST), + }, + { + MX51_PIN_DISP1_DAT1, IOMUX_CONFIG_ALT0, + (PAD_CTL_HYS_NONE | PAD_CTL_DRV_LOW | PAD_CTL_SRE_FAST), + }, + { + MX51_PIN_DISP1_DAT2, IOMUX_CONFIG_ALT0, + (PAD_CTL_HYS_NONE | PAD_CTL_DRV_LOW | PAD_CTL_SRE_FAST), + }, + { + MX51_PIN_DISP1_DAT3, IOMUX_CONFIG_ALT0, + (PAD_CTL_HYS_NONE | PAD_CTL_DRV_LOW | PAD_CTL_SRE_FAST), + }, + { + MX51_PIN_DISP1_DAT4, IOMUX_CONFIG_ALT0, + (PAD_CTL_HYS_NONE | PAD_CTL_DRV_LOW | PAD_CTL_SRE_FAST), + }, + { + MX51_PIN_DISP1_DAT5, IOMUX_CONFIG_ALT0, + (PAD_CTL_HYS_NONE | PAD_CTL_DRV_LOW | PAD_CTL_SRE_FAST), + }, + { + MX51_PIN_DISP1_DAT6, IOMUX_CONFIG_ALT0, + (PAD_CTL_HYS_NONE | PAD_CTL_DRV_LOW | PAD_CTL_SRE_FAST), + }, + { + MX51_PIN_DISP1_DAT7, IOMUX_CONFIG_ALT0, + (PAD_CTL_HYS_NONE | PAD_CTL_DRV_LOW | PAD_CTL_SRE_FAST), + }, + { + MX51_PIN_DISP1_DAT8, IOMUX_CONFIG_ALT0, + (PAD_CTL_HYS_NONE | PAD_CTL_DRV_LOW | PAD_CTL_SRE_FAST), + }, + { + MX51_PIN_DISP1_DAT9, IOMUX_CONFIG_ALT0, + (PAD_CTL_HYS_NONE | PAD_CTL_DRV_LOW | PAD_CTL_SRE_FAST), + }, + { + MX51_PIN_DISP1_DAT10, IOMUX_CONFIG_ALT0, + (PAD_CTL_HYS_NONE | PAD_CTL_DRV_LOW | PAD_CTL_SRE_FAST), + }, + { + MX51_PIN_DISP1_DAT11, IOMUX_CONFIG_ALT0, + (PAD_CTL_HYS_NONE | PAD_CTL_DRV_LOW | PAD_CTL_SRE_FAST), + }, + { + MX51_PIN_DISP1_DAT12, IOMUX_CONFIG_ALT0, + (PAD_CTL_HYS_NONE | PAD_CTL_DRV_LOW | PAD_CTL_SRE_FAST), + }, + { + MX51_PIN_DISP1_DAT13, IOMUX_CONFIG_ALT0, + (PAD_CTL_HYS_NONE | PAD_CTL_DRV_LOW | PAD_CTL_SRE_FAST), + }, + { + MX51_PIN_DISP1_DAT14, IOMUX_CONFIG_ALT0, + (PAD_CTL_HYS_NONE | PAD_CTL_DRV_LOW | PAD_CTL_SRE_FAST), + }, + { + MX51_PIN_DISP1_DAT15, IOMUX_CONFIG_ALT0, + (PAD_CTL_HYS_NONE | PAD_CTL_DRV_LOW | PAD_CTL_SRE_FAST), + }, + { + MX51_PIN_DISP1_DAT16, IOMUX_CONFIG_ALT0, + (PAD_CTL_HYS_NONE | PAD_CTL_DRV_LOW | PAD_CTL_SRE_FAST), + }, + { + MX51_PIN_DISP1_DAT17, IOMUX_CONFIG_ALT0, + (PAD_CTL_HYS_NONE | PAD_CTL_DRV_LOW | PAD_CTL_SRE_FAST), + }, + { + MX51_PIN_DISP1_DAT18, IOMUX_CONFIG_ALT0, + (PAD_CTL_HYS_NONE | PAD_CTL_DRV_LOW | PAD_CTL_SRE_FAST), + }, + { + MX51_PIN_DISP1_DAT19, IOMUX_CONFIG_ALT0, + (PAD_CTL_HYS_NONE | PAD_CTL_DRV_LOW | PAD_CTL_SRE_FAST), + }, + { + MX51_PIN_DISP1_DAT20, IOMUX_CONFIG_ALT0, + (PAD_CTL_HYS_NONE | PAD_CTL_DRV_LOW | PAD_CTL_SRE_FAST), + }, + { + MX51_PIN_DISP1_DAT21, IOMUX_CONFIG_ALT0, + (PAD_CTL_HYS_NONE | PAD_CTL_DRV_LOW | PAD_CTL_SRE_FAST), + }, + { + MX51_PIN_DISP1_DAT22, IOMUX_CONFIG_ALT0, + (PAD_CTL_HYS_NONE | PAD_CTL_DRV_LOW | PAD_CTL_SRE_FAST), + }, + { + MX51_PIN_DISP1_DAT23, IOMUX_CONFIG_ALT0, + (PAD_CTL_HYS_NONE | PAD_CTL_DRV_LOW | PAD_CTL_SRE_FAST), + }, +#endif + { + MX51_PIN_I2C1_CLK, IOMUX_CONFIG_ALT0 | IOMUX_CONFIG_SION, + 0x1E4, + }, + { + MX51_PIN_I2C1_DAT, IOMUX_CONFIG_ALT0 | IOMUX_CONFIG_SION, + 0x1E4, + }, + { + MX51_PIN_GPIO1_6, IOMUX_CONFIG_GPIO, + }, + { + MX51_PIN_GPIO1_7, IOMUX_CONFIG_ALT2, + (PAD_CTL_DRV_HIGH | PAD_CTL_PUE_PULL | + PAD_CTL_100K_PU | PAD_CTL_PKE_ENABLE | + PAD_CTL_SRE_FAST), + }, + { + MX51_PIN_GPIO1_2, IOMUX_CONFIG_ALT2 | IOMUX_CONFIG_SION, + (PAD_CTL_SRE_FAST | PAD_CTL_ODE_OPENDRAIN_ENABLE | PAD_CTL_DRV_HIGH | + PAD_CTL_100K_PU | PAD_CTL_HYS_ENABLE), + MUX_IN_I2C2_IPP_SCL_IN_SELECT_INPUT, INPUT_CTL_PATH3, + }, + { + MX51_PIN_GPIO1_3, IOMUX_CONFIG_ALT2 | IOMUX_CONFIG_SION, + (PAD_CTL_SRE_FAST | PAD_CTL_ODE_OPENDRAIN_ENABLE | PAD_CTL_DRV_HIGH | + PAD_CTL_100K_PU | PAD_CTL_HYS_ENABLE), + MUX_IN_I2C2_IPP_SDA_IN_SELECT_INPUT, INPUT_CTL_PATH3, + }, + { + MX51_PIN_USBH1_STP, IOMUX_CONFIG_ALT0, + (PAD_CTL_SRE_FAST | PAD_CTL_DRV_HIGH | PAD_CTL_PUE_KEEPER | + PAD_CTL_PKE_ENABLE | PAD_CTL_HYS_ENABLE), + }, + { /* USBH1_CLK */ + MX51_PIN_USBH1_CLK, IOMUX_CONFIG_ALT0, + (PAD_CTL_SRE_FAST | PAD_CTL_DRV_HIGH | PAD_CTL_PUE_KEEPER | + PAD_CTL_PKE_ENABLE | PAD_CTL_HYS_ENABLE | PAD_CTL_DDR_INPUT_CMOS), + }, + { /* USBH1_DIR */ + MX51_PIN_USBH1_DIR, IOMUX_CONFIG_ALT0, + (PAD_CTL_SRE_FAST | PAD_CTL_DRV_HIGH | PAD_CTL_PUE_KEEPER | + PAD_CTL_PKE_ENABLE | PAD_CTL_HYS_ENABLE | PAD_CTL_DDR_INPUT_CMOS), + }, + { /* USBH1_NXT */ + MX51_PIN_USBH1_NXT, IOMUX_CONFIG_ALT0, + (PAD_CTL_SRE_FAST | PAD_CTL_DRV_HIGH | PAD_CTL_PUE_KEEPER | + PAD_CTL_PKE_ENABLE | PAD_CTL_HYS_ENABLE | PAD_CTL_DDR_INPUT_CMOS), + }, + { /* USBH1_DATA0 */ + MX51_PIN_USBH1_DATA0, IOMUX_CONFIG_ALT0, + (PAD_CTL_SRE_FAST | PAD_CTL_DRV_HIGH | PAD_CTL_100K_PU | + PAD_CTL_PUE_KEEPER | PAD_CTL_PKE_ENABLE | PAD_CTL_HYS_ENABLE), + }, + { /* USBH1_DATA1 */ + MX51_PIN_USBH1_DATA1, IOMUX_CONFIG_ALT0, + (PAD_CTL_SRE_FAST | PAD_CTL_DRV_HIGH | PAD_CTL_100K_PU | + PAD_CTL_PUE_KEEPER | PAD_CTL_PKE_ENABLE | PAD_CTL_HYS_ENABLE), + }, + { /* USBH1_DATA2 */ + MX51_PIN_USBH1_DATA2, IOMUX_CONFIG_ALT0, + (PAD_CTL_SRE_FAST | PAD_CTL_DRV_HIGH | PAD_CTL_100K_PU | + PAD_CTL_PUE_KEEPER | PAD_CTL_PKE_ENABLE | PAD_CTL_HYS_ENABLE), + }, + { /* USBH1_DATA3 */ + MX51_PIN_USBH1_DATA3, IOMUX_CONFIG_ALT0, + (PAD_CTL_SRE_FAST | PAD_CTL_DRV_HIGH | PAD_CTL_100K_PU | + PAD_CTL_PUE_KEEPER | PAD_CTL_PKE_ENABLE | PAD_CTL_HYS_ENABLE), + }, + { /* USBH1_DATA4 */ + MX51_PIN_USBH1_DATA4, IOMUX_CONFIG_ALT0, + (PAD_CTL_SRE_FAST | PAD_CTL_DRV_HIGH | PAD_CTL_100K_PU | + PAD_CTL_PUE_KEEPER | PAD_CTL_PKE_ENABLE | PAD_CTL_HYS_ENABLE), + }, + { /* USBH1_DATA5 */ + MX51_PIN_USBH1_DATA5, IOMUX_CONFIG_ALT0, + (PAD_CTL_SRE_FAST | PAD_CTL_DRV_HIGH | PAD_CTL_100K_PU | + PAD_CTL_PUE_KEEPER | PAD_CTL_PKE_ENABLE | PAD_CTL_HYS_ENABLE), + }, + { /* USBH1_DATA6 */ + MX51_PIN_USBH1_DATA6, IOMUX_CONFIG_ALT0, + (PAD_CTL_SRE_FAST | PAD_CTL_DRV_HIGH | PAD_CTL_100K_PU | + PAD_CTL_PUE_KEEPER | PAD_CTL_PKE_ENABLE | PAD_CTL_HYS_ENABLE), + }, + { /* USBH1_DATA7 */ + MX51_PIN_USBH1_DATA7, IOMUX_CONFIG_ALT0, + (PAD_CTL_SRE_FAST | PAD_CTL_DRV_HIGH | PAD_CTL_100K_PU | + PAD_CTL_PUE_KEEPER | PAD_CTL_PKE_ENABLE | PAD_CTL_HYS_ENABLE), + }, + { /* USB1_OC */ + MX51_PIN_GPIO1_9, IOMUX_CONFIG_ALT1, + (PAD_CTL_SRE_SLOW | PAD_CTL_DRV_LOW | PAD_CTL_ODE_OPENDRAIN_NONE | + PAD_CTL_PUE_KEEPER | PAD_CTL_PKE_ENABLE | + PAD_CTL_HYS_ENABLE), + }, + { /* USB1_PWR */ + MX51_PIN_GPIO1_8, IOMUX_CONFIG_ALT1, + (PAD_CTL_SRE_FAST | PAD_CTL_DRV_HIGH | PAD_CTL_ODE_OPENDRAIN_NONE | + PAD_CTL_PKE_NONE | PAD_CTL_HYS_ENABLE), + }, + { + MX51_PIN_SD1_CMD, IOMUX_CONFIG_ALT0 | IOMUX_CONFIG_SION, + (PAD_CTL_DRV_MAX | PAD_CTL_22K_PU | PAD_CTL_SRE_FAST), + }, + { + MX51_PIN_SD1_CLK, IOMUX_CONFIG_ALT0 | IOMUX_CONFIG_SION, + (PAD_CTL_DRV_MAX | PAD_CTL_22K_PU | PAD_CTL_SRE_FAST), + }, + { + MX51_PIN_SD1_DATA0, IOMUX_CONFIG_ALT0, + (PAD_CTL_DRV_MAX | PAD_CTL_22K_PU | PAD_CTL_SRE_FAST), + }, + { + MX51_PIN_SD1_DATA1, IOMUX_CONFIG_ALT0, + (PAD_CTL_DRV_MAX | PAD_CTL_22K_PU | PAD_CTL_SRE_FAST), + }, + { + MX51_PIN_SD1_DATA2, IOMUX_CONFIG_ALT0, + (PAD_CTL_DRV_MAX | PAD_CTL_22K_PU | PAD_CTL_SRE_FAST), + }, + { + MX51_PIN_SD1_DATA3, IOMUX_CONFIG_ALT0, + (PAD_CTL_DRV_MAX | PAD_CTL_22K_PU | PAD_CTL_SRE_FAST), + }, + { + MX51_PIN_GPIO1_0, IOMUX_CONFIG_GPIO | IOMUX_CONFIG_SION, + (PAD_CTL_HYS_ENABLE | PAD_CTL_100K_PU), + }, + { + MX51_PIN_GPIO1_1, IOMUX_CONFIG_GPIO | IOMUX_CONFIG_SION, + (PAD_CTL_HYS_ENABLE | PAD_CTL_100K_PU), + }, + { + MX51_PIN_SD2_CMD, IOMUX_CONFIG_ALT0 | IOMUX_CONFIG_SION, + (PAD_CTL_DRV_MAX | PAD_CTL_22K_PU | PAD_CTL_SRE_FAST), + }, + { + MX51_PIN_SD2_CLK, IOMUX_CONFIG_ALT0 | IOMUX_CONFIG_SION, + (PAD_CTL_DRV_MAX | PAD_CTL_22K_PU | PAD_CTL_SRE_FAST), + }, + { + MX51_PIN_SD2_DATA0, IOMUX_CONFIG_ALT0, + (PAD_CTL_DRV_MAX | PAD_CTL_22K_PU | PAD_CTL_SRE_FAST), + }, + { + MX51_PIN_SD2_DATA1, IOMUX_CONFIG_ALT0, + (PAD_CTL_DRV_MAX | PAD_CTL_22K_PU | PAD_CTL_SRE_FAST), + }, + { + MX51_PIN_SD2_DATA2, IOMUX_CONFIG_ALT0, + (PAD_CTL_DRV_MAX | PAD_CTL_22K_PU | PAD_CTL_SRE_FAST), + }, + { + MX51_PIN_SD2_DATA3, IOMUX_CONFIG_ALT0, + (PAD_CTL_DRV_MAX | PAD_CTL_22K_PU | PAD_CTL_SRE_FAST), + }, + { + MX51_PIN_UART1_RXD, IOMUX_CONFIG_ALT0, + (PAD_CTL_HYS_ENABLE | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | + PAD_CTL_DRV_HIGH | PAD_CTL_SRE_FAST), + MUX_IN_UART1_IPP_UART_RXD_MUX_SELECT_INPUT, + INPUT_CTL_PATH0, + }, + { + MX51_PIN_UART1_TXD, IOMUX_CONFIG_ALT0, + (PAD_CTL_HYS_ENABLE | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | + PAD_CTL_DRV_HIGH | PAD_CTL_SRE_FAST), + }, + { + MX51_PIN_UART1_RTS, IOMUX_CONFIG_ALT0, + (PAD_CTL_HYS_ENABLE | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | + PAD_CTL_DRV_HIGH), + MUX_IN_UART1_IPP_UART_RTS_B_SELECT_INPUT, + INPUT_CTL_PATH0, + }, + { + MX51_PIN_UART1_CTS, IOMUX_CONFIG_ALT0, + (PAD_CTL_HYS_ENABLE | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | + PAD_CTL_DRV_HIGH), + }, + { + MX51_PIN_UART2_RXD, IOMUX_CONFIG_ALT0, + (PAD_CTL_HYS_NONE | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | + PAD_CTL_DRV_HIGH | PAD_CTL_SRE_FAST), + MUX_IN_UART2_IPP_UART_RXD_MUX_SELECT_INPUT, + INPUT_CTL_PATH2, + }, + { + MX51_PIN_UART2_TXD, IOMUX_CONFIG_ALT0, + (PAD_CTL_HYS_NONE | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | + PAD_CTL_DRV_HIGH | PAD_CTL_SRE_FAST), + }, + { + MX51_PIN_EIM_D26, IOMUX_CONFIG_ALT4, + (PAD_CTL_HYS_NONE | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_KEEPER | + PAD_CTL_DRV_HIGH | PAD_CTL_SRE_FAST), + MUX_IN_UART2_IPP_UART_RTS_B_SELECT_INPUT, + INPUT_CTL_PATH3, + }, + { + MX51_PIN_EIM_D25, IOMUX_CONFIG_ALT4, + (PAD_CTL_HYS_NONE | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_KEEPER | + PAD_CTL_DRV_HIGH | PAD_CTL_SRE_FAST), + }, + { + MX51_PIN_UART3_RXD, IOMUX_CONFIG_ALT1, + (PAD_CTL_HYS_NONE | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_KEEPER | + PAD_CTL_DRV_HIGH | PAD_CTL_SRE_FAST), + MUX_IN_UART3_IPP_UART_RXD_MUX_SELECT_INPUT, + INPUT_CTL_PATH4, + }, + { + MX51_PIN_UART3_TXD, IOMUX_CONFIG_ALT1, + (PAD_CTL_HYS_NONE | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_KEEPER | + PAD_CTL_DRV_HIGH | PAD_CTL_SRE_FAST), + }, + { + MX51_PIN_EIM_D27, IOMUX_CONFIG_ALT3, + (PAD_CTL_HYS_NONE | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_KEEPER | + PAD_CTL_DRV_HIGH | PAD_CTL_SRE_FAST), + MUX_IN_UART3_IPP_UART_RTS_B_SELECT_INPUT, + INPUT_CTL_PATH3, + }, + { + MX51_PIN_EIM_D24, IOMUX_CONFIG_ALT3, + (PAD_CTL_HYS_NONE | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_KEEPER | + PAD_CTL_DRV_HIGH | PAD_CTL_SRE_FAST), + }, +}; + +static struct mxc_iomux_pin_cfg __initdata ata_iomux_pins[] = { + { + MX51_PIN_NANDF_ALE, IOMUX_CONFIG_ALT1, + ATA_PAD_CONFIG, + }, + { + MX51_PIN_NANDF_CS2, IOMUX_CONFIG_ALT1, + ATA_PAD_CONFIG, + }, + { + MX51_PIN_NANDF_CS3, IOMUX_CONFIG_ALT1, + ATA_PAD_CONFIG, + }, + { + MX51_PIN_NANDF_CS4, IOMUX_CONFIG_ALT1, + ATA_PAD_CONFIG, + }, + { + MX51_PIN_NANDF_CS5, IOMUX_CONFIG_ALT1, + ATA_PAD_CONFIG, + }, + { + MX51_PIN_NANDF_CS6, IOMUX_CONFIG_ALT1, + ATA_PAD_CONFIG, + }, + { + MX51_PIN_NANDF_RE_B, IOMUX_CONFIG_ALT1, + ATA_PAD_CONFIG, + }, + { + MX51_PIN_NANDF_WE_B, IOMUX_CONFIG_ALT1, + ATA_PAD_CONFIG, + }, + { + MX51_PIN_NANDF_CLE, IOMUX_CONFIG_ALT1, + ATA_PAD_CONFIG, + }, + { + MX51_PIN_NANDF_RB0, IOMUX_CONFIG_ALT1, + ATA_PAD_CONFIG, + }, + { + MX51_PIN_NANDF_WP_B, IOMUX_CONFIG_ALT1, + ATA_PAD_CONFIG, + }, + /* TO 2.0 */ + { + MX51_PIN_GPIO_NAND, IOMUX_CONFIG_ALT1, + ATA_PAD_CONFIG, + }, + /* TO 1.0 */ + { + MX51_PIN_NANDF_RB5, IOMUX_CONFIG_ALT1, + ATA_PAD_CONFIG, + }, + { + MX51_PIN_NANDF_RB1, IOMUX_CONFIG_ALT1, + ATA_PAD_CONFIG, + }, + { + MX51_PIN_NANDF_D0, IOMUX_CONFIG_ALT1, + ATA_PAD_CONFIG, + }, + { + MX51_PIN_NANDF_D1, IOMUX_CONFIG_ALT1, + ATA_PAD_CONFIG, + }, + { + MX51_PIN_NANDF_D2, IOMUX_CONFIG_ALT1, + ATA_PAD_CONFIG, + }, + { + MX51_PIN_NANDF_D3, IOMUX_CONFIG_ALT1, + ATA_PAD_CONFIG, + }, + { + MX51_PIN_NANDF_D4, IOMUX_CONFIG_ALT1, + ATA_PAD_CONFIG, + }, + { + MX51_PIN_NANDF_D5, IOMUX_CONFIG_ALT1, + ATA_PAD_CONFIG, + }, + { + MX51_PIN_NANDF_D6, IOMUX_CONFIG_ALT1, + ATA_PAD_CONFIG, + }, + { + MX51_PIN_NANDF_D7, IOMUX_CONFIG_ALT1, + ATA_PAD_CONFIG, + }, + { + MX51_PIN_NANDF_D8, IOMUX_CONFIG_ALT1, + ATA_PAD_CONFIG, + }, + { + MX51_PIN_NANDF_D9, IOMUX_CONFIG_ALT1, + ATA_PAD_CONFIG, + }, + { + MX51_PIN_NANDF_D10, IOMUX_CONFIG_ALT1, + ATA_PAD_CONFIG, + }, + { + MX51_PIN_NANDF_D11, IOMUX_CONFIG_ALT1, + ATA_PAD_CONFIG, + }, + { + MX51_PIN_NANDF_D12, IOMUX_CONFIG_ALT1, + ATA_PAD_CONFIG, + }, + { + MX51_PIN_NANDF_D13, IOMUX_CONFIG_ALT1, + ATA_PAD_CONFIG, + }, + { + MX51_PIN_NANDF_D14, IOMUX_CONFIG_ALT1, + ATA_PAD_CONFIG, + }, + { + MX51_PIN_NANDF_D15, IOMUX_CONFIG_ALT1, + ATA_PAD_CONFIG, + }, +}; + +static struct mxc_iomux_pin_cfg __initdata nand_iomux_pins[] = { + { + MX51_PIN_NANDF_CS0, IOMUX_CONFIG_ALT0, + }, + { + MX51_PIN_NANDF_CS1, IOMUX_CONFIG_ALT0, + }, + { + MX51_PIN_NANDF_CS2, IOMUX_CONFIG_ALT0, + }, + { + MX51_PIN_NANDF_CS3, IOMUX_CONFIG_ALT0, + }, + { + MX51_PIN_NANDF_CS4, IOMUX_CONFIG_ALT0, + }, + { + MX51_PIN_NANDF_CS5, IOMUX_CONFIG_ALT0, + }, + { + MX51_PIN_NANDF_CS6, IOMUX_CONFIG_ALT0, + }, + { + MX51_PIN_NANDF_CS7, IOMUX_CONFIG_ALT0, + }, + /* TO2 */ + { + MX51_PIN_GPIO_NAND, IOMUX_CONFIG_ALT0, + }, + /* TO1 */ + { + MX51_PIN_NANDF_RB5, IOMUX_CONFIG_ALT0, + }, +}; + +static struct mxc_iomux_pin_cfg __initdata sim_iomux_pins[] = { + { + MX51_PIN_NANDF_CS4, IOMUX_CONFIG_ALT6, + PAD_CTL_DRV_HIGH | PAD_CTL_DRV_VOT_HIGH | + PAD_CTL_HYS_NONE | PAD_CTL_47K_PU | + PAD_CTL_PUE_KEEPER | PAD_CTL_ODE_OPENDRAIN_NONE | PAD_CTL_PKE_ENABLE, + }, + { + MX51_PIN_NANDF_CS5, IOMUX_CONFIG_ALT6, + PAD_CTL_DRV_HIGH | PAD_CTL_DRV_VOT_HIGH | + PAD_CTL_HYS_NONE | PAD_CTL_47K_PU | + PAD_CTL_PUE_KEEPER | PAD_CTL_ODE_OPENDRAIN_NONE | PAD_CTL_PKE_ENABLE, + }, + { + MX51_PIN_NANDF_CS6, IOMUX_CONFIG_ALT6, + PAD_CTL_DRV_HIGH | PAD_CTL_DRV_VOT_HIGH | + PAD_CTL_HYS_NONE | PAD_CTL_100K_PD | + PAD_CTL_PUE_PULL | PAD_CTL_ODE_OPENDRAIN_NONE | PAD_CTL_PKE_ENABLE, + }, + { + MX51_PIN_NANDF_CS7, IOMUX_CONFIG_ALT6, + PAD_CTL_DRV_HIGH | PAD_CTL_DRV_VOT_HIGH | + PAD_CTL_HYS_NONE | PAD_CTL_22K_PU | + PAD_CTL_PUE_PULL | PAD_CTL_ODE_OPENDRAIN_NONE | PAD_CTL_PKE_ENABLE, + }, +}; + +static int __initdata enable_ata = { 0 }; +static int __init ata_setup(char *__unused) +{ + enable_ata = 1; + return 1; +} + +__setup("ata", ata_setup); + +static int __initdata enable_sim = { 0 }; +static int __init sim_setup(char *__unused) +{ + enable_sim = 1; + return 1; +} + +__setup("sim", sim_setup); + +void __init mx51_3stack_io_init(void) +{ + int i, num; + struct mxc_iomux_pin_cfg *pin_ptr; + + for (i = 0; i < ARRAY_SIZE(mxc_iomux_pins); i++) { + mxc_request_iomux(mxc_iomux_pins[i].pin, + mxc_iomux_pins[i].mux_mode); + if (mxc_iomux_pins[i].pad_cfg) + mxc_iomux_set_pad(mxc_iomux_pins[i].pin, + mxc_iomux_pins[i].pad_cfg); + if (mxc_iomux_pins[i].in_select) + mxc_iomux_set_input(mxc_iomux_pins[i].in_select, + mxc_iomux_pins[i].in_mode); + } + + if (enable_ata) { + pin_ptr = ata_iomux_pins; + num = ARRAY_SIZE(ata_iomux_pins); + } else if (enable_sim) { + pin_ptr = sim_iomux_pins; + num = ARRAY_SIZE(sim_iomux_pins); + } else { + pin_ptr = nand_iomux_pins; + num = ARRAY_SIZE(nand_iomux_pins); + } + + for (i = 0; i < num; i++) { + mxc_request_iomux(pin_ptr[i].pin, pin_ptr[i].mux_mode); + if (pin_ptr[i].pad_cfg) + mxc_iomux_set_pad(pin_ptr[i].pin, pin_ptr[i].pad_cfg); + if (pin_ptr[i].in_select) + mxc_iomux_set_input(pin_ptr[i].in_select, + pin_ptr[i].in_mode); + } + + /* TO3 doesn't need pad to drive CSI_DATA_EN[0] high */ + if (cpu_is_mx51_rev(CHIP_REV_3_0) > 0) + mxc_request_iomux(MX51_PIN_EIM_A26, IOMUX_CONFIG_ALT0); + + /* Camera low power */ + gpio_request(IOMUX_TO_GPIO(MX51_PIN_CSI1_D8), "csi1_d8"); + gpio_direction_output(IOMUX_TO_GPIO(MX51_PIN_CSI1_D8), 0); + gpio_set_value(IOMUX_TO_GPIO(MX51_PIN_CSI1_D8), 0); + gpio_request(IOMUX_TO_GPIO(MX51_PIN_EIM_EB2), "eim_eb2"); + gpio_direction_output(IOMUX_TO_GPIO(MX51_PIN_EIM_EB2), 0); /* TO1 */ + gpio_set_value(IOMUX_TO_GPIO(MX51_PIN_EIM_EB2), 0); /* TO1 */ + + /* Camera reset */ + gpio_request(IOMUX_TO_GPIO(MX51_PIN_CSI1_D9), "csi1_d9"); + gpio_direction_output(IOMUX_TO_GPIO(MX51_PIN_CSI1_D9), 0); + gpio_set_value(IOMUX_TO_GPIO(MX51_PIN_CSI1_D9), 1); + gpio_request(IOMUX_TO_GPIO(MX51_PIN_DI1_D1_CS), "di1_d1_cs"); + gpio_direction_output(IOMUX_TO_GPIO(MX51_PIN_DI1_D1_CS), 0); + gpio_request(IOMUX_TO_GPIO(MX51_PIN_GPIO1_0), "gpio1_0"); + gpio_direction_input(IOMUX_TO_GPIO(MX51_PIN_GPIO1_0)); /* SD1 CD */ + gpio_request(IOMUX_TO_GPIO(MX51_PIN_GPIO1_1), "gpio1_1"); + gpio_direction_input(IOMUX_TO_GPIO(MX51_PIN_GPIO1_1)); /* SD1 WP */ + + /* EIM_D16 */ + /* osc_en is shared by SPDIF */ + gpio_request(IOMUX_TO_GPIO(MX51_PIN_EIM_D16), "eim_d16"); + gpio_direction_output(IOMUX_TO_GPIO(MX51_PIN_EIM_D16), 0); + gpio_set_value(IOMUX_TO_GPIO(MX51_PIN_EIM_D16), 1); + + /* LCD related gpio */ + gpio_request(IOMUX_TO_GPIO(MX51_PIN_DI1_D1_CS), "di1_d1_cs"); + gpio_request(IOMUX_TO_GPIO(MX51_PIN_DISPB2_SER_DIO), "dispb2_ser_di0"); + gpio_direction_output(IOMUX_TO_GPIO(MX51_PIN_DI1_D1_CS), 0); + gpio_direction_output(IOMUX_TO_GPIO(MX51_PIN_DISPB2_SER_DIO), 0); + gpio_set_value(IOMUX_TO_GPIO(MX51_PIN_DISPB2_SER_DIO), 0); + + /* GPS related gpio */ + gpio_request(IOMUX_TO_GPIO(MX51_PIN_EIM_CS2), "eim_cs2"); + gpio_direction_output(IOMUX_TO_GPIO(MX51_PIN_EIM_CS2), 0); + gpio_set_value(IOMUX_TO_GPIO(MX51_PIN_EIM_CS2), 0); + gpio_request(IOMUX_TO_GPIO(MX51_PIN_EIM_CRE), "eim_cre"); + gpio_direction_output(IOMUX_TO_GPIO(MX51_PIN_EIM_CRE), 0); + gpio_set_value(IOMUX_TO_GPIO(MX51_PIN_EIM_CRE), 0); + gpio_set_value(IOMUX_TO_GPIO(MX51_PIN_EIM_CRE), 1); +} + diff --git a/arch/arm/mach-mx51/mx51_3stack_pmic_mc13892.c b/arch/arm/mach-mx51/mx51_3stack_pmic_mc13892.c new file mode 100644 index 000000000000..b84bb1ee05d4 --- /dev/null +++ b/arch/arm/mach-mx51/mx51_3stack_pmic_mc13892.c @@ -0,0 +1,352 @@ +/* + * mx51-3stack-pmic-mc13892.c -- i.MX51 3STACK Driver for Atlas MC13892 PMIC + */ + /* + * Copyright 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/init.h> +#include <linux/platform_device.h> +#include <linux/i2c.h> +#include <linux/err.h> +#include <linux/pmic_external.h> +#include <linux/regulator/machine.h> +#include <linux/mfd/mc13892/core.h> +#include "iomux.h" + +/* + * Convenience conversion. + * Here atm, maybe there is somewhere better for this. + */ +#define mV_to_uV(mV) (mV * 1000) +#define uV_to_mV(uV) (uV / 1000) +#define V_to_uV(V) (mV_to_uV(V * 1000)) +#define uV_to_V(uV) (uV_to_mV(uV) / 1000) + +#define STANDBYSECINV_LSH 11 +#define STANDBYSECINV_WID 1 + +/* Coin cell charger enable */ +#define CIONCHEN_LSH 23 +#define CIONCHEN_WID 1 +/* Coin cell charger voltage setting */ +#define VCOIN_LSH 20 +#define VCOIN_WID 3 + +/* Coin Charger voltage */ +#define VCOIN_2_5V 0x0 +#define VCOIN_2_7V 0x1 +#define VCOIN_2_8V 0x2 +#define VCOIN_2_9V 0x3 +#define VCOIN_3_0V 0x4 +#define VCOIN_3_1V 0x5 +#define VCOIN_3_2V 0x6 +#define VCOIN_3_3V 0x7 + +/* Keeps VSRTC and CLK32KMCU on for all states */ +#define DRM_LSH 4 +#define DRM_WID 1 + +/* CPU */ +static struct regulator_consumer_supply sw1_consumers[] = { + { + .supply = "cpu_vcc", + } +}; + +struct mc13892; + +static struct regulator_init_data sw1_init = { + .constraints = { + .name = "SW1", + .min_uV = mV_to_uV(600), + .max_uV = mV_to_uV(1375), + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE, + .valid_modes_mask = 0, + .always_on = 1, + .boot_on = 1, + .initial_state = PM_SUSPEND_MEM, + .state_mem = { + .uV = 850000, + .mode = REGULATOR_MODE_NORMAL, + .enabled = 1, + }, + }, + .num_consumer_supplies = ARRAY_SIZE(sw1_consumers), + .consumer_supplies = sw1_consumers, +}; + +static struct regulator_init_data sw2_init = { + .constraints = { + .name = "SW2", + .min_uV = mV_to_uV(900), + .max_uV = mV_to_uV(1850), + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE, + .always_on = 1, + .boot_on = 1, + .initial_state = PM_SUSPEND_MEM, + .state_mem = { + .uV = 950000, + .mode = REGULATOR_MODE_NORMAL, + .enabled = 1, + }, + } +}; + +static struct regulator_init_data sw3_init = { + .constraints = { + .name = "SW3", + .min_uV = mV_to_uV(1100), + .max_uV = mV_to_uV(1850), + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE, + .always_on = 1, + .boot_on = 1, + } +}; + +static struct regulator_init_data sw4_init = { + .constraints = { + .name = "SW4", + .min_uV = mV_to_uV(1100), + .max_uV = mV_to_uV(1850), + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE, + .always_on = 1, + .boot_on = 1, + } +}; + +static struct regulator_init_data viohi_init = { + .constraints = { + .name = "VIOHI", + .boot_on = 1, + } +}; + +static struct regulator_init_data vusb_init = { + .constraints = { + .name = "VUSB", + .boot_on = 1, + } +}; + +static struct regulator_init_data swbst_init = { + .constraints = { + .name = "SWBST", + } +}; + +static struct regulator_init_data vdig_init = { + .constraints = { + .name = "VDIG", + .min_uV = mV_to_uV(1050), + .max_uV = mV_to_uV(1800), + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE, + .boot_on = 1, + } +}; + +static struct regulator_init_data vpll_init = { + .constraints = { + .name = "VPLL", + .min_uV = mV_to_uV(1050), + .max_uV = mV_to_uV(1800), + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE, + .boot_on = 1, + } +}; + +static struct regulator_init_data vusb2_init = { + .constraints = { + .name = "VUSB2", + .min_uV = mV_to_uV(2400), + .max_uV = mV_to_uV(2775), + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE, + .boot_on = 1, + } +}; + +static struct regulator_init_data vvideo_init = { + .constraints = { + .name = "VVIDEO", + .min_uV = mV_to_uV(2500), + .max_uV = mV_to_uV(2775), + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE, + } +}; + +static struct regulator_init_data vaudio_init = { + .constraints = { + .name = "VAUDIO", + .min_uV = mV_to_uV(2300), + .max_uV = mV_to_uV(3000), + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE, + } +}; + +static struct regulator_init_data vsd_init = { + .constraints = { + .name = "VSD", + .min_uV = mV_to_uV(1800), + .max_uV = mV_to_uV(3150), + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE, + } +}; + +static struct regulator_init_data vcam_init = { + .constraints = { + .name = "VCAM", + .min_uV = mV_to_uV(2500), + .max_uV = mV_to_uV(3000), + .valid_ops_mask = + REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_MODE, + .valid_modes_mask = REGULATOR_MODE_FAST | REGULATOR_MODE_NORMAL, + } +}; + +static struct regulator_init_data vgen1_init = { + .constraints = { + .name = "VGEN1", + .min_uV = mV_to_uV(1200), + .max_uV = mV_to_uV(3150), + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE, + } +}; + +static struct regulator_init_data vgen2_init = { + .constraints = { + .name = "VGEN2", + .min_uV = mV_to_uV(1200), + .max_uV = mV_to_uV(3150), + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE, + .boot_on = 1, + } +}; + +static struct regulator_init_data vgen3_init = { + .constraints = { + .name = "VGEN3", + .min_uV = mV_to_uV(1800), + .max_uV = mV_to_uV(2900), + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE, + } +}; + +static struct regulator_init_data gpo1_init = { + .constraints = { + .name = "GPO1", + } +}; + +static struct regulator_init_data gpo2_init = { + .constraints = { + .name = "GPO2", + } +}; + +static struct regulator_init_data gpo3_init = { + .constraints = { + .name = "GPO3", + } +}; + +static struct regulator_init_data gpo4_init = { + .constraints = { + .name = "GPO4", + } +}; + +/*! + * the event handler for power on event + */ +static void power_on_evt_handler(void) +{ + pr_info("pwr on event1 is received \n"); +} + +static int mc13892_regulator_init(struct mc13892 *mc13892) +{ + unsigned int value; + pmic_event_callback_t power_key_event; + int register_mask; + + printk("Initializing regulators for 3-stack.\n"); + if (mxc_cpu_is_rev(CHIP_REV_2_0) < 0) + sw2_init.constraints.state_mem.uV = 1100000; + else if (mxc_cpu_is_rev(CHIP_REV_2_0) == 1) { + sw2_init.constraints.state_mem.uV = 1250000; + sw1_init.constraints.state_mem.uV = 1000000; + } + + /* subscribe PWRON1 event to enable ON_OFF key */ + power_key_event.param = NULL; + power_key_event.func = (void *)power_on_evt_handler; + pmic_event_subscribe(EVENT_PWRONI, power_key_event); + + /* Bit 4 DRM: keep VSRTC and CLK32KMCU on for all states */ +#if defined(CONFIG_RTC_DRV_MXC_V2) || defined(CONFIG_RTC_DRV_MXC_V2_MODULE) + value = BITFVAL(DRM, 1); + register_mask = BITFMASK(DRM); + pmic_write_reg(REG_POWER_CTL0, value, register_mask); +#endif + /* Set the STANDBYSECINV bit, so that STANDBY pin is + * interpreted as active low. + */ + value = BITFVAL(STANDBYSECINV, 1); + register_mask = BITFMASK(STANDBYSECINV); + pmic_write_reg(REG_POWER_CTL2, value, register_mask); + + /* Enable coin cell charger */ + value = BITFVAL(CIONCHEN, 1) | BITFVAL(VCOIN, VCOIN_3_0V); + register_mask = BITFMASK(CIONCHEN) | BITFMASK(VCOIN); + pmic_write_reg(REG_POWER_CTL0, value, register_mask); + + mc13892_register_regulator(mc13892, MC13892_SW1, &sw1_init); + mc13892_register_regulator(mc13892, MC13892_SW2, &sw2_init); + mc13892_register_regulator(mc13892, MC13892_SW3, &sw3_init); + mc13892_register_regulator(mc13892, MC13892_SW4, &sw4_init); + mc13892_register_regulator(mc13892, MC13892_SWBST, &swbst_init); + mc13892_register_regulator(mc13892, MC13892_VIOHI, &viohi_init); + mc13892_register_regulator(mc13892, MC13892_VPLL, &vpll_init); + mc13892_register_regulator(mc13892, MC13892_VDIG, &vdig_init); + mc13892_register_regulator(mc13892, MC13892_VSD, &vsd_init); + mc13892_register_regulator(mc13892, MC13892_VUSB2, &vusb2_init); + mc13892_register_regulator(mc13892, MC13892_VVIDEO, &vvideo_init); + mc13892_register_regulator(mc13892, MC13892_VAUDIO, &vaudio_init); + mc13892_register_regulator(mc13892, MC13892_VCAM, &vcam_init); + mc13892_register_regulator(mc13892, MC13892_VGEN1, &vgen1_init); + mc13892_register_regulator(mc13892, MC13892_VGEN2, &vgen2_init); + mc13892_register_regulator(mc13892, MC13892_VGEN3, &vgen3_init); + mc13892_register_regulator(mc13892, MC13892_VUSB, &vusb_init); + mc13892_register_regulator(mc13892, MC13892_GPO1, &gpo1_init); + mc13892_register_regulator(mc13892, MC13892_GPO2, &gpo2_init); + mc13892_register_regulator(mc13892, MC13892_GPO3, &gpo3_init); + mc13892_register_regulator(mc13892, MC13892_GPO4, &gpo4_init); + + return 0; +} + +static struct mc13892_platform_data mc13892_plat = { + .init = mc13892_regulator_init, +}; + +static struct i2c_board_info __initdata mc13892_i2c_device = { + I2C_BOARD_INFO("mc13892", 0x08), + .irq = MX51_PIN_GPIO1_5, + .platform_data = &mc13892_plat, +}; + +int __init mx51_3stack_init_mc13892(void) +{ + return i2c_register_board_info(1, &mc13892_i2c_device, 1); +} + diff --git a/arch/arm/mach-mx51/mx51_babbage.c b/arch/arm/mach-mx51/mx51_babbage.c new file mode 100644 index 000000000000..9b28b90ce3ed --- /dev/null +++ b/arch/arm/mach-mx51/mx51_babbage.c @@ -0,0 +1,1069 @@ +/* + * Copyright 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/types.h> +#include <linux/sched.h> +#include <linux/delay.h> +#include <linux/pm.h> +#include <linux/interrupt.h> +#include <linux/irq.h> +#include <linux/init.h> +#include <linux/input.h> +#include <linux/nodemask.h> +#include <linux/clk.h> +#include <linux/platform_device.h> +#include <linux/fsl_devices.h> +#include <linux/spi/spi.h> +#include <linux/i2c.h> +#include <linux/ata.h> +#include <linux/mtd/mtd.h> +#include <linux/mtd/map.h> +#include <linux/mtd/partitions.h> +#include <linux/spi/flash.h> +#include <linux/regulator/consumer.h> +#include <linux/pmic_external.h> +#include <linux/pmic_status.h> +#include <linux/ipu.h> +#include <linux/mxcfb.h> +#include <mach/common.h> +#include <mach/hardware.h> +#include <mach/spba.h> +#include <asm/irq.h> +#include <asm/setup.h> +#include <asm/mach-types.h> +#include <asm/mach/arch.h> +#include <asm/mach/time.h> +#include <asm/mach/keypad.h> +#include <mach/memory.h> +#include <mach/gpio.h> +#include <mach/mmc.h> +#include "board-mx51_babbage.h" +#include "iomux.h" +#include "crm_regs.h" +#include <mach/mxc_edid.h> + +/*! + * @file mach-mx51/mx51_babbage.c + * + * @brief This file contains the board specific initialization routines. + * + * @ingroup MSL_MX51 + */ +extern void __init mx51_babbage_io_init(void); +extern struct cpu_wp *(*get_cpu_wp)(int *wp); +extern void (*set_num_cpu_wp)(int num); +static int num_cpu_wp = 3; + +/* working point(wp): 0 - 800MHz; 1 - 166.25MHz; */ +static struct cpu_wp cpu_wp_auto[] = { + { + .pll_rate = 1000000000, + .cpu_rate = 1000000000, + .pdf = 0, + .mfi = 10, + .mfd = 11, + .mfn = 5, + .cpu_podf = 0, + .cpu_voltage = 1175000,}, + { + .pll_rate = 800000000, + .cpu_rate = 800000000, + .pdf = 0, + .mfi = 8, + .mfd = 2, + .mfn = 1, + .cpu_podf = 0, + .cpu_voltage = 1100000,}, + { + .pll_rate = 800000000, + .cpu_rate = 166250000, + .pdf = 4, + .mfi = 8, + .mfd = 2, + .mfn = 1, + .cpu_podf = 4, + .cpu_voltage = 850000,}, +}; + +static struct fb_videomode video_modes[] = { + { + /* 720p60 TV output */ + "720P60", 60, 1280, 720, 7418, + 220, 110, + 20, 5, + 40, 5, + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT | FB_SYNC_EXT, + FB_VMODE_NONINTERLACED, + 0,}, + { + /* MITSUBISHI LVDS panel */ + "XGA", 60, 1024, 768, 15385, + 220, 40, + 21, 7, + 60, 10, + 0, + FB_VMODE_NONINTERLACED, + 0,}, +}; + +struct cpu_wp *mx51_babbage_get_cpu_wp(int *wp) +{ + *wp = num_cpu_wp; + return cpu_wp_auto; +} + +void mx51_babbage_set_num_cpu_wp(int num) +{ + num_cpu_wp = num; + return; +} +static void mxc_nop_release(struct device *dev) +{ + /* Nothing */ +} + +#if defined(CONFIG_KEYBOARD_MXC) || defined(CONFIG_KEYBOARD_MXC_MODULE) +static u16 keymapping[24] = { + KEY_1, KEY_2, KEY_3, KEY_F1, KEY_UP, KEY_F2, + KEY_4, KEY_5, KEY_6, KEY_LEFT, KEY_SELECT, KEY_RIGHT, + KEY_7, KEY_8, KEY_9, KEY_F3, KEY_DOWN, KEY_F4, + KEY_0, KEY_OK, KEY_ESC, KEY_ENTER, KEY_MENU, KEY_BACK, +}; + +static struct resource mxc_kpp_resources[] = { + [0] = { + .start = MXC_INT_KPP, + .end = MXC_INT_KPP, + .flags = IORESOURCE_IRQ, + } +}; + +static struct keypad_data keypad_plat_data = { + .rowmax = 4, + .colmax = 6, + .irq = MXC_INT_KPP, + .learning = 0, + .delay = 2, + .matrix = keymapping, +}; + +/* 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 = &keypad_plat_data, + }, +}; + +static void mxc_init_keypad(void) +{ + (void)platform_device_register(&mxc_keypad_device); +} +#else +static inline void mxc_init_keypad(void) +{ +} +#endif + +#if defined(CONFIG_FB_MXC_SYNC_PANEL) || \ + defined(CONFIG_FB_MXC_SYNC_PANEL_MODULE) +static struct resource mxcfb_resources[] = { + [0] = { + .flags = IORESOURCE_MEM, + }, +}; + +static struct mxc_fb_platform_data fb_data[] = { + { + .interface_pix_fmt = IPU_PIX_FMT_RGB24, + .mode_str = "1024x768M-16@60", + }, + { + .interface_pix_fmt = IPU_PIX_FMT_RGB565, + .mode_str = "1024x768M-16@60", + }, +}; + +static struct platform_device mxc_fb_device[] = { + { + .name = "mxc_sdc_fb", + .id = 0, + .dev = { + .release = mxc_nop_release, + .coherent_dma_mask = 0xFFFFFFFF, + .platform_data = &fb_data[0], + }, + .num_resources = ARRAY_SIZE(mxcfb_resources), + .resource = mxcfb_resources, + }, + { + .name = "mxc_sdc_fb", + .id = 1, + .dev = { + .release = mxc_nop_release, + .coherent_dma_mask = 0xFFFFFFFF, + .platform_data = &fb_data[1], + }, + }, + { + .name = "mxc_sdc_fb", + .id = 2, + .dev = { + .release = mxc_nop_release, + .coherent_dma_mask = 0xFFFFFFFF, + }, + }, +}; + +static int __initdata enable_vga = { 0 }; +static int __initdata enable_wvga = { 0 }; +static int __initdata enable_tv = { 0 }; +static int __initdata enable_mitsubishi_xga = { 0 }; + +static void wvga_reset(void) +{ + gpio_set_value(IOMUX_TO_GPIO(MX51_PIN_DI1_D1_CS), 1); +} + +static struct mxc_lcd_platform_data lcd_wvga_data = { + .reset = wvga_reset, +}; + +static struct platform_device lcd_wvga_device = { + .name = "lcd_claa", + .dev = { + .release = mxc_nop_release, + .platform_data = &lcd_wvga_data, + }, +}; + +static int handle_edid(int *pixclk) +{ + int err = 0; + int dvi = 0; + int fb0 = 0; + int fb1 = 1; + struct fb_var_screeninfo screeninfo; + struct i2c_adapter *adp; + + memset(&screeninfo, 0, sizeof(screeninfo)); + + adp = i2c_get_adapter(1); + + if (cpu_is_mx51_rev(CHIP_REV_3_0) > 0) { + gpio_set_value(IOMUX_TO_GPIO(MX51_PIN_CSI2_HSYNC), 1); + msleep(1); + } + err = read_edid(adp, &screeninfo, &dvi); + if (cpu_is_mx51_rev(CHIP_REV_3_0) > 0) + gpio_set_value(IOMUX_TO_GPIO(MX51_PIN_CSI2_HSYNC), 0); + + if (!err) { + printk(KERN_INFO " EDID read\n"); + if (!dvi) { + enable_vga = 1; + fb0 = 1; /* fb0 will be VGA */ + fb1 = 0; /* fb1 will be DVI or TV */ + } + + /* Handle TV modes */ + /* This logic is fairly complex yet still doesn't handle all + possibilities. Once a customer knows the platform + configuration, this should be simplified to what is desired. + */ + if (screeninfo.xres == 1920 && screeninfo.yres != 1200) { + /* MX51 can't handle clock speeds for anything larger.*/ + if (!enable_tv) + enable_tv = 1; + if (enable_vga || enable_wvga || enable_tv == 2) + enable_tv = 2; + fb_data[0].mode = &(video_modes[0]); + if (!enable_wvga) + fb_data[1].mode_str = "800x600M-16@60"; + } else if (screeninfo.xres > 1280 && screeninfo.yres > 1024) { + if (!enable_wvga) { + fb_data[fb0].mode_str = "1280x1024M-16@60"; + fb_data[fb1].mode_str = NULL; + } else { + /* WVGA is preset so the DVI can't be > this. */ + fb_data[0].mode_str = "1024x768M-16@60"; + } + } else if (screeninfo.xres > 0 && screeninfo.yres > 0) { + if (!enable_wvga) { + fb_data[fb0].mode = + kzalloc(sizeof(struct fb_videomode), + GFP_KERNEL); + fb_var_to_videomode(fb_data[fb0].mode, + &screeninfo); + fb_data[fb0].mode_str = NULL; + if (screeninfo.xres >= 1280 && + screeninfo.yres > 720) + fb_data[fb1].mode_str = NULL; + else if (screeninfo.xres > 1024 && + screeninfo.yres > 768) + fb_data[fb1].mode_str = + "800x600M-16@60"; + else if (screeninfo.xres > 800 && + screeninfo.yres > 600) + fb_data[fb1].mode_str = + "1024x768M-16@60"; + } else { + /* A WVGA panel was specified and an EDID was + read thus there is a DVI monitor attached. */ + if (screeninfo.xres >= 1024) + fb_data[0].mode_str = "1024x768M-16@60"; + else if (screeninfo.xres >= 800) + fb_data[0].mode_str = "800x600M-16@60"; + else + fb_data[0].mode_str = "640x480M-16@60"; + } + } + } + + return 0; +} + +static int __init mxc_init_fb(void) +{ + int pixclk = 0; + + if (!machine_is_mx51_babbage()) + return 0; + + if (cpu_is_mx51_rev(CHIP_REV_1_1) == 1) { + enable_vga = 1; + fb_data[0].mode_str = NULL; + fb_data[1].mode_str = NULL; + } + + if (enable_wvga) { + fb_data[1].interface_pix_fmt = IPU_PIX_FMT_RGB565; + fb_data[1].mode_str = "800x480M-16@55"; + } + + if (enable_mitsubishi_xga) { + fb_data[0].interface_pix_fmt = IPU_PIX_FMT_LVDS666; + fb_data[0].mode = &(video_modes[1]); + + gpio_set_value(IOMUX_TO_GPIO(MX51_PIN_DI1_D0_CS), 0); + msleep(1); + gpio_set_value(IOMUX_TO_GPIO(MX51_PIN_DI1_D0_CS), 1); + + gpio_set_value(IOMUX_TO_GPIO(MX51_PIN_CSI2_D12), 1); + gpio_set_value(IOMUX_TO_GPIO(MX51_PIN_CSI2_D13), 1); + } + + /* DVI Detect */ + gpio_request(IOMUX_TO_GPIO(MX51_PIN_NANDF_D12), "nandf_d12"); + gpio_direction_input(IOMUX_TO_GPIO(MX51_PIN_NANDF_D12)); + /* DVI Reset - Assert for i2c disabled mode */ + gpio_request(IOMUX_TO_GPIO(MX51_PIN_DISPB2_SER_DIN), "dispb2_ser_din"); + gpio_set_value(IOMUX_TO_GPIO(MX51_PIN_DISPB2_SER_DIN), 0); + gpio_direction_output(IOMUX_TO_GPIO(MX51_PIN_DISPB2_SER_DIN), 0); + /* DVI Power-down */ + gpio_request(IOMUX_TO_GPIO(MX51_PIN_DISPB2_SER_DIO), "dispb2_ser_di0"); + gpio_set_value(IOMUX_TO_GPIO(MX51_PIN_DISPB2_SER_DIO), 1); + gpio_direction_output(IOMUX_TO_GPIO(MX51_PIN_DISPB2_SER_DIO), 0); + + (void)platform_device_register(&lcd_wvga_device); + +#if 0 + if (cpu_is_mx51_rev(CHIP_REV_1_1) == 2) + handle_edid(&pixclk); +#endif + + if (enable_vga) + printk(KERN_INFO "VGA monitor is primary\n"); + else if (enable_wvga) + printk(KERN_INFO "WVGA LCD panel is primary\n"); + else if (!enable_tv) + printk(KERN_INFO "DVI monitor is primary\n"); + + if (enable_tv) { + printk(KERN_INFO "TV is specified as %d\n", enable_tv); + if (!fb_data[0].mode) { + fb_data[0].mode = &(video_modes[0]); + if (!enable_wvga) + fb_data[1].mode_str = "800x600M-16@60"; + } + } + + if (enable_tv) { + struct clk *clk, *di_clk; + clk = clk_get(NULL, "pll3"); + di_clk = clk_get(NULL, "ipu_di0_clk"); + clk_disable(clk); + clk_disable(di_clk); + clk_set_rate(clk, 297000000); + clk_set_rate(di_clk, 297000000 / 4); + clk_enable(clk); + clk_enable(di_clk); + clk_put(di_clk); + clk_put(clk); + } + + /* Once a customer knows the platform configuration, + this should be simplified to what is desired. + */ + if (enable_vga || enable_wvga || enable_tv == 2) { + (void)platform_device_register(&mxc_fb_device[1]); /* VGA */ + if (fb_data[0].mode_str || fb_data[0].mode) + (void)platform_device_register(&mxc_fb_device[0]); + } else { + (void)platform_device_register(&mxc_fb_device[0]); /* DVI */ + if (fb_data[1].mode_str || fb_data[1].mode) + (void)platform_device_register(&mxc_fb_device[1]); + } + + (void)platform_device_register(&mxc_fb_device[2]); + + return 0; +} +device_initcall(mxc_init_fb); + +static int __init vga_setup(char *__unused) +{ + enable_vga = 1; + return 1; +} + +__setup("vga", vga_setup); + +static int __init wvga_setup(char *__unused) +{ + enable_wvga = 1; + return 1; +} + +__setup("wvga", wvga_setup); + +static int __init mitsubishi_xga_setup(char *__unused) +{ + enable_mitsubishi_xga = 1; + return 1; +} + +__setup("mitsubishi_xga", mitsubishi_xga_setup); + +static int __init tv_setup(char *s) +{ + enable_tv = 1; + if (strcmp(s, "2") == 0 || strcmp(s, "=2") == 0) + enable_tv = 2; + return 1; +} + +__setup("tv", tv_setup); +#else +static inline void mxc_init_fb(void) +{ +} +#endif + +static void dvi_reset(void) +{ + gpio_direction_output(IOMUX_TO_GPIO(MX51_PIN_DISPB2_SER_DIN), 0); + gpio_set_value(IOMUX_TO_GPIO(MX51_PIN_DISPB2_SER_DIN), 0); + msleep(50); + + /* do reset */ + gpio_set_value(IOMUX_TO_GPIO(MX51_PIN_DISPB2_SER_DIN), 1); + msleep(20); /* tRES >= 50us */ + + gpio_set_value(IOMUX_TO_GPIO(MX51_PIN_DISPB2_SER_DIN), 0); +} + +static struct mxc_lcd_platform_data dvi_data = { + .core_reg = "VGEN1", + .io_reg = "VGEN3", + .reset = dvi_reset, +}; + +static void vga_reset(void) +{ + gpio_request(IOMUX_TO_GPIO(MX51_PIN_EIM_A19), "eim_a19"); + gpio_direction_output(IOMUX_TO_GPIO(MX51_PIN_EIM_A19), 0); + gpio_set_value(IOMUX_TO_GPIO(MX51_PIN_EIM_A19), 0); + msleep(50); + /* do reset */ + gpio_set_value(IOMUX_TO_GPIO(MX51_PIN_EIM_A19), 1); + msleep(10); /* tRES >= 50us */ + gpio_set_value(IOMUX_TO_GPIO(MX51_PIN_EIM_A19), 0); +} + +static struct mxc_lcd_platform_data vga_data = { + .core_reg = "VCAM", + .io_reg = "VGEN3", + .analog_reg = "VAUDIO", + .reset = vga_reset, +}; + +static void si4702_reset(void) +{ + return; + gpio_set_value(IOMUX_TO_GPIO(MX51_PIN_EIM_A21), 0); + msleep(100); + gpio_set_value(IOMUX_TO_GPIO(MX51_PIN_EIM_A21), 1); + msleep(100); +} + +static void si4702_clock_ctl(int flag) +{ + gpio_set_value(IOMUX_TO_GPIO(MX51_PIN_EIM_A18), flag); + msleep(100); +} + +static void si4702_gpio_get(void) +{ + gpio_request(IOMUX_TO_GPIO(MX51_PIN_EIM_A18), "eim_a18"); + gpio_direction_output(IOMUX_TO_GPIO(MX51_PIN_EIM_A18), 0); +} + +static void si4702_gpio_put(void) +{ +} + +static struct mxc_fm_platform_data si4702_data = { + .reg_vio = "SW4", + .reg_vdd = "VIOHI", + .gpio_get = si4702_gpio_get, + .gpio_put = si4702_gpio_put, + .reset = si4702_reset, + .clock_ctl = si4702_clock_ctl, +}; + +#if defined(CONFIG_I2C_MXC) || defined(CONFIG_I2C_MXC_MODULE) + +#ifdef CONFIG_I2C_MXC_SELECT1 +static struct mxc_camera_platform_data camera_data = { + .io_regulator = "SW4", + .analog_regulator = "VIOHI", + .mclk = 24000000, + .csi = 0, +}; + +static struct i2c_board_info mxc_i2c0_board_info[] __initdata = { + { + .type = "ov3640", + .addr = 0x3C, + .platform_data = (void *)&camera_data, + }, +}; +#endif +#ifdef CONFIG_I2C_MXC_SELECT2 +static struct i2c_board_info mxc_i2c1_board_info[] __initdata = { + { + .type = "sgtl5000-i2c", + .addr = 0x0a, + }, +}; +#endif + +#if defined(CONFIG_I2C_MXC_HS) || defined(CONFIG_I2C_MXC_HS_MODULE) +static struct i2c_board_info mxc_i2c_hs_board_info[] __initdata = { + { + .type = "sii9022", + .addr = 0x39, + .platform_data = &dvi_data, + }, + { + .type = "ch7026", + .addr = 0x75, + .platform_data = &vga_data, + }, + { + .type = "si4702", + .addr = 0x10, + .platform_data = (void *)&si4702_data, + }, +}; +#endif + +#endif + +#if defined(CONFIG_MTD) || defined(CONFIG_MTD_MODULE) +static struct mtd_partition mxc_spi_nor_partitions[] = { + { + .name = "bootloader", + .offset = 0, + .size = 0x00040000,}, + { + .name = "kernel", + .offset = MTDPART_OFS_APPEND, + .size = MTDPART_SIZ_FULL,}, + +}; + +static struct mtd_partition mxc_dataflash_partitions[] = { + { + .name = "bootloader", + .offset = 0, + .size = 0x000100000,}, + { + .name = "kernel", + .offset = MTDPART_OFS_APPEND, + .size = MTDPART_SIZ_FULL,}, +}; + +static struct flash_platform_data mxc_spi_flash_data[] = { + { + .name = "mxc_spi_nor", + .parts = mxc_spi_nor_partitions, + .nr_parts = ARRAY_SIZE(mxc_spi_nor_partitions), + .type = "sst25vf016b",}, + { + .name = "mxc_dataflash", + .parts = mxc_dataflash_partitions, + .nr_parts = ARRAY_SIZE(mxc_dataflash_partitions), + .type = "at45db321d",} +}; +#endif + +static struct spi_board_info mxc_spi_nor_device[] __initdata = { +#if defined(CONFIG_MTD) || defined(CONFIG_MTD_MODULE) + { + .modalias = "mxc_spi_nor", + .max_speed_hz = 25000000, /* max spi clock (SCK) speed in HZ */ + .bus_num = 1, + .chip_select = 1, + .platform_data = &mxc_spi_flash_data[0],}, +#endif +}; + +static struct spi_board_info mxc_dataflash_device[] __initdata = { +#if defined(CONFIG_MTD) || defined(CONFIG_MTD_MODULE) + { + .modalias = "mxc_dataflash", + .max_speed_hz = 25000000, /* max spi clock (SCK) speed in HZ */ + .bus_num = 1, + .chip_select = 1, + .platform_data = &mxc_spi_flash_data[1],}, +#endif +}; + +#if defined(CONFIG_FEC) || defined(CONFIG_FEC_MODULE) +unsigned int expio_intr_fec; + +EXPORT_SYMBOL(expio_intr_fec); +#endif + +#if defined(CONFIG_MMC_IMX_ESDHCI) || defined(CONFIG_MMC_IMX_ESDHCI_MODULE) +static int sdhc_write_protect(struct device *dev) +{ + unsigned short rc = 0; + + if (to_platform_device(dev)->id == 0) + rc = gpio_get_value(IOMUX_TO_GPIO(MX51_PIN_GPIO1_1)); + else + rc = gpio_get_value(IOMUX_TO_GPIO(MX51_PIN_GPIO1_5)); + + return rc; +} + +static unsigned int sdhc_get_card_det_status(struct device *dev) +{ + int ret; + + if (to_platform_device(dev)->id == 0) { + ret = gpio_get_value(IOMUX_TO_GPIO(MX51_PIN_GPIO1_0)); + return ret; + } else { /* config the det pin for SDHC2 */ + if (board_is_babbage_2_5() == 1) + /* BB2.5 */ + ret = gpio_get_value(IOMUX_TO_GPIO(MX51_PIN_GPIO1_6)); + else + /* BB2.0 */ + ret = gpio_get_value(IOMUX_TO_GPIO(MX51_PIN_GPIO1_4)); + return ret; + } +} + +static struct mxc_mmc_platform_data mmc1_data = { + .ocr_mask = MMC_VDD_31_32, + .caps = MMC_CAP_4_BIT_DATA, + .min_clk = 400000, + .max_clk = 52000000, + .card_inserted_state = 1, + .status = sdhc_get_card_det_status, + .wp_status = sdhc_write_protect, + .clock_mmc = "esdhc_clk", + .power_mmc = NULL, +}; + +static struct mxc_mmc_platform_data mmc2_data = { + .ocr_mask = MMC_VDD_27_28 | MMC_VDD_28_29 | MMC_VDD_29_30 | + MMC_VDD_31_32, + .caps = MMC_CAP_4_BIT_DATA, + .min_clk = 150000, + .max_clk = 50000000, + .card_inserted_state = 0, + .status = sdhc_get_card_det_status, + .wp_status = sdhc_write_protect, + .clock_mmc = "esdhc_clk", +}; + +/*! + * Resource definition for the SDHC1 + */ +static struct resource mxcsdhc1_resources[] = { + [0] = { + .start = MMC_SDHC1_BASE_ADDR, + .end = MMC_SDHC1_BASE_ADDR + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = MXC_INT_MMC_SDHC1, + .end = MXC_INT_MMC_SDHC1, + .flags = IORESOURCE_IRQ, + }, + [2] = { + .start = IOMUX_TO_IRQ(MX51_PIN_GPIO1_0), + .end = IOMUX_TO_IRQ(MX51_PIN_GPIO1_0), + .flags = IORESOURCE_IRQ, + }, +}; + +/*! + * Resource definition for the SDHC2 + */ +static struct resource mxcsdhc2_resources[] = { + [0] = { + .start = MMC_SDHC2_BASE_ADDR, + .end = MMC_SDHC2_BASE_ADDR + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = MXC_INT_MMC_SDHC2, + .end = MXC_INT_MMC_SDHC2, + .flags = IORESOURCE_IRQ, + }, + [2] = { + .start = IOMUX_TO_IRQ(MX51_PIN_GPIO1_6), + .end = IOMUX_TO_IRQ(MX51_PIN_GPIO1_6), + .flags = IORESOURCE_IRQ, + }, +}; + +/*! Device Definition for MXC SDHC1 */ +static struct platform_device mxcsdhc1_device = { + .name = "mxsdhci", + .id = 0, + .dev = { + .release = mxc_nop_release, + .platform_data = &mmc1_data, + }, + .num_resources = ARRAY_SIZE(mxcsdhc1_resources), + .resource = mxcsdhc1_resources, +}; + +/*! Device Definition for MXC SDHC2 */ +static struct platform_device mxcsdhc2_device = { + .name = "mxsdhci", + .id = 1, + .dev = { + .release = mxc_nop_release, + .platform_data = &mmc2_data, + }, + .num_resources = ARRAY_SIZE(mxcsdhc2_resources), + .resource = mxcsdhc2_resources, +}; + +static inline void mxc_init_mmc(void) +{ + if (board_is_babbage_2_5() == 1) { + /* BB2.5 */ + mxcsdhc2_resources[2].start = + IOMUX_TO_IRQ(MX51_PIN_GPIO1_6); /* SD2 CD */ + mxcsdhc2_resources[2].end = + IOMUX_TO_IRQ(MX51_PIN_GPIO1_6); /* SD2 CD */ + } + + (void)platform_device_register(&mxcsdhc1_device); + (void)platform_device_register(&mxcsdhc2_device); +} +#else +static inline void mxc_init_mmc(void) +{ +} +#endif + +#if defined(CONFIG_SND_SOC_IMX_3STACK_SGTL5000) \ + || defined(CONFIG_SND_SOC_IMX_3STACK_SGTL5000_MODULE) +static int mxc_sgtl5000_amp_enable(int enable); + +static int headphone_det_status(void) +{ + if (cpu_is_mx51_rev(CHIP_REV_1_1) == 2) + return (gpio_get_value(IOMUX_TO_GPIO(MX51_PIN_NANDF_D14)) == 0); + + return gpio_get_value(IOMUX_TO_GPIO(MX51_PIN_NANDF_CS0)); +} + +static struct mxc_audio_platform_data sgtl5000_data = { + .ssi_num = 1, + .src_port = 2, + .ext_port = 3, + .hp_irq = IOMUX_TO_IRQ(MX51_PIN_NANDF_CS0), + .hp_status = headphone_det_status, + .vddio_reg = "VVIDEO", + .vdda_reg = "VDIG", + .vddd_reg = "VGEN1", + .amp_enable = mxc_sgtl5000_amp_enable, + .vddio = 2775000, + .vdda = 1650000, + .vddd = 1200000, + .sysclk = 12288000, +}; + +static struct platform_device mxc_sgtl5000_device = { + .name = "imx-3stack-sgtl5000", + .dev = { + .release = mxc_nop_release, + .platform_data = &sgtl5000_data, + }, +}; + +static int mxc_sgtl5000_amp_enable(int enable) +{ + gpio_set_value(IOMUX_TO_GPIO(MX51_PIN_EIM_A23), enable ? 1 : 0); + return 0; +} + +static void mxc_init_sgtl5000(void) +{ + if (cpu_is_mx51_rev(CHIP_REV_1_1) == 2) { + sgtl5000_data.sysclk = 26000000; + sgtl5000_data.vddd_reg = NULL; + sgtl5000_data.vddd = 0; + } + + gpio_request(IOMUX_TO_GPIO(MX51_PIN_EIM_A23), "eim_a23"); + gpio_direction_output(IOMUX_TO_GPIO(MX51_PIN_EIM_A23), 0); + + platform_device_register(&mxc_sgtl5000_device); +} +#else +static inline void mxc_init_sgtl5000(void) +{ +} +#endif + +#if defined(CONFIG_GPIO_BUTTON_MXC) || \ + defined(CONFIG_GPIO_BUTTON_MXC_MODULE) + +#define MXC_BUTTON_GPIO_PIN MX51_PIN_EIM_DTACK + +static struct mxc_gpio_button_data gpio_button_data = { + .name = "Power Button (CM)", + .gpio = MXC_BUTTON_GPIO_PIN, + .irq = IOMUX_TO_IRQ(MXC_BUTTON_GPIO_PIN), + .key = KEY_POWER, +}; + +static struct platform_device gpio_button_device = { + .name = "gpio_button", + .dev = { + .release = mxc_nop_release, + .platform_data = &gpio_button_data, + }, +}; + +static inline void mxc_init_gpio_button(void) +{ + gpio_request(IOMUX_TO_GPIO(MXC_BUTTON_GPIO_PIN), "button"); + gpio_direction_input(IOMUX_TO_GPIO(MXC_BUTTON_GPIO_PIN)); + platform_device_register(&gpio_button_device); +} +#else +static inline void mxc_init_gpio_button(void) +{ +} +#endif + +/*! + * Board specific fixup function. It is called by \b setup_arch() in + * setup.c file very early on during kernel starts. It allows the user to + * statically fill in the proper values for the passed-in parameters. None of + * the parameters is used currently. + * + * @param desc pointer to \b struct \b machine_desc + * @param tags pointer to \b struct \b tag + * @param cmdline pointer to the command line + * @param mi pointer to \b struct \b meminfo + */ +static void __init fixup_mxc_board(struct machine_desc *desc, struct tag *tags, + char **cmdline, struct meminfo *mi) +{ + char *str; + int size = SZ_512M - SZ_32M; + struct tag *t; + + mxc_cpu_init(); + + get_cpu_wp = mx51_babbage_get_cpu_wp; + set_num_cpu_wp = mx51_babbage_set_num_cpu_wp; + + for_each_tag(t, tags) { + if (t->hdr.tag != ATAG_CMDLINE) + continue; + str = t->u.cmdline.cmdline; + str = strstr(str, "mem="); + if (str != NULL) { + str += 4; + size = memparse(str, &str); + if (size == 0 || size == SZ_512M) + return; + } + } + + for_each_tag(t, tags) { + if (t->hdr.tag != ATAG_MEM) + continue; + + t->u.mem.size = size; + mxcfb_resources[0].start = t->u.mem.start + size; + mxcfb_resources[0].end = t->u.mem.start + SZ_512M - 1; + } +} + +#define PWGT1SPIEN (1<<15) +#define PWGT2SPIEN (1<<16) +#define USEROFFSPI (1<<3) + +static void mxc_power_off(void) +{ + /* We can do power down one of two ways: + Set the power gating + Set USEROFFSPI */ + + /* Set the power gate bits to power down */ + pmic_write_reg(REG_POWER_MISC, (PWGT1SPIEN|PWGT2SPIEN), + (PWGT1SPIEN|PWGT2SPIEN)); +} + +/*! + * Power Key interrupt handler. + */ +static irqreturn_t power_key_int(int irq, void *dev_id) +{ + pr_info(KERN_INFO "PWR key pressed\n"); + return 0; +} + +/*! + * Power Key initialization. + */ +static int __init mxc_init_power_key(void) +{ + /* Set power key as wakeup resource */ + int irq, ret; + irq = IOMUX_TO_IRQ(MX51_PIN_EIM_A27); + set_irq_type(irq, IRQF_TRIGGER_RISING); + ret = request_irq(irq, power_key_int, 0, "power_key", 0); + if (ret) + pr_info("register on-off key interrupt failed\n"); + else + enable_irq_wake(irq); + return ret; +} + +late_initcall(mxc_init_power_key); + +/*! + * Board specific initialization. + */ +static void __init mxc_board_init(void) +{ + mxc_cpu_common_init(); + mxc_register_gpios(); + mx51_babbage_io_init(); + early_console_setup(saved_command_line); + + mxc_init_devices(); + + mxc_init_keypad(); + mxc_init_mmc(); + mxc_init_gpio_button(); + mx51_babbage_init_mc13892(); + + if (board_is_babbage_2_5() == 1) + /* BB2.5 */ + spi_register_board_info(mxc_dataflash_device, + ARRAY_SIZE(mxc_dataflash_device)); + else + /* BB2.0 */ + spi_register_board_info(mxc_spi_nor_device, + ARRAY_SIZE(mxc_spi_nor_device)); + +#if defined(CONFIG_I2C_MXC) || defined(CONFIG_I2C_MXC_MODULE) + +#ifdef CONFIG_I2C_MXC_SELECT1 + i2c_register_board_info(0, mxc_i2c0_board_info, + ARRAY_SIZE(mxc_i2c0_board_info)); +#endif +#ifdef CONFIG_I2C_MXC_SELECT2 + i2c_register_board_info(1, mxc_i2c1_board_info, + ARRAY_SIZE(mxc_i2c1_board_info)); +#endif +#if defined(CONFIG_I2C_MXC_HS) || defined(CONFIG_I2C_MXC_HS_MODULE) + if (cpu_is_mx51_rev(CHIP_REV_2_0) >= 1) { + vga_data.core_reg = NULL; + vga_data.io_reg = NULL; + vga_data.analog_reg = NULL; + } + i2c_register_board_info(3, mxc_i2c_hs_board_info, + ARRAY_SIZE(mxc_i2c_hs_board_info)); +#endif + +#endif + pm_power_off = mxc_power_off; + mxc_init_sgtl5000(); +} + +static void __init mx51_babbage_timer_init(void) +{ + /* Change the CPU voltages for TO2*/ + if (cpu_is_mx51_rev(CHIP_REV_2_0) <= 1) { + cpu_wp_auto[0].cpu_voltage = 1175000; + cpu_wp_auto[1].cpu_voltage = 1100000; + cpu_wp_auto[2].cpu_voltage = 1000000; + } + + mxc_clocks_init(32768, 24000000, 22579200, 24576000); + mxc_timer_init("gpt_clk.0"); +} + +static struct sys_timer mxc_timer = { + .init = mx51_babbage_timer_init, +}; + +/* + * The following uses standard kernel macros define in arch.h in order to + * initialize __mach_desc_MX51_BABBAGE data structure. + */ +/* *INDENT-OFF* */ +MACHINE_START(MX51_BABBAGE, "Freescale MX51 Babbage Board") + /* Maintainer: Freescale Semiconductor, Inc. */ + .phys_io = AIPS1_BASE_ADDR, + .io_pg_offst = ((AIPS1_BASE_ADDR_VIRT) >> 18) & 0xfffc, + .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-mx51/mx51_babbage_gpio.c b/arch/arm/mach-mx51/mx51_babbage_gpio.c new file mode 100644 index 000000000000..8e4b9968fef5 --- /dev/null +++ b/arch/arm/mach-mx51/mx51_babbage_gpio.c @@ -0,0 +1,803 @@ +/* + * Copyright 2007-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/platform_device.h> +#include <linux/delay.h> +#include <mach/hardware.h> +#include <mach/gpio.h> + +#include "iomux.h" + +/*! + * @file mach-mx51/mx51_babbage_gpio.c + * + * @brief This file contains all the GPIO setup functions for the board. + * + * @ingroup GPIO + */ + +static struct mxc_iomux_pin_cfg __initdata mxc_iomux_pins[] = { + { + MX51_PIN_EIM_A16, IOMUX_CONFIG_GPIO, + }, + { + MX51_PIN_EIM_A17, IOMUX_CONFIG_GPIO, + }, + { + MX51_PIN_EIM_A18, IOMUX_CONFIG_GPIO, + }, + { + MX51_PIN_EIM_A19, IOMUX_CONFIG_GPIO, + }, + { + MX51_PIN_EIM_A20, IOMUX_CONFIG_GPIO, + (PAD_CTL_PKE_ENABLE), + }, + { + MX51_PIN_EIM_A21, IOMUX_CONFIG_GPIO, + }, + { + MX51_PIN_EIM_A22, IOMUX_CONFIG_GPIO, + }, + { + MX51_PIN_EIM_A23, IOMUX_CONFIG_GPIO, + }, + { /*MDIO */ + MX51_PIN_EIM_EB2, IOMUX_CONFIG_ALT3, + (PAD_CTL_SRE_FAST | PAD_CTL_DRV_HIGH | PAD_CTL_ODE_OPENDRAIN_ENABLE | + PAD_CTL_22K_PU | PAD_CTL_HYS_ENABLE | PAD_CTL_PKE_ENABLE | + PAD_CTL_PUE_PULL), + }, + { /*RDATA[1] */ + + MX51_PIN_EIM_EB3, IOMUX_CONFIG_ALT3, + (PAD_CTL_HYS_ENABLE | PAD_CTL_PKE_ENABLE), + }, + { /*RDATA[2] */ + MX51_PIN_EIM_CS2, IOMUX_CONFIG_ALT3, + (PAD_CTL_HYS_ENABLE | PAD_CTL_PKE_ENABLE), + }, + { /*RDATA[3] */ + MX51_PIN_EIM_CS3, IOMUX_CONFIG_ALT3, + (PAD_CTL_HYS_ENABLE | PAD_CTL_PKE_ENABLE), + }, + { /*RX_ER */ + MX51_PIN_EIM_CS4, IOMUX_CONFIG_ALT3, + (PAD_CTL_HYS_ENABLE | PAD_CTL_PKE_ENABLE), + }, + { /*CRS */ + MX51_PIN_EIM_CS5, IOMUX_CONFIG_ALT3, + (PAD_CTL_HYS_ENABLE | PAD_CTL_PKE_ENABLE), + }, + { + MX51_PIN_EIM_DTACK, IOMUX_CONFIG_GPIO, + (PAD_CTL_PKE_ENABLE | PAD_CTL_100K_PU), + }, + { + MX51_PIN_EIM_LBA, IOMUX_CONFIG_GPIO, + }, + { + MX51_PIN_NANDF_RB2, IOMUX_CONFIG_ALT1, + (PAD_CTL_HYS_ENABLE | PAD_CTL_PKE_ENABLE), + }, + { + MX51_PIN_NANDF_RB3, IOMUX_CONFIG_ALT1, + (PAD_CTL_HYS_ENABLE | PAD_CTL_PKE_ENABLE), + }, + { + MX51_PIN_NANDF_RB4, IOMUX_CONFIG_ALT1, + (PAD_CTL_HYS_ENABLE | PAD_CTL_PKE_ENABLE), + }, + { /*RDATA[0] */ + MX51_PIN_NANDF_RB6, IOMUX_CONFIG_ALT1, + (PAD_CTL_DRV_VOT_HIGH | PAD_CTL_HYS_ENABLE | PAD_CTL_PKE_ENABLE), + }, + { /*TDATA[0] */ + MX51_PIN_NANDF_RB7, IOMUX_CONFIG_ALT1, + (PAD_CTL_DRV_VOT_HIGH | PAD_CTL_DRV_HIGH), + }, + { + MX51_PIN_NANDF_CS0, IOMUX_CONFIG_GPIO, + PAD_CTL_100K_PU, + }, + { + MX51_PIN_NANDF_CS1, IOMUX_CONFIG_GPIO, + }, + { /*TX_ER */ + MX51_PIN_NANDF_CS2, IOMUX_CONFIG_ALT2, + (PAD_CTL_DRV_VOT_HIGH | PAD_CTL_DRV_HIGH), + }, + { + MX51_PIN_NANDF_CS3, IOMUX_CONFIG_ALT2, + (PAD_CTL_DRV_VOT_HIGH | PAD_CTL_DRV_HIGH), + }, + { /*TDATA[1] */ + MX51_PIN_NANDF_CS4, IOMUX_CONFIG_ALT2, + (PAD_CTL_DRV_VOT_HIGH | PAD_CTL_DRV_HIGH), + }, + { /*TDATA[2] */ + MX51_PIN_NANDF_CS5, IOMUX_CONFIG_ALT2, + (PAD_CTL_DRV_VOT_HIGH | PAD_CTL_DRV_HIGH), + }, + { /*TDATA[3] */ + MX51_PIN_NANDF_CS6, IOMUX_CONFIG_ALT2, + (PAD_CTL_DRV_VOT_HIGH | PAD_CTL_DRV_HIGH), + }, + { /*TX_EN */ + MX51_PIN_NANDF_CS7, IOMUX_CONFIG_ALT1, + (PAD_CTL_DRV_VOT_HIGH | PAD_CTL_DRV_HIGH), + }, + { /*TX_CLK */ + MX51_PIN_NANDF_RDY_INT, IOMUX_CONFIG_ALT1, + (PAD_CTL_DRV_VOT_HIGH | PAD_CTL_HYS_ENABLE | PAD_CTL_PKE_ENABLE), + }, + { + MX51_PIN_GPIO1_8, IOMUX_CONFIG_GPIO | IOMUX_CONFIG_SION, + (PAD_CTL_SRE_SLOW | PAD_CTL_DRV_MEDIUM | PAD_CTL_100K_PU | + PAD_CTL_HYS_ENABLE | PAD_CTL_DRV_VOT_HIGH), + }, + { + MX51_PIN_DI_GP4, IOMUX_CONFIG_ALT4, + }, + { + MX51_PIN_DISPB2_SER_DIN, IOMUX_CONFIG_GPIO, + 0, + MUX_IN_GPIO3_IPP_IND_G_IN_5_SELECT_INPUT, + INPUT_CTL_PATH1, + }, +#ifdef CONFIG_FB_MXC_CLAA_WVGA_SYNC_PANEL + { /* DISP2_DAT16 */ + MX51_PIN_DISP1_DAT22, IOMUX_CONFIG_ALT5, + }, + { /* DISP2_DAT17 */ + MX51_PIN_DISP1_DAT23, IOMUX_CONFIG_ALT5, + }, + { + MX51_PIN_DI1_D1_CS, IOMUX_CONFIG_ALT4, + (PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_KEEPER | PAD_CTL_DRV_HIGH | + PAD_CTL_SRE_FAST), + MUX_IN_GPIO3_IPP_IND_G_IN_4_SELECT_INPUT, INPUT_CTL_PATH1, + }, +#endif + /* LVDS GPIO control */ + { + MX51_PIN_DI1_D0_CS, IOMUX_CONFIG_ALT4, + (PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_KEEPER | PAD_CTL_DRV_HIGH | + PAD_CTL_SRE_FAST), + }, + { + MX51_PIN_CSI2_D12, IOMUX_CONFIG_ALT3, + (PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_KEEPER | PAD_CTL_DRV_HIGH | + PAD_CTL_SRE_FAST), + }, + { + MX51_PIN_CSI2_D13, IOMUX_CONFIG_ALT3, + (PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_KEEPER | PAD_CTL_DRV_HIGH | + PAD_CTL_SRE_FAST), + }, + { + MX51_PIN_NANDF_D12, IOMUX_CONFIG_GPIO, + 0, + }, + { + MX51_PIN_I2C1_CLK, IOMUX_CONFIG_ALT0 | IOMUX_CONFIG_SION, + 0x1E4, + }, + { + MX51_PIN_I2C1_DAT, IOMUX_CONFIG_ALT0 | IOMUX_CONFIG_SION, + 0x1E4, + }, + { + MX51_PIN_GPIO1_2, IOMUX_CONFIG_ALT1, + }, + { + MX51_PIN_GPIO1_3, IOMUX_CONFIG_ALT2 | IOMUX_CONFIG_SION, + (PAD_CTL_SRE_FAST | PAD_CTL_ODE_OPENDRAIN_ENABLE | PAD_CTL_DRV_HIGH | + PAD_CTL_100K_PU | PAD_CTL_HYS_ENABLE), + MUX_IN_I2C2_IPP_SDA_IN_SELECT_INPUT, INPUT_CTL_PATH3, + }, + { + MX51_PIN_USBH1_STP, IOMUX_CONFIG_ALT0, + (PAD_CTL_SRE_FAST | PAD_CTL_DRV_HIGH | PAD_CTL_PUE_KEEPER | + PAD_CTL_PKE_ENABLE | PAD_CTL_HYS_ENABLE), + }, + { /* USBH1_CLK */ + MX51_PIN_USBH1_CLK, IOMUX_CONFIG_ALT0, + (PAD_CTL_SRE_FAST | PAD_CTL_DRV_HIGH | PAD_CTL_PUE_KEEPER | + PAD_CTL_PKE_ENABLE | PAD_CTL_HYS_ENABLE | PAD_CTL_DDR_INPUT_CMOS), + }, + { /* USBH1_DIR */ + MX51_PIN_USBH1_DIR, IOMUX_CONFIG_ALT0, + (PAD_CTL_SRE_FAST | PAD_CTL_DRV_HIGH | PAD_CTL_PUE_KEEPER | + PAD_CTL_PKE_ENABLE | PAD_CTL_HYS_ENABLE | PAD_CTL_DDR_INPUT_CMOS), + }, + { /* USBH1_NXT */ + MX51_PIN_USBH1_NXT, IOMUX_CONFIG_ALT0, + (PAD_CTL_SRE_FAST | PAD_CTL_DRV_HIGH | PAD_CTL_PUE_KEEPER | + PAD_CTL_PKE_ENABLE | PAD_CTL_HYS_ENABLE | PAD_CTL_DDR_INPUT_CMOS), + }, + { /* USBH1_DATA0 */ + MX51_PIN_USBH1_DATA0, IOMUX_CONFIG_ALT0, + (PAD_CTL_SRE_FAST | PAD_CTL_DRV_HIGH | PAD_CTL_100K_PU | + PAD_CTL_PUE_KEEPER | PAD_CTL_PKE_ENABLE | PAD_CTL_HYS_ENABLE), + }, + { /* USBH1_DATA1 */ + MX51_PIN_USBH1_DATA1, IOMUX_CONFIG_ALT0, + (PAD_CTL_SRE_FAST | PAD_CTL_DRV_HIGH | PAD_CTL_100K_PU | + PAD_CTL_PUE_KEEPER | PAD_CTL_PKE_ENABLE | PAD_CTL_HYS_ENABLE), + }, + { /* USBH1_DATA2 */ + MX51_PIN_USBH1_DATA2, IOMUX_CONFIG_ALT0, + (PAD_CTL_SRE_FAST | PAD_CTL_DRV_HIGH | PAD_CTL_100K_PU | + PAD_CTL_PUE_KEEPER | PAD_CTL_PKE_ENABLE | PAD_CTL_HYS_ENABLE), + }, + { /* USBH1_DATA3 */ + MX51_PIN_USBH1_DATA3, IOMUX_CONFIG_ALT0, + (PAD_CTL_SRE_FAST | PAD_CTL_DRV_HIGH | PAD_CTL_100K_PU | + PAD_CTL_PUE_KEEPER | PAD_CTL_PKE_ENABLE | PAD_CTL_HYS_ENABLE), + }, + { /* USBH1_DATA4 */ + MX51_PIN_USBH1_DATA4, IOMUX_CONFIG_ALT0, + (PAD_CTL_SRE_FAST | PAD_CTL_DRV_HIGH | PAD_CTL_100K_PU | + PAD_CTL_PUE_KEEPER | PAD_CTL_PKE_ENABLE | PAD_CTL_HYS_ENABLE), + }, + { /* USBH1_DATA5 */ + MX51_PIN_USBH1_DATA5, IOMUX_CONFIG_ALT0, + (PAD_CTL_SRE_FAST | PAD_CTL_DRV_HIGH | PAD_CTL_100K_PU | + PAD_CTL_PUE_KEEPER | PAD_CTL_PKE_ENABLE | PAD_CTL_HYS_ENABLE), + }, + { /* USBH1_DATA6 */ + MX51_PIN_USBH1_DATA6, IOMUX_CONFIG_ALT0, + (PAD_CTL_SRE_FAST | PAD_CTL_DRV_HIGH | PAD_CTL_100K_PU | + PAD_CTL_PUE_KEEPER | PAD_CTL_PKE_ENABLE | PAD_CTL_HYS_ENABLE), + }, + { /* USBH1_DATA7 */ + MX51_PIN_USBH1_DATA7, IOMUX_CONFIG_ALT0, + (PAD_CTL_SRE_FAST | PAD_CTL_DRV_HIGH | PAD_CTL_100K_PU | + PAD_CTL_PUE_KEEPER | PAD_CTL_PKE_ENABLE | PAD_CTL_HYS_ENABLE), + }, + { + MX51_PIN_SD1_CMD, IOMUX_CONFIG_ALT0 | IOMUX_CONFIG_SION, + (PAD_CTL_PUE_KEEPER | PAD_CTL_PKE_ENABLE | PAD_CTL_DRV_HIGH | + PAD_CTL_47K_PU | PAD_CTL_SRE_FAST), + }, + { + MX51_PIN_SD1_CLK, IOMUX_CONFIG_ALT0 | IOMUX_CONFIG_SION, + (PAD_CTL_PUE_KEEPER | PAD_CTL_PKE_ENABLE | PAD_CTL_DRV_HIGH | + PAD_CTL_47K_PU | PAD_CTL_SRE_FAST), + }, + { + MX51_PIN_SD1_DATA0, IOMUX_CONFIG_ALT0, + (PAD_CTL_PUE_KEEPER | PAD_CTL_PKE_ENABLE | PAD_CTL_DRV_HIGH | + PAD_CTL_47K_PU | PAD_CTL_SRE_FAST), + }, + { + MX51_PIN_SD1_DATA1, IOMUX_CONFIG_ALT0, + (PAD_CTL_PUE_KEEPER | PAD_CTL_PKE_ENABLE | PAD_CTL_DRV_HIGH | + PAD_CTL_47K_PU | PAD_CTL_SRE_FAST), + }, + { + MX51_PIN_SD1_DATA2, IOMUX_CONFIG_ALT0, + (PAD_CTL_PUE_KEEPER | PAD_CTL_PKE_ENABLE | PAD_CTL_DRV_HIGH | + PAD_CTL_47K_PU | PAD_CTL_SRE_FAST), + }, + { + MX51_PIN_SD1_DATA3, IOMUX_CONFIG_ALT0, + (PAD_CTL_PUE_KEEPER | PAD_CTL_PKE_ENABLE | PAD_CTL_DRV_HIGH | + PAD_CTL_47K_PU | PAD_CTL_SRE_FAST), + }, + { + MX51_PIN_GPIO1_0, IOMUX_CONFIG_GPIO | IOMUX_CONFIG_SION, + (PAD_CTL_HYS_ENABLE | PAD_CTL_100K_PU), + }, + { + MX51_PIN_GPIO1_1, IOMUX_CONFIG_GPIO | IOMUX_CONFIG_SION, + (PAD_CTL_HYS_ENABLE | PAD_CTL_100K_PU), + }, + { + MX51_PIN_SD2_CMD, IOMUX_CONFIG_ALT0 | IOMUX_CONFIG_SION, + (PAD_CTL_DRV_MAX | PAD_CTL_22K_PU | PAD_CTL_SRE_FAST), + }, + { + MX51_PIN_SD2_CLK, IOMUX_CONFIG_ALT0 | IOMUX_CONFIG_SION, + (PAD_CTL_DRV_MAX | PAD_CTL_22K_PU | PAD_CTL_SRE_FAST), + }, + { + MX51_PIN_SD2_DATA0, IOMUX_CONFIG_ALT0, + (PAD_CTL_DRV_MAX | PAD_CTL_22K_PU | PAD_CTL_SRE_FAST), + }, + { + MX51_PIN_SD2_DATA1, IOMUX_CONFIG_ALT0, + (PAD_CTL_DRV_MAX | PAD_CTL_22K_PU | PAD_CTL_SRE_FAST), + }, + { + MX51_PIN_SD2_DATA2, IOMUX_CONFIG_ALT0, + (PAD_CTL_DRV_MAX | PAD_CTL_22K_PU | PAD_CTL_SRE_FAST), + }, + { + MX51_PIN_SD2_DATA3, IOMUX_CONFIG_ALT0, + (PAD_CTL_DRV_MAX | PAD_CTL_22K_PU | PAD_CTL_SRE_FAST), + }, + { + MX51_PIN_GPIO1_4, IOMUX_CONFIG_GPIO | IOMUX_CONFIG_SION, + (PAD_CTL_HYS_ENABLE | PAD_CTL_100K_PU), + }, + { + MX51_PIN_GPIO1_5, IOMUX_CONFIG_GPIO | IOMUX_CONFIG_SION, + (PAD_CTL_HYS_ENABLE | PAD_CTL_100K_PU), + }, + { + MX51_PIN_GPIO1_6, IOMUX_CONFIG_GPIO | IOMUX_CONFIG_SION, + (PAD_CTL_HYS_ENABLE | PAD_CTL_100K_PU), + }, + { /* Detect pin GPIO BB2.0 and BB2.5 */ + MX51_PIN_UART3_RXD, IOMUX_CONFIG_ALT3, + (PAD_CTL_HYS_NONE | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_KEEPER | + PAD_CTL_DRV_HIGH | PAD_CTL_SRE_FAST), + }, + { + MX51_PIN_UART1_RXD, IOMUX_CONFIG_ALT0, + (PAD_CTL_HYS_ENABLE | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | + PAD_CTL_DRV_HIGH | PAD_CTL_SRE_FAST), + MUX_IN_UART1_IPP_UART_RXD_MUX_SELECT_INPUT, + INPUT_CTL_PATH0, + }, + { + MX51_PIN_UART1_TXD, IOMUX_CONFIG_ALT0, + (PAD_CTL_HYS_ENABLE | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | + PAD_CTL_DRV_HIGH | PAD_CTL_SRE_FAST), + }, + { + MX51_PIN_UART1_RTS, IOMUX_CONFIG_ALT0, + (PAD_CTL_HYS_ENABLE | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | + PAD_CTL_DRV_HIGH), + MUX_IN_UART1_IPP_UART_RTS_B_SELECT_INPUT, + INPUT_CTL_PATH0, + }, + { + MX51_PIN_UART1_CTS, IOMUX_CONFIG_ALT0, + (PAD_CTL_HYS_ENABLE | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | + PAD_CTL_DRV_HIGH), + }, + { + MX51_PIN_AUD3_BB_TXD, IOMUX_CONFIG_ALT0, + (PAD_CTL_SRE_FAST | PAD_CTL_DRV_HIGH | PAD_CTL_ODE_OPENDRAIN_NONE | + PAD_CTL_100K_PU | PAD_CTL_HYS_NONE | PAD_CTL_DDR_INPUT_CMOS | + PAD_CTL_DRV_VOT_LOW), + }, + { + MX51_PIN_AUD3_BB_RXD, IOMUX_CONFIG_ALT0, + (PAD_CTL_SRE_FAST | PAD_CTL_DRV_HIGH | PAD_CTL_ODE_OPENDRAIN_NONE | + PAD_CTL_100K_PU | PAD_CTL_HYS_NONE | PAD_CTL_DDR_INPUT_CMOS | + PAD_CTL_DRV_VOT_LOW), + }, + { + MX51_PIN_AUD3_BB_CK, IOMUX_CONFIG_ALT0, + (PAD_CTL_SRE_FAST | PAD_CTL_DRV_HIGH | PAD_CTL_ODE_OPENDRAIN_NONE | + PAD_CTL_100K_PU | PAD_CTL_HYS_NONE | PAD_CTL_DDR_INPUT_CMOS | + PAD_CTL_DRV_VOT_LOW), + }, + { + MX51_PIN_AUD3_BB_FS, IOMUX_CONFIG_ALT0, + (PAD_CTL_SRE_FAST | PAD_CTL_DRV_HIGH | PAD_CTL_ODE_OPENDRAIN_NONE | + PAD_CTL_100K_PU | PAD_CTL_HYS_NONE | PAD_CTL_DDR_INPUT_CMOS | + PAD_CTL_DRV_VOT_LOW), + }, + { + MX51_PIN_CSPI1_SS1, IOMUX_CONFIG_ALT0, + (PAD_CTL_HYS_ENABLE | PAD_CTL_PKE_ENABLE | PAD_CTL_DRV_HIGH | + PAD_CTL_SRE_FAST), + }, + /* Camera on expansion board */ + { /* camera reset */ + MX51_PIN_EIM_D23, IOMUX_CONFIG_ALT1, + (PAD_CTL_HYS_NONE | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_KEEPER | + PAD_CTL_DRV_HIGH | PAD_CTL_SRE_FAST), + }, + { /* camera low power */ + MX51_PIN_CSI2_D19, IOMUX_CONFIG_ALT3, + (PAD_CTL_HYS_NONE | PAD_CTL_PKE_ENABLE | PAD_CTL_DRV_LOW | + PAD_CTL_SRE_SLOW), + }, + { /* CSI1_DATA_EN need to be pulled up */ + MX51_PIN_DI_GP3, IOMUX_CONFIG_ALT3, + (PAD_CTL_HYS_NONE | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | + PAD_CTL_DRV_HIGH | PAD_CTL_SRE_FAST), + MUX_IN_HSC_MIPI_MIX_IPP_IND_SENS2_DATA_EN_SELECT_INPUT, + INPUT_CTL_PATH1, + }, + { + MX51_PIN_CSI1_D10, IOMUX_CONFIG_ALT0, PAD_CTL_HYS_NONE, + }, + { + MX51_PIN_CSI1_D11, IOMUX_CONFIG_ALT0, PAD_CTL_HYS_NONE, + }, + { + MX51_PIN_CSI1_D12, IOMUX_CONFIG_ALT0, PAD_CTL_HYS_NONE, + }, + { + MX51_PIN_CSI1_D13, IOMUX_CONFIG_ALT0, PAD_CTL_HYS_NONE, + }, + { + MX51_PIN_CSI1_D14, IOMUX_CONFIG_ALT0, PAD_CTL_HYS_NONE, + }, + { + MX51_PIN_CSI1_D15, IOMUX_CONFIG_ALT0, PAD_CTL_HYS_NONE, + }, + { + MX51_PIN_CSI1_D16, IOMUX_CONFIG_ALT0, PAD_CTL_HYS_NONE, + }, + { + MX51_PIN_CSI1_D17, IOMUX_CONFIG_ALT0, PAD_CTL_HYS_NONE, + }, + { + MX51_PIN_CSI1_D18, IOMUX_CONFIG_ALT0, PAD_CTL_HYS_NONE, + }, + { + MX51_PIN_CSI1_D19, IOMUX_CONFIG_ALT0, PAD_CTL_HYS_NONE, + }, + { + MX51_PIN_CSI1_VSYNC, IOMUX_CONFIG_ALT0, + (PAD_CTL_HYS_NONE | PAD_CTL_SRE_SLOW), + }, + { + MX51_PIN_CSI1_HSYNC, IOMUX_CONFIG_ALT0, + (PAD_CTL_HYS_NONE | PAD_CTL_SRE_SLOW), + }, + { + MX51_PIN_EIM_D18, IOMUX_CONFIG_GPIO, + (PAD_CTL_DRV_HIGH | PAD_CTL_PKE_ENABLE | + PAD_CTL_PUE_KEEPER | PAD_CTL_100K_PU | PAD_CTL_SRE_FAST), + }, +}; + +static int __initdata enable_w1 = { 0 }; +static int __init w1_setup(char *__unused) +{ + enable_w1 = 1; + return 1; +} + +__setup("w1", w1_setup); + +void __init mx51_babbage_io_init(void) +{ + int i; + + /* Work-around For external USB HUB chip to use default configuration + by reseting hub with i2c lines pulled low */ + mxc_request_iomux(MX51_PIN_GPIO1_7, IOMUX_CONFIG_GPIO); + mxc_iomux_set_pad(MX51_PIN_GPIO1_7, PAD_CTL_DRV_HIGH | + PAD_CTL_PKE_ENABLE | PAD_CTL_SRE_FAST); + gpio_request(IOMUX_TO_GPIO(MX51_PIN_GPIO1_7), "gpio1_7"); + gpio_direction_output(IOMUX_TO_GPIO(MX51_PIN_GPIO1_7), 0); + + if (cpu_is_mx51_rev(CHIP_REV_1_1) == 1) { + /* Drive I2C1 SDA line low */ + mxc_request_iomux(MX51_PIN_GPIO1_3, IOMUX_CONFIG_ALT0); + mxc_iomux_set_pad(MX51_PIN_GPIO1_3, PAD_CTL_DRV_HIGH | + PAD_CTL_PKE_ENABLE | PAD_CTL_SRE_FAST); + gpio_request(IOMUX_TO_GPIO(MX51_PIN_GPIO1_3), "gpio1_3"); + gpio_direction_output(IOMUX_TO_GPIO(MX51_PIN_GPIO1_3), 0); + gpio_set_value(IOMUX_TO_GPIO(MX51_PIN_GPIO1_3), 0); + + /* Drive I2C1 SCL line low */ + mxc_request_iomux(MX51_PIN_GPIO1_2, IOMUX_CONFIG_ALT0); + mxc_iomux_set_pad(MX51_PIN_GPIO1_2, PAD_CTL_DRV_HIGH | + PAD_CTL_PKE_ENABLE | PAD_CTL_SRE_FAST); + gpio_request(IOMUX_TO_GPIO(MX51_PIN_GPIO1_2), "gpio1_2"); + gpio_direction_output(IOMUX_TO_GPIO(MX51_PIN_GPIO1_2), 0); + gpio_set_value(IOMUX_TO_GPIO(MX51_PIN_GPIO1_2), 0); + + msleep(5); + mxc_free_iomux(MX51_PIN_GPIO1_2, IOMUX_CONFIG_ALT2); + mxc_free_iomux(MX51_PIN_GPIO1_3, IOMUX_CONFIG_ALT2); + } + + /* USB HUB RESET - De-assert USB HUB RESET_N */ + msleep(1); + gpio_set_value(IOMUX_TO_GPIO(MX51_PIN_GPIO1_7), 0); + msleep(1); + gpio_set_value(IOMUX_TO_GPIO(MX51_PIN_GPIO1_7), 1); + + for (i = 0; i < ARRAY_SIZE(mxc_iomux_pins); i++) { + mxc_request_iomux(mxc_iomux_pins[i].pin, + mxc_iomux_pins[i].mux_mode); + if (mxc_iomux_pins[i].pad_cfg) + mxc_iomux_set_pad(mxc_iomux_pins[i].pin, + mxc_iomux_pins[i].pad_cfg); + if (mxc_iomux_pins[i].in_select) + mxc_iomux_set_input(mxc_iomux_pins[i].in_select, + mxc_iomux_pins[i].in_mode); + } + + gpio_request(IOMUX_TO_GPIO(MX51_PIN_GPIO1_8), "gpio1_8"); + gpio_request(IOMUX_TO_GPIO(MX51_PIN_GPIO1_0), "gpio1_0"); + gpio_request(IOMUX_TO_GPIO(MX51_PIN_GPIO1_1), "gpio1_1"); + gpio_direction_input(IOMUX_TO_GPIO(MX51_PIN_GPIO1_8)); + gpio_direction_input(IOMUX_TO_GPIO(MX51_PIN_GPIO1_0)); /* SD1 CD */ + gpio_direction_input(IOMUX_TO_GPIO(MX51_PIN_GPIO1_1)); /* SD1 WP */ + if (board_is_babbage_2_5() == 1) { + /* SD2 CD for BB2.5 */ + gpio_request(IOMUX_TO_GPIO(MX51_PIN_GPIO1_6), "gpio1_6"); + gpio_direction_input(IOMUX_TO_GPIO(MX51_PIN_GPIO1_6)); + } else { + /* SD2 CD for BB2.0 */ + gpio_request(IOMUX_TO_GPIO(MX51_PIN_GPIO1_4), "gpio1_4"); + gpio_direction_input(IOMUX_TO_GPIO(MX51_PIN_GPIO1_4)); + } + gpio_request(IOMUX_TO_GPIO(MX51_PIN_GPIO1_5), "gpio1_5"); + gpio_direction_input(IOMUX_TO_GPIO(MX51_PIN_GPIO1_5)); /* SD2 WP */ + + /* reset FEC PHY */ + gpio_request(IOMUX_TO_GPIO(MX51_PIN_EIM_A20), "eim_a20"); + gpio_direction_output(IOMUX_TO_GPIO(MX51_PIN_EIM_A20), 0); + gpio_set_value(IOMUX_TO_GPIO(MX51_PIN_EIM_A20), 0); + msleep(10); + gpio_set_value(IOMUX_TO_GPIO(MX51_PIN_EIM_A20), 1); + + /* reset FM */ + gpio_request(IOMUX_TO_GPIO(MX51_PIN_EIM_A21), "eim_a21"); + gpio_set_value(IOMUX_TO_GPIO(MX51_PIN_EIM_A21), 0); + gpio_direction_output(IOMUX_TO_GPIO(MX51_PIN_EIM_A21), 0); + msleep(10); + gpio_set_value(IOMUX_TO_GPIO(MX51_PIN_EIM_A21), 1); + + if (cpu_is_mx51_rev(CHIP_REV_1_1) == 1) { + /* MX51_PIN_EIM_CRE - De-assert USB PHY RESETB */ + gpio_request(IOMUX_TO_GPIO(MX51_PIN_EIM_CRE), "eim_cre"); + gpio_direction_output(IOMUX_TO_GPIO(MX51_PIN_EIM_CRE), 0); + gpio_set_value(IOMUX_TO_GPIO(MX51_PIN_EIM_CRE), 1); + + /* hphone_det_b */ + gpio_request(IOMUX_TO_GPIO(MX51_PIN_NANDF_CS0), "nandf_cs0"); + gpio_direction_input(IOMUX_TO_GPIO(MX51_PIN_NANDF_CS0)); + } else { + mxc_free_iomux(MX51_PIN_EIM_D21, IOMUX_CONFIG_ALT2); + mxc_free_iomux(MX51_PIN_EIM_A24, IOMUX_CONFIG_ALT2); + mxc_free_iomux(MX51_PIN_EIM_A25, IOMUX_CONFIG_ALT2); + mxc_free_iomux(MX51_PIN_EIM_D18, IOMUX_CONFIG_ALT2); + mxc_free_iomux(MX51_PIN_EIM_D20, IOMUX_CONFIG_ALT2); + mxc_free_iomux(MX51_PIN_EIM_D21, IOMUX_CONFIG_ALT2); + mxc_free_iomux(MX51_PIN_EIM_D16, IOMUX_CONFIG_ALT2); + mxc_free_iomux(MX51_PIN_EIM_D17, IOMUX_CONFIG_ALT2); + mxc_free_iomux(MX51_PIN_EIM_D19, IOMUX_CONFIG_ALT2); + mxc_free_iomux(MX51_PIN_GPIO1_2, IOMUX_CONFIG_ALT2); + mxc_free_iomux(MX51_PIN_GPIO1_3, IOMUX_CONFIG_ALT2); + mxc_free_iomux(MX51_PIN_EIM_LBA, IOMUX_CONFIG_GPIO); + mxc_free_iomux(MX51_PIN_NANDF_CS0, IOMUX_CONFIG_GPIO); + + /* i2c1 SDA */ + mxc_request_iomux(MX51_PIN_EIM_D16, + IOMUX_CONFIG_ALT4 | IOMUX_CONFIG_SION); + mxc_iomux_set_input(MUX_IN_I2C1_IPP_SDA_IN_SELECT_INPUT, + INPUT_CTL_PATH0); + mxc_iomux_set_pad(MX51_PIN_EIM_D16, PAD_CTL_SRE_FAST | + PAD_CTL_ODE_OPENDRAIN_ENABLE | + PAD_CTL_DRV_HIGH | PAD_CTL_100K_PU | + PAD_CTL_HYS_ENABLE); + + /* i2c1 SCL */ + mxc_request_iomux(MX51_PIN_EIM_D19, + IOMUX_CONFIG_ALT4 | IOMUX_CONFIG_SION); + mxc_iomux_set_input(MUX_IN_I2C1_IPP_SCL_IN_SELECT_INPUT, + INPUT_CTL_PATH0); + mxc_iomux_set_pad(MX51_PIN_EIM_D19, PAD_CTL_SRE_FAST | + PAD_CTL_ODE_OPENDRAIN_ENABLE | + PAD_CTL_DRV_HIGH | PAD_CTL_100K_PU | + PAD_CTL_HYS_ENABLE); + + /* i2c2 SDA */ + mxc_request_iomux(MX51_PIN_KEY_COL5, + IOMUX_CONFIG_ALT3 | IOMUX_CONFIG_SION); + mxc_iomux_set_input(MUX_IN_I2C2_IPP_SDA_IN_SELECT_INPUT, + INPUT_CTL_PATH1); + mxc_iomux_set_pad(MX51_PIN_KEY_COL5, + PAD_CTL_SRE_FAST | + PAD_CTL_ODE_OPENDRAIN_ENABLE | + PAD_CTL_DRV_HIGH | PAD_CTL_100K_PU | + PAD_CTL_HYS_ENABLE); + + /* i2c2 SCL */ + mxc_request_iomux(MX51_PIN_KEY_COL4, + IOMUX_CONFIG_ALT3 | IOMUX_CONFIG_SION); + mxc_iomux_set_input(MUX_IN_I2C2_IPP_SCL_IN_SELECT_INPUT, + INPUT_CTL_PATH1); + mxc_iomux_set_pad(MX51_PIN_KEY_COL4, + PAD_CTL_SRE_FAST | + PAD_CTL_ODE_OPENDRAIN_ENABLE | + PAD_CTL_DRV_HIGH | PAD_CTL_100K_PU | + PAD_CTL_HYS_ENABLE); + + /* Drive 26M_OSC_EN line high */ + mxc_request_iomux(MX51_PIN_DI1_PIN12, IOMUX_CONFIG_ALT4); + mxc_iomux_set_pad(MX51_PIN_DI1_PIN12, PAD_CTL_DRV_HIGH | + PAD_CTL_PKE_ENABLE | PAD_CTL_SRE_FAST); + gpio_request(IOMUX_TO_GPIO(MX51_PIN_DI1_PIN12), "di1_pin12"); + gpio_direction_output(IOMUX_TO_GPIO(MX51_PIN_DI1_PIN12), 0); + gpio_set_value(IOMUX_TO_GPIO(MX51_PIN_DI1_PIN12), 1); + + /* Drive USB_CLK_EN_B line low */ + mxc_request_iomux(MX51_PIN_EIM_D17, IOMUX_CONFIG_ALT1); + mxc_iomux_set_pad(MX51_PIN_EIM_D17, PAD_CTL_DRV_HIGH | + PAD_CTL_PKE_ENABLE | PAD_CTL_SRE_FAST); + gpio_request(IOMUX_TO_GPIO(MX51_PIN_EIM_D17), "eim_d17"); + gpio_direction_output(IOMUX_TO_GPIO(MX51_PIN_EIM_D17), 0); + gpio_set_value(IOMUX_TO_GPIO(MX51_PIN_EIM_D17), 0); + + /* MX51_PIN_EIM_D21 - De-assert USB PHY RESETB */ + mxc_request_iomux(MX51_PIN_EIM_D21, IOMUX_CONFIG_ALT1); + mxc_iomux_set_pad(MX51_PIN_EIM_D21, PAD_CTL_DRV_HIGH | + PAD_CTL_HYS_NONE | PAD_CTL_PUE_KEEPER | + PAD_CTL_100K_PU | PAD_CTL_ODE_OPENDRAIN_NONE | + PAD_CTL_PKE_ENABLE | PAD_CTL_SRE_FAST); + gpio_request(IOMUX_TO_GPIO(MX51_PIN_EIM_D21), "eim_d21"); + gpio_direction_output(IOMUX_TO_GPIO(MX51_PIN_EIM_D21), 0); + gpio_set_value(IOMUX_TO_GPIO(MX51_PIN_EIM_D21), 1); + + /* hphone_det_b */ + mxc_request_iomux(MX51_PIN_NANDF_D14, IOMUX_CONFIG_ALT3); + mxc_iomux_set_pad(MX51_PIN_NANDF_D14, PAD_CTL_100K_PU); + gpio_request(IOMUX_TO_GPIO(MX51_PIN_NANDF_D14), "nandf_d14"); + gpio_direction_input(IOMUX_TO_GPIO(MX51_PIN_NANDF_D14)); + + /* audio_clk_en_b */ + mxc_request_iomux(MX51_PIN_CSPI1_RDY, IOMUX_CONFIG_ALT3); + mxc_iomux_set_pad(MX51_PIN_CSPI1_RDY, PAD_CTL_DRV_HIGH | + PAD_CTL_HYS_NONE | PAD_CTL_PUE_KEEPER | + PAD_CTL_100K_PU | PAD_CTL_ODE_OPENDRAIN_NONE | + PAD_CTL_PKE_ENABLE | PAD_CTL_SRE_FAST); + gpio_request(IOMUX_TO_GPIO(MX51_PIN_CSPI1_RDY), "cspi1_rdy"); + gpio_direction_output(IOMUX_TO_GPIO(MX51_PIN_CSPI1_RDY), 0); + gpio_set_value(IOMUX_TO_GPIO(MX51_PIN_CSPI1_RDY), 0); + + /* power key */ + mxc_request_iomux(MX51_PIN_EIM_A27, IOMUX_CONFIG_ALT1); + mxc_iomux_set_pad(MX51_PIN_EIM_A27, PAD_CTL_SRE_FAST | + PAD_CTL_ODE_OPENDRAIN_NONE | + PAD_CTL_DRV_HIGH | PAD_CTL_100K_PU | + PAD_CTL_HYS_NONE); + gpio_request(IOMUX_TO_GPIO(MX51_PIN_EIM_A27), "eim_a27"); + gpio_direction_input(IOMUX_TO_GPIO(MX51_PIN_EIM_A27)); + } + + if (cpu_is_mx51_rev(CHIP_REV_3_0) > 0) { + /* DVI_I2C_ENB = 0 tristates the DVI I2C level shifter */ + mxc_request_iomux(MX51_PIN_CSI2_HSYNC, IOMUX_CONFIG_ALT3); + mxc_iomux_set_pad(MX51_PIN_CSI2_HSYNC, PAD_CTL_DRV_HIGH | + PAD_CTL_PKE_ENABLE | PAD_CTL_SRE_FAST); + gpio_request(IOMUX_TO_GPIO(MX51_PIN_CSI2_HSYNC), "csi2_hsync"); + gpio_direction_output(IOMUX_TO_GPIO(MX51_PIN_CSI2_HSYNC), 0); + gpio_set_value(IOMUX_TO_GPIO(MX51_PIN_CSI2_HSYNC), 0); + + /* TO3 doesn't need pad to drive CSI_DATA_EN[0] high */ + mxc_request_iomux(MX51_PIN_DI_GP3, IOMUX_CONFIG_ALT0); + } + + /* Deassert VGA reset to free i2c bus */ + gpio_request(IOMUX_TO_GPIO(MX51_PIN_EIM_A19), "eim_a19"); + gpio_direction_output(IOMUX_TO_GPIO(MX51_PIN_EIM_A19), 0); + gpio_set_value(IOMUX_TO_GPIO(MX51_PIN_EIM_A19), 1); + + /* LCD related gpio */ + gpio_request(IOMUX_TO_GPIO(MX51_PIN_DI1_D1_CS), "di1_d1_cs"); + gpio_request(IOMUX_TO_GPIO(MX51_PIN_DI1_D0_CS), "di1_d0_cs"); + gpio_request(IOMUX_TO_GPIO(MX51_PIN_CSI2_D12), "csi2_d12"); + gpio_request(IOMUX_TO_GPIO(MX51_PIN_CSI2_D13), "csi2_d13"); + gpio_direction_output(IOMUX_TO_GPIO(MX51_PIN_DI1_D1_CS), 0); + gpio_direction_output(IOMUX_TO_GPIO(MX51_PIN_DI1_D0_CS), 0); + gpio_direction_output(IOMUX_TO_GPIO(MX51_PIN_CSI2_D12), 0); + gpio_direction_output(IOMUX_TO_GPIO(MX51_PIN_CSI2_D13), 0); + + /* Camera reset */ + gpio_request(IOMUX_TO_GPIO(MX51_PIN_EIM_D23), "eim_d23"); + gpio_direction_output(IOMUX_TO_GPIO(MX51_PIN_EIM_D23), 0); + gpio_set_value(IOMUX_TO_GPIO(MX51_PIN_EIM_D23), 1); + + /* Camera low power */ + gpio_request(IOMUX_TO_GPIO(MX51_PIN_CSI2_D19), "csi2_d19"); + gpio_direction_output(IOMUX_TO_GPIO(MX51_PIN_CSI2_D19), 0); + gpio_set_value(IOMUX_TO_GPIO(MX51_PIN_CSI2_D19), 0); + + /* OSC_EN */ + gpio_request(IOMUX_TO_GPIO(MX51_PIN_EIM_D18), "eim_d18"); + gpio_direction_output(IOMUX_TO_GPIO(MX51_PIN_EIM_D18), 0); + gpio_set_value(IOMUX_TO_GPIO(MX51_PIN_EIM_D18), 1); + + if (enable_w1) { + /* OneWire */ + mxc_request_iomux(MX51_PIN_OWIRE_LINE, IOMUX_CONFIG_ALT0); + mxc_iomux_set_pad(MX51_PIN_OWIRE_LINE, PAD_CTL_HYS_ENABLE | + PAD_CTL_PKE_ENABLE | + PAD_CTL_ODE_OPENDRAIN_ENABLE | + PAD_CTL_DRV_HIGH | PAD_CTL_SRE_FAST | + PAD_CTL_100K_PU | PAD_CTL_PUE_PULL); + } else { + /* SPDIF Out */ + mxc_request_iomux(MX51_PIN_OWIRE_LINE, IOMUX_CONFIG_ALT6); + mxc_iomux_set_pad(MX51_PIN_OWIRE_LINE, PAD_CTL_DRV_HIGH | + PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | + PAD_CTL_100K_PU | PAD_CTL_SRE_FAST); + } +} + +/* workaround for ecspi chipselect pin may not keep correct level when idle */ +void mx51_babbage_gpio_spi_chipselect_active(int cspi_mode, int status, + int chipselect) +{ + u32 gpio; + + switch (cspi_mode) { + case 1: + switch (chipselect) { + case 0x1: + mxc_request_iomux(MX51_PIN_CSPI1_SS0, + IOMUX_CONFIG_ALT0); + mxc_iomux_set_pad(MX51_PIN_CSPI1_SS0, + PAD_CTL_HYS_ENABLE | + PAD_CTL_PKE_ENABLE | + PAD_CTL_DRV_HIGH | PAD_CTL_SRE_FAST); + break; + case 0x2: + gpio = IOMUX_TO_GPIO(MX51_PIN_CSPI1_SS0); + mxc_request_iomux(MX51_PIN_CSPI1_SS0, + IOMUX_CONFIG_GPIO); + gpio_request(gpio, "cspi1_ss0"); + gpio_direction_output(gpio, 0); + gpio_set_value(gpio, 1 & (~status)); + break; + default: + break; + } + break; + case 2: + break; + case 3: + break; + default: + break; + } +} +EXPORT_SYMBOL(mx51_babbage_gpio_spi_chipselect_active); + +void mx51_babbage_gpio_spi_chipselect_inactive(int cspi_mode, int status, + int chipselect) +{ + switch (cspi_mode) { + case 1: + switch (chipselect) { + case 0x1: + mxc_free_iomux(MX51_PIN_CSPI1_SS0, IOMUX_CONFIG_ALT0); + mxc_request_iomux(MX51_PIN_CSPI1_SS0, + IOMUX_CONFIG_GPIO); + mxc_free_iomux(MX51_PIN_CSPI1_SS0, IOMUX_CONFIG_GPIO); + break; + case 0x2: + mxc_free_iomux(MX51_PIN_CSPI1_SS0, IOMUX_CONFIG_GPIO); + break; + default: + break; + } + break; + case 2: + break; + case 3: + break; + default: + break; + } +} +EXPORT_SYMBOL(mx51_babbage_gpio_spi_chipselect_inactive); + diff --git a/arch/arm/mach-mx51/mx51_babbage_pmic_mc13892.c b/arch/arm/mach-mx51/mx51_babbage_pmic_mc13892.c new file mode 100644 index 000000000000..7a8e2216aff1 --- /dev/null +++ b/arch/arm/mach-mx51/mx51_babbage_pmic_mc13892.c @@ -0,0 +1,363 @@ +/* + * mx51-3stack-pmic-mc13892.c -- i.MX51 3STACK Driver for Atlas MC13892 PMIC + */ + /* + * Copyright 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/init.h> +#include <linux/platform_device.h> +#include <linux/spi/spi.h> +#include <linux/err.h> +#include <linux/pmic_external.h> +#include <linux/regulator/machine.h> +#include <linux/mfd/mc13892/core.h> +#include "iomux.h" + +/* + * Convenience conversion. + * Here atm, maybe there is somewhere better for this. + */ +#define mV_to_uV(mV) (mV * 1000) +#define uV_to_mV(uV) (uV / 1000) +#define V_to_uV(V) (mV_to_uV(V * 1000)) +#define uV_to_V(uV) (uV_to_mV(uV) / 1000) + +/* Coin cell charger enable */ +#define CIONCHEN_LSH 23 +#define CIONCHEN_WID 1 +/* Coin cell charger voltage setting */ +#define VCOIN_LSH 20 +#define VCOIN_WID 3 + +/* Coin Charger voltage */ +#define VCOIN_2_5V 0x0 +#define VCOIN_2_7V 0x1 +#define VCOIN_2_8V 0x2 +#define VCOIN_2_9V 0x3 +#define VCOIN_3_0V 0x4 +#define VCOIN_3_1V 0x5 +#define VCOIN_3_2V 0x6 +#define VCOIN_3_3V 0x7 + +/* Keeps VSRTC and CLK32KMCU on for all states */ +#define DRM_LSH 4 +#define DRM_WID 1 + +/* regulator standby mask */ +#define GEN1_STBY_MASK (1 << 1) +#define IOHI_STBY_MASK (1 << 4) +#define DIG_STBY_MASK (1 << 10) +#define GEN2_STBY_MASK (1 << 13) +#define PLL_STBY_MASK (1 << 16) +#define USB2_STBY_MASK (1 << 19) + +#define GEN3_STBY_MASK (1 << 1) +#define CAM_STBY_MASK (1 << 7) +#define VIDEO_STBY_MASK (1 << 13) +#define AUDIO_STBY_MASK (1 << 16) +#define SD_STBY_MASK (1 << 19) + +/* 0x92412 */ +#define REG_MODE_0_ALL_MASK (GEN1_STBY_MASK |\ + DIG_STBY_MASK | GEN2_STBY_MASK |\ + PLL_STBY_MASK | USB2_STBY_MASK) +/* 0x92082 */ +#define REG_MODE_1_ALL_MASK (GEN3_STBY_MASK | CAM_STBY_MASK |\ + VIDEO_STBY_MASK | AUDIO_STBY_MASK |\ + SD_STBY_MASK) + +/* CPU */ +static struct regulator_consumer_supply sw1_consumers[] = { + { + .supply = "cpu_vcc", + } +}; + +struct mc13892; + +static struct regulator_init_data sw1_init = { + .constraints = { + .name = "SW1", + .min_uV = mV_to_uV(600), + .max_uV = mV_to_uV(1375), + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE, + .valid_modes_mask = 0, + .always_on = 1, + .boot_on = 1, + .initial_state = PM_SUSPEND_MEM, + .state_mem = { + .uV = 850000, + .mode = REGULATOR_MODE_NORMAL, + .enabled = 1, + }, + }, + .num_consumer_supplies = ARRAY_SIZE(sw1_consumers), + .consumer_supplies = sw1_consumers, +}; + +static struct regulator_init_data sw2_init = { + .constraints = { + .name = "SW2", + .min_uV = mV_to_uV(900), + .max_uV = mV_to_uV(1850), + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE, + .always_on = 1, + .boot_on = 1, + .initial_state = PM_SUSPEND_MEM, + .state_mem = { + .uV = 950000, + .mode = REGULATOR_MODE_NORMAL, + .enabled = 1, + }, + } +}; + +static struct regulator_init_data sw3_init = { + .constraints = { + .name = "SW3", + .min_uV = mV_to_uV(1100), + .max_uV = mV_to_uV(1850), + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE, + .always_on = 1, + .boot_on = 1, + } +}; + +static struct regulator_init_data sw4_init = { + .constraints = { + .name = "SW4", + .min_uV = mV_to_uV(1100), + .max_uV = mV_to_uV(1850), + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE, + .always_on = 1, + .boot_on = 1, + } +}; + +static struct regulator_init_data viohi_init = { + .constraints = { + .name = "VIOHI", + .boot_on = 1, + } +}; + +static struct regulator_init_data vusb_init = { + .constraints = { + .name = "VUSB", + .boot_on = 1, + } +}; + +static struct regulator_init_data swbst_init = { + .constraints = { + .name = "SWBST", + } +}; + +static struct regulator_init_data vdig_init = { + .constraints = { + .name = "VDIG", + .min_uV = mV_to_uV(1050), + .max_uV = mV_to_uV(1800), + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE, + .boot_on = 1, + } +}; + +static struct regulator_init_data vpll_init = { + .constraints = { + .name = "VPLL", + .min_uV = mV_to_uV(1050), + .max_uV = mV_to_uV(1800), + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE, + .boot_on = 1, + } +}; + +static struct regulator_init_data vusb2_init = { + .constraints = { + .name = "VUSB2", + .min_uV = mV_to_uV(2400), + .max_uV = mV_to_uV(2775), + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE, + .boot_on = 1, + } +}; + +static struct regulator_init_data vvideo_init = { + .constraints = { + .name = "VVIDEO", + .min_uV = mV_to_uV(2775), + .max_uV = mV_to_uV(2775), + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE, + .always_on = 1, + .apply_uV =1, + } +}; + +static struct regulator_init_data vaudio_init = { + .constraints = { + .name = "VAUDIO", + .min_uV = mV_to_uV(2300), + .max_uV = mV_to_uV(3000), + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE, + } +}; + +static struct regulator_init_data vsd_init = { + .constraints = { + .name = "VSD", + .min_uV = mV_to_uV(1800), + .max_uV = mV_to_uV(3150), + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE, + } +}; + +static struct regulator_init_data vcam_init = { + .constraints = { + .name = "VCAM", + .min_uV = mV_to_uV(2500), + .max_uV = mV_to_uV(3000), + .valid_ops_mask = + REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_MODE, + .valid_modes_mask = REGULATOR_MODE_FAST | REGULATOR_MODE_NORMAL, + } +}; + +static struct regulator_init_data vgen1_init = { + .constraints = { + .name = "VGEN1", + .min_uV = mV_to_uV(1200), + .max_uV = mV_to_uV(3150), + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE, + } +}; + +static struct regulator_init_data vgen2_init = { + .constraints = { + .name = "VGEN2", + .min_uV = mV_to_uV(1200), + .max_uV = mV_to_uV(3150), + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE, + } +}; + +static struct regulator_init_data vgen3_init = { + .constraints = { + .name = "VGEN3", + .min_uV = mV_to_uV(1800), + .max_uV = mV_to_uV(2900), + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE, + } +}; + +static struct regulator_init_data gpo1_init = { + .constraints = { + .name = "GPO1", + } +}; + +static struct regulator_init_data gpo2_init = { + .constraints = { + .name = "GPO2", + } +}; + +static struct regulator_init_data gpo3_init = { + .constraints = { + .name = "GPO3", + } +}; + +static struct regulator_init_data gpo4_init = { + .constraints = { + .name = "GPO4", + } +}; + +static int mc13892_regulator_init(struct mc13892 *mc13892) +{ + unsigned int value, register_mask; + printk("Initializing regulators for Babbage.\n"); + if (mxc_cpu_is_rev(CHIP_REV_2_0) < 0) + sw2_init.constraints.state_mem.uV = 1100000; + else if (mxc_cpu_is_rev(CHIP_REV_2_0) == 1) { + sw2_init.constraints.state_mem.uV = 1250000; + sw1_init.constraints.state_mem.uV = 1000000; + } + + /* enable standby controll for all regulators */ + pmic_read_reg(REG_MODE_0, &value, 0xffffff); + value |= REG_MODE_0_ALL_MASK; + pmic_write_reg(REG_MODE_0, value, 0xffffff); + + pmic_read_reg(REG_MODE_1, &value, 0xffffff); + value |= REG_MODE_1_ALL_MASK; + pmic_write_reg(REG_MODE_1, value, 0xffffff); + + /* Enable coin cell charger */ + value = BITFVAL(CIONCHEN, 1) | BITFVAL(VCOIN, VCOIN_3_0V); + register_mask = BITFMASK(CIONCHEN) | BITFMASK(VCOIN); + pmic_write_reg(REG_POWER_CTL0, value, register_mask); + +#if defined(CONFIG_RTC_DRV_MXC_V2) || defined(CONFIG_RTC_DRV_MXC_V2_MODULE) + value = BITFVAL(DRM, 1); + register_mask = BITFMASK(DRM); + pmic_write_reg(REG_POWER_CTL0, value, register_mask); +#endif + + mc13892_register_regulator(mc13892, MC13892_SW1, &sw1_init); + mc13892_register_regulator(mc13892, MC13892_SW2, &sw2_init); + mc13892_register_regulator(mc13892, MC13892_SW3, &sw3_init); + mc13892_register_regulator(mc13892, MC13892_SW4, &sw4_init); + mc13892_register_regulator(mc13892, MC13892_SWBST, &swbst_init); + mc13892_register_regulator(mc13892, MC13892_VIOHI, &viohi_init); + mc13892_register_regulator(mc13892, MC13892_VPLL, &vpll_init); + mc13892_register_regulator(mc13892, MC13892_VDIG, &vdig_init); + mc13892_register_regulator(mc13892, MC13892_VSD, &vsd_init); + mc13892_register_regulator(mc13892, MC13892_VUSB2, &vusb2_init); + mc13892_register_regulator(mc13892, MC13892_VVIDEO, &vvideo_init); + mc13892_register_regulator(mc13892, MC13892_VAUDIO, &vaudio_init); + mc13892_register_regulator(mc13892, MC13892_VCAM, &vcam_init); + mc13892_register_regulator(mc13892, MC13892_VGEN1, &vgen1_init); + mc13892_register_regulator(mc13892, MC13892_VGEN2, &vgen2_init); + mc13892_register_regulator(mc13892, MC13892_VGEN3, &vgen3_init); + mc13892_register_regulator(mc13892, MC13892_VUSB, &vusb_init); + mc13892_register_regulator(mc13892, MC13892_GPO1, &gpo1_init); + mc13892_register_regulator(mc13892, MC13892_GPO2, &gpo2_init); + mc13892_register_regulator(mc13892, MC13892_GPO3, &gpo3_init); + mc13892_register_regulator(mc13892, MC13892_GPO4, &gpo4_init); + + return 0; +} + +static struct mc13892_platform_data mc13892_plat = { + .init = mc13892_regulator_init, +}; + +static struct spi_board_info __initdata mc13892_spi_device = { + .modalias = "pmic_spi", + .irq = IOMUX_TO_IRQ(MX51_PIN_GPIO1_8), + .max_speed_hz = 1000000, /* max spi SCK clock speed in HZ */ + .bus_num = 1, + .chip_select = 0, + .platform_data = &mc13892_plat, +}; + + +int __init mx51_babbage_init_mc13892(void) +{ + return spi_register_board_info(&mc13892_spi_device, 1); +} + diff --git a/arch/arm/mach-mx51/mx51_ccwmx51js.c b/arch/arm/mach-mx51/mx51_ccwmx51js.c new file mode 100644 index 000000000000..2d603bb3655e --- /dev/null +++ b/arch/arm/mach-mx51/mx51_ccwmx51js.c @@ -0,0 +1,566 @@ +/* + * Copyright 2009 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright 2009 Digi International, 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/types.h> +#include <linux/sched.h> +#include <linux/delay.h> +#include <linux/pm.h> +#include <linux/interrupt.h> +#include <linux/irq.h> +#include <linux/init.h> +#include <linux/input.h> +#include <linux/nodemask.h> +#include <linux/clk.h> +#include <linux/platform_device.h> +#include <linux/fsl_devices.h> +#include <linux/spi/spi.h> +#include <linux/i2c.h> +#include <linux/ata.h> +#include <linux/regulator/consumer.h> +#include <linux/pmic_external.h> +#include <linux/pmic_status.h> +#include <linux/ipu.h> +#include <linux/mxcfb.h> +#include <mach/common.h> +#include <mach/hardware.h> +#include <mach/spba.h> +#include <asm/irq.h> +#include <asm/setup.h> +#include <asm/mach-types.h> +#include <asm/mach/arch.h> +#include <asm/mach/time.h> +#include <mach/memory.h> +#include <mach/gpio.h> +#include <mach/mmc.h> +#include "board.h" +#include "iomux.h" +#include "crm_regs.h" + + +#include <linux/smc911x.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 + +extern void __init ccwmx51_io_init(void); +extern int __init ccwmx51_init_mc13892(void); +extern struct cpu_wp *(*get_cpu_wp)(int *wp); +extern void (*set_num_cpu_wp)(int num); +static int num_cpu_wp = 3; + +/* working point(wp): 0 - 800MHz; 1 - 166.25MHz; */ +static struct cpu_wp cpu_wp_auto[] = { + { + .pll_rate = 1000000000, + .cpu_rate = 1000000000, + .pdf = 0, + .mfi = 10, + .mfd = 11, + .mfn = 5, + .cpu_podf = 0, + .cpu_voltage = 1175000,}, + { + .pll_rate = 800000000, + .cpu_rate = 800000000, + .pdf = 0, + .mfi = 8, + .mfd = 2, + .mfn = 1, + .cpu_podf = 0, + .cpu_voltage = 1100000,}, + { + .pll_rate = 800000000, + .cpu_rate = 166250000, + .pdf = 4, + .mfi = 8, + .mfd = 2, + .mfn = 1, + .cpu_podf = 4, + .cpu_voltage = 850000,}, +}; + +struct cpu_wp *mx51_get_cpu_wp(int *wp) +{ + *wp = num_cpu_wp; + return cpu_wp_auto; +} + +void mx51_set_num_cpu_wp(int num) +{ + num_cpu_wp = num; + return; +} +static void mxc_nop_release(struct device *dev) +{ + /* Nothing */ +} + +/* MTD NAND flash */ +#if defined(CONFIG_MTD_NAND_MXC) \ + || defined(CONFIG_MTD_NAND_MXC_MODULE) \ + || defined(CONFIG_MTD_NAND_MXC_V2) \ + || defined(CONFIG_MTD_NAND_MXC_V2_MODULE) \ + || defined(CONFIG_MTD_NAND_MXC_V3) \ + || defined(CONFIG_MTD_NAND_MXC_V3_MODULE) + +extern void gpio_nand_active(void); +extern void gpio_nand_inactive(void); + +static int nand_init(void) +{ + /* Configure the pins */ + gpio_nand_active(); + return 0; +} + +static void nand_exit(void) +{ + /* Free the pins */ + gpio_nand_inactive(); +} + +static struct flash_platform_data mxc_nand_data = { + .width = 1, + .init = nand_init, + .exit = nand_exit, +}; + +static struct platform_device mxc_nandv2_mtd_device = { + .name = "mxc_nandv2_flash", + .id = 0, + .dev = { + .release = mxc_nop_release, + .platform_data = &mxc_nand_data, + }, +}; + +static void ccwmx51_init_nand_mtd(void) +{ + (void)platform_device_register(&mxc_nandv2_mtd_device); +} +#else +static inline void ccwmx51_init_nand_mtd(void) { } +#endif + +#if defined(CONFIG_SMSC9118) +static struct resource smsc911x_device_resources[] = { + [0] = { + .name = "smsc911x-memory", + .start = CS5_BASE_ADDR, + .end = CS5_BASE_ADDR + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IOMUX_TO_IRQ(MX51_PIN_GPIO1_9), + .end = IOMUX_TO_IRQ(MX51_PIN_GPIO1_9), + .flags = IORESOURCE_IRQ, + }, +}; + +static struct smc911x_platdata ccwmx51_smsc9118 = { + .flags = SMC911X_USE_16BIT, + .irq_flags = IRQF_DISABLED | IRQF_TRIGGER_FALLING, + .irq_polarity = 0, +}; + +static struct platform_device smsc911x_device = { + .name = "smsc911x", + .id = -1, + .num_resources = ARRAY_SIZE(smsc911x_device_resources), + .resource = smsc911x_device_resources, + .dev = { + .platform_data = &ccwmx51_smsc9118, + } +}; + +/* WEIM registers */ +#define CSGCR1 0x00 +#define CSGCR2 0x04 +#define CSRCR1 0x08 +#define CSRCR2 0x0C +#define CSWCR1 0x10 + +static void ccwmx51_init_ext_eth_mac(void) +{ + __iomem u32 *weim_vbaddr; + + weim_vbaddr = ioremap(WEIM_BASE_ADDR, SZ_4K); + if (weim_vbaddr == 0) { + printk(KERN_ERR "Unable to ioremap 0x%08x in %s\n", WEIM_BASE_ADDR, __func__); + return; + } + + /** Configure the CS timming, bus width, etc. + * 16 bit on DATA[31..16], not multiplexed, async + * RWSC=50, RADVA=2, RADVN=6, OEA=0, OEN=0, RCSA=0, RCSN=0, APR=0 + * WAL=0, WBED=1, WWSC=50, WADVA=2, WADVN=6, WEA=0, WEN=0, WCSA=0 + */ + __raw_writel(0x00420081, weim_vbaddr + 0x78 + CSGCR1); + __raw_writel(0, weim_vbaddr + 0x78 + CSGCR2); + __raw_writel(0x32260000, weim_vbaddr + 0x78 + CSRCR1); + __raw_writel(0, weim_vbaddr + 0x78 + CSRCR2); + __raw_writel(0x72080f00, weim_vbaddr + 0x78 + CSWCR1); + + iounmap(weim_vbaddr); + + /* Configure interrupt line as GPIO input, the iomux should be already setup */ + gpio_request(IOMUX_TO_GPIO(MX51_PIN_GPIO1_9), "LAN2-irq"); + gpio_direction_input(IOMUX_TO_GPIO(MX51_PIN_GPIO1_9)); + + (void)platform_device_register(&smsc911x_device); +} +#else +static void ccwmx51_init_ext_eth_mac(void) { } +#endif + + +#if defined(CONFIG_FEC) || defined(CONFIG_FEC_MODULE) +unsigned int expio_intr_fec; + +EXPORT_SYMBOL(expio_intr_fec); +#endif + +#if defined(CONFIG_MMC_IMX_ESDHCI) || defined(CONFIG_MMC_IMX_ESDHCI_MODULE) +static int sdhc_write_protect(struct device *dev) +{ + unsigned short rc = 0; + + if (to_platform_device(dev)->id == 0) + rc = 1; /* Not supported WP on JSK board */ + else if (to_platform_device(dev)->id == 2) + rc = gpio_get_value(IOMUX_TO_GPIO(MX51_PIN_NANDF_CS1)); + + return rc; +} + +static unsigned int sdhc_get_card_det_status(struct device *dev) +{ + int ret = 0; + + if (to_platform_device(dev)->id == 0) + ret = gpio_get_value(IOMUX_TO_GPIO(MX51_PIN_GPIO1_0)); + else if (to_platform_device(dev)->id == 2) + ret = gpio_get_value(IOMUX_TO_GPIO(MX51_PIN_GPIO_NAND)); + + return ret; +} + +static struct mxc_mmc_platform_data mmc1_data = { + .ocr_mask = MMC_VDD_31_32, + .caps = MMC_CAP_4_BIT_DATA, + .min_clk = 400000, + .max_clk = 52000000, + .card_inserted_state = 1, + .status = sdhc_get_card_det_status, + .wp_status = sdhc_write_protect, + .clock_mmc = "esdhc_clk", + .power_mmc = NULL, +}; + +static struct mxc_mmc_platform_data mmc3_data = { + .ocr_mask = MMC_VDD_27_28 | MMC_VDD_28_29 | MMC_VDD_29_30 | + MMC_VDD_31_32, + .caps = MMC_CAP_4_BIT_DATA, + .min_clk = 150000, + .max_clk = 50000000, + .card_inserted_state = 0, + .status = sdhc_get_card_det_status, + .wp_status = sdhc_write_protect, + .clock_mmc = "esdhc_clk", + .power_mmc = NULL, +}; + +/** + * Resource definition for the SDHC1 + */ +static struct resource mxcsdhc1_resources[] = { + [0] = { + .start = MMC_SDHC1_BASE_ADDR, + .end = MMC_SDHC1_BASE_ADDR + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = MXC_INT_MMC_SDHC1, + .end = MXC_INT_MMC_SDHC1, + .flags = IORESOURCE_IRQ, + }, + [2] = { + .start = IOMUX_TO_IRQ(MX51_PIN_GPIO1_0), + .end = IOMUX_TO_IRQ(MX51_PIN_GPIO1_0), + .flags = IORESOURCE_IRQ, + }, +}; + +/** + * Resource definition for the SDHC3 + */ +static struct resource mxcsdhc3_resources[] = { + [0] = { + .start = MMC_SDHC3_BASE_ADDR, + .end = MMC_SDHC3_BASE_ADDR + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = MXC_INT_MMC_SDHC3, + .end = MXC_INT_MMC_SDHC3, + .flags = IORESOURCE_IRQ, + }, + [2] = { + .start = IOMUX_TO_IRQ(MX51_PIN_GPIO_NAND), + .end = IOMUX_TO_IRQ(MX51_PIN_GPIO_NAND), + .flags = IORESOURCE_IRQ, + }, +}; + +/*! Device Definition for MXC SDHC1 */ +static struct platform_device mxcsdhc1_device = { + .name = "mxsdhci", + .id = 0, + .dev = { + .release = mxc_nop_release, + .platform_data = &mmc1_data, + }, + .num_resources = ARRAY_SIZE(mxcsdhc1_resources), + .resource = mxcsdhc1_resources, +}; + +/*! Device Definition for MXC SDHC3 */ +static struct platform_device mxcsdhc3_device = { + .name = "mxsdhci", + .id = 2, + .dev = { + .release = mxc_nop_release, + .platform_data = &mmc3_data, + }, + .num_resources = ARRAY_SIZE(mxcsdhc3_resources), + .resource = mxcsdhc3_resources, +}; + +static inline void ccwmx51_init_mmc(void) +{ + (void)platform_device_register(&mxcsdhc1_device); + (void)platform_device_register(&mxcsdhc3_device); +} +#else +static inline void ccwmx51_init_mmc(void) {} +#endif + +#if defined(CONFIG_FB_MXC_SYNC_PANEL) || \ + defined(CONFIG_FB_MXC_SYNC_PANEL_MODULE) + +static struct mxc_fb_platform_data fb_data_vga = { + .interface_pix_fmt = IPU_PIX_FMT_RGB24, + .mode_str = "1024x768M-16@60", /* Default */ +}; + +static struct platform_device mxc_fb_device[] = { + { + .name = "mxc_sdc_fb", + .id = 0, + .dev = { + .release = mxc_nop_release, + .coherent_dma_mask = 0xFFFFFFFF, + .platform_data = &fb_data_vga, + }, + }, { + .name = "mxc_sdc_fb", + .id = 1, + .dev = { + .release = mxc_nop_release, + .coherent_dma_mask = 0xFFFFFFFF, + .platform_data = NULL, + }, + }, { + .name = "mxc_sdc_fb", + .id = 2, + .dev = { + .release = mxc_nop_release, + .coherent_dma_mask = 0xFFFFFFFF, + }, + }, +}; + +static int __init ccwmx51_init_fb(void) +{ + char *options = NULL, *p; + + if (fb_get_options("displayfb", &options)) + pr_warning("no display information available in commnad line\n"); + + if (!options) + return -ENODEV; + + if (!strncasecmp(options, "VGA", 3)) { + pr_info("VGA interface is primary\n"); + + /* Get the desired configuration provided by the bootloader */ + if (options[3] != '@') { + pr_info("Video resolution for VGA interface not provided, using default\n"); + /* TODO set default video here */ + } else { + options = &options[4]; + if (((p = strsep (&options, "@")) != NULL) && *p) { + if (!strcmp(p, "640x480x16")) { + strcpy(fb_data_vga.mode_str, "640x480M-16@60"); + } else if (!strcmp(p, "800x600x16")) { + strcpy(fb_data_vga.mode_str, "800x600M-16@60"); + } else if (!strcmp(p, "1024x768x16")) { + strcpy(fb_data_vga.mode_str, "1024x768M-16@60"); + } else if (!strcmp(p, "1280x1024x16")) { + strcpy(fb_data_vga.mode_str, "1280x1024M-16@60"); + } else if (!strcmp(p, "1280x1024x16")) { + strcpy(fb_data_vga.mode_str, "1280x1024M-16@60"); + } else + pr_warning("Unsuported video resolution: %s, using default\n", p); + } + } + (void)platform_device_register(&mxc_fb_device[0]); /* VGA */ + } + + return 0; +} +device_initcall(ccwmx51_init_fb); +#else +static inline void ccwmx51_init_fb(void) { } +#endif + + + +/*! + * Board specific fixup function. It is called by \b setup_arch() in + * setup.c file very early on during kernel starts. It allows the user to + * statically fill in the proper values for the passed-in parameters. None of + * the parameters is used currently. + * + * @param desc pointer to \b struct \b machine_desc + * @param tags pointer to \b struct \b tag + * @param cmdline pointer to the command line + * @param mi pointer to \b struct \b meminfo + */ +static void __init fixup_mxc_board(struct machine_desc *desc, struct tag *tags, + char **cmdline, struct meminfo *mi) +{ + char *str; + int size = SZ_512M - SZ_32M; + struct tag *t; + + mxc_cpu_init(); + + get_cpu_wp = mx51_get_cpu_wp; + set_num_cpu_wp = mx51_set_num_cpu_wp; + + for_each_tag(t, tags) { + if (t->hdr.tag != ATAG_CMDLINE) + continue; + str = t->u.cmdline.cmdline; + str = strstr(str, "mem="); + if (str != NULL) { + str += 4; + size = memparse(str, &str); + if (size == 0 || size == SZ_512M) + return; + } + } + + for_each_tag(t, tags) { + if (t->hdr.tag != ATAG_MEM) + continue; + + t->u.mem.size = size; + } +} + +#define PWGT1SPIEN (1<<15) +#define PWGT2SPIEN (1<<16) +#define USEROFFSPI (1<<3) + +static void mxc_power_off(void) +{ + /* We can do power down one of two ways: + Set the power gating + Set USEROFFSPI */ + + /* Set the power gate bits to power down */ + pmic_write_reg(REG_POWER_MISC, (PWGT1SPIEN|PWGT2SPIEN), + (PWGT1SPIEN|PWGT2SPIEN)); +} + +static struct i2c_board_info ccwmx51_i2c_devices[] __initdata = { +#if defined(CONFIG_INPUT_MMA7455L) + { + I2C_BOARD_INFO("mma7455l", 0x1d), + .irq = IOMUX_TO_IRQ(MX51_PIN_GPIO1_7), + }, +#endif +}; + +int __init ccwmx51_init_mma7455l(void) +{ + + return i2c_register_board_info(1, ccwmx51_i2c_devices , ARRAY_SIZE(ccwmx51_i2c_devices) ); +} + +/*! + * Board specific initialization. + */ +static void __init mxc_board_init(void) +{ + mxc_cpu_common_init(); + mxc_register_gpios(); + ccwmx51_io_init(); + early_console_setup(saved_command_line); + + mxc_init_devices(); + ccwmx51_init_mmc(); + ccwmx51_init_nand_mtd(); +// ccwmx51_init_ext_eth_mac(); + ccwmx51_init_mma7455l(); + ccwmx51_init_mc13892(); + + pm_power_off = mxc_power_off; +} + +static void __init ccwmx51_timer_init(void) +{ + /* Change the CPU voltages for TO2*/ + if (cpu_is_mx51_rev(CHIP_REV_2_0) <= 1) { + cpu_wp_auto[0].cpu_voltage = 1175000; + cpu_wp_auto[1].cpu_voltage = 1100000; + cpu_wp_auto[2].cpu_voltage = 1000000; + } + + mxc_clocks_init(32768, 24000000, 22579200, 24576000); + mxc_timer_init("gpt_clk.0"); +} + +static struct sys_timer mxc_timer = { + .init = ccwmx51_timer_init, +}; + +MACHINE_START(CCWMX51JS, "ConnectCore Wi-MX51 on a JSK board") + /* Maintainer: Digi International, Inc. */ + .phys_io = AIPS1_BASE_ADDR, + .io_pg_offst = ((AIPS1_BASE_ADDR_VIRT) >> 18) & 0xfffc, + .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-mx51/mx51_ccwmx51js_gpio.c b/arch/arm/mach-mx51/mx51_ccwmx51js_gpio.c new file mode 100644 index 000000000000..3458935cd8cf --- /dev/null +++ b/arch/arm/mach-mx51/mx51_ccwmx51js_gpio.c @@ -0,0 +1,528 @@ +/* + * Copyright 2009 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright 2009 Digi International, 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/platform_device.h> +#include <linux/delay.h> +#include <mach/hardware.h> +#include <mach/gpio.h> + +#include "iomux.h" + +/** + * iomux settings for the external ethernet mac + */ +#if defined(CONFIG_SMSC9118) +static struct mxc_iomux_pin_cfg __initdata ccwmx51_iomux_ext_eth_pins[] = { + {MX51_PIN_EIM_CS5, IOMUX_CONFIG_ALT0, + (PAD_CTL_HYS_ENABLE | PAD_CTL_PUE_KEEPER | PAD_CTL_DRV_MEDIUM), }, + {MX51_PIN_EIM_OE, IOMUX_CONFIG_ALT0,}, + {MX51_PIN_EIM_DA0, IOMUX_CONFIG_ALT0,}, + {MX51_PIN_EIM_DA1, IOMUX_CONFIG_ALT0,}, + {MX51_PIN_EIM_DA2, IOMUX_CONFIG_ALT0,}, + {MX51_PIN_EIM_DA3, IOMUX_CONFIG_ALT0,}, + {MX51_PIN_EIM_DA4, IOMUX_CONFIG_ALT0,}, + {MX51_PIN_EIM_DA5, IOMUX_CONFIG_ALT0,}, + {MX51_PIN_EIM_DA6, IOMUX_CONFIG_ALT0,}, + {MX51_PIN_EIM_DA7, IOMUX_CONFIG_ALT0,}, + {MX51_PIN_EIM_D16, IOMUX_CONFIG_ALT0,}, + {MX51_PIN_EIM_D17, IOMUX_CONFIG_ALT0,}, + {MX51_PIN_EIM_D18, IOMUX_CONFIG_ALT0,}, + {MX51_PIN_EIM_D19, IOMUX_CONFIG_ALT0,}, + {MX51_PIN_EIM_D20, IOMUX_CONFIG_ALT0,}, + {MX51_PIN_EIM_D21, IOMUX_CONFIG_ALT0,}, + {MX51_PIN_EIM_D22, IOMUX_CONFIG_ALT0,}, + {MX51_PIN_EIM_D23, IOMUX_CONFIG_ALT0,}, + {MX51_PIN_EIM_D24, IOMUX_CONFIG_ALT0,}, + {MX51_PIN_EIM_D25, IOMUX_CONFIG_ALT0,}, + {MX51_PIN_EIM_D26, IOMUX_CONFIG_ALT0,}, + {MX51_PIN_EIM_D27, IOMUX_CONFIG_ALT0,}, + {MX51_PIN_EIM_D28, IOMUX_CONFIG_ALT0,}, + {MX51_PIN_EIM_D29, IOMUX_CONFIG_ALT0,}, + {MX51_PIN_EIM_D30, IOMUX_CONFIG_ALT0,}, + {MX51_PIN_EIM_D31, IOMUX_CONFIG_ALT0,}, + {MX51_PIN_GPIO1_9, IOMUX_CONFIG_ALT0, (PAD_CTL_HYS_ENABLE | PAD_CTL_100K_PU), }, +}; +#endif + +#if defined(CONFIG_MMC_IMX_ESDHCI) || defined(CONFIG_MMC_IMX_ESDHCI_MODULE) +static struct mxc_iomux_pin_cfg __initdata ccwmx51_iomux_mmc_pins[] = { + /* SDHC1*/ + { + MX51_PIN_SD1_CMD, IOMUX_CONFIG_ALT0 | IOMUX_CONFIG_SION, + (PAD_CTL_PUE_KEEPER | PAD_CTL_PKE_ENABLE | PAD_CTL_DRV_HIGH | + PAD_CTL_47K_PU | PAD_CTL_SRE_FAST), + }, + { + MX51_PIN_SD1_CLK, IOMUX_CONFIG_ALT0 | IOMUX_CONFIG_SION, + (PAD_CTL_PUE_KEEPER | PAD_CTL_PKE_ENABLE | PAD_CTL_DRV_HIGH | + PAD_CTL_47K_PU | PAD_CTL_SRE_FAST), + }, + { + MX51_PIN_SD1_DATA0, IOMUX_CONFIG_ALT0, + (PAD_CTL_PUE_KEEPER | PAD_CTL_PKE_ENABLE | PAD_CTL_DRV_HIGH | + PAD_CTL_47K_PU | PAD_CTL_SRE_FAST), + }, + { + MX51_PIN_SD1_DATA1, IOMUX_CONFIG_ALT0, + (PAD_CTL_PUE_KEEPER | PAD_CTL_PKE_ENABLE | PAD_CTL_DRV_HIGH | + PAD_CTL_47K_PU | PAD_CTL_SRE_FAST), + }, + { + MX51_PIN_SD1_DATA2, IOMUX_CONFIG_ALT0, + (PAD_CTL_PUE_KEEPER | PAD_CTL_PKE_ENABLE | PAD_CTL_DRV_HIGH | + PAD_CTL_47K_PU | PAD_CTL_SRE_FAST), + }, + { + MX51_PIN_SD1_DATA3, IOMUX_CONFIG_ALT0, + (PAD_CTL_PUE_KEEPER | PAD_CTL_PKE_ENABLE | PAD_CTL_DRV_HIGH | + PAD_CTL_47K_PU | PAD_CTL_SRE_FAST), + }, + { + MX51_PIN_GPIO1_0, IOMUX_CONFIG_GPIO | IOMUX_CONFIG_SION, + (PAD_CTL_HYS_ENABLE | PAD_CTL_100K_PU), + }, + + /* SDHC3*/ + { + MX51_PIN_NANDF_RDY_INT, IOMUX_CONFIG_ALT5 | IOMUX_CONFIG_SION, + (PAD_CTL_DRV_MAX | PAD_CTL_22K_PU | PAD_CTL_SRE_FAST), + }, + { + MX51_PIN_NANDF_CS7, IOMUX_CONFIG_ALT5, + (PAD_CTL_DRV_MAX | PAD_CTL_22K_PU | PAD_CTL_SRE_FAST), + }, + { /* SD3 DATA0 */ + MX51_PIN_NANDF_D8, IOMUX_CONFIG_ALT5, + (PAD_CTL_DRV_MAX | PAD_CTL_22K_PU | PAD_CTL_SRE_FAST), + MUX_IN_ESDHC3_IPP_DAT0_IN_SELECT_INPUT, INPUT_CTL_PATH1 + }, + { /* SD3 DATA1 */ + MX51_PIN_NANDF_D9, IOMUX_CONFIG_ALT5, + (PAD_CTL_DRV_MAX | PAD_CTL_22K_PU | PAD_CTL_SRE_FAST), + MUX_IN_ESDHC3_IPP_DAT1_IN_SELECT_INPUT, INPUT_CTL_PATH1 + }, + { /* SD3 DATA2 */ + MX51_PIN_NANDF_D10, IOMUX_CONFIG_ALT5, + (PAD_CTL_DRV_MAX | PAD_CTL_22K_PU | PAD_CTL_SRE_FAST), + MUX_IN_ESDHC3_IPP_DAT2_IN_SELECT_INPUT, INPUT_CTL_PATH1 + }, + { /* SD3 DATA3 */ + MX51_PIN_NANDF_D11, IOMUX_CONFIG_ALT5, + (PAD_CTL_DRV_MAX | PAD_CTL_22K_PU | PAD_CTL_SRE_FAST), + MUX_IN_ESDHC3_IPP_DAT3_IN_SELECT_INPUT, INPUT_CTL_PATH1 + }, + { /* SD3 Card detect */ + MX51_PIN_GPIO_NAND, IOMUX_CONFIG_GPIO | IOMUX_CONFIG_SION, + (PAD_CTL_HYS_ENABLE | PAD_CTL_100K_PU), + }, + { /* SD3 Write protect */ + MX51_PIN_NANDF_CS1, IOMUX_CONFIG_GPIO | IOMUX_CONFIG_SION, + (PAD_CTL_HYS_ENABLE | PAD_CTL_100K_PU), + }, +}; +#endif + +#if defined(CONFIG_USB_EHCI_ARC_H1) || defined(CONFIG_USB_EHCI_ARC_H1_MODULE) +static struct mxc_iomux_pin_cfg __initdata ccwmx51_iomux_usbh1_pins[] = { + { /* USBH1_STP */ + MX51_PIN_USBH1_STP, IOMUX_CONFIG_ALT0, + (PAD_CTL_SRE_FAST | PAD_CTL_DRV_HIGH | PAD_CTL_PUE_KEEPER | + PAD_CTL_PKE_ENABLE | PAD_CTL_HYS_ENABLE), + }, + { /* USBH1_CLK */ + MX51_PIN_USBH1_CLK, IOMUX_CONFIG_ALT0, + (PAD_CTL_SRE_FAST | PAD_CTL_DRV_HIGH | PAD_CTL_PUE_KEEPER | + PAD_CTL_PKE_ENABLE | PAD_CTL_HYS_ENABLE | PAD_CTL_DDR_INPUT_CMOS), + }, + { /* USBH1_DIR */ + MX51_PIN_USBH1_DIR, IOMUX_CONFIG_ALT0, + (PAD_CTL_SRE_FAST | PAD_CTL_DRV_HIGH | PAD_CTL_PUE_KEEPER | + PAD_CTL_PKE_ENABLE | PAD_CTL_HYS_ENABLE | PAD_CTL_DDR_INPUT_CMOS), + }, + { /* USBH1_NXT */ + MX51_PIN_USBH1_NXT, IOMUX_CONFIG_ALT0, + (PAD_CTL_SRE_FAST | PAD_CTL_DRV_HIGH | PAD_CTL_PUE_KEEPER | + PAD_CTL_PKE_ENABLE | PAD_CTL_HYS_ENABLE | PAD_CTL_DDR_INPUT_CMOS), + }, + { /* USBH1_DATA0 */ + MX51_PIN_USBH1_DATA0, IOMUX_CONFIG_ALT0, + (PAD_CTL_SRE_FAST | PAD_CTL_DRV_HIGH | PAD_CTL_100K_PU | + PAD_CTL_PUE_KEEPER | PAD_CTL_PKE_ENABLE | PAD_CTL_HYS_ENABLE), + }, + { /* USBH1_DATA1 */ + MX51_PIN_USBH1_DATA1, IOMUX_CONFIG_ALT0, + (PAD_CTL_SRE_FAST | PAD_CTL_DRV_HIGH | PAD_CTL_100K_PU | + PAD_CTL_PUE_KEEPER | PAD_CTL_PKE_ENABLE | PAD_CTL_HYS_ENABLE), + }, + { /* USBH1_DATA2 */ + MX51_PIN_USBH1_DATA2, IOMUX_CONFIG_ALT0, + (PAD_CTL_SRE_FAST | PAD_CTL_DRV_HIGH | PAD_CTL_100K_PU | + PAD_CTL_PUE_KEEPER | PAD_CTL_PKE_ENABLE | PAD_CTL_HYS_ENABLE), + }, + { /* USBH1_DATA3 */ + MX51_PIN_USBH1_DATA3, IOMUX_CONFIG_ALT0, + (PAD_CTL_SRE_FAST | PAD_CTL_DRV_HIGH | PAD_CTL_100K_PU | + PAD_CTL_PUE_KEEPER | PAD_CTL_PKE_ENABLE | PAD_CTL_HYS_ENABLE), + }, + { /* USBH1_DATA4 */ + MX51_PIN_USBH1_DATA4, IOMUX_CONFIG_ALT0, + (PAD_CTL_SRE_FAST | PAD_CTL_DRV_HIGH | PAD_CTL_100K_PU | + PAD_CTL_PUE_KEEPER | PAD_CTL_PKE_ENABLE | PAD_CTL_HYS_ENABLE), + }, + { /* USBH1_DATA5 */ + MX51_PIN_USBH1_DATA5, IOMUX_CONFIG_ALT0, + (PAD_CTL_SRE_FAST | PAD_CTL_DRV_HIGH | PAD_CTL_100K_PU | + PAD_CTL_PUE_KEEPER | PAD_CTL_PKE_ENABLE | PAD_CTL_HYS_ENABLE), + }, + { /* USBH1_DATA6 */ + MX51_PIN_USBH1_DATA6, IOMUX_CONFIG_ALT0, + (PAD_CTL_SRE_FAST | PAD_CTL_DRV_HIGH | PAD_CTL_100K_PU | + PAD_CTL_PUE_KEEPER | PAD_CTL_PKE_ENABLE | PAD_CTL_HYS_ENABLE), + }, + { /* USBH1_DATA7 */ + MX51_PIN_USBH1_DATA7, IOMUX_CONFIG_ALT0, + (PAD_CTL_SRE_FAST | PAD_CTL_DRV_HIGH | PAD_CTL_100K_PU | + PAD_CTL_PUE_KEEPER | PAD_CTL_PKE_ENABLE | PAD_CTL_HYS_ENABLE), + }, + { /* USBH PHY RESET */ + MX51_PIN_DISPB2_SER_RS, IOMUX_CONFIG_GPIO, + (PAD_CTL_SRE_FAST | PAD_CTL_DRV_HIGH | PAD_CTL_47K_PU | + PAD_CTL_PUE_KEEPER | PAD_CTL_PKE_ENABLE | PAD_CTL_HYS_ENABLE), + }, +}; +#endif + +#if defined(CONFIG_FB_MXC_SYNC_PANEL) || defined(CONFIG_FB_MXC_SYNC_PANEL_MODULE) +static struct mxc_iomux_pin_cfg __initdata ccwmx51_iomux_video1_pins[] = { + { /* DISP1 DAT0 */ + MX51_PIN_DISP1_DAT0, IOMUX_CONFIG_ALT0, + (PAD_CTL_HYS_NONE | PAD_CTL_DRV_LOW | PAD_CTL_SRE_FAST), + }, + { /* DISP1 DAT1 */ + MX51_PIN_DISP1_DAT1, IOMUX_CONFIG_ALT0, + (PAD_CTL_HYS_NONE | PAD_CTL_DRV_LOW | PAD_CTL_SRE_FAST), + }, + { /* DISP1 DAT2 */ + MX51_PIN_DISP1_DAT2, IOMUX_CONFIG_ALT0, + (PAD_CTL_HYS_NONE | PAD_CTL_DRV_LOW | PAD_CTL_SRE_FAST), + }, + { /* DISP1 DAT3 */ + MX51_PIN_DISP1_DAT3, IOMUX_CONFIG_ALT0, + (PAD_CTL_HYS_NONE | PAD_CTL_DRV_LOW | PAD_CTL_SRE_FAST), + }, + { /* DISP1 DAT4 */ + MX51_PIN_DISP1_DAT4, IOMUX_CONFIG_ALT0, + (PAD_CTL_HYS_NONE | PAD_CTL_DRV_LOW | PAD_CTL_SRE_FAST), + }, + { /* DISP1 DAT5 */ + MX51_PIN_DISP1_DAT5, IOMUX_CONFIG_ALT0, + (PAD_CTL_HYS_NONE | PAD_CTL_DRV_LOW | PAD_CTL_SRE_FAST), + }, + { /* DISP1 DAT6 */ + MX51_PIN_DISP1_DAT6, IOMUX_CONFIG_ALT0, + (PAD_CTL_HYS_NONE | PAD_CTL_DRV_LOW | PAD_CTL_SRE_FAST), + }, + { /* DISP1 DAT7 */ + MX51_PIN_DISP1_DAT7, IOMUX_CONFIG_ALT0, + (PAD_CTL_HYS_NONE | PAD_CTL_DRV_LOW | PAD_CTL_SRE_FAST), + }, + { /* DISP1 DAT8 */ + MX51_PIN_DISP1_DAT8, IOMUX_CONFIG_ALT0, + (PAD_CTL_HYS_NONE | PAD_CTL_DRV_LOW | PAD_CTL_SRE_FAST), + }, + { /* DISP1 DAT9 */ + MX51_PIN_DISP1_DAT9, IOMUX_CONFIG_ALT0, + (PAD_CTL_HYS_NONE | PAD_CTL_DRV_LOW | PAD_CTL_SRE_FAST), + }, + { /* DISP1 DAT10 */ + MX51_PIN_DISP1_DAT10, IOMUX_CONFIG_ALT0, + (PAD_CTL_HYS_NONE | PAD_CTL_DRV_LOW | PAD_CTL_SRE_FAST), + }, + { /* DISP1 DAT11 */ + MX51_PIN_DISP1_DAT11, IOMUX_CONFIG_ALT0, + (PAD_CTL_HYS_NONE | PAD_CTL_DRV_LOW | PAD_CTL_SRE_FAST), + }, + { /* DISP1 DAT12 */ + MX51_PIN_DISP1_DAT12, IOMUX_CONFIG_ALT0, + (PAD_CTL_HYS_NONE | PAD_CTL_DRV_LOW | PAD_CTL_SRE_FAST), + }, + { /* DISP1 DAT13 */ + MX51_PIN_DISP1_DAT13, IOMUX_CONFIG_ALT0, + (PAD_CTL_HYS_NONE | PAD_CTL_DRV_LOW | PAD_CTL_SRE_FAST), + }, + { /* DISP1 DAT14 */ + MX51_PIN_DISP1_DAT14, IOMUX_CONFIG_ALT0, + (PAD_CTL_HYS_NONE | PAD_CTL_DRV_LOW | PAD_CTL_SRE_FAST), + }, + { /* DISP1 DAT15 */ + MX51_PIN_DISP1_DAT15, IOMUX_CONFIG_ALT0, + (PAD_CTL_HYS_NONE | PAD_CTL_DRV_LOW | PAD_CTL_SRE_FAST), + }, + { /* DISP1 DAT16 */ + MX51_PIN_DISP1_DAT16, IOMUX_CONFIG_ALT0, + (PAD_CTL_HYS_NONE | PAD_CTL_DRV_LOW | PAD_CTL_SRE_FAST), + }, + { /* DISP1 DAT17 */ + MX51_PIN_DISP1_DAT17, IOMUX_CONFIG_ALT0, + (PAD_CTL_HYS_NONE | PAD_CTL_DRV_LOW | PAD_CTL_SRE_FAST), + }, + { /* DISP1 DAT18 */ + MX51_PIN_DISP1_DAT18, IOMUX_CONFIG_ALT0, + (PAD_CTL_HYS_NONE | PAD_CTL_DRV_LOW | PAD_CTL_SRE_FAST), + }, + { /* DISP1 DAT19 */ + MX51_PIN_DISP1_DAT19, IOMUX_CONFIG_ALT0, + (PAD_CTL_HYS_NONE | PAD_CTL_DRV_LOW | PAD_CTL_SRE_FAST), + }, + { /* DISP1 DAT20 */ + MX51_PIN_DISP1_DAT20, IOMUX_CONFIG_ALT0, + (PAD_CTL_HYS_NONE | PAD_CTL_DRV_LOW | PAD_CTL_SRE_FAST), + }, + { /* DISP1 DAT21 */ + MX51_PIN_DISP1_DAT21, IOMUX_CONFIG_ALT0, + (PAD_CTL_HYS_NONE | PAD_CTL_DRV_LOW | PAD_CTL_SRE_FAST), + }, + { /* DISP1 DAT22 */ + MX51_PIN_DISP1_DAT22, IOMUX_CONFIG_ALT0, + (PAD_CTL_HYS_NONE | PAD_CTL_DRV_LOW | PAD_CTL_SRE_FAST), + }, + { /* DISP1 DAT23 */ + MX51_PIN_DISP1_DAT23, IOMUX_CONFIG_ALT0, + (PAD_CTL_HYS_NONE | PAD_CTL_DRV_LOW | PAD_CTL_SRE_FAST), + }, +}; +#endif + +#if defined(CONFIG_I2C_MXC) || defined(CONFIG_I2C_MXC_MODULE) + +static struct mxc_iomux_pin_cfg __initdata ccwmx51_iomux_mma7455l_pins[] = { + +// AG - Could use gpio_i2c_active() which is called from mxci2c_probe() and mxci2c_resume() + +#ifdef CONFIG_I2C_MXC_SELECT1 + { + MX51_PIN_SD2_CMD, IOMUX_CONFIG_ALT1 | IOMUX_CONFIG_SION, + (PAD_CTL_SRE_FAST | PAD_CTL_ODE_OPENDRAIN_ENABLE | PAD_CTL_HYS_ENABLE | + PAD_CTL_100K_PU | PAD_CTL_DRV_HIGH), + MUX_IN_I2C1_IPP_SDA_IN_SELECT_INPUT, INPUT_CTL_PATH2, + }, + { + MX51_PIN_SD2_CLK, IOMUX_CONFIG_ALT1 | IOMUX_CONFIG_SION, + (PAD_CTL_SRE_FAST | PAD_CTL_ODE_OPENDRAIN_ENABLE | PAD_CTL_HYS_ENABLE | + PAD_CTL_100K_PU | PAD_CTL_DRV_HIGH), + MUX_IN_I2C1_IPP_SCL_IN_SELECT_INPUT, INPUT_CTL_PATH2, + }, +#endif + +#ifdef CONFIG_I2C_MXC_SELECT2 + { + MX51_PIN_GPIO1_2, IOMUX_CONFIG_ALT2 | IOMUX_CONFIG_SION, + (PAD_CTL_SRE_FAST | PAD_CTL_ODE_OPENDRAIN_ENABLE | PAD_CTL_DRV_HIGH | + PAD_CTL_100K_PU | PAD_CTL_HYS_ENABLE), + MUX_IN_I2C2_IPP_SCL_IN_SELECT_INPUT, INPUT_CTL_PATH3, + }, + { + MX51_PIN_GPIO1_3, IOMUX_CONFIG_ALT2 | IOMUX_CONFIG_SION, + (PAD_CTL_SRE_FAST | PAD_CTL_ODE_OPENDRAIN_ENABLE | PAD_CTL_DRV_HIGH | + PAD_CTL_100K_PU | PAD_CTL_HYS_ENABLE), + MUX_IN_I2C2_IPP_SDA_IN_SELECT_INPUT, INPUT_CTL_PATH3, + }, +#endif + +#ifdef CONFIG_I2C_MXC_SELECT3 + { + MX51_PIN_I2C1_CLK, IOMUX_CONFIG_ALT0 | IOMUX_CONFIG_SION, + ( PAD_CTL_ODE_OPENDRAIN_NONE | PAD_CTL_HYS_ENABLE | + PAD_CTL_DRV_HIGH | PAD_CTL_100K_PU | PAD_CTL_SRE_SLOW), + }, + { + MX51_PIN_I2C1_DAT, IOMUX_CONFIG_ALT0 | IOMUX_CONFIG_SION, + ( PAD_CTL_ODE_OPENDRAIN_NONE | PAD_CTL_HYS_ENABLE | + PAD_CTL_DRV_HIGH | PAD_CTL_100K_PU | PAD_CTL_SRE_SLOW), + } +#endif +}; + +#endif //defined(CONFIG_I2C_MXC) || defined(CONFIG_I2C_MXC_MODULE) + +static struct mxc_iomux_pin_cfg __initdata ccwmx51_iomux_devices_pins[] = { + { /* PMIC interrupt line */ + MX51_PIN_GPIO1_5, IOMUX_CONFIG_GPIO | IOMUX_CONFIG_SION, + (PAD_CTL_SRE_SLOW | PAD_CTL_DRV_MEDIUM | PAD_CTL_100K_PU | + PAD_CTL_HYS_ENABLE | PAD_CTL_DRV_VOT_HIGH), + }, +// { /* MMA7455L interrupt line */ +// MX51_PIN_GPIO1_6, IOMUX_CONFIG_GPIO, +// }, +// { +// MX51_PIN_GPIO1_7, IOMUX_CONFIG_ALT2, +// (PAD_CTL_DRV_HIGH | PAD_CTL_PUE_PULL | +// PAD_CTL_100K_PU | PAD_CTL_PKE_ENABLE | +// PAD_CTL_SRE_FAST), +// }, +}; + + +void __init ccwmx51_io_init(void) +{ + int i; + +#if defined(CONFIG_SMSC9118) + for (i = 0; i < ARRAY_SIZE(ccwmx51_iomux_ext_eth_pins); i++) { + mxc_request_iomux(ccwmx51_iomux_ext_eth_pins[i].pin, + ccwmx51_iomux_ext_eth_pins[i].mux_mode); + if (ccwmx51_iomux_ext_eth_pins[i].pad_cfg) + mxc_iomux_set_pad(ccwmx51_iomux_ext_eth_pins[i].pin, + ccwmx51_iomux_ext_eth_pins[i].pad_cfg); + if (ccwmx51_iomux_ext_eth_pins[i].in_select) + mxc_iomux_set_input(ccwmx51_iomux_ext_eth_pins[i].in_select, + ccwmx51_iomux_ext_eth_pins[i].in_mode); + } +#endif + +#if defined(CONFIG_MMC_IMX_ESDHCI) || defined(CONFIG_MMC_IMX_ESDHCI_MODULE) + for (i = 0; i < ARRAY_SIZE(ccwmx51_iomux_mmc_pins); i++) { + mxc_request_iomux(ccwmx51_iomux_mmc_pins[i].pin, + ccwmx51_iomux_mmc_pins[i].mux_mode); + if (ccwmx51_iomux_mmc_pins[i].pad_cfg) + mxc_iomux_set_pad(ccwmx51_iomux_mmc_pins[i].pin, + ccwmx51_iomux_mmc_pins[i].pad_cfg); + if (ccwmx51_iomux_mmc_pins[i].in_select) + mxc_iomux_set_input(ccwmx51_iomux_mmc_pins[i].in_select, + ccwmx51_iomux_mmc_pins[i].in_mode); + } +#endif + +#if defined(CONFIG_USB_EHCI_ARC_H1) || defined(CONFIG_USB_EHCI_ARC_H1_MODULE) + for (i = 0; i < ARRAY_SIZE(ccwmx51_iomux_usbh1_pins); i++) { + mxc_request_iomux(ccwmx51_iomux_usbh1_pins[i].pin, + ccwmx51_iomux_usbh1_pins[i].mux_mode); + if (ccwmx51_iomux_usbh1_pins[i].pad_cfg) + mxc_iomux_set_pad(ccwmx51_iomux_usbh1_pins[i].pin, + ccwmx51_iomux_usbh1_pins[i].pad_cfg); + if (ccwmx51_iomux_usbh1_pins[i].in_select) + mxc_iomux_set_input(ccwmx51_iomux_usbh1_pins[i].in_select, + ccwmx51_iomux_usbh1_pins[i].in_mode); + } +#endif + +#if defined(CONFIG_FB_MXC_SYNC_PANEL) || defined(CONFIG_FB_MXC_SYNC_PANEL_MODULE) + for (i = 0; i < ARRAY_SIZE(ccwmx51_iomux_video1_pins); i++) { + mxc_request_iomux(ccwmx51_iomux_video1_pins[i].pin, + ccwmx51_iomux_video1_pins[i].mux_mode); + if (ccwmx51_iomux_video1_pins[i].pad_cfg) + mxc_iomux_set_pad(ccwmx51_iomux_video1_pins[i].pin, + ccwmx51_iomux_video1_pins[i].pad_cfg); + if (ccwmx51_iomux_video1_pins[i].in_select) + mxc_iomux_set_input(ccwmx51_iomux_video1_pins[i].in_select, + ccwmx51_iomux_video1_pins[i].in_mode); + } +#endif + +#if defined(CONFIG_I2C_MXC) || defined(CONFIG_I2C_MXC_MODULE) + for (i = 0; i < ARRAY_SIZE(ccwmx51_iomux_mma7455l_pins); i++) { + mxc_request_iomux(ccwmx51_iomux_mma7455l_pins[i].pin, + ccwmx51_iomux_mma7455l_pins[i].mux_mode); + if (ccwmx51_iomux_mma7455l_pins[i].pad_cfg) + mxc_iomux_set_pad(ccwmx51_iomux_mma7455l_pins[i].pin, + ccwmx51_iomux_mma7455l_pins[i].pad_cfg); + if (ccwmx51_iomux_mma7455l_pins[i].in_select) + mxc_iomux_set_input(ccwmx51_iomux_mma7455l_pins[i].in_select, + ccwmx51_iomux_mma7455l_pins[i].in_mode); + } +#endif + + for (i = 0; i < ARRAY_SIZE(ccwmx51_iomux_devices_pins); i++) { + mxc_request_iomux(ccwmx51_iomux_devices_pins[i].pin, + ccwmx51_iomux_devices_pins[i].mux_mode); + if (ccwmx51_iomux_devices_pins[i].pad_cfg) + mxc_iomux_set_pad(ccwmx51_iomux_devices_pins[i].pin, + ccwmx51_iomux_devices_pins[i].pad_cfg); + if (ccwmx51_iomux_devices_pins[i].in_select) + mxc_iomux_set_input(ccwmx51_iomux_devices_pins[i].in_select, + ccwmx51_iomux_devices_pins[i].in_mode); + } + + /* PMIC interrupt line */ + gpio_request(IOMUX_TO_GPIO(MX51_PIN_GPIO1_5), "gpio1_5"); + gpio_direction_input(IOMUX_TO_GPIO(MX51_PIN_GPIO1_5)); + +#if defined(CONFIG_USB_EHCI_ARC_H1) || defined(CONFIG_USB_EHCI_ARC_H1_MODULE) + /* USB PHY/HUB reset*/ + gpio_request(IOMUX_TO_GPIO(MX51_PIN_DISPB2_SER_RS), "gpio3_8"); + gpio_direction_output(IOMUX_TO_GPIO(MX51_PIN_DISPB2_SER_RS), 0); + msleep(1); + gpio_set_value(IOMUX_TO_GPIO(MX51_PIN_DISPB2_SER_RS), 1); +#endif +} + + +#if defined(CONFIG_SERIAL_MXC) || defined(CONFIG_SERIAL_MXC_MODULE) +#define SERIAL_PORT_PAD (PAD_CTL_HYS_ENABLE | PAD_CTL_PKE_ENABLE | \ + PAD_CTL_PUE_PULL | PAD_CTL_DRV_HIGH | \ + PAD_CTL_SRE_FAST) + +void gpio_uart_active(int port, int no_irda) +{ + /* Configure the IOMUX control registers for the UART signals */ + switch (port) { + + case 0: /* UART 1 IOMUX Configs */ +#ifdef CONFIG_UART1_ENABLED + mxc_request_iomux(MX51_PIN_UART1_RXD, IOMUX_CONFIG_ALT0); + mxc_request_iomux(MX51_PIN_UART1_TXD, IOMUX_CONFIG_ALT0); + mxc_iomux_set_pad(MX51_PIN_UART1_RXD, SERIAL_PORT_PAD); + mxc_iomux_set_pad(MX51_PIN_UART1_TXD, SERIAL_PORT_PAD); + mxc_iomux_set_input(MUX_IN_UART1_IPP_UART_RXD_MUX_SELECT_INPUT, INPUT_CTL_PATH0); + + /* TODO enable CTS/RTS if selected */ +#endif + break; + + case 1: /* UART 2 IOMUX Configs */ +#ifdef CONFIG_UART2_ENABLED + mxc_request_iomux(MX51_PIN_UART2_RXD, IOMUX_CONFIG_ALT0); + mxc_request_iomux(MX51_PIN_UART2_TXD, IOMUX_CONFIG_ALT0); + mxc_iomux_set_pad(MX51_PIN_UART2_RXD, SERIAL_PORT_PAD); + mxc_iomux_set_pad(MX51_PIN_UART2_TXD, SERIAL_PORT_PAD); + mxc_iomux_set_input(MUX_IN_UART2_IPP_UART_RXD_MUX_SELECT_INPUT, INPUT_CTL_PATH2); + + /* TODO enable CTS/RTS if selected */ +#endif + break; + case 2: /* UART 3 IOMUX Configs */ +#ifdef CONFIG_UART3_ENABLED + mxc_request_iomux(MX51_PIN_UART3_RXD, IOMUX_CONFIG_ALT1); + mxc_request_iomux(MX51_PIN_UART3_TXD, IOMUX_CONFIG_ALT1); + mxc_iomux_set_pad(MX51_PIN_UART3_RXD, SERIAL_PORT_PAD); + mxc_iomux_set_pad(MX51_PIN_UART3_TXD, SERIAL_PORT_PAD); + mxc_iomux_set_input(MUX_IN_UART3_IPP_UART_RXD_MUX_SELECT_INPUT, INPUT_CTL_PATH4); + + /* TODO enable CTS/RTS if selected */ +#endif + break; + default: + break; + } + +} + +#else +void gpio_uart_active(int port, int no_irda) {} +#endif +void gpio_uart_inactive(int port, int no_irda) {} +EXPORT_SYMBOL(gpio_uart_active); +EXPORT_SYMBOL(gpio_uart_inactive); diff --git a/arch/arm/mach-mx51/mx51_ccwmx51js_pmic_mc13892.c b/arch/arm/mach-mx51/mx51_ccwmx51js_pmic_mc13892.c new file mode 100644 index 000000000000..f650724871ea --- /dev/null +++ b/arch/arm/mach-mx51/mx51_ccwmx51js_pmic_mc13892.c @@ -0,0 +1,361 @@ + /* + * Copyright 2009 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright 2009 Digi International, 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/init.h> +#include <linux/platform_device.h> +#include <linux/spi/spi.h> +#include <linux/err.h> +#include <linux/pmic_external.h> +#include <linux/regulator/machine.h> +#include <linux/mfd/mc13892/core.h> +#include "iomux.h" + +/* + * Convenience conversion. + * Here atm, maybe there is somewhere better for this. + */ +#define mV_to_uV(mV) (mV * 1000) +#define uV_to_mV(uV) (uV / 1000) +#define V_to_uV(V) (mV_to_uV(V * 1000)) +#define uV_to_V(uV) (uV_to_mV(uV) / 1000) + +/* Coin cell charger enable */ +#define CIONCHEN_LSH 23 +#define CIONCHEN_WID 1 +/* Coin cell charger voltage setting */ +#define VCOIN_LSH 20 +#define VCOIN_WID 3 + +/* Coin Charger voltage */ +#define VCOIN_2_5V 0x0 +#define VCOIN_2_7V 0x1 +#define VCOIN_2_8V 0x2 +#define VCOIN_2_9V 0x3 +#define VCOIN_3_0V 0x4 +#define VCOIN_3_1V 0x5 +#define VCOIN_3_2V 0x6 +#define VCOIN_3_3V 0x7 + +/* Keeps VSRTC and CLK32KMCU on for all states */ +#define DRM_LSH 4 +#define DRM_WID 1 + +/* regulator standby mask */ +#define GEN1_STBY_MASK (1 << 1) +#define IOHI_STBY_MASK (1 << 4) +#define DIG_STBY_MASK (1 << 10) +#define GEN2_STBY_MASK (1 << 13) +#define PLL_STBY_MASK (1 << 16) +#define USB2_STBY_MASK (1 << 19) + +#define GEN3_STBY_MASK (1 << 1) +#define CAM_STBY_MASK (1 << 7) +#define VIDEO_STBY_MASK (1 << 13) +#define AUDIO_STBY_MASK (1 << 16) +#define SD_STBY_MASK (1 << 19) + +/* 0x92412 */ +#define REG_MODE_0_ALL_MASK (GEN1_STBY_MASK |\ + DIG_STBY_MASK | GEN2_STBY_MASK |\ + PLL_STBY_MASK | USB2_STBY_MASK) +/* 0x92082 */ +#define REG_MODE_1_ALL_MASK (GEN3_STBY_MASK | CAM_STBY_MASK |\ + VIDEO_STBY_MASK | AUDIO_STBY_MASK |\ + SD_STBY_MASK) + +/* CPU */ +static struct regulator_consumer_supply sw1_consumers[] = { + { + .supply = "cpu_vcc", + } +}; + +struct mc13892; + +static struct regulator_init_data sw1_init = { + .constraints = { + .name = "SW1", + .min_uV = mV_to_uV(600), + .max_uV = mV_to_uV(1375), + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE, + .valid_modes_mask = 0, + .always_on = 1, + .boot_on = 1, + .initial_state = PM_SUSPEND_MEM, + .state_mem = { + .uV = 850000, + .mode = REGULATOR_MODE_NORMAL, + .enabled = 1, + }, + }, + .num_consumer_supplies = ARRAY_SIZE(sw1_consumers), + .consumer_supplies = sw1_consumers, +}; + +static struct regulator_init_data sw2_init = { + .constraints = { + .name = "SW2", + .min_uV = mV_to_uV(900), + .max_uV = mV_to_uV(1850), + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE, + .always_on = 1, + .boot_on = 1, + .initial_state = PM_SUSPEND_MEM, + .state_mem = { + .uV = 950000, + .mode = REGULATOR_MODE_NORMAL, + .enabled = 1, + }, + } +}; + +static struct regulator_init_data sw3_init = { + .constraints = { + .name = "SW3", + .min_uV = mV_to_uV(1100), + .max_uV = mV_to_uV(1850), + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE, + .always_on = 1, + .boot_on = 1, + } +}; + +static struct regulator_init_data sw4_init = { + .constraints = { + .name = "SW4", + .min_uV = mV_to_uV(1100), + .max_uV = mV_to_uV(1850), + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE, + .always_on = 1, + .boot_on = 1, + } +}; + +static struct regulator_init_data viohi_init = { + .constraints = { + .name = "VIOHI", + .boot_on = 1, + } +}; + +static struct regulator_init_data vusb_init = { + .constraints = { + .name = "VUSB", + .boot_on = 1, + } +}; + +static struct regulator_init_data swbst_init = { + .constraints = { + .name = "SWBST", + } +}; + +static struct regulator_init_data vdig_init = { + .constraints = { + .name = "VDIG", + .min_uV = mV_to_uV(1050), + .max_uV = mV_to_uV(1800), + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE, + .boot_on = 1, + } +}; + +static struct regulator_init_data vpll_init = { + .constraints = { + .name = "VPLL", + .min_uV = mV_to_uV(1050), + .max_uV = mV_to_uV(1800), + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE, + .boot_on = 1, + } +}; + +static struct regulator_init_data vusb2_init = { + .constraints = { + .name = "VUSB2", + .min_uV = mV_to_uV(2400), + .max_uV = mV_to_uV(2775), + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE, + .boot_on = 1, + } +}; + +static struct regulator_init_data vvideo_init = { + .constraints = { + .name = "VVIDEO", + .min_uV = mV_to_uV(2775), + .max_uV = mV_to_uV(2775), + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE, + .always_on = 1, + .apply_uV =1, + } +}; + +static struct regulator_init_data vaudio_init = { + .constraints = { + .name = "VAUDIO", + .min_uV = mV_to_uV(2300), + .max_uV = mV_to_uV(3000), + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE, + } +}; + +static struct regulator_init_data vsd_init = { + .constraints = { + .name = "VSD", + .min_uV = mV_to_uV(1800), + .max_uV = mV_to_uV(3150), + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE, + } +}; + +static struct regulator_init_data vcam_init = { + .constraints = { + .name = "VCAM", + .min_uV = mV_to_uV(2500), + .max_uV = mV_to_uV(3000), + .valid_ops_mask = + REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_MODE, + .valid_modes_mask = REGULATOR_MODE_FAST | REGULATOR_MODE_NORMAL, + } +}; + +static struct regulator_init_data vgen1_init = { + .constraints = { + .name = "VGEN1", + .min_uV = mV_to_uV(1200), + .max_uV = mV_to_uV(3150), + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE, + } +}; + +static struct regulator_init_data vgen2_init = { + .constraints = { + .name = "VGEN2", + .min_uV = mV_to_uV(1200), + .max_uV = mV_to_uV(3150), + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE, + } +}; + +static struct regulator_init_data vgen3_init = { + .constraints = { + .name = "VGEN3", + .min_uV = mV_to_uV(1800), + .max_uV = mV_to_uV(2900), + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE, + } +}; + +static struct regulator_init_data gpo1_init = { + .constraints = { + .name = "GPO1", + } +}; + +static struct regulator_init_data gpo2_init = { + .constraints = { + .name = "GPO2", + } +}; + +static struct regulator_init_data gpo3_init = { + .constraints = { + .name = "GPO3", + } +}; + +static struct regulator_init_data gpo4_init = { + .constraints = { + .name = "GPO4", + } +}; + +static int mc13892_regulator_init(struct mc13892 *mc13892) +{ + unsigned int value, register_mask; + printk("Initializing regulators for Babbage.\n"); + if (mxc_cpu_is_rev(CHIP_REV_2_0) < 0) + sw2_init.constraints.state_mem.uV = 1100000; + else if (mxc_cpu_is_rev(CHIP_REV_2_0) == 1) { + sw2_init.constraints.state_mem.uV = 1250000; + sw1_init.constraints.state_mem.uV = 1000000; + } + + /* enable standby controll for all regulators */ + pmic_read_reg(REG_MODE_0, &value, 0xffffff); + value |= REG_MODE_0_ALL_MASK; + pmic_write_reg(REG_MODE_0, value, 0xffffff); + + pmic_read_reg(REG_MODE_1, &value, 0xffffff); + value |= REG_MODE_1_ALL_MASK; + pmic_write_reg(REG_MODE_1, value, 0xffffff); + + /* Enable coin cell charger */ + value = BITFVAL(CIONCHEN, 1) | BITFVAL(VCOIN, VCOIN_3_0V); + register_mask = BITFMASK(CIONCHEN) | BITFMASK(VCOIN); + pmic_write_reg(REG_POWER_CTL0, value, register_mask); + +#if defined(CONFIG_RTC_DRV_MXC_V2) || defined(CONFIG_RTC_DRV_MXC_V2_MODULE) + value = BITFVAL(DRM, 1); + register_mask = BITFMASK(DRM); + pmic_write_reg(REG_POWER_CTL0, value, register_mask); +#endif + + mc13892_register_regulator(mc13892, MC13892_SW1, &sw1_init); + mc13892_register_regulator(mc13892, MC13892_SW2, &sw2_init); + mc13892_register_regulator(mc13892, MC13892_SW3, &sw3_init); + mc13892_register_regulator(mc13892, MC13892_SW4, &sw4_init); + mc13892_register_regulator(mc13892, MC13892_SWBST, &swbst_init); + mc13892_register_regulator(mc13892, MC13892_VIOHI, &viohi_init); + mc13892_register_regulator(mc13892, MC13892_VPLL, &vpll_init); + mc13892_register_regulator(mc13892, MC13892_VDIG, &vdig_init); + mc13892_register_regulator(mc13892, MC13892_VSD, &vsd_init); + mc13892_register_regulator(mc13892, MC13892_VUSB2, &vusb2_init); + mc13892_register_regulator(mc13892, MC13892_VVIDEO, &vvideo_init); + mc13892_register_regulator(mc13892, MC13892_VAUDIO, &vaudio_init); + mc13892_register_regulator(mc13892, MC13892_VCAM, &vcam_init); + mc13892_register_regulator(mc13892, MC13892_VGEN1, &vgen1_init); + mc13892_register_regulator(mc13892, MC13892_VGEN2, &vgen2_init); + mc13892_register_regulator(mc13892, MC13892_VGEN3, &vgen3_init); + mc13892_register_regulator(mc13892, MC13892_VUSB, &vusb_init); + mc13892_register_regulator(mc13892, MC13892_GPO1, &gpo1_init); + mc13892_register_regulator(mc13892, MC13892_GPO2, &gpo2_init); + mc13892_register_regulator(mc13892, MC13892_GPO3, &gpo3_init); + mc13892_register_regulator(mc13892, MC13892_GPO4, &gpo4_init); + + return 0; +} + +static struct mc13892_platform_data mc13892_plat = { + .init = mc13892_regulator_init, +}; + +static struct spi_board_info __initdata mc13892_spi_device = { + .modalias = "pmic_spi", + .irq = IOMUX_TO_IRQ(MX51_PIN_GPIO1_5), + .max_speed_hz = 1000000, /* max spi SCK clock speed in HZ */ + .bus_num = 1, + .chip_select = 0, + .platform_data = &mc13892_plat, +}; + + +int __init ccwmx51_init_mc13892(void) +{ + return spi_register_board_info(&mc13892_spi_device, 1); +} + diff --git a/arch/arm/mach-mx51/mx51_pins.h b/arch/arm/mach-mx51/mx51_pins.h new file mode 100644 index 000000000000..c0905a025556 --- /dev/null +++ b/arch/arm/mach-mx51/mx51_pins.h @@ -0,0 +1,361 @@ +/* + * Copyright 2008-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_MX51_PINS_H__ +#define __ASM_ARCH_MXC_MX51_PINS_H__ + +/*! + * @file arch-mxc/mx51_pins.h + * + * @brief MX51 I/O Pin List + * + * @ingroup GPIO_MX51 + */ + +#ifndef __ASSEMBLY__ + +/*! + * @name IOMUX/PAD Bit field definitions + */ + +/*! @{ */ + +/*! + * In order to identify pins more effectively, each mux-controlled pin's + * enumerated value is constructed in the following way: + * + * ------------------------------------------------------------------- + * 31-29 | 28 - 24 | 23 - 21 | 20 - 10| 9 - 0 + * ------------------------------------------------------------------- + * IO_P | IO_I | GPIO_I | PAD_I | MUX_I + * ------------------------------------------------------------------- + * + * Bit 0 to 9 contains MUX_I used to identify the register + * offset (0-based. base is IOMUX_module_base) defined in the Section + * "sw_pad_ctl & sw_mux_ctl details" of the IC Spec. The + * similar field definitions are used for the pad control register. + * For example, the MX51_PIN_ETM_D0 is defined in the enumeration: + * ( (0x28 - MUX_I_START) << MUX_I)|( (0x250 - PAD_I_START) << PAD_I) + * It means the mux control register is at register offset 0x28. The pad control + * register offset is: 0x250 and also occupy the least significant bits + * within the register. + */ + +/*! + * Starting bit position within each entry of \b iomux_pins to represent the + * MUX control register offset + */ +#define MUX_I 0 +/*! + * Starting bit position within each entry of \b iomux_pins to represent the + * PAD control register offset + */ +#define PAD_I 10 +/*! + * Starting bit position within each entry of \b iomux_pins to represent which + * mux mode is for GPIO (0-based) + */ +#define GPIO_I 21 + +#define NON_GPIO_PORT 0x7 +#define PIN_TO_MUX_MASK ((1 << (PAD_I - MUX_I)) - 1) +#define PIN_TO_PAD_MASK ((1 << (GPIO_I - PAD_I)) - 1) +#define PIN_TO_ALT_GPIO_MASK ((1 << (MUX_IO_I - GPIO_I)) - 1) + +#define NON_MUX_I PIN_TO_MUX_MASK +#define MUX_I_START 0x001C +#define PAD_I_START 0x3F0 +#define INPUT_CTL_START 0x8C4 +#define INPUT_CTL_START_TO1 0x928 +#define MUX_I_END (PAD_I_START - 4) + +#define _MXC_BUILD_PIN(gp, gi, ga, mi, pi) \ + (((gp) << MUX_IO_P) | ((gi) << MUX_IO_I) | \ + ((mi) << MUX_I) | \ + ((pi - PAD_I_START) << PAD_I) | \ + ((ga) << GPIO_I)) + +#define _MXC_BUILD_GPIO_PIN(gp, gi, ga, mi, pi) \ + _MXC_BUILD_PIN(gp, gi, ga, mi, pi) + +#define _MXC_BUILD_NON_GPIO_PIN(mi, pi) \ + _MXC_BUILD_PIN(NON_GPIO_PORT, 0, 0, mi, pi) + +#define PIN_TO_IOMUX_MUX(pin) ((pin >> MUX_I) & PIN_TO_MUX_MASK) +#define PIN_TO_IOMUX_PAD(pin) ((pin >> PAD_I) & PIN_TO_PAD_MASK) +#define PIN_TO_ALT_GPIO(pin) ((pin >> GPIO_I) & PIN_TO_ALT_GPIO_MASK) +#define PIN_TO_IOMUX_INDEX(pin) (PIN_TO_IOMUX_MUX(pin) >> 2) + +/*! @} End IOMUX/PAD Bit field definitions */ + +/*! + * This enumeration is constructed based on the Section + * "sw_pad_ctl & sw_mux_ctl details" of the MX51 IC Spec. Each enumerated + * value is constructed based on the rules described above. + */ +enum iomux_pins { + MX51_PIN_EIM_DA0 = _MXC_BUILD_NON_GPIO_PIN(0x1C, 0x7A8), + MX51_PIN_EIM_DA1 = _MXC_BUILD_NON_GPIO_PIN(0x20, 0x7A8), + MX51_PIN_EIM_DA2 = _MXC_BUILD_NON_GPIO_PIN(0x24, 0x7A8), + MX51_PIN_EIM_DA3 = _MXC_BUILD_NON_GPIO_PIN(0x28, 0x7A8), + MX51_PIN_EIM_DA4 = _MXC_BUILD_NON_GPIO_PIN(0x2C, 0x7AC), + MX51_PIN_EIM_DA5 = _MXC_BUILD_NON_GPIO_PIN(0x30, 0x7AC), + MX51_PIN_EIM_DA6 = _MXC_BUILD_NON_GPIO_PIN(0x34, 0x7AC), + MX51_PIN_EIM_DA7 = _MXC_BUILD_NON_GPIO_PIN(0x38, 0x7AC), + MX51_PIN_EIM_DA8 = _MXC_BUILD_NON_GPIO_PIN(0x3C, 0x7B0), + MX51_PIN_EIM_DA9 = _MXC_BUILD_NON_GPIO_PIN(0x40, 0x7B0), + MX51_PIN_EIM_DA10 = _MXC_BUILD_NON_GPIO_PIN(0x44, 0x7B0), + MX51_PIN_EIM_DA11 = _MXC_BUILD_NON_GPIO_PIN(0x48, 0x7B0), + MX51_PIN_EIM_DA12 = _MXC_BUILD_NON_GPIO_PIN(0x4C, 0x7BC), + MX51_PIN_EIM_DA13 = _MXC_BUILD_NON_GPIO_PIN(0x50, 0x7BC), + MX51_PIN_EIM_DA14 = _MXC_BUILD_NON_GPIO_PIN(0x54, 0x7BC), + MX51_PIN_EIM_DA15 = _MXC_BUILD_NON_GPIO_PIN(0x58, 0x7BC), + MX51_PIN_EIM_D16 = _MXC_BUILD_GPIO_PIN(1, 0, 1, 0x5C, 0x3F0), + MX51_PIN_EIM_D17 = _MXC_BUILD_GPIO_PIN(1, 1, 1, 0x60, 0x3F4), + MX51_PIN_EIM_D18 = _MXC_BUILD_GPIO_PIN(1, 2, 1, 0x64, 0x3F8), + MX51_PIN_EIM_D19 = _MXC_BUILD_GPIO_PIN(1, 3, 1, 0x68, 0x3FC), + MX51_PIN_EIM_D20 = _MXC_BUILD_GPIO_PIN(1, 4, 1, 0x6C, 0x400), + MX51_PIN_EIM_D21 = _MXC_BUILD_GPIO_PIN(1, 5, 1, 0x70, 0x404), + MX51_PIN_EIM_D22 = _MXC_BUILD_GPIO_PIN(1, 6, 1, 0x74, 0x408), + MX51_PIN_EIM_D23 = _MXC_BUILD_GPIO_PIN(1, 7, 1, 0x78, 0x40C), + MX51_PIN_EIM_D24 = _MXC_BUILD_GPIO_PIN(1, 8, 1, 0x7C, 0x410), + MX51_PIN_EIM_D25 = _MXC_BUILD_NON_GPIO_PIN(0x80, 0x414), + MX51_PIN_EIM_D26 = _MXC_BUILD_NON_GPIO_PIN(0x84, 0x418), + MX51_PIN_EIM_D27 = _MXC_BUILD_GPIO_PIN(1, 9, 1, 0x88, 0x41C), + MX51_PIN_EIM_D28 = _MXC_BUILD_NON_GPIO_PIN(0x8C, 0x420), + MX51_PIN_EIM_D29 = _MXC_BUILD_NON_GPIO_PIN(0x90, 0x424), + MX51_PIN_EIM_D30 = _MXC_BUILD_NON_GPIO_PIN(0x94, 0x428), + MX51_PIN_EIM_D31 = _MXC_BUILD_NON_GPIO_PIN(0x98, 0x42C), + MX51_PIN_EIM_A16 = _MXC_BUILD_GPIO_PIN(1, 10, 1, 0x9C, 0x430), + MX51_PIN_EIM_A17 = _MXC_BUILD_GPIO_PIN(1, 11, 1, 0xA0, 0x434), + MX51_PIN_EIM_A18 = _MXC_BUILD_GPIO_PIN(1, 12, 1, 0xA4, 0x438), + MX51_PIN_EIM_A19 = _MXC_BUILD_GPIO_PIN(1, 13, 1, 0xA8, 0x43C), + MX51_PIN_EIM_A20 = _MXC_BUILD_GPIO_PIN(1, 14, 1, 0xAC, 0x440), + MX51_PIN_EIM_A21 = _MXC_BUILD_GPIO_PIN(1, 15, 1, 0xB0, 0x444), + MX51_PIN_EIM_A22 = _MXC_BUILD_GPIO_PIN(1, 16, 1, 0xB4, 0x448), + MX51_PIN_EIM_A23 = _MXC_BUILD_GPIO_PIN(1, 17, 1, 0xB8, 0x44C), + MX51_PIN_EIM_A24 = _MXC_BUILD_GPIO_PIN(1, 18, 1, 0xBC, 0x450), + MX51_PIN_EIM_A25 = _MXC_BUILD_GPIO_PIN(1, 19, 1, 0xC0, 0x454), + MX51_PIN_EIM_A26 = _MXC_BUILD_GPIO_PIN(1, 20, 1, 0xC4, 0x458), + MX51_PIN_EIM_A27 = _MXC_BUILD_GPIO_PIN(1, 21, 1, 0xC8, 0x45C), + MX51_PIN_EIM_EB0 = _MXC_BUILD_NON_GPIO_PIN(0xCC, 0x460), + MX51_PIN_EIM_EB1 = _MXC_BUILD_NON_GPIO_PIN(0xD0, 0x464), + MX51_PIN_EIM_EB2 = _MXC_BUILD_GPIO_PIN(1, 22, 1, 0xD4, 0x468), + MX51_PIN_EIM_EB3 = _MXC_BUILD_GPIO_PIN(1, 23, 1, 0xD8, 0x46C), + MX51_PIN_EIM_OE = _MXC_BUILD_GPIO_PIN(1, 24, 1, 0xDC, 0x470), + MX51_PIN_EIM_CS0 = _MXC_BUILD_GPIO_PIN(1, 25, 1, 0xE0, 0x474), + MX51_PIN_EIM_CS1 = _MXC_BUILD_GPIO_PIN(1, 26, 1, 0xE4, 0x478), + MX51_PIN_EIM_CS2 = _MXC_BUILD_GPIO_PIN(1, 27, 1, 0xE8, 0x47C), + MX51_PIN_EIM_CS3 = _MXC_BUILD_GPIO_PIN(1, 28, 1, 0xEC, 0x480), + MX51_PIN_EIM_CS4 = _MXC_BUILD_GPIO_PIN(1, 29, 1, 0xF0, 0x484), + MX51_PIN_EIM_CS5 = _MXC_BUILD_GPIO_PIN(1, 30, 1, 0xF4, 0x488), + MX51_PIN_EIM_DTACK = _MXC_BUILD_GPIO_PIN(1, 31, 1, 0xF8, 0x48C), + MX51_PIN_EIM_LBA = _MXC_BUILD_GPIO_PIN(2, 1, 1, 0xFC, 0x494), + MX51_PIN_EIM_CRE = _MXC_BUILD_GPIO_PIN(2, 2, 1, 0x100, 0x4A0), + MX51_PIN_DRAM_CS1 = _MXC_BUILD_NON_GPIO_PIN(0x104, 0x4D0), + MX51_PIN_NANDF_WE_B = _MXC_BUILD_GPIO_PIN(2, 3, 3, 0x108, 0x4E4), + MX51_PIN_NANDF_RE_B = _MXC_BUILD_GPIO_PIN(2, 4, 3, 0x10C, 0x4E8), + MX51_PIN_NANDF_ALE = _MXC_BUILD_GPIO_PIN(2, 5, 3, 0x110, 0x4EC), + MX51_PIN_NANDF_CLE = _MXC_BUILD_GPIO_PIN(2, 6, 3, 0x114, 0x4F0), + MX51_PIN_NANDF_WP_B = _MXC_BUILD_GPIO_PIN(2, 7, 3, 0x118, 0x4F4), + MX51_PIN_NANDF_RB0 = _MXC_BUILD_GPIO_PIN(2, 8, 3, 0x11C, 0x4F8), + MX51_PIN_NANDF_RB1 = _MXC_BUILD_GPIO_PIN(2, 9, 3, 0x120, 0x4FC), + MX51_PIN_NANDF_RB2 = _MXC_BUILD_GPIO_PIN(2, 10, 3, 0x124, 0x500), + MX51_PIN_NANDF_RB3 = _MXC_BUILD_GPIO_PIN(2, 11, 3, 0x128, 0x504), + MX51_PIN_GPIO_NAND = _MXC_BUILD_GPIO_PIN(2, 12, 3, 0x12C, 0x514), + MX51_PIN_NANDF_RB4 = MX51_PIN_GPIO_NAND, + MX51_PIN_NANDF_RB5 = _MXC_BUILD_GPIO_PIN(2, 13, 3, 0x130, 0x5D8), + MX51_PIN_NANDF_RB6 = _MXC_BUILD_GPIO_PIN(2, 14, 3, 0x134, 0x5DC), + MX51_PIN_NANDF_RB7 = _MXC_BUILD_GPIO_PIN(2, 15, 3, 0x138, 0x5E0), + MX51_PIN_NANDF_CS0 = _MXC_BUILD_GPIO_PIN(2, 16, 3, 0x130, 0x518), + MX51_PIN_NANDF_CS1 = _MXC_BUILD_GPIO_PIN(2, 17, 3, 0x134, 0x51C), + MX51_PIN_NANDF_CS2 = _MXC_BUILD_GPIO_PIN(2, 18, 3, 0x138, 0x520), + MX51_PIN_NANDF_CS3 = _MXC_BUILD_GPIO_PIN(2, 19, 3, 0x13C, 0x524), + MX51_PIN_NANDF_CS4 = _MXC_BUILD_GPIO_PIN(2, 20, 3, 0x140, 0x528), + MX51_PIN_NANDF_CS5 = _MXC_BUILD_GPIO_PIN(2, 21, 3, 0x144, 0x52C), + MX51_PIN_NANDF_CS6 = _MXC_BUILD_GPIO_PIN(2, 22, 3, 0x148, 0x530), + MX51_PIN_NANDF_CS7 = _MXC_BUILD_GPIO_PIN(2, 23, 3, 0x14C, 0x534), + MX51_PIN_NANDF_RDY_INT = _MXC_BUILD_GPIO_PIN(2, 24, 3, 0x150, 0x538), + MX51_PIN_NANDF_D15 = _MXC_BUILD_GPIO_PIN(2, 25, 3, 0x154, 0x53C), + MX51_PIN_NANDF_D14 = _MXC_BUILD_GPIO_PIN(2, 26, 3, 0x158, 0x540), + MX51_PIN_NANDF_D13 = _MXC_BUILD_GPIO_PIN(2, 27, 3, 0x15C, 0x544), + MX51_PIN_NANDF_D12 = _MXC_BUILD_GPIO_PIN(2, 28, 3, 0x160, 0x548), + MX51_PIN_NANDF_D11 = _MXC_BUILD_GPIO_PIN(2, 29, 3, 0x164, 0x54C), + MX51_PIN_NANDF_D10 = _MXC_BUILD_GPIO_PIN(2, 30, 3, 0x168, 0x550), + MX51_PIN_NANDF_D9 = _MXC_BUILD_GPIO_PIN(2, 31, 3, 0x16C, 0x554), + MX51_PIN_NANDF_D8 = _MXC_BUILD_GPIO_PIN(3, 0, 3, 0x170, 0x558), + MX51_PIN_NANDF_D7 = _MXC_BUILD_GPIO_PIN(3, 1, 3, 0x174, 0x55C), + MX51_PIN_NANDF_D6 = _MXC_BUILD_GPIO_PIN(3, 2, 3, 0x178, 0x560), + MX51_PIN_NANDF_D5 = _MXC_BUILD_GPIO_PIN(3, 3, 3, 0x17C, 0x564), + MX51_PIN_NANDF_D4 = _MXC_BUILD_GPIO_PIN(3, 4, 3, 0x180, 0x568), + MX51_PIN_NANDF_D3 = _MXC_BUILD_GPIO_PIN(3, 5, 3, 0x184, 0x56C), + MX51_PIN_NANDF_D2 = _MXC_BUILD_GPIO_PIN(3, 6, 3, 0x188, 0x570), + MX51_PIN_NANDF_D1 = _MXC_BUILD_GPIO_PIN(3, 7, 3, 0x18C, 0x574), + MX51_PIN_NANDF_D0 = _MXC_BUILD_GPIO_PIN(3, 8, 3, 0x190, 0x578), + MX51_PIN_CSI1_D8 = _MXC_BUILD_GPIO_PIN(2, 12, 3, 0x194, 0x57C), + MX51_PIN_CSI1_D9 = _MXC_BUILD_GPIO_PIN(2, 13, 3, 0x198, 0x580), + MX51_PIN_CSI1_D10 = _MXC_BUILD_NON_GPIO_PIN(0x19C, 0x584), + MX51_PIN_CSI1_D11 = _MXC_BUILD_NON_GPIO_PIN(0x1A0, 0x588), + MX51_PIN_CSI1_D12 = _MXC_BUILD_NON_GPIO_PIN(0x1A4, 0x58C), + MX51_PIN_CSI1_D13 = _MXC_BUILD_NON_GPIO_PIN(0x1A8, 0x590), + MX51_PIN_CSI1_D14 = _MXC_BUILD_NON_GPIO_PIN(0x1AC, 0x594), + MX51_PIN_CSI1_D15 = _MXC_BUILD_NON_GPIO_PIN(0x1B0, 0x598), + MX51_PIN_CSI1_D16 = _MXC_BUILD_NON_GPIO_PIN(0x1B4, 0x59C), + MX51_PIN_CSI1_D17 = _MXC_BUILD_NON_GPIO_PIN(0x1B8, 0x5A0), + MX51_PIN_CSI1_D18 = _MXC_BUILD_NON_GPIO_PIN(0x1BC, 0x5A4), + MX51_PIN_CSI1_D19 = _MXC_BUILD_NON_GPIO_PIN(0x1C0, 0x5A8), + MX51_PIN_CSI1_VSYNC = _MXC_BUILD_GPIO_PIN(2, 14, 3, 0x1C4, 0x5AC), + MX51_PIN_CSI1_HSYNC = _MXC_BUILD_GPIO_PIN(2, 15, 3, 0x1C8, 0x5B0), + MX51_PIN_CSI1_PIXCLK = _MXC_BUILD_NON_GPIO_PIN(NON_MUX_I, 0x5B4), + MX51_PIN_CSI1_MCLK = _MXC_BUILD_NON_GPIO_PIN(NON_MUX_I, 0x5B8), + MX51_PIN_CSI1_PKE0 = _MXC_BUILD_NON_GPIO_PIN(NON_MUX_I, 0x860), + MX51_PIN_CSI2_D12 = _MXC_BUILD_GPIO_PIN(3, 9, 3, 0x1CC, 0x5BC), + MX51_PIN_CSI2_D13 = _MXC_BUILD_GPIO_PIN(3, 10, 3, 0x1D0, 0x5C0), + MX51_PIN_CSI2_D14 = _MXC_BUILD_GPIO_PIN(3, 11, 3, 0x1D4, 0x5C4), + MX51_PIN_CSI2_D15 = _MXC_BUILD_GPIO_PIN(3, 12, 3, 0x1D8, 0x5C8), + MX51_PIN_CSI2_D16 = _MXC_BUILD_GPIO_PIN(3, 11, 3, 0x1DC, 0x5CC), + MX51_PIN_CSI2_D17 = _MXC_BUILD_GPIO_PIN(3, 12, 3, 0x1E0, 0x5D0), + MX51_PIN_CSI2_D18 = _MXC_BUILD_GPIO_PIN(3, 11, 3, 0x1E4, 0x5D4), + MX51_PIN_CSI2_D19 = _MXC_BUILD_GPIO_PIN(3, 12, 3, 0x1E8, 0x5D8), + MX51_PIN_CSI2_VSYNC = _MXC_BUILD_GPIO_PIN(3, 13, 3, 0x1EC, 0x5DC), + MX51_PIN_CSI2_HSYNC = _MXC_BUILD_GPIO_PIN(3, 14, 3, 0x1F0, 0x5E0), + MX51_PIN_CSI2_PIXCLK = _MXC_BUILD_GPIO_PIN(3, 15, 3, 0x1F4, 0x5E4), + MX51_PIN_CSI2_PKE0 = _MXC_BUILD_NON_GPIO_PIN(NON_MUX_I, 0x81C), + MX51_PIN_I2C1_CLK = _MXC_BUILD_GPIO_PIN(3, 16, 3, 0x1F8, 0x5E8), + MX51_PIN_I2C1_DAT = _MXC_BUILD_GPIO_PIN(3, 17, 3, 0x1FC, 0x5EC), + MX51_PIN_AUD3_BB_TXD = _MXC_BUILD_GPIO_PIN(3, 18, 3, 0x200, 0x5F0), + MX51_PIN_AUD3_BB_RXD = _MXC_BUILD_GPIO_PIN(3, 19, 3, 0x204, 0x5F4), + MX51_PIN_AUD3_BB_CK = _MXC_BUILD_GPIO_PIN(3, 20, 3, 0x208, 0x5F8), + MX51_PIN_AUD3_BB_FS = _MXC_BUILD_GPIO_PIN(3, 21, 3, 0x20C, 0x5FC), + MX51_PIN_CSPI1_MOSI = _MXC_BUILD_GPIO_PIN(3, 22, 3, 0x210, 0x600), + MX51_PIN_CSPI1_MISO = _MXC_BUILD_GPIO_PIN(3, 23, 3, 0x214, 0x604), + MX51_PIN_CSPI1_SS0 = _MXC_BUILD_GPIO_PIN(3, 24, 3, 0x218, 0x608), + MX51_PIN_CSPI1_SS1 = _MXC_BUILD_GPIO_PIN(3, 25, 3, 0x21C, 0x60C), + MX51_PIN_CSPI1_RDY = _MXC_BUILD_GPIO_PIN(3, 26, 3, 0x220, 0x610), + MX51_PIN_CSPI1_SCLK = _MXC_BUILD_GPIO_PIN(3, 27, 3, 0x224, 0x614), + MX51_PIN_UART1_RXD = _MXC_BUILD_GPIO_PIN(3, 28, 3, 0x228, 0x618), + MX51_PIN_UART1_TXD = _MXC_BUILD_GPIO_PIN(3, 29, 3, 0x22C, 0x61C), + MX51_PIN_UART1_RTS = _MXC_BUILD_GPIO_PIN(3, 30, 3, 0x230, 0x620), + MX51_PIN_UART1_CTS = _MXC_BUILD_GPIO_PIN(3, 31, 3, 0x234, 0x624), + MX51_PIN_UART2_RXD = _MXC_BUILD_GPIO_PIN(0, 20, 3, 0x238, 0x628), + MX51_PIN_UART2_TXD = _MXC_BUILD_GPIO_PIN(0, 21, 3, 0x23C, 0x62C), + MX51_PIN_UART3_RXD = _MXC_BUILD_GPIO_PIN(0, 22, 3, 0x240, 0x630), + MX51_PIN_UART3_TXD = _MXC_BUILD_GPIO_PIN(0, 23, 3, 0x244, 0x634), + MX51_PIN_OWIRE_LINE = _MXC_BUILD_GPIO_PIN(0, 24, 3, 0x248, 0x638), + MX51_PIN_KEY_ROW0 = _MXC_BUILD_NON_GPIO_PIN(0x24C, 0x63C), + MX51_PIN_KEY_ROW1 = _MXC_BUILD_NON_GPIO_PIN(0x250, 0x640), + MX51_PIN_KEY_ROW2 = _MXC_BUILD_NON_GPIO_PIN(0x254, 0x644), + MX51_PIN_KEY_ROW3 = _MXC_BUILD_NON_GPIO_PIN(0x258, 0x648), + MX51_PIN_KEY_COL0 = _MXC_BUILD_NON_GPIO_PIN(0x25C, 0x64C), + MX51_PIN_KEY_COL1 = _MXC_BUILD_NON_GPIO_PIN(0x260, 0x650), + MX51_PIN_KEY_COL2 = _MXC_BUILD_NON_GPIO_PIN(0x264, 0x654), + MX51_PIN_KEY_COL3 = _MXC_BUILD_NON_GPIO_PIN(0x268, 0x658), + MX51_PIN_KEY_COL4 = _MXC_BUILD_NON_GPIO_PIN(0x26C, 0x65C), + MX51_PIN_KEY_COL5 = _MXC_BUILD_NON_GPIO_PIN(0x270, 0x660), + MX51_PIN_USBH1_CLK = _MXC_BUILD_GPIO_PIN(0, 25, 2, 0x278, 0x678), + MX51_PIN_USBH1_DIR = _MXC_BUILD_GPIO_PIN(0, 26, 2, 0x27C, 0x67C), + MX51_PIN_USBH1_STP = _MXC_BUILD_GPIO_PIN(0, 27, 2, 0x280, 0x680), + MX51_PIN_USBH1_NXT = _MXC_BUILD_GPIO_PIN(0, 28, 2, 0x284, 0x684), + MX51_PIN_USBH1_DATA0 = _MXC_BUILD_GPIO_PIN(0, 11, 2, 0x288, 0x688), + MX51_PIN_USBH1_DATA1 = _MXC_BUILD_GPIO_PIN(0, 12, 2, 0x28C, 0x68C), + MX51_PIN_USBH1_DATA2 = _MXC_BUILD_GPIO_PIN(0, 13, 2, 0x290, 0x690), + MX51_PIN_USBH1_DATA3 = _MXC_BUILD_GPIO_PIN(0, 14, 2, 0x294, 0x694), + MX51_PIN_USBH1_DATA4 = _MXC_BUILD_GPIO_PIN(0, 15, 2, 0x298, 0x698), + MX51_PIN_USBH1_DATA5 = _MXC_BUILD_GPIO_PIN(0, 16, 2, 0x29C, 0x69C), + MX51_PIN_USBH1_DATA6 = _MXC_BUILD_GPIO_PIN(0, 17, 2, 0x2A0, 0x6A0), + MX51_PIN_USBH1_DATA7 = _MXC_BUILD_GPIO_PIN(0, 18, 2, 0x2A4, 0x6A4), + MX51_PIN_DI1_PIN11 = _MXC_BUILD_GPIO_PIN(2, 0, 4, 0x2A8, 0x6A8), + MX51_PIN_DI1_PIN12 = _MXC_BUILD_GPIO_PIN(2, 1, 4, 0x2AC, 0x6AC), + MX51_PIN_DI1_PIN13 = _MXC_BUILD_GPIO_PIN(2, 2, 4, 0x2B0, 0x6B0), + MX51_PIN_DI1_D0_CS = _MXC_BUILD_GPIO_PIN(2, 3, 4, 0x2B4, 0x6B4), + MX51_PIN_DI1_D1_CS = _MXC_BUILD_GPIO_PIN(2, 4, 4, 0x2B8, 0x6B8), + MX51_PIN_DISPB2_SER_DIN = _MXC_BUILD_GPIO_PIN(2, 5, 4, 0x2BC, 0x6BC), + MX51_PIN_DISPB2_SER_DIO = _MXC_BUILD_GPIO_PIN(2, 6, 4, 0x2C0, 0x6C0), + MX51_PIN_DISPB2_SER_CLK = _MXC_BUILD_GPIO_PIN(2, 7, 4, 0x2C4, 0x6C4), + MX51_PIN_DISPB2_SER_RS = _MXC_BUILD_GPIO_PIN(2, 8, 4, 0x2C8, 0x6C8), + MX51_PIN_DISP1_DAT0 = _MXC_BUILD_NON_GPIO_PIN(0x2CC, 0x6CC), + MX51_PIN_DISP1_DAT1 = _MXC_BUILD_NON_GPIO_PIN(0x2D0, 0x6D0), + MX51_PIN_DISP1_DAT2 = _MXC_BUILD_NON_GPIO_PIN(0x2D4, 0x6D4), + MX51_PIN_DISP1_DAT3 = _MXC_BUILD_NON_GPIO_PIN(0x2D8, 0x6D8), + MX51_PIN_DISP1_DAT4 = _MXC_BUILD_NON_GPIO_PIN(0x2DC, 0x6DC), + MX51_PIN_DISP1_DAT5 = _MXC_BUILD_NON_GPIO_PIN(0x2E0, 0x6E0), + MX51_PIN_DISP1_DAT6 = _MXC_BUILD_NON_GPIO_PIN(0x2E4, 0x6E4), + MX51_PIN_DISP1_DAT7 = _MXC_BUILD_NON_GPIO_PIN(0x2E8, 0x6E8), + MX51_PIN_DISP1_DAT8 = _MXC_BUILD_NON_GPIO_PIN(0x2EC, 0x6EC), + MX51_PIN_DISP1_DAT9 = _MXC_BUILD_NON_GPIO_PIN(0x2F0, 0x6F0), + MX51_PIN_DISP1_DAT10 = _MXC_BUILD_NON_GPIO_PIN(0x2F4, 0x6F4), + MX51_PIN_DISP1_DAT11 = _MXC_BUILD_NON_GPIO_PIN(0x2F8, 0x6F8), + MX51_PIN_DISP1_DAT12 = _MXC_BUILD_NON_GPIO_PIN(0x2FC, 0x6FC), + MX51_PIN_DISP1_DAT13 = _MXC_BUILD_NON_GPIO_PIN(0x300, 0x700), + MX51_PIN_DISP1_DAT14 = _MXC_BUILD_NON_GPIO_PIN(0x304, 0x704), + MX51_PIN_DISP1_DAT15 = _MXC_BUILD_NON_GPIO_PIN(0x308, 0x708), + MX51_PIN_DISP1_DAT16 = _MXC_BUILD_NON_GPIO_PIN(0x30C, 0x70C), + MX51_PIN_DISP1_DAT17 = _MXC_BUILD_NON_GPIO_PIN(0x310, 0x710), + MX51_PIN_DISP1_DAT18 = _MXC_BUILD_NON_GPIO_PIN(0x314, 0x714), + MX51_PIN_DISP1_DAT19 = _MXC_BUILD_NON_GPIO_PIN(0x318, 0x718), + MX51_PIN_DISP1_DAT20 = _MXC_BUILD_NON_GPIO_PIN(0x31C, 0x71C), + MX51_PIN_DISP1_DAT21 = _MXC_BUILD_NON_GPIO_PIN(0x320, 0x720), + MX51_PIN_DISP1_DAT22 = _MXC_BUILD_NON_GPIO_PIN(0x324, 0x724), + MX51_PIN_DISP1_DAT23 = _MXC_BUILD_NON_GPIO_PIN(0x328, 0x728), + MX51_PIN_DI1_PIN3 = _MXC_BUILD_NON_GPIO_PIN(0x32C, 0x72C), + MX51_PIN_DI1_PIN2 = _MXC_BUILD_NON_GPIO_PIN(0x330, 0x734), + MX51_PIN_DI_GP1 = _MXC_BUILD_NON_GPIO_PIN(0x334, 0x73C), + MX51_PIN_DI_GP2 = _MXC_BUILD_NON_GPIO_PIN(0x338, 0x740), + MX51_PIN_DI_GP3 = _MXC_BUILD_NON_GPIO_PIN(0x33C, 0x744), + MX51_PIN_DI2_PIN4 = _MXC_BUILD_NON_GPIO_PIN(0x340, 0x748), + MX51_PIN_DI2_PIN2 = _MXC_BUILD_NON_GPIO_PIN(0x344, 0x74C), + MX51_PIN_DI2_PIN3 = _MXC_BUILD_NON_GPIO_PIN(0x348, 0x750), + MX51_PIN_DI2_DISP_CLK = _MXC_BUILD_NON_GPIO_PIN(0x34C, 0x754), + MX51_PIN_DI_GP4 = _MXC_BUILD_NON_GPIO_PIN(0x350, 0x758), + MX51_PIN_DISP2_DAT0 = _MXC_BUILD_NON_GPIO_PIN(0x354, 0x75C), + MX51_PIN_DISP2_DAT1 = _MXC_BUILD_NON_GPIO_PIN(0x358, 0x760), + MX51_PIN_DISP2_DAT2 = _MXC_BUILD_NON_GPIO_PIN(0x35C, 0x764), + MX51_PIN_DISP2_DAT3 = _MXC_BUILD_NON_GPIO_PIN(0x360, 0x768), + MX51_PIN_DISP2_DAT4 = _MXC_BUILD_NON_GPIO_PIN(0x364, 0x76C), + MX51_PIN_DISP2_DAT5 = _MXC_BUILD_NON_GPIO_PIN(0x368, 0x770), + MX51_PIN_DISP2_DAT6 = _MXC_BUILD_GPIO_PIN(0, 19, 5, 0x36C, 0x774), + MX51_PIN_DISP2_DAT7 = _MXC_BUILD_GPIO_PIN(0, 29, 5, 0x370, 0x778), + MX51_PIN_DISP2_DAT8 = _MXC_BUILD_GPIO_PIN(0, 30, 5, 0x374, 0x77C), + MX51_PIN_DISP2_DAT9 = _MXC_BUILD_GPIO_PIN(0, 31, 5, 0x378, 0x780), + MX51_PIN_DISP2_DAT10 = _MXC_BUILD_NON_GPIO_PIN(0x37C, 0x784), + MX51_PIN_DISP2_DAT11 = _MXC_BUILD_NON_GPIO_PIN(0x380, 0x788), + MX51_PIN_DISP2_DAT12 = _MXC_BUILD_NON_GPIO_PIN(0x384, 0x78C), + MX51_PIN_DISP2_DAT13 = _MXC_BUILD_NON_GPIO_PIN(0x388, 0x790), + MX51_PIN_DISP2_DAT14 = _MXC_BUILD_NON_GPIO_PIN(0x38C, 0x794), + MX51_PIN_DISP2_DAT15 = _MXC_BUILD_NON_GPIO_PIN(0x390, 0x798), + MX51_PIN_SD1_CMD = _MXC_BUILD_NON_GPIO_PIN(0x394, 0x79C), + MX51_PIN_SD1_CLK = _MXC_BUILD_NON_GPIO_PIN(0x398, 0x7A0), + MX51_PIN_SD1_DATA0 = _MXC_BUILD_NON_GPIO_PIN(0x39C, 0x7A4), + MX51_PIN_SD1_DATA1 = _MXC_BUILD_NON_GPIO_PIN(0x3A0, 0x7A8), + MX51_PIN_SD1_DATA2 = _MXC_BUILD_NON_GPIO_PIN(0x3A4, 0x7AC), + MX51_PIN_SD1_DATA3 = _MXC_BUILD_NON_GPIO_PIN(0x3A8, 0x7B0), + MX51_PIN_GPIO1_0 = _MXC_BUILD_GPIO_PIN(0, 0, 1, 0x3AC, 0x7B4), + MX51_PIN_GPIO1_1 = _MXC_BUILD_GPIO_PIN(0, 1, 1, 0x3B0, 0x7B8), + MX51_PIN_SD2_CMD = _MXC_BUILD_NON_GPIO_PIN(0x3B4, 0x7BC), + MX51_PIN_SD2_CLK = _MXC_BUILD_NON_GPIO_PIN(0x3B8, 0x7C0), + MX51_PIN_SD2_DATA0 = _MXC_BUILD_NON_GPIO_PIN(0x3BC, 0x7C4), + MX51_PIN_SD2_DATA1 = _MXC_BUILD_NON_GPIO_PIN(0x3C0, 0x7C8), + MX51_PIN_SD2_DATA2 = _MXC_BUILD_NON_GPIO_PIN(0x3C4, 0x7CC), + MX51_PIN_SD2_DATA3 = _MXC_BUILD_NON_GPIO_PIN(0x3C8, 0x7D0), + MX51_PIN_GPIO1_2 = _MXC_BUILD_GPIO_PIN(0, 2, 0, 0x3CC, 0x7D4), + MX51_PIN_GPIO1_3 = _MXC_BUILD_GPIO_PIN(0, 3, 0, 0x3D0, 0x7D8), + MX51_PIN_PMIC_INT_REQ = _MXC_BUILD_NON_GPIO_PIN(0x3D4, 0x7FC), + MX51_PIN_GPIO1_4 = _MXC_BUILD_GPIO_PIN(0, 4, 0, 0x3D8, 0x804), + MX51_PIN_GPIO1_5 = _MXC_BUILD_GPIO_PIN(0, 5, 0, 0x3DC, 0x808), + MX51_PIN_GPIO1_6 = _MXC_BUILD_GPIO_PIN(0, 6, 0, 0x3E0, 0x80C), + MX51_PIN_GPIO1_7 = _MXC_BUILD_GPIO_PIN(0, 7, 0, 0x3E4, 0x810), + MX51_PIN_GPIO1_8 = _MXC_BUILD_GPIO_PIN(0, 8, 0, 0x3E8, 0x814), + MX51_PIN_GPIO1_9 = _MXC_BUILD_GPIO_PIN(0, 9, 0, 0x3EC, 0x818), +}; + +#endif /* __ASSEMBLY__ */ +#endif /* __ASM_ARCH_MXC_MX51_PINS_H__ */ diff --git a/arch/arm/mach-mx51/pm.c b/arch/arm/mach-mx51/pm.c new file mode 100644 index 000000000000..1a6a5b1d6025 --- /dev/null +++ b/arch/arm/mach-mx51/pm.c @@ -0,0 +1,222 @@ +/* + * Copyright 2008-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/init.h> +#include <linux/io.h> +#include <linux/kernel.h> +#include <linux/clk.h> +#include <linux/platform_device.h> +#include <linux/regulator/consumer.h> +#include <linux/suspend.h> +#include <linux/proc_fs.h> +#include <linux/cpufreq.h> +#include <mach/hardware.h> +#include <asm/cacheflush.h> +#include <asm/tlb.h> +#include <asm/mach/map.h> +#include "crm_regs.h" + +static struct cpu_wp *cpu_wp_tbl; +static struct clk *cpu_clk; + +#if defined(CONFIG_CPU_FREQ) +static int org_freq; +extern int cpufreq_suspended; +extern int set_cpu_freq(int wp); +#endif + + +static struct device *pm_dev; +struct clk *gpc_dvfs_clk; +extern void cpu_do_suspend_workaround(u32 sdclk_iomux_addr); +extern void cpu_cortexa8_do_idle(u32); +extern struct cpu_wp *(*get_cpu_wp)(int *wp); + +extern int iram_ready; +void *suspend_iram_base; +void (*suspend_in_iram)(u32 sdclk_iomux_addr) = NULL; + +static int mx51_suspend_enter(suspend_state_t state) +{ + u32 sdclk_iomux_addr = IO_ADDRESS(IOMUXC_BASE_ADDR + 0x4b8); + + if (gpc_dvfs_clk == NULL) + gpc_dvfs_clk = clk_get(NULL, "gpc_dvfs_clk"); + /* gpc clock is needed for SRPG */ + clk_enable(gpc_dvfs_clk); + switch (state) { + case PM_SUSPEND_MEM: + mxc_cpu_lp_set(STOP_POWER_OFF); + break; + case PM_SUSPEND_STANDBY: + mxc_cpu_lp_set(WAIT_UNCLOCKED_POWER_OFF); + break; + default: + return -EINVAL; + } + + if (tzic_enable_wake(0) != 0) + return -EAGAIN; + + if (state == PM_SUSPEND_MEM) { + local_flush_tlb_all(); + flush_cache_all(); + + /* Run the suspend code from iRAM. */ + suspend_in_iram(sdclk_iomux_addr); + + /*clear the EMPGC0/1 bits */ + __raw_writel(0, MXC_SRPG_EMPGC0_SRPGCR); + __raw_writel(0, MXC_SRPG_EMPGC1_SRPGCR); + } else { + if ((mxc_cpu_is_rev(CHIP_REV_2_0)) < 0) { + /* do cpu_idle_workaround */ + u32 l2_iram_addr = IDLE_IRAM_BASE_ADDR; + if (!iram_ready) + return 0; + if (l2_iram_addr > 0x1FFE8000) + cpu_cortexa8_do_idle(IO_ADDRESS(l2_iram_addr)); + } else { + cpu_do_idle(); + } + } + clk_disable(gpc_dvfs_clk); + + return 0; +} + +/* + * Called after processes are frozen, but before we shut down devices. + */ +static int mx51_suspend_prepare(void) +{ +#if defined(CONFIG_CPU_FREQ) + struct cpufreq_freqs freqs; + org_freq = clk_get_rate(cpu_clk); + freqs.old = org_freq / 1000; + freqs.new = cpu_wp_tbl[0].cpu_rate / 1000; + freqs.cpu = 0; + freqs.flags = 0; + + cpufreq_suspended = 1; + if (clk_get_rate(cpu_clk) != cpu_wp_tbl[0].cpu_rate) { + set_cpu_freq(cpu_wp_tbl[0].cpu_rate); + cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); + cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); + } +#endif + return 0; +} + +/* + * Called before devices are re-setup. + */ +static void mx51_suspend_finish(void) +{ +#if defined(CONFIG_CPU_FREQ) + struct cpufreq_freqs freqs; + + freqs.old = clk_get_rate(cpu_clk) / 1000; + freqs.new = org_freq / 1000; + freqs.cpu = 0; + freqs.flags = 0; + + cpufreq_suspended = 0; + + if (org_freq != clk_get_rate(cpu_clk)) { + set_cpu_freq(org_freq); + cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); + cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); + } +#endif +} + +/* + * Called after devices are re-setup, but before processes are thawed. + */ +static void mx51_suspend_end(void) +{ +} + +static int mx51_pm_valid(suspend_state_t state) +{ + return (state > PM_SUSPEND_ON && state <= PM_SUSPEND_MAX); +} + +struct platform_suspend_ops mx51_suspend_ops = { + .valid = mx51_pm_valid, + .prepare = mx51_suspend_prepare, + .enter = mx51_suspend_enter, + .finish = mx51_suspend_finish, + .end = mx51_suspend_end, +}; + + +static int __devinit mx51_pm_probe(struct platform_device *pdev) +{ + pm_dev = &pdev->dev; + return 0; +} + +static struct platform_driver mx51_pm_driver = { + .driver = { + .name = "mx51_pm", + }, + .probe = mx51_pm_probe, +}; + +static int __init pm_init(void) +{ + int cpu_wp_nr; + + pr_info("Static Power Management for Freescale i.MX51\n"); + if (platform_driver_register(&mx51_pm_driver) != 0) { + printk(KERN_ERR "mx51_pm_driver register failed\n"); + return -ENODEV; + } + suspend_set_ops(&mx51_suspend_ops); + /* Move suspend routine into iRAM */ + suspend_iram_base = IO_ADDRESS(SUSPEND_IRAM_BASE_ADDR); + memcpy(suspend_iram_base, cpu_do_suspend_workaround, SZ_4K); + /* Need to remap the area here since we want the memory region + to be executable. */ + suspend_iram_base = __arm_ioremap(SUSPEND_IRAM_BASE_ADDR, SZ_4K, + MT_HIGH_VECTORS); + suspend_in_iram = (void *)suspend_iram_base; + + cpu_wp_tbl = get_cpu_wp(&cpu_wp_nr); + + cpu_clk = clk_get(NULL, "cpu_clk"); + if (IS_ERR(cpu_clk)) { + printk(KERN_DEBUG "%s: failed to get cpu_clk\n", __func__); + return PTR_ERR(cpu_clk); + } + printk(KERN_INFO "PM driver module loaded\n"); + + return 0; +} + + +static void __exit pm_cleanup(void) +{ + /* Unregister the device structure */ + platform_driver_unregister(&mx51_pm_driver); +} + +module_init(pm_init); +module_exit(pm_cleanup); + +MODULE_AUTHOR("Freescale Semiconductor, Inc."); +MODULE_DESCRIPTION("PM driver"); +MODULE_LICENSE("GPL"); + diff --git a/arch/arm/mach-mx51/sdma_script_code.h b/arch/arm/mach-mx51/sdma_script_code.h new file mode 100644 index 000000000000..9b8de26ab74a --- /dev/null +++ b/arch/arm/mach-mx51/sdma_script_code.h @@ -0,0 +1,170 @@ +/* + * Copyright 2008 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 */ + +/*! + * @file sdma_script_code.h + * @brief This file contains functions of SDMA scripts code initialization + * + * The file was generated automatically. Based on sdma scripts library. + * + * @ingroup SDMA + */ +/******************************************************************************* + + SDMA RELEASE LABEL: "SS15_ELVIS" + +*******************************************************************************/ + +#ifndef __SDMA_SCRIPT_CODE_H__ +#define __SDMA_SCRIPT_CODE_H__ + +/*! +* SDMA ROM scripts start addresses and sizes +*/ + +#define start_ADDR 0 +#define start_SIZE 24 + +#define core_ADDR 80 +#define core_SIZE 232 + +#define common_ADDR 312 +#define common_SIZE 330 + +#define ap_2_ap_ADDR 642 +#define ap_2_ap_SIZE 41 + +#define app_2_mcu_ADDR 683 +#define app_2_mcu_SIZE 64 + +#define mcu_2_app_ADDR 747 +#define mcu_2_app_SIZE 70 + +#define uart_2_mcu_ADDR 817 +#define uart_2_mcu_SIZE 75 + +#define shp_2_mcu_ADDR 892 +#define shp_2_mcu_SIZE 69 + +#define mcu_2_shp_ADDR 961 +#define mcu_2_shp_SIZE 72 + +#define app_2_per_ADDR 1033 +#define app_2_per_SIZE 66 + +#define per_2_app_ADDR 1099 +#define per_2_app_SIZE 74 + +#define per_2_shp_ADDR 1173 +#define per_2_shp_SIZE 78 + +#define shp_2_per_ADDR 1251 +#define shp_2_per_SIZE 72 + +#define uartsh_2_mcu_ADDR 1323 +#define uartsh_2_mcu_SIZE 69 + +#define mcu_2_ata_ADDR 1392 +#define mcu_2_ata_SIZE 81 + +#define ata_2_mcu_ADDR 1473 +#define ata_2_mcu_SIZE 96 + +#define loop_DMAs_routines_ADDR 1569 +#define loop_DMAs_routines_SIZE 227 + +#define test_ADDR 1796 +#define test_SIZE 63 + +#define signature_ADDR 1023 +#define signature_SIZE 1 + +/*! +* SDMA RAM scripts start addresses and sizes +*/ + +#define ext_mem__ipu_ram_ADDR 6144 +#define ext_mem__ipu_ram_SIZE 123 + +#define mcu_2_spdif_ADDR 6267 +#define mcu_2_spdif_SIZE 59 + +#define uart_2_per_ADDR 6326 +#define uart_2_per_SIZE 73 + +#define uartsh_2_per_ADDR 6399 +#define uartsh_2_per_SIZE 67 + +/*! +* SDMA RAM image start address and size +*/ + +#define RAM_CODE_START_ADDR 6144 +#define RAM_CODE_SIZE 322 + +/*! +* Buffer that holds the SDMA RAM image +*/ +__attribute__ ((__aligned__(4))) +#ifndef CONFIG_XIP_KERNEL +const +#endif +static const short sdma_code[] = { + 0x0e70, 0x0611, 0x5616, 0xc13c, 0x7d2a, 0x5ade, 0x008e, 0xc14e, + 0x7c26, 0x5be0, 0x5ef0, 0x5ce8, 0x0688, 0x08ff, 0x0011, 0x28ff, + 0x00bc, 0x53f6, 0x05df, 0x7d0b, 0x6dc5, 0x03df, 0x7d03, 0x6bd5, + 0xd84f, 0x982b, 0x6b05, 0xc681, 0x7e27, 0x7f29, 0x982b, 0x6d01, + 0x03df, 0x7d05, 0x6bd5, 0xc6ab, 0x7e18, 0x7f1a, 0x982b, 0x6b05, + 0xc621, 0x7e07, 0x7f06, 0x52de, 0x53e6, 0xc159, 0x7dd7, 0x0200, + 0x9803, 0x0007, 0x6004, 0x680c, 0x53f6, 0x028e, 0x00a3, 0xc256, + 0x048b, 0x0498, 0x0454, 0x068a, 0x982b, 0x0207, 0x680c, 0x6ddf, + 0x0107, 0x68ff, 0x60d0, 0x9834, 0x0207, 0x68ff, 0x6d28, 0x0107, + 0x6004, 0x680c, 0x9834, 0x0007, 0x68ff, 0x60d0, 0x9834, 0x0288, + 0x03a5, 0x3b03, 0x3d03, 0x4d00, 0x7d0a, 0x0804, 0x00a5, 0x00da, + 0x7d1a, 0x02a0, 0x7b01, 0x65d8, 0x7eee, 0x65ff, 0x7eec, 0x0804, + 0x02d0, 0x7d11, 0x4b00, 0x7c0f, 0x008a, 0x3003, 0x6dcf, 0x6bdf, + 0x0015, 0x0015, 0x7b02, 0x65d8, 0x0000, 0x7edd, 0x63ff, 0x7edb, + 0x3a03, 0x6dcd, 0x6bdd, 0x008a, 0x7b02, 0x65d8, 0x0000, 0x7ed3, + 0x65ff, 0x7ed1, 0x0006, 0xc1d9, 0xc1e3, 0x57db, 0x52f3, 0x6a01, + 0x008f, 0x00d5, 0x7d01, 0x008d, 0x05a0, 0x5deb, 0x56fb, 0x0478, + 0x7d28, 0x0479, 0x7c16, 0x0015, 0x0015, 0x0388, 0x620a, 0x0808, + 0x7801, 0x0217, 0x5a06, 0x7f1d, 0x620a, 0x0808, 0x7801, 0x0217, + 0x5a26, 0x7f17, 0x2301, 0x4b00, 0x7cf1, 0x0b70, 0x0311, 0x5313, + 0x98aa, 0x0015, 0x0015, 0x0015, 0x7804, 0x620b, 0x5a06, 0x620b, + 0x5a26, 0x7c07, 0x0000, 0x55eb, 0x4d00, 0x7d06, 0xc1fa, 0x57db, + 0x9880, 0x0007, 0x680c, 0xc213, 0xc20a, 0x987d, 0xc1e3, 0x57db, + 0x52f3, 0x6ad5, 0x56fb, 0x028e, 0x1a94, 0x6ac3, 0x62c8, 0x0269, + 0x7d1e, 0x1e94, 0x6ee3, 0x62d0, 0x5aeb, 0x62c8, 0x0248, 0x6ed3, + 0x6ac8, 0x2694, 0x52eb, 0x6ad5, 0x6ee3, 0x62c8, 0x026e, 0x7d27, + 0x6ac8, 0x7f23, 0x2501, 0x4d00, 0x7d26, 0x028e, 0x1a98, 0x6ac3, + 0x62c8, 0x6ec3, 0x0260, 0x7df1, 0x62d0, 0xc27a, 0x98fb, 0x6ee3, + 0x008f, 0x2001, 0x00d5, 0x7d01, 0x008d, 0x05a0, 0x62c8, 0x026e, + 0x7d0e, 0x6ac8, 0x7f0a, 0x2001, 0x7cf9, 0x6add, 0x7f06, 0x0000, + 0x4d00, 0x7d09, 0xc1fa, 0x57db, 0x98ba, 0x0007, 0x6aff, 0x62d0, + 0xc27a, 0x0458, 0x0454, 0x6add, 0x7ff8, 0xc20a, 0x98b7, 0xc1d9, + 0xc1e3, 0x57db, 0x52f3, 0x6ad5, 0x56fb, 0x028e, 0x1a94, 0x5202, + 0x0269, 0x7d17, 0x1e94, 0x5206, 0x0248, 0x5a06, 0x2694, 0x5206, + 0x026e, 0x7d26, 0x6ac8, 0x7f22, 0x2501, 0x4d00, 0x7d27, 0x028e, + 0x1a98, 0x5202, 0x0260, 0x7df3, 0x6add, 0x7f18, 0x62d0, 0xc27a, + 0x993e, 0x008f, 0x2001, 0x00d5, 0x7d01, 0x008d, 0x05a0, 0x5206, + 0x026e, 0x7d0e, 0x6ac8, 0x7f0a, 0x2001, 0x7cf9, 0x6add, 0x7f06, + 0x0000, 0x4d00, 0x7d0b, 0xc1fa, 0x57db, 0x9904, 0x0007, 0x6aff, + 0x6add, 0x7ffc, 0x62d0, 0xc27a, 0x0458, 0x0454, 0x6add, 0x7ff6, + 0xc20a, 0x9901 +}; +#endif diff --git a/arch/arm/mach-mx51/sdram_autogating.c b/arch/arm/mach-mx51/sdram_autogating.c new file mode 100644 index 000000000000..1d47e5aaf606 --- /dev/null +++ b/arch/arm/mach-mx51/sdram_autogating.c @@ -0,0 +1,164 @@ +/* + * Copyright 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 sdram_autogating.c + * + * @brief Enable auto clock gating of the EMI_FAST clock using M4IF. + * + * The APIs are for enabling and disabling automatic clock gating of EMI_FAST. + * + * @ingroup PM + */ +#include <asm/io.h> +#include <linux/proc_fs.h> +#include <linux/clk.h> +#include <linux/delay.h> +#include <linux/platform_device.h> +#include <linux/regulator/consumer.h> +#include <mach/hardware.h> +#include <mach/clock.h> +#include <mach/mxc_dvfs.h> +#include "crm_regs.h" + +int sdram_autogating_is_active; +static struct device *sdram_autogating_dev; +#define M4IF_CNTL_REG0 0x8c +#define M4IF_CNTL_REG1 0x90 + +void enable_sdram_autogating(void); +void disable_sdram_autogating(void); + +void enable_sdram_autogating() +{ + u32 reg; + + /* Set the Fast arbitration Power saving timer */ + reg = __raw_readl((IO_ADDRESS(M4IF_BASE_ADDR) + M4IF_CNTL_REG1)); + reg &= ~0xFF; + reg |= 0x09; + __raw_writel(reg, (IO_ADDRESS(M4IF_BASE_ADDR) + M4IF_CNTL_REG1)); + /*Allow for automatic gating of the EMI internal clock. + * If this is done, emi_intr CCGR bits should be set to 11. + */ + reg = __raw_readl((IO_ADDRESS(M4IF_BASE_ADDR) + M4IF_CNTL_REG0)); + reg &= ~0x5; + __raw_writel(reg, (IO_ADDRESS(M4IF_BASE_ADDR) + M4IF_CNTL_REG0)); + + sdram_autogating_is_active = 1; +} + +void disable_sdram_autogating() +{ + u32 reg; + + reg = __raw_readl((IO_ADDRESS(M4IF_BASE_ADDR) + M4IF_CNTL_REG0)); + reg |= 0x4; + __raw_writel(reg, (IO_ADDRESS(M4IF_BASE_ADDR) + M4IF_CNTL_REG0)); + sdram_autogating_is_active = 0; +} + +static ssize_t sdram_autogating_enable_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + if (sdram_autogating_is_active) + return sprintf(buf, + "M4IF autoclock gating for EMI_FAST enabled\n"); + else + return sprintf(buf, + "M4IF autoclock gating for EMI_FAST disabled\n"); +} + +static ssize_t sdram_autogating_enable_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + if (strstr(buf, "1") != NULL) + enable_sdram_autogating(); + else if (strstr(buf, "0") != NULL) { + if (sdram_autogating_is_active) + disable_sdram_autogating(); + } + return size; +} + +static DEVICE_ATTR(enable, 0644, sdram_autogating_enable_show, + sdram_autogating_enable_store); + +/*! + * This is the probe routine for the auto clockgating of sdram driver. + * + * @param pdev The platform device structure + * + * @return The function returns 0 on success + * + */ +static int __devinit sdram_autogating_probe(struct platform_device *pdev) +{ + int err = 0; + + sdram_autogating_dev = &pdev->dev; + + err = sysfs_create_file(&sdram_autogating_dev->kobj, + &dev_attr_enable.attr); + if (err) { + printk(KERN_ERR + "Unable to register sysdev entry for sdram_autogating"); + return err; + } + + sdram_autogating_is_active = 0; + if (mxc_cpu_is_rev(CHIP_REV_3_0) >= 1) + enable_sdram_autogating(); + return 0; +} + +static struct platform_driver sdram_autogating_driver = { + .driver = { + .name = "sdram_autogating", + }, + .probe = sdram_autogating_probe, +}; + +/*! + * Initialise the sdram_autogating_driver. + * + * @return The function always returns 0. + */ + +static int __init sdram_autogating_init(void) +{ + if (platform_driver_register(&sdram_autogating_driver) != 0) { + printk(KERN_ERR "sdram_autogating_driver register failed\n"); + return -ENODEV; + } + + printk(KERN_INFO "sdram autogating driver module loaded\n"); + return 0; +} + +static void __exit sdram_autogating_cleanup(void) +{ + sysfs_remove_file(&sdram_autogating_dev->kobj, &dev_attr_enable.attr); + + /* Unregister the device structure */ + platform_driver_unregister(&sdram_autogating_driver); +} + +module_init(sdram_autogating_init); +module_exit(sdram_autogating_cleanup); + +MODULE_AUTHOR("Freescale Semiconductor, Inc."); +MODULE_DESCRIPTION("sdram_autogating driver"); +MODULE_LICENSE("GPL"); + diff --git a/arch/arm/mach-mx51/serial.c b/arch/arm/mach-mx51/serial.c new file mode 100644 index 000000000000..7d1f94c26b85 --- /dev/null +++ b/arch/arm/mach-mx51/serial.c @@ -0,0 +1,178 @@ +/* + * Copyright 2008-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-mx51/serial.c + * + * @brief This file contains the UART initiliazation. + * + * @ingroup MSL_MX51 + */ +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/serial.h> +#include <mach/hardware.h> +#include <mach/mxc_uart.h> +#include <mach/spba.h> +#include "serial.h" +#include "board.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, + }, + [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, + }, + [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_RXDMUX, + }, +}; + +#if defined CONFIG_UART1_ENABLED +static struct platform_device mxc_uart_device1 = { + .name = "mxcintuart", + .id = 0, + .dev = { + .platform_data = &mxc_ports[0], + }, +}; +#endif + +#if defined CONFIG_UART2_ENABLED +static struct platform_device mxc_uart_device2 = { + .name = "mxcintuart", + .id = 1, + .dev = { + .platform_data = &mxc_ports[1], + }, +}; +#endif + +#if defined CONFIG_UART3_ENABLED +static struct platform_device mxc_uart_device3 = { + .name = "mxcintuart", + .id = 2, + .dev = { + .platform_data = &mxc_ports[2], + }, +}; +#endif + +static int __init mxc_init_uart(void) +{ + /* Register all the MXC UART platform device structures */ +#if defined CONFIG_UART1_ENABLED + platform_device_register(&mxc_uart_device1); +#endif +#if defined CONFIG_UART2_ENABLED + platform_device_register(&mxc_uart_device2); +#endif + + /* Grab ownership of shared UARTs 3 and 4, only when enabled */ +#if defined CONFIG_UART3_ENABLED +#if UART3_DMA_ENABLE == 1 + spba_take_ownership(UART3_SHARED_PERI, (SPBA_MASTER_A | SPBA_MASTER_C)); +#else + spba_take_ownership(UART3_SHARED_PERI, SPBA_MASTER_A); +#endif /* UART3_DMA_ENABLE */ + platform_device_register(&mxc_uart_device3); +#endif /* UART3_ENABLED */ + return 0; +} + +#else +static int __init mxc_init_uart(void) +{ + return 0; +} +#endif + +arch_initcall(mxc_init_uart); diff --git a/arch/arm/mach-mx51/serial.h b/arch/arm/mach-mx51/serial.h new file mode 100644 index 000000000000..ff4928c3b002 --- /dev/null +++ b/arch/arm/mach-mx51/serial.h @@ -0,0 +1,127 @@ +/* + * Copyright 2008-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_MX51_SERIAL_H__ +#define __ARCH_ARM_MACH_MX51_SERIAL_H__ + +#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). + */ +/* UART used as wakeup source */ +#define UART1_HW_FLOW 0 +/*! + * 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 minimum buffer size is 512 + * bytes. The buffer size should be a multiple of 256. + */ +#define UART1_DMA_RXBUFSIZE 1024 +/*! + * 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 0 +#define UART2_UCR4_CTSTL -1 +#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 1 +#define UART3_UCR4_CTSTL 16 +#define UART3_DMA_ENABLE 1 +#define UART3_DMA_RXBUFSIZE 1024 +#define UART3_UFCR_RXTL 16 +#define UART3_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 SPBA_UART3 + +#endif /* __ARCH_ARM_MACH_MX51_SERIAL_H__ */ diff --git a/arch/arm/mach-mx51/suspend.S b/arch/arm/mach-mx51/suspend.S new file mode 100644 index 000000000000..a7f585aa9525 --- /dev/null +++ b/arch/arm/mach-mx51/suspend.S @@ -0,0 +1,155 @@ +/* + * Copyright 2008-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/linkage.h> + +#define ARM_CTRL_DCACHE 1 << 2 +#define ARM_CTRL_ICACHE 1 << 12 +#define ARM_AUXCR_L2EN 1 << 1 + + +/* + * cpu_do_suspend_workaround() + * + * Suspend the processor (eg, wait for interrupt). + * + * IRQs are already disabled. + */ +ENTRY(cpu_do_suspend_workaround) + stmfd sp!, {r4,r5,r6,r7,r9,r10,r11} @ Save registers + + mov r6, r0 @save iomux address + /* Disable L1 caches */ + mrc p15, 0, r0, c1, c0, 0 @ R0 = system control reg + bic r0, r0, #ARM_CTRL_ICACHE @ Disable ICache + bic r0, r0, #ARM_CTRL_DCACHE @ Disable DCache + mcr p15, 0, r0, c1, c0, 0 @ Update system control reg + + mrc p15, 1, r0, c0, c0, 1 @ Read CLIDR + ands r3, r0, #0x7000000 @ Isolate level of coherency + mov r3, r3, lsr #23 @ Cache level value (naturally aligned) + beq FinishedClean + mov r10, #0 +Loop1Clean: + add r2, r10, r10, lsr #1 @ Work out cache level + mov r1, r0, lsr r2 @ R0 bottom 3 bits = Cache Type for this level + and r1, r1, #7 @ Get those 3 bits alone + cmp r1, #2 + blt SkipClean @ No cache or only instruction cache at this level + mcr p15, 2, r10, c0, c0, 0 @ Write the Cache Size selection register + mov r1, #0 + .long 0xF57FF06F @ ISB + mrc p15, 1, r1, c0, c0, 0 @ Reads current Cache Size ID register + and r2, r1, #7 @ Extract the line length field + add r2, r2, #4 @ Add 4 for the line length offset (log2 16 bytes) + ldr r4, =0x3FF + ands r4, r4, r1, lsr #3 @ R4 is the max number on the way size (right aligned) + clz r5, r4 @ R5 is the bit position of the way size increment + ldr r7, =0x00007FFF + ands r7, r7, r1, lsr #13 @ R7 is the max number of the index size (right aligned) +Loop2Clean: + mov r9, r4 @ R9 working copy of the max way size (right aligned) +Loop3Clean: + orr r11, r10, r9, lsl r5 @ Factor in the way number and cache number into R11 + orr r11, r11, r7, lsl r2 @ Factor in the index number + mcr p15, 0, r11, c7, c14, 2 @ Clean and invalidate by set/way + subs r9, r9, #1 @ Decrement the way number + bge Loop3Clean + subs r7, r7, #1 @ Decrement the index + bge Loop2Clean +SkipClean: + add r10, r10, #2 @ Increment the cache number + cmp r3, r10 + bgt Loop1Clean + +FinishedClean: + + /* Disable L2 cache */ + mrc p15, 0, r0, c1, c0, 1 @ R0 = auxiliary control reg + bic r0, r0, #ARM_AUXCR_L2EN @ Disable L2 cache + mcr p15, 0, r0, c1, c0, 1 @ Update aux control reg + + /*Set the DDR drive strength to low */ + ldr r10, [r6] + and r10, r10, #0xF1 @ clear bits 2-1 + str r10, [r6] + + .long 0xe320f003 @ Opcode for WFI + + /*Set the DDR drive strength to max */ + orr r10, r10, #0x06 @ set bits 2-1 + str r10, [r6] + + mov r0, #0 + mcr p15, 0, r0, c7, c5, 0 @ Invalidate inst cache + + /* Invalidate data caches */ + mrc p15, 1, r0, c0, c0, 1 @ Read CLIDR + ands r3, r0, #0x7000000 @ Isolate level of coherency + mov r3, r3, lsr #23 @ Cache level value (naturally aligned) + beq FinishedInvalidate + mov r10, #0 +Loop1Invalidate: + add r2, r10, r10, lsr #1 @ Work out cache level + mov r1, r0, lsr r2 @ R0 bottom 3 bits = Cache Type for this level + and r1, r1, #7 @ Get those 3 bits alone + cmp r1, #2 + blt SkipInvalidate @ No cache or only instruction cache at this level + mcr p15, 2, r10, c0, c0, 0 @ Write the Cache Size selection register + mov r1, #0 + .long 0xF57FF06F @ ISB + mrc p15, 1, r1, c0, c0, 0 @ Reads current Cache Size ID register + and r2, r1, #7 @ Extract the line length field + add r2, r2, #4 @ Add 4 for the line length offset (log2 16 bytes) + ldr r4, =0x3FF + ands r4, r4, r1, lsr #3 @ R4 is the max number on the way size (right aligned) + clz r5, r4 @ R5 is the bit position of the way size increment + ldr r7, =0x00007FFF + ands r7, r7, r1, lsr #13 @ R7 is the max number of the index size (right aligned) +Loop2Invalidate: + mov r9, r4 @ R9 working copy of the max way size (right aligned) +Loop3Invalidate: + orr r11, r10, r9, lsl r5 @ Factor in the way number and cache number into R11 + orr r11, r11, r7, lsl r2 @ Factor in the index number + mcr p15, 0, r11, c7, c6, 2 @ Invalidate by set/way + subs r9, r9, #1 @ Decrement the way number + bge Loop3Invalidate + subs r7, r7, #1 @ Decrement the index + bge Loop2Invalidate +SkipInvalidate: + add r10, r10, #2 @ Increment the cache number + cmp r3, r10 + bgt Loop1Invalidate + +FinishedInvalidate: + + /* Enable L2 cache */ + mrc p15, 0, r0, c1, c0, 1 @ R0 = auxiliary control reg + orr r0, r0, #ARM_AUXCR_L2EN @ Enable L2 cache + mcr p15, 0, r0, c1, c0, 1 @ Update aux control reg + + /* Enable L1 caches */ + mrc p15, 0, r0, c1, c0, 0 @ R0 = system control reg + orr r0, r0, #ARM_CTRL_ICACHE @ Enable ICache + orr r0, r0, #ARM_CTRL_DCACHE @ Enable DCache + mcr p15, 0, r0, c1, c0, 0 @ Update system control reg + + /* Restore registers */ + ldmfd sp!, {r4,r5,r6,r7,r9,r10,r11} + mov pc, lr + + .type cpu_do_suspend, #object +ENTRY(cpu_do_suspend) + .word cpu_do_suspend_workaround + .size cpu_do_suspend_workaround, . - cpu_do_suspend_workaround + + diff --git a/arch/arm/mach-mx51/system.c b/arch/arm/mach-mx51/system.c new file mode 100644 index 000000000000..749282d5a633 --- /dev/null +++ b/arch/arm/mach-mx51/system.c @@ -0,0 +1,187 @@ +/* + * Copyright 2008-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/clk.h> +#include <linux/platform_device.h> +#include <asm/io.h> +#include <mach/hardware.h> +#include <asm/proc-fns.h> +#include <asm/system.h> +#include "crm_regs.h" + +/*! + * @defgroup MSL_MX51 i.MX51 Machine Specific Layer (MSL) + */ + +/*! + * @file mach-mx51/system.c + * @brief This file contains idle and reset functions. + * + * @ingroup MSL_MX51 + */ + +extern int mxc_jtag_enabled; +extern int iram_ready; +static struct clk *gpc_dvfs_clk; + +extern void cpu_cortexa8_do_idle(u32 addr); + + +/* set cpu low power mode before WFI instruction */ +void mxc_cpu_lp_set(enum mxc_cpu_pwr_mode mode) +{ + u32 plat_lpc, arm_srpgcr, ccm_clpcr; + u32 empgc0, empgc1; + int stop_mode = 0; + + /* always allow platform to issue a deep sleep mode request */ + plat_lpc = __raw_readl(MXC_CORTEXA8_PLAT_LPC) & + ~(MXC_CORTEXA8_PLAT_LPC_DSM); + ccm_clpcr = __raw_readl(MXC_CCM_CLPCR) & ~(MXC_CCM_CLPCR_LPM_MASK); + arm_srpgcr = __raw_readl(MXC_SRPG_ARM_SRPGCR) & ~(MXC_SRPGCR_PCR); + empgc0 = __raw_readl(MXC_SRPG_EMPGC0_SRPGCR) & ~(MXC_SRPGCR_PCR); + empgc1 = __raw_readl(MXC_SRPG_EMPGC1_SRPGCR) & ~(MXC_SRPGCR_PCR); + + switch (mode) { + case WAIT_CLOCKED: + break; + case WAIT_UNCLOCKED: + ccm_clpcr |= (0x1 << MXC_CCM_CLPCR_LPM_OFFSET); + break; + case WAIT_UNCLOCKED_POWER_OFF: + case STOP_POWER_OFF: + plat_lpc |= MXC_CORTEXA8_PLAT_LPC_DSM + | MXC_CORTEXA8_PLAT_LPC_DBG_DSM; + if (mode == WAIT_UNCLOCKED_POWER_OFF) { + ccm_clpcr |= (0x1 << MXC_CCM_CLPCR_LPM_OFFSET); + ccm_clpcr &= ~MXC_CCM_CLPCR_VSTBY; + stop_mode = 0; + } else { + ccm_clpcr |= (0x2 << MXC_CCM_CLPCR_LPM_OFFSET); + ccm_clpcr |= (0x3 << MXC_CCM_CLPCR_STBY_COUNT_OFFSET); + ccm_clpcr |= MXC_CCM_CLPCR_VSTBY; + ccm_clpcr |= MXC_CCM_CLPCR_SBYOS; + stop_mode = 1; + } + + arm_srpgcr |= MXC_SRPGCR_PCR; + if (stop_mode) { + empgc0 |= MXC_SRPGCR_PCR; + empgc1 |= MXC_SRPGCR_PCR; + } + + if (tzic_enable_wake(1) != 0) + return; + break; + case STOP_POWER_ON: + ccm_clpcr |= (0x2 << MXC_CCM_CLPCR_LPM_OFFSET); + break; + default: + printk(KERN_WARNING "UNKNOWN cpu power mode: %d\n", mode); + return; + } + + __raw_writel(plat_lpc, MXC_CORTEXA8_PLAT_LPC); + __raw_writel(ccm_clpcr, MXC_CCM_CLPCR); + __raw_writel(arm_srpgcr, MXC_SRPG_ARM_SRPGCR); + __raw_writel(arm_srpgcr, MXC_SRPG_NEON_SRPGCR); + if (stop_mode) { + __raw_writel(empgc0, MXC_SRPG_EMPGC0_SRPGCR); + __raw_writel(empgc1, MXC_SRPG_EMPGC1_SRPGCR); + } +} + +void mxc_pg_enable(struct platform_device *pdev) +{ + if (pdev == NULL) + return; + + if (strcmp(pdev->name, "mxc_ipu") == 0) { + __raw_writel(MXC_PGCR_PCR, MXC_PGC_IPU_PGCR); + __raw_writel(MXC_PGSR_PSR, MXC_PGC_IPU_PGSR); + } else if (strcmp(pdev->name, "mxc_vpu") == 0) { + __raw_writel(MXC_PGCR_PCR, MXC_PGC_VPU_PGCR); + __raw_writel(MXC_PGSR_PSR, MXC_PGC_VPU_PGSR); + } +} + +EXPORT_SYMBOL(mxc_pg_enable); + +void mxc_pg_disable(struct platform_device *pdev) +{ + if (pdev == NULL) + return; + + if (strcmp(pdev->name, "mxc_ipu") == 0) { + __raw_writel(0x0, MXC_PGC_IPU_PGCR); + if (__raw_readl(MXC_PGC_IPU_PGSR) & MXC_PGSR_PSR) + dev_dbg(&pdev->dev, "power gating successful\n"); + __raw_writel(MXC_PGSR_PSR, MXC_PGC_IPU_PGSR); + } else if (strcmp(pdev->name, "mxc_vpu") == 0) { + __raw_writel(0x0, MXC_PGC_VPU_PGCR); + if (__raw_readl(MXC_PGC_VPU_PGSR) & MXC_PGSR_PSR) + dev_dbg(&pdev->dev, "power gating successful\n"); + __raw_writel(MXC_PGSR_PSR, MXC_PGC_VPU_PGSR); + } +} + +EXPORT_SYMBOL(mxc_pg_disable); + +/* To change the idle power mode, need to set arch_idle_mode to a different + * power mode as in enum mxc_cpu_pwr_mode. + * May allow dynamically changing the idle mode. + */ +static int arch_idle_mode = WAIT_UNCLOCKED_POWER_OFF; +/*! + * This function puts the CPU into idle mode. It is called by default_idle() + * in process.c file. + */ +void arch_idle(void) +{ + if (likely(!mxc_jtag_enabled)) { + if (gpc_dvfs_clk == NULL) + gpc_dvfs_clk = clk_get(NULL, "gpc_dvfs_clk"); + /* gpc clock is needed for SRPG */ + clk_enable(gpc_dvfs_clk); + mxc_cpu_lp_set(arch_idle_mode); + if ((mxc_cpu_is_rev(CHIP_REV_2_0)) < 0) { + u32 l2_iram_addr = IDLE_IRAM_BASE_ADDR; + + if (!iram_ready) + return; + + if (l2_iram_addr > 0x1FFE8000) + cpu_cortexa8_do_idle(IO_ADDRESS(l2_iram_addr)); + } else { + cpu_do_idle(); + } + clk_disable(gpc_dvfs_clk); + } +} + +/* + * This function resets the system. It is called by machine_restart(). + * + * @param mode indicates different kinds of resets + */ +void arch_reset(char mode) +{ + /* Workaround to reset NFC_CONFIG3 register + * due to the chip warm reset does not reset it + */ + __raw_writel(0x20600, IO_ADDRESS(NFC_BASE_ADDR) + 0x28); + + /* Assert SRS signal */ + mxc_wd_reset(); +} diff --git a/arch/arm/mach-mx51/usb.h b/arch/arm/mach-mx51/usb.h new file mode 100644 index 000000000000..7cc14d9119d1 --- /dev/null +++ b/arch/arm/mach-mx51/usb.h @@ -0,0 +1,112 @@ +/* + * 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 + */ + + +extern int usbotg_init(struct platform_device *pdev); +extern void usbotg_uninit(struct fsl_usb2_platform_data *pdata); +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_usbotg_utmi_active(void); +extern void gpio_usbotg_utmi_inactive(void); + +/* + * Determine which platform_data struct to use for the DR controller, + * based on which transceiver is configured. + * PDATA is a pointer to it. + */ +#if 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) +#elif defined(CONFIG_UTMI_MXC) +static struct fsl_usb2_platform_data __maybe_unused dr_utmi_config; +#define PDATA (&dr_utmi_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-mx51/usb_dr.c b/arch/arm/mach-mx51/usb_dr.c new file mode 100644 index 000000000000..b3eb7d645e34 --- /dev/null +++ b/arch/arm/mach-mx51/usb_dr.c @@ -0,0 +1,160 @@ +/* + * 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/clk.h> +#include <linux/platform_device.h> +#include <linux/fsl_devices.h> +#include <mach/arc_otg.h> +#include "usb.h" + +static int usbotg_init_ext(struct platform_device *pdev); +static void usbotg_uninit_ext(struct fsl_usb2_platform_data *pdata); +static void _wake_up_enable(struct fsl_usb2_platform_data *pdata, bool enable); + +/* + * 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_utmi_config = { + .name = "DR", + .platform_init = usbotg_init_ext, + .platform_uninit = usbotg_uninit_ext, + .phy_mode = FSL_USB2_PHY_UTMI_WIDE, + .power_budget = 500, /* 500 mA max power */ + .gpio_usb_active = gpio_usbotg_hs_active, + .gpio_usb_inactive = gpio_usbotg_hs_inactive, + .wake_up_enable = _wake_up_enable, + .transceiver = "utmi", +}; + + +/* + * 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_USB_OTG, + .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 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), +}; + +/* Notes: configure USB clock*/ +static int usbotg_init_ext(struct platform_device *pdev) +{ + struct clk *usb_clk; + + usb_clk = clk_get(NULL, "usboh3_clk"); + clk_enable(usb_clk); + clk_put(usb_clk); + + usb_clk = clk_get(NULL, "usb_phy_clk"); + clk_enable(usb_clk); + clk_put(usb_clk); + + /*derive clock from oscillator */ + usb_clk = clk_get(NULL, "usb_utmi_clk"); + clk_disable(usb_clk); + clk_put(usb_clk); + + return usbotg_init(pdev); +} + +static void usbotg_uninit_ext(struct fsl_usb2_platform_data *pdata) +{ + struct clk *usb_clk; + + usb_clk = clk_get(NULL, "usboh3_clk"); + clk_disable(usb_clk); + clk_put(usb_clk); + + usb_clk = clk_get(NULL, "usb_phy_clk"); + clk_disable(usb_clk); + clk_put(usb_clk); + + usbotg_uninit(pdata); +} + +static void _wake_up_enable(struct fsl_usb2_platform_data *pdata, bool enable) +{ + if (get_usb_mode(pdata) == FSL_USB_DR_DEVICE) { + if (enable) { + USBCTRL |= UCTRL_OWIE; + USBCTRL_HOST2 |= UCTRL_H2OVBWK_EN; + USB_PHY_CTR_FUNC |= USB_UTMI_PHYCTRL_CONF2; + } else { + USBCTRL &= ~UCTRL_OWIE; + USBCTRL_HOST2 &= ~UCTRL_H2OVBWK_EN; + USB_PHY_CTR_FUNC &= ~USB_UTMI_PHYCTRL_CONF2; + } + } +} + +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-mx51/usb_h1.c b/arch/arm/mach-mx51/usb_h1.c new file mode 100644 index 000000000000..869ec45f0726 --- /dev/null +++ b/arch/arm/mach-mx51/usb_h1.c @@ -0,0 +1,114 @@ +/* + * 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/delay.h> +#include <linux/platform_device.h> +#include <linux/fsl_devices.h> +#include <mach/arc_otg.h> +#include <asm/mach-types.h> +#include <asm/mach/arch.h> +#include "usb.h" +#include "iomux.h" + + +/* + * USB Host1 HS port + */ +static int gpio_usbh1_active(void) +{ + /* Set USBH1_STP to GPIO and toggle it */ + mxc_request_iomux(MX51_PIN_USBH1_STP, IOMUX_CONFIG_GPIO | + IOMUX_CONFIG_SION); + gpio_request(IOMUX_TO_GPIO(MX51_PIN_USBH1_STP), "usbh1_stp"); + gpio_direction_output(IOMUX_TO_GPIO(MX51_PIN_USBH1_STP), 0); + gpio_set_value(IOMUX_TO_GPIO(MX51_PIN_USBH1_STP), 1); + + /* Signal only used on MX51-3DS for reset to PHY.*/ + if (machine_is_mx51_3ds()) { + mxc_request_iomux(MX51_PIN_EIM_D17, IOMUX_CONFIG_ALT1); + mxc_iomux_set_pad(MX51_PIN_EIM_D17, PAD_CTL_DRV_HIGH | + PAD_CTL_HYS_NONE | PAD_CTL_PUE_KEEPER | + PAD_CTL_100K_PU | PAD_CTL_ODE_OPENDRAIN_NONE | + PAD_CTL_PKE_ENABLE | PAD_CTL_SRE_FAST); + gpio_request(IOMUX_TO_GPIO(MX51_PIN_EIM_D17), "eim_d17"); + gpio_direction_output(IOMUX_TO_GPIO(MX51_PIN_EIM_D17), 0); + gpio_set_value(IOMUX_TO_GPIO(MX51_PIN_EIM_D17), 1); + } + + msleep(100); + + return 0; +} + +void gpio_usbh1_setback_stp(void) +{ + /* setback USBH1_STP to be function */ + mxc_request_iomux(MX51_PIN_USBH1_STP, IOMUX_CONFIG_ALT0); + mxc_iomux_set_pad(MX51_PIN_USBH1_STP, PAD_CTL_SRE_FAST | + PAD_CTL_DRV_HIGH | PAD_CTL_ODE_OPENDRAIN_NONE | + PAD_CTL_PUE_KEEPER | PAD_CTL_PKE_ENABLE | + PAD_CTL_HYS_ENABLE | PAD_CTL_DDR_INPUT_CMOS | + PAD_CTL_DRV_VOT_LOW); + gpio_free(IOMUX_TO_GPIO(MX51_PIN_USBH1_STP)); +} +EXPORT_SYMBOL(gpio_usbh1_setback_stp); + +static void gpio_usbh1_inactive(void) +{ + /* Signal only used on MX51-3DS for reset to PHY.*/ + if (machine_is_mx51_3ds()) { + gpio_free(IOMUX_TO_GPIO(MX51_PIN_EIM_D17)); + mxc_free_iomux(MX51_PIN_EIM_D17, IOMUX_CONFIG_GPIO); + } + + mxc_free_iomux(MX51_PIN_USBH1_STP, IOMUX_CONFIG_GPIO); + gpio_free(IOMUX_TO_GPIO(MX51_PIN_USBH1_STP)); +} + +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_ULPI, + .power_budget = 500, /* 500 mA max power */ + .gpio_usb_active = gpio_usbh1_active, + .gpio_usb_inactive = gpio_usbh1_inactive, + .transceiver = "isp1504", +}; + +static struct resource usbh1_resources[] = { + [0] = { + .start = (u32) (USB_H1REGS_BASE), + .end = (u32) (USB_H1REGS_BASE + 0x1ff), + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = MXC_INT_USB_H1, + .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-mx51/usb_h2.c b/arch/arm/mach-mx51/usb_h2.c new file mode 100644 index 000000000000..90de5a28733f --- /dev/null +++ b/arch/arm/mach-mx51/usb_h2.c @@ -0,0 +1,91 @@ +/* + * 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/delay.h> +#include <linux/platform_device.h> +#include <linux/fsl_devices.h> +#include <asm/mach-types.h> +#include <mach/arc_otg.h> +#include "usb.h" +#include "iomux.h" + +/* + * USB Host2 HS port + */ +static int gpio_usbh2_active(void) +{ + /* Set USBH2_STP to GPIO and toggle it */ + mxc_request_iomux(MX51_PIN_EIM_A26, IOMUX_CONFIG_GPIO); + gpio_request(IOMUX_TO_GPIO(MX51_PIN_EIM_A26), "eim_a26"); + gpio_direction_output(IOMUX_TO_GPIO(MX51_PIN_EIM_A26), 0); + gpio_set_value(IOMUX_TO_GPIO(MX51_PIN_EIM_A26), 1); + + msleep(100); + + return 0; +} + +void gpio_usbh2_setback_stp(void) +{ + /* setback USBH2_STP to be function */ + mxc_request_iomux(MX51_PIN_EIM_A26, IOMUX_CONFIG_ALT2); +} +EXPORT_SYMBOL(gpio_usbh2_setback_stp); + +static void gpio_usbh2_inactive(void) +{ + gpio_free(IOMUX_TO_GPIO(MX51_PIN_EIM_A26)); + mxc_free_iomux(MX51_PIN_EIM_A26, IOMUX_CONFIG_GPIO); +} + +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_USB_H2, + .flags = IORESOURCE_IRQ, + }, +}; + +static int __init usbh2_init(void) +{ + pr_debug("%s: \n", __func__); + + if (machine_is_mx51_3ds() || + (machine_is_mx51_babbage() && (cpu_is_mx51_rev(CHIP_REV_2_0) >= 1))) + return 0; + + host_pdev_register(usbh2_resources, ARRAY_SIZE(usbh2_resources), + &usbh2_config); + return 0; +} + +module_init(usbh2_init); + diff --git a/arch/arm/mach-mx51/wfi.S b/arch/arm/mach-mx51/wfi.S new file mode 100644 index 000000000000..559669611b6a --- /dev/null +++ b/arch/arm/mach-mx51/wfi.S @@ -0,0 +1,427 @@ +/* + * Copyright 2008-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/linkage.h> + +#define ARM_CTRL_DCACHE 1 << 2 +#define ARM_AUXCR_L2EN 1 << 1 +/* + * cpu_cortexa8_do_idle() + * + * Idle the processor (eg, wait for interrupt). + * + * IRQs are already disabled. + */ +ENTRY(cpu_cortexa8_do_idle) + + mrc p15, 0, r1, c1, c0, 1 @ R1 = auxiliary control reg + ands r2, r1, #ARM_AUXCR_L2EN @ Check if L2 is disabled + beq SkipL2Access + + mrc p15, 0, r2, c1, c0, 0 @ R2 = system control reg + bic r2, r2, #ARM_CTRL_DCACHE @ Disable DCache + mcr p15, 0, r2, c1, c0, 0 @ Update system control reg + + bic r1, r1, #ARM_AUXCR_L2EN @ Disable L2 cache + mcr p15, 0, r1, c1, c0, 1 @ Update aux control reg + + ldr r1, =(0x0 << 6) @ A[6] = 0 + mcr p15, 0, r1, c15, c9, 2 @ Read L2 tag RAM into L2 data 0 register + mrc p15, 0, r2, c15, c8, 0 @ Move L2 data 0 register to R2 + str r2, [r0, #0x00] @ Save tag info + + ldr r1, =(0x1 << 6) @ A[6] = 1 + mcr p15, 0, r1, c15, c9, 2 @ Read L2 tag RAM into L2 data 0 register + mrc p15, 0, r2, c15, c8, 0 @ Move L2 data 0 register to R2 + str r2, [r0, #0x04] @ Save tag info + + ldr r1, =(0x0 << 3) @ A[6:3] = b0000 + mcr p15, 0, r1, c15, c9, 3 @ Read L2 Data RAM into L2 data 0-2 register + mrc p15, 0, r2, c15, c8, 0 @ Move L2 data 0 register to R2 + str r2, [r0, #0x08] @ Store data info + mrc p15, 0, r2, c15, c8, 1 @ Move L2 data 1 register to R2 + str r2, [r0, #0x0C] @ Store data info + mrc p15, 0, r2, c15, c8, 5 @ Move L2 data 2 register to R2 + str r2, [r0, #0x10] @ Store data info + + ldr r1, =(0x1 << 3) @ A[6:3] = b0001 + mcr p15, 0, r1, c15, c9, 3 @ Read L2 Data RAM into L2 data 0-2 register + mrc p15, 0, r2, c15, c8, 0 @ Move L2 data 0 register to R2 + str r2, [r0, #0x14] @ Store data info + mrc p15, 0, r2, c15, c8, 1 @ Move L2 data 1 register to R2 + str r2, [r0, #0x18] @ Store data info + mrc p15, 0, r2, c15, c8, 5 @ Move L2 data 2 register to R2 + str r2, [r0, #0x1C] @ Store data info + + ldr r1, =(0x2 << 3) @ A[6:3] = b0010 + mcr p15, 0, r1, c15, c9, 3 @ Read L2 Data RAM into L2 data 0-2 register + mrc p15, 0, r2, c15, c8, 0 @ Move L2 data 0 register to R2 + str r2, [r0, #0x20] @ Store data info + mrc p15, 0, r2, c15, c8, 1 @ Move L2 data 1 register to R2 + str r2, [r0, #0x24] @ Store data info + mrc p15, 0, r2, c15, c8, 5 @ Move L2 data 2 register to R2 + str r2, [r0, #0x28] @ Store data info + + ldr r1, =(0x3 << 3) @ A[6:3] = b0011 + mcr p15, 0, r1, c15, c9, 3 @ Read L2 Data RAM into L2 data 0-2 register + mrc p15, 0, r2, c15, c8, 0 @ Move L2 data 0 register to R2 + str r2, [r0, #0x2C] @ Store data info + mrc p15, 0, r2, c15, c8, 1 @ Move L2 data 1 register to R2 + str r2, [r0, #0x30] @ Store data info + mrc p15, 0, r2, c15, c8, 5 @ Move L2 data 2 register to R2 + str r2, [r0, #0x34] @ Store data info + + ldr r1, =(0x4 << 3) @ A[6:3] = b0100 + mcr p15, 0, r1, c15, c9, 3 @ Read L2 Data RAM into L2 data 0-2 register + mrc p15, 0, r2, c15, c8, 0 @ Move L2 data 0 register to R2 + str r2, [r0, #0x38] @ Store data info + mrc p15, 0, r2, c15, c8, 1 @ Move L2 data 1 register to R2 + str r2, [r0, #0x3C] @ Store data info + mrc p15, 0, r2, c15, c8, 5 @ Move L2 data 2 register to R2 + str r2, [r0, #0x40] @ Store data info + + ldr r1, =(0x5 << 3) @ A[6:3] = b0101 + mcr p15, 0, r1, c15, c9, 3 @ Read L2 Data RAM into L2 data 0-2 register + mrc p15, 0, r2, c15, c8, 0 @ Move L2 data 0 register to R2 + str r2, [r0, #0x44] @ Store data info + mrc p15, 0, r2, c15, c8, 1 @ Move L2 data 1 register to R2 + str r2, [r0, #0x48] @ Store data info + mrc p15, 0, r2, c15, c8, 5 @ Move L2 data 2 register to R2 + str r2, [r0, #0x4C] @ Store data info + + ldr r1, =(0x6 << 3) @ A[6:3] = b0110 + mcr p15, 0, r1, c15, c9, 3 @ Read L2 Data RAM into L2 data 0-2 register + mrc p15, 0, r2, c15, c8, 0 @ Move L2 data 0 register to R2 + str r2, [r0, #0x50] @ Store data info + mrc p15, 0, r2, c15, c8, 1 @ Move L2 data 1 register to R2 + str r2, [r0, #0x54] @ Store data info + mrc p15, 0, r2, c15, c8, 5 @ Move L2 data 2 register to R2 + str r2, [r0, #0x58] @ Store data info + + ldr r1, =(0x7 << 3) @ A[6:3] = b0111 + mcr p15, 0, r1, c15, c9, 3 @ Read L2 Data RAM into L2 data 0-2 register + mrc p15, 0, r2, c15, c8, 0 @ Move L2 data 0 register to R2 + str r2, [r0, #0x5C] @ Store data info + mrc p15, 0, r2, c15, c8, 1 @ Move L2 data 1 register to R2 + str r2, [r0, #0x60] @ Store data info + mrc p15, 0, r2, c15, c8, 5 @ Move L2 data 2 register to R2 + str r2, [r0, #0x64] @ Store data info + + ldr r1, =(0x8 << 3) @ A[6:3] = b1000 + mcr p15, 0, r1, c15, c9, 3 @ Read L2 Data RAM into L2 data 0-2 register + mrc p15, 0, r2, c15, c8, 0 @ Move L2 data 0 register to R2 + str r2, [r0, #0x68] @ Store data info + mrc p15, 0, r2, c15, c8, 1 @ Move L2 data 1 register to R2 + str r2, [r0, #0x6C] @ Store data info + mrc p15, 0, r2, c15, c8, 5 @ Move L2 data 2 register to R2 + str r2, [r0, #0x70] @ Store data info + + ldr r1, =(0x9 << 3) @ A[6:3] = b1001 + mcr p15, 0, r1, c15, c9, 3 @ Read L2 Data RAM into L2 data 0-2 register + mrc p15, 0, r2, c15, c8, 0 @ Move L2 data 0 register to R2 + str r2, [r0, #0x74] @ Store data info + mrc p15, 0, r2, c15, c8, 1 @ Move L2 data 1 register to R2 + str r2, [r0, #0x78] @ Store data info + mrc p15, 0, r2, c15, c8, 5 @ Move L2 data 2 register to R2 + str r2, [r0, #0x7C] @ Store data info + + ldr r1, =(0xA << 3) @ A[6:3] = b1010 + mcr p15, 0, r1, c15, c9, 3 @ Read L2 Data RAM into L2 data 0-2 register + mrc p15, 0, r2, c15, c8, 0 @ Move L2 data 0 register to R2 + str r2, [r0, #0x80] @ Store data info + mrc p15, 0, r2, c15, c8, 1 @ Move L2 data 1 register to R2 + str r2, [r0, #0x84] @ Store data info + mrc p15, 0, r2, c15, c8, 5 @ Move L2 data 2 register to R2 + str r2, [r0, #0x88] @ Store data info + + ldr r1, =(0xB << 3) @ A[6:3] = b1011 + mcr p15, 0, r1, c15, c9, 3 @ Read L2 Data RAM into L2 data 0-2 register + mrc p15, 0, r2, c15, c8, 0 @ Move L2 data 0 register to R2 + str r2, [r0, #0x8C] @ Store data info + mrc p15, 0, r2, c15, c8, 1 @ Move L2 data 1 register to R2 + str r2, [r0, #0x90] @ Store data info + mrc p15, 0, r2, c15, c8, 5 @ Move L2 data 2 register to R2 + str r2, [r0, #0x94] @ Store data info + + ldr r1, =(0xC << 3) @ A[6:3] = b1100 + mcr p15, 0, r1, c15, c9, 3 @ Read L2 Data RAM into L2 data 0-2 register + mrc p15, 0, r2, c15, c8, 0 @ Move L2 data 0 register to R2 + str r2, [r0, #0x98] @ Store data info + mrc p15, 0, r2, c15, c8, 1 @ Move L2 data 1 register to R2 + str r2, [r0, #0x9C] @ Store data info + mrc p15, 0, r2, c15, c8, 5 @ Move L2 data 2 register to R2 + str r2, [r0, #0xA0] @ Store data info + + ldr r1, =(0xD << 3) @ A[6:3] = b1101 + mcr p15, 0, r1, c15, c9, 3 @ Read L2 Data RAM into L2 data 0-2 register + mrc p15, 0, r2, c15, c8, 0 @ Move L2 data 0 register to R2 + str r2, [r0, #0xA4] @ Store data info + mrc p15, 0, r2, c15, c8, 1 @ Move L2 data 1 register to R2 + str r2, [r0, #0xA8] @ Store data info + mrc p15, 0, r2, c15, c8, 5 @ Move L2 data 2 register to R2 + str r2, [r0, #0xAC] @ Store data info + + ldr r1, =(0xE << 3) @ A[6:3] = b1110 + mcr p15, 0, r1, c15, c9, 3 @ Read L2 Data RAM into L2 data 0-2 register + mrc p15, 0, r2, c15, c8, 0 @ Move L2 data 0 register to R2 + str r2, [r0, #0xB0] @ Store data info + mrc p15, 0, r2, c15, c8, 1 @ Move L2 data 1 register to R2 + str r2, [r0, #0xB4] @ Store data info + mrc p15, 0, r2, c15, c8, 5 @ Move L2 data 2 register to R2 + str r2, [r0, #0xB8] @ Store data info + + ldr r1, =(0xF << 3) @ A[6:3] = b1111 + mcr p15, 0, r1, c15, c9, 3 @ Read L2 Data RAM into L2 data 0-2 register + mrc p15, 0, r2, c15, c8, 0 @ Move L2 data 0 register to R2 + str r2, [r0, #0xBC] @ Store data info + mrc p15, 0, r2, c15, c8, 1 @ Move L2 data 1 register to R2 + str r2, [r0, #0xC0] @ Store data info + mrc p15, 0, r2, c15, c8, 5 @ Move L2 data 2 register to R2 + str r2, [r0, #0xC4] @ Store data info + + ldr r1, =(0x2 << 29) | (0x0 << 6) @ WAY = A[31:29] = 2, A[6] = 0 + mcr p15, 0, r1, c15, c9, 2 @ Read L2 tag RAM into L2 data 0 register + mrc p15, 0, r2, c15, c8, 0 @ Move L2 data 0 register to R2 + str r2, [r0, #0xC8] @ Save tag info + + ldr r1, =(0x2 << 29) | (0x1 << 6) @ WAY = A[31:29] = 2, A[6] = 1 + mcr p15, 0, r1, c15, c9, 2 @ Read L2 tag RAM into L2 data 0 register + mrc p15, 0, r2, c15, c8, 0 @ Move L2 data 0 register to R2 + str r2, [r0, #0xCC] @ Save tag info + + ldr r1, =(0x4 << 29) | (0x0 << 6) @ WAY = A[31:29] = 4, A[6] = 0 + mcr p15, 0, r1, c15, c9, 2 @ Read L2 tag RAM into L2 data 0 register + mrc p15, 0, r2, c15, c8, 0 @ Move L2 data 0 register to R2 + str r2, [r0, #0xD0] @ Save tag info + + ldr r1, =(0x4 << 29) | (0x1 << 6) @ WAY = A[31:29] = 4, A[6] = 1 + mcr p15, 0, r1, c15, c9, 2 @ Read L2 tag RAM into L2 data 0 register + mrc p15, 0, r2, c15, c8, 0 @ Move L2 data 0 register to R2 + str r2, [r0, #0xD4] @ Save tag info + + ldr r1, =(0x6 << 29) | (0x0 << 6) @ WAY = A[31:29] = 6, A[6] = 0 + mcr p15, 0, r1, c15, c9, 2 @ Read L2 tag RAM into L2 data 0 register + mrc p15, 0, r2, c15, c8, 0 @ Move L2 data 0 register to R2 + str r2, [r0, #0xD8] @ Save tag info + + ldr r1, =(0x6 << 29) | (0x1 << 6) @ WAY = A[31:29] = 6, A[6] = 1 + mcr p15, 0, r1, c15, c9, 2 @ Read L2 tag RAM into L2 data 0 register + mrc p15, 0, r2, c15, c8, 0 @ Move L2 data 0 register to R2 + str r2, [r0, #0xDC] @ Save tag info + + .long 0xe320f003 @ Opcode for WFI + + ldr r1, =(0x0 << 6) @ A[6] = 0 + ldr r2, [r0, #0x00] @ Load tag info + mcr p15, 0, r2, c15, c8, 0 @ Move R2 to L2 data 0 register + mcr p15, 0, r1, c15, c8, 2 @ Write L2 data 0 register to L2 tag RAM + + ldr r1, =(0x1 << 6) @ A[6] = 1 + ldr r2, [r0, #0x04] @ Load tag info + mcr p15, 0, r2, c15, c8, 0 @ Move R2 to L2 data 0 register + mcr p15, 0, r1, c15, c8, 2 @ Write L2 data 0 register to L2 tag RAM + + ldr r1, =(0x0 << 3) @ A[6:3] = b0000 + ldr r2, [r0, #0x08] @ Load data info + mcr p15, 0, r2, c15, c8, 0 @ Move R2 to L2 data 0 register + ldr r2, [r0, #0x0C] @ Load data info + mcr p15, 0, r2, c15, c8, 1 @ Move R2 to L2 data 1 register + ldr r2, [r0, #0x10] @ Load data info + mcr p15, 0, r2, c15, c8, 5 @ Move R2 to L2 data 2 register + mcr p15, 0, r1, c15, c8, 3 @ Write L2 data 0-2 registers to L2 data RAM + + ldr r1, =(0x1 << 3) @ A[6:3] = b0001 + ldr r2, [r0, #0x14] @ Load data info + mcr p15, 0, r2, c15, c8, 0 @ Move R2 to L2 data 0 register + ldr r2, [r0, #0x18] @ Load data info + mcr p15, 0, r2, c15, c8, 1 @ Move R2 to L2 data 1 register + ldr r2, [r0, #0x1C] @ Load data info + mcr p15, 0, r2, c15, c8, 5 @ Move R2 to L2 data 2 register + mcr p15, 0, r1, c15, c8, 3 @ Write L2 data 0-2 registers to L2 data RAM + + ldr r1, =(0x2 << 3) @ A[6:3] = b0010 + ldr r2, [r0, #0x20] @ Load data info + mcr p15, 0, r2, c15, c8, 0 @ Move R2 to L2 data 0 register + ldr r2, [r0, #0x24] @ Load data info + mcr p15, 0, r2, c15, c8, 1 @ Move R2 to L2 data 1 register + ldr r2, [r0, #0x28] @ Load data info + mcr p15, 0, r2, c15, c8, 5 @ Move R2 to L2 data 2 register + mcr p15, 0, r1, c15, c8, 3 @ Write L2 data 0-2 registers to L2 data RAM + + ldr r1, =(0x3 << 3) @ A[6:3] = b0011 + ldr r2, [r0, #0x2C] @ Load data info + mcr p15, 0, r2, c15, c8, 0 @ Move R2 to L2 data 0 register + ldr r2, [r0, #0x30] @ Load data info + mcr p15, 0, r2, c15, c8, 1 @ Move R2 to L2 data 1 register + ldr r2, [r0, #0x34] @ Load data info + mcr p15, 0, r2, c15, c8, 5 @ Move R2 to L2 data 2 register + mcr p15, 0, r1, c15, c8, 3 @ Write L2 data 0-2 registers to L2 data RAM + + ldr r1, =(0x4 << 3) @ A[6:3] = b0100 + ldr r2, [r0, #0x38] @ Load data info + mcr p15, 0, r2, c15, c8, 0 @ Move R2 to L2 data 0 register + ldr r2, [r0, #0x3C] @ Load data info + mcr p15, 0, r2, c15, c8, 1 @ Move R2 to L2 data 1 register + ldr r2, [r0, #0x40] @ Load data info + mcr p15, 0, r2, c15, c8, 5 @ Move R2 to L2 data 2 register + mcr p15, 0, r1, c15, c8, 3 @ Write L2 data 0-2 registers to L2 data RAM + + ldr r1, =(0x5 << 3) @ A[6:3] = b0101 + ldr r2, [r0, #0x44] @ Load data info + mcr p15, 0, r2, c15, c8, 0 @ Move R2 to L2 data 0 register + ldr r2, [r0, #0x48] @ Load data info + mcr p15, 0, r2, c15, c8, 1 @ Move R2 to L2 data 1 register + ldr r2, [r0, #0x4C] @ Load data info + mcr p15, 0, r2, c15, c8, 5 @ Move R2 to L2 data 2 register + mcr p15, 0, r1, c15, c8, 3 @ Write L2 data 0-2 registers to L2 data RAM + + ldr r1, =(0x6 << 3) @ A[6:3] = b0110 + ldr r2, [r0, #0x50] @ Load data info + mcr p15, 0, r2, c15, c8, 0 @ Move R2 to L2 data 0 register + ldr r2, [r0, #0x54] @ Load data info + mcr p15, 0, r2, c15, c8, 1 @ Move R2 to L2 data 1 register + ldr r2, [r0, #0x58] @ Load data info + mcr p15, 0, r2, c15, c8, 5 @ Move R2 to L2 data 2 register + mcr p15, 0, r1, c15, c8, 3 @ Write L2 data 0-2 registers to L2 data RAM + + ldr r1, =(0x7 << 3) @ A[6:3] = b0111 + ldr r2, [r0, #0x5C] @ Load data info + mcr p15, 0, r2, c15, c8, 0 @ Move R2 to L2 data 0 register + ldr r2, [r0, #0x60] @ Load data info + mcr p15, 0, r2, c15, c8, 1 @ Move R2 to L2 data 1 register + ldr r2, [r0, #0x64] @ Load data info + mcr p15, 0, r2, c15, c8, 5 @ Move R2 to L2 data 2 register + mcr p15, 0, r1, c15, c8, 3 @ Write L2 data 0-2 registers to L2 data RAM + + ldr r1, =(0x8 << 3) @ A[6:3] = b1000 + ldr r2, [r0, #0x68] @ Load data info + mcr p15, 0, r2, c15, c8, 0 @ Move R2 to L2 data 0 register + ldr r2, [r0, #0x6C] @ Load data info + mcr p15, 0, r2, c15, c8, 1 @ Move R2 to L2 data 1 register + ldr r2, [r0, #0x70] @ Load data info + mcr p15, 0, r2, c15, c8, 5 @ Move R2 to L2 data 2 register + mcr p15, 0, r1, c15, c8, 3 @ Write L2 data 0-2 registers to L2 data RAM + + ldr r1, =(0x9 << 3) @ A[6:3] = b1001 + ldr r2, [r0, #0x74] @ Load data info + mcr p15, 0, r2, c15, c8, 0 @ Move R2 to L2 data 0 register + ldr r2, [r0, #0x78] @ Load data info + mcr p15, 0, r2, c15, c8, 1 @ Move R2 to L2 data 1 register + ldr r2, [r0, #0x7C] @ Load data info + mcr p15, 0, r2, c15, c8, 5 @ Move R2 to L2 data 2 register + mcr p15, 0, r1, c15, c8, 3 @ Write L2 data 0-2 registers to L2 data RAM + + ldr r1, =(0xA << 3) @ A[6:3] = b1010 + ldr r2, [r0, #0x80] @ Load data info + mcr p15, 0, r2, c15, c8, 0 @ Move R2 to L2 data 0 register + ldr r2, [r0, #0x84] @ Load data info + mcr p15, 0, r2, c15, c8, 1 @ Move R2 to L2 data 1 register + ldr r2, [r0, #0x88] @ Load data info + mcr p15, 0, r2, c15, c8, 5 @ Move R2 to L2 data 2 register + mcr p15, 0, r1, c15, c8, 3 @ Write L2 data 0-2 registers to L2 data RAM + + ldr r1, =(0xB << 3) @ A[6:3] = b1011 + ldr r2, [r0, #0x8C] @ Load data info + mcr p15, 0, r2, c15, c8, 0 @ Move R2 to L2 data 0 register + ldr r2, [r0, #0x90] @ Load data info + mcr p15, 0, r2, c15, c8, 1 @ Move R2 to L2 data 1 register + ldr r2, [r0, #0x94] @ Load data info + mcr p15, 0, r2, c15, c8, 5 @ Move R2 to L2 data 2 register + mcr p15, 0, r1, c15, c8, 3 @ Write L2 data 0-2 registers to L2 data RAM + + ldr r1, =(0xC << 3) @ A[6:3] = b1100 + ldr r2, [r0, #0x98] @ Load data info + mcr p15, 0, r2, c15, c8, 0 @ Move R2 to L2 data 0 register + ldr r2, [r0, #0x9C] @ Load data info + mcr p15, 0, r2, c15, c8, 1 @ Move R2 to L2 data 1 register + ldr r2, [r0, #0xA0] @ Load data info + mcr p15, 0, r2, c15, c8, 5 @ Move R2 to L2 data 2 register + mcr p15, 0, r1, c15, c8, 3 @ Write L2 data 0-2 registers to L2 data RAM + + ldr r1, =(0xD << 3) @ A[6:3] = b1101 + ldr r2, [r0, #0xA4] @ Load data info + mcr p15, 0, r2, c15, c8, 0 @ Move R2 to L2 data 0 register + ldr r2, [r0, #0xA8] @ Load data info + mcr p15, 0, r2, c15, c8, 1 @ Move R2 to L2 data 1 register + ldr r2, [r0, #0xAC] @ Load data info + mcr p15, 0, r2, c15, c8, 5 @ Move R2 to L2 data 2 register + mcr p15, 0, r1, c15, c8, 3 @ Write L2 data 0-2 registers to L2 data RAM + + ldr r1, =(0xE << 3) @ A[6:3] = b1110 + ldr r2, [r0, #0xB0] @ Load data info + mcr p15, 0, r2, c15, c8, 0 @ Move R2 to L2 data 0 register + ldr r2, [r0, #0xB4] @ Load data info + mcr p15, 0, r2, c15, c8, 1 @ Move R2 to L2 data 1 register + ldr r2, [r0, #0xB8] @ Load data info + mcr p15, 0, r2, c15, c8, 5 @ Move R2 to L2 data 2 register + mcr p15, 0, r1, c15, c8, 3 @ Write L2 data 0-2 registers to L2 data RAM + + ldr r1, =(0xF << 3) @ A[6:3] = b1111 + ldr r2, [r0, #0xBC] @ Load data info + mcr p15, 0, r2, c15, c8, 0 @ Move R2 to L2 data 0 register + ldr r2, [r0, #0xC0] @ Load data info + mcr p15, 0, r2, c15, c8, 1 @ Move R2 to L2 data 1 register + ldr r2, [r0, #0xC4] @ Load data info + mcr p15, 0, r2, c15, c8, 5 @ Move R2 to L2 data 2 register + mcr p15, 0, r1, c15, c8, 3 @ Write L2 data 0-2 registers to L2 data RAM + + ldr r1, =(0x2 << 29) | (0x0 << 6) @ WAY = A[31:29] = 2, A[6] = 0 + ldr r2, [r0, #0xC8] @ Load tag info + mcr p15, 0, r2, c15, c8, 0 @ Move R2 to L2 data 0 register + mcr p15, 0, r1, c15, c8, 2 @ Write L2 data 0 register to L2 tag RAM + + ldr r1, =(0x2 << 29) | (0x1 << 6) @ WAY = A[31:29] = 2, A[6] = 1 + ldr r2, [r0, #0xCC] @ Load tag info + mcr p15, 0, r2, c15, c8, 0 @ Move R2 to L2 data 0 register + mcr p15, 0, r1, c15, c8, 2 @ Write L2 data 0 register to L2 tag RAM + + ldr r1, =(0x4 << 29) | (0x0 << 6) @ WAY = A[31:29] = 4, A[6] = 0 + ldr r2, [r0, #0xD0] @ Load tag info + mcr p15, 0, r2, c15, c8, 0 @ Move R2 to L2 data 0 register + mcr p15, 0, r1, c15, c8, 2 @ Write L2 data 0 register to L2 tag RAM + + ldr r1, =(0x4 << 29) | (0x1 << 6) @ WAY = A[31:29] = 4, A[6] = 1 + ldr r2, [r0, #0xD4] @ Load tag info + mcr p15, 0, r2, c15, c8, 0 @ Move R2 to L2 data 0 register + mcr p15, 0, r1, c15, c8, 2 @ Write L2 data 0 register to L2 tag RAM + + ldr r1, =(0x6 << 29) | (0x0 << 6) @ WAY = A[31:29] = 6, A[6] = 0 + ldr r2, [r0, #0xD8] @ Load tag info + mcr p15, 0, r2, c15, c8, 0 @ Move R2 to L2 data 0 register + mcr p15, 0, r1, c15, c8, 2 @ Write L2 data 0 register to L2 tag RAM + + ldr r1, =(0x6 << 29) | (0x1 << 6) @ WAY = A[31:29] = 6, A[6] = 1 + ldr r2, [r0, #0xDC] @ Load tag info + mcr p15, 0, r2, c15, c8, 0 @ Move R2 to L2 data 0 register + mcr p15, 0, r1, c15, c8, 2 @ Write L2 data 0 register to L2 tag RAM + + mrc p15, 0, r1, c1, c0, 1 @ R1 = auxiliary control reg + orr r1, r1, #ARM_AUXCR_L2EN @ Enable L2 cache + mcr p15, 0, r1, c1, c0, 1 @ Update aux control reg + + mrc p15, 0, r2, c1, c0, 0 @ R2 = system control reg + orr r2, r2, #ARM_CTRL_DCACHE @ Enable DCache + mcr p15, 0, r2, c1, c0, 0 @ Update system control reg + + b Done + +SkipL2Access: + .long 0xe320f003 @ Opcode for WFI + +Done: + mov pc, lr + + .type cortexa8_idle_workaround, #object +ENTRY(cortexa8_idle_workaround) + .word cpu_cortexa8_do_idle + .size cortexa8_idle_workaround, . - cortexa8_idle_workaround + |