diff options
Diffstat (limited to 'arch/arm/mach-mx35')
29 files changed, 11054 insertions, 0 deletions
diff --git a/arch/arm/mach-mx35/Kconfig b/arch/arm/mach-mx35/Kconfig new file mode 100644 index 000000000000..6fdc1dd45919 --- /dev/null +++ b/arch/arm/mach-mx35/Kconfig @@ -0,0 +1,111 @@ +menu "MX35 Options" + depends on ARCH_MX35 + +config FORCE_MAX_ZONEORDER + int "MAX_ORDER" + default "13" + +config MX35_OPTIONS + bool + default y + select CPU_V6 + select ARM_ERRATA_364296 + select ARM_ERRATA_411920 + select CACHE_L2X0 + select OUTER_CACHE + select USB_ARCH_HAS_EHCI + select ARCH_HAS_EVTMON + select ARCH_HAS_RNGC + +config MACH_MX35_3DS + bool "Support MX35 3STACK platforms" + default y + select MXC_PSEUDO_IRQS if MXC_PMIC_MC9SDZ60 + help + Include support for MX35 3STACK platform. This includes specific + configurations for the board and its peripherals. + +config MACH_MX35EVB + bool "Support MX35EVB platforms" + default n + help + Include support for MX35EVB platform. This includes specific + configurations for the board and its peripherals. + +config MX35_DOZE_DURING_IDLE + bool "Enter Doze mode during idle" + help + Turning on this option will put the CPU into Doze mode during idle. + The default is to enter Wait mode during idle. Doze mode during + idle will save additional power over Wait mode. + +config MXC_SDMA_API + bool "Use SDMA API" + default y + help + This selects the Freescale MXC SDMA API. + 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 + +config ARCH_MXC_HAS_NFC_V2 + bool "MXC NFC Hardware Version 2" + depends on ARCH_MX35 + default y + help + This selects the Freescale MXC Nand Flash Controller Hardware Version 3 + If unsure, say N. + +config ARCH_MXC_HAS_NFC_V2_1 + bool "MXC NFC Hardware Version 2.1" + depends on ARCH_MXC_HAS_NFC_V2 + default y + help + This selects the Freescale MXC Nand Flash Controller Hardware Version 2.1 + If unsure, say N. + +menu "Device options" + +config I2C_MXC_SELECT1 + bool "Enable I2C1 module" + default y + depends on I2C_MXC + help + Enable MX35 I2C1 module. + +config I2C_MXC_SELECT2 + bool "Enable I2C2 module" + default n + depends on I2C_MXC + help + Enable MX35 I2C2 module. + +config I2C_MXC_SELECT3 + bool "Enable I2C3 module" + default n + depends on I2C_MXC + help + Enable MX35 I2C3 module. + +endmenu + +config MXC_PSEUDO_IRQS + bool + +endmenu diff --git a/arch/arm/mach-mx35/Makefile b/arch/arm/mach-mx35/Makefile new file mode 100644 index 000000000000..39b152d9ad21 --- /dev/null +++ b/arch/arm/mach-mx35/Makefile @@ -0,0 +1,19 @@ +# +# Makefile for the linux kernel. +# + +# Object file lists. + +obj-y := system.o iomux.o cpu.o mm.o clock.o devices.o serial.o +obj-$(CONFIG_MXC_SDMA_API) += dma.o +obj-$(CONFIG_MACH_MX35_3DS) += mx35_3stack.o mx35_3stack_gpio.o mx35_3stack_cpld.o dvfs.o mx35_3stack_pmic_mc13892.o mx35_3stack_pmic_mc9s08dz60.o +obj-$(CONFIG_MACH_MX35EVB) += mx35evb.o mx35evb_cpld.o mx35evb_gpio.o + +obj-$(CONFIG_MXC_PSEUDO_IRQS) += mx35_3stack_irq.o +obj-$(CONFIG_PM) += pm.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-mx35/Makefile.boot b/arch/arm/mach-mx35/Makefile.boot new file mode 100644 index 000000000000..198d92d5e463 --- /dev/null +++ b/arch/arm/mach-mx35/Makefile.boot @@ -0,0 +1,9 @@ +ifeq ($(CONFIG_MACH_MX35EVB), y) + zreladdr-y := 0x90008000 +params_phys-y := 0x90000100 +initrd_phys-y := 0x90800000 +else + zreladdr-y := 0x80008000 +params_phys-y := 0x80000100 +initrd_phys-y := 0x80800000 +endif diff --git a/arch/arm/mach-mx35/board-mx35_3stack.h b/arch/arm/mach-mx35/board-mx35_3stack.h new file mode 100644 index 000000000000..231ea5af91a3 --- /dev/null +++ b/arch/arm/mach-mx35/board-mx35_3stack.h @@ -0,0 +1,200 @@ +/* + * 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_MX35_3STACK_H__ +#define __ASM_ARCH_MXC_BOARD_MX35_3STACK_H__ + +#ifdef CONFIG_MACH_MX35_3DS + +/*! + * @defgroup BRDCFG_MX35 Board Configuration Options + * @ingroup MSL_MX35 + */ + +/*! + * @file mach-mx35/board-mx35_3stack.h + * + * @brief This file contains all the board level configuration options. + * + * It currently hold the options defined for MX35 3STACK Platform. + * + * @ingroup BRDCFG_MX35 + */ + +/* + * Include Files + */ +#include <mach/mxc_uart.h> + +/*! + * @name MXC UART EVB board level configurations + */ +/*! @{ */ +/*! + * Specifies if the Irda transmit path is inverting + */ +#define MXC_IRDA_TX_INV 0 +/*! + * Specifies if the Irda receive path is inverting + */ +#define MXC_IRDA_RX_INV 0 + +/* UART 1 configuration */ +/*! + * This define specifies if the UART port is configured to be in DTE or + * DCE mode. There exists a define like this for each UART port. Valid + * values that can be used are \b MODE_DTE or \b MODE_DCE. + */ +#define UART1_MODE MODE_DCE +/*! + * This define specifies if the UART is to be used for IRDA. There exists a + * define like this for each UART port. Valid values that can be used are + * \b IRDA or \b NO_IRDA. + */ +#define UART1_IR NO_IRDA +/*! + * This define is used to enable or disable a particular UART port. If + * disabled, the UART will not be registered in the file system and the user + * will not be able to access it. There exists a define like this for each UART + * port. Specify a value of 1 to enable the UART and 0 to disable it. + */ +#define UART1_ENABLED 1 +/*! @} */ +/* UART 2 configuration */ +#define UART2_MODE MODE_DTE +#define UART2_IR NO_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) + +#define MXC_PSEUDO_PARENT MXC_INT_FORCE + +enum { + MCU_INT_HEADPHONE = 0, + MCU_INT_GPS, + MCU_INT_SD1_CD, + MCU_INT_SD1_WP, + MCU_INT_SD2_CD, + MCU_INT_SD2_WP, + MCU_INT_POWER_KEY, + MCU_INT_RTC, + MCU_INT_TS_ADC, + MCU_INT_KEYPAD, +}; + +#define MXC_PSEUDO_IRQ_HEADPHONE (MXC_PSEUDO_IO_BASE + MCU_INT_HEADPHONE) +#define MXC_PSEUDO_IRQ_GPS (MXC_PSEUDO_IO_BASE + MCU_INT_GPS) +#define MXC_PSEUDO_IRQ_SD1_CD (MXC_PSEUDO_IO_BASE + MCU_INT_SD1_CD) +#define MXC_PSEUDO_IRQ_SD1_WP (MXC_PSEUDO_IO_BASE + MCU_INT_SD1_WP) +#define MXC_PSEUDO_IRQ_SD2_CD (MXC_PSEUDO_IO_BASE + MCU_INT_SD2_CD) +#define MXC_PSEUDO_IRQ_SD2_WP (MXC_PSEUDO_IO_BASE + MCU_INT_SD2_WP) +#define MXC_PSEUDO_IRQ_POWER_KEY (MXC_PSEUDO_IO_BASE + MCU_INT_POWER_KEY) +#define MXC_PSEUDO_IRQ_KEYPAD (MXC_PSEUDO_IO_BASE + MCU_INT_KEYPAD) +#define MXC_PSEUDO_IRQ_RTC (MXC_PSEUDO_IO_BASE + MCU_INT_RTC) +#define MXC_PSEUDO_IRQ_TS_ADC (MXC_PSEUDO_IO_BASE + MCU_INT_TS_ADC) + +/*! + * @name debug board parameters + */ +/*! @{ */ +/*! + * Base address of debug board + */ +#define DEBUG_BASE_ADDRESS CS5_BASE_ADDR + +/* External ethernet LAN9217 base address */ +#define LAN9217_BASE_ADDR DEBUG_BASE_ADDRESS + +/* External UART */ +#define UARTA_BASE_ADDR (DEBUG_BASE_ADDRESS + 0x08000) +#define UARTB_BASE_ADDR (DEBUG_BASE_ADDRESS + 0x10000) + +#define BOARD_IO_ADDR (DEBUG_BASE_ADDRESS + 0x20000) + +/* LED switchs */ +#define LED_SWITCH_REG 0x00 +/* buttons */ +#define SWITCH_BUTTON_REG 0x08 +/* status, interrupt */ +#define INTR_STATUS_REG 0x10 +#define INTR_RESET_REG 0x20 +/*CPLD configuration*/ +#define CONFIG1_REG 0x28 +#define CONFIG2_REG 0x30 +/*interrupt mask */ +#define INTR_MASK_REG 0x38 + +/* 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 MAGIC3_NUMBER3_REG 0x58 +/* module reset register*/ +#define CONTROL_REG 0x60 +/* CPU ID and Personality ID*/ +#define IDENT_REG 0x68 + +/* For interrupts like xuart, enet etc */ +#define EXPIO_PARENT_INT MX35_PIN_GPIO1_1 + +#define EXPIO_INT_ENET_INT (MXC_BOARD_IRQ_START + 0) +#define EXPIO_INT_XUARTA_INT (MXC_BOARD_IRQ_START + 1) +#define EXPIO_INT_XUARTB_INT (MXC_BOARD_IRQ_START + 2) +#define EXPIO_INT_BUTTONA_INT (MXC_BOARD_IRQ_START + 3) +#define EXPIO_INT_BUTTONB_INT (MXC_BOARD_IRQ_START + 4) + +/*! This is System IRQ used by LAN9217 for interrupt generation taken + * from platform.h + */ +#define LAN9217_IRQ EXPIO_INT_ENET_INT + +/*! This is base virtual address of debug board*/ +extern unsigned int mx35_3stack_board_io; + +#define MXC_BD_LED1 (1) +#define MXC_BD_LED2 (1 << 1) +#define MXC_BD_LED3 (1 << 2) +#define MXC_BD_LED4 (1 << 3) +#define MXC_BD_LED5 (1 << 4) +#define MXC_BD_LED6 (1 << 5) +#define MXC_BD_LED7 (1 << 6) +#define MXC_BD_LED8 (1 << 7) +#define MXC_BD_LED_ON(led) +#define MXC_BD_LED_OFF(led) + +/*! @} */ + +#define AHB_FREQ 133000000 +#define IPG_FREQ 66500000 + +extern void mx35_3stack_gpio_init(void) __init; +extern void gpio_tsc_active(void); +extern void gpio_tsc_inactive(void); +extern unsigned int sdhc_get_card_det_status(struct device *dev); +extern int sdhc_write_protect(struct device *dev); +extern void gpio_can_active(int id); +extern void gpio_can_inactive(int id); +extern struct flexcan_platform_data flexcan_data[]; +extern int __init mx35_3stack_init_mc13892(void); +extern int __init mx35_3stack_init_mc9s08dz60(void); + +#endif /* CONFIG_MACH_MX35_3DS */ +#endif /* __ASM_ARCH_MXC_BOARD_MX35_3STACK_H__ */ diff --git a/arch/arm/mach-mx35/clock.c b/arch/arm/mach-mx35/clock.c new file mode 100644 index 000000000000..5abc3cceba7e --- /dev/null +++ b/arch/arm/mach-mx35/clock.c @@ -0,0 +1,1932 @@ +/* + * 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/spinlock.h> +#include <linux/delay.h> +#include <linux/clk.h> +#include <linux/io.h> +#include <mach/common.h> +#include <mach/hardware.h> +#include <mach/clock.h> +#include <asm/div64.h> + +#include "crm_regs.h" + +#define PRE_DIV_MIN_FREQ 10000000 /* Minimum Frequency after Predivider */ +#define PROPAGATE_RATE_DIS 2 + +struct timer_list dptcen_timer; +static int cpu_curr_wp; +static struct cpu_wp *cpu_wp_tbl; +static int cpu_wp_nr; +static int cpu_wp_offset; + +static struct clk mcu_pll_clk; +static struct clk peri_pll_clk; +static struct clk ipg_clk; +static struct clk ckih_clk; +static struct clk ckie_clk; +static struct clk ahb_clk; +static struct clk cpu_clk; + +#define CLK_CODE(arm, ahb, sel) (((arm) << 16) + ((ahb) << 8) + (sel)) +#define CLK_CODE_ARM(c) (((c) >> 16) & 0xFF) +#define CLK_CODE_AHB(c) (((c) >> 8) & 0xFF) +#define CLK_CODE_PATH(c) ((c) & 0xFF) + +static int __get_arm_div(unsigned long pdr0, int *fi, int *fd); + +static int g_clk_mux_auto[8] = { + CLK_CODE(1, 3, 0), CLK_CODE(1, 2, 1), CLK_CODE(2, 1, 1), -1, + CLK_CODE(1, 6, 0), CLK_CODE(1, 4, 1), CLK_CODE(2, 2, 1), -1, +}; + +static int g_clk_mux_consumer[16] = { + CLK_CODE(1, 4, 0), CLK_CODE(1, 3, 1), CLK_CODE(2, 2, 0), -1, + -1, -1, CLK_CODE(4, 1, 0), CLK_CODE(1, 5, 0), + CLK_CODE(1, 8, 0), CLK_CODE(1, 6, 1), CLK_CODE(2, 4, 0), -1, + -1, -1, CLK_CODE(4, 2, 0), -1, +}; + +static int g_hsp_div_table[3][16] = { + {4, 3, 2, -1, -1, -1, 1, 5, 4, 3, 2, -1, -1, -1, 1, -1}, + {-1, -1, -1, -1, -1, -1, -1, -1, 8, 6, 4, -1, -1, -1, 2, -1}, + {3, -1, -1, -1, -1, -1, -1, -1, 3, -1, -1, -1, -1, -1, -1, -1}, +}; + +static void __calc_dividers(u32 div, u32 *pre, u32 *post, u32 base) +{ + u32 min_pre, temp_pre, old_err, err; + min_pre = (div - 1) / base + 1; + old_err = 8; + for (temp_pre = 8; temp_pre >= min_pre; temp_pre--) { + if (div > (temp_pre * base)) + break; + if (div < (temp_pre * temp_pre)) + continue; + 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; +} + +static void __calc_pre_post_dividers(u32 div, u32 *pre, u32 *post) +{ + if (div >= 512) { + *pre = 8; + *post = 64; + } else if (div >= 64) { + __calc_dividers(div, pre, post, 64); + } else if (div <= 8) { + *pre = div; + *post = 1; + } else { + *pre = 1; + *post = div; + } +} + +static void __calc_two_dividers(u32 div, u32 *pre, u32 *post) +{ + if (div >= 64) { + *pre = *post = 8; + } else if (div > 8) { + __calc_dividers(div, pre, post, 8); + } else { + *pre = 1; + *post = div; + } +} + +static unsigned long _clk_per_post_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 unsigned long _clk_round_rate(struct clk *clk, unsigned long rate) +{ + u32 pre, post; + u32 div = clk->parent->rate / rate; + if (clk->parent->rate % rate) + div++; + + if (cpu_is_mx35_rev(CHIP_REV_2_0) < 1) { + __calc_two_dividers(div, &pre, &post); + return clk->parent->rate / (pre * post); + } else + return clk->parent->rate / div; +} + +static int __switch_cpu_wp(struct clk *clk, unsigned long rate) +{ + int i; + u32 reg_value; + if (cpu_wp_tbl[cpu_curr_wp].cpu_rate < rate) { + for (i = cpu_curr_wp + 2; i < cpu_wp_nr; i += 2) { + if (rate == cpu_wp_tbl[i].cpu_rate) + goto found; + } + return -EINVAL; + } else { + for (i = cpu_curr_wp - 2; i >= 0; i -= 2) { + if (rate == cpu_wp_tbl[i].cpu_rate) + goto found; + } + return -EINVAL; + } + found: + reg_value = __raw_readl(MXC_CCM_PDR0); + reg_value = (reg_value & ~(MXC_CCM_PDR0_CON_MUX_DIV_MASK | + MXC_CCM_PDR0_AUTO_MUX_DIV_MASK)) | + cpu_wp_tbl[i].pdr0_reg; + __raw_writel(reg_value, MXC_CCM_PDR0); + + if (cpu_wp_tbl[i].pll_rate != cpu_wp_tbl[cpu_curr_wp].pll_rate) + clk_set_rate(clk->parent, cpu_wp_tbl[i].pll_rate); + cpu_curr_wp = i; + clk->rate = rate; + return 0; +} + +static int __switch_cpu_rate(struct clk *clk, unsigned long rate) +{ + int prev; + unsigned long tmp; + int arm_div, fi, fd, start, end; + u32 reg_value; + + if (cpu_wp_tbl[cpu_curr_wp].cpu_rate < rate) { + start = cpu_curr_wp + 2; + end = cpu_wp_nr; + prev = cpu_curr_wp; + } else { + start = cpu_wp_offset + 2; + end = cpu_curr_wp; + prev = cpu_wp_offset; + } + while (start < end) { + arm_div = __get_arm_div(cpu_wp_tbl[start].pdr0_reg, &fi, &fd); + tmp = (mcu_pll_clk.rate * fi) / (arm_div * fd); + if (tmp == rate) { + prev = start; + break; + } + if (tmp < rate) { + if (prev < start) + prev = start; + } else { + break; + } + start += 2; + } + if (start >= end) + return -EINVAL; + + if (prev == cpu_curr_wp) + return 0; + + reg_value = __raw_readl(MXC_CCM_PDR0); + reg_value = (reg_value & ~(MXC_CCM_PDR0_CON_MUX_DIV_MASK | + MXC_CCM_PDR0_AUTO_MUX_DIV_MASK)) | + cpu_wp_tbl[prev].pdr0_reg; + __raw_writel(reg_value, MXC_CCM_PDR0); + + cpu_curr_wp = prev; + clk->rate = rate; + return 0; +} + +static int __get_arm_div(unsigned long pdr0, int *fi, int *fd) +{ + int *pclk_mux; + if ((pdr0 & MXC_CCM_PDR0_AUTO_CON) + || (cpu_is_mx35_rev(CHIP_REV_2_0) >= 1)) + pclk_mux = + g_clk_mux_consumer + + ((pdr0 & MXC_CCM_PDR0_CON_MUX_DIV_MASK) >> + MXC_CCM_PDR0_CON_MUX_DIV_OFFSET); + else { + pclk_mux = g_clk_mux_auto + + ((pdr0 & MXC_CCM_PDR0_AUTO_MUX_DIV_MASK) >> + MXC_CCM_PDR0_AUTO_MUX_DIV_OFFSET); + } + + if ((*pclk_mux) == -1) { + BUG(); + return -EINVAL; + } + + if (fi && fd) { + if (!CLK_CODE_PATH(*pclk_mux)) { + *fi = *fd = 1; + return CLK_CODE_ARM(*pclk_mux); + } + if ((pdr0 & MXC_CCM_PDR0_AUTO_CON) + || (cpu_is_mx35_rev(CHIP_REV_2_0) >= 1)) { + *fi = 3; + *fd = 4; + } else { + *fi = 2; + *fd = 3; + } + } + return CLK_CODE_ARM(*pclk_mux); +} + +static int __get_ahb_div(unsigned long pdr0) +{ + int *pclk_mux; + if ((pdr0 & MXC_CCM_PDR0_AUTO_CON) + || (cpu_is_mx35_rev(CHIP_REV_2_0) >= 1)) { + pclk_mux = + g_clk_mux_consumer + + ((pdr0 & MXC_CCM_PDR0_CON_MUX_DIV_MASK) >> + MXC_CCM_PDR0_CON_MUX_DIV_OFFSET); + } else { + pclk_mux = g_clk_mux_auto + + ((pdr0 & MXC_CCM_PDR0_AUTO_MUX_DIV_MASK) >> + MXC_CCM_PDR0_AUTO_MUX_DIV_OFFSET); + } + + if ((*pclk_mux) == -1) { + BUG(); + return -EINVAL; + } + return CLK_CODE_AHB(*pclk_mux); +} + +static void sync_cpu_wb(void) +{ + int i; + struct cpu_wp *p; + unsigned long reg = __raw_readl(MXC_CCM_PDR0); + if ((reg & MXC_CCM_PDR0_AUTO_CON) + || (cpu_is_mx35_rev(CHIP_REV_2_0) >= 1)) { + reg &= MXC_CCM_PDR0_CON_MUX_DIV_MASK; + } else { + reg &= MXC_CCM_PDR0_AUTO_MUX_DIV_MASK; + } + for (i = 0; i < cpu_wp_nr; i++) { + p = cpu_wp_tbl + cpu_curr_wp; + if (p->pdr0_reg == (reg & 0xF0E00)) + break; + cpu_curr_wp = (cpu_curr_wp + 1) % cpu_wp_nr; + } + cpu_wp_offset = cpu_curr_wp & 1; +} + +static int _clk_enable(struct clk *clk) +{ + u32 reg; + reg = __raw_readl(clk->enable_reg); + reg |= 3 << clk->enable_shift; + __raw_writel(reg, clk->enable_reg); + + return 0; +} + +static void _clk_disable(struct clk *clk) +{ + u32 reg; + + reg = __raw_readl(clk->enable_reg); + reg &= ~(3 << clk->enable_shift); + __raw_writel(reg, clk->enable_reg); +} + +static void _clk_emi_disable(struct clk *clk) +{ + u32 reg; + + reg = __raw_readl(clk->enable_reg); + reg &= ~(3 << clk->enable_shift); + reg |= (1 << clk->enable_shift); + __raw_writel(reg, clk->enable_reg); +} + +static int _clk_asrc_enable(struct clk *clk) +{ + u32 reg; + reg = __raw_readl(MXC_CCM_COSR); + __raw_writel(reg | MXC_CCM_COSR_ASRC_AUDIO_EN, MXC_CCM_COSR); + return 0; +} + +static void _clk_asrc_disable(struct clk *clk) +{ + u32 reg; + reg = __raw_readl(MXC_CCM_COSR); + __raw_writel(reg & (~MXC_CCM_COSR_ASRC_AUDIO_EN), MXC_CCM_COSR); +} + +static int _clk_pll_set_rate(struct clk *clk, unsigned long rate) +{ + u32 reg; + signed long pd = 1; /* Pre-divider */ + signed long mfi; /* Multiplication Factor (Integer part) */ + signed long mfn; /* Multiplication Factor (Integer part) */ + signed long mfd; /* Multiplication Factor (Denominator Part) */ + signed long tmp; + u32 ref_freq = clk->parent->rate; + + if ((clk == &mcu_pll_clk) + && (clk->parent->rate == cpu_wp_tbl[cpu_curr_wp].pll_rate)) { + __raw_writel(cpu_wp_tbl[cpu_curr_wp].pll_reg, MXC_CCM_MPCTL); + clk->rate = rate; + return 0; + } + + while (((ref_freq / pd) * 10) > rate) + pd++; + + if ((ref_freq / pd) < PRE_DIV_MIN_FREQ) + return -EINVAL; + + /* the ref_freq/2 in the following is to round up */ + mfi = (((rate / 2) * pd) + (ref_freq / 2)) / ref_freq; + if (mfi < 5 || mfi > 15) + return -EINVAL; + + /* pick a mfd value that will work + * then solve for mfn */ + mfd = ref_freq / 50000; + + /* + * pll_freq * pd * mfd + * mfn = -------------------- - (mfi * mfd) + * 2 * ref_freq + */ + /* the tmp/2 is for rounding */ + tmp = ref_freq / 10000; + mfn = + ((((((rate / 2) + (tmp / 2)) / tmp) * pd) * mfd) / 10000) - + (mfi * mfd); + + mfn = mfn & 0x3ff; + pd--; + mfd--; + + /* Change the Pll value */ + reg = (mfi << MXC_CCM_PCTL_MFI_OFFSET) | + (mfn << MXC_CCM_PCTL_MFN_OFFSET) | + (mfd << MXC_CCM_PCTL_MFD_OFFSET) | (pd << MXC_CCM_PCTL_PD_OFFSET); + + if (clk == &mcu_pll_clk) + __raw_writel(reg, MXC_CCM_MPCTL); + else if (clk == &peri_pll_clk) + __raw_writel(reg, MXC_CCM_PPCTL); + + clk->rate = rate; + return 0; +} + +static int _clk_cpu_set_rate(struct clk *clk, unsigned long rate) +{ + if ((rate < ahb_clk.rate) || (rate % ahb_clk.rate != 0)) { + printk(KERN_ERR "Wrong rate %lu in _clk_cpu_set_rate\n", rate); + return -EINVAL; + } + + if (clk->rate == rate) + return 0; + + if (clk->parent->rate == cpu_wp_tbl[cpu_curr_wp].pll_rate) + return __switch_cpu_wp(clk, rate); + return __switch_cpu_rate(clk, rate); +} + +static void _clk_pll_recalc(struct clk *clk) +{ + long mfi, mfn, mfd, pdf, ref_clk, mfn_abs; + unsigned long reg = 0; + s64 temp; + + ref_clk = ckih_clk.rate; + + if (clk == &mcu_pll_clk) + reg = __raw_readl(MXC_CCM_MPCTL); + else if (clk == &peri_pll_clk) + reg = __raw_readl(MXC_CCM_PPCTL); + else + BUG(); + + pdf = (reg & MXC_CCM_PCTL_PD_MASK) >> MXC_CCM_PCTL_PD_OFFSET; + mfd = (reg & MXC_CCM_PCTL_MFD_MASK) >> MXC_CCM_PCTL_MFD_OFFSET; + mfi = (reg & MXC_CCM_PCTL_MFI_MASK) >> MXC_CCM_PCTL_MFI_OFFSET; + mfi = (mfi <= 5) ? 5 : mfi; + mfn = mfn_abs = reg & MXC_CCM_PCTL_MFN_MASK; + + if (mfn >= 0x200) { + mfn |= 0xFFFFFE00; + mfn_abs = -mfn; + } + + 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_peri_pll_enable(struct clk *clk) +{ + u32 reg; + reg = __raw_readl(MXC_CCM_CCMR); + reg |= MXC_CCM_CCMR_UPE; + __raw_writel(reg, MXC_CCM_CCMR); + + /* No lock bit on MX31, so using max time from spec */ + udelay(80); + + return 0; +} + +static void _clk_peri_pll_disable(struct clk *clk) +{ + u32 reg; + + reg = __raw_readl(MXC_CCM_CCMR); + reg &= ~MXC_CCM_CCMR_UPE; + __raw_writel(reg, MXC_CCM_CCMR); +} + +#define PDR0(mask, off) ((__raw_readl(MXC_CCM_PDR0) & mask) >> off) +#define PDR1(mask, off) ((__raw_readl(MXC_CCM_PDR1) & mask) >> off) +#define PDR2(mask, off) ((__raw_readl(MXC_CCM_PDR2) & mask) >> off) +#define PDR3(mask, off) ((__raw_readl(MXC_CCM_PDR3) & mask) >> off) +#define PDR4(mask, off) ((__raw_readl(MXC_CCM_PDR4) & mask) >> off) + +static void _clk_cpu_recalc(struct clk *clk) +{ + unsigned long pdr0 = __raw_readl(MXC_CCM_PDR0); + int arm_div, fi, fd; + if (clk->parent->rate == cpu_wp_tbl[cpu_curr_wp].pll_rate) { + clk->rate = cpu_wp_tbl[cpu_curr_wp].cpu_rate; + } else { + arm_div = __get_arm_div(pdr0, &fi, &fd); + clk->rate = (clk->parent->rate * fi) / (arm_div * fd); + } +} + +static void _clk_hclk_recalc(struct clk *clk) +{ + unsigned long ahb_div, pdr0 = __raw_readl(MXC_CCM_PDR0); + ahb_div = __get_ahb_div(pdr0); + clk->rate = clk->parent->rate / ahb_div; +} + +static void _clk_ipg_recalc(struct clk *clk) +{ + clk->rate = clk->parent->rate / 2; +} + +static void _clk_nfc_recalc(struct clk *clk) +{ + unsigned long nfc_pdf; + + nfc_pdf = PDR4(MXC_CCM_PDR4_NFC_PODF_MASK, + MXC_CCM_PDR4_NFC_PODF_OFFSET); + clk->rate = clk->parent->rate / (nfc_pdf + 1); +} + +static void _clk_hsp_recalc(struct clk *clk) +{ + int hsp_pdf; + unsigned long reg; + reg = __raw_readl(MXC_CCM_PDR0); + + if ((reg & MXC_CCM_PDR0_AUTO_CON) + || (cpu_is_mx35_rev(CHIP_REV_2_0) >= 1)) { + hsp_pdf = + (reg & MXC_CCM_PDR0_HSP_PODF_MASK) >> + MXC_CCM_PDR0_HSP_PODF_OFFSET; + reg = + (reg & MXC_CCM_PDR0_CON_MUX_DIV_MASK) >> + MXC_CCM_PDR0_CON_MUX_DIV_OFFSET; + if (hsp_pdf < 3) { + hsp_pdf = g_hsp_div_table[hsp_pdf][reg]; + if (hsp_pdf > 0) + clk->rate = clk->parent->rate / hsp_pdf; + } + } else { + clk->rate = clk->parent->rate; + } +} + +static void _clk_mlb_recalc(struct clk *clk) +{ + clk->rate = clk->parent->rate * 2; +} + +static void _clk_usb_recalc(struct clk *clk) +{ + unsigned long usb_podf, usb_prdf; + if (cpu_is_mx35_rev(CHIP_REV_2_0) < 1) { + usb_podf = PDR4(MXC_CCM_PDR4_USB_PODF_MASK, + MXC_CCM_PDR4_USB_PODF_OFFSET); + usb_prdf = PDR4(MXC_CCM_PDR4_USB_PRDF_MASK, + MXC_CCM_PDR4_USB_PRDF_OFFSET); + clk->rate = + clk->parent->rate / ((usb_prdf + 1) * (usb_podf + 1)); + } else { + usb_podf = PDR4(MXC_CCM_PDR4_USB_PODF_MASK_V2, + MXC_CCM_PDR4_USB_PODF_OFFSET); + clk->rate = clk->parent->rate / (usb_podf + 1); + } +} + +static int _clk_usb_set_rate(struct clk *clk, unsigned long rate) +{ + u32 reg; + u32 div; + u32 podf, prdf; + + div = clk->parent->rate / rate; + + if ((clk->parent->rate / div) != rate) + return -EINVAL; + + if (cpu_is_mx35_rev(CHIP_REV_2_0) < 1) { + __calc_two_dividers(div, &prdf, &podf); + reg = __raw_readl(MXC_CCM_PDR4) & + ~(MXC_CCM_PDR4_USB_PODF_MASK | MXC_CCM_PDR4_USB_PRDF_MASK); + reg |= (podf - 1) << MXC_CCM_PDR4_USB_PODF_OFFSET; + reg |= (prdf - 1) << MXC_CCM_PDR4_USB_PRDF_OFFSET; + } else { + podf = div - 1; + reg = + __raw_readl(MXC_CCM_PDR4) & ~MXC_CCM_PDR4_USB_PODF_MASK_V2; + reg |= (podf - 1) << MXC_CCM_PDR4_USB_PODF_OFFSET; + } + __raw_writel(reg, MXC_CCM_PDR4); + clk->rate = rate; + return 0; +} + +static void _clk_csi_recalc(struct clk *clk) +{ + u32 podf, prdf; + + if (cpu_is_mx35_rev(CHIP_REV_2_0) < 1) { + prdf = PDR2(MXC_CCM_PDR2_CSI_PRDF_MASK, + MXC_CCM_PDR2_CSI_PRDF_OFFSET); + podf = + PDR2(MXC_CCM_PDR2_CSI_PODF_MASK, + MXC_CCM_PDR2_CSI_PODF_OFFSET); + clk->rate = clk->parent->rate / ((prdf + 1) * (podf + 1)); + } else { + podf = + PDR2(MXC_CCM_PDR2_CSI_PODF_MASK_V2, + MXC_CCM_PDR2_CSI_PODF_OFFSET); + clk->rate = clk->parent->rate / (podf + 1); + } +} + +static int _clk_csi_set_rate(struct clk *clk, unsigned long rate) +{ + u32 reg; + u32 div; + u32 prdf, podf; + + div = clk->parent->rate / rate; + + if ((clk->parent->rate / div) != rate) + return -EINVAL; + + if (cpu_is_mx35_rev(CHIP_REV_2_0) < 1) { + __calc_two_dividers(div, &prdf, &podf); + reg = __raw_readl(MXC_CCM_PDR2) & + ~(MXC_CCM_PDR2_CSI_PRDF_MASK | MXC_CCM_PDR2_CSI_PODF_MASK); + reg |= (podf - 1) << MXC_CCM_PDR2_CSI_PODF_OFFSET; + reg |= (prdf - 1) << MXC_CCM_PDR2_CSI_PRDF_OFFSET; + } else { + reg = + __raw_readl(MXC_CCM_PDR2) & ~MXC_CCM_PDR2_CSI_PODF_MASK_V2; + reg |= (div - 1) << MXC_CCM_PDR2_CSI_PODF_OFFSET; + } + + /* Set CSI clock divider */ + __raw_writel(reg, MXC_CCM_PDR2); + clk->rate = rate; + return 0; +} + +static int _clk_csi_set_parent(struct clk *clk, struct clk *parent) +{ + u32 reg; + if (parent == &cpu_clk) + reg = __raw_readl(MXC_CCM_PDR2) | MXC_CCM_PDR2_CSI_M_U; + else if (parent == &peri_pll_clk) + reg = __raw_readl(MXC_CCM_PDR2) & (~MXC_CCM_PDR2_CSI_M_U); + else + return -EINVAL; + __raw_writel(reg, MXC_CCM_PDR2); + return 0; +} + +static void _clk_per_recalc(struct clk *clk) +{ + u32 podf = 0, prdf = 0; + + if (cpu_is_mx35_rev(CHIP_REV_2_0) < 1) { + if (clk->parent == &cpu_clk) { + prdf = PDR4(MXC_CCM_PDR4_PER0_PRDF_MASK, + MXC_CCM_PDR4_PER0_PRDF_OFFSET); + podf = PDR4(MXC_CCM_PDR4_PER0_PODF_MASK, + MXC_CCM_PDR4_PER0_PODF_OFFSET); + } else { + podf = PDR0(MXC_CCM_PDR0_PER_PODF_MASK, + MXC_CCM_PDR0_PER_PODF_OFFSET); + } + clk->rate = clk->parent->rate / ((podf + 1) * (prdf + 1)); + } else { + if (clk->parent == &ahb_clk) + podf = PDR0(MXC_CCM_PDR0_PER_PODF_MASK, + MXC_CCM_PDR0_PER_PODF_OFFSET); + else if (clk->parent == &cpu_clk) { + podf = PDR4(MXC_CCM_PDR4_PER0_PODF_MASK_V2, + MXC_CCM_PDR4_PER0_PODF_OFFSET); + } + clk->rate = clk->parent->rate / (podf + 1); + } +} + +static void _clk_uart_per_recalc(struct clk *clk) +{ + unsigned long podf, prdf; + if (cpu_is_mx35_rev(CHIP_REV_2_0) < 1) { + prdf = PDR4(MXC_CCM_PDR4_UART_PRDF_MASK, + MXC_CCM_PDR4_UART_PRDF_OFFSET); + podf = PDR4(MXC_CCM_PDR4_UART_PODF_MASK, + MXC_CCM_PDR4_UART_PODF_OFFSET); + clk->rate = clk->parent->rate / ((prdf + 1) * (podf + 1)); + } else { + podf = + PDR4(MXC_CCM_PDR4_UART_PODF_MASK_V2, + MXC_CCM_PDR4_UART_PODF_OFFSET); + clk->rate = clk->parent->rate / (podf + 1); + } + +} + +static int _clk_uart_set_rate(struct clk *clk, unsigned long rate) +{ + u32 reg; + u32 div; + u32 prdf, podf; + + div = clk->parent->rate / rate; + + if ((clk->parent->rate / div) != rate) + return -EINVAL; + + /* Set UART clock divider */ + if (cpu_is_mx35_rev(CHIP_REV_2_0) < 1) { + __calc_two_dividers(div, &prdf, &podf); + reg = __raw_readl(MXC_CCM_PDR4) & + ~(MXC_CCM_PDR4_UART_PRDF_MASK | + MXC_CCM_PDR4_UART_PODF_MASK); + reg |= (podf - 1) << MXC_CCM_PDR4_UART_PODF_OFFSET; + reg |= (prdf - 1) << MXC_CCM_PDR4_UART_PRDF_OFFSET; + } else { + reg = + __raw_readl(MXC_CCM_PDR4) & ~MXC_CCM_PDR4_UART_PODF_MASK_V2; + reg |= (div - 1) << MXC_CCM_PDR4_UART_PODF_OFFSET; + } + __raw_writel(reg, MXC_CCM_PDR4); + clk->rate = rate; + return 0; +} + +static void _clk_ssi_recalc(struct clk *clk) +{ + unsigned long ssi_pdf, ssi_prepdf; + + if (clk->id == 1) { + ssi_pdf = PDR2(MXC_CCM_PDR2_SSI2_PODF_MASK, + MXC_CCM_PDR2_SSI2_PODF_OFFSET); + ssi_prepdf = PDR2(MXC_CCM_PDR2_SSI2_PRDF_MASK, + MXC_CCM_PDR2_SSI2_PRDF_OFFSET); + } else { + ssi_pdf = PDR2(MXC_CCM_PDR2_SSI1_PODF_MASK, + MXC_CCM_PDR2_SSI1_PODF_OFFSET); + ssi_prepdf = PDR2(MXC_CCM_PDR2_SSI1_PRDF_MASK, + MXC_CCM_PDR2_SSI1_PRDF_OFFSET); + } + clk->rate = clk->parent->rate / ((ssi_prepdf + 1) * (ssi_pdf + 1)); +} + +static int _clk_ssi_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); + + if (clk->id == 1) { + reg = __raw_readl(MXC_CCM_PDR2) & + ~(MXC_CCM_PDR2_SSI2_PRDF_MASK | + MXC_CCM_PDR2_SSI2_PODF_MASK); + reg |= (post - 1) << MXC_CCM_PDR2_SSI2_PODF_OFFSET; + reg |= (pre - 1) << MXC_CCM_PDR2_SSI2_PRDF_OFFSET; + } else { + reg = __raw_readl(MXC_CCM_PDR2) & + ~(MXC_CCM_PDR2_SSI1_PRDF_MASK | + MXC_CCM_PDR2_SSI1_PODF_MASK); + reg |= (post - 1) << MXC_CCM_PDR2_SSI1_PODF_OFFSET; + reg |= (pre - 1) << MXC_CCM_PDR2_SSI1_PRDF_OFFSET; + } + __raw_writel(reg, MXC_CCM_PDR2); + + clk->rate = rate; + return 0; +} + +static void _clk_mstick1_recalc(struct clk *clk) +{ + unsigned long prdf, podf; + prdf = PDR1(MXC_CCM_PDR1_MSHC_PRDF_MASK, MXC_CCM_PDR1_MSHC_PRDF_OFFSET); + podf = PDR1(MXC_CCM_PDR1_MSHC_PODF_MASK, MXC_CCM_PDR1_MSHC_PODF_OFFSET); + clk->rate = clk->parent->rate / ((prdf + 1) * (podf + 1)); +} + +static int _clk_mstick1_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); + + reg = __raw_readl(MXC_CCM_PDR1) & + ~(MXC_CCM_PDR1_MSHC_PRDF_MASK | MXC_CCM_PDR1_MSHC_PODF_MASK); + reg |= (post - 1) << MXC_CCM_PDR1_MSHC_PODF_OFFSET; + reg |= (pre - 1) << MXC_CCM_PDR1_MSHC_PRDF_OFFSET; + __raw_writel(reg, MXC_CCM_PDR1); + + clk->rate = rate; + return 0; +} + +static int _clk_mstick1_set_parent(struct clk *clk, struct clk *parent) +{ + u32 reg; + if (parent == &cpu_clk) + reg = __raw_readl(MXC_CCM_PDR1) | MXC_CCM_PDR1_MSHC_M_U; + else if (parent == &peri_pll_clk) + reg = __raw_readl(MXC_CCM_PDR1) & (~MXC_CCM_PDR1_MSHC_M_U); + else + return -EINVAL; + __raw_writel(reg, MXC_CCM_PDR1); + return 0; +} + +static void _clk_spdif_recalc(struct clk *clk) +{ + unsigned long prdf, podf; + prdf = + PDR3(MXC_CCM_PDR3_SPDIF_PRDF_MASK, MXC_CCM_PDR3_SPDIF_PRDF_OFFSET); + podf = + PDR3(MXC_CCM_PDR3_SPDIF_PODF_MASK, MXC_CCM_PDR3_SPDIF_PODF_OFFSET); + clk->rate = clk->parent->rate / ((prdf + 1) * (podf + 1)); +} + +static int _clk_spdif_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); + + reg = __raw_readl(MXC_CCM_PDR3) & + ~(MXC_CCM_PDR3_SPDIF_PRDF_MASK | MXC_CCM_PDR3_SPDIF_PODF_MASK); + reg |= (post - 1) << MXC_CCM_PDR3_SPDIF_PODF_OFFSET; + reg |= (pre - 1) << MXC_CCM_PDR3_SPDIF_PRDF_OFFSET; + __raw_writel(reg, MXC_CCM_PDR3); + + clk->rate = rate; + return 0; +} + +static int _clk_spdif_set_parent(struct clk *clk, struct clk *parent) +{ + u32 reg; + if (parent == &cpu_clk) + reg = __raw_readl(MXC_CCM_PDR3) | MXC_CCM_PDR3_SPDIF_M_U; + else if (parent == &peri_pll_clk) + reg = __raw_readl(MXC_CCM_PDR3) & (~MXC_CCM_PDR3_SPDIF_M_U); + else + return -EINVAL; + __raw_writel(reg, MXC_CCM_PDR3); + return 0; +} + +static void _clk_asrc_recalc(struct clk *clk) +{ + unsigned long div; + div = __raw_readl(MXC_CCM_COSR) & MXC_CCM_COSR_ASRC_AUDIO_PODF_MASK; + div = div >> MXC_CCM_COSR_ASRC_AUDIO_PODF_OFFSET; + clk->rate = clk->parent->rate / (div + 1); +} + +static int _clk_asrc_set_rate(struct clk *clk, unsigned long rate) +{ + int div; + unsigned long reg; + if (clk->parent->rate % rate) + return -EINVAL; + + div = clk->parent->rate / rate; + reg = __raw_readl(MXC_CCM_COSR) & (~MXC_CCM_COSR_ASRC_AUDIO_PODF_MASK); + reg |= (div - 1) << MXC_CCM_COSR_ASRC_AUDIO_PODF_OFFSET; + __raw_writel(reg, MXC_CCM_COSR); + clk->rate = rate; + return 0; +} + +static void _clk_sdhc_recalc(struct clk *clk) +{ + u32 podf = 0, prdf = 0; + + switch (clk->id) { + case 0: + if (cpu_is_mx35_rev(CHIP_REV_2_0) < 1) { + prdf = PDR3(MXC_CCM_PDR3_ESDHC1_PRDF_MASK, + MXC_CCM_PDR3_ESDHC1_PRDF_OFFSET); + podf = PDR3(MXC_CCM_PDR3_ESDHC1_PODF_MASK, + MXC_CCM_PDR3_ESDHC1_PODF_OFFSET); + } else + podf = PDR3(MXC_CCM_PDR3_ESDHC1_PODF_MASK_V2, + MXC_CCM_PDR3_ESDHC1_PODF_OFFSET); + break; + case 1: + if (cpu_is_mx35_rev(CHIP_REV_2_0) < 1) { + prdf = PDR3(MXC_CCM_PDR3_ESDHC2_PRDF_MASK, + MXC_CCM_PDR3_ESDHC2_PRDF_OFFSET); + podf = PDR3(MXC_CCM_PDR3_ESDHC2_PODF_MASK, + MXC_CCM_PDR3_ESDHC2_PODF_OFFSET); + } else + podf = PDR3(MXC_CCM_PDR3_ESDHC2_PODF_MASK_V2, + MXC_CCM_PDR3_ESDHC2_PODF_OFFSET); + break; + case 2: + if (cpu_is_mx35_rev(CHIP_REV_2_0) < 1) { + prdf = PDR3(MXC_CCM_PDR3_ESDHC3_PRDF_MASK, + MXC_CCM_PDR3_ESDHC3_PRDF_OFFSET); + podf = PDR3(MXC_CCM_PDR3_ESDHC3_PODF_MASK, + MXC_CCM_PDR3_ESDHC3_PODF_OFFSET); + } else + podf = PDR3(MXC_CCM_PDR3_ESDHC3_PODF_MASK_V2, + MXC_CCM_PDR3_ESDHC3_PODF_OFFSET); + break; + default: + return; + } + clk->rate = clk->parent->rate / ((podf + 1) * (prdf + 1)); +} + +static int _clk_sdhc_set_rate(struct clk *clk, unsigned long rate) +{ + u32 reg; + u32 div; + u32 prdf, podf; + + div = clk->parent->rate / rate; + + if ((clk->parent->rate / div) != rate) + return -EINVAL; + + if (cpu_is_mx35_rev(CHIP_REV_2_0) < 1) + __calc_pre_post_dividers(div, &prdf, &podf); + + switch (clk->id) { + case 0: + if (cpu_is_mx35_rev(CHIP_REV_2_0) < 1) { + reg = __raw_readl(MXC_CCM_PDR3) & + ~(MXC_CCM_PDR3_ESDHC1_PRDF_MASK | + MXC_CCM_PDR3_ESDHC1_PODF_MASK); + reg |= (podf - 1) << MXC_CCM_PDR3_ESDHC1_PODF_OFFSET; + reg |= (prdf - 1) << MXC_CCM_PDR3_ESDHC1_PRDF_OFFSET; + } else { + reg = __raw_readl(MXC_CCM_PDR3) & + ~MXC_CCM_PDR3_ESDHC1_PODF_MASK_V2; + reg |= (div - 1) << MXC_CCM_PDR3_ESDHC1_PODF_OFFSET; + } + break; + case 1: + if (cpu_is_mx35_rev(CHIP_REV_2_0) < 1) { + reg = __raw_readl(MXC_CCM_PDR3) & + ~(MXC_CCM_PDR3_ESDHC2_PRDF_MASK | + MXC_CCM_PDR3_ESDHC2_PODF_MASK); + reg |= (podf - 1) << MXC_CCM_PDR3_ESDHC2_PODF_OFFSET; + reg |= (prdf - 1) << MXC_CCM_PDR3_ESDHC2_PRDF_OFFSET; + } else { + reg = __raw_readl(MXC_CCM_PDR3) & + ~MXC_CCM_PDR3_ESDHC2_PODF_MASK_V2; + reg |= (div - 1) << MXC_CCM_PDR3_ESDHC2_PODF_OFFSET; + } + break; + case 2: + if (cpu_is_mx35_rev(CHIP_REV_2_0) < 1) { + reg = __raw_readl(MXC_CCM_PDR3) & + ~(MXC_CCM_PDR3_ESDHC3_PRDF_MASK | + MXC_CCM_PDR3_ESDHC3_PODF_MASK); + reg |= (podf - 1) << MXC_CCM_PDR3_ESDHC3_PODF_OFFSET; + reg |= (prdf - 1) << MXC_CCM_PDR3_ESDHC3_PRDF_OFFSET; + } else { + reg = __raw_readl(MXC_CCM_PDR3) & + ~MXC_CCM_PDR3_ESDHC3_PODF_MASK_V2; + reg |= (div - 1) << MXC_CCM_PDR3_ESDHC3_PODF_OFFSET; + } + break; + default: + return -EINVAL; + } + __raw_writel(reg, MXC_CCM_PDR3); + + clk->rate = rate; + return 0; +} + +static struct clk ckih_clk = { + .name = "ckih", + .rate = CKIH_CLK_FREQ, + .flags = RATE_FIXED, +}; + +static struct clk int_32k_clk = { + .name = "int_32k", + .rate = CKIL_CLK_FREQ, + .flags = RATE_FIXED, +}; + +static struct clk ext_32k_clk = { + .name = "ext_32k", + .rate = CKIL_EXT_FREQ, + .flags = RATE_FIXED, +}; + +static int _clk_ckil_set_parent(struct clk *clk, struct clk *parent) +{ + u32 reg; + if (parent == &int_32k_clk) { + reg = __raw_readl(MXC_CCM_PDR0) & (~MXC_CCM_PDR0_CKIL_SEL); + clk->rate = parent->rate; + } else if (parent == &ext_32k_clk) { + reg = __raw_readl(MXC_CCM_PDR0) | MXC_CCM_PDR0_CKIL_SEL; + clk->rate = parent->rate; + } else + return -EINVAL; + __raw_writel(reg, MXC_CCM_PDR0); + return 0; +} + +static int _clk_ckil_set_rate(struct clk *clk, unsigned long rate) +{ + clk->rate = clk->parent->rate; + return 0; +} + +static struct clk ckil_clk = { + .name = "ckil", + .parent = &ext_32k_clk, + .set_parent = _clk_ckil_set_parent, + .set_rate = _clk_ckil_set_rate, +}; + +static int _clk_ckie_enable(struct clk *clk) +{ + u32 reg; + + reg = __raw_readl(MXC_CCM_PMCR2) & ~MXC_CCM_PMCR2_OSC_AUDIO_DOWN; + __raw_writel(reg, MXC_CCM_PMCR2); + + return 0; +} + +static void _clk_ckie_disable(struct clk *clk) +{ + u32 reg; + + reg = __raw_readl(MXC_CCM_PMCR2) | MXC_CCM_PMCR2_OSC_AUDIO_DOWN; + __raw_writel(reg, MXC_CCM_PMCR2); +} + +static struct clk ckie_clk = { + .name = "ckie", + .rate = CKIE_CLK_FREQ, + .flags = RATE_FIXED, + .enable = _clk_ckie_enable, + .disable = _clk_ckie_disable, +}; + +static struct clk mcu_pll_clk = { + .name = "mcu_pll", + .parent = &ckih_clk, + .set_rate = _clk_pll_set_rate, + .recalc = _clk_pll_recalc, + .flags = RATE_PROPAGATES, +}; + +static struct clk peri_pll_clk = { + .name = "peri_pll", + .parent = &ckih_clk, + .set_rate = _clk_pll_set_rate, + .recalc = _clk_pll_recalc, + .enable = _clk_peri_pll_enable, + .disable = _clk_peri_pll_disable, + .flags = RATE_PROPAGATES, +}; + +static struct clk cpu_clk = { + .name = "cpu_clk", + .parent = &mcu_pll_clk, + .recalc = _clk_cpu_recalc, + .set_rate = _clk_cpu_set_rate, +}; + +static struct clk ahb_clk = { + .name = "ahb_clk", + .parent = &cpu_clk, + .recalc = _clk_hclk_recalc, + .flags = RATE_PROPAGATES, +}; + +static struct clk ipg_clk = { + .name = "ipg_clk", + .parent = &ahb_clk, + .recalc = _clk_ipg_recalc, + .flags = RATE_PROPAGATES, +}; + +static struct clk perclk_clk = { + .name = "perclk_clk", + .parent = &ahb_clk, + .recalc = _clk_per_recalc, + .flags = RATE_PROPAGATES, +}; + +static struct clk uart_per_clk = { + .name = "uart_per_clk", + .parent = &peri_pll_clk, + .recalc = _clk_uart_per_recalc, + .round_rate = _clk_round_rate, + .set_rate = _clk_uart_set_rate, + .flags = RATE_PROPAGATES, +}; + +static struct clk asrc_clk[] = { + { + .name = "asrc_clk", + .parent = &ipg_clk, + .enable = _clk_enable, + .enable_reg = MXC_CCM_CGR0, + .enable_shift = MXC_CCM_CGR0_ASRC_OFFSET, + .disable = _clk_disable,}, + { + .name = "asrc_audio_clk", + .parent = &ckie_clk, + .recalc = _clk_asrc_recalc, + .round_rate = _clk_round_rate, + .set_rate = _clk_asrc_set_rate, + .enable = _clk_asrc_enable, + .disable = _clk_asrc_disable,}, +}; + +static struct clk ata_clk = { + .name = "ata_clk", + .parent = &ipg_clk, + .enable = _clk_enable, + .enable_reg = MXC_CCM_CGR0, + .enable_shift = MXC_CCM_CGR0_ATA_OFFSET, + .disable = _clk_disable, +}; + +static struct clk can_clk[] = { + { + .name = "can_clk", + .id = 0, + .parent = &ipg_clk, + .enable = _clk_enable, + .enable_reg = MXC_CCM_CGR0, + .enable_shift = MXC_CCM_CGR0_CAN1_OFFSET, + .disable = _clk_disable,}, + { + .name = "can_clk", + .id = 1, + .parent = &ipg_clk, + .enable = _clk_enable, + .enable_reg = MXC_CCM_CGR0, + .enable_shift = MXC_CCM_CGR0_CAN2_OFFSET, + .disable = _clk_disable,}, +}; + +static struct clk cspi_clk[] = { + { + .name = "cspi_clk", + .id = 0, + .parent = &ipg_clk, + .enable = _clk_enable, + .enable_reg = MXC_CCM_CGR0, + .enable_shift = MXC_CCM_CGR0_CSPI1_OFFSET, + .disable = _clk_disable,}, + { + .name = "cspi_clk", + .id = 1, + .parent = &ipg_clk, + .enable = _clk_enable, + .enable_reg = MXC_CCM_CGR0, + .enable_shift = MXC_CCM_CGR0_CSPI2_OFFSET, + .disable = _clk_disable,}, +}; + +static struct clk ect_clk = { + .name = "ect_clk", + .parent = &ipg_clk, + .enable = _clk_enable, + .enable_reg = MXC_CCM_CGR0, + .enable_shift = MXC_CCM_CGR0_ECT_OFFSET, + .disable = _clk_disable, +}; + +static struct clk emi_clk = { + .name = "emi_clk", + .parent = &ahb_clk, + .enable = _clk_enable, + .enable_reg = MXC_CCM_CGR0, + .enable_shift = MXC_CCM_CGR0_EMI_OFFSET, + .disable = _clk_emi_disable, +}; + +static struct clk epit_clk[] = { + { + .name = "epit_clk", + .id = 0, + .parent = &perclk_clk, + .enable = _clk_enable, + .enable_reg = MXC_CCM_CGR0, + .enable_shift = MXC_CCM_CGR0_EPIT1_OFFSET, + .disable = _clk_disable,}, + { + .name = "epit_clk", + .id = 1, + .parent = &perclk_clk, + .enable = _clk_enable, + .enable_reg = MXC_CCM_CGR0, + .enable_shift = MXC_CCM_CGR0_EPIT2_OFFSET, + .disable = _clk_disable,}, +}; + +static struct clk esai_clk = { + .name = "esai_clk", + .parent = &ipg_clk, + .enable = _clk_enable, + .enable_reg = MXC_CCM_CGR0, + .enable_shift = MXC_CCM_CGR0_ESAI_OFFSET, + .disable = _clk_disable, +}; + +static struct clk sdhc_clk[] = { + { + .name = "sdhc_clk", + .id = 0, + .parent = &peri_pll_clk, + .recalc = _clk_sdhc_recalc, + .set_rate = _clk_sdhc_set_rate, + .round_rate = _clk_round_rate, + .enable = _clk_enable, + .enable_reg = MXC_CCM_CGR0, + .enable_shift = MXC_CCM_CGR0_ESDHC1_OFFSET, + .disable = _clk_disable,}, + { + .name = "sdhc_clk", + .id = 1, + .parent = &peri_pll_clk, + .recalc = _clk_sdhc_recalc, + .set_rate = _clk_sdhc_set_rate, + .round_rate = _clk_round_rate, + .enable = _clk_enable, + .enable_reg = MXC_CCM_CGR0, + .enable_shift = MXC_CCM_CGR0_ESDHC2_OFFSET, + .disable = _clk_disable,}, + { + .name = "sdhc_clk", + .id = 2, + .parent = &peri_pll_clk, + .recalc = _clk_sdhc_recalc, + .set_rate = _clk_sdhc_set_rate, + .round_rate = _clk_round_rate, + .enable = _clk_enable, + .enable_reg = MXC_CCM_CGR0, + .enable_shift = MXC_CCM_CGR0_ESDHC3_OFFSET, + .disable = _clk_disable,}, +}; + +static struct clk fec_clk = { + .name = "fec_clk", + .parent = &ipg_clk, + .enable = _clk_enable, + .enable_reg = MXC_CCM_CGR1, + .enable_shift = MXC_CCM_CGR1_FEC_OFFSET, + .disable = _clk_disable, +}; + +static struct clk gpt_clk = { + .name = "gpt_clk", + .parent = &perclk_clk, + .enable = _clk_enable, + .enable_reg = MXC_CCM_CGR1, + .enable_shift = MXC_CCM_CGR1_GPT_OFFSET, + .disable = _clk_disable, +}; + +static struct clk i2c_clk[] = { + { + .name = "i2c_clk", + .id = 0, + .parent = &perclk_clk, + .enable = _clk_enable, + .enable_reg = MXC_CCM_CGR1, + .enable_shift = MXC_CCM_CGR1_I2C1_OFFSET, + .disable = _clk_disable,}, + { + .name = "i2c_clk", + .id = 1, + .parent = &perclk_clk, + .enable = _clk_enable, + .enable_reg = MXC_CCM_CGR1, + .enable_shift = MXC_CCM_CGR1_I2C2_OFFSET, + .disable = _clk_disable,}, + { + .name = "i2c_clk", + .id = 2, + .parent = &perclk_clk, + .enable = _clk_enable, + .enable_reg = MXC_CCM_CGR1, + .enable_shift = MXC_CCM_CGR1_I2C3_OFFSET, + .disable = _clk_disable,}, +}; + +static struct clk ipu_clk = { + .name = "ipu_clk", + .parent = &cpu_clk, + .recalc = _clk_hsp_recalc, + .enable = _clk_enable, + .enable_reg = MXC_CCM_CGR1, + .enable_shift = MXC_CCM_CGR1_IPU_OFFSET, + .disable = _clk_disable, +}; + +static struct clk kpp_clk = { + .name = "kpp_clk", + .parent = &ipg_clk, + .enable = _clk_enable, + .enable_reg = MXC_CCM_CGR1, + .enable_shift = MXC_CCM_CGR1_KPP_OFFSET, + .disable = _clk_disable, +}; + +static struct clk mlb_clk = { + .name = "mlb_clk", + .parent = &ahb_clk, + .recalc = _clk_mlb_recalc, + .enable = _clk_enable, + .enable_reg = MXC_CCM_CGR1, + .enable_shift = MXC_CCM_CGR1_MLB_OFFSET, + .disable = _clk_disable, +}; + +static struct clk mstick_clk = { + .name = "mstick_clk", + .id = 0, + .parent = &peri_pll_clk, + .recalc = _clk_mstick1_recalc, + .set_rate = _clk_mstick1_set_rate, + .round_rate = _clk_per_post_round_rate, + .set_parent = _clk_mstick1_set_parent, + .enable = _clk_enable, + .enable_reg = MXC_CCM_CGR1, + .enable_shift = MXC_CCM_CGR1_MSHC_OFFSET, + .disable = _clk_disable, +}; + +static struct clk owire_clk = { + .name = "owire_clk", + .parent = &perclk_clk, + .enable_reg = MXC_CCM_CGR1, + .enable_shift = MXC_CCM_CGR1_OWIRE_OFFSET, + .enable = _clk_enable, + .disable = _clk_disable, +}; + +static struct clk pwm_clk = { + .name = "pwm_clk", + .parent = &perclk_clk, + .enable = _clk_enable, + .enable_reg = MXC_CCM_CGR1, + .enable_shift = MXC_CCM_CGR1_PWM_OFFSET, + .disable = _clk_disable, +}; + +static struct clk rng_clk = { + .name = "rng_clk", + .parent = &ipg_clk, + .enable = _clk_enable, + .enable_reg = MXC_CCM_CGR1, + .enable_shift = MXC_CCM_CGR1_RNGC_OFFSET, + .disable = _clk_disable, +}; + +static struct clk rtc_clk = { + .name = "rtc_clk", + .parent = &ipg_clk, + .enable = _clk_enable, + .enable_reg = MXC_CCM_CGR2, + .enable_shift = MXC_CCM_CGR2_RTC_OFFSET, + .disable = _clk_disable, +}; + +static struct clk rtic_clk = { + .name = "rtic_clk", + .parent = &ahb_clk, + .enable = _clk_enable, + .enable_reg = MXC_CCM_CGR2, + .enable_shift = MXC_CCM_CGR2_RTIC_OFFSET, + .disable = _clk_disable, +}; + +static struct clk scc_clk = { + .name = "scc_clk", + .parent = &ipg_clk, + .enable = _clk_enable, + .enable_reg = MXC_CCM_CGR2, + .enable_shift = MXC_CCM_CGR2_SCC_OFFSET, + .disable = _clk_disable, +}; + +static struct clk sdma_clk[] = { + { + .name = "sdma_ahb_clk", + .parent = &ahb_clk, + .enable = _clk_enable, + .enable_reg = MXC_CCM_CGR2, + .enable_shift = MXC_CCM_CGR2_SDMA_OFFSET, + .disable = _clk_disable,}, + { + .name = "sdma_ipg_clk", + .parent = &ipg_clk,} +}; + +static struct clk spba_clk = { + .name = "spba_clk", + .parent = &ipg_clk, + .enable = _clk_enable, + .enable_reg = MXC_CCM_CGR2, + .enable_shift = MXC_CCM_CGR2_SPBA_OFFSET, + .disable = _clk_disable, +}; + +static struct clk spdif_clk[] = { + { + .name = "spdif_clk", + .parent = &peri_pll_clk, + .recalc = _clk_spdif_recalc, + .set_rate = _clk_spdif_set_rate, + .round_rate = _clk_per_post_round_rate, + .set_parent = _clk_spdif_set_parent, + .enable = _clk_enable, + .enable_reg = MXC_CCM_CGR2, + .enable_shift = MXC_CCM_CGR2_SPDIF_OFFSET, + .disable = _clk_disable,}, + { + .name = "spdif_audio_clk", + .parent = &ckie_clk,}, + { + .name = "spdif_ipg_clk", + .parent = &ipg_clk,}, +}; + +static struct clk ssi_clk[] = { + { + .name = "ssi_clk", + .parent = &peri_pll_clk, + .recalc = _clk_ssi_recalc, + .set_rate = _clk_ssi_set_rate, + .round_rate = _clk_per_post_round_rate, + .enable = _clk_enable, + .enable_reg = MXC_CCM_CGR2, + .enable_shift = MXC_CCM_CGR2_SSI1_OFFSET, + .disable = _clk_disable,}, + { + .name = "ssi_clk", + .id = 1, + .parent = &peri_pll_clk, + .recalc = _clk_ssi_recalc, + .set_rate = _clk_ssi_set_rate, + .round_rate = _clk_per_post_round_rate, + .enable = _clk_enable, + .enable_reg = MXC_CCM_CGR2, + .enable_shift = MXC_CCM_CGR2_SSI2_OFFSET, + .disable = _clk_disable,}, +}; + +static struct clk uart_clk[] = { + { + .name = "uart_clk", + .id = 0, + .parent = &uart_per_clk, + .enable = _clk_enable, + .enable_reg = MXC_CCM_CGR2, + .enable_shift = MXC_CCM_CGR2_UART1_OFFSET, + .disable = _clk_disable,}, + { + .name = "uart_clk", + .id = 1, + .parent = &uart_per_clk, + .enable = _clk_enable, + .enable_reg = MXC_CCM_CGR2, + .enable_shift = MXC_CCM_CGR2_UART2_OFFSET, + .disable = _clk_disable,}, + { + .name = "uart_clk", + .id = 2, + .parent = &uart_per_clk, + .enable = _clk_enable, + .enable_reg = MXC_CCM_CGR2, + .enable_shift = MXC_CCM_CGR2_UART3_OFFSET, + .disable = _clk_disable,}, +}; + +static struct clk usb_clk[] = { + { + .name = "usb_clk", + .parent = &peri_pll_clk, + .recalc = _clk_usb_recalc, + .round_rate = _clk_round_rate, + .set_rate = _clk_usb_set_rate,}, + { + .name = "usb_ahb_clk", + .parent = &ahb_clk, + .enable = _clk_enable, + .enable_reg = MXC_CCM_CGR2, + .enable_shift = MXC_CCM_CGR2_USBOTG_OFFSET, + .disable = _clk_disable,}, +}; + +static struct clk wdog_clk = { + .name = "wdog_clk", + .parent = &ipg_clk, + .enable = _clk_enable, + .enable_reg = MXC_CCM_CGR2, + .enable_shift = MXC_CCM_CGR2_WDOG_OFFSET, + .disable = _clk_disable, +}; + +static struct clk csi_clk = { + .name = "csi_clk", + .parent = &peri_pll_clk, + .recalc = _clk_csi_recalc, + .round_rate = _clk_round_rate, + .set_rate = _clk_csi_set_rate, + .set_parent = _clk_csi_set_parent, + .enable = _clk_enable, + .enable_reg = MXC_CCM_CGR3, + .enable_shift = MXC_CCM_CGR3_CSI_OFFSET, + .disable = _clk_disable, +}; + +static struct clk iim_clk = { + .name = "iim_clk", + .parent = &ipg_clk, + .enable = _clk_enable, + .enable_reg = MXC_CCM_CGR3, + .enable_shift = MXC_CCM_CGR3_IIM_OFFSET, + .disable = _clk_disable, +}; + +static struct clk nfc_clk = { + .name = "nfc_clk", + .parent = &ahb_clk, + .recalc = _clk_nfc_recalc, +}; + +static unsigned long _clk_cko1_round_rate(struct clk *clk, unsigned long rate) +{ + u32 div = 0, div1 = 1; + + div = clk->parent->rate / rate; + if (clk->parent->rate % rate) + div++; + + if (div > 64) { + div = (div + 1) >> 1; + div1++; + } + + if (div > 128) + div = 64; + return clk->parent->rate / (div * div1); +} + +static int _clk_cko1_set_rate(struct clk *clk, unsigned long rate) +{ + u32 reg; + u32 div, div1 = 0; + u32 prdf, podf; + + div = clk->parent->rate / rate; + if ((clk->parent->rate / div) != rate) + return -EINVAL; + if (div > 64) { + div1 = MXC_CCM_COSR_CLKOUTDIV_1; + div >>= 1; + } else { + div1 = 0; + } + + if (cpu_is_mx35_rev(CHIP_REV_2_0) < 1) { + __calc_two_dividers(div, &prdf, &podf); + reg = __raw_readl(MXC_CCM_COSR) & + ~(MXC_CCM_COSR_CLKOUT_PREDIV_MASK | + MXC_CCM_COSR_CLKOUT_PRODIV_MASK | + MXC_CCM_COSR_CLKOUTDIV_1); + reg |= ((prdf - 1) << MXC_CCM_COSR_CLKOUT_PREDIV_OFFSET) + | ((podf - 1) << MXC_CCM_COSR_CLKOUT_PRODIV_OFFSET) + | div1; + } else { + reg = __raw_readl(MXC_CCM_COSR) & + ~(MXC_CCM_COSR_CLKOUT_PRODIV_MASK_V2 | + MXC_CCM_COSR_CLKOUTDIV_1); + reg |= ((div - 1) << MXC_CCM_COSR_CLKOUT_PRODIV_OFFSET) | div1; + } + __raw_writel(reg, MXC_CCM_COSR); + + return 0; +} + +static void _clk_cko1_recalc(struct clk *clk) +{ + u32 prdf = 1; + u32 podf, div1; + u32 reg = __raw_readl(MXC_CCM_COSR); + + div1 = 1 << ((reg & MXC_CCM_COSR_CLKOUTDIV_1) != 0); + if (cpu_is_mx35_rev(CHIP_REV_2_0) < 1) { + prdf = (reg & MXC_CCM_COSR_CLKOUT_PREDIV_MASK) >> + MXC_CCM_COSR_CLKOUT_PREDIV_OFFSET; + podf = (reg & MXC_CCM_COSR_CLKOUT_PRODIV_MASK) >> + MXC_CCM_COSR_CLKOUT_PRODIV_OFFSET; + } else + podf = (reg & MXC_CCM_COSR_CLKOUT_PRODIV_MASK_V2) >> + MXC_CCM_COSR_CLKOUT_PRODIV_OFFSET; + + clk->rate = clk->parent->rate / (div1 * (podf + 1) * (prdf + 1)); +} + +static int _clk_cko1_set_parent(struct clk *clk, struct clk *parent) +{ + u32 reg; + reg = __raw_readl(MXC_CCM_COSR) & ~MXC_CCM_COSR_CLKOSEL_MASK; + + if (parent == &ckil_clk) { + reg &= ~MXC_CCM_COSR_CKIL_CKIH_MASK; + reg |= 0 << MXC_CCM_COSR_CLKOSEL_OFFSET; + } else if (parent == &ckih_clk) { + reg |= 1 << MXC_CCM_COSR_CLKOSEL_OFFSET; + } else if (parent == &ckie_clk) + reg |= 2 << MXC_CCM_COSR_CLKOSEL_OFFSET; + else if (parent == &peri_pll_clk) + reg |= 6 << MXC_CCM_COSR_CLKOSEL_OFFSET; + else if (parent == &cpu_clk) + reg |= 7 << MXC_CCM_COSR_CLKOSEL_OFFSET; + else if (parent == &ahb_clk) + reg |= 8 << MXC_CCM_COSR_CLKOSEL_OFFSET; + else if (parent == &ipg_clk) + reg |= 9 << MXC_CCM_COSR_CLKOSEL_OFFSET; + else if (parent == &usb_clk[1]) + reg |= 0xB << MXC_CCM_COSR_CLKOSEL_OFFSET; + else if (parent == &sdhc_clk[1]) + reg |= 0xC << MXC_CCM_COSR_CLKOSEL_OFFSET; + else if (parent == &ssi_clk[1]) + reg |= 0xD << MXC_CCM_COSR_CLKOSEL_OFFSET; + else if (parent == &mlb_clk) + reg |= 0xE << MXC_CCM_COSR_CLKOSEL_OFFSET; + else if (parent == &csi_clk) + reg |= 0x11 << MXC_CCM_COSR_CLKOSEL_OFFSET; + else if (parent == &spdif_clk[0]) + reg |= 0x12 << MXC_CCM_COSR_CLKOSEL_OFFSET; + else if (parent == &uart_clk[0]) + reg |= 0x13 << MXC_CCM_COSR_CLKOSEL_OFFSET; + else if (parent == &asrc_clk[1]) + reg |= 0x14 << MXC_CCM_COSR_CLKOSEL_OFFSET; + else if ((parent == &nfc_clk) && (cpu_is_mx35_rev(CHIP_REV_2_0) >= 1)) + reg |= 0x17 << MXC_CCM_COSR_CLKOSEL_OFFSET; + else if ((parent == &ipu_clk) && (cpu_is_mx35_rev(CHIP_REV_2_0) >= 1)) + reg |= 0x18 << MXC_CCM_COSR_CLKOSEL_OFFSET; + else + return -EINVAL; + + __raw_writel(reg, MXC_CCM_COSR); + return 0; +} + +static int _clk_cko1_enable(struct clk *clk) +{ + u32 reg; + + reg = __raw_readl(MXC_CCM_COSR) | MXC_CCM_COSR_CLKOEN; + __raw_writel(reg, MXC_CCM_COSR); + + return 0; +} + +static void _clk_cko1_disable(struct clk *clk) +{ + u32 reg; + + reg = __raw_readl(MXC_CCM_COSR) & ~MXC_CCM_COSR_CLKOEN; + __raw_writel(reg, MXC_CCM_COSR); +} + +static struct clk cko1_clk = { + .name = "cko1_clk", + .recalc = _clk_cko1_recalc, + .set_rate = _clk_cko1_set_rate, + .round_rate = _clk_cko1_round_rate, + .set_parent = _clk_cko1_set_parent, + .enable = _clk_cko1_enable, + .disable = _clk_cko1_disable, +}; + +static struct clk gpu2d_clk = { + .name = "gpu2d_clk", + .parent = &ahb_clk, + .enable = _clk_enable, + .enable_reg = MXC_CCM_CGR3, + .enable_shift = MXC_CCM_CGR3_GPU2D_OFFSET, + .disable = _clk_disable, +}; + +static struct clk *mxc_clks[] = { + &int_32k_clk, + &ext_32k_clk, + &ckih_clk, + &ckil_clk, + &ckie_clk, + &mcu_pll_clk, + &peri_pll_clk, + &cpu_clk, + &ahb_clk, + &ipg_clk, + &perclk_clk, + &uart_per_clk, + &asrc_clk[0], + &asrc_clk[1], + &ata_clk, + &can_clk[0], + &can_clk[1], + &cspi_clk[0], + &cspi_clk[1], + &ect_clk, + &emi_clk, + &epit_clk[0], + &epit_clk[1], + &esai_clk, + &sdhc_clk[0], + &sdhc_clk[1], + &sdhc_clk[2], + &fec_clk, + &gpt_clk, + &i2c_clk[0], + &i2c_clk[1], + &i2c_clk[2], + &ipu_clk, + &kpp_clk, + &mlb_clk, + &mstick_clk, + &owire_clk, + &rng_clk, + &pwm_clk, + &rtc_clk, + &rtic_clk, + &scc_clk, + &sdma_clk[0], + &sdma_clk[1], + &spba_clk, + &spdif_clk[0], + &spdif_clk[1], + &spdif_clk[2], + &ssi_clk[0], + &ssi_clk[1], + &uart_clk[0], + &uart_clk[1], + &uart_clk[2], + &usb_clk[0], + &usb_clk[1], + &wdog_clk, + &csi_clk, + &iim_clk, + &nfc_clk, + &cko1_clk, + &gpu2d_clk, +}; + +extern void propagate_rate(struct clk *tclk); + +static void mxc_clockout_scan(void) +{ + u32 reg = __raw_readl(MXC_CCM_COSR) & MXC_CCM_COSR_CLKOSEL_MASK; + reg >>= MXC_CCM_COSR_CLKOSEL_OFFSET; + switch (reg) { + case 0: + cko1_clk.parent = &ckil_clk; + break; + case 1: + cko1_clk.parent = &ckih_clk; + break; + case 2: + cko1_clk.parent = &ckie_clk; + break; + case 6: + cko1_clk.parent = &peri_pll_clk; + break; + case 7: + cko1_clk.parent = &cpu_clk; + break; + case 8: + cko1_clk.parent = &ahb_clk; + break; + case 9: + cko1_clk.parent = &ipg_clk; + break; + case 0xB: + cko1_clk.parent = &usb_clk[1]; + break; + case 0xC: + cko1_clk.parent = &sdhc_clk[1]; + break; + case 0xD: + cko1_clk.parent = &ssi_clk[1]; + break; + case 0xE: + cko1_clk.parent = &mlb_clk; + break; + case 0x11: + cko1_clk.parent = &csi_clk; + break; + case 0x12: + cko1_clk.parent = &spdif_clk[0]; + break; + case 0x13: + cko1_clk.parent = &uart_clk[0]; + break; + case 0x14: + cko1_clk.parent = &asrc_clk[1]; + break; + case 0x17: + cko1_clk.parent = &nfc_clk; + break; + case 0x18: + cko1_clk.parent = &ipu_clk; + break; + } +} + +static void mxc_update_clocks(void) +{ + unsigned long reg; + reg = __raw_readl(MXC_CCM_PDR0); + if ((!(reg & MXC_CCM_PDR0_AUTO_CON)) + && (cpu_is_mx35_rev(CHIP_REV_2_0) < 1)) + ipu_clk.parent = &ahb_clk; + + if (reg & MXC_CCM_PDR0_PER_SEL) + perclk_clk.parent = &cpu_clk; + + reg = __raw_readl(MXC_CCM_PDR1); + if (reg & MXC_CCM_PDR1_MSHC_M_U) + mstick_clk.parent = &cpu_clk; + + reg = __raw_readl(MXC_CCM_PDR2); + if (reg & MXC_CCM_PDR2_CSI_M_U) + csi_clk.parent = &cpu_clk; + if (reg & MXC_CCM_PDR2_SSI_M_U) { + ssi_clk[0].parent = &cpu_clk; + ssi_clk[1].parent = &cpu_clk; + } + + reg = __raw_readl(MXC_CCM_PDR3); + if (reg & MXC_CCM_PDR3_SPDIF_M_U) + spdif_clk[0].parent = &cpu_clk; + + if (reg & MXC_CCM_PDR3_UART_M_U) + uart_per_clk.parent = &cpu_clk; + + if (reg & MXC_CCM_PDR3_ESDHC_M_U) { + sdhc_clk[0].parent = &cpu_clk; + sdhc_clk[1].parent = &cpu_clk; + sdhc_clk[2].parent = &cpu_clk; + } + + reg = __raw_readl(MXC_CCM_PDR4); + if (reg & MXC_CCM_PDR4_USB_M_U) + usb_clk[0].parent = &cpu_clk; + + mxc_clockout_scan(); +} + +int __init mx35_clocks_init(void) +{ + struct clk **clkp; + for (clkp = mxc_clks; clkp < mxc_clks + ARRAY_SIZE(mxc_clks); clkp++) + clk_register(*clkp); + + /* Turn off all possible clocks */ + __raw_writel(MXC_CCM_CGR0_ECT_MASK | MXC_CCM_CGR0_EMI_MASK, + MXC_CCM_CGR0); + __raw_writel(MXC_CCM_CGR1_GPIO1_MASK | MXC_CCM_CGR1_GPIO2_MASK | + MXC_CCM_CGR1_GPIO3_MASK | MXC_CCM_CGR1_GPT_MASK | + MXC_CCM_CGR1_IOMUXC_MASK, MXC_CCM_CGR1); + __raw_writel(MXC_CCM_CGR2_MAX_MASK | MXC_CCM_CGR2_SPBA_MASK | + MXC_CCM_CGR2_AUDMUX_MASK | MXC_CCM_CGR2_MAX_ENABLE, + MXC_CCM_CGR2); + __raw_writel(MXC_CCM_CGR3_IIM_MASK, MXC_CCM_CGR3); + __raw_writel((__raw_readl(MXC_CCM_PMCR2) | + MXC_CCM_PMCR2_OSC24M_DOWN | + MXC_CCM_PMCR2_OSC_AUDIO_DOWN), MXC_CCM_PMCR2); + mxc_update_clocks(); + pr_info("Clock input source is %ld\n", ckih_clk.rate); + + /* Determine which high frequency clock source is coming in */ + cpu_wp_tbl = get_cpu_wp(&cpu_wp_nr); + sync_cpu_wb(); + + /* This will propagate to all children and init all the clock rates */ + propagate_rate(&ckih_clk); + propagate_rate(&ext_32k_clk); + propagate_rate(&ckie_clk); + + clk_enable(&mcu_pll_clk); + clk_enable(&gpt_clk); + clk_enable(&emi_clk); + clk_enable(&iim_clk); + clk_enable(&spba_clk); + + /* Init serial PLL according */ + clk_set_rate(&peri_pll_clk, 300000000); + + clk_enable(&peri_pll_clk); + + mxc_timer_init(&gpt_clk, IO_ADDRESS(GPT1_BASE_ADDR), MXC_INT_GPT); + + return 0; +} diff --git a/arch/arm/mach-mx35/cpu.c b/arch/arm/mach-mx35/cpu.c new file mode 100644 index 000000000000..90848a55e0ad --- /dev/null +++ b/arch/arm/mach-mx35/cpu.c @@ -0,0 +1,82 @@ +/* + * 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-mx35/cpu.c + * + * @brief This file contains the CPU initialization code. + * + * @ingroup MSL_MX35 + */ + +#include <linux/types.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <mach/hardware.h> +#include <linux/io.h> +#include <asm/hardware/cache-l2x0.h> + +/*! + * CPU initialization. It is called by fixup_mxc_board() + */ +void __init mxc_cpu_init(void) +{ + + /* Setup Peripheral Port Remap register for AVIC */ + asm("ldr r0, =0xC0000015 \n\ + mcr p15, 0, r0, c15, c2, 4"); + /*TODO:Add code to check chip version */ + + if (!system_rev) + mxc_set_system_rev(0x35, CHIP_REV_1_0); + +} + +/*! + * Post CPU init code + * + * @return 0 always + */ +static int __init post_cpu_init(void) +{ + void *l2_base; + unsigned long aips_reg; + + /* Initialize L2 cache */ + l2_base = ioremap(L2CC_BASE_ADDR, SZ_4K); + if (l2_base) + l2x0_init(l2_base, 0x00030024, 0x00000000); + + /* + * S/W workaround: Clear the off platform peripheral modules + * Supervisor Protect bit for SDMA to access them. + */ + __raw_writel(0x0, IO_ADDRESS(AIPS1_BASE_ADDR + 0x40)); + __raw_writel(0x0, IO_ADDRESS(AIPS1_BASE_ADDR + 0x44)); + __raw_writel(0x0, IO_ADDRESS(AIPS1_BASE_ADDR + 0x48)); + __raw_writel(0x0, IO_ADDRESS(AIPS1_BASE_ADDR + 0x4C)); + aips_reg = __raw_readl(IO_ADDRESS(AIPS1_BASE_ADDR + 0x50)); + aips_reg &= 0x00FFFFFF; + __raw_writel(aips_reg, IO_ADDRESS(AIPS1_BASE_ADDR + 0x50)); + __raw_writel(0x0, IO_ADDRESS(AIPS2_BASE_ADDR + 0x40)); + __raw_writel(0x0, IO_ADDRESS(AIPS2_BASE_ADDR + 0x44)); + __raw_writel(0x0, IO_ADDRESS(AIPS2_BASE_ADDR + 0x48)); + __raw_writel(0x0, IO_ADDRESS(AIPS2_BASE_ADDR + 0x4C)); + aips_reg = __raw_readl(IO_ADDRESS(AIPS2_BASE_ADDR + 0x50)); + aips_reg &= 0x00FFFFFF; + __raw_writel(aips_reg, IO_ADDRESS(AIPS2_BASE_ADDR + 0x50)); + + return 0; +} + +postcore_initcall(post_cpu_init); diff --git a/arch/arm/mach-mx35/crm_regs.h b/arch/arm/mach-mx35/crm_regs.h new file mode 100644 index 000000000000..b770b4841e8e --- /dev/null +++ b/arch/arm/mach-mx35/crm_regs.h @@ -0,0 +1,430 @@ +/* + * Copyright 2004-2009 Freescale Semiconductor, Inc. All Rights Reserved. + */ + +/* + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ +#ifndef __ARCH_ARM_MACH_MX35_CRM_REGS_H__ +#define __ARCH_ARM_MACH_MX35_CRM_REGS_H__ + +#define CKIH_CLK_FREQ 24000000 +#define CKIE_CLK_FREQ 24576000 +#define CKIL_CLK_FREQ 32000 +#define CKIL_EXT_FREQ 32768 + +#define MXC_CCM_BASE ((char *)IO_ADDRESS(CCM_BASE_ADDR)) + +/* Register addresses */ +#define MXC_CCM_CCMR (MXC_CCM_BASE + 0x00) +#define MXC_CCM_PDR0 (MXC_CCM_BASE + 0x04) +#define MXC_CCM_PDR1 (MXC_CCM_BASE + 0x08) +#define MXC_CCM_PDR2 (MXC_CCM_BASE + 0x0C) +#define MXC_CCM_PDR3 (MXC_CCM_BASE + 0x10) +#define MXC_CCM_PDR4 (MXC_CCM_BASE + 0x14) +#define MXC_CCM_RCSR (MXC_CCM_BASE + 0x18) +#define MXC_CCM_MPCTL (MXC_CCM_BASE + 0x1C) +#define MXC_CCM_PPCTL (MXC_CCM_BASE + 0x20) +#define MXC_CCM_ACMR (MXC_CCM_BASE + 0x24) +#define MXC_CCM_COSR (MXC_CCM_BASE + 0x28) +#define MXC_CCM_CGR0 (MXC_CCM_BASE + 0x2C) +#define MXC_CCM_CGR1 (MXC_CCM_BASE + 0x30) +#define MXC_CCM_CGR2 (MXC_CCM_BASE + 0x34) +#define MXC_CCM_CGR3 (MXC_CCM_BASE + 0x38) +#define MXC_CCM_RESV (MXC_CCM_BASE + 0x3C) +#define MXC_CCM_DCVR0 (MXC_CCM_BASE + 0x40) +#define MXC_CCM_DCVR1 (MXC_CCM_BASE + 0x44) +#define MXC_CCM_DCVR2 (MXC_CCM_BASE + 0x48) +#define MXC_CCM_DCVR3 (MXC_CCM_BASE + 0x4C) +#define MXC_CCM_LTR0 (MXC_CCM_BASE + 0x50) +#define MXC_CCM_LTR1 (MXC_CCM_BASE + 0x54) +#define MXC_CCM_LTR2 (MXC_CCM_BASE + 0x58) +#define MXC_CCM_LTR3 (MXC_CCM_BASE + 0x5C) +#define MXC_CCM_LTBR0 (MXC_CCM_BASE + 0x60) +#define MXC_CCM_LTBR1 (MXC_CCM_BASE + 0x64) +#define MXC_CCM_PMCR0 (MXC_CCM_BASE + 0x68) +#define MXC_CCM_PMCR1 (MXC_CCM_BASE + 0x6C) +#define MXC_CCM_PMCR2 (MXC_CCM_BASE + 0x70) + +/* Register bit definitions */ +#define MXC_CCM_CCMR_WFI (1 << 30) +#define MXC_CCM_CCMR_STBY_EXIT_SRC (1 << 29) +#define MXC_CCM_CCMR_VSTBY (1 << 28) +#define MXC_CCM_CCMR_WBEN (1 << 27) +#define MXC_CCM_CCMR_VOL_RDY_CNT_OFFSET 20 +#define MXC_CCM_CCMR_VOL_RDY_CNT_MASK (0xF << 20) +#define MXC_CCM_CCMR_ROMW_OFFSET 18 +#define MXC_CCM_CCMR_ROMW_MASK (0x3 << 18) +#define MXC_CCM_CCMR_RAMW_OFFSET 21 +#define MXC_CCM_CCMR_RAMW_MASK (0x3 << 21) +#define MXC_CCM_CCMR_LPM_OFFSET 14 +#define MXC_CCM_CCMR_LPM_MASK (0x3 << 14) +#define MXC_CCM_CCMR_UPE (1 << 9) +#define MXC_CCM_CCMR_MPE (1 << 3) + +#define MXC_CCM_PDR0_PER_SEL (1 << 26) +#define MXC_CCM_PDR0_IPU_HND_BYP (1 << 23) +#define MXC_CCM_PDR0_HSP_PODF_OFFSET 20 +#define MXC_CCM_PDR0_HSP_PODF_MASK (0x3 << 20) +#define MXC_CCM_PDR0_CON_MUX_DIV_OFFSET 16 +#define MXC_CCM_PDR0_CON_MUX_DIV_MASK (0xF << 16) +#define MXC_CCM_PDR0_CKIL_SEL (1 << 15) +#define MXC_CCM_PDR0_PER_PODF_OFFSET 12 +#define MXC_CCM_PDR0_PER_PODF_MASK (0xF << 12) +#define MXC_CCM_PDR0_AUTO_MUX_DIV_OFFSET 9 +#define MXC_CCM_PDR0_AUTO_MUX_DIV_MASK (0x7 << 9) +#define MXC_CCM_PDR0_AUTO_CON 0x1 + +#define MXC_CCM_PDR1_MSHC_PRDF_OFFSET 28 +#define MXC_CCM_PDR1_MSHC_PRDF_MASK (0x7 << 28) +#define MXC_CCM_PDR1_MSHC_PODF_OFFSET 22 +#define MXC_CCM_PDR1_MSHC_PODF_MASK (0x3F << 22) +#define MXC_CCM_PDR1_MSHC_M_U (1 << 7) + +#define MXC_CCM_PDR2_SSI2_PRDF_OFFSET 27 +#define MXC_CCM_PDR2_SSI2_PRDF_MASK (0x7 << 27) +#define MXC_CCM_PDR2_SSI1_PRDF_OFFSET 24 +#define MXC_CCM_PDR2_SSI1_PRDF_MASK (0x7 << 24) +#define MXC_CCM_PDR2_CSI_PRDF_OFFSET 19 +#define MXC_CCM_PDR2_CSI_PRDF_MASK (0x7 << 19) +#define MXC_CCM_PDR2_CSI_PODF_OFFSET 16 +#define MXC_CCM_PDR2_CSI_PODF_MASK (0x7 << 16) +#define MXC_CCM_PDR2_SSI2_PODF_OFFSET 8 +#define MXC_CCM_PDR2_SSI2_PODF_MASK (0x3F << 8) +#define MXC_CCM_PDR2_CSI_M_U (1 << 7) +#define MXC_CCM_PDR2_SSI_M_U (1 << 6) +#define MXC_CCM_PDR2_SSI1_PODF_OFFSET 0 +#define MXC_CCM_PDR2_SSI1_PODF_MASK (0x3F) + +/* Extra definitions for Chip Version 2*/ +#define MXC_CCM_PDR2_CSI_PODF_MASK_V2 (0x3F << 16) + +#define MXC_CCM_PDR3_SPDIF_PRDF_OFFSET 29 +#define MXC_CCM_PDR3_SPDIF_PRDF_MASK (0x7 << 29) +#define MXC_CCM_PDR3_SPDIF_PODF_OFFSET 23 +#define MXC_CCM_PDR3_SPDIF_PODF_MASK (0x3F << 23) +#define MXC_CCM_PDR3_SPDIF_M_U (1 << 22) +#define MXC_CCM_PDR3_ESDHC3_PRDF_OFFSET 19 +#define MXC_CCM_PDR3_ESDHC3_PRDF_MASK (0x7 << 19) +#define MXC_CCM_PDR3_ESDHC3_PODF_OFFSET 16 +#define MXC_CCM_PDR3_ESDHC3_PODF_MASK (0x7 << 16) +#define MXC_CCM_PDR3_UART_M_U (1 << 15) +#define MXC_CCM_PDR3_ESDHC2_PRDF_OFFSET 11 +#define MXC_CCM_PDR3_ESDHC2_PRDF_MASK (0x7 << 11) +#define MXC_CCM_PDR3_ESDHC2_PODF_OFFSET 8 +#define MXC_CCM_PDR3_ESDHC2_PODF_MASK (0x7 << 8) +#define MXC_CCM_PDR3_ESDHC_M_U (1 << 6) +#define MXC_CCM_PDR3_ESDHC1_PRDF_OFFSET 3 +#define MXC_CCM_PDR3_ESDHC1_PRDF_MASK (0x7 << 3) +#define MXC_CCM_PDR3_ESDHC1_PODF_OFFSET 0 +#define MXC_CCM_PDR3_ESDHC1_PODF_MASK (0x7) + +/* Extra definitions for Chip Version 2 */ +#define MXC_CCM_PDR3_ESDHC3_PODF_MASK_V2 (0x3F << 16) +#define MXC_CCM_PDR3_ESDHC2_PODF_MASK_V2 (0x3F << 8) +#define MXC_CCM_PDR3_ESDHC1_PODF_MASK_V2 0x3F + +#define MXC_CCM_PDR4_NFC_PODF_OFFSET 28 +#define MXC_CCM_PDR4_NFC_PODF_MASK (0xF << 28) +#define MXC_CCM_PDR4_USB_PRDF_OFFSET 25 +#define MXC_CCM_PDR4_USB_PRDF_MASK (0x7 << 25) +#define MXC_CCM_PDR4_USB_PODF_OFFSET 22 +#define MXC_CCM_PDR4_USB_PODF_MASK (0x7 << 22) +#define MXC_CCM_PDR4_PER0_PRDF_OFFSET 19 +#define MXC_CCM_PDR4_PER0_PRDF_MASK (0x7 << 19) +#define MXC_CCM_PDR4_PER0_PODF_OFFSET 16 +#define MXC_CCM_PDR4_PER0_PODF_MASK (0x7 << 16) +#define MXC_CCM_PDR4_UART_PRDF_OFFSET 13 +#define MXC_CCM_PDR4_UART_PRDF_MASK (0x7 << 13) +#define MXC_CCM_PDR4_UART_PODF_OFFSET 10 +#define MXC_CCM_PDR4_UART_PODF_MASK (0x7 << 10) +#define MXC_CCM_PDR4_USB_M_U (1 << 9) + +/* Extra definitions for Chip Version 2 */ +#define MXC_CCM_PDR4_USB_PODF_MASK_V2 (0x3F << 22) +#define MXC_CCM_PDR4_PER0_PODF_MASK_V2 (0x3F << 16) +#define MXC_CCM_PDR4_UART_PODF_MASK_V2 (0x3F << 10) + +/* Bit definitions for RCSR */ +#define MXC_CCM_RCSR_BUS_WIDTH (1 << 29) +#define MXC_CCM_RCSR_BUS_16BIT (1 << 29) +#define MXC_CCM_RCSR_PAGE_SIZE (3 << 27) +#define MXC_CCM_RCSR_PAGE_512 (0 << 27) +#define MXC_CCM_RCSR_PAGE_2K (1 << 27) +#define MXC_CCM_RCSR_PAGE_4K1 (2 << 27) +#define MXC_CCM_RCSR_PAGE_4K2 (3 << 27) +#define MXC_CCM_RCSR_SOFT_RESET (1 << 15) +#define MXC_CCM_RCSR_NF16B (1 << 14) +#define MXC_CCM_RCSR_NFC_4K (1 << 9) +#define MXC_CCM_RCSR_NFC_FMS (1 << 8) + +/* Bit definitions for both MCU, PERIPHERAL PLL control registers */ +#define MXC_CCM_PCTL_BRM 0x80000000 +#define MXC_CCM_PCTL_PD_OFFSET 26 +#define MXC_CCM_PCTL_PD_MASK (0xF << 26) +#define MXC_CCM_PCTL_MFD_OFFSET 16 +#define MXC_CCM_PCTL_MFD_MASK (0x3FF << 16) +#define MXC_CCM_PCTL_MFI_OFFSET 10 +#define MXC_CCM_PCTL_MFI_MASK (0xF << 10) +#define MXC_CCM_PCTL_MFN_OFFSET 0 +#define MXC_CCM_PCTL_MFN_MASK 0x3FF + +/* Bit definitions for Audio clock mux register*/ +#define MXC_CCM_ACMR_ESAI_CLK_SEL_OFFSET 12 +#define MXC_CCM_ACMR_ESAI_CLK_SEL_MASK (0xF << 12) +#define MXC_CCM_ACMR_SPDIF_CLK_SEL_OFFSET 8 +#define MXC_CCM_ACMR_SPDIF_CLK_SEL_MASK (0xF << 8) +#define MXC_CCM_ACMR_SSI1_CLK_SEL_OFFSET 4 +#define MXC_CCM_ACMR_SSI1_CLK_SEL_MASK (0xF << 4) +#define MXC_CCM_ACMR_SSI2_CLK_SEL_OFFSET 0 +#define MXC_CCM_ACMR_SSI2_CLK_SEL_MASK (0xF << 0) + +/* Extra definitions for Version 2 */ +#define MXC_CCM_ACMR_CKILH_PODF0_OFFSET 16 +#define MXC_CCM_ACMR_CKILH_PODF1_OFFSET 19 +#define MXC_CCM_ACMR_CKILH_PODF2_OFFSET 22 +#define MXC_CCM_ACMR_CKILH_PODF3_OFFSET 25 +#define MXC_CCM_ACMR_CKILH_PODF_MASK 0x7 + +/* Bit definitions for Clock gating Register*/ +#define MXC_CCM_CGR0_ASRC_OFFSET 0 +#define MXC_CCM_CGR0_ASRC_MASK (0x3 << 0) +#define MXC_CCM_CGR0_ATA_OFFSET 2 +#define MXC_CCM_CGR0_ATA_MASK (0x3 << 2) +#define MXC_CCM_CGR0_CAN1_OFFSET 6 +#define MXC_CCM_CGR0_CAN1_MASK (0x3 << 6) +#define MXC_CCM_CGR0_CAN2_OFFSET 8 +#define MXC_CCM_CGR0_CAN2_MASK (0x3 << 8) +#define MXC_CCM_CGR0_CSPI1_OFFSET 10 +#define MXC_CCM_CGR0_CSPI1_MASK (0x3 << 10) +#define MXC_CCM_CGR0_CSPI2_OFFSET 12 +#define MXC_CCM_CGR0_CSPI2_MASK (0x3 << 12) +#define MXC_CCM_CGR0_ECT_OFFSET 14 +#define MXC_CCM_CGR0_ECT_MASK (0x3 << 14) +#define MXC_CCM_CGR0_EMI_OFFSET 18 +#define MXC_CCM_CGR0_EMI_MASK (0x3 << 18) +#define MXC_CCM_CGR0_EPIT1_OFFSET 20 +#define MXC_CCM_CGR0_EPIT1_MASK (0x3 << 20) +#define MXC_CCM_CGR0_EPIT2_OFFSET 22 +#define MXC_CCM_CGR0_EPIT2_MASK (0x3 << 22) +#define MXC_CCM_CGR0_ESAI_OFFSET 24 +#define MXC_CCM_CGR0_ESAI_MASK (0x3 << 24) +#define MXC_CCM_CGR0_ESDHC1_OFFSET 26 +#define MXC_CCM_CGR0_ESDHC1_MASK (0x3 << 26) +#define MXC_CCM_CGR0_ESDHC2_OFFSET 28 +#define MXC_CCM_CGR0_ESDHC2_MASK (0x3 << 28) +#define MXC_CCM_CGR0_ESDHC3_OFFSET 30 +#define MXC_CCM_CGR0_ESDHC3_MASK (0x3 << 30) + +#define MXC_CCM_CGR1_FEC_OFFSET 0 +#define MXC_CCM_CGR1_FEC_MASK (0x3 << 0) +#define MXC_CCM_CGR1_GPIO1_OFFSET 2 +#define MXC_CCM_CGR1_GPIO1_MASK (0x3 << 2) +#define MXC_CCM_CGR1_GPIO2_OFFSET 4 +#define MXC_CCM_CGR1_GPIO2_MASK (0x3 << 4) +#define MXC_CCM_CGR1_GPIO3_OFFSET 6 +#define MXC_CCM_CGR1_GPIO3_MASK (0x3 << 6) +#define MXC_CCM_CGR1_GPT_OFFSET 8 +#define MXC_CCM_CGR1_GPT_MASK (0x3 << 8) +#define MXC_CCM_CGR1_I2C1_OFFSET 10 +#define MXC_CCM_CGR1_I2C1_MASK (0x3 << 10) +#define MXC_CCM_CGR1_I2C2_OFFSET 12 +#define MXC_CCM_CGR1_I2C2_MASK (0x3 << 12) +#define MXC_CCM_CGR1_I2C3_OFFSET 14 +#define MXC_CCM_CGR1_I2C3_MASK (0x3 << 14) +#define MXC_CCM_CGR1_IOMUXC_OFFSET 16 +#define MXC_CCM_CGR1_IOMUXC_MASK (0x3 << 16) +#define MXC_CCM_CGR1_IPU_OFFSET 18 +#define MXC_CCM_CGR1_IPU_MASK (0x3 << 18) +#define MXC_CCM_CGR1_KPP_OFFSET 20 +#define MXC_CCM_CGR1_KPP_MASK (0x3 << 20) +#define MXC_CCM_CGR1_MLB_OFFSET 22 +#define MXC_CCM_CGR1_MLB_MASK (0x3 << 22) +#define MXC_CCM_CGR1_MSHC_OFFSET 24 +#define MXC_CCM_CGR1_MSHC_MASK (0x3 << 24) +#define MXC_CCM_CGR1_OWIRE_OFFSET 26 +#define MXC_CCM_CGR1_OWIRE_MASK (0x3 << 26) +#define MXC_CCM_CGR1_PWM_OFFSET 28 +#define MXC_CCM_CGR1_PWM_MASK (0x3 << 28) +#define MXC_CCM_CGR1_RNGC_OFFSET 30 +#define MXC_CCM_CGR1_RNGC_MASK (0x3 << 30) + +#define MXC_CCM_CGR2_RTC_OFFSET 0 +#define MXC_CCM_CGR2_RTC_MASK (0x3 << 0) +#define MXC_CCM_CGR2_RTIC_OFFSET 2 +#define MXC_CCM_CGR2_RTIC_MASK (0x3 << 2) +#define MXC_CCM_CGR2_SCC_OFFSET 4 +#define MXC_CCM_CGR2_SCC_MASK (0x3 << 4) +#define MXC_CCM_CGR2_SDMA_OFFSET 6 +#define MXC_CCM_CGR2_SDMA_MASK (0x3 << 6) +#define MXC_CCM_CGR2_SPBA_OFFSET 8 +#define MXC_CCM_CGR2_SPBA_MASK (0x3 << 8) +#define MXC_CCM_CGR2_SPDIF_OFFSET 10 +#define MXC_CCM_CGR2_SPDIF_MASK (0x3 << 10) +#define MXC_CCM_CGR2_SSI1_OFFSET 12 +#define MXC_CCM_CGR2_SSI1_MASK (0x3 << 12) +#define MXC_CCM_CGR2_SSI2_OFFSET 14 +#define MXC_CCM_CGR2_SSI2_MASK (0x3 << 14) +#define MXC_CCM_CGR2_UART1_OFFSET 16 +#define MXC_CCM_CGR2_UART1_MASK (0x3 << 16) +#define MXC_CCM_CGR2_UART2_OFFSET 18 +#define MXC_CCM_CGR2_UART2_MASK (0x3 << 18) +#define MXC_CCM_CGR2_UART3_OFFSET 20 +#define MXC_CCM_CGR2_UART3_MASK (0x3 << 20) +#define MXC_CCM_CGR2_USBOTG_OFFSET 22 +#define MXC_CCM_CGR2_USBOTG_MASK (0x3 << 22) +#define MXC_CCM_CGR2_WDOG_OFFSET 24 +#define MXC_CCM_CGR2_WDOG_MASK (0x3 << 24) +#define MXC_CCM_CGR2_MAX_OFFSET 26 +#define MXC_CCM_CGR2_MAX_MASK (0x3 << 26) +#define MXC_CCM_CGR2_MAX_ENABLE (0x2 << 26) +#define MXC_CCM_CGR2_AUDMUX_OFFSET 30 +#define MXC_CCM_CGR2_AUDMUX_MASK (0x3 << 30) + +#define MXC_CCM_CGR3_CSI_OFFSET 0 +#define MXC_CCM_CGR3_CSI_MASK (0x3 << 0) +#define MXC_CCM_CGR3_IIM_OFFSET 2 +#define MXC_CCM_CGR3_IIM_MASK (0x3 << 2) +#define MXC_CCM_CGR3_GPU2D_OFFSET 4 +#define MXC_CCM_CGR3_GPU2D_MASK (0x3 << 4) +/* + * LTR0 register offsets + */ +#define MXC_CCM_LTR0_DNTHR_OFFSET 16 +#define MXC_CCM_LTR0_DNTHR_MASK (0x3F << 16) +#define MXC_CCM_LTR0_UPTHR_OFFSET 22 +#define MXC_CCM_LTR0_UPTHR_MASK (0x3F << 22) +#define MXC_CCM_LTR0_DIV3CK_OFFSET 1 +#define MXC_CCM_LTR0_DIV3CK_MASK (0x3 << 1) + +/* + * LTR1 register offsets + */ +#define MXC_CCM_LTR1_PNCTHR_OFFSET 0 +#define MXC_CCM_LTR1_PNCTHR_MASK 0x3F +#define MXC_CCM_LTR1_UPCNT_OFFSET 6 +#define MXC_CCM_LTR1_UPCNT_MASK (0xFF << 6) +#define MXC_CCM_LTR1_DNCNT_OFFSET 14 +#define MXC_CCM_LTR1_DNCNT_MASK (0xFF << 14) +#define MXC_CCM_LTR1_LTBRSR_MASK 0x400000 +#define MXC_CCM_LTR1_LTBRSR_OFFSET 22 +#define MXC_CCM_LTR1_LTBRSR 0x400000 +#define MXC_CCM_LTR1_LTBRSH 0x800000 + +/* + * LTR2 bit definitions. x ranges from 0 for WSW9 to 6 for WSW15 + */ +#define MXC_CCM_LTR2_WSW_OFFSET(x) (11 + (x) * 3) +#define MXC_CCM_LTR2_WSW_MASK(x) (0x7 << MXC_CCM_LTR2_WSW_OFFSET((x))) +#define MXC_CCM_LTR2_EMAC_OFFSET 0 +#define MXC_CCM_LTR2_EMAC_MASK 0x1FF + +/* + * LTR3 bit definitions. x ranges from 0 for WSW0 to 8 for WSW8 + */ +#define MXC_CCM_LTR3_WSW_OFFSET(x) (5 + (x) * 3) +#define MXC_CCM_LTR3_WSW_MASK(x) (0x7 << MXC_CCM_LTR3_WSW_OFFSET((x))) + +#define DVSUP_TURBO 0 +#define DVSUP_HIGH 1 +#define DVSUP_MEDIUM 2 +#define DVSUP_LOW 3 +#define MXC_CCM_PMCR0_DVSUP_TURBO (DVSUP_TURBO << 28) +#define MXC_CCM_PMCR0_DVSUP_HIGH (DVSUP_HIGH << 28) +#define MXC_CCM_PMCR0_DVSUP_MEDIUM (DVSUP_MEDIUM << 28) +#define MXC_CCM_PMCR0_DVSUP_LOW (DVSUP_LOW << 28) +#define MXC_CCM_PMCR0_DVSUP_OFFSET 28 +#define MXC_CCM_PMCR0_DVSUP_MASK (0x3 << 28) +#define MXC_CCM_PMCR0_DVFS_UPDATE_FINISH 0x01000000 +#define MXC_CCM_PMCR0_DVFEV 0x00800000 +#define MXC_CCM_PMCR0_DVFIS 0x00400000 +#define MXC_CCM_PMCR0_LBMI 0x00200000 +#define MXC_CCM_PMCR0_LBFL 0x00100000 +#define MXC_CCM_PMCR0_LBCF_4 (0x0 << 18) +#define MXC_CCM_PMCR0_LBCF_8 (0x1 << 18) +#define MXC_CCM_PMCR0_LBCF_12 (0x2 << 18) +#define MXC_CCM_PMCR0_LBCF_16 (0x3 << 18) +#define MXC_CCM_PMCR0_LBCF_OFFSET 18 +#define MXC_CCM_PMCR0_LBCF_MASK (0x3 << 18) +#define MXC_CCM_PMCR0_PTVIS 0x00020000 +#define MXC_CCM_PMCR0_DVFS_START 0x00010000 +#define MXC_CCM_PMCR0_DVFS_START_MASK 0x1 << 16) +#define MXC_CCM_PMCR0_FSVAIM 0x00008000 +#define MXC_CCM_PMCR0_FSVAI_OFFSET 13 +#define MXC_CCM_PMCR0_FSVAI_MASK (0x3 << 13) +#define MXC_CCM_PMCR0_DPVCR 0x00001000 +#define MXC_CCM_PMCR0_DPVV 0x00000800 +#define MXC_CCM_PMCR0_WFIM 0x00000400 +#define MXC_CCM_PMCR0_DRCE3 0x00000200 +#define MXC_CCM_PMCR0_DRCE2 0x00000100 +#define MXC_CCM_PMCR0_DRCE1 0x00000080 +#define MXC_CCM_PMCR0_DRCE0 0x00000040 +#define MXC_CCM_PMCR0_DCR 0x00000020 +#define MXC_CCM_PMCR0_DVFEN 0x00000010 +#define MXC_CCM_PMCR0_PTVAIM 0x00000008 +#define MXC_CCM_PMCR0_PTVAI_OFFSET 1 +#define MXC_CCM_PMCR0_PTVAI_MASK (0x3 << 1) +#define MXC_CCM_PMCR0_DPTEN 0x00000001 + +#define MXC_CCM_PMCR1_DVGP_OFFSET 0 +#define MXC_CCM_PMCR1_DVGP_MASK (0xF) + +#define MXC_CCM_PMCR1_PLLRDIS (0x1 << 7) +#define MXC_CCM_PMCR1_EMIRQ_EN (0x1 << 8) + +#define MXC_CCM_DCVR_ULV_MASK (0x3FF << 22) +#define MXC_CCM_DCVR_ULV_OFFSET 22 +#define MXC_CCM_DCVR_LLV_MASK (0x3FF << 12) +#define MXC_CCM_DCVR_LLV_OFFSET 12 +#define MXC_CCM_DCVR_ELV_MASK (0x3FF << 2) +#define MXC_CCM_DCVR_ELV_OFFSET 2 + +#define MXC_CCM_PDR2_MST2_PDF_MASK (0x3F << 7) +#define MXC_CCM_PDR2_MST2_PDF_OFFSET 7 +#define MXC_CCM_PDR2_MST1_PDF_MASK 0x3F +#define MXC_CCM_PDR2_MST1_PDF_OFFSET 0 + +#define MXC_CCM_COSR_CLKOSEL_MASK 0x1F +#define MXC_CCM_COSR_CLKOSEL_OFFSET 0 +#define MXC_CCM_COSR_CLKOEN (1 << 5) +#define MXC_CCM_COSR_CLKOUTDIV_1 (1 << 6) +#define MXC_CCM_COSR_CLKOUT_PREDIV_MASK (0x7 << 13) +#define MXC_CCM_COSR_CLKOUT_PREDIV_OFFSET 13 +#define MXC_CCM_COSR_CLKOUT_PRODIV_MASK (0x7 << 10) +#define MXC_CCM_COSR_CLKOUT_PRODIV_OFFSET 10 +#define MXC_CCM_COSR_SSI1_RX_SRC_SEL_MASK (0x3 << 16) +#define MXC_CCM_COSR_SSI1_RX_SRC_SEL_OFFSET 16 +#define MXC_CCM_COSR_SSI1_TX_SRC_SEL_MASK (0x3 << 18) +#define MXC_CCM_COSR_SSI1_TX_SRC_SEL_OFFSET 18 +#define MXC_CCM_COSR_SSI2_RX_SRC_SEL_MASK (0x3 << 20) +#define MXC_CCM_COSR_SSI2_RX_SRC_SEL_OFFSET 20 +#define MXC_CCM_COSR_SSI2_TX_SRC_SEL_MASK (0x3 << 22) +#define MXC_CCM_COSR_SSI2_TX_SRC_SEL_OFFSET 22 +#define MXC_CCM_COSR_ASRC_AUDIO_EN (1 << 24) +#define MXC_CCM_COSR_ASRC_AUDIO_PODF_MASK (0x3F << 26) +#define MXC_CCM_COSR_ASRC_AUDIO_PODF_OFFSET 26 + +/* extra definitions for Version 2 */ +#define MXC_CCM_COSR_CKIL_CKIH_MASK (1 << 7) +#define MXC_CCM_COSR_CKIL_CKIH_OFFSET 7 +#define MXC_CCM_COSR_CLKOUT_PRODIV_MASK_V2 (0x3F << 10) + +/* + * PMCR0 register offsets + */ +#define MXC_CCM_PMCR0_LBFL_OFFSET 20 +#define MXC_CCM_PMCR0_DFSUP0_OFFSET 30 +#define MXC_CCM_PMCR0_DFSUP1_OFFSET 31 + +/* + * PMCR2 register definitions + */ +#define MXC_CCM_PMCR2_OSC24M_DOWN (1 << 16) +#define MXC_CCM_PMCR2_OSC_AUDIO_DOWN (1 << 17) + +#endif /* __ARCH_ARM_MACH_MX3_CRM_REGS_H__ */ diff --git a/arch/arm/mach-mx35/devices.c b/arch/arm/mach-mx35/devices.c new file mode 100644 index 000000000000..769b7ac0541f --- /dev/null +++ b/arch/arm/mach-mx35/devices.c @@ -0,0 +1,804 @@ +/* + * 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/init.h> +#include <linux/io.h> +#include <linux/platform_device.h> +#include <linux/clk.h> +#include <linux/spi/spi.h> + +#include <mach/hardware.h> +#include <mach/mmc.h> +#include <mach/spba.h> +#include <mach/sdma.h> + +#include "iomux.h" +#include "sdma_script_code.h" +#include "sdma_script_code_v2.h" +#include "board-mx35_3stack.h" + +void mxc_sdma_get_script_info(sdma_script_start_addrs * sdma_script_addr) +{ + if (cpu_is_mx35_rev(CHIP_REV_2_0) < 1) { + 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_loopback_on_dsp_side_addr = -1; + sdma_script_addr->mxc_sdma_mcu_interrupt_only_addr = -1; + + 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; + + 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; + 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; + + sdma_script_addr->mxc_sdma_per_2_per_addr = p_2_p_ADDR; + + 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; + sdma_script_addr->mxc_sdma_per_2_shp_addr = per_2_shp_ADDR; + sdma_script_addr->mxc_sdma_mcu_2_shp_addr = mcu_2_shp_ADDR; + + sdma_script_addr->mxc_sdma_ata_2_mcu_addr = ata_2_mcu_ADDR; + sdma_script_addr->mxc_sdma_mcu_2_ata_addr = mcu_2_ata_ADDR; + + 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_shp_2_per_addr = shp_2_per_ADDR; + sdma_script_addr->mxc_sdma_shp_2_mcu_addr = shp_2_mcu_ADDR; + + sdma_script_addr->mxc_sdma_mshc_2_mcu_addr = -1; + sdma_script_addr->mxc_sdma_mcu_2_mshc_addr = -1; + + sdma_script_addr->mxc_sdma_spdif_2_mcu_addr = spdif_2_mcu_ADDR; + sdma_script_addr->mxc_sdma_mcu_2_spdif_addr = mcu_2_spdif_ADDR; + + sdma_script_addr->mxc_sdma_asrc_2_mcu_addr = asrc__mcu_ADDR; + + sdma_script_addr->mxc_sdma_dptc_dvfs_addr = -1; + sdma_script_addr->mxc_sdma_ext_mem_2_ipu_addr = + ext_mem__ipu_ram_ADDR; + sdma_script_addr->mxc_sdma_descrambler_addr = -1; + + sdma_script_addr->mxc_sdma_start_addr = + (unsigned short *)sdma_code; + sdma_script_addr->mxc_sdma_ram_code_size = RAM_CODE_SIZE; + sdma_script_addr->mxc_sdma_ram_code_start_addr = + RAM_CODE_START_ADDR; + } else { + sdma_script_addr->mxc_sdma_ap_2_ap_addr = ap_2_ap_ADDR_V2; + 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_loopback_on_dsp_side_addr = -1; + sdma_script_addr->mxc_sdma_mcu_interrupt_only_addr = -1; + + 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; + + sdma_script_addr->mxc_sdma_uart_2_per_addr = uart_2_per_ADDR_V2; + sdma_script_addr->mxc_sdma_uart_2_mcu_addr = uart_2_mcu_ADDR_V2; + sdma_script_addr->mxc_sdma_per_2_app_addr = per_2_app_ADDR_V2; + sdma_script_addr->mxc_sdma_mcu_2_app_addr = mcu_2_app_ADDR_V2; + + sdma_script_addr->mxc_sdma_per_2_per_addr = p_2_p_ADDR_V2; + + sdma_script_addr->mxc_sdma_uartsh_2_per_addr = + uartsh_2_per_ADDR_V2; + sdma_script_addr->mxc_sdma_uartsh_2_mcu_addr = + uartsh_2_mcu_ADDR_V2; + sdma_script_addr->mxc_sdma_per_2_shp_addr = per_2_shp_ADDR_V2; + sdma_script_addr->mxc_sdma_mcu_2_shp_addr = mcu_2_shp_ADDR_V2; + + sdma_script_addr->mxc_sdma_ata_2_mcu_addr = ata_2_mcu_ADDR_V2; + sdma_script_addr->mxc_sdma_mcu_2_ata_addr = mcu_2_ata_ADDR_V2; + + sdma_script_addr->mxc_sdma_app_2_per_addr = app_2_per_ADDR_V2; + sdma_script_addr->mxc_sdma_app_2_mcu_addr = app_2_mcu_ADDR_V2; + sdma_script_addr->mxc_sdma_shp_2_per_addr = shp_2_per_ADDR_V2; + sdma_script_addr->mxc_sdma_shp_2_mcu_addr = shp_2_mcu_ADDR_V2; + + sdma_script_addr->mxc_sdma_mshc_2_mcu_addr = -1; + sdma_script_addr->mxc_sdma_mcu_2_mshc_addr = -1; + + sdma_script_addr->mxc_sdma_spdif_2_mcu_addr = + spdif_2_mcu_ADDR_V2; + sdma_script_addr->mxc_sdma_mcu_2_spdif_addr = + mcu_2_spdif_ADDR_V2; + + sdma_script_addr->mxc_sdma_asrc_2_mcu_addr = asrc__mcu_ADDR_V2; + + sdma_script_addr->mxc_sdma_dptc_dvfs_addr = -1; + sdma_script_addr->mxc_sdma_ext_mem_2_ipu_addr = + ext_mem__ipu_ram_ADDR_V2; + sdma_script_addr->mxc_sdma_descrambler_addr = -1; + + sdma_script_addr->mxc_sdma_start_addr = + (unsigned short *)sdma_code_v2; + sdma_script_addr->mxc_sdma_ram_code_size = RAM_CODE_SIZE; + sdma_script_addr->mxc_sdma_ram_code_start_addr = + RAM_CODE_START_ADDR_V2; + } +} + +static void mxc_nop_release(struct device *dev) +{ + /* Nothing */ +} + +#if defined(CONFIG_RTC_MXC) || defined(CONFIG_RTC_MXC_MODULE) +static struct resource rtc_resources[] = { + { + .start = RTC_BASE_ADDR, + .end = RTC_BASE_ADDR + 0x30, + .flags = IORESOURCE_MEM, + }, + { + .start = MXC_INT_RTC, + .flags = IORESOURCE_IRQ, + }, +}; +static struct platform_device mxc_rtc_device = { + .name = "mxc_rtc", + .id = 0, + .dev = { + .release = mxc_nop_release, + }, + .num_resources = ARRAY_SIZE(rtc_resources), + .resource = rtc_resources, +}; +static void mxc_init_rtc(void) +{ + (void)platform_device_register(&mxc_rtc_device); +} +#else +static inline void mxc_init_rtc(void) +{ +} +#endif + +#if defined(CONFIG_MXC_MC9SDZ60_RTC) || defined(CONFIG_MXC_MC9SDZ60_RTC_MODULE) +static struct resource pmic_rtc_resources[] = { + { + .start = MXC_PSEUDO_IRQ_RTC, + .flags = IORESOURCE_IRQ, + }, +}; +static struct platform_device pmic_rtc_device = { + .name = "pmic_rtc", + .id = 0, + .dev = { + .release = mxc_nop_release, + }, + .num_resources = ARRAY_SIZE(pmic_rtc_resources), + .resource = pmic_rtc_resources, +}; +static void pmic_init_rtc(void) +{ + platform_device_register(&pmic_rtc_device); +} +#else +static void pmic_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_IPU) || defined(CONFIG_MXC_IPU_MODULE) +static struct mxc_ipu_config mxc_ipu_data = { + .rev = 2, +}; + +static struct resource ipu_resources[] = { + { + .start = IPU_CTRL_BASE_ADDR, + .end = IPU_CTRL_BASE_ADDR + SZ_4K, + .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) +{ + platform_device_register(&mxc_ipu_device); +} +#else +static inline void mxc_init_ipu(void) +{ +} +#endif + +/* SPI controller and device data */ +#if defined(CONFIG_SPI_MXC) || defined(CONFIG_SPI_MXC_MODULE) + +#ifdef CONFIG_SPI_MXC_SELECT1 +/*! + * Resource definition for the CSPI1 + */ +static struct resource mxcspi1_resources[] = { + [0] = { + .start = CSPI1_BASE_ADDR, + .end = CSPI1_BASE_ADDR + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = MXC_INT_CSPI1, + .end = MXC_INT_CSPI1, + .flags = IORESOURCE_IRQ, + }, +}; + +/*! Platform Data for MXC CSPI1 */ +static struct mxc_spi_master mxcspi1_data = { + .maxchipselect = 4, + .spi_version = 7, +}; + +/*! 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 = 7, +}; + +/*! 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 */ + +static inline void mxc_init_spi(void) +{ + /* SPBA configuration for CSPI2 - MCU is set */ + spba_take_ownership(SPBA_CSPI2, SPBA_MASTER_A); +#ifdef CONFIG_SPI_MXC_SELECT1 + 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 */ +} +#else +static inline void 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 = I2C_BASE_ADDR, + .end = I2C_BASE_ADDR + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = MXC_INT_I2C, + .end = MXC_INT_I2C, + .flags = IORESOURCE_IRQ, + }, +}; + +/*! Platform Data for MXC I2C */ +static struct mxc_i2c_platform_data mxci2c1_data = { + .i2c_clk = 100000, +}; +#endif + +/*! + * Resource definition for the I2C2 + */ +static struct resource mxci2c2_resources[] = { + [0] = { + .start = I2C2_BASE_ADDR, + .end = I2C2_BASE_ADDR + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = MXC_INT_I2C2, + .end = MXC_INT_I2C2, + .flags = IORESOURCE_IRQ, + }, +}; + +/*! Platform Data for MXC I2C */ +static struct mxc_i2c_platform_data mxci2c2_data = { + .i2c_clk = 100000, +}; + +#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 + { + .name = "mxc_i2c_slave", + .id = 1, + .dev = { + .release = mxc_nop_release, + .platform_data = &mxci2c2_data, + }, + .num_resources = ARRAY_SIZE(mxci2c2_resources), + .resource = mxci2c2_resources,}, +#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 + +struct mxc_gpio_port mxc_gpio_ports[] = { + [0] = { + .chip.label = "gpio-0", + .base = IO_ADDRESS(GPIO1_BASE_ADDR), + .irq = MXC_INT_GPIO1, + .irq_high = 0, + .virtual_irq_start = MXC_GPIO_IRQ_START + }, + [1] = { + .chip.label = "gpio-1", + .base = IO_ADDRESS(GPIO2_BASE_ADDR), + .irq = MXC_INT_GPIO2, + .irq_high = 0, + .virtual_irq_start = MXC_GPIO_IRQ_START + 32 + }, + [2] = { + .chip.label = "gpio-2", + .base = IO_ADDRESS(GPIO3_BASE_ADDR), + .irq = MXC_INT_GPIO3, + .irq_high = 0, + .virtual_irq_start = MXC_GPIO_IRQ_START + 32 * 2 + } +}; + +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 = 1, + .spdif_clk_44100 = 3, /* spdif_ext_clk source for 44.1KHz */ + .spdif_clk_48000 = 0, /* 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_clk = clk_get(NULL, "spdif_ipg_clk"); + clk_put(mxc_spdif_data.spdif_clk); + mxc_spdif_data.spdif_core_clk = clk_get(NULL, "spdif_clk"); + clk_put(mxc_spdif_data.spdif_core_clk); + mxc_spdif_data.spdif_audio_clk = clk_get(NULL, "spdif_audio_clk"); + clk_put(mxc_spdif_data.spdif_audio_clk); + platform_device_register(&mxc_alsa_spdif_device); +} + +static struct platform_device mxc_alsa_surround_device = { + .name = "imx-3stack-wm8580", + .id = 0, + .dev = { + .release = mxc_nop_release, + }, +}; + +static void mxc_init_surround_audio(void) +{ + platform_device_register(&mxc_alsa_surround_device); +} + +static struct mxc_audio_platform_data mxc_bt_audio_data; + +static struct platform_device mxc_bt_alsa_device = { + .name = "imx-3stack-bt", + .id = 0, + .dev = { + .release = mxc_nop_release, + .platform_data = &mxc_bt_audio_data, + }, + +}; + +static void mxc_init_bt_audio(void) +{ + mxc_bt_audio_data.src_port = 2; + mxc_bt_audio_data.ext_port = 5; + mxc_bt_audio_data.ext_ram = 1; + platform_device_register(&mxc_bt_alsa_device); +} + +static struct resource asrc_resources[] = { + { + .start = ASRC_BASE_ADDR, + .end = ASRC_BASE_ADDR + 0x9C, + .flags = IORESOURCE_MEM, + }, +}; + +static struct mxc_asrc_platform_data mxc_asrc_data; + +static struct platform_device mxc_asrc_device = { + .name = "mxc_asrc", + .id = 0, + .dev = { + .release = mxc_nop_release, + .platform_data = &mxc_asrc_data, + }, + .num_resources = ARRAY_SIZE(asrc_resources), + .resource = asrc_resources, +}; + +static inline void mxc_init_asrc(void) +{ + if (cpu_is_mx35_rev(CHIP_REV_2_0) < 1) + mxc_asrc_data.channel_bits = 3; + else + mxc_asrc_data.channel_bits = 4; + + mxc_asrc_data.asrc_core_clk = clk_get(NULL, "asrc_clk"); + clk_put(mxc_asrc_data.asrc_core_clk); + mxc_asrc_data.asrc_audio_clk = clk_get(NULL, "asrc_audio_clk"); + clk_set_rate(mxc_asrc_data.asrc_audio_clk, 768000); + clk_put(mxc_asrc_data.asrc_audio_clk); + platform_device_register(&mxc_asrc_device); +} + +#if defined(CONFIG_CAN_FLEXCAN) || defined(CONFIG_CAN_FLEXCAN_MODULE) + +static struct resource flexcan1_resources[] = { + { + .start = CAN1_BASE_ADDR, + .end = CAN1_BASE_ADDR + 0x97F, + .flags = IORESOURCE_MEM,}, + { + .start = MXC_INT_CAN1, + .end = MXC_INT_CAN1, + .flags = IORESOURCE_IRQ,} +}; + +static struct resource flexcan2_resources[] = { + { + .start = CAN2_BASE_ADDR, + .end = CAN2_BASE_ADDR + 0x97F, + .flags = IORESOURCE_MEM,}, + { + .start = MXC_INT_CAN2, + .end = MXC_INT_CAN2, + .flags = IORESOURCE_IRQ,} +}; + +static struct platform_device flexcan_devices[] = { + { + .name = "FlexCAN", + .id = 0, + .dev = { + .release = mxc_nop_release, + .platform_data = &flexcan_data[0], + }, + .num_resources = ARRAY_SIZE(flexcan1_resources), + .resource = flexcan1_resources,}, + { + .name = "FlexCAN", + .id = 1, + .dev = { + .release = mxc_nop_release, + .platform_data = &flexcan_data[1], + }, + .num_resources = ARRAY_SIZE(flexcan2_resources), + .resource = flexcan2_resources,}, +}; + +static inline void mxc_init_flexcan(void) +{ + platform_device_register(&flexcan_devices[0]); + platform_device_register(&flexcan_devices[1]); +} +#else +static inline void mxc_init_flexcan(void) +{ +} +#endif + +#if defined(CONFIG_HW_RANDOM_FSL_RNGC) || \ +defined(CONFIG_HW_RANDOM_FSL_RNGC_MODULE) +static struct resource rngc_resources[] = { + { + .start = RNGC_BASE_ADDR, + .end = RNGC_BASE_ADDR + 0x34, + .flags = IORESOURCE_MEM, + }, + { + .start = MXC_INT_RNG, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device fsl_rngc_device = { + .name = "fsl_rngc", + .id = -1, + .num_resources = ARRAY_SIZE(rngc_resources), + .resource = rngc_resources, +}; + +static inline void mxc_init_rngc(void) +{ + platform_device_register(&fsl_rngc_device); +} +#else +static inline void mxc_init_rngc(void) +{ +} +#endif + +#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[] = { + { + .start = MXC_INT_GPU2D, + .end = MXC_INT_GPU2D, + .name = "gpu_2d_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); +} + +int __init mxc_init_devices(void) +{ + mxc_init_wdt(); + mxc_init_ipu(); + mxc_init_spi(); + mxc_init_i2c(); + pmic_init_rtc(); + mxc_init_rtc(); + mxc_init_dma(); + mxc_init_bt_audio(); + mxc_init_spdif(); + mxc_init_surround_audio(); + mxc_init_asrc(); + mxc_init_flexcan(); + mxc_init_rngc(); + mxc_init_iim(); + mxc_init_gpu(); + + /* SPBA configuration for SSI2 - SDMA and MCU are set */ + spba_take_ownership(SPBA_SSI2, SPBA_MASTER_C | SPBA_MASTER_A); + return 0; +} diff --git a/arch/arm/mach-mx35/dma.c b/arch/arm/mach-mx35/dma.c new file mode 100644 index 000000000000..ef7f557d1cc8 --- /dev/null +++ b/arch/arm/mach-mx35/dma.c @@ -0,0 +1,1046 @@ +/* + * 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" + +#ifdef CONFIG_SND_MXC_SOC_IRAM +#define soc_trans_type int_2_per +#else +#define soc_trans_type emi_2_per +#endif + +#define MXC_SPDIF_TXFIFO_WML 8 +#define MXC_SPDIF_RXFIFO_WML 8 +#define MXC_SPDIF_TX_REG 0x2C +#define MXC_SPDIF_RX_REG 0x14 + +#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_ASRC_FIFO_WML 0x40 +#define MXC_ASRCA_RX_REG 0x60 +#define MXC_ASRCA_TX_REG 0x64 +#define MXC_ASRCB_RX_REG 0x68 +#define MXC_ASRCB_TX_REG 0x6C +#define MXC_ASRCC_RX_REG 0x70 +#define MXC_ASRCC_TX_REG 0x74 + +#define MXC_ESAI_TX_REG 0x00 +#define MXC_ESAI_RX_REG 0x04 +#define MXC_ESAI_FIFO_WML 0x40 + +struct mxc_sdma_info_entry_s { + mxc_dma_device_t device; + void *chnl_info; +}; + +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_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_TX, + .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_TX, + .bd_number = 32, + .word_size = TRANSFER_32BIT, + }, + .channel_num = MXC_DMA_CHANNEL_SPDIF_TX, + .chnl_priority = MXC_SDMA_DEFAULT_PRIORITY, +}; + +static mxc_sdma_channel_params_t mxc_sdma_spdif_32bit_rx_params = { + .chnl_params = { + .watermark_level = MXC_SPDIF_RXFIFO_WML, + .per_address = SPDIF_BASE_ADDR + MXC_SPDIF_RX_REG, + .peripheral_type = SPDIF, + .transfer_type = per_2_emi, + .event_id = DMA_REQ_SPDIF_RX, + .bd_number = 32, + .word_size = TRANSFER_32BIT, + }, + .channel_num = MXC_DMA_CHANNEL_SPDIF_RX, + .chnl_priority = MXC_SDMA_DEFAULT_PRIORITY, +}; + +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_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 = soc_trans_type, + .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 = soc_trans_type, + .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 = soc_trans_type, + .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 = soc_trans_type, + .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 = soc_trans_type, + .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 = soc_trans_type, + .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_asrca_rx_params = { + .chnl_params = { + .watermark_level = MXC_ASRC_FIFO_WML, + .per_address = ASRC_BASE_ADDR + MXC_ASRCA_RX_REG, + .peripheral_type = ASRC, + .transfer_type = emi_2_per, + .event_id = DMA_REQ_ASRC_DMA1, + .bd_number = 32, + .word_size = TRANSFER_32BIT, + }, + .channel_num = MXC_DMA_CHANNEL_ASRCA_RX, + .chnl_priority = MXC_SDMA_DEFAULT_PRIORITY, +}; + +static mxc_sdma_channel_params_t mxc_sdma_asrca_tx_params = { + .chnl_params = { + .watermark_level = MXC_ASRC_FIFO_WML, + .per_address = ASRC_BASE_ADDR + MXC_ASRCA_TX_REG, + .peripheral_type = ASRC, + .transfer_type = per_2_emi, + .event_id = DMA_REQ_ASRC_DMA4, + .bd_number = 32, + .word_size = TRANSFER_32BIT, + }, + .channel_num = MXC_DMA_CHANNEL_ASRCA_TX, + .chnl_priority = MXC_SDMA_DEFAULT_PRIORITY, +}; + +static mxc_sdma_channel_params_t mxc_sdma_asrcb_rx_params = { + .chnl_params = { + .watermark_level = MXC_ASRC_FIFO_WML, + .per_address = ASRC_BASE_ADDR + MXC_ASRCB_RX_REG, + .peripheral_type = ASRC, + .transfer_type = emi_2_per, + .event_id = DMA_REQ_ASRC_DMA2, + .bd_number = 32, + .word_size = TRANSFER_32BIT, + }, + .channel_num = MXC_DMA_CHANNEL_ASRCB_RX, + .chnl_priority = MXC_SDMA_DEFAULT_PRIORITY, +}; + +static mxc_sdma_channel_params_t mxc_sdma_asrcb_tx_params = { + .chnl_params = { + .watermark_level = MXC_ASRC_FIFO_WML, + .per_address = ASRC_BASE_ADDR + MXC_ASRCB_TX_REG, + .peripheral_type = ASRC, + .transfer_type = per_2_emi, + .event_id = DMA_REQ_ASRC_DMA5, + .bd_number = 32, + .word_size = TRANSFER_32BIT, + }, + .channel_num = MXC_DMA_CHANNEL_ASRCB_TX, + .chnl_priority = MXC_SDMA_DEFAULT_PRIORITY, +}; + +static mxc_sdma_channel_params_t mxc_sdma_asrcc_rx_params = { + .chnl_params = { + .watermark_level = MXC_ASRC_FIFO_WML * 3, + .per_address = ASRC_BASE_ADDR + MXC_ASRCC_RX_REG, + .peripheral_type = ASRC, + .transfer_type = emi_2_per, + .event_id = DMA_REQ_ASRC_DMA3, + .bd_number = 32, + .word_size = TRANSFER_32BIT, + }, + .channel_num = MXC_DMA_CHANNEL_ASRCC_RX, + .chnl_priority = MXC_SDMA_DEFAULT_PRIORITY, +}; + +static mxc_sdma_channel_params_t mxc_sdma_asrcc_tx_params = { + .chnl_params = { + .watermark_level = MXC_ASRC_FIFO_WML * 3, + .per_address = ASRC_BASE_ADDR + MXC_ASRCC_TX_REG, + .peripheral_type = ASRC, + .transfer_type = per_2_emi, + .event_id = DMA_REQ_ASRC_DMA6, + .bd_number = 32, + .word_size = TRANSFER_32BIT, + }, + .channel_num = MXC_DMA_CHANNEL_ASRCC_TX, + .chnl_priority = MXC_SDMA_DEFAULT_PRIORITY, +}; + +static mxc_sdma_channel_ext_params_t mxc_sdma_asrca_ssi1_tx0_params = { + .chnl_ext_params = { + .common = { + .watermark_level = + MXC_ASRC_FIFO_WML >> 1, + .per_address = + SSI1_BASE_ADDR + MXC_SSI_TX0_REG, + .peripheral_type = ASRC, + .transfer_type = per_2_per, + .event_id = DMA_REQ_SSI1_TX1, + .event_id2 = DMA_REQ_ASRC_DMA4, + .bd_number = 32, + .word_size = TRANSFER_32BIT, + .ext = 1, + }, + .p2p_dir = 0, + .info_bits = + SDMA_ASRC_P2P_INFO_CONT | SDMA_ASRC_P2P_INFO_SP, + .watermark_level2 = MXC_SSI_TXFIFO_WML, + .per_address2 = ASRC_BASE_ADDR + MXC_ASRCA_TX_REG, + }, + .channel_num = MXC_DMA_CHANNEL_ASRCA_SSI1_TX0, + .chnl_priority = MXC_SDMA_DEFAULT_PRIORITY, +}; + +static mxc_sdma_channel_ext_params_t mxc_sdma_asrca_ssi1_tx1_params = { + .chnl_ext_params = { + .common = { + .watermark_level = + MXC_ASRC_FIFO_WML >> 1, + .per_address = + SSI1_BASE_ADDR + MXC_SSI_TX1_REG, + .peripheral_type = ASRC, + .transfer_type = per_2_per, + .event_id = DMA_REQ_SSI1_TX2, + .event_id2 = DMA_REQ_ASRC_DMA4, + .bd_number = 32, + .word_size = TRANSFER_32BIT, + .ext = 1, + }, + .p2p_dir = 0, + .info_bits = + SDMA_ASRC_P2P_INFO_CONT | SDMA_ASRC_P2P_INFO_SP, + .watermark_level2 = MXC_SSI_TXFIFO_WML, + .per_address2 = ASRC_BASE_ADDR + MXC_ASRCA_TX_REG, + }, + .channel_num = MXC_DMA_CHANNEL_ASRCA_SSI1_TX1, + .chnl_priority = MXC_SDMA_DEFAULT_PRIORITY, +}; + +static mxc_sdma_channel_ext_params_t mxc_sdma_asrca_ssi2_tx0_params = { + .chnl_ext_params = { + .common = { + .watermark_level = + MXC_ASRC_FIFO_WML >> 1, + .per_address = + SSI2_BASE_ADDR + MXC_SSI_TX0_REG, + .peripheral_type = ASRC, + .transfer_type = per_2_per, + .event_id = DMA_REQ_SSI2_TX1, + .event_id2 = DMA_REQ_ASRC_DMA4, + .bd_number = 32, + .word_size = TRANSFER_32BIT, + .ext = 1, + }, + .p2p_dir = 0, + .info_bits = + SDMA_ASRC_P2P_INFO_CONT | SDMA_ASRC_P2P_INFO_SP | + SDMA_ASRC_P2P_INFO_DP, + .watermark_level2 = MXC_SSI_TXFIFO_WML, + .per_address2 = ASRC_BASE_ADDR + MXC_ASRCA_TX_REG, + }, + .channel_num = MXC_DMA_CHANNEL_ASRCA_SSI2_TX0, + .chnl_priority = MXC_SDMA_DEFAULT_PRIORITY, +}; + +static mxc_sdma_channel_ext_params_t mxc_sdma_asrca_ssi2_tx1_params = { + .chnl_ext_params = { + .common = { + .watermark_level = + MXC_ASRC_FIFO_WML >> 1, + .per_address = + SSI2_BASE_ADDR + MXC_SSI_TX1_REG, + .peripheral_type = ASRC, + .transfer_type = per_2_per, + .event_id = DMA_REQ_SSI2_TX2, + .event_id2 = DMA_REQ_ASRC_DMA4, + .bd_number = 32, + .word_size = TRANSFER_32BIT, + .ext = 1, + }, + .p2p_dir = 0, + .info_bits = + SDMA_ASRC_P2P_INFO_CONT | SDMA_ASRC_P2P_INFO_SP | + SDMA_ASRC_P2P_INFO_DP, + .watermark_level2 = MXC_SSI_TXFIFO_WML, + .per_address2 = ASRC_BASE_ADDR + MXC_ASRCA_TX_REG, + }, + .channel_num = MXC_DMA_CHANNEL_ASRCA_SSI2_TX1, + .chnl_priority = MXC_SDMA_DEFAULT_PRIORITY, +}; + +static mxc_sdma_channel_ext_params_t mxc_sdma_asrcb_ssi1_tx0_params = { + .chnl_ext_params = { + .common = { + .watermark_level = + MXC_ASRC_FIFO_WML >> 1, + .per_address = + SSI1_BASE_ADDR + MXC_SSI_TX0_REG, + .peripheral_type = ASRC, + .transfer_type = per_2_per, + .event_id = DMA_REQ_SSI1_TX1, + .event_id2 = DMA_REQ_ASRC_DMA5, + .bd_number = 32, + .word_size = TRANSFER_32BIT, + .ext = 1, + }, + .p2p_dir = 0, + .info_bits = + SDMA_ASRC_P2P_INFO_CONT | SDMA_ASRC_P2P_INFO_SP, + .watermark_level2 = MXC_SSI_TXFIFO_WML, + .per_address2 = ASRC_BASE_ADDR + MXC_ASRCB_TX_REG, + }, + .channel_num = MXC_DMA_CHANNEL_ASRCB_SSI1_TX0, + .chnl_priority = MXC_SDMA_DEFAULT_PRIORITY, +}; + +static mxc_sdma_channel_ext_params_t mxc_sdma_asrcb_ssi1_tx1_params = { + .chnl_ext_params = { + .common = { + .watermark_level = + MXC_ASRC_FIFO_WML >> 1, + .per_address = + SSI1_BASE_ADDR + MXC_SSI_TX1_REG, + .peripheral_type = ASRC, + .transfer_type = per_2_per, + .event_id = DMA_REQ_SSI1_TX2, + .event_id2 = DMA_REQ_ASRC_DMA5, + .bd_number = 32, + .word_size = TRANSFER_32BIT, + .ext = 1, + }, + .p2p_dir = 0, + .info_bits = + SDMA_ASRC_P2P_INFO_CONT | SDMA_ASRC_P2P_INFO_SP, + .watermark_level2 = MXC_SSI_TXFIFO_WML, + .per_address2 = ASRC_BASE_ADDR + MXC_ASRCB_TX_REG, + }, + .channel_num = MXC_DMA_CHANNEL_ASRCB_SSI1_TX1, + .chnl_priority = MXC_SDMA_DEFAULT_PRIORITY, +}; + +static mxc_sdma_channel_ext_params_t mxc_sdma_asrcb_ssi2_tx0_params = { + .chnl_ext_params = { + .common = { + .watermark_level = + MXC_ASRC_FIFO_WML >> 1, + .per_address = + SSI2_BASE_ADDR + MXC_SSI_TX0_REG, + .peripheral_type = ASRC, + .transfer_type = per_2_per, + .event_id = DMA_REQ_SSI2_TX1, + .event_id2 = DMA_REQ_ASRC_DMA5, + .bd_number = 32, + .word_size = TRANSFER_32BIT, + .ext = 1, + }, + .p2p_dir = 0, + .info_bits = + SDMA_ASRC_P2P_INFO_CONT | SDMA_ASRC_P2P_INFO_SP | + SDMA_ASRC_P2P_INFO_DP, + .watermark_level2 = MXC_SSI_TXFIFO_WML, + .per_address2 = ASRC_BASE_ADDR + MXC_ASRCB_TX_REG, + }, + .channel_num = MXC_DMA_CHANNEL_ASRCB_SSI2_TX0, + .chnl_priority = MXC_SDMA_DEFAULT_PRIORITY, +}; + +static mxc_sdma_channel_ext_params_t mxc_sdma_asrcb_ssi2_tx1_params = { + .chnl_ext_params = { + .common = { + .watermark_level = + MXC_ASRC_FIFO_WML >> 1, + .per_address = + SSI2_BASE_ADDR + MXC_SSI_TX1_REG, + .peripheral_type = ASRC, + .transfer_type = per_2_per, + .event_id = DMA_REQ_SSI2_TX2, + .event_id2 = DMA_REQ_ASRC_DMA5, + .bd_number = 32, + .word_size = TRANSFER_32BIT, + .ext = 1, + }, + .p2p_dir = 0, + .info_bits = + SDMA_ASRC_P2P_INFO_CONT | SDMA_ASRC_P2P_INFO_SP | + SDMA_ASRC_P2P_INFO_DP, + .watermark_level2 = MXC_SSI_TXFIFO_WML, + .per_address2 = ASRC_BASE_ADDR + MXC_ASRCB_TX_REG, + }, + .channel_num = MXC_DMA_CHANNEL_ASRCB_SSI2_TX1, + .chnl_priority = MXC_SDMA_DEFAULT_PRIORITY, +}; + +static mxc_sdma_channel_ext_params_t mxc_sdma_asrca_esai_params = { + .chnl_ext_params = { + .common = { + .watermark_level = + MXC_ASRC_FIFO_WML >> 1, + .per_address = + ESAI_BASE_ADDR + MXC_ESAI_TX_REG, + .peripheral_type = ASRC, + .transfer_type = per_2_per, + .event_id = DMA_REQ_ESAI_TX, + .event_id2 = DMA_REQ_ASRC_DMA4, + .bd_number = 32, + .word_size = TRANSFER_32BIT, + .ext = 1, + }, + .p2p_dir = 0, + .info_bits = + SDMA_ASRC_P2P_INFO_CONT | SDMA_ASRC_P2P_INFO_SP | + SDMA_ASRC_P2P_INFO_DP, + .watermark_level2 = MXC_ESAI_FIFO_WML, + .per_address2 = ASRC_BASE_ADDR + MXC_ASRCA_TX_REG, + }, + .channel_num = MXC_DMA_CHANNEL_ASRCA_ESAI, + .chnl_priority = MXC_SDMA_DEFAULT_PRIORITY, +}; + +static mxc_sdma_channel_ext_params_t mxc_sdma_asrcb_esai_params = { + .chnl_ext_params = { + .common = { + .watermark_level = + MXC_ASRC_FIFO_WML >> 1, + .per_address = + ESAI_BASE_ADDR + MXC_ESAI_TX_REG, + .peripheral_type = ASRC, + .transfer_type = per_2_per, + .event_id = DMA_REQ_ESAI_TX, + .event_id2 = DMA_REQ_ASRC_DMA5, + .bd_number = 32, + .word_size = TRANSFER_32BIT, + .ext = 1, + }, + .p2p_dir = 0, + .info_bits = + SDMA_ASRC_P2P_INFO_CONT | SDMA_ASRC_P2P_INFO_SP | + SDMA_ASRC_P2P_INFO_DP, + .watermark_level2 = MXC_ESAI_FIFO_WML, + .per_address2 = ASRC_BASE_ADDR + MXC_ASRCB_TX_REG, + }, + .channel_num = MXC_DMA_CHANNEL_ASRCB_ESAI, + .chnl_priority = MXC_SDMA_DEFAULT_PRIORITY, +}; + +static mxc_sdma_channel_ext_params_t mxc_sdma_asrcc_esai_params = { + .chnl_ext_params = { + .common = { + .watermark_level = + MXC_ASRC_FIFO_WML >> 1, + .per_address = + ESAI_BASE_ADDR + MXC_ESAI_TX_REG, + .peripheral_type = ASRC, + .transfer_type = per_2_per, + .event_id = DMA_REQ_ESAI_TX, + .event_id2 = DMA_REQ_ASRC_DMA6, + .bd_number = 32, + .word_size = TRANSFER_32BIT, + .ext = 1, + }, + .p2p_dir = 0, + .info_bits = + SDMA_ASRC_P2P_INFO_CONT | SDMA_ASRC_P2P_INFO_SP | + SDMA_ASRC_P2P_INFO_DP, + .watermark_level2 = MXC_ASRC_FIFO_WML, + .per_address2 = ASRC_BASE_ADDR + MXC_ASRCC_TX_REG, + }, + .channel_num = MXC_DMA_CHANNEL_ASRCC_ESAI, + .chnl_priority = MXC_SDMA_DEFAULT_PRIORITY, +}; + +static mxc_sdma_channel_params_t mxc_sdma_esai_16bit_rx_params = { + .chnl_params = { + .watermark_level = MXC_ESAI_FIFO_WML, + .per_address = ESAI_BASE_ADDR + MXC_ESAI_RX_REG, + .peripheral_type = ESAI, + .transfer_type = per_2_emi, + .event_id = DMA_REQ_ESAI_RX, + .bd_number = 32, + .word_size = TRANSFER_16BIT, + }, + .channel_num = MXC_DMA_CHANNEL_ESAI_RX, + .chnl_priority = MXC_SDMA_DEFAULT_PRIORITY, +}; + +static mxc_sdma_channel_params_t mxc_sdma_esai_16bit_tx_params = { + .chnl_params = { + .watermark_level = MXC_ESAI_FIFO_WML, + .per_address = ESAI_BASE_ADDR + MXC_ESAI_TX_REG, + .peripheral_type = ESAI, + .transfer_type = soc_trans_type, + .event_id = DMA_REQ_ESAI_TX, + .bd_number = 32, + .word_size = TRANSFER_16BIT, + }, + .channel_num = MXC_DMA_CHANNEL_ESAI_TX, + .chnl_priority = MXC_SDMA_DEFAULT_PRIORITY, +}; + +static mxc_sdma_channel_params_t mxc_sdma_esai_24bit_rx_params = { + .chnl_params = { + .watermark_level = MXC_ESAI_FIFO_WML, + .per_address = ESAI_BASE_ADDR + MXC_ESAI_RX_REG, + .peripheral_type = ESAI, + .transfer_type = per_2_emi, + .event_id = DMA_REQ_ESAI_RX, + .bd_number = 32, + .word_size = TRANSFER_32BIT, + }, + .channel_num = MXC_DMA_CHANNEL_ESAI_RX, + .chnl_priority = MXC_SDMA_DEFAULT_PRIORITY, +}; + +static mxc_sdma_channel_params_t mxc_sdma_esai_24bit_tx_params = { + .chnl_params = { + .watermark_level = MXC_ESAI_FIFO_WML, + .per_address = ESAI_BASE_ADDR + MXC_ESAI_TX_REG, + .peripheral_type = ESAI, + .transfer_type = soc_trans_type, + .event_id = DMA_REQ_ESAI_TX, + .bd_number = 32, + .word_size = TRANSFER_32BIT, + }, + .channel_num = MXC_DMA_CHANNEL_ESAI_TX, + .chnl_priority = MXC_SDMA_DEFAULT_PRIORITY, +}; + +static struct mxc_sdma_info_entry_s 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_SPDIF_16BIT_TX, &mxc_sdma_spdif_16bit_tx_params}, + {MXC_DMA_SPDIF_32BIT_TX, &mxc_sdma_spdif_32bit_tx_params}, + {MXC_DMA_SPDIF_32BIT_RX, &mxc_sdma_spdif_32bit_rx_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_ASRC_A_RX, &mxc_sdma_asrca_rx_params}, + {MXC_DMA_ASRC_A_TX, &mxc_sdma_asrca_tx_params}, + {MXC_DMA_ASRC_B_RX, &mxc_sdma_asrcb_rx_params}, + {MXC_DMA_ASRC_B_TX, &mxc_sdma_asrcb_tx_params}, + {MXC_DMA_ASRC_C_RX, &mxc_sdma_asrcc_rx_params}, + {MXC_DMA_ASRC_C_TX, &mxc_sdma_asrcc_tx_params}, + {MXC_DMA_ASRCA_SSI1_TX0, &mxc_sdma_asrca_ssi1_tx0_params}, + {MXC_DMA_ASRCA_SSI1_TX1, &mxc_sdma_asrca_ssi1_tx1_params}, + {MXC_DMA_ASRCA_SSI2_TX0, &mxc_sdma_asrca_ssi2_tx0_params}, + {MXC_DMA_ASRCA_SSI2_TX1, &mxc_sdma_asrca_ssi2_tx1_params}, + {MXC_DMA_ASRCB_SSI1_TX0, &mxc_sdma_asrcb_ssi1_tx0_params}, + {MXC_DMA_ASRCB_SSI1_TX1, &mxc_sdma_asrcb_ssi1_tx1_params}, + {MXC_DMA_ASRCB_SSI2_TX0, &mxc_sdma_asrcb_ssi2_tx0_params}, + {MXC_DMA_ASRCB_SSI2_TX1, &mxc_sdma_asrcb_ssi2_tx1_params}, + {MXC_DMA_ASRCA_ESAI, &mxc_sdma_asrca_esai_params}, + {MXC_DMA_ASRCB_ESAI, &mxc_sdma_asrcb_esai_params}, + {MXC_DMA_ASRCC_ESAI, &mxc_sdma_asrcc_esai_params}, + {MXC_DMA_ESAI_16BIT_RX, &mxc_sdma_esai_16bit_rx_params}, + {MXC_DMA_ESAI_16BIT_TX, &mxc_sdma_esai_16bit_tx_params}, + {MXC_DMA_ESAI_24BIT_RX, &mxc_sdma_esai_24bit_rx_params}, + {MXC_DMA_ESAI_24BIT_TX, &mxc_sdma_esai_24bit_tx_params}, + {MXC_DMA_MEMORY, &mxc_sdma_memory_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) +{ + struct mxc_sdma_info_entry_s *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; +} + +EXPORT_SYMBOL(mxc_sdma_get_channel_params); + +/*! + * 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) +{ + /* No channels statically allocated for MX35 */ +#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_get_static_channels); diff --git a/arch/arm/mach-mx35/dvfs.c b/arch/arm/mach-mx35/dvfs.c new file mode 100644 index 000000000000..c2e3de4f56c3 --- /dev/null +++ b/arch/arm/mach-mx35/dvfs.c @@ -0,0 +1,606 @@ +/* + * 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 dvfs.c + * + * @brief A simplied driver for the Freescale Semiconductor MXC DVFS module. + * + * Upon initialization, the DVFS driver initializes the DVFS hardware + * sets up driver nodes attaches to the DVFS interrupt and initializes internal + * data structures. When the DVFS interrupt occurs the driver checks the cause + * of the interrupt (lower frequency, increase frequency or emergency) and + * changes the CPU voltage according to translation table that is loaded into + * the driver. + * + * @ingroup PM + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/fs.h> +#include <linux/interrupt.h> +#include <linux/io.h> +#include <linux/device.h> +#include <linux/sysdev.h> +#include <linux/delay.h> +#include <linux/clk.h> +#include <linux/regulator/consumer.h> +#include <mach/hardware.h> +#include "crm_regs.h" + +/* + * The frequency of div_3_clk will affect the dvfs sample rate.. + */ +#define DVFS_DIV3CK (3 << MXC_CCM_LTR0_DIV3CK_OFFSET) + +/* + * Panic threshold. Panic frequency change request + * will be sent if DVFS counter value will be more than this value. + */ +#define DVFS_PNCTHR (63 << MXC_CCM_LTR1_PNCTHR_OFFSET) + +/* + * Load tracking buffer source: 1 for ld_add; 0 for pre_ld_add + */ +#define DVFS_LTBRSR (1 << MXC_CCM_LTR1_LTBRSR_OFFSET) + +/* EMAC defines how many samples are included in EMA calculation */ +#define DVFS_EMAC (0x20 << MXC_CCM_LTR2_EMAC_OFFSET) + +/* + * Frequency increase threshold. Increase frequency change request + * will be sent if DVFS counter value will be more than this value. + */ +#define DVFS_UPTHR(val) (val << MXC_CCM_LTR0_UPTHR_OFFSET) + +/* + * Frequency decrease threshold. Decrease frequency change request + * will be sent if DVFS counter value will be less than this value. + */ +#define DVFS_DNTHR(val) (val << MXC_CCM_LTR0_DNTHR_OFFSET) + +/* + * DNCNT defines the amount of times the down threshold should be exceeded + * before DVFS will trigger frequency decrease request. + */ +#define DVFS_DNCNT(val) (val << MXC_CCM_LTR1_DNCNT_OFFSET) + +/* + * UPCNT defines the amount of times the up threshold should be exceeded + * before DVFS will trigger frequency increase request. + */ +#define DVFS_UPCNT(val) (val << MXC_CCM_LTR1_UPCNT_OFFSET) + +#define DVFS_DVSUP(val) (val << MXC_CCM_PMCR0_DVSUP_OFFSET) + +#define MXC_DVFS_MAX_WP_NUM 2 + +enum { + FSVAI_FREQ_NOCHANGE = 0x0, + FSVAI_FREQ_INCREASE, + FSVAI_FREQ_DECREASE, + FSVAI_FREQ_EMERG, +}; + +struct dvfs_wp { + unsigned long cpu_rate; + u32 core_voltage; + u32 dvsup; + u32 dnthr; + u32 upthr; + u32 dncnt; + u32 upcnt; +}; + +/* the default working points for MX35 TO2 DVFS. */ +static struct dvfs_wp dvfs_wp_tbl[MXC_DVFS_MAX_WP_NUM] = { + {399000000, 1200000, DVFS_DVSUP(DVSUP_LOW), DVFS_DNTHR(18), + DVFS_UPTHR(31), DVFS_DNCNT(0x33), + DVFS_UPCNT(0x33)}, +/* TBD: Need to set default voltage according to published data sheet */ + {532000000, 1350000, DVFS_DVSUP(DVSUP_TURBO), DVFS_DNTHR(18), + DVFS_UPTHR(30), DVFS_DNCNT(0x33), + DVFS_UPCNT(0x33)} +}; + +static u8 dvfs_wp_num = MXC_DVFS_MAX_WP_NUM; + + /* Used for tracking the number of interrupts */ +static u32 dvfs_nr_up[MXC_DVFS_MAX_WP_NUM]; +static u32 dvfs_nr_dn[MXC_DVFS_MAX_WP_NUM]; +static unsigned long stored_cpu_rate; /* cpu rate before DVFS starts */ +static u32 stored_pmcr0; +static int dvfs_is_active; /* indicate DVFS is active or not */ + +static struct delayed_work dvfs_work; + +/* + * Clock structures + */ +static struct clk *cpu_clk; +static struct regulator *core_reg; + +const static u8 ltr_gp_weight[] = { + 0, /* 0 */ + 0, + 0, + 0, + 0, + 0, /* 5 */ + 0, + 0, + 0, + 0, + 0, /* 10 */ + 0, + 0, + 0, + 0, + 0, /* 15 */ +}; + +DEFINE_SPINLOCK(mxc_dvfs_lock); + +/*! + * This function sets the weight of general purpose signals + * @param gp_id number of general purpose bit + * @param weight the weight of the general purpose bit + */ +static void set_gp_weight(int gp_id, u8 weight) +{ + u32 reg; + + if (gp_id < 9) { + reg = __raw_readl(MXC_CCM_LTR3); + reg = (reg & ~(MXC_CCM_LTR3_WSW_MASK(gp_id))) | + (weight << MXC_CCM_LTR3_WSW_OFFSET(gp_id)); + __raw_writel(reg, MXC_CCM_LTR3); + } else if (gp_id < 16) { + reg = __raw_readl(MXC_CCM_LTR2); + reg = (reg & ~(MXC_CCM_LTR2_WSW_MASK(gp_id))) | + (weight << MXC_CCM_LTR2_WSW_OFFSET(gp_id)); + __raw_writel(reg, MXC_CCM_LTR2); + } +} + +/*! + * This function sets upper threshold, lower threshold, + * up-counter, down-counter for load tracking. + * @param upthr upper threshold + * @param dnthr lower threshold + * @param upcnt up counter + * @param dncnt down counter + */ +static void set_ltr_thres_counter(u32 upthr, u32 dnthr, u32 upcnt, u32 dncnt) +{ + u32 reg; + reg = __raw_readl(MXC_CCM_LTR0); + reg = + (reg & + ~(MXC_CCM_LTR0_UPTHR_MASK | + MXC_CCM_LTR0_DNTHR_MASK)) | upthr | dnthr; + __raw_writel(reg, MXC_CCM_LTR0); + + reg = __raw_readl(MXC_CCM_LTR1); + reg = + (reg & + ~(MXC_CCM_LTR1_UPCNT_MASK | + MXC_CCM_LTR1_DNCNT_MASK)) | upcnt | dncnt; + __raw_writel(reg, MXC_CCM_LTR1); +} + +/*! + * This function is called for module initialization. + * It sets up the DVFS hardware. + * It sets default values for DVFS thresholds and counters. The default + * values was chosen from a set of different reasonable values. They was tested + * and the default values in the driver gave the best results. + * More work should be done to find optimal values. + * + * @return 0 if successful; non-zero otherwise. + * + */ +static int init_dvfs_controller(void) +{ + u32 i, reg; + + /* setup LTR0 */ + reg = __raw_readl(MXC_CCM_LTR0); + reg = (reg & ~(MXC_CCM_LTR0_DIV3CK_MASK)) | DVFS_DIV3CK; + __raw_writel(reg, MXC_CCM_LTR0); + + /* set up LTR1 */ + reg = __raw_readl(MXC_CCM_LTR1); + reg = (reg & ~(MXC_CCM_LTR1_PNCTHR_MASK | MXC_CCM_LTR1_LTBRSR_MASK)); + reg = reg | DVFS_PNCTHR | DVFS_LTBRSR; + __raw_writel(reg, MXC_CCM_LTR1); + + /* setup LTR2 */ + reg = __raw_readl(MXC_CCM_LTR2); + reg = (reg & ~(MXC_CCM_LTR2_EMAC_MASK)) | DVFS_EMAC; + __raw_writel(reg, MXC_CCM_LTR2); + + /* Set general purpose weights to 0 */ + for (i = 0; i < 16; i++) + set_gp_weight(i, ltr_gp_weight[i]); + + /* ARM interrupt, mask load buf full interrupt */ + reg = __raw_readl(MXC_CCM_PMCR0); + reg |= MXC_CCM_PMCR0_DVFIS | MXC_CCM_PMCR0_LBMI; + __raw_writel(reg, MXC_CCM_PMCR0); + + return 0; +} + +static void dvfs_workqueue_handler(struct work_struct *work) +{ + u32 pmcr0 = stored_pmcr0; + u32 fsvai = (pmcr0 & MXC_CCM_PMCR0_FSVAI_MASK) >> + MXC_CCM_PMCR0_FSVAI_OFFSET; + u32 dvsup = (pmcr0 & MXC_CCM_PMCR0_DVSUP_MASK) >> + MXC_CCM_PMCR0_DVSUP_OFFSET; + u32 curr_cpu; + u8 curr_dvfs; + + if (!dvfs_is_active) + return; + + if (fsvai == FSVAI_FREQ_NOCHANGE) { + /* Do nothing. Freq change is not required */ + printk(KERN_WARNING "fsvai should not be 0\n"); + goto exit; + } + + if (((dvsup == DVSUP_LOW) && (fsvai == FSVAI_FREQ_DECREASE)) || + ((dvsup == DVSUP_TURBO) && ((fsvai == FSVAI_FREQ_INCREASE) || + (fsvai == FSVAI_FREQ_EMERG)))) { + /* Interrupt should be disabled in these cases according to + * the spec since DVFS is already at lowest (highest) state */ + printk(KERN_WARNING "Something is wrong?\n"); + goto exit; + } + + /*Disable DPTC voltage update */ + pmcr0 = pmcr0 & ~MXC_CCM_PMCR0_DPVCR; + __raw_writel(pmcr0, MXC_CCM_PMCR0); + + curr_cpu = clk_get_rate(cpu_clk); + for (curr_dvfs = 0; curr_dvfs < dvfs_wp_num; curr_dvfs++) { + if (dvfs_wp_tbl[curr_dvfs].cpu_rate == curr_cpu) { + if (fsvai == FSVAI_FREQ_DECREASE) { + curr_dvfs--; + dvfs_nr_dn[dvsup]++; + /*reduce frequency and then voltage */ + clk_set_rate(cpu_clk, + dvfs_wp_tbl[curr_dvfs].cpu_rate); + regulator_set_voltage(core_reg, + dvfs_wp_tbl[curr_dvfs]. + core_voltage, + dvfs_wp_tbl[curr_dvfs]. + core_voltage); + pr_info("Decrease frequency to: %ld \n", + dvfs_wp_tbl[curr_dvfs].cpu_rate); + } else { + /*increase freq to the highest one */ + curr_dvfs = dvfs_wp_num - 1; + dvfs_nr_up[dvsup]++; + /*Increase voltage and then frequency */ + regulator_set_voltage(core_reg, + dvfs_wp_tbl[curr_dvfs]. + core_voltage, + dvfs_wp_tbl[curr_dvfs]. + core_voltage); + clk_set_rate(cpu_clk, + dvfs_wp_tbl[curr_dvfs].cpu_rate); + pr_info("Increase frequency to: %ld \n", + dvfs_wp_tbl[curr_dvfs].cpu_rate); + } + pmcr0 = (pmcr0 & ~MXC_CCM_PMCR0_DVSUP_MASK) + | (dvfs_wp_tbl[curr_dvfs].dvsup); + __raw_writel(pmcr0, MXC_CCM_PMCR0); + + set_ltr_thres_counter(dvfs_wp_tbl[curr_dvfs].upthr, + dvfs_wp_tbl[curr_dvfs].dnthr, + dvfs_wp_tbl[curr_dvfs].upcnt, + dvfs_wp_tbl[curr_dvfs].dncnt); + break; + } + } + + exit: + /* unmask interrupt */ + pmcr0 = pmcr0 & ~MXC_CCM_PMCR0_FSVAIM; + __raw_writel(pmcr0, MXC_CCM_PMCR0); + /*DVFS update finish */ + pmcr0 = (pmcr0 | MXC_CCM_PMCR0_DVFS_UPDATE_FINISH); + __raw_writel(pmcr0, MXC_CCM_PMCR0); +} + +static irqreturn_t dvfs_irq(int irq, void *dev_id) +{ + + u32 pmcr0 = __raw_readl(MXC_CCM_PMCR0); + + /* Config dvfs_start bit */ + pmcr0 = pmcr0 | MXC_CCM_PMCR0_DVFS_START; + /*Mask interrupt */ + pmcr0 = pmcr0 | MXC_CCM_PMCR0_FSVAIM; + __raw_writel(pmcr0, MXC_CCM_PMCR0); + + stored_pmcr0 = pmcr0; + schedule_delayed_work(&dvfs_work, 0); + + return IRQ_RETVAL(1); +} + +/*! + * This function enables the DVFS module. + */ +static int start_dvfs(void) +{ + u32 reg = 0; + unsigned long flags; + u8 i; + + if (dvfs_is_active) { + pr_info("DVFS is already started\n"); + return 0; + } + + spin_lock_irqsave(&mxc_dvfs_lock, flags); + + stored_cpu_rate = clk_get_rate(cpu_clk); + for (i = 0; i < dvfs_wp_num; i++) { + if (dvfs_wp_tbl[i].cpu_rate == stored_cpu_rate) { + /*Set LTR0 and LTR1 */ + set_ltr_thres_counter(dvfs_wp_tbl[i].upthr, + dvfs_wp_tbl[i].dnthr, + dvfs_wp_tbl[i].upcnt, + dvfs_wp_tbl[i].dncnt); + + reg = __raw_readl(MXC_CCM_PMCR0); + reg = + (reg & ~MXC_CCM_PMCR0_DVSUP_MASK) | (dvfs_wp_tbl[i]. + dvsup); + /* enable dvfs and interrupt */ + reg = + (reg & ~MXC_CCM_PMCR0_FSVAIM) | MXC_CCM_PMCR0_DVFEN; + + __raw_writel(reg, MXC_CCM_PMCR0); + + dvfs_is_active = 1; + pr_info("DVFS Starts\n"); + break; + } + } + + spin_unlock_irqrestore(&mxc_dvfs_lock, flags); + if (dvfs_is_active) + return 0; + else + return 1; +} + +/*! + * This function disables the DVFS module. + */ +static void stop_dvfs(void) +{ + u32 pmcr0; + unsigned long curr_cpu = clk_get_rate(cpu_clk); + u8 index; + + if (dvfs_is_active) { + + pmcr0 = __raw_readl(MXC_CCM_PMCR0); + /* disable dvfs and its interrupt */ + pmcr0 = (pmcr0 & ~MXC_CCM_PMCR0_DVFEN) | MXC_CCM_PMCR0_FSVAIM; + __raw_writel(pmcr0, MXC_CCM_PMCR0); + + if (stored_cpu_rate < curr_cpu) { + for (index = 0; index < dvfs_wp_num; index++) { + if (dvfs_wp_tbl[index].cpu_rate == + stored_cpu_rate) + break; + } + clk_set_rate(cpu_clk, stored_cpu_rate); + regulator_set_voltage(core_reg, + dvfs_wp_tbl[index].core_voltage, + dvfs_wp_tbl[index].core_voltage); + } else if (stored_cpu_rate > curr_cpu) { + for (index = 0; index < dvfs_wp_num; index++) { + if (dvfs_wp_tbl[index].cpu_rate == + stored_cpu_rate) + break; + } + regulator_set_voltage(core_reg, + dvfs_wp_tbl[index].core_voltage, + dvfs_wp_tbl[index].core_voltage); + clk_set_rate(cpu_clk, stored_cpu_rate); + } + + dvfs_is_active = 0; + } + + pr_info("DVFS is stopped\n"); +} + +static ssize_t dvfs_enable_store(struct sys_device *dev, struct sysdev_attribute *attr, + const char *buf, size_t size) +{ + if (strstr(buf, "1") != NULL) { + if (start_dvfs() != 0) + printk(KERN_ERR "Failed to start DVFS\n"); + } else if (strstr(buf, "0") != NULL) { + stop_dvfs(); + } + + return size; +} + +static ssize_t dvfs_status_show(struct sys_device *dev, struct sysdev_attribute *attr, + char *buf) +{ + int size = 0, i; + + if (dvfs_is_active) + size = sprintf(buf, "DVFS is enabled\n"); + else + size = sprintf(buf, "DVFS is disabled\n"); + + size += sprintf((buf + size), "UP:\t"); + for (i = 0; i < MXC_DVFS_MAX_WP_NUM; i++) + size += sprintf((buf + size), "%d\t", dvfs_nr_up[i]); + size += sprintf((buf + size), "\n"); + + size += sprintf((buf + size), "DOWN:\t"); + for (i = 0; i < MXC_DVFS_MAX_WP_NUM; i++) + size += sprintf((buf + size), "%d\t", dvfs_nr_dn[i]); + size += sprintf((buf + size), "\n"); + + return size; +} + +static ssize_t dvfs_status_store(struct sys_device *dev, struct sysdev_attribute *attr, + const char *buf, size_t size) +{ + if (strstr(buf, "reset") != NULL) { + int i; + for (i = 0; i < MXC_DVFS_MAX_WP_NUM; i++) { + dvfs_nr_up[i] = 0; + dvfs_nr_dn[i] = 0; + } + } + + return size; +} + +static SYSDEV_ATTR(enable, 0200, NULL, dvfs_enable_store); +static SYSDEV_ATTR(status, 0644, dvfs_status_show, dvfs_status_store); + +static struct sysdev_class dvfs_sysclass = { + .name = "dvfs", +}; + +static struct sys_device dvfs_device = { + .id = 0, + .cls = &dvfs_sysclass, +}; + +static int dvfs_sysdev_ctrl_init(void) +{ + int err; + + err = sysdev_class_register(&dvfs_sysclass); + if (!err) + err = sysdev_register(&dvfs_device); + if (!err) { + err = sysdev_create_file(&dvfs_device, &attr_enable); + err = sysdev_create_file(&dvfs_device, &attr_status); + } + + return err; +} + +static void dvfs_sysdev_ctrl_exit(void) +{ + sysdev_remove_file(&dvfs_device, &attr_enable); + sysdev_remove_file(&dvfs_device, &attr_status); + sysdev_unregister(&dvfs_device); + sysdev_class_unregister(&dvfs_sysclass); +} + +static int __init dvfs_init(void) +{ + int err = 0; + u8 index; + unsigned long curr_cpu; + + if (cpu_is_mx35_rev(CHIP_REV_1_0) == 1) { + /* + * Don't support DVFS for auto path in TO1 because + * the voltages under 399M are all 1.2v + */ + if (!(__raw_readl(MXC_CCM_PDR0) & MXC_CCM_PDR0_AUTO_CON)) { + pr_info("MX35 TO1 auto path, no need to use DVFS \n"); + return -1; + } + } + + cpu_clk = clk_get(NULL, "cpu_clk"); + curr_cpu = clk_get_rate(cpu_clk); + + if (board_is_rev(BOARD_REV_2)) + core_reg = regulator_get(NULL, "SW2"); + else + core_reg = regulator_get(NULL, "SW3"); + + dvfs_is_active = 0; + + /*Set voltage */ + for (index = 0; index < dvfs_wp_num; index++) { + if (dvfs_wp_tbl[index].cpu_rate == curr_cpu + && !IS_ERR(core_reg)) { + regulator_set_voltage(core_reg, + dvfs_wp_tbl[index].core_voltage, + dvfs_wp_tbl[index].core_voltage); + break; + } + } + + err = init_dvfs_controller(); + if (err) { + printk(KERN_ERR "DVFS: Unable to initialize DVFS"); + return err; + } + + INIT_DELAYED_WORK(&dvfs_work, dvfs_workqueue_handler); + + /* request the DVFS interrupt */ + err = request_irq(MXC_INT_DVFS, dvfs_irq, IRQF_DISABLED, "dvfs", NULL); + if (err) { + printk(KERN_ERR "DVFS: Unable to attach to DVFS interrupt"); + return err; + } + + err = dvfs_sysdev_ctrl_init(); + if (err) { + printk(KERN_ERR + "DVFS: Unable to register sysdev entry for dvfs"); + return err; + } + + return err; +} + +static void __exit dvfs_cleanup(void) +{ + stop_dvfs(); + + /* release the DVFS interrupt */ + free_irq(MXC_INT_DVFS, NULL); + + dvfs_sysdev_ctrl_exit(); + + clk_put(cpu_clk); + regulator_put(core_reg); +} + +module_init(dvfs_init); +module_exit(dvfs_cleanup); + +MODULE_AUTHOR("Freescale Seminconductor, Inc."); +MODULE_DESCRIPTION("DVFS driver"); +MODULE_LICENSE("GPL"); diff --git a/arch/arm/mach-mx35/iomux.c b/arch/arm/mach-mx35/iomux.c new file mode 100644 index 000000000000..5d5547344896 --- /dev/null +++ b/arch/arm/mach-mx35/iomux.c @@ -0,0 +1,206 @@ +/* + * 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_MX35 Board GPIO and Muxing Setup + * @ingroup MSL_MX35 + */ +/*! + * @file mach-mx35/iomux.c + * + * @brief I/O Muxing control functions + * + * @ingroup GPIO_MX35 + */ + +#include <linux/io.h> +#include <linux/module.h> +#include <linux/spinlock.h> +#include <mach/hardware.h> +#include <mach/gpio.h> +#include <mach/irqs.h> +#include "iomux.h" + +/*! + * IOMUX register (base) addresses + */ +#define IOMUXGPR (IO_ADDRESS(IOMUXC_BASE_ADDR)) +#define IOMUXSW_MUX_CTL (IO_ADDRESS(IOMUXC_BASE_ADDR) + 4) +#define IOMUXSW_MUX_END (IO_ADDRESS(IOMUXC_BASE_ADDR) + 0x324) +#define IOMUXSW_PAD_CTL (IO_ADDRESS(IOMUXC_BASE_ADDR) + 0x328) +#define IOMUXSW_PAD_END (IO_ADDRESS(IOMUXC_BASE_ADDR) + 0x790) +#define IOMUXSW_INPUT_CTL (IO_ADDRESS(IOMUXC_BASE_ADDR) + 0x7A8) +#define IOMUXSW_INPUT_END (IO_ADDRESS(IOMUXC_BASE_ADDR) + 0x9F4) + +#define MUX_PIN_NUM_MAX \ + (((IOMUXSW_PAD_END - IOMUXSW_PAD_CTL) >> 2) + 1) +#define MUX_INPUT_NUM_MUX \ + (((IOMUXSW_INPUT_END - IOMUXSW_INPUT_CTL) >> 2) + 1) + +#define PIN_TO_IOMUX_INDEX(pin) ((PIN_TO_IOMUX_PAD(pin) - 0x328) >> 2) + +static DEFINE_SPINLOCK(gpio_mux_lock); +static u8 iomux_pin_res_table[MUX_PIN_NUM_MAX]; + +/*! + * This function is used to configure a pin through the IOMUX module. + * FIXED ME: for backward compatible. Will be static function! + * @param pin a pin number as defined in \b #iomux_pin_name_t + * @param cfg an output function 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 cfg) +{ + u32 ret = 0; + u32 pin_index = PIN_TO_IOMUX_INDEX(pin); + void *mux_reg = IOMUXGPR + PIN_TO_IOMUX_MUX(pin); + u8 *rp; + + BUG_ON(pin_index > MUX_PIN_NUM_MAX); + BUG_ON((mux_reg > IOMUXSW_MUX_END) || (mux_reg < IOMUXSW_MUX_CTL)); + + spin_lock(&gpio_mux_lock); + __raw_writel(cfg, mux_reg); + /* + * Log a warning if a pin changes ownership + */ + rp = iomux_pin_res_table + pin_index; + if ((cfg & *rp) && (*rp != cfg)) { + /*Console: how to do */ + printk(KERN_ERR "iomux_config_mux: Warning: iomux pin" + " config changed, index=%d register=%p, " + " prev=0x%x new=0x%x\n", pin_index, mux_reg, + *rp, cfg); + ret = -EINVAL; + } + *rp = cfg; + 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 cfg an input function 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 cfg) +{ + u32 gpio = IOMUX_TO_GPIO(pin); + int ret = iomux_config_mux(pin, cfg); + if (gpio < MXC_GPIO_IRQS) { + if (((cfg & (~MUX_CONFIG_SION)) == MUX_CONFIG_GPIO) || + (((cfg & (~MUX_CONFIG_SION)) == MUX_CONFIG_FUNC) && + ((pin == MX35_PIN_GPIO1_0) || (pin == MX35_PIN_GPIO1_1) || + (pin == MX35_PIN_GPIO2_0) || (pin == MX35_PIN_GPIO3_0)))) + ret |= gpio_request(gpio, 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 cfg an input function as defined in \b #iomux_pin_cfg_t + */ +void mxc_free_iomux(iomux_pin_name_t pin, iomux_pin_cfg_t cfg) +{ + u32 pin_index = PIN_TO_IOMUX_INDEX(pin); + u8 *rp = iomux_pin_res_table + pin_index; + u32 gpio = IOMUX_TO_GPIO(pin); + + BUG_ON((pin_index > MUX_PIN_NUM_MAX)); + + *rp = 0; + if (gpio < MXC_GPIO_IRQS) { + if (((cfg & (~MUX_CONFIG_SION)) == MUX_CONFIG_GPIO) || + (((cfg & (~MUX_CONFIG_SION)) == MUX_CONFIG_FUNC) && + ((pin == MX35_PIN_GPIO1_0) || (pin == MX35_PIN_GPIO1_1) || + (pin == MX35_PIN_GPIO2_0) || (pin == MX35_PIN_GPIO3_0)))) + gpio_free(gpio); + } +} + +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) +{ + void *pad_reg = IOMUXGPR + PIN_TO_IOMUX_PAD(pin); + + BUG_ON((pad_reg > IOMUXSW_PAD_END) || (pad_reg < IOMUXSW_PAD_CTL)); + + spin_lock(&gpio_mux_lock); + __raw_writel(config, pad_reg); + spin_unlock(&gpio_mux_lock); +} + +EXPORT_SYMBOL(mxc_iomux_set_pad); + +/*! + * This function enables/disables the general purpose function for a particular + * signal. + * + * @param gp one signal as defined in \b #iomux_gp_func_t + * @param en \b #true to enable; \b #false to disable + */ +void mxc_iomux_set_gpr(iomux_gp_func_t gp, bool en) +{ + u32 l; + + spin_lock(&gpio_mux_lock); + l = __raw_readl(IOMUXGPR); + + if (en) + l |= gp; + else + l &= ~gp; + + __raw_writel(l, IOMUXGPR); + spin_unlock(&gpio_mux_lock); +} + +EXPORT_SYMBOL(mxc_iomux_set_gpr); + +/*! + * 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) +{ + void *reg = IOMUXSW_INPUT_CTL + (input << 2); + + BUG_ON(input >= MUX_INPUT_NUM_MUX); + + __raw_writel(config, reg); +} + +EXPORT_SYMBOL(mxc_iomux_set_input); diff --git a/arch/arm/mach-mx35/iomux.h b/arch/arm/mach-mx35/iomux.h new file mode 100644 index 000000000000..dc8de152c5a5 --- /dev/null +++ b/arch/arm/mach-mx35/iomux.h @@ -0,0 +1,295 @@ +/* + * 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_MX35_IOMUX_H__ +#define __MACH_MX35_IOMUX_H__ + +#include <linux/types.h> +#include <mach/gpio.h> +#include "mx35_pins.h" + +/*! + * @file mach-mx35/iomux.h + * + * @brief I/O Muxing control definitions and functions + * + * @ingroup GPIO_MX35 + */ + +typedef unsigned int iomux_pin_name_t; + +/*! + * various IOMUX functions + */ +typedef enum iomux_pin_config { + MUX_CONFIG_FUNC = 0, /*!< used as function */ + MUX_CONFIG_ALT1, /*!< used as alternate function 1 */ + MUX_CONFIG_ALT2, /*!< used as alternate function 2 */ + MUX_CONFIG_ALT3, /*!< used as alternate function 3 */ + MUX_CONFIG_ALT4, /*!< used as alternate function 4 */ + MUX_CONFIG_ALT5, /*!< used as alternate function 5 */ + MUX_CONFIG_ALT6, /*!< used as alternate function 6 */ + MUX_CONFIG_ALT7, /*!< used as alternate function 7 */ + MUX_CONFIG_SION = 0x1 << 4, /*!< used as LOOPBACK:MUX SION bit */ + MUX_CONFIG_GPIO = MUX_CONFIG_ALT5, /*!< used as GPIO */ +} iomux_pin_cfg_t; + +/*! + * various IOMUX pad functions + */ +typedef enum iomux_pad_config { + PAD_CTL_DRV_3_3V = 0x0 << 13, + PAD_CTL_DRV_1_8V = 0x1 << 13, + PAD_CTL_HYS_CMOS = 0x0 << 8, + PAD_CTL_HYS_SCHMITZ = 0x1 << 8, + PAD_CTL_PKE_NONE = 0x0 << 7, + PAD_CTL_PKE_ENABLE = 0x1 << 7, + PAD_CTL_PUE_KEEPER = 0x0 << 6, + PAD_CTL_PUE_PUD = 0x1 << 6, + 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_ODE_CMOS = 0x0 << 3, + PAD_CTL_ODE_OpenDrain = 0x1 << 3, + PAD_CTL_DRV_NORMAL = 0x0 << 1, + PAD_CTL_DRV_HIGH = 0x1 << 1, + PAD_CTL_DRV_MAX = 0x2 << 1, + PAD_CTL_SRE_SLOW = 0x0 << 0, + PAD_CTL_SRE_FAST = 0x1 << 0 +} iomux_pad_config_t; + +/*! + * various IOMUX general purpose functions + */ +typedef enum iomux_gp_func { + MUX_SDCTL_CSD0_SEL = 0x1 << 0, + MUX_SDCTL_CSD1_SEL = 0x1 << 1, + MUX_TAMPER_DETECT_EN = 0x1 << 2, +} iomux_gp_func_t; + +/*! + * various IOMUX input select register index + */ +typedef enum iomux_input_select { + MUX_IN_AMX_P5_RXCLK = 0, + MUX_IN_AMX_P5_RXFS, + MUX_IN_AMX_P6_DA, + MUX_IN_AMX_P6_DB, + MUX_IN_AMX_P6_RXCLK, + MUX_IN_AMX_P6_RXFS, + MUX_IN_AMX_P6_TXCLK, + MUX_IN_AMX_P6_TXFS, + MUX_IN_CAN1_CANRX, + MUX_IN_CAN2_CANRX, + MUX_IN_CCM_32K_MUXED, + MUX_IN_CCM_PMIC_RDY, + MUX_IN_CSPI1_SS2_B, + MUX_IN_CSPI1_SS3_B, + MUX_IN_CSPI2_CLK_IN, + MUX_IN_CSPI2_DATAREADY_B, + MUX_IN_CSPI2_MISO, + MUX_IN_CSPI2_MOSI, + MUX_IN_CSPI2_SS0_B, + MUX_IN_CSPI2_SS1_B, + MUX_IN_CSPI2_SS2_B, + MUX_IN_CSPI2_SS3_B, + MUX_IN_EMI_WEIM_DTACK_B, + MUX_IN_ESDHC1_DAT4_IN, + MUX_IN_ESDHC1_DAT5_IN, + MUX_IN_ESDHC1_DAT6_IN, + MUX_IN_ESDHC1_DAT7_IN, + MUX_IN_ESDHC3_CARD_CLK_IN, + MUX_IN_ESDHC3_CMD_IN, + MUX_IN_ESDHC3_DAT0, + MUX_IN_ESDHC3_DAT1, + MUX_IN_ESDHC3_DAT2, + MUX_IN_ESDHC3_DAT3, + MUX_IN_GPIO1_IN_0, + MUX_IN_GPIO1_IN_10, + MUX_IN_GPIO1_IN_11, + MUX_IN_GPIO1_IN_1, + MUX_IN_GPIO1_IN_20, + MUX_IN_GPIO1_IN_21, + MUX_IN_GPIO1_IN_22, + MUX_IN_GPIO1_IN_2, + MUX_IN_GPIO1_IN_3, + MUX_IN_GPIO1_IN_4, + MUX_IN_GPIO1_IN_5, + MUX_IN_GPIO1_IN_6, + MUX_IN_GPIO1_IN_7, + MUX_IN_GPIO1_IN_8, + MUX_IN_GPIO1_IN_9, + MUX_IN_GPIO2_IN_0, + MUX_IN_GPIO2_IN_10, + MUX_IN_GPIO2_IN_11, + MUX_IN_GPIO2_IN_12, + MUX_IN_GPIO2_IN_13, + MUX_IN_GPIO2_IN_14, + MUX_IN_GPIO2_IN_15, + MUX_IN_GPIO2_IN_16, + MUX_IN_GPIO2_IN_17, + MUX_IN_GPIO2_IN_18, + MUX_IN_GPIO2_IN_19, + MUX_IN_GPIO2_IN_1, + MUX_IN_GPIO2_IN_20, + MUX_IN_GPIO2_IN_21, + MUX_IN_GPIO2_IN_22, + MUX_IN_GPIO2_IN_23, + MUX_IN_GPIO2_IN_24, + MUX_IN_GPIO2_IN_25, + MUX_IN_GPIO2_IN_26, + MUX_IN_GPIO2_IN_27, + MUX_IN_GPIO2_IN_28, + MUX_IN_GPIO2_IN_29, + MUX_IN_GPIO2_IN_2, + MUX_IN_GPIO2_IN_30, + MUX_IN_GPIO2_IN_31, + MUX_IN_GPIO2_IN_3, + MUX_IN_GPIO2_IN_4, + MUX_IN_GPIO2_IN_5, + MUX_IN_GPIO2_IN_6, + MUX_IN_GPIO2_IN_7, + MUX_IN_GPIO2_IN_8, + MUX_IN_GPIO2_IN_9, + MUX_IN_GPIO3_IN_0, + MUX_IN_GPIO3_IN_10, + MUX_IN_GPIO3_IN_11, + MUX_IN_GPIO3_IN_12, + MUX_IN_GPIO3_IN_13, + MUX_IN_GPIO3_IN_14, + MUX_IN_GPIO3_IN_15, + MUX_IN_GPIO3_IN_4, + MUX_IN_GPIO3_IN_5, + MUX_IN_GPIO3_IN_6, + MUX_IN_GPIO3_IN_7, + MUX_IN_GPIO3_IN_8, + MUX_IN_GPIO3_IN_9, + MUX_IN_I2C3_SCL_IN, + MUX_IN_I2C3_SDA_IN, + MUX_IN_IPU_DISPB_D0_VSYNC, + MUX_IN_IPU_DISPB_D12_VSYNC, + MUX_IN_IPU_DISPB_SD_D, + MUX_IN_IPU_SENSB_DATA_0, + MUX_IN_IPU_SENSB_DATA_1, + MUX_IN_IPU_SENSB_DATA_2, + MUX_IN_IPU_SENSB_DATA_3, + MUX_IN_IPU_SENSB_DATA_4, + MUX_IN_IPU_SENSB_DATA_5, + MUX_IN_IPU_SENSB_DATA_6, + MUX_IN_IPU_SENSB_DATA_7, + MUX_IN_KPP_COL_0, + MUX_IN_KPP_COL_1, + MUX_IN_KPP_COL_2, + MUX_IN_KPP_COL_3, + MUX_IN_KPP_COL_4, + MUX_IN_KPP_COL_5, + MUX_IN_KPP_COL_6, + MUX_IN_KPP_COL_7, + MUX_IN_KPP_ROW_0, + MUX_IN_KPP_ROW_1, + MUX_IN_KPP_ROW_2, + MUX_IN_KPP_ROW_3, + MUX_IN_KPP_ROW_4, + MUX_IN_KPP_ROW_5, + MUX_IN_KPP_ROW_6, + MUX_IN_KPP_ROW_7, + MUX_IN_OWIRE_BATTERY_LINE, + MUX_IN_SPDIF_HCKT_CLK2, + MUX_IN_SPDIF_SPDIF_IN1, + MUX_IN_UART3_UART_RTS_B, + MUX_IN_UART3_UART_RXD_MUX, + MUX_IN_USB_OTG_DATA_0, + MUX_IN_USB_OTG_DATA_1, + MUX_IN_USB_OTG_DATA_2, + MUX_IN_USB_OTG_DATA_3, + MUX_IN_USB_OTG_DATA_4, + MUX_IN_USB_OTG_DATA_5, + MUX_IN_USB_OTG_DATA_6, + MUX_IN_USB_OTG_DATA_7, + MUX_IN_USB_OTG_DIR, + MUX_IN_USB_OTG_NXT, + MUX_IN_USB_UH2_DATA_0, + MUX_IN_USB_UH2_DATA_1, + MUX_IN_USB_UH2_DATA_2, + MUX_IN_USB_UH2_DATA_3, + MUX_IN_USB_UH2_DATA_4, + MUX_IN_USB_UH2_DATA_5, + MUX_IN_USB_UH2_DATA_6, + MUX_IN_USB_UH2_DATA_7, + MUX_IN_USB_UH2_DIR, + MUX_IN_USB_UH2_NXT, + MUX_IN_USB_UH2_USB_OC, +} 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_cfg_t; + +/*! + * 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 cfg an input function 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 cfg); + +/*! + * Release ownership for an IO pin + * + * @param pin a name defined by \b iomux_pin_name_t + * @param cfg an input function as defined in \b #iomux_pin_cfg_t + */ +void mxc_free_iomux(iomux_pin_name_t pin, iomux_pin_cfg_t cfg); + +/*! + * This function enables/disables the general purpose function for a particular + * signal. + * + * @param gp one signal as defined in \b #iomux_gp_func_t + * @param en \b #true to enable; \b #false to disable + */ +void mxc_iomux_set_gpr(iomux_gp_func_t gp, bool en); + +/*! + * 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 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_cfg_t + */ +void mxc_iomux_set_input(iomux_input_select_t input, u32 config); +#endif diff --git a/arch/arm/mach-mx35/mm.c b/arch/arm/mach-mx35/mm.c new file mode 100644 index 000000000000..2d86bae4b3bd --- /dev/null +++ b/arch/arm/mach-mx35/mm.c @@ -0,0 +1,77 @@ +/* + * 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-mx35/mm.c + * + * @brief This file creates static mapping between physical to virtual memory. + * + * @ingroup Memory_MX35 + */ + +/*! + * This structure defines the MX35 memory map. + */ +static struct map_desc mx35_io_desc[] __initdata = { + { + .virtual = IRAM_BASE_ADDR_VIRT, + .pfn = __phys_to_pfn(MX35_IRAM_BASE_ADDR), + .length = MX35_IRAM_SIZE, + .type = MT_DEVICE_NONSHARED}, + { + .virtual = X_MEMC_BASE_ADDR_VIRT, + .pfn = __phys_to_pfn(X_MEMC_BASE_ADDR), + .length = X_MEMC_SIZE, + .type = MT_DEVICE}, + { + .virtual = NFC_BASE_ADDR_VIRT, + .pfn = __phys_to_pfn(NFC_BASE_ADDR), + .length = NFC_SIZE, + .type = MT_DEVICE_NONSHARED}, + { + .virtual = AVIC_BASE_ADDR_VIRT, + .pfn = __phys_to_pfn(AVIC_BASE_ADDR), + .length = AVIC_SIZE, + .type = MT_DEVICE_NONSHARED}, + { + .virtual = AIPS1_BASE_ADDR_VIRT, + .pfn = __phys_to_pfn(AIPS1_BASE_ADDR), + .length = AIPS1_SIZE, + .type = MT_DEVICE_NONSHARED}, + { + .virtual = SPBA0_BASE_ADDR_VIRT, + .pfn = __phys_to_pfn(SPBA0_BASE_ADDR), + .length = SPBA0_SIZE, + .type = MT_DEVICE_NONSHARED}, + { + .virtual = AIPS2_BASE_ADDR_VIRT, + .pfn = __phys_to_pfn(AIPS2_BASE_ADDR), + .length = AIPS2_SIZE, + .type = MT_DEVICE_NONSHARED}, +}; + +/*! + * 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 mx35_map_io(void) +{ + iotable_init(mx35_io_desc, ARRAY_SIZE(mx35_io_desc)); +} diff --git a/arch/arm/mach-mx35/mx35_3stack.c b/arch/arm/mach-mx35/mx35_3stack.c new file mode 100644 index 000000000000..02fed337d772 --- /dev/null +++ b/arch/arm/mach-mx35/mx35_3stack.c @@ -0,0 +1,1260 @@ +/* + * 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/interrupt.h> +#include <linux/init.h> +#include <linux/input.h> +#include <linux/nodemask.h> +#include <linux/clk.h> +#include <linux/spi/spi.h> +#include <linux/i2c.h> +#include <linux/platform_device.h> +#include <linux/fsl_devices.h> +#include <linux/ata.h> +#include <linux/pmic_external.h> +#include <linux/mfd/mc9s08dz60/pmic.h> +#include <linux/regulator/consumer.h> +#include <linux/smsc911x.h> +#include <linux/i2c/tsc2007.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 <linux/delay.h> + +#include <asm/mach/flash.h> +#endif + +#include <mach/hardware.h> +#include <asm/irq.h> +#include <asm/setup.h> +#include <asm/mach-types.h> +#include <asm/mach/arch.h> +#include <asm/mach/irq.h> +#include <asm/mach/time.h> +#include <mach/common.h> +#include <mach/memory.h> +#include <mach/gpio.h> +#include <mach/mmc.h> + +#include "board-mx35_3stack.h" +#include "crm_regs.h" +#include "iomux.h" + +/*! + * @file mach-mx35/mx35_3stack.c + * + * @brief This file contains the board specific initialization routines. + * + * @ingroup MSL_MX35 + */ + +unsigned int mx35_3stack_board_io; + +static void mxc_nop_release(struct device *dev) +{ + /* Nothing */ +} + +/* MTD NOR flash */ + +#if defined(CONFIG_MTD_MXC) || defined(CONFIG_MTD_MXC_MODULE) + +static struct mtd_partition mxc_nor_partitions[] = { + { + .name = "Bootloader", + .size = 512 * 1024, + .offset = 0x00000000, + .mask_flags = MTD_WRITEABLE /* force read-only */ + }, + { + .name = "nor.Kernel", + .size = 4 * 1024 * 1024, + .offset = MTDPART_OFS_APPEND, + .mask_flags = 0}, + { + .name = "nor.userfs", + .size = 30 * 1024 * 1024, + .offset = MTDPART_OFS_APPEND, + .mask_flags = 0}, + { + .name = "nor.rootfs", + .size = 28 * 1024 * 1024, + .offset = MTDPART_OFS_APPEND, + .mask_flags = MTD_WRITEABLE}, + { + .name = "FIS directory", + .size = 12 * 1024, + .offset = 0x01FE0000, + .mask_flags = MTD_WRITEABLE /* force read-only */ + }, + { + .name = "Redboot config", + .size = MTDPART_SIZ_FULL, + .offset = 0x01FFF000, + .mask_flags = MTD_WRITEABLE /* force read-only */ + }, +}; + +static struct flash_platform_data mxc_flash_data = { + .map_name = "cfi_probe", + .width = 2, + .parts = mxc_nor_partitions, + .nr_parts = ARRAY_SIZE(mxc_nor_partitions), +}; + +static struct resource mxc_flash_resource = { + .start = 0xa0000000, + .end = 0xa0000000 + 0x04000000 - 1, + .flags = IORESOURCE_MEM, + +}; + +static struct platform_device mxc_nor_mtd_device = { + .name = "mxc_nor_flash", + .id = 0, + .dev = { + .release = mxc_nop_release, + .platform_data = &mxc_flash_data, + }, + .num_resources = 1, + .resource = &mxc_flash_resource, +}; + +static void mxc_init_nor_mtd(void) +{ + (void)platform_device_register(&mxc_nor_mtd_device); +} +#else +static void mxc_init_nor_mtd(void) +{ +} +#endif + +/* MTD NAND flash */ + +#if defined(CONFIG_MTD_NAND_MXC) || defined(CONFIG_MTD_NAND_MXC_MODULE) \ +|| defined(CONFIG_MTD_NAND_MXC_V2) || defined(CONFIG_MTD_NAND_MXC_V2_MODULE) + +static struct mtd_partition mxc_nand_partitions[] = { + { + .name = "nand.bootloader", + .offset = 0, + .size = 1024 * 1024}, + { + .name = "nand.kernel", + .offset = MTDPART_OFS_APPEND, + .size = 5 * 1024 * 1024}, + { + .name = "nand.rootfs", + .offset = MTDPART_OFS_APPEND, + .size = 256 * 1024 * 1024}, + { + .name = "nand.configure", + .offset = MTDPART_OFS_APPEND, + .size = 8 * 1024 * 1024}, + { + .name = "nand.userfs", + .offset = MTDPART_OFS_APPEND, + .size = MTDPART_SIZ_FULL}, +}; + +static struct flash_platform_data mxc_nand_data = { + .parts = mxc_nand_partitions, + .nr_parts = ARRAY_SIZE(mxc_nand_partitions), + .width = 1, +}; + +static struct platform_device mxc_nand_mtd_device = { + .name = "mxc_nandv2_flash", + .id = 0, + .dev = { + .release = mxc_nop_release, + .platform_data = &mxc_nand_data, + }, +}; + +static void mxc_init_nand_mtd(void) +{ + if (__raw_readl(MXC_CCM_RCSR) & MXC_CCM_RCSR_NF16B) + mxc_nand_data.width = 2; + + platform_device_register(&mxc_nand_mtd_device); +} +#else +static inline void mxc_init_nand_mtd(void) +{ +} +#endif + +static struct mxc_lcd_platform_data lcd_data = { + .io_reg = "LCD" +}; + +static struct platform_device lcd_dev = { + .name = "lcd_claa", + .id = 0, + .dev = { + .release = mxc_nop_release, + .platform_data = (void *)&lcd_data, + }, +}; + +static void mxc_init_lcd(void) +{ + platform_device_register(&lcd_dev); +} + +#if defined(CONFIG_FB_MXC_SYNC_PANEL) || defined(CONFIG_FB_MXC_SYNC_PANEL_MODULE) +/* mxc lcd driver */ +static struct platform_device mxc_fb_device = { + .name = "mxc_sdc_fb", + .id = 0, + .dev = { + .release = mxc_nop_release, + .coherent_dma_mask = 0xFFFFFFFF, + }, +}; + +static void mxc_init_fb(void) +{ + (void)platform_device_register(&mxc_fb_device); +} +#else +static inline void mxc_init_fb(void) +{ +} +#endif + +#if defined(CONFIG_BACKLIGHT_MXC) +static struct platform_device mxcbl_devices[] = { +#if defined(CONFIG_BACKLIGHT_MXC_IPU) || defined(CONFIG_BACKLIGHT_MXC_IPU_MODULE) + { + .name = "mxc_ipu_bl", + .id = 0, + .dev = { + .platform_data = (void *)3, /* DISP # for this backlight */ + }, + } +#endif +}; + +static inline void mxc_init_bl(void) +{ + int i; + for (i = 0; i < ARRAY_SIZE(mxcbl_devices); i++) { + platform_device_register(&mxcbl_devices[i]); + } +} +#else +static inline void mxc_init_bl(void) +{ +} +#endif + +#if defined(CONFIG_MXC_MLB) || defined(CONFIG_MXC_MLB_MODULE) +static struct resource mlb_resource[] = { + [0] = { + .start = MLB_BASE_ADDR, + .end = MLB_BASE_ADDR + 0x300, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = MXC_INT_MLB, + .end = MXC_INT_MLB, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct mxc_mlb_platform_data mlb_data = { + .buf_address = IRAM_BASE_ADDR_VIRT + MLB_IRAM_ADDR_OFFSET, + .phy_address = IRAM_BASE_ADDR + MLB_IRAM_ADDR_OFFSET, + .reg_nvcc = "VVIDEO", + .mlb_clk = "mlb_clk", +}; + +static struct platform_device mlb_dev = { + .name = "mxc_mlb", + .id = 0, + .dev = { + .platform_data = &mlb_data, + }, + .num_resources = ARRAY_SIZE(mlb_resource), + .resource = mlb_resource, +}; + +static inline void mxc_init_mlb(void) +{ + platform_device_register(&mlb_dev); +} +#else +static inline void mxc_init_mlb(void) +{ +} +#endif + +static void mxc_unifi_hardreset(int pin_level) +{ + pmic_gpio_set_bit_val(MCU_GPIO_REG_RESET_1, 1, pin_level & 0x01); +} + +static void mxc_unifi_enable(int en) +{ + if (en) { + pmic_gpio_set_bit_val(MCU_GPIO_REG_GPIO_CONTROL_1, 5, 1); + msleep(10); + } else + pmic_gpio_set_bit_val(MCU_GPIO_REG_GPIO_CONTROL_1, 5, 0); +} + +static struct mxc_unifi_platform_data unifi_data = { + .hardreset = mxc_unifi_hardreset, + .enable = mxc_unifi_enable, + .reg_gpo1 = "GPO2", + .reg_gpo2 = "GPO3", + .reg_1v5_ana_bb = "PWGT1", + .reg_vdd_vpa = "VAUDIO", + .reg_1v5_dd = "SW1", + .host_id = 1, +}; + +struct mxc_unifi_platform_data *get_unifi_plat_data(void) +{ + return &unifi_data; +} + +EXPORT_SYMBOL(get_unifi_plat_data); + +static int tsc2007_get_pendown_state(void) +{ + return !gpio_get_value(IOMUX_TO_GPIO(MX35_PIN_CAPTURE)); +} + +static int tsc2007_init(void) +{ + return 0; +} + +static void tsc2007_exit(void) +{ +} + +struct tsc2007_platform_data tsc2007_data = { + .model = 2007, + .x_plate_ohms = 400, + .get_pendown_state = tsc2007_get_pendown_state, + .init_platform_hw = tsc2007_init, + .exit_platform_hw = tsc2007_exit, +}; + +static struct mxc_camera_platform_data camera_data = { + .core_regulator = "SW1", + .io_regulator = "VAUDIO", + .analog_regulator = NULL, + .gpo_regulator = "PWGT1", + .mclk = 27000000, +}; + +void si4702_reset(void) +{ + pmic_gpio_set_bit_val(MCU_GPIO_REG_RESET_1, 4, 0); + msleep(100); + pmic_gpio_set_bit_val(MCU_GPIO_REG_RESET_1, 4, 1); + msleep(100); +} + +void si4702_clock_ctl(int flag) +{ + pmic_gpio_set_bit_val(MCU_GPIO_REG_GPIO_CONTROL_1, 7, flag); +} + +static void si4702_gpio_get(void) +{ +} + +static void si4702_gpio_put(void) +{ +} + +static struct mxc_fm_platform_data si4702_data = { + .reg_vio = "VSD", + .reg_vdd = NULL, + .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, +}; + +static void adv7180_pwdn(int pwdn) +{ + pmic_gpio_set_bit_val(MCU_GPIO_REG_GPIO_CONTROL_1, 1, pwdn); +} + +static void adv7180_reset(void) +{ + pmic_gpio_set_bit_val(MCU_GPIO_REG_RESET_1, 6, 0); + msleep(5); + pmic_gpio_set_bit_val(MCU_GPIO_REG_RESET_1, 6, 1); + msleep(5); +} + +static struct mxc_tvin_platform_data adv7180_data = { + .dvddio_reg = NULL, + .dvdd_reg = "SW3", + .avdd_reg = "PWGT2", + .pvdd_reg = NULL, + .pwdn = adv7180_pwdn, + .reset = adv7180_reset, +}; + +static struct i2c_board_info mxc_i2c_board_info[] __initdata = { + { + .type = "max8660", + .addr = 0x34, + }, + { + .type = "tsc2007", + .addr = 0x48, + .platform_data = &tsc2007_data, + .irq = IOMUX_TO_IRQ(MX35_PIN_CAPTURE), + }, + { + .type = "ov2640", + .addr = 0x30, + .platform_data = (void *)&camera_data, + }, + { + .type = "sgtl5000-i2c", + .addr = 0x0a, + }, + { + .type = "ak4647-i2c", + .addr = 0x12, + }, +#if defined(CONFIG_I2C_SLAVE_CLIENT) + { + .type = "i2c-slave-client", + .addr = 0x55, + }, +#endif + { + .type = "si4702", + .addr = 0x10, + .platform_data = (void *)&si4702_data, + }, + { + .type = "adv7180", + .addr = 0x21, + .platform_data = (void *)&adv7180_data, + }, +}; + +static struct spi_board_info mxc_spi_board_info[] __initdata = { + { + .modalias = "wm8580_spi", + .max_speed_hz = 8000000, /* max spi SCK clock speed in HZ */ + .bus_num = 1, + .chip_select = 1, + }, +}; + +#if defined(CONFIG_SMSC911X) || defined(CONFIG_SMSC911X_MODULE) +static struct resource smsc911x_resources[] = { + { + .start = LAN9217_BASE_ADDR, + .end = LAN9217_BASE_ADDR + 0x100, + .flags = IORESOURCE_MEM, + }, + { + .start = LAN9217_IRQ, + .end = LAN9217_IRQ, + .flags = IORESOURCE_IRQ, + } +}; + +struct smsc911x_platform_config smsc911x_config = { + .irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_LOW, + .flags = SMSC911X_USE_32BIT | SMSC911X_FORCE_INTERNAL_PHY, +}; + +static struct platform_device smsc_lan9217_device = { + .name = "smsc911x", + .id = 0, + .dev = { + .release = mxc_nop_release, + .platform_data = &smsc911x_config, + }, + .num_resources = ARRAY_SIZE(smsc911x_resources), + .resource = smsc911x_resources, +}; + +static void mxc_init_enet(void) +{ + platform_device_register(&smsc_lan9217_device); +} +#else +static inline void mxc_init_enet(void) +{ +} +#endif + +#if defined(CONFIG_FEC) || defined(CONFIG_FEC_MODULE) +static struct resource mxc_fec_resources[] = { + { + .start = FEC_BASE_ADDR, + .end = FEC_BASE_ADDR + 0xfff, + .flags = IORESOURCE_MEM + }, { + .start = MXC_INT_FEC, + .end = MXC_INT_FEC, + .flags = IORESOURCE_IRQ + }, +}; + +struct platform_device mxc_fec_device = { + .name = "fec", + .id = 0, + .num_resources = ARRAY_SIZE(mxc_fec_resources), + .resource = mxc_fec_resources, +}; + +static __init int mxc_init_fec(void) +{ + return platform_device_register(&mxc_fec_device); +} +#else +static inline int mxc_init_fec(void) +{ + return 0; +} +#endif + +#if defined(CONFIG_MMC_IMX_ESDHCI) || defined(CONFIG_MMC_IMX_ESDHCI_MODULE) +static struct mxc_mmc_platform_data mmc1_data = { + .ocr_mask = MMC_VDD_32_33, +#if defined(CONFIG_SDIO_UNIFI_FS) || defined(CONFIG_SDIO_UNIFI_FS_MODULE) + .caps = MMC_CAP_4_BIT_DATA, +#else + .caps = MMC_CAP_8_BIT_DATA, +#endif + .min_clk = 150000, + .max_clk = 52000000, + .card_inserted_state = 0, + .status = sdhc_get_card_det_status, + .wp_status = sdhc_write_protect, + .clock_mmc = "sdhc_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 = MX35_INT_MMC_SDHC1, + .end = MX35_INT_MMC_SDHC1, + .flags = IORESOURCE_IRQ, + }, + [2] = { + .start = MXC_PSEUDO_IRQ_SD1_CD, + .end = MXC_PSEUDO_IRQ_SD1_CD, + .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, +}; + +#if defined(CONFIG_SDIO_UNIFI_FS) || defined(CONFIG_SDIO_UNIFI_FS_MODULE) +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 = "sdhc_clk", +}; + +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, + }, +}; + +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, +}; +#endif + +static inline void mxc_init_mmc(void) +{ + (void)platform_device_register(&mxcsdhc1_device); +#if defined(CONFIG_SDIO_UNIFI_FS) || defined(CONFIG_SDIO_UNIFI_FS_MODULE) + (void)platform_device_register(&mxcsdhc2_device); +#endif +} +#else +static inline void mxc_init_mmc(void) +{ +} +#endif + +#ifdef CONFIG_MXC_PSEUDO_IRQS +/*! Device Definition for MXC SDHC1 */ +static struct platform_device mxc_pseudo_irq_device = { + .name = "mxc_pseudo_irq", + .id = 0, + .dev = { + .release = mxc_nop_release, + }, +}; + +static inline int mxc_init_pseudo_irq(void) +{ + return platform_device_register(&mxc_pseudo_irq_device); +} + +late_initcall(mxc_init_pseudo_irq); + +/*! + * Power Key interrupt handler. + */ +static irqreturn_t power_key_int(int irq, void *dev_id) +{ + pr_info(KERN_INFO "on-off key pressed\n"); + return 0; +} + +/*! + * Power Key initialization. + */ +static int __init mxc_init_power_key(void) +{ + if (!board_is_rev(BOARD_REV_2)) { + /*Set power key as wakeup resource */ + int irq, ret; + irq = MXC_PSEUDO_IRQ_POWER_KEY; + 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; + } + return 0; +} + +late_initcall(mxc_init_power_key); +#endif + +#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 = { + .adma_flag = 1, /* 0:smart dma, 1:ADMA */ + .udma_mask = 0x3F, + .mwdma_mask = 0x1F, + .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, /*"LDO2", */ + .io_reg = NULL, /*"LDO3", */ +}; + +static struct resource pata_fsl_resources[] = { + [0] = { /* I/O */ + .start = ATA_BASE_ADDR, + .end = ATA_BASE_ADDR + 0x000000C8, + .flags = IORESOURCE_MEM, + }, + [2] = { /* IRQ */ + .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_GPS_IOCTRL) || defined(CONFIG_GPS_IOCTRL_MODULE) +static struct mxc_gps_platform_data gps_data = { + .core_reg = "SW3", + .analog_reg = "PWGT2", +}; + +static struct platform_device mxc_gps_device = { + .name = "gps_ioctrl", + .id = 0, + .dev = { + .platform_data = &gps_data, + }, +}; + +static void __init mxc_init_gps(void) +{ + (void)platform_device_register(&mxc_gps_device); +} +#else +static void __init mxc_init_gps(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) +{ + mxc_cpu_init(); + +#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 +} + +static void bt_reset(void) +{ + pmic_gpio_set_bit_val(MCU_GPIO_REG_RESET_1, 2, 0); + msleep(5); + pmic_gpio_set_bit_val(MCU_GPIO_REG_RESET_1, 2, 1); +} + +static struct mxc_bt_platform_data mxc_bt_data = { + .bt_vdd = "GPO2", + .bt_vdd_parent = NULL, + .bt_vusb = NULL, + .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); +} + +#if defined(CONFIG_SND_SOC_IMX_3STACK_SGTL5000) \ + || defined(CONFIG_SND_SOC_IMX_3STACK_SGTL5000_MODULE) + +static int sgtl5000_headphone_det_status(void) +{ + int ret = 0; + if (0 != pmic_gpio_get_designation_bit_val(0, &ret)) + printk(KERN_ERR "Get headphone status error."); + return ret; +} + +static int mxc_sgtl5000_plat_init(void); +static int mxc_sgtl5000_plat_finit(void); +static int mxc_sgtl5000_amp_enable(int enable); + +static struct mxc_audio_platform_data sgtl5000_data = { + .ssi_num = 1, + .src_port = 1, + .ext_port = 4, + .hp_irq = MXC_PSEUDO_IRQ_HEADPHONE, + .hp_status = sgtl5000_headphone_det_status, + .vddio_reg = NULL, + .vdda_reg = "VCAM", + .amp_enable = mxc_sgtl5000_amp_enable, + .vddio = 0, + .vdda = 3000000, + .vddd = 0, + .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, "SPKR"); + 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) +{ + struct clk *cko1, *parent; + unsigned long rate; + + /* for board v1.1 do nothing */ + if (!board_is_rev(BOARD_REV_2)) + return; + + cko1 = clk_get(NULL, "cko1_clk"); + if (IS_ERR(cko1)) + return; + parent = clk_get(NULL, "ckih"); + if (IS_ERR(parent)) + return; + clk_set_parent(cko1, parent); + rate = clk_round_rate(cko1, 12000000); + if (rate < 8000000 || rate > 27000000) { + printk(KERN_ERR "Error: SGTL5000 mclk freq %d out of range!\n", + (unsigned int)rate); + clk_put(parent); + clk_put(cko1); + return; + } + clk_set_rate(cko1, rate); + clk_enable(cko1); + sgtl5000_data.sysclk = rate; + platform_device_register(&mxc_sgtl5000_device); +} +#else +static void mxc_init_sgtl5000(void) +{ +} +#endif + +#if defined(CONFIG_SND_SOC_IMX_3STACK_AK4647) \ + || defined(CONFIG_SND_SOC_IMX_3STACK_AK4647_MODULE) +static int mxc_ak4647_amp_enable(int enable) +{ + pmic_gpio_set_bit_val(MCU_GPIO_REG_GPIO_CONTROL_1, 0, enable); + return 0; +} + +static int mxc_ak4647_plat_init(void) +{ + pmic_gpio_set_bit_val(MCU_GPIO_REG_RESET_2, 1, 0); + msleep(1); + pmic_gpio_set_bit_val(MCU_GPIO_REG_RESET_2, 1, 1); + return 0; +} + +static int ak4647_headphone_det_status(void) +{ + int ret = 0; + if (0 != pmic_gpio_get_designation_bit_val(0, &ret)) + printk(KERN_ERR "Get headphone status error."); + return ret; +} + +static struct mxc_audio_platform_data mxc_ak4647_data = { + .ssi_num = 1, + .src_port = 1, + .ext_port = 4, + .amp_enable = mxc_ak4647_amp_enable, + .init = mxc_ak4647_plat_init, + .hp_status = ak4647_headphone_det_status, + .intr_id_hp = MXC_PSEUDO_IRQ_HEADPHONE, +}; + +static struct platform_device mxc_alsa_device = { + .name = "imx-3stack-ak4647", + .id = 0, + .dev = { + .release = mxc_nop_release, + .platform_data = &mxc_ak4647_data, + }, + +}; + +static void mxc_init_ak4647(void) +{ + platform_device_register(&mxc_alsa_device); +} +#else +static void mxc_init_ak4647(void) +{ +} +#endif + +#if defined(CONFIG_CAN_FLEXCAN) || defined(CONFIG_CAN_FLEXCAN_MODULE) +static void flexcan_xcvr_enable(int id, int en) +{ + static int pwdn; + + if (id < 0 || id > 1) + return; + + if (en) { + if (!(pwdn++)) + pmic_gpio_set_bit_val(MCU_GPIO_REG_GPIO_CONTROL_2, + 1, 0); + } else { + if (!(--pwdn)) + pmic_gpio_set_bit_val(MCU_GPIO_REG_GPIO_CONTROL_2, + 1, 1); + } +} + +struct flexcan_platform_data flexcan_data[] = { + { + .core_reg = "GPO2", + .io_reg = NULL, + .xcvr_enable = flexcan_xcvr_enable, + .active = gpio_can_active, + .inactive = gpio_can_inactive,}, + { + .core_reg = "GPO2", + .io_reg = NULL, + .xcvr_enable = flexcan_xcvr_enable, + .active = gpio_can_active, + .inactive = gpio_can_inactive,}, +}; +#endif + +/*! + * fixup for mx35 3stack board v1.0 (MAX8660) + */ +static void mx35_3stack_fixup_for_board_v1(void) +{ +#if defined(CONFIG_MXC_MLB) || defined(CONFIG_MXC_MLB_MODULE) + mlb_data.reg_nvcc = "LDO6"; +#endif + +#if defined(CONFIG_SDIO_UNIFI_FS) || defined(CONFIG_SDIO_UNIFI_FS_MODULE) + unifi_data.reg_gpo1 = NULL; + unifi_data.reg_gpo2 = NULL; + unifi_data.reg_1v5_ana_bb = "SW4"; + unifi_data.reg_vdd_vpa = "SW1"; + unifi_data.reg_1v5_dd = "SW4"; +#endif + camera_data.analog_regulator = "LDO7"; + camera_data.core_regulator = NULL; + camera_data.io_regulator = NULL; + camera_data.gpo_regulator = NULL; + camera_data.mclk = 20000000; + + adv7180_data.dvddio_reg = NULL; + adv7180_data.dvdd_reg = NULL; + adv7180_data.avdd_reg = NULL; + adv7180_data.pvdd_reg = NULL; + + si4702_data.reg_vio = "SW1"; + si4702_data.reg_vdd = NULL; + +#if defined(CONFIG_GPS_IOCTRL) || defined(CONFIG_GPS_IOCTRL_MODULE) + gps_data.core_reg = "SW1"; + gps_data.analog_reg = "SW2"; +#endif + + mxc_bt_data.bt_vdd = "SW1"; + +#if defined(CONFIG_CAN_FLEXCAN) || defined(CONFIG_CAN_FLEXCAN_MODULE) + flexcan_data[0].core_reg = "SW1"; + flexcan_data[1].core_reg = "SW1"; +#endif +} + +/*! + * Board specific initialization. + */ +static void __init mxc_board_init(void) +{ + mxc_cpu_common_init(); + + early_console_setup(saved_command_line); + mxc_register_gpios(); + mxc_init_devices(); + if (!board_is_rev(BOARD_REV_2)) + mx35_3stack_fixup_for_board_v1(); + mx35_3stack_gpio_init(); + mxc_init_enet(); + mxc_init_nor_mtd(); + mxc_init_nand_mtd(); + + mx35_3stack_init_mc13892(); + mx35_3stack_init_mc9s08dz60(); + mxc_init_lcd(); + mxc_init_fb(); + mxc_init_bl(); + mxc_init_sgtl5000(); + mxc_init_ak4647(); + + i2c_register_board_info(0, mxc_i2c_board_info, + ARRAY_SIZE(mxc_i2c_board_info)); + + spi_register_board_info(mxc_spi_board_info, + ARRAY_SIZE(mxc_spi_board_info)); + mxc_init_mmc(); + mxc_init_pata(); + mxc_init_bluetooth(); + mxc_init_gps(); + mxc_init_mlb(); + mxc_init_fec(); +} + +#define PLL_PCTL_REG(brmo, pd, mfd, mfi, mfn) \ + (((brmo) << 31) + (((pd) - 1) << 26) + (((mfd) - 1) << 16) + \ + ((mfi) << 10) + mfn) + +/* For 24MHz input clock */ +#define PLL_665MHZ PLL_PCTL_REG(1, 1, 48, 13, 41) +#define PLL_532MHZ PLL_PCTL_REG(1, 1, 12, 11, 1) +#define PLL_399MHZ PLL_PCTL_REG(0, 1, 16, 8, 5) + +/* working point(wp): 0,1 - 133MHz; 2,3 - 266MHz; 4,5 - 399MHz;*/ +/* auto input clock table */ +static struct cpu_wp cpu_wp_auto[] = { + { + .pll_reg = PLL_399MHZ, + .pll_rate = 399000000, + .cpu_rate = 133000000, + .pdr0_reg = (0x2 << MXC_CCM_PDR0_AUTO_MUX_DIV_OFFSET),}, + { + .pll_reg = PLL_399MHZ, + .pll_rate = 399000000, + .cpu_rate = 133000000, + .pdr0_reg = (0x6 << MXC_CCM_PDR0_AUTO_MUX_DIV_OFFSET),}, + { + .pll_reg = PLL_399MHZ, + .pll_rate = 399000000, + .cpu_rate = 266000000, + .pdr0_reg = (0x1 << MXC_CCM_PDR0_AUTO_MUX_DIV_OFFSET),}, + { + .pll_reg = PLL_399MHZ, + .pll_rate = 399000000, + .cpu_rate = 266000000, + .pdr0_reg = (0x5 << MXC_CCM_PDR0_AUTO_MUX_DIV_OFFSET),}, + { + .pll_reg = PLL_399MHZ, + .pll_rate = 399000000, + .cpu_rate = 399000000, + .pdr0_reg = (0x0 << MXC_CCM_PDR0_AUTO_MUX_DIV_OFFSET),}, + { + .pll_reg = PLL_399MHZ, + .pll_rate = 399000000, + .cpu_rate = 399000000, + .pdr0_reg = (0x6 << MXC_CCM_PDR0_AUTO_MUX_DIV_OFFSET),}, +}; + +/* consumer input clock table */ +static struct cpu_wp cpu_wp_con[] = { + { + .pll_reg = PLL_532MHZ, + .pll_rate = 532000000, + .cpu_rate = 133000000, + .pdr0_reg = (0x6 << MXC_CCM_PDR0_CON_MUX_DIV_OFFSET),}, + { + .pll_reg = PLL_532MHZ, + .pll_rate = 532000000, + .cpu_rate = 133000000, + .pdr0_reg = (0xE << MXC_CCM_PDR0_CON_MUX_DIV_OFFSET),}, + { + .pll_reg = PLL_532MHZ, + .pll_rate = 532000000, + .cpu_rate = 266000000, + .pdr0_reg = (0x2 << MXC_CCM_PDR0_CON_MUX_DIV_OFFSET),}, + { + .pll_reg = PLL_532MHZ, + .pll_rate = 532000000, + .cpu_rate = 266000000, + .pdr0_reg = (0xA << MXC_CCM_PDR0_CON_MUX_DIV_OFFSET),}, + { + .pll_reg = PLL_532MHZ, + .pll_rate = 532000000, + .cpu_rate = 399000000, + .pdr0_reg = (0x1 << MXC_CCM_PDR0_CON_MUX_DIV_OFFSET),}, + { + .pll_reg = PLL_532MHZ, + .pll_rate = 532000000, + .cpu_rate = 399000000, + .pdr0_reg = (0x9 << MXC_CCM_PDR0_CON_MUX_DIV_OFFSET),}, + { + .pll_reg = PLL_532MHZ, + .pll_rate = 532000000, + .cpu_rate = 532000000, + .pdr0_reg = (0x0 << MXC_CCM_PDR0_CON_MUX_DIV_OFFSET),}, + { + .pll_reg = PLL_532MHZ, + .pll_rate = 532000000, + .cpu_rate = 532000000, + .pdr0_reg = (0x8 << MXC_CCM_PDR0_CON_MUX_DIV_OFFSET),}, + { + .pll_reg = PLL_665MHZ, + .pll_rate = 665000000, + .cpu_rate = 665000000, + .pdr0_reg = (0x7 << MXC_CCM_PDR0_CON_MUX_DIV_OFFSET),}, +}; + +struct cpu_wp *get_cpu_wp(int *wp) +{ + if (cpu_is_mx35_rev(CHIP_REV_2_0) >= 1) { + *wp = 9; + return cpu_wp_con; + } else { + if (__raw_readl(MXC_CCM_PDR0) & MXC_CCM_PDR0_AUTO_CON) { + *wp = 9; + return cpu_wp_con; + } else { + *wp = 6; + return cpu_wp_auto; + } + } +} + +static void __init mx35_3stack_timer_init(void) +{ + mx35_clocks_init(); +} + +static struct sys_timer mxc_timer = { + .init = mx35_3stack_timer_init, +}; + +/* + * The following uses standard kernel macros define in arch.h in order to + * initialize __mach_desc_MX35_3DS data structure. + */ +/* *INDENT-OFF* */ +MACHINE_START(MX35_3DS, "Freescale MX35 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 = mx35_map_io, + .init_irq = mxc_init_irq, + .init_machine = mxc_board_init, + .timer = &mxc_timer, +MACHINE_END diff --git a/arch/arm/mach-mx35/mx35_3stack_cpld.c b/arch/arm/mach-mx35/mx35_3stack_cpld.c new file mode 100644 index 000000000000..efa4b2b42019 --- /dev/null +++ b/arch/arm/mach-mx35/mx35_3stack_cpld.c @@ -0,0 +1,161 @@ +/* + * 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/interrupt.h> +#include <linux/irq.h> +#include <linux/init.h> +#include <linux/io.h> +#include <linux/clk.h> + +#include <asm/irq.h> +#include <asm/setup.h> +#include <asm/mach-types.h> +#include <asm/mach/arch.h> +#include <mach/hardware.h> +#include <mach/gpio.h> + +#include "board-mx35_3stack.h" +#include "crm_regs.h" +#include "iomux.h" + +/*! + * @file mach-mx35/mx35_3stack_cpld.c + * + * @brief This file contains the board specific initialization routines. + * + * @ingroup MSL_MX35 + */ +static void mxc_expio_irq_handler(u32 irq, struct irq_desc *desc) +{ + u32 expio_irq; + u32 index, mask; + desc->chip->mask(irq); /* irq = gpio irq number */ + + index = __raw_readw(mx35_3stack_board_io + INTR_STATUS_REG); + mask = __raw_readw(mx35_3stack_board_io + INTR_MASK_REG); + + if (unlikely(!(index & (~mask)))) { + printk(KERN_ERR "\nEXPIO: Spurious interrupt:0x%0x\n\n", index); + pr_info("CPLD IMR(0x38)=0x%x, PENDING(0x28)=0x%x\n", mask, + index); + goto out; + } + index = index & (~mask); + expio_irq = MXC_BOARD_IRQ_START; + for (; index != 0; index >>= 1, expio_irq++) { + struct irq_desc *d; + if ((index & 1) == 0) + continue; + d = irq_desc + expio_irq; + if (unlikely(!(d->handle_irq))) { + printk(KERN_ERR "\nEXPIO irq: %d unhandeled\n", + expio_irq); + BUG(); /* oops */ + } + d->handle_irq(expio_irq, d); + } + + out: + desc->chip->ack(irq); + desc->chip->unmask(irq); +} + +/* + * 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, expio = MXC_IRQ_TO_EXPIO(irq); + + reg = __raw_readw(mx35_3stack_board_io + INTR_MASK_REG); + /* mask the interrupt */ + __raw_writew(reg | (1 << expio), mx35_3stack_board_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, mx35_3stack_board_io + INTR_RESET_REG); + __raw_writew(0, mx35_3stack_board_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, expio = MXC_IRQ_TO_EXPIO(irq); + + reg = __raw_readw(mx35_3stack_board_io + INTR_MASK_REG); + /* unmask the interrupt */ + __raw_writew(reg & (~(1 << expio)), + mx35_3stack_board_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; + + mx35_3stack_board_io = (u32) ioremap(BOARD_IO_ADDR, SZ_4K); + if (mx35_3stack_board_io == 0) + return -ENOMEM; + + if ((__raw_readw(mx35_3stack_board_io + MAGIC_NUMBER1_REG) != 0xAAAA) || + (__raw_readw(mx35_3stack_board_io + MAGIC_NUMBER2_REG) != 0x5555)) + return -ENODEV; + + pr_info("3-Stack Debug board detected, rev = 0x%04X\n", + readw(mx35_3stack_board_io + CPLD_CODE_VER_REG)); + + /* + * Configure INT line as GPIO input + */ + mxc_request_iomux(EXPIO_PARENT_INT, MUX_CONFIG_FUNC); + gpio_request(IOMUX_TO_GPIO(EXPIO_PARENT_INT), NULL); + gpio_direction_input(IOMUX_TO_GPIO(EXPIO_PARENT_INT)); + + /* disable the interrupt and clear the status */ + __raw_writew(0, mx35_3stack_board_io + INTR_MASK_REG); + __raw_writew(0xFFFF, mx35_3stack_board_io + INTR_RESET_REG); + __raw_writew(0, mx35_3stack_board_io + INTR_RESET_REG); + __raw_writew(0x1F, mx35_3stack_board_io + INTR_MASK_REG); + for (i = MXC_BOARD_IRQ_START; i < (MXC_BOARD_IRQ_START + MXC_BOARD_IRQS); + i++) { + set_irq_chip(i, &expio_irq_chip); + set_irq_handler(i, handle_level_irq); + set_irq_flags(i, IRQF_VALID); + } + set_irq_type(IOMUX_TO_IRQ(EXPIO_PARENT_INT), IRQF_TRIGGER_LOW); + set_irq_chained_handler(IOMUX_TO_IRQ(EXPIO_PARENT_INT), + mxc_expio_irq_handler); + return 0; +} + +arch_initcall(mxc_expio_init); diff --git a/arch/arm/mach-mx35/mx35_3stack_gpio.c b/arch/arm/mach-mx35/mx35_3stack_gpio.c new file mode 100644 index 000000000000..43474317add2 --- /dev/null +++ b/arch/arm/mach-mx35/mx35_3stack_gpio.c @@ -0,0 +1,1378 @@ +/* + * 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 <linux/io.h> +#include <mach/hardware.h> +#include <mach/gpio.h> +#include <linux/mfd/mc9s08dz60/pmic.h> +#include "board-mx35_3stack.h" +#include "iomux.h" + +/*! + * @file mach-mx35/mx35_3stack_gpio.c + * + * @brief This file contains all the GPIO setup functions for the board. + * + * @ingroup GPIO_MX35 + */ + +/*! + * This system-wise GPIO function initializes the pins during system startup. + * All the statically linked device drivers should put the proper GPIO + * initialization code inside this function. It is called by \b fixup_mx31ads() + * during system startup. This function is board specific. + */ +void mx35_3stack_gpio_init(void) +{ + /* config CS5 */ + mxc_request_iomux(MX35_PIN_CS5, MUX_CONFIG_FUNC); + + /* configure capture pin for ckil input */ + mxc_request_iomux(MX35_PIN_CAPTURE, MUX_CONFIG_ALT4); + mxc_iomux_set_pad(MX35_PIN_CAPTURE, + PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | + PAD_CTL_100K_PU | PAD_CTL_PUE_PUD); + mxc_iomux_set_input(MUX_IN_CCM_32K_MUXED, INPUT_CTL_PATH0); + +} + +/*! + * Setup GPIO for a UART port to be active + * + * @param port a UART port + * @param no_irda indicates if the port is used for SIR + */ +void gpio_uart_active(int port, int no_irda) +{ + /* + * Configure the IOMUX control registers for the UART signals + */ + switch (port) { + /* UART 1 IOMUX Configs */ + case 0: + mxc_request_iomux(MX35_PIN_RXD1, MUX_CONFIG_FUNC); + mxc_request_iomux(MX35_PIN_TXD1, MUX_CONFIG_FUNC); + mxc_request_iomux(MX35_PIN_RTS1, MUX_CONFIG_FUNC); + mxc_request_iomux(MX35_PIN_CTS1, MUX_CONFIG_FUNC); + + mxc_iomux_set_pad(MX35_PIN_RXD1, + PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | + PAD_CTL_PUE_PUD | PAD_CTL_100K_PU); + mxc_iomux_set_pad(MX35_PIN_TXD1, + PAD_CTL_PUE_PUD | PAD_CTL_100K_PD); + mxc_iomux_set_pad(MX35_PIN_RTS1, + PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | + PAD_CTL_PUE_PUD | PAD_CTL_100K_PU); + mxc_iomux_set_pad(MX35_PIN_CTS1, + PAD_CTL_PUE_PUD | PAD_CTL_100K_PD); + + break; + /* UART 2 IOMUX Configs */ + case 1: + mxc_request_iomux(MX35_PIN_TXD2, MUX_CONFIG_FUNC); + mxc_request_iomux(MX35_PIN_RXD2, MUX_CONFIG_FUNC); + mxc_request_iomux(MX35_PIN_RTS2, MUX_CONFIG_FUNC); + mxc_request_iomux(MX35_PIN_CTS2, MUX_CONFIG_FUNC); + mxc_iomux_set_pad(MX35_PIN_RXD2, + PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | + PAD_CTL_PUE_PUD | PAD_CTL_100K_PU); + mxc_iomux_set_pad(MX35_PIN_TXD2, + PAD_CTL_PUE_PUD | PAD_CTL_100K_PD); + mxc_iomux_set_pad(MX35_PIN_RTS2, + PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | + PAD_CTL_PUE_PUD | PAD_CTL_100K_PU); + mxc_iomux_set_pad(MX35_PIN_CTS2, + PAD_CTL_PUE_PUD | PAD_CTL_100K_PD); + break; + /* UART 3 IOMUX Configs */ + case 2: + mxc_request_iomux(MX35_PIN_FEC_TX_CLK, MUX_CONFIG_ALT2); + mxc_request_iomux(MX35_PIN_FEC_RX_CLK, MUX_CONFIG_ALT2); + mxc_request_iomux(MX35_PIN_FEC_COL, MUX_CONFIG_ALT2); + mxc_request_iomux(MX35_PIN_FEC_RX_DV, MUX_CONFIG_ALT2); + + mxc_iomux_set_pad(MX35_PIN_FEC_TX_CLK, + PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | + PAD_CTL_PUE_PUD | PAD_CTL_100K_PU); + mxc_iomux_set_pad(MX35_PIN_FEC_RX_CLK, + PAD_CTL_PUE_PUD | PAD_CTL_100K_PD); + mxc_iomux_set_pad(MX35_PIN_FEC_RX_DV, + PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | + PAD_CTL_PUE_PUD | PAD_CTL_100K_PU); + mxc_iomux_set_pad(MX35_PIN_FEC_COL, + PAD_CTL_PUE_PUD | PAD_CTL_100K_PD); + + mxc_iomux_set_input(MUX_IN_UART3_UART_RTS_B, INPUT_CTL_PATH2); + mxc_iomux_set_input(MUX_IN_UART3_UART_RXD_MUX, INPUT_CTL_PATH3); + break; + default: + break; + } + +} + +EXPORT_SYMBOL(gpio_uart_active); + +/*! + * Setup GPIO for a UART port to be inactive + * + * @param port a UART port + * @param no_irda indicates if the port is used for SIR + */ +void gpio_uart_inactive(int port, int no_irda) +{ + switch (port) { + case 0: + gpio_request(IOMUX_TO_GPIO(MX35_PIN_RXD1), NULL); + gpio_request(IOMUX_TO_GPIO(MX35_PIN_TXD1), NULL); + gpio_request(IOMUX_TO_GPIO(MX35_PIN_RTS1), NULL); + gpio_request(IOMUX_TO_GPIO(MX35_PIN_CTS1), NULL); + + mxc_free_iomux(MX35_PIN_RXD1, MUX_CONFIG_GPIO); + mxc_free_iomux(MX35_PIN_TXD1, MUX_CONFIG_GPIO); + mxc_free_iomux(MX35_PIN_RTS1, MUX_CONFIG_GPIO); + mxc_free_iomux(MX35_PIN_CTS1, MUX_CONFIG_GPIO); + break; + case 1: + gpio_request(IOMUX_TO_GPIO(MX35_PIN_RXD2), NULL); + gpio_request(IOMUX_TO_GPIO(MX35_PIN_TXD2), NULL); + gpio_request(IOMUX_TO_GPIO(MX35_PIN_RTS2), NULL); + gpio_request(IOMUX_TO_GPIO(MX35_PIN_CTS2), NULL); + + mxc_free_iomux(MX35_PIN_RXD2, MUX_CONFIG_GPIO); + mxc_free_iomux(MX35_PIN_TXD2, MUX_CONFIG_GPIO); + mxc_free_iomux(MX35_PIN_RTS2, MUX_CONFIG_GPIO); + mxc_free_iomux(MX35_PIN_CTS2, MUX_CONFIG_GPIO); + break; + case 2: + gpio_request(IOMUX_TO_GPIO(MX35_PIN_FEC_TX_CLK), NULL); + gpio_request(IOMUX_TO_GPIO(MX35_PIN_FEC_RX_CLK), NULL); + gpio_request(IOMUX_TO_GPIO(MX35_PIN_FEC_COL), NULL); + gpio_request(IOMUX_TO_GPIO(MX35_PIN_FEC_RX_DV), NULL); + + mxc_free_iomux(MX35_PIN_FEC_TX_CLK, MUX_CONFIG_GPIO); + mxc_free_iomux(MX35_PIN_FEC_RX_CLK, MUX_CONFIG_GPIO); + mxc_free_iomux(MX35_PIN_FEC_COL, MUX_CONFIG_GPIO); + mxc_free_iomux(MX35_PIN_FEC_RX_DV, MUX_CONFIG_GPIO); + + mxc_iomux_set_input(MUX_IN_UART3_UART_RTS_B, INPUT_CTL_PATH0); + mxc_iomux_set_input(MUX_IN_UART3_UART_RXD_MUX, INPUT_CTL_PATH0); + break; + default: + break; + } +} + +EXPORT_SYMBOL(gpio_uart_inactive); + +/*! + * Configure the IOMUX GPR register to receive shared SDMA UART events + * + * @param port a UART port + */ +void config_uartdma_event(int port) +{ +} + +EXPORT_SYMBOL(config_uartdma_event); + +void gpio_fec_active(void) +{ + mxc_request_iomux(MX35_PIN_FEC_TX_CLK, MUX_CONFIG_FUNC); + mxc_request_iomux(MX35_PIN_FEC_RX_CLK, MUX_CONFIG_FUNC); + mxc_request_iomux(MX35_PIN_FEC_RX_DV, MUX_CONFIG_FUNC); + mxc_request_iomux(MX35_PIN_FEC_COL, MUX_CONFIG_FUNC); + mxc_request_iomux(MX35_PIN_FEC_RDATA0, MUX_CONFIG_FUNC); + mxc_request_iomux(MX35_PIN_FEC_TDATA0, MUX_CONFIG_FUNC); + mxc_request_iomux(MX35_PIN_FEC_TX_EN, MUX_CONFIG_FUNC); + mxc_request_iomux(MX35_PIN_FEC_MDC, MUX_CONFIG_FUNC); + mxc_request_iomux(MX35_PIN_FEC_MDIO, MUX_CONFIG_FUNC); + mxc_request_iomux(MX35_PIN_FEC_TX_ERR, MUX_CONFIG_FUNC); + mxc_request_iomux(MX35_PIN_FEC_RX_ERR, MUX_CONFIG_FUNC); + mxc_request_iomux(MX35_PIN_FEC_CRS, MUX_CONFIG_FUNC); + mxc_request_iomux(MX35_PIN_FEC_RDATA1, MUX_CONFIG_FUNC); + mxc_request_iomux(MX35_PIN_FEC_TDATA1, MUX_CONFIG_FUNC); + mxc_request_iomux(MX35_PIN_FEC_RDATA2, MUX_CONFIG_FUNC); + mxc_request_iomux(MX35_PIN_FEC_TDATA2, MUX_CONFIG_FUNC); + mxc_request_iomux(MX35_PIN_FEC_RDATA3, MUX_CONFIG_FUNC); + mxc_request_iomux(MX35_PIN_FEC_TDATA3, MUX_CONFIG_FUNC); + +#define FEC_PAD_CTL_COMMON (PAD_CTL_DRV_3_3V|PAD_CTL_PUE_PUD| \ + PAD_CTL_ODE_CMOS|PAD_CTL_DRV_NORMAL|PAD_CTL_SRE_SLOW) + mxc_iomux_set_pad(MX35_PIN_FEC_TX_CLK, FEC_PAD_CTL_COMMON | + PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | + PAD_CTL_100K_PD); + mxc_iomux_set_pad(MX35_PIN_FEC_RX_CLK, + FEC_PAD_CTL_COMMON | PAD_CTL_HYS_SCHMITZ | + PAD_CTL_PKE_ENABLE | PAD_CTL_100K_PD); + mxc_iomux_set_pad(MX35_PIN_FEC_RX_DV, + FEC_PAD_CTL_COMMON | PAD_CTL_HYS_SCHMITZ | + PAD_CTL_PKE_ENABLE | PAD_CTL_100K_PD); + mxc_iomux_set_pad(MX35_PIN_FEC_COL, + FEC_PAD_CTL_COMMON | PAD_CTL_HYS_SCHMITZ | + PAD_CTL_PKE_ENABLE | PAD_CTL_100K_PD); + mxc_iomux_set_pad(MX35_PIN_FEC_RDATA0, + FEC_PAD_CTL_COMMON | PAD_CTL_HYS_SCHMITZ | + PAD_CTL_PKE_ENABLE | PAD_CTL_100K_PD); + mxc_iomux_set_pad(MX35_PIN_FEC_TDATA0, + FEC_PAD_CTL_COMMON | PAD_CTL_HYS_CMOS | + PAD_CTL_PKE_NONE | PAD_CTL_100K_PD); + mxc_iomux_set_pad(MX35_PIN_FEC_TX_EN, + FEC_PAD_CTL_COMMON | PAD_CTL_HYS_CMOS | + PAD_CTL_PKE_NONE | PAD_CTL_100K_PD); + mxc_iomux_set_pad(MX35_PIN_FEC_MDC, + FEC_PAD_CTL_COMMON | PAD_CTL_HYS_CMOS | + PAD_CTL_PKE_NONE | PAD_CTL_100K_PD); + mxc_iomux_set_pad(MX35_PIN_FEC_MDIO, + FEC_PAD_CTL_COMMON | PAD_CTL_HYS_SCHMITZ | + PAD_CTL_PKE_ENABLE | PAD_CTL_22K_PU); + mxc_iomux_set_pad(MX35_PIN_FEC_TX_ERR, + FEC_PAD_CTL_COMMON | PAD_CTL_HYS_CMOS | + PAD_CTL_PKE_NONE | PAD_CTL_100K_PD); + mxc_iomux_set_pad(MX35_PIN_FEC_RX_ERR, + FEC_PAD_CTL_COMMON | PAD_CTL_HYS_SCHMITZ | + PAD_CTL_PKE_ENABLE | PAD_CTL_100K_PD); + mxc_iomux_set_pad(MX35_PIN_FEC_CRS, + FEC_PAD_CTL_COMMON | PAD_CTL_HYS_SCHMITZ | + PAD_CTL_PKE_ENABLE | PAD_CTL_100K_PD); + mxc_iomux_set_pad(MX35_PIN_FEC_RDATA1, + FEC_PAD_CTL_COMMON | PAD_CTL_HYS_SCHMITZ | + PAD_CTL_PKE_ENABLE | PAD_CTL_100K_PD); + mxc_iomux_set_pad(MX35_PIN_FEC_TDATA1, + FEC_PAD_CTL_COMMON | PAD_CTL_HYS_CMOS | + PAD_CTL_PKE_NONE | PAD_CTL_100K_PD); + mxc_iomux_set_pad(MX35_PIN_FEC_RDATA2, + FEC_PAD_CTL_COMMON | PAD_CTL_HYS_SCHMITZ | + PAD_CTL_PKE_ENABLE | PAD_CTL_100K_PD); + mxc_iomux_set_pad(MX35_PIN_FEC_TDATA2, + FEC_PAD_CTL_COMMON | PAD_CTL_HYS_CMOS | + PAD_CTL_PKE_NONE | PAD_CTL_100K_PD); + mxc_iomux_set_pad(MX35_PIN_FEC_RDATA3, + FEC_PAD_CTL_COMMON | PAD_CTL_HYS_SCHMITZ | + PAD_CTL_PKE_ENABLE | PAD_CTL_100K_PD); + mxc_iomux_set_pad(MX35_PIN_FEC_TDATA3, + FEC_PAD_CTL_COMMON | PAD_CTL_HYS_CMOS | + PAD_CTL_PKE_NONE | PAD_CTL_100K_PD); +#undef FEC_PAD_CTL_COMMON + /* Pull GPIO1_5 to be high for routing signal to FEC */ + if (board_is_rev(BOARD_REV_2)) { + mxc_request_iomux(MX35_PIN_COMPARE, MUX_CONFIG_GPIO); + mxc_iomux_set_pad(MX35_PIN_COMPARE, PAD_CTL_DRV_NORMAL | + PAD_CTL_PKE_ENABLE | PAD_CTL_100K_PU | + PAD_CTL_DRV_3_3V | PAD_CTL_PUE_PUD | + PAD_CTL_SRE_SLOW); + gpio_request(IOMUX_TO_GPIO(MX35_PIN_COMPARE), "compare"); + gpio_direction_output(IOMUX_TO_GPIO(MX35_PIN_COMPARE), 0); + gpio_set_value(IOMUX_TO_GPIO(MX35_PIN_COMPARE), 1); + } + + /* FEC enable */ + pmic_gpio_set_bit_val(MCU_GPIO_REG_GPIO_CONTROL_1, 2, 1); + /* FEC reset */ + pmic_gpio_set_bit_val(MCU_GPIO_REG_RESET_1, 7, 0); + msleep(10); + pmic_gpio_set_bit_val(MCU_GPIO_REG_RESET_1, 7, 1); + msleep(100); +} + +EXPORT_SYMBOL(gpio_fec_active); + +void gpio_fec_inactive(void) +{ + gpio_request(IOMUX_TO_GPIO(MX35_PIN_FEC_TX_CLK), NULL); + gpio_request(IOMUX_TO_GPIO(MX35_PIN_FEC_RX_CLK), NULL); + gpio_request(IOMUX_TO_GPIO(MX35_PIN_FEC_RX_DV), NULL); + gpio_request(IOMUX_TO_GPIO(MX35_PIN_FEC_COL), NULL); + gpio_request(IOMUX_TO_GPIO(MX35_PIN_FEC_RDATA0), NULL); + gpio_request(IOMUX_TO_GPIO(MX35_PIN_FEC_TDATA0), NULL); + gpio_request(IOMUX_TO_GPIO(MX35_PIN_FEC_TX_EN), NULL); + gpio_request(IOMUX_TO_GPIO(MX35_PIN_FEC_MDC), NULL); + gpio_request(IOMUX_TO_GPIO(MX35_PIN_FEC_MDIO), NULL); + gpio_request(IOMUX_TO_GPIO(MX35_PIN_FEC_TX_ERR), NULL); + gpio_request(IOMUX_TO_GPIO(MX35_PIN_FEC_RX_ERR), NULL); + gpio_request(IOMUX_TO_GPIO(MX35_PIN_FEC_CRS), NULL); + gpio_request(IOMUX_TO_GPIO(MX35_PIN_FEC_RDATA1), NULL); + gpio_request(IOMUX_TO_GPIO(MX35_PIN_FEC_TDATA1), NULL); + gpio_request(IOMUX_TO_GPIO(MX35_PIN_FEC_RDATA2), NULL); + gpio_request(IOMUX_TO_GPIO(MX35_PIN_FEC_TDATA2), NULL); + gpio_request(IOMUX_TO_GPIO(MX35_PIN_FEC_RDATA3), NULL); + gpio_request(IOMUX_TO_GPIO(MX35_PIN_FEC_TDATA3), NULL); + + mxc_free_iomux(MX35_PIN_FEC_TX_CLK, MUX_CONFIG_GPIO); + mxc_free_iomux(MX35_PIN_FEC_RX_CLK, MUX_CONFIG_GPIO); + mxc_free_iomux(MX35_PIN_FEC_RX_DV, MUX_CONFIG_GPIO); + mxc_free_iomux(MX35_PIN_FEC_COL, MUX_CONFIG_GPIO); + mxc_free_iomux(MX35_PIN_FEC_RDATA0, MUX_CONFIG_GPIO); + mxc_free_iomux(MX35_PIN_FEC_TDATA0, MUX_CONFIG_GPIO); + mxc_free_iomux(MX35_PIN_FEC_TX_EN, MUX_CONFIG_GPIO); + mxc_free_iomux(MX35_PIN_FEC_MDC, MUX_CONFIG_GPIO); + mxc_free_iomux(MX35_PIN_FEC_MDIO, MUX_CONFIG_GPIO); + mxc_free_iomux(MX35_PIN_FEC_TX_ERR, MUX_CONFIG_GPIO); + mxc_free_iomux(MX35_PIN_FEC_RX_ERR, MUX_CONFIG_GPIO); + mxc_free_iomux(MX35_PIN_FEC_CRS, MUX_CONFIG_GPIO); + mxc_free_iomux(MX35_PIN_FEC_RDATA1, MUX_CONFIG_GPIO); + mxc_free_iomux(MX35_PIN_FEC_TDATA1, MUX_CONFIG_GPIO); + mxc_free_iomux(MX35_PIN_FEC_RDATA2, MUX_CONFIG_GPIO); + mxc_free_iomux(MX35_PIN_FEC_TDATA2, MUX_CONFIG_GPIO); + mxc_free_iomux(MX35_PIN_FEC_RDATA3, MUX_CONFIG_GPIO); + mxc_free_iomux(MX35_PIN_FEC_TDATA3, MUX_CONFIG_GPIO); + + pmic_gpio_set_bit_val(MCU_GPIO_REG_GPIO_CONTROL_1, 2, 0); + + /* Free GPIO1_5 */ + if (board_is_rev(BOARD_REV_2)) { + gpio_free(IOMUX_TO_GPIO(MX35_PIN_COMPARE)); + mxc_free_iomux(MX35_PIN_COMPARE, MUX_CONFIG_GPIO); + } +} + +EXPORT_SYMBOL(gpio_fec_inactive); + +/*! + * Setup GPIO for an I2C device to be active + * + * @param i2c_num an I2C device + */ +void gpio_i2c_active(int i2c_num) +{ + +#define PAD_CONFIG (PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PUD | PAD_CTL_ODE_OpenDrain) + + switch (i2c_num) { + case 0: + mxc_request_iomux(MX35_PIN_I2C1_CLK, MUX_CONFIG_SION); + mxc_request_iomux(MX35_PIN_I2C1_DAT, MUX_CONFIG_SION); + + mxc_iomux_set_pad(MX35_PIN_I2C1_CLK, PAD_CONFIG); + mxc_iomux_set_pad(MX35_PIN_I2C1_DAT, PAD_CONFIG); + break; + case 1: + mxc_request_iomux(MX35_PIN_I2C2_CLK, MUX_CONFIG_SION); + mxc_request_iomux(MX35_PIN_I2C2_DAT, MUX_CONFIG_SION); + + mxc_iomux_set_pad(MX35_PIN_I2C2_CLK, PAD_CONFIG); + mxc_iomux_set_pad(MX35_PIN_I2C2_DAT, PAD_CONFIG); + + break; + case 2: + mxc_request_iomux(MX35_PIN_TX3_RX2, MUX_CONFIG_ALT1); + mxc_request_iomux(MX35_PIN_TX2_RX3, MUX_CONFIG_ALT1); + mxc_iomux_set_pad(MX35_PIN_TX3_RX2, PAD_CONFIG); + mxc_iomux_set_pad(MX35_PIN_TX2_RX3, PAD_CONFIG); + break; + default: + break; + } + +#undef PAD_CONFIG + +} + +EXPORT_SYMBOL(gpio_i2c_active); + +/*! + * Setup GPIO for an I2C device to be inactive + * + * @param i2c_num an I2C device + */ +void gpio_i2c_inactive(int i2c_num) +{ + switch (i2c_num) { + case 0: + break; + case 1: + break; + case 2: + mxc_request_iomux(MX35_PIN_TX3_RX2, MUX_CONFIG_GPIO); + mxc_request_iomux(MX35_PIN_TX2_RX3, MUX_CONFIG_GPIO); + break; + default: + break; + } +} + +EXPORT_SYMBOL(gpio_i2c_inactive); + +/*! + * Setup GPIO for a CSPI device to be active + * + * @param cspi_mod an CSPI device + */ +void gpio_spi_active(int cspi_mod) +{ + switch (cspi_mod) { + case 0: + /* SPI1 */ + mxc_request_iomux(MX35_PIN_CSPI1_MOSI, MUX_CONFIG_FUNC); + mxc_request_iomux(MX35_PIN_CSPI1_MISO, MUX_CONFIG_FUNC); + mxc_request_iomux(MX35_PIN_CSPI1_SS0, MUX_CONFIG_FUNC); + mxc_request_iomux(MX35_PIN_CSPI1_SS1, MUX_CONFIG_FUNC); + mxc_request_iomux(MX35_PIN_CSPI1_SCLK, MUX_CONFIG_FUNC); + mxc_request_iomux(MX35_PIN_CSPI1_SPI_RDY, MUX_CONFIG_FUNC); + + mxc_iomux_set_pad(MX35_PIN_CSPI1_MOSI, + PAD_CTL_DRV_3_3V | PAD_CTL_HYS_SCHMITZ | + PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PUD | + PAD_CTL_100K_PD | PAD_CTL_DRV_NORMAL); + mxc_iomux_set_pad(MX35_PIN_CSPI1_MISO, + PAD_CTL_DRV_3_3V | PAD_CTL_HYS_SCHMITZ | + PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PUD | + PAD_CTL_100K_PD | PAD_CTL_DRV_NORMAL); + mxc_iomux_set_pad(MX35_PIN_CSPI1_SS0, + PAD_CTL_DRV_3_3V | PAD_CTL_HYS_SCHMITZ | + PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PUD | + PAD_CTL_100K_PU | PAD_CTL_ODE_CMOS | + PAD_CTL_DRV_NORMAL); + mxc_iomux_set_pad(MX35_PIN_CSPI1_SS1, + PAD_CTL_DRV_3_3V | PAD_CTL_HYS_SCHMITZ | + PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PUD | + PAD_CTL_100K_PU | PAD_CTL_ODE_CMOS | + PAD_CTL_DRV_NORMAL); + mxc_iomux_set_pad(MX35_PIN_CSPI1_SCLK, + PAD_CTL_DRV_3_3V | PAD_CTL_HYS_SCHMITZ | + PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PUD | + PAD_CTL_100K_PD | PAD_CTL_DRV_NORMAL); + mxc_iomux_set_pad(MX35_PIN_CSPI1_SPI_RDY, + PAD_CTL_DRV_3_3V | PAD_CTL_HYS_SCHMITZ | + PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PUD | + PAD_CTL_100K_PU | PAD_CTL_DRV_NORMAL); + break; + case 1: + /* SPI2 */ + break; + default: + break; + } +} + +EXPORT_SYMBOL(gpio_spi_active); + +/*! + * Setup GPIO for a CSPI device to be inactive + * + * @param cspi_mod a CSPI device + */ +void gpio_spi_inactive(int cspi_mod) +{ + switch (cspi_mod) { + case 0: + /* SPI1 */ + gpio_request(IOMUX_TO_GPIO(MX35_PIN_CSPI1_MOSI), NULL); + gpio_request(IOMUX_TO_GPIO(MX35_PIN_CSPI1_MISO), NULL); + gpio_request(IOMUX_TO_GPIO(MX35_PIN_CSPI1_SS0), NULL); + gpio_request(IOMUX_TO_GPIO(MX35_PIN_CSPI1_SS1), NULL); + gpio_request(IOMUX_TO_GPIO(MX35_PIN_CSPI1_SCLK), NULL); + gpio_request(IOMUX_TO_GPIO(MX35_PIN_CSPI1_SPI_RDY), NULL); + + mxc_free_iomux(MX35_PIN_CSPI1_MOSI, MUX_CONFIG_GPIO); + mxc_free_iomux(MX35_PIN_CSPI1_MISO, MUX_CONFIG_GPIO); + mxc_free_iomux(MX35_PIN_CSPI1_SS0, MUX_CONFIG_GPIO); + mxc_free_iomux(MX35_PIN_CSPI1_SS1, MUX_CONFIG_GPIO); + mxc_free_iomux(MX35_PIN_CSPI1_SCLK, MUX_CONFIG_GPIO); + mxc_free_iomux(MX35_PIN_CSPI1_SPI_RDY, MUX_CONFIG_GPIO); + break; + case 1: + /* SPI2 */ + break; + default: + break; + } +} + +EXPORT_SYMBOL(gpio_spi_inactive); + +/*! + * Setup GPIO for LCD to be active + */ +void gpio_lcd_active(void) +{ + mxc_request_iomux(MX35_PIN_LD0, MUX_CONFIG_FUNC); + mxc_request_iomux(MX35_PIN_LD1, MUX_CONFIG_FUNC); + mxc_request_iomux(MX35_PIN_LD2, MUX_CONFIG_FUNC); + mxc_request_iomux(MX35_PIN_LD3, MUX_CONFIG_FUNC); + mxc_request_iomux(MX35_PIN_LD4, MUX_CONFIG_FUNC); + mxc_request_iomux(MX35_PIN_LD5, MUX_CONFIG_FUNC); + mxc_request_iomux(MX35_PIN_LD6, MUX_CONFIG_FUNC); + mxc_request_iomux(MX35_PIN_LD7, MUX_CONFIG_FUNC); + mxc_request_iomux(MX35_PIN_LD8, MUX_CONFIG_FUNC); + mxc_request_iomux(MX35_PIN_LD9, MUX_CONFIG_FUNC); + mxc_request_iomux(MX35_PIN_LD10, MUX_CONFIG_FUNC); + mxc_request_iomux(MX35_PIN_LD11, MUX_CONFIG_FUNC); + mxc_request_iomux(MX35_PIN_LD12, MUX_CONFIG_FUNC); + mxc_request_iomux(MX35_PIN_LD13, MUX_CONFIG_FUNC); + mxc_request_iomux(MX35_PIN_LD14, MUX_CONFIG_FUNC); + mxc_request_iomux(MX35_PIN_LD15, MUX_CONFIG_FUNC); + mxc_request_iomux(MX35_PIN_LD16, MUX_CONFIG_FUNC); + mxc_request_iomux(MX35_PIN_LD17, MUX_CONFIG_FUNC); + mxc_request_iomux(MX35_PIN_D3_VSYNC, MUX_CONFIG_FUNC); + mxc_request_iomux(MX35_PIN_D3_HSYNC, MUX_CONFIG_FUNC); + mxc_request_iomux(MX35_PIN_D3_FPSHIFT, MUX_CONFIG_FUNC); + mxc_request_iomux(MX35_PIN_D3_DRDY, MUX_CONFIG_FUNC); + mxc_request_iomux(MX35_PIN_CONTRAST, MUX_CONFIG_FUNC); +} + +EXPORT_SYMBOL(gpio_lcd_active); + +/*! + * Setup GPIO for LCD to be inactive + */ +void gpio_lcd_inactive(void) +{ +} + +EXPORT_SYMBOL(gpio_lcd_inactive); + +/*! + * Setup pin for touchscreen + */ +void gpio_tsc_active(void) +{ + unsigned int pad_val = PAD_CTL_PKE_ENABLE | PAD_CTL_100K_PU; + mxc_request_iomux(MX35_PIN_CAPTURE, MUX_CONFIG_GPIO); + mxc_iomux_set_pad(MX35_PIN_CAPTURE, pad_val); + gpio_request(IOMUX_TO_GPIO(MX35_PIN_CAPTURE), "capture"); + gpio_direction_input(IOMUX_TO_GPIO(MX35_PIN_CAPTURE)); +} + +/*! + * Release pin for touchscreen + */ +void gpio_tsc_inactive(void) +{ + gpio_free(IOMUX_TO_GPIO(MX35_PIN_CAPTURE)); + mxc_free_iomux(MX35_PIN_CAPTURE, MUX_CONFIG_GPIO); +} + +/*! + * Setup GPIO for SDHC to be active + * + * @param module SDHC module number + */ +void gpio_sdhc_active(int module) +{ + unsigned int pad_val; + + switch (module) { + case 0: + mxc_request_iomux(MX35_PIN_SD1_CLK, + MUX_CONFIG_FUNC | MUX_CONFIG_SION); + mxc_request_iomux(MX35_PIN_SD1_CMD, + MUX_CONFIG_FUNC | MUX_CONFIG_SION); + mxc_request_iomux(MX35_PIN_SD1_DATA0, + MUX_CONFIG_FUNC | MUX_CONFIG_SION); + mxc_request_iomux(MX35_PIN_SD1_DATA1, + MUX_CONFIG_FUNC | MUX_CONFIG_SION); + mxc_request_iomux(MX35_PIN_SD1_DATA2, + MUX_CONFIG_FUNC | MUX_CONFIG_SION); + mxc_request_iomux(MX35_PIN_SD1_DATA3, + MUX_CONFIG_FUNC | MUX_CONFIG_SION); +#if defined(CONFIG_SDIO_UNIFI_FS) || defined(CONFIG_SDIO_UNIFI_FS_MODULE) +#else + /* MUX4_CTR , 0: SD2 to WIFI, 1:SD2 to SD1 8bit */ + if (board_is_rev(BOARD_REV_2)) + pmic_gpio_set_bit_val(MCU_GPIO_REG_GPIO_CONTROL_2, + 7, 1); + mxc_request_iomux(MX35_PIN_SD2_CMD, + MUX_CONFIG_ALT2 | MUX_CONFIG_SION); + mxc_request_iomux(MX35_PIN_SD2_CLK, + MUX_CONFIG_ALT2 | MUX_CONFIG_SION); + mxc_request_iomux(MX35_PIN_SD2_DATA0, + MUX_CONFIG_ALT2 | MUX_CONFIG_SION); + mxc_request_iomux(MX35_PIN_SD2_DATA1, + MUX_CONFIG_ALT2 | MUX_CONFIG_SION); +#endif + + pad_val = PAD_CTL_PUE_PUD | PAD_CTL_PKE_ENABLE | + PAD_CTL_HYS_SCHMITZ | PAD_CTL_DRV_MAX | + PAD_CTL_47K_PU | PAD_CTL_SRE_FAST; + mxc_iomux_set_pad(MX35_PIN_SD1_CMD, pad_val); + mxc_iomux_set_pad(MX35_PIN_SD1_DATA0, pad_val); + mxc_iomux_set_pad(MX35_PIN_SD1_DATA1, pad_val); + mxc_iomux_set_pad(MX35_PIN_SD1_DATA2, pad_val); + pad_val = PAD_CTL_PUE_PUD | PAD_CTL_PKE_ENABLE | + PAD_CTL_DRV_MAX | PAD_CTL_47K_PU | PAD_CTL_SRE_FAST; + mxc_iomux_set_pad(MX35_PIN_SD1_CLK, pad_val); + pad_val = PAD_CTL_PUE_PUD | PAD_CTL_PKE_ENABLE | + PAD_CTL_HYS_SCHMITZ | PAD_CTL_DRV_MAX | + PAD_CTL_100K_PU | PAD_CTL_SRE_FAST; + mxc_iomux_set_pad(MX35_PIN_SD1_DATA3, pad_val); +#if defined(CONFIG_SDIO_UNIFI_FS) || defined(CONFIG_SDIO_UNIFI_FS_MODULE) +#else + pad_val = PAD_CTL_PUE_PUD | PAD_CTL_PKE_ENABLE | + PAD_CTL_HYS_SCHMITZ | PAD_CTL_DRV_MAX | + PAD_CTL_47K_PU | PAD_CTL_SRE_FAST; + mxc_iomux_set_pad(MX35_PIN_SD2_CMD, pad_val); + mxc_iomux_set_pad(MX35_PIN_SD2_DATA0, pad_val); + mxc_iomux_set_pad(MX35_PIN_SD2_DATA1, pad_val); + pad_val = PAD_CTL_PUE_PUD | PAD_CTL_PKE_ENABLE | + PAD_CTL_DRV_MAX | PAD_CTL_47K_PU | PAD_CTL_SRE_FAST; + mxc_iomux_set_pad(MX35_PIN_SD2_CLK, pad_val); +#endif + break; + case 1: + /* MUX4_CTR , 0: SD2 to WIFI, 1:SD2 to SD1 8bit */ + if (board_is_rev(BOARD_REV_2)) + pmic_gpio_set_bit_val(MCU_GPIO_REG_GPIO_CONTROL_2, + 7, 0); + mxc_request_iomux(MX35_PIN_SD2_CLK, + MUX_CONFIG_FUNC | MUX_CONFIG_SION); + mxc_request_iomux(MX35_PIN_SD2_CMD, + MUX_CONFIG_FUNC | MUX_CONFIG_SION); + mxc_request_iomux(MX35_PIN_SD2_DATA0, + MUX_CONFIG_FUNC | MUX_CONFIG_SION); + mxc_request_iomux(MX35_PIN_SD2_DATA1, + MUX_CONFIG_FUNC | MUX_CONFIG_SION); + mxc_request_iomux(MX35_PIN_SD2_DATA2, + MUX_CONFIG_FUNC | MUX_CONFIG_SION); + mxc_request_iomux(MX35_PIN_SD2_DATA3, + MUX_CONFIG_FUNC | MUX_CONFIG_SION); + + pad_val = PAD_CTL_PUE_PUD | PAD_CTL_PKE_ENABLE | + PAD_CTL_HYS_SCHMITZ | PAD_CTL_DRV_MAX | + PAD_CTL_47K_PU | PAD_CTL_SRE_FAST; + + mxc_iomux_set_pad(MX35_PIN_SD2_CLK, pad_val); + mxc_iomux_set_pad(MX35_PIN_SD2_CMD, pad_val); + mxc_iomux_set_pad(MX35_PIN_SD2_DATA0, pad_val); + mxc_iomux_set_pad(MX35_PIN_SD2_DATA1, pad_val); + mxc_iomux_set_pad(MX35_PIN_SD2_DATA2, pad_val); + + pad_val = PAD_CTL_PUE_PUD | PAD_CTL_PKE_ENABLE | + PAD_CTL_HYS_SCHMITZ | PAD_CTL_DRV_MAX | + PAD_CTL_100K_PU | PAD_CTL_SRE_FAST; + + mxc_iomux_set_pad(MX35_PIN_SD2_DATA3, pad_val); + break; + default: + break; + } +} + +EXPORT_SYMBOL(gpio_sdhc_active); + +/*! + * Setup GPIO for SDHC1 to be inactive + * + * @param module SDHC module number + */ +void gpio_sdhc_inactive(int module) +{ + switch (module) { + case 0: + mxc_free_iomux(MX35_PIN_SD1_CLK, + MUX_CONFIG_FUNC | MUX_CONFIG_SION); + mxc_free_iomux(MX35_PIN_SD1_CMD, + MUX_CONFIG_FUNC | MUX_CONFIG_SION); + mxc_free_iomux(MX35_PIN_SD1_DATA0, + MUX_CONFIG_FUNC | MUX_CONFIG_SION); + mxc_free_iomux(MX35_PIN_SD1_DATA1, + MUX_CONFIG_FUNC | MUX_CONFIG_SION); + mxc_free_iomux(MX35_PIN_SD1_DATA2, + MUX_CONFIG_FUNC | MUX_CONFIG_SION); + mxc_free_iomux(MX35_PIN_SD1_DATA3, + MUX_CONFIG_FUNC | MUX_CONFIG_SION); + mxc_free_iomux(MX35_PIN_SD2_CMD, + MUX_CONFIG_ALT2 | MUX_CONFIG_SION); + mxc_free_iomux(MX35_PIN_SD2_CLK, + MUX_CONFIG_ALT2 | MUX_CONFIG_SION); + mxc_free_iomux(MX35_PIN_SD2_DATA0, + MUX_CONFIG_ALT2 | MUX_CONFIG_SION); + mxc_free_iomux(MX35_PIN_SD2_DATA1, + MUX_CONFIG_ALT2 | MUX_CONFIG_SION); + + mxc_iomux_set_pad(MX35_PIN_SD1_CLK, + (PAD_CTL_DRV_NORMAL | PAD_CTL_SRE_SLOW)); + mxc_iomux_set_pad(MX35_PIN_SD1_CMD, + (PAD_CTL_DRV_NORMAL | PAD_CTL_SRE_SLOW)); + mxc_iomux_set_pad(MX35_PIN_SD1_DATA0, + (PAD_CTL_DRV_NORMAL | PAD_CTL_SRE_SLOW)); + mxc_iomux_set_pad(MX35_PIN_SD1_DATA1, + (PAD_CTL_DRV_NORMAL | PAD_CTL_SRE_SLOW)); + mxc_iomux_set_pad(MX35_PIN_SD1_DATA2, + (PAD_CTL_DRV_NORMAL | PAD_CTL_SRE_SLOW)); + mxc_iomux_set_pad(MX35_PIN_SD1_DATA3, + (PAD_CTL_DRV_NORMAL | PAD_CTL_SRE_SLOW)); + mxc_iomux_set_pad(MX35_PIN_SD2_CMD, + (PAD_CTL_DRV_NORMAL | PAD_CTL_SRE_SLOW)); + mxc_iomux_set_pad(MX35_PIN_SD2_CLK, + (PAD_CTL_DRV_NORMAL | PAD_CTL_SRE_SLOW)); + mxc_iomux_set_pad(MX35_PIN_SD2_DATA0, + (PAD_CTL_DRV_NORMAL | PAD_CTL_SRE_SLOW)); + mxc_iomux_set_pad(MX35_PIN_SD2_DATA1, + (PAD_CTL_DRV_NORMAL | PAD_CTL_SRE_SLOW)); + break; + case 1: + mxc_free_iomux(MX35_PIN_SD2_CLK, + MUX_CONFIG_FUNC | MUX_CONFIG_SION); + mxc_free_iomux(MX35_PIN_SD2_CMD, + MUX_CONFIG_FUNC | MUX_CONFIG_SION); + mxc_free_iomux(MX35_PIN_SD2_DATA0, + MUX_CONFIG_FUNC | MUX_CONFIG_SION); + mxc_free_iomux(MX35_PIN_SD2_DATA1, + MUX_CONFIG_FUNC | MUX_CONFIG_SION); + mxc_free_iomux(MX35_PIN_SD2_DATA2, + MUX_CONFIG_FUNC | MUX_CONFIG_SION); + mxc_free_iomux(MX35_PIN_SD2_DATA3, + MUX_CONFIG_FUNC | MUX_CONFIG_SION); + + mxc_iomux_set_pad(MX35_PIN_SD2_CLK, + (PAD_CTL_DRV_NORMAL | PAD_CTL_SRE_SLOW)); + mxc_iomux_set_pad(MX35_PIN_SD2_CMD, + (PAD_CTL_DRV_NORMAL | PAD_CTL_SRE_SLOW)); + mxc_iomux_set_pad(MX35_PIN_SD2_DATA0, + (PAD_CTL_DRV_NORMAL | PAD_CTL_SRE_SLOW)); + mxc_iomux_set_pad(MX35_PIN_SD2_DATA1, + (PAD_CTL_DRV_NORMAL | PAD_CTL_SRE_SLOW)); + mxc_iomux_set_pad(MX35_PIN_SD2_DATA2, + (PAD_CTL_DRV_NORMAL | PAD_CTL_SRE_SLOW)); + mxc_iomux_set_pad(MX35_PIN_SD2_DATA3, + (PAD_CTL_DRV_NORMAL | PAD_CTL_SRE_SLOW)); + break; + default: + break; + } +} + +EXPORT_SYMBOL(gpio_sdhc_inactive); + +/* + * Probe for the card. If present the GPIO data would be set. + */ +unsigned int sdhc_get_card_det_status(struct device *dev) +{ + unsigned int ret; + + if (to_platform_device(dev)->id == 0) { + if (0 != pmic_gpio_get_designation_bit_val(2, &ret)) + printk(KERN_ERR "Get cd status error."); + return ret; + } else { /* config the det pin for SDHC2 */ + return 0; + } +} + +EXPORT_SYMBOL(sdhc_get_card_det_status); + +/*! + * Get pin value to detect write protection + */ +int sdhc_write_protect(struct device *dev) +{ + unsigned int rc = 0; + + if (0 != pmic_gpio_get_designation_bit_val(3, &rc)) + printk(KERN_ERR "Get wp status error."); + return rc; +} + +EXPORT_SYMBOL(sdhc_write_protect); + +/* + * USB Host2 + */ +int gpio_usbh2_active(void) +{ + if (board_is_rev(BOARD_REV_2)) { + /* MUX3_CTR to be low for USB Host2 DP&DM */ + pmic_gpio_set_bit_val(MCU_GPIO_REG_GPIO_CONTROL_2, 6, 0); + /* CAN_PWDN to be high for USB Host2 Power&OC */ + pmic_gpio_set_bit_val(MCU_GPIO_REG_GPIO_CONTROL_2, 1, 1); + } + + mxc_request_iomux(MX35_PIN_I2C2_CLK, MUX_CONFIG_ALT2); + mxc_iomux_set_pad(MX35_PIN_I2C2_CLK, 0x0040); + + mxc_request_iomux(MX35_PIN_I2C2_DAT, MUX_CONFIG_ALT2); + mxc_iomux_set_input(MUX_IN_USB_UH2_USB_OC, INPUT_CTL_PATH0); + mxc_iomux_set_pad(MX35_PIN_I2C2_DAT, 0x01c0); + + return 0; +} + +EXPORT_SYMBOL(gpio_usbh2_active); + +void gpio_usbh2_inactive(void) +{ + gpio_request(IOMUX_TO_GPIO(MX35_PIN_I2C2_DAT), NULL); + mxc_free_iomux(MX35_PIN_I2C2_DAT, MUX_CONFIG_GPIO); + gpio_request(IOMUX_TO_GPIO(MX35_PIN_I2C2_CLK), NULL); + mxc_free_iomux(MX35_PIN_I2C2_CLK, MUX_CONFIG_GPIO); +} + +EXPORT_SYMBOL(gpio_usbh2_inactive); + +/* + * USB OTG UTMI + */ +int gpio_usbotg_utmi_active(void) +{ + mxc_request_iomux(MX35_PIN_USBOTG_PWR, MUX_CONFIG_FUNC); + mxc_iomux_set_pad(MX35_PIN_USBOTG_PWR, 0x0040); + mxc_request_iomux(MX35_PIN_USBOTG_OC, MUX_CONFIG_FUNC); + mxc_iomux_set_pad(MX35_PIN_USBOTG_OC, 0x01c0); + + return 0; +} + +EXPORT_SYMBOL(gpio_usbotg_utmi_active); + +void gpio_usbotg_utmi_inactive(void) +{ + gpio_request(IOMUX_TO_GPIO(MX35_PIN_USBOTG_PWR), NULL); + mxc_free_iomux(MX35_PIN_USBOTG_PWR, MUX_CONFIG_GPIO); + gpio_request(IOMUX_TO_GPIO(MX35_PIN_USBOTG_OC), NULL); + mxc_free_iomux(MX35_PIN_USBOTG_OC, MUX_CONFIG_GPIO); +} + +EXPORT_SYMBOL(gpio_usbotg_utmi_inactive); + +void gpio_sensor_active(void) +{ + /*CSI D6 */ + mxc_request_iomux(MX35_PIN_TX1, MUX_CONFIG_ALT6); + /*CSI D7 */ + mxc_request_iomux(MX35_PIN_TX0, MUX_CONFIG_ALT6); + mxc_request_iomux(MX35_PIN_CSI_D8, MUX_CONFIG_FUNC); + mxc_request_iomux(MX35_PIN_CSI_D9, MUX_CONFIG_FUNC); + mxc_request_iomux(MX35_PIN_CSI_D10, MUX_CONFIG_FUNC); + mxc_request_iomux(MX35_PIN_CSI_D11, MUX_CONFIG_FUNC); + mxc_request_iomux(MX35_PIN_CSI_D12, MUX_CONFIG_FUNC); + mxc_request_iomux(MX35_PIN_CSI_D13, MUX_CONFIG_FUNC); + mxc_request_iomux(MX35_PIN_CSI_D14, MUX_CONFIG_FUNC); + mxc_request_iomux(MX35_PIN_CSI_D15, MUX_CONFIG_FUNC); + mxc_request_iomux(MX35_PIN_CSI_HSYNC, MUX_CONFIG_FUNC); + mxc_request_iomux(MX35_PIN_CSI_MCLK, MUX_CONFIG_FUNC); + mxc_request_iomux(MX35_PIN_CSI_PIXCLK, MUX_CONFIG_FUNC); + mxc_request_iomux(MX35_PIN_CSI_VSYNC, MUX_CONFIG_FUNC); +} + +EXPORT_SYMBOL(gpio_sensor_active); + +void gpio_sensor_inactive(void) +{ + mxc_request_iomux(MX35_PIN_TX1, MUX_CONFIG_FUNC); + mxc_request_iomux(MX35_PIN_TX0, MUX_CONFIG_FUNC); +} + +EXPORT_SYMBOL(gpio_sensor_inactive); + +/*! + * Setup GPIO for spdif tx/rx to be active + */ +void gpio_spdif_active(void) +{ + /* SPDIF OUT */ + mxc_request_iomux(MX35_PIN_STXD5, MUX_CONFIG_ALT1); + mxc_iomux_set_pad(MX35_PIN_STXD5, PAD_CTL_PKE_NONE | PAD_CTL_PUE_PUD); + /* SPDIF IN */ + mxc_request_iomux(MX35_PIN_SRXD5, MUX_CONFIG_ALT1); + mxc_iomux_set_pad(MX35_PIN_SRXD5, PAD_CTL_PKE_ENABLE + | PAD_CTL_100K_PU | PAD_CTL_HYS_SCHMITZ); + /* SPDIF ext clock */ + mxc_request_iomux(MX35_PIN_SCK5, MUX_CONFIG_ALT1); + if (board_is_rev(BOARD_REV_2)) + pmic_gpio_set_bit_val(MCU_GPIO_REG_GPIO_CONTROL_2, 5, 1); + else + pmic_gpio_set_bit_val(MCU_GPIO_REG_RESET_2, 0, 1); +} + +EXPORT_SYMBOL(gpio_spdif_active); + +/*! + * Setup GPIO for spdif tx/rx to be inactive + */ +void gpio_spdif_inactive(void) +{ + /* SPDIF OUT */ + mxc_free_iomux(MX35_PIN_STXD5, MUX_CONFIG_ALT1); + /* SPDIF IN */ + mxc_free_iomux(MX35_PIN_SRXD5, MUX_CONFIG_ALT1); + /* SPDIF ext clock */ + mxc_free_iomux(MX35_PIN_SCK5, MUX_CONFIG_ALT1); +} + +EXPORT_SYMBOL(gpio_spdif_inactive); + +/*! + * This function activates DAM ports 3 to enable + * audio I/O. + */ +void gpio_activate_audio_ports(void) +{ + unsigned int pad_val; + + mxc_request_iomux(MX35_PIN_STXD4, MUX_CONFIG_FUNC); + mxc_request_iomux(MX35_PIN_SRXD4, MUX_CONFIG_FUNC); + mxc_request_iomux(MX35_PIN_SCK4, MUX_CONFIG_FUNC); + mxc_request_iomux(MX35_PIN_STXFS4, MUX_CONFIG_FUNC); + + pad_val = PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_100K_PU | + PAD_CTL_PUE_PUD; + mxc_iomux_set_pad(MX35_PIN_STXD4, pad_val); + mxc_iomux_set_pad(MX35_PIN_SRXD4, pad_val); + mxc_iomux_set_pad(MX35_PIN_SCK4, pad_val); + mxc_iomux_set_pad(MX35_PIN_STXFS4, pad_val); +} + +EXPORT_SYMBOL(gpio_activate_audio_ports); + +/*! + * This function deactivates DAM ports 3 to disable + * audio I/O. + */ +void gpio_inactivate_audio_ports(void) +{ + mxc_free_iomux(MX35_PIN_STXD4, MUX_CONFIG_FUNC); + mxc_free_iomux(MX35_PIN_SRXD4, MUX_CONFIG_FUNC); + mxc_free_iomux(MX35_PIN_SCK4, MUX_CONFIG_FUNC); + mxc_free_iomux(MX35_PIN_STXFS4, MUX_CONFIG_FUNC); +} + +EXPORT_SYMBOL(gpio_inactivate_audio_ports); + +/*! + * This function activates DAM ports 5 to enable + * audio I/O. + */ +void gpio_activate_bt_audio_port(void) +{ + unsigned int pad_val; + + mxc_request_iomux(MX35_PIN_STXD5, MUX_CONFIG_FUNC); + mxc_request_iomux(MX35_PIN_SRXD5, MUX_CONFIG_FUNC); + mxc_request_iomux(MX35_PIN_SCK5, MUX_CONFIG_FUNC); + mxc_request_iomux(MX35_PIN_STXFS5, MUX_CONFIG_FUNC); + + pad_val = PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_100K_PU | + PAD_CTL_PUE_PUD; + mxc_iomux_set_pad(MX35_PIN_STXD5, pad_val); + mxc_iomux_set_pad(MX35_PIN_SRXD5, pad_val); + mxc_iomux_set_pad(MX35_PIN_SCK5, pad_val); + mxc_iomux_set_pad(MX35_PIN_STXFS5, pad_val); + if (board_is_rev(BOARD_REV_2)) + pmic_gpio_set_bit_val(MCU_GPIO_REG_GPIO_CONTROL_2, 5, 0); + else + pmic_gpio_set_bit_val(MCU_GPIO_REG_RESET_2, 0, 0); +} + +EXPORT_SYMBOL(gpio_activate_bt_audio_port); + +/*! + * Setup GPIO for bluetooth audio to be inactive + */ +void gpio_inactivate_bt_audio_port(void) +{ + mxc_free_iomux(MX35_PIN_STXD5, MUX_CONFIG_FUNC); + mxc_free_iomux(MX35_PIN_SRXD5, MUX_CONFIG_FUNC); + mxc_free_iomux(MX35_PIN_SCK5, MUX_CONFIG_FUNC); + mxc_free_iomux(MX35_PIN_STXFS5, MUX_CONFIG_FUNC); +} + +EXPORT_SYMBOL(gpio_inactivate_bt_audio_port); + +/*! + * Setup GPIO for ATA interface + * + */ +void gpio_ata_active(void) +{ + unsigned int ata_ctl_pad_cfg, ata_dat_pad_cfg; + + /* HDD_ENBALE */ + pmic_gpio_set_bit_val(MCU_GPIO_REG_GPIO_CONTROL_1, 3, 0); + /* Power On the HDD */ + pmic_gpio_set_bit_val(MCU_GPIO_REG_GPIO_CONTROL_1, 4, 1); + msleep(300); + + /*IOMUX Settings */ + /*PATA_DIOR */ + mxc_request_iomux(MX35_PIN_ATA_DIOR, MUX_CONFIG_FUNC); + /*PATA_DIOW */ + mxc_request_iomux(MX35_PIN_ATA_DIOW, MUX_CONFIG_FUNC); + /*PATA_DMARQ_B */ + mxc_request_iomux(MX35_PIN_ATA_DMARQ, MUX_CONFIG_FUNC); + /*PATA_DMACK */ + mxc_request_iomux(MX35_PIN_ATA_DMACK, MUX_CONFIG_FUNC); + /*PATA_RESET_B */ + mxc_request_iomux(MX35_PIN_ATA_RESET_B, MUX_CONFIG_FUNC); + /*PATA_IORDY */ + mxc_request_iomux(MX35_PIN_ATA_IORDY, MUX_CONFIG_FUNC); + /*PATA_INTRQ_B */ + mxc_request_iomux(MX35_PIN_ATA_INTRQ, MUX_CONFIG_FUNC); + /*PATA_CS_0 */ + mxc_request_iomux(MX35_PIN_ATA_CS0, MUX_CONFIG_FUNC); + /*PATA_CS_1 */ + mxc_request_iomux(MX35_PIN_ATA_CS1, MUX_CONFIG_FUNC); + /*PATA_DA0 */ + mxc_request_iomux(MX35_PIN_ATA_DA0, MUX_CONFIG_FUNC); + /*PATA_DA1 */ + mxc_request_iomux(MX35_PIN_ATA_DA1, MUX_CONFIG_FUNC); + /*PATA_DA2 */ + mxc_request_iomux(MX35_PIN_ATA_DA2, MUX_CONFIG_FUNC); + /* BUFFER_ENABLE - HDD_ENABLE_B */ + mxc_request_iomux(MX35_PIN_ATA_BUFF_EN, MUX_CONFIG_FUNC); + + /*PATA_D0 */ + mxc_request_iomux(MX35_PIN_ATA_DATA0, MUX_CONFIG_FUNC); + /*PATA_D1 */ + mxc_request_iomux(MX35_PIN_ATA_DATA1, MUX_CONFIG_FUNC); + /*PATA_D2 */ + mxc_request_iomux(MX35_PIN_ATA_DATA2, MUX_CONFIG_FUNC); + /*PATA_D3 */ + mxc_request_iomux(MX35_PIN_ATA_DATA3, MUX_CONFIG_FUNC); + /*PATA_D4 */ + mxc_request_iomux(MX35_PIN_ATA_DATA4, MUX_CONFIG_FUNC); + /*PATA_D5 */ + mxc_request_iomux(MX35_PIN_ATA_DATA5, MUX_CONFIG_FUNC); + /*PATA_D6 */ + mxc_request_iomux(MX35_PIN_ATA_DATA6, MUX_CONFIG_FUNC); + /*PATA_D7 */ + mxc_request_iomux(MX35_PIN_ATA_DATA7, MUX_CONFIG_FUNC); + /*PATA_D8 */ + mxc_request_iomux(MX35_PIN_ATA_DATA8, MUX_CONFIG_FUNC); + /*PATA_D9 */ + mxc_request_iomux(MX35_PIN_ATA_DATA9, MUX_CONFIG_FUNC); + /*PATA_D10 */ + mxc_request_iomux(MX35_PIN_ATA_DATA10, MUX_CONFIG_FUNC); + /*PATA_D11 */ + mxc_request_iomux(MX35_PIN_ATA_DATA11, MUX_CONFIG_FUNC); + /*PATA_D12 */ + mxc_request_iomux(MX35_PIN_ATA_DATA12, MUX_CONFIG_FUNC); + /*PATA_D13 */ + mxc_request_iomux(MX35_PIN_ATA_DATA13, MUX_CONFIG_FUNC); + /*PATA_D14 */ + mxc_request_iomux(MX35_PIN_ATA_DATA14, MUX_CONFIG_FUNC); + /*PATA_D15 */ + mxc_request_iomux(MX35_PIN_ATA_DATA15, MUX_CONFIG_FUNC); + + /* IOMUX Pad Settings */ + ata_ctl_pad_cfg = PAD_CTL_SRE_SLOW | PAD_CTL_DRV_NORMAL | + PAD_CTL_ODE_CMOS | PAD_CTL_PKE_ENABLE | + PAD_CTL_PUE_PUD | PAD_CTL_100K_PD | + PAD_CTL_HYS_CMOS | PAD_CTL_DRV_3_3V; + ata_dat_pad_cfg = PAD_CTL_SRE_FAST | PAD_CTL_DRV_MAX | + PAD_CTL_ODE_CMOS | PAD_CTL_PKE_ENABLE | + PAD_CTL_PUE_PUD | PAD_CTL_100K_PD | + PAD_CTL_HYS_SCHMITZ | PAD_CTL_DRV_3_3V; + + mxc_iomux_set_pad(MX35_PIN_ATA_DMARQ, ata_dat_pad_cfg); + mxc_iomux_set_pad(MX35_PIN_ATA_DIOR, ata_ctl_pad_cfg); + mxc_iomux_set_pad(MX35_PIN_ATA_DIOW, ata_ctl_pad_cfg); + mxc_iomux_set_pad(MX35_PIN_ATA_DMACK, ata_ctl_pad_cfg); + mxc_iomux_set_pad(MX35_PIN_ATA_RESET_B, PAD_CTL_SRE_SLOW | + PAD_CTL_DRV_NORMAL | PAD_CTL_ODE_CMOS | + PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PUD | + PAD_CTL_100K_PU | PAD_CTL_HYS_CMOS | + PAD_CTL_DRV_3_3V); + mxc_iomux_set_pad(MX35_PIN_ATA_IORDY, ata_dat_pad_cfg); + mxc_iomux_set_pad(MX35_PIN_ATA_INTRQ, ata_dat_pad_cfg); + mxc_iomux_set_pad(MX35_PIN_ATA_CS0, ata_ctl_pad_cfg); + mxc_iomux_set_pad(MX35_PIN_ATA_CS1, ata_ctl_pad_cfg); + + mxc_iomux_set_pad(MX35_PIN_ATA_DATA0, ata_dat_pad_cfg); + mxc_iomux_set_pad(MX35_PIN_ATA_DATA1, ata_dat_pad_cfg); + mxc_iomux_set_pad(MX35_PIN_ATA_DATA2, ata_dat_pad_cfg); + mxc_iomux_set_pad(MX35_PIN_ATA_DATA3, ata_dat_pad_cfg); + mxc_iomux_set_pad(MX35_PIN_ATA_DATA4, ata_dat_pad_cfg); + mxc_iomux_set_pad(MX35_PIN_ATA_DATA5, ata_dat_pad_cfg); + mxc_iomux_set_pad(MX35_PIN_ATA_DATA6, ata_dat_pad_cfg); + mxc_iomux_set_pad(MX35_PIN_ATA_DATA7, ata_dat_pad_cfg); + mxc_iomux_set_pad(MX35_PIN_ATA_DATA8, ata_dat_pad_cfg); + mxc_iomux_set_pad(MX35_PIN_ATA_DATA9, ata_dat_pad_cfg); + mxc_iomux_set_pad(MX35_PIN_ATA_DATA10, ata_dat_pad_cfg); + mxc_iomux_set_pad(MX35_PIN_ATA_DATA11, ata_dat_pad_cfg); + mxc_iomux_set_pad(MX35_PIN_ATA_DATA12, ata_dat_pad_cfg); + mxc_iomux_set_pad(MX35_PIN_ATA_DATA13, ata_dat_pad_cfg); + mxc_iomux_set_pad(MX35_PIN_ATA_DATA14, ata_dat_pad_cfg); + mxc_iomux_set_pad(MX35_PIN_ATA_DATA15, ata_dat_pad_cfg); + + mxc_iomux_set_pad(MX35_PIN_ATA_DA0, ata_ctl_pad_cfg); + mxc_iomux_set_pad(MX35_PIN_ATA_DA1, ata_ctl_pad_cfg); + mxc_iomux_set_pad(MX35_PIN_ATA_DA2, ata_ctl_pad_cfg); + mxc_iomux_set_pad(MX35_PIN_ATA_BUFF_EN, ata_ctl_pad_cfg); +} + +EXPORT_SYMBOL(gpio_ata_active); + +/*! + * Restore ATA interface pins to reset values + * + */ +void gpio_ata_inactive(void) +{ + /*Turn off the IOMUX for ATA group B signals */ + mxc_free_iomux(MX35_PIN_ATA_DATA0, MUX_CONFIG_FUNC); + mxc_free_iomux(MX35_PIN_ATA_DATA1, MUX_CONFIG_FUNC); + mxc_free_iomux(MX35_PIN_ATA_DATA2, MUX_CONFIG_FUNC); + mxc_free_iomux(MX35_PIN_ATA_DATA3, MUX_CONFIG_FUNC); + mxc_free_iomux(MX35_PIN_ATA_DATA4, MUX_CONFIG_FUNC); + mxc_free_iomux(MX35_PIN_ATA_DATA5, MUX_CONFIG_FUNC); + mxc_free_iomux(MX35_PIN_ATA_DATA6, MUX_CONFIG_FUNC); + mxc_free_iomux(MX35_PIN_ATA_DATA7, MUX_CONFIG_FUNC); + mxc_free_iomux(MX35_PIN_ATA_DATA8, MUX_CONFIG_FUNC); + mxc_free_iomux(MX35_PIN_ATA_DATA9, MUX_CONFIG_FUNC); + mxc_free_iomux(MX35_PIN_ATA_DATA10, MUX_CONFIG_FUNC); + mxc_free_iomux(MX35_PIN_ATA_DATA11, MUX_CONFIG_FUNC); + mxc_free_iomux(MX35_PIN_ATA_DATA12, MUX_CONFIG_FUNC); + mxc_free_iomux(MX35_PIN_ATA_DATA13, MUX_CONFIG_FUNC); + mxc_free_iomux(MX35_PIN_ATA_DATA14, MUX_CONFIG_FUNC); + mxc_free_iomux(MX35_PIN_ATA_DATA15, MUX_CONFIG_FUNC); + + /* Config the multiplex pin of ATA interface DIR, DA0-2, INTRQ, DMARQ */ + mxc_free_iomux(MX35_PIN_ATA_DMARQ, MUX_CONFIG_FUNC); + mxc_free_iomux(MX35_PIN_ATA_DIOR, MUX_CONFIG_FUNC); + mxc_free_iomux(MX35_PIN_ATA_DIOW, MUX_CONFIG_FUNC); + mxc_free_iomux(MX35_PIN_ATA_DMACK, MUX_CONFIG_FUNC); + mxc_free_iomux(MX35_PIN_ATA_RESET_B, MUX_CONFIG_FUNC); + mxc_free_iomux(MX35_PIN_ATA_IORDY, MUX_CONFIG_FUNC); + mxc_free_iomux(MX35_PIN_ATA_INTRQ, MUX_CONFIG_FUNC); + mxc_free_iomux(MX35_PIN_ATA_CS0, MUX_CONFIG_FUNC); + mxc_free_iomux(MX35_PIN_ATA_CS1, MUX_CONFIG_FUNC); + mxc_free_iomux(MX35_PIN_ATA_DA0, MUX_CONFIG_FUNC); + mxc_free_iomux(MX35_PIN_ATA_DA1, MUX_CONFIG_FUNC); + mxc_free_iomux(MX35_PIN_ATA_DA2, MUX_CONFIG_FUNC); + mxc_free_iomux(MX35_PIN_ATA_BUFF_EN, MUX_CONFIG_FUNC); + + /* Power Off the HDD */ + pmic_gpio_set_bit_val(MCU_GPIO_REG_GPIO_CONTROL_1, 4, 0); + /* HDD_ENBALE */ + pmic_gpio_set_bit_val(MCU_GPIO_REG_GPIO_CONTROL_1, 3, 1); +} + +EXPORT_SYMBOL(gpio_ata_inactive); + +/*! + * This function activates ESAI ports to enable + * surround sound I/O + */ +void gpio_activate_esai_ports(void) +{ + unsigned int pad_val; + /* ESAI TX - WM8580 */ + mxc_request_iomux(MX35_PIN_HCKT, MUX_CONFIG_FUNC); + mxc_request_iomux(MX35_PIN_SCKT, MUX_CONFIG_FUNC); + mxc_request_iomux(MX35_PIN_FST, MUX_CONFIG_FUNC); + mxc_request_iomux(MX35_PIN_TX0, MUX_CONFIG_FUNC); + mxc_request_iomux(MX35_PIN_TX1, MUX_CONFIG_FUNC); + mxc_request_iomux(MX35_PIN_TX2_RX3, MUX_CONFIG_FUNC); + + /* ESAI RX - AK5702 */ + /*mxc_request_iomux(MX35_PIN_HCKR, MUX_CONFIG_FUNC); + mxc_request_iomux(MX35_PIN_SCKR, MUX_CONFIG_FUNC); + mxc_request_iomux(MX35_PIN_FSR, MUX_CONFIG_FUNC); + mxc_request_iomux(MX35_PIN_TX3_RX2, MUX_CONFIG_FUNC); + mxc_request_iomux(MX35_PIN_TX4_RX1, MUX_CONFIG_FUNC);*/ + + pad_val = PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_100K_PU | + PAD_CTL_PUE_PUD; + /* ESAI TX - WM8580 */ + mxc_iomux_set_pad(MX35_PIN_SCKT, pad_val); + mxc_iomux_set_pad(MX35_PIN_FST, pad_val); + mxc_iomux_set_pad(MX35_PIN_TX0, pad_val); + mxc_iomux_set_pad(MX35_PIN_TX1, pad_val); + mxc_iomux_set_pad(MX35_PIN_TX2_RX3, pad_val); + + /* ESAI RX - AK5702 */ + /*mxc_iomux_set_pad(MX35_PIN_SCKR, pad_val); + mxc_iomux_set_pad(MX35_PIN_FSR, pad_val); + mxc_iomux_set_pad(MX35_PIN_TX3_RX2, pad_val); + mxc_iomux_set_pad(MX35_PIN_TX4_RX1, pad_val);*/ + + pad_val = + PAD_CTL_DRV_HIGH | PAD_CTL_PKE_ENABLE | PAD_CTL_100K_PU | + PAD_CTL_PUE_PUD; + + /* ESAI TX - WM8580 */ + mxc_iomux_set_pad(MX35_PIN_HCKT, pad_val); + /* ESAI RX - AK5702 */ + /*mxc_iomux_set_pad(MX35_PIN_HCKR, pad_val);*/ +} + +EXPORT_SYMBOL(gpio_activate_esai_ports); + +/*! + * This function deactivates ESAI ports to disable + * surround sound I/O + */ +void gpio_deactivate_esai_ports(void) +{ + + mxc_free_iomux(MX35_PIN_HCKT, MUX_CONFIG_FUNC); + mxc_free_iomux(MX35_PIN_SCKT, MUX_CONFIG_FUNC); + mxc_free_iomux(MX35_PIN_FST, MUX_CONFIG_FUNC); + mxc_free_iomux(MX35_PIN_TX0, MUX_CONFIG_FUNC); + mxc_free_iomux(MX35_PIN_TX1, MUX_CONFIG_FUNC); + mxc_free_iomux(MX35_PIN_TX2_RX3, MUX_CONFIG_FUNC); + /*mxc_free_iomux(MX35_PIN_HCKR, MUX_CONFIG_GPIO); + mxc_free_iomux(MX35_PIN_SCKR, MUX_CONFIG_GPIO); + mxc_free_iomux(MX35_PIN_FSR, MUX_CONFIG_GPIO); + mxc_free_iomux(MX35_PIN_TX3_RX2, MUX_CONFIG_GPIO); + mxc_free_iomux(MX35_PIN_TX4_RX1, MUX_CONFIG_GPIO);*/ +} + +EXPORT_SYMBOL(gpio_deactivate_esai_ports); + +/*! + * This function enable and reset GPS GPIO + */ +void gpio_gps_active(void) +{ + /* Pull GPIO1_5 to be low for routing signal to UART3/GPS */ + if (board_is_rev(BOARD_REV_2)) { + mxc_request_iomux(MX35_PIN_COMPARE, MUX_CONFIG_GPIO); + mxc_iomux_set_pad(MX35_PIN_COMPARE, PAD_CTL_DRV_NORMAL | + PAD_CTL_PKE_ENABLE | PAD_CTL_100K_PU | + PAD_CTL_DRV_3_3V | PAD_CTL_PUE_PUD | + PAD_CTL_SRE_SLOW); + gpio_direction_output(IOMUX_TO_GPIO(MX35_PIN_COMPARE), 0); + gpio_set_value(IOMUX_TO_GPIO(MX35_PIN_COMPARE), 0); + } + + /* PWR_EN_GPS is set to be 0, will be toggled on in app by ioctl */ + pmic_gpio_set_bit_val(MCU_GPIO_REG_GPIO_CONTROL_2, 0, 0); + + /* GPS 32KHz clock enbale */ + pmic_gpio_set_bit_val(MCU_GPIO_REG_GPIO_CONTROL_1, 7, 1); + + /* GPS reset */ + pmic_gpio_set_bit_val(MCU_GPIO_REG_RESET_1, 5, 0); + msleep(5); + pmic_gpio_set_bit_val(MCU_GPIO_REG_RESET_1, 5, 1); + msleep(5); +} + +EXPORT_SYMBOL(gpio_gps_active); + +/*! + * This function get GPS GPIO status. + */ +int gpio_gps_access(int para) +{ + unsigned int gps_val; + + if (para & 0x4) { /* Read GPIO */ + if (para & 0x1) /* Read PWR_EN */ + pmic_gpio_get_bit_val(MCU_GPIO_REG_GPIO_CONTROL_2, 0, + &gps_val); + else /* Read nReset */ + pmic_gpio_get_bit_val(MCU_GPIO_REG_RESET_1, 5, + &gps_val); + return gps_val; + } else { /* Write GPIO */ + gps_val = (para & 0x2) ? 1 : 0; + if (para & 0x1) + pmic_gpio_set_bit_val(MCU_GPIO_REG_GPIO_CONTROL_2, 0, + gps_val); + else + pmic_gpio_set_bit_val(MCU_GPIO_REG_RESET_1, 5, gps_val); + } + return 0; +} + +EXPORT_SYMBOL(gpio_gps_access); + +/*! + * This function disable GPS GPIO + */ +void gpio_gps_inactive(void) +{ + /* GPS disable */ + pmic_gpio_set_bit_val(MCU_GPIO_REG_GPIO_CONTROL_2, 0, 0); + /* Free GPIO1_5 */ + if (board_is_rev(BOARD_REV_2)) + mxc_free_iomux(MX35_PIN_COMPARE, MUX_CONFIG_GPIO); +} + +EXPORT_SYMBOL(gpio_gps_inactive); + +/*! + * The MLB gpio configuration routine + */ +void gpio_mlb_active(void) +{ + mxc_request_iomux(MX35_PIN_MLB_CLK, MUX_CONFIG_FUNC); + mxc_request_iomux(MX35_PIN_MLB_SIG, MUX_CONFIG_FUNC); + mxc_request_iomux(MX35_PIN_MLB_DAT, MUX_CONFIG_FUNC); +} + +EXPORT_SYMBOL(gpio_mlb_active); + +void gpio_mlb_inactive(void) +{ + mxc_free_iomux(MX35_PIN_MLB_CLK, MUX_CONFIG_FUNC); + mxc_free_iomux(MX35_PIN_MLB_SIG, MUX_CONFIG_FUNC); + mxc_free_iomux(MX35_PIN_MLB_DAT, MUX_CONFIG_FUNC); +} + +EXPORT_SYMBOL(gpio_mlb_inactive); + +void gpio_can_active(int id) +{ + int pad; + + switch (id) { + case 0: + pad = PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | \ + PAD_CTL_PUE_PUD | PAD_CTL_100K_PU | PAD_CTL_DRV_HIGH; + mxc_request_iomux(MX35_PIN_I2C2_CLK, MUX_CONFIG_ALT1); + mxc_request_iomux(MX35_PIN_I2C2_DAT, MUX_CONFIG_ALT1); + mxc_iomux_set_pad(MX35_PIN_I2C2_CLK, pad); + mxc_iomux_set_pad(MX35_PIN_I2C2_DAT, pad); + mxc_iomux_set_input(MUX_IN_CAN1_CANRX, INPUT_CTL_PATH0); + break; + case 1: + pad = PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PUD | PAD_CTL_100K_PU; + mxc_request_iomux(MX35_PIN_FEC_MDC, MUX_CONFIG_ALT1); + mxc_request_iomux(MX35_PIN_FEC_MDIO, MUX_CONFIG_ALT1); + mxc_iomux_set_pad(MX35_PIN_FEC_MDC, pad); + mxc_iomux_set_pad(MX35_PIN_FEC_MDIO, pad); + mxc_iomux_set_input(MUX_IN_CAN2_CANRX, INPUT_CTL_PATH2); + break; + default: + printk(KERN_ERR "NO such device\n"); + } +} + +void gpio_can_inactive(int id) +{ + switch (id) { + case 0: + mxc_free_iomux(MX35_PIN_I2C2_CLK, MUX_CONFIG_ALT1); + mxc_free_iomux(MX35_PIN_I2C2_DAT, MUX_CONFIG_ALT1); + mxc_iomux_set_input(MUX_IN_CAN1_CANRX, INPUT_CTL_PATH0); + break; + case 1: + mxc_free_iomux(MX35_PIN_FEC_MDC, MUX_CONFIG_ALT1); + mxc_free_iomux(MX35_PIN_FEC_MDIO, MUX_CONFIG_ALT1); + mxc_iomux_set_input(MUX_IN_CAN2_CANRX, INPUT_CTL_PATH0); + break; + default: + printk(KERN_ERR "NO such device\n"); + } +} + +void gpio_pmic_active(void) +{ + unsigned int pad_val = PAD_CTL_SRE_SLOW | PAD_CTL_DRV_NORMAL + | PAD_CTL_HYS_CMOS | PAD_CTL_100K_PU | PAD_CTL_DRV_3_3V; + mxc_request_iomux(MX35_PIN_GPIO2_0, MUX_CONFIG_FUNC); + mxc_iomux_set_pad(MX35_PIN_GPIO2_0, pad_val); + gpio_request(IOMUX_TO_GPIO(MX35_PIN_GPIO2_0), NULL); + gpio_direction_input(IOMUX_TO_GPIO(MX35_PIN_GPIO2_0)); +} + +EXPORT_SYMBOL(gpio_pmic_active); diff --git a/arch/arm/mach-mx35/mx35_3stack_irq.c b/arch/arm/mach-mx35/mx35_3stack_irq.c new file mode 100644 index 000000000000..ad772040c19e --- /dev/null +++ b/arch/arm/mach-mx35/mx35_3stack_irq.c @@ -0,0 +1,372 @@ +/* + * 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/interrupt.h> +#include <linux/init.h> +#include <linux/platform_device.h> +#include <linux/clk.h> +#include <linux/mfd/mc9s08dz60/pmic.h> + +#include <mach/hardware.h> +#include <asm/irq.h> +#include <asm/setup.h> +#include <asm/bitops.h> +#include <asm/mach-types.h> +#include <asm/mach/arch.h> +#include <asm/mach/irq.h> + +#include <mach/gpio.h> + +#include "board-mx35_3stack.h" +#include "iomux.h" + +/*! + * @file mach-mx35/mx35_3stack_irq.c + * + * @brief This file contains the board specific initialization routines. + * + * @ingroup MSL_MX35 + */ +#ifdef CONFIG_MXC_PSEUDO_IRQS + +/* + * The interrupt status and mask variables. + */ +static unsigned long pseudo_irq_pending; +static unsigned long pseudo_irq_enable; +static unsigned long pseudo_irq_wakeup; +static unsigned long pseudo_suspend; +static atomic_t pseudo_irq_state = ATOMIC_INIT(0); + +/* + * The declaration of handler of two work queue. + * The one is the work queue to indentify the events from MCU. + * The another is the work queue to change the events mask. + */ +static void mcu_event_handler(struct work_struct *work); +static void mcu_state_handler(struct work_struct *work); +static void mcu_event_delay(unsigned long data); + +/*! + * The work structure for mcu events. + */ +static DECLARE_WORK(mcu_event_ws, mcu_event_handler); +static DECLARE_WORK(mcu_state_ws, mcu_state_handler); +static DEFINE_TIMER(mcu_delay_timer, mcu_event_delay, HZ, 0); + +static inline void mxc_pseudo_irq_ack(void) +{ + disable_irq(MXC_PSEUDO_PARENT); + atomic_set(&pseudo_irq_state, 0); +} + +static inline void mxc_pseudo_irq_trigger(void) +{ + if (!atomic_xchg(&pseudo_irq_state, 1)) + enable_irq(MXC_PSEUDO_PARENT); +} + +/* + * mask a pseudo interrupt by setting the bit in the mask variable. + * @param irq a pseudo virtual irq number + */ +static void pseudo_mask_irq(u32 irq) +{ + int index = irq - MXC_PSEUDO_IO_BASE; + clear_bit(index, &pseudo_irq_enable); +} + +/* + * disable a pseudo interrupt by triggerring a work queue + * @param irq a pseudo virtual irq number + */ +static void pseudo_disable_irq(u32 irq) +{ + struct irq_desc *desc = irq_desc + irq; + desc->chip->mask(irq); + desc->status |= IRQ_MASKED; + schedule_work(&mcu_state_ws); +} + +/* + * Acknowledge a pseudo interrupt by clearing the bit in the isr variable. + * @param irq a pseudo virtual irq number + */ +static void pseudo_ack_irq(u32 irq) +{ + int index = irq - MXC_PSEUDO_IO_BASE; + /* clear the interrupt status */ + clear_bit(index, &pseudo_irq_pending); +} + +/* + * unmask a pseudo interrupt by clearing the bit in the imr. + * @param irq a pseudo virtual irq number + */ +static void pseudo_unmask_irq(u32 irq) +{ + int index = irq - MXC_PSEUDO_IO_BASE; + + set_bit(index, &pseudo_irq_enable); + + if (test_bit(index, &pseudo_irq_pending)) + mxc_pseudo_irq_trigger(); +} + +/* + * Enable a pseudo interrupt by triggerring a work queue + * @param irq a pseudo virtual irq number + */ +static void pseudo_enable_irq(u32 irq) +{ + struct irq_desc *desc = irq_desc + irq; + desc->chip->unmask(irq); + desc->status &= ~IRQ_MASKED; + schedule_work(&mcu_state_ws); +} + +/* + * set pseudo irq as a wake-up source. + * @param irq a pseudo virtual irq number + * @param enable enable as wake-up if equal to non-ero + * @return This function return 0 on success + */ +static int pseudo_set_wake_irq(u32 irq, u32 enable) +{ + int index = irq - MXC_PSEUDO_IO_BASE; + + if (index >= MXC_MAX_PSEUDO_IO_LINES) + return -ENODEV; + + if (enable) { + if (!pseudo_irq_wakeup) + enable_irq_wake(IOMUX_TO_IRQ(MX35_PIN_GPIO1_0)); + pseudo_irq_wakeup |= (1 << index); + } else { + pseudo_irq_wakeup &= ~(1 << index); + if (!pseudo_irq_wakeup) + disable_irq_wake(IOMUX_TO_IRQ(MX35_PIN_GPIO1_0)); + } + return 0; +} + +static struct irq_chip pseudo_irq_chip = { + .ack = pseudo_ack_irq, + .mask = pseudo_mask_irq, + .disable = pseudo_disable_irq, + .unmask = pseudo_unmask_irq, + .enable = pseudo_enable_irq, + .set_wake = pseudo_set_wake_irq, +}; + +static void mxc_pseudo_irq_handler(u32 irq, struct irq_desc *desc) +{ + u32 pseudo_irq; + u32 index, mask; + + desc->chip->mask(irq); + mxc_pseudo_irq_ack(); + + mask = pseudo_irq_enable; + index = pseudo_irq_pending; + + if (unlikely(!(index & mask))) { + printk(KERN_ERR "\nPseudo IRQ: Spurious interrupt:0x%0x\n\n", + index); + pr_info("IEN=0x%x, PENDING=0x%x\n", mask, index); + return; + } + + index = index & mask; + pseudo_irq = MXC_PSEUDO_IO_BASE; + for (; index != 0; index >>= 1, pseudo_irq++) { + struct irq_desc *d; + if ((index & 1) == 0) + continue; + d = irq_desc + pseudo_irq; + if (unlikely(!(d->handle_irq))) { + printk(KERN_ERR "\nPseudo irq: %d unhandeled\n", + pseudo_irq); + BUG(); /* oops */ + } + d->handle_irq(pseudo_irq, d); + d->chip->ack(pseudo_irq); + } +} + +static void mcu_event_delay(unsigned long data) +{ + schedule_work(&mcu_event_ws); +} + +/*! + * This function is called when mcu interrupt occurs on the processor. + * It is the interrupt handler for the mcu. + * + * @param irq the irq number + * @param dev_id the pointer on the device + * + * @return The function returns IRQ_HANDLED when handled. + */ +static irqreturn_t mcu_irq_handler(int irq, void *dev_id) +{ + disable_irq(IOMUX_TO_IRQ(MX35_PIN_GPIO1_0)); + if (pseudo_suspend) + mod_timer(&mcu_delay_timer, jiffies + HZ); + else + schedule_work(&mcu_event_ws); + + return IRQ_HANDLED; +} + +/*! + * This function is the work handler of mcu interrupt. + * It reads the events status and trigger the pseudo irq. + */ +static void mcu_event_handler(struct work_struct *work) +{ + int i, err; + unsigned int flag1, flag2; + + /* read int flags and ack int */ + for (i = 0; i < 3; i++) { + err = mcu_pmic_read_reg(REG_MCU_INT_FLAG_1, &flag1, 0xFFFFFFFF); + err |= mcu_pmic_read_reg(REG_MCU_INT_FLAG_2, + &flag2, 0xFFFFFFFF); + err |= mcu_pmic_write_reg(REG_MCU_INT_FLAG_1, 0, 0xFFFFFFFF); + err |= mcu_pmic_write_reg(REG_MCU_INT_FLAG_2, 0, 0xFFFFFFFF); + if (err == 0) + break; + } + + if (i >= 3) { + printk(KERN_ERR "Reads MCU event fail\n"); + goto no_new_events; + } + + for (i = 0; flag1 && (i < MCU_INT_RTC); i++, flag1 >>= 1) + if (flag1 & 1) + set_bit(i, &pseudo_irq_pending); + + for (i = MCU_INT_RTC; flag2 && (i <= MCU_INT_KEYPAD); i++, flag2 >>= 1) + if (flag2 & 1) + set_bit(i, &pseudo_irq_pending); + no_new_events: + if (pseudo_irq_pending & pseudo_irq_enable) + mxc_pseudo_irq_trigger(); + enable_irq(IOMUX_TO_IRQ(MX35_PIN_GPIO1_0)); +} + +static void mcu_state_handler(struct work_struct *work) +{ + int err, i; + unsigned int event1, event2; + event1 = pseudo_irq_enable & ((1 << MCU_INT_RTC) - 1); + event2 = pseudo_irq_enable >> MCU_INT_RTC; + + for (i = 0; i < 3; i++) { + err = mcu_pmic_write_reg(REG_MCU_INT_ENABLE_1, event1, 0xFF); + err |= mcu_pmic_write_reg(REG_MCU_INT_ENABLE_2, event2, 0xFF); + if (err == 0) + break; + } + if (i >= 3) + printk(KERN_ERR "Change MCU event mask fail\n"); +} + +static int __init mxc_pseudo_init(void) +{ + int i; + + /* disable the interrupt and clear the status */ + pseudo_irq_pending = 0; + pseudo_irq_enable = 0; + + pr_info("3-Stack Pseudo interrupt rev=0.1v\n"); + + for (i = MXC_PSEUDO_IO_BASE; + i < (MXC_PSEUDO_IO_BASE + MXC_MAX_PSEUDO_IO_LINES); i++) { + set_irq_chip(i, &pseudo_irq_chip); + set_irq_handler(i, handle_simple_irq); + set_irq_flags(i, IRQF_VALID); + } + + set_irq_flags(MXC_PSEUDO_PARENT, IRQF_NOAUTOEN); + set_irq_handler(MXC_PSEUDO_PARENT, mxc_pseudo_irq_handler); + + /* Set and install PMIC IRQ handler */ + mxc_request_iomux(MX35_PIN_GPIO1_0, MUX_CONFIG_FUNC); + mxc_iomux_set_pad(MX35_PIN_GPIO1_0, PAD_CTL_PKE_NONE); + gpio_request(IOMUX_TO_GPIO(MX35_PIN_GPIO1_0), NULL); + gpio_direction_input(IOMUX_TO_GPIO(MX35_PIN_GPIO1_0)); + + set_irq_type(IOMUX_TO_IRQ(MX35_PIN_GPIO1_0), IRQF_TRIGGER_RISING); + if (request_irq(IOMUX_TO_IRQ(MX35_PIN_GPIO1_0), mcu_irq_handler, + 0, "MCU_IRQ", 0)) { + printk(KERN_ERR "mcu request irq failed\n"); + return -1; + } + return 0; +} + +fs_initcall_sync(mxc_pseudo_init); + +static int mxc_pseudo_irq_suspend(struct platform_device *dev, + pm_message_t mesg) +{ + int err, i; + unsigned int event1, event2; + + if (!pseudo_irq_wakeup) + return 0; + + event1 = pseudo_irq_wakeup & ((1 << MCU_INT_RTC) - 1); + event2 = pseudo_irq_wakeup >> MCU_INT_RTC; + + for (i = 0; i < 3; i++) { + err = mcu_pmic_write_reg(REG_MCU_INT_ENABLE_1, event1, 0xFF); + err |= mcu_pmic_write_reg(REG_MCU_INT_ENABLE_2, event2, 0xFF); + if (err == 0) + break; + } + pseudo_suspend = 1; + return err; +} + +static int mxc_pseudo_irq_resume(struct platform_device *dev) +{ + if (!pseudo_irq_wakeup) + return 0; + + schedule_work(&mcu_state_ws); + pseudo_suspend = 0; + return 0; +} + +static struct platform_driver mxc_pseudo_irq_driver = { + .driver = { + .name = "mxc_pseudo_irq", + }, + .suspend = mxc_pseudo_irq_suspend, + .resume = mxc_pseudo_irq_resume, +}; + +static int __init mxc_pseudo_sysinit(void) +{ + return platform_driver_register(&mxc_pseudo_irq_driver); +} + +late_initcall(mxc_pseudo_sysinit); +#endif /* CONFIG_MXC_PSEUDO_IRQS */ diff --git a/arch/arm/mach-mx35/mx35_3stack_pmic_mc13892.c b/arch/arm/mach-mx35/mx35_3stack_pmic_mc13892.c new file mode 100644 index 000000000000..44cccc564c2e --- /dev/null +++ b/arch/arm/mach-mx35/mx35_3stack_pmic_mc13892.c @@ -0,0 +1,347 @@ +/* + * mx35-3stack-pmic-mc13892.c -- i.MX35 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 <mach/irqs.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 + +/* 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 = 700000, + .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 = 1200000, + .mode = REGULATOR_MODE_NORMAL, + .enabled = 1, + }, + .state_standby = { + .uV = 1000000, + .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", + } +}; + +static struct regulator_init_data pwg1_init = { + .constraints = { + .name = "PWG1", + } +}; + +static struct regulator_init_data pwg2_init = { + .constraints = { + .name = "PWG2", + } +}; + +/*! + * the event handler for power on event + */ +static void power_on_evt_handler(void) +{ + pr_info("pwr on event1 is received \n"); +} + +/*! + * pmic board initialization code + */ +static int init_mc13892(void) +{ + unsigned int value; + pmic_event_callback_t power_key_event; + + if (!board_is_rev(BOARD_REV_2)) + return -1; + + /* subscribe PWRON1 event. */ + power_key_event.param = NULL; + power_key_event.func = (void *)power_on_evt_handler; + pmic_event_subscribe(EVENT_PWRONI, power_key_event); + + pmic_read_reg(REG_POWER_CTL2, &value, 0xffffff); + /* Bit 11 (STANDBYSECINV): Active Low */ + value |= 0x00800; + /* Bit 12 (WDIRESET): enable */ + value |= 0x01000; + pmic_write_reg(REG_POWER_CTL2, value, 0xffffff); + + /* Battery charger default settings */ + /* current limit = 1200mA, PLIM = 1000mw, disable auto charge */ + value = 0x210068; + pmic_write_reg(REG_CHARGE, value, 0x018078); + + return 0; +} + +static int mc13892_regulator_init(struct mc13892 *mc13892) +{ + 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); + mc13892_register_regulator(mc13892, MC13892_PWGT1, &pwg1_init); + mc13892_register_regulator(mc13892, MC13892_PWGT2, &pwg2_init); + + init_mc13892(); + 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 = IOMUX_TO_IRQ(MX35_PIN_GPIO2_0), + .platform_data = &mc13892_plat, +}; + +int __init mx35_3stack_init_mc13892(void) +{ + return i2c_register_board_info(0, &mc13892_i2c_device, 1); +} diff --git a/arch/arm/mach-mx35/mx35_3stack_pmic_mc9s08dz60.c b/arch/arm/mach-mx35/mx35_3stack_pmic_mc9s08dz60.c new file mode 100644 index 000000000000..25d37f98f9d7 --- /dev/null +++ b/arch/arm/mach-mx35/mx35_3stack_pmic_mc9s08dz60.c @@ -0,0 +1,104 @@ +/* + * mx35-3stack-pmic-mc9s08dz60.c -- i.MX35 3STACK Driver for MCU 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/mc9s08dz60/core.h> +#include "iomux.h" +#include "board-mx35_3stack.h" + +static struct regulator_init_data lcd_init = { + .constraints = { + .name = "LCD", + } +}; + +static struct regulator_init_data wifi_init = { + .constraints = { + .name = "WIFI", + } +}; + +static struct regulator_init_data hdd_init = { + .constraints = { + .name = "HDD", + } +}; + +static struct regulator_init_data gps_init = { + .constraints = { + .name = "GPS", + } +}; + +static struct regulator_init_data spkr_init = { + .constraints = { + .name = "SPKR", + } +}; + +static int mc9s08dz60_regulator_init(struct mc9s08dz60 *mc9s08dz60) +{ + if (!board_is_rev(BOARD_REV_2)) + return 0; + + mc9s08dz60_register_regulator( + mc9s08dz60, MC9S08DZ60_LCD, &lcd_init); + mc9s08dz60_register_regulator(mc9s08dz60, + MC9S08DZ60_WIFI, &wifi_init); + mc9s08dz60_register_regulator( + mc9s08dz60, MC9S08DZ60_HDD, &hdd_init); + mc9s08dz60_register_regulator( + mc9s08dz60, MC9S08DZ60_GPS, &gps_init); + mc9s08dz60_register_regulator(mc9s08dz60, + MC9S08DZ60_SPKR, &spkr_init); + return 0; +} + +static struct mc9s08dz60_platform_data mc9s08dz60_plat = { + .init = mc9s08dz60_regulator_init, +}; + +static struct i2c_board_info __initdata mc9s08dz60_i2c_device = { + I2C_BOARD_INFO("mc9s08dz60", 0x69), + .platform_data = &mc9s08dz60_plat, +}; + +static struct resource mc9s08dz60_keypad_resource = { + .start = MXC_PSEUDO_IRQ_KEYPAD, + .end = MXC_PSEUDO_IRQ_KEYPAD, + .flags = IORESOURCE_IRQ, +}; + +static struct platform_device mc9s08dz60_keypad_dev = { + .name = "mc9s08dz60keypad", + .num_resources = 1, + .resource = &mc9s08dz60_keypad_resource, +}; + +int __init mx35_3stack_init_mc9s08dz60(void) +{ + int retval = 0; + retval = i2c_register_board_info(0, &mc9s08dz60_i2c_device, 1); + if (retval == 0) + platform_device_register(&mc9s08dz60_keypad_dev); + return retval; +} diff --git a/arch/arm/mach-mx35/mx35_pins.h b/arch/arm/mach-mx35/mx35_pins.h new file mode 100644 index 000000000000..082384231370 --- /dev/null +++ b/arch/arm/mach-mx35/mx35_pins.h @@ -0,0 +1,333 @@ +/* + * 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_MX35_PINS_H__ +#define __ASM_ARCH_MXC_MX35_PINS_H__ + +/*! + * @file arch-mxc/mx35_pins.h + * + * @brief MX35 I/O Pin List + * + * @ingroup GPIO_MX35 + */ + +#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 | RSVD | PAD_I | MUX_I + * ------------------------------------------------------------------- + * + * Bit 0 to 7 contains MUX_I used to identify the register + * offset (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.the MX35_PIN_A0 is + * defined in the enumeration: ( 0x28 << MUX_I) |( 0x368 << PAD_I) + * So the absolute address is: IOMUX_module_base + 0x28. + * The pad control register offset is: 0x368. + */ + +/*! + * 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 the + * reserved filed + */ +#define RSVD_I 21 + +#define NON_GPIO_I 0x7 +#define PIN_TO_MUX_MASK ((1<<(PAD_I - MUX_I)) - 1) +#define PIN_TO_PAD_MASK ((1<<(RSVD_I - PAD_I)) - 1) +#define NON_MUX_I PIN_TO_MUX_MASK + +#define _MXC_BUILD_PIN(gp, gi, mi, pi) \ + (((gp) << MUX_IO_P) | ((gi) << MUX_IO_I) | \ + ((mi) << MUX_I) | ((pi) << PAD_I)) + +#define _MXC_BUILD_GPIO_PIN(gp, gi, mi, pi) \ + _MXC_BUILD_PIN(gp, gi, mi, pi) + +#define _MXC_BUILD_NON_GPIO_PIN(mi, pi) \ + _MXC_BUILD_PIN(NON_GPIO_I, 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) + +/*! @} End IOMUX/PAD Bit field definitions */ + +/*! + * This enumeration is constructed based on the Section + * "sw_pad_ctl & sw_mux_ctl details" of the MX35 IC Spec. Each enumerated + * value is constructed based on the rules described above. + */ +enum iomux_pins { + MX35_PIN_CAPTURE = _MXC_BUILD_GPIO_PIN(0, 4, 0x4, 0x328), + MX35_PIN_COMPARE = _MXC_BUILD_GPIO_PIN(0, 5, 0x8, 0x32C), + MX35_PIN_WATCHDOG_RST = _MXC_BUILD_GPIO_PIN(0, 6, 0xC, 0x330), + MX35_PIN_GPIO1_0 = _MXC_BUILD_GPIO_PIN(0, 0, 0x10, 0x334), + MX35_PIN_GPIO1_1 = _MXC_BUILD_GPIO_PIN(0, 1, 0x14, 0x338), + MX35_PIN_GPIO2_0 = _MXC_BUILD_GPIO_PIN(1, 0, 0x18, 0x33C), + MX35_PIN_GPIO3_0 = _MXC_BUILD_GPIO_PIN(2, 0, 0x1C, 0x340), + MX35_PIN_CLKO = _MXC_BUILD_GPIO_PIN(0, 8, 0x20, 0x34C), + + MX35_PIN_POWER_FAIL = _MXC_BUILD_NON_GPIO_PIN(NON_MUX_I, 0x360), + MX35_PIN_VSTBY = _MXC_BUILD_GPIO_PIN(0, 7, 0x24, 0x364), + MX35_PIN_A0 = _MXC_BUILD_NON_GPIO_PIN(0x28, 0x368), + MX35_PIN_A1 = _MXC_BUILD_NON_GPIO_PIN(0x2C, 0x36C), + MX35_PIN_A2 = _MXC_BUILD_NON_GPIO_PIN(0x30, 0x370), + MX35_PIN_A3 = _MXC_BUILD_NON_GPIO_PIN(0x34, 0x374), + MX35_PIN_A4 = _MXC_BUILD_NON_GPIO_PIN(0x38, 0x378), + MX35_PIN_A5 = _MXC_BUILD_NON_GPIO_PIN(0x3C, 0x37C), + MX35_PIN_A6 = _MXC_BUILD_NON_GPIO_PIN(0x40, 0x380), + MX35_PIN_A7 = _MXC_BUILD_NON_GPIO_PIN(0x44, 0x384), + MX35_PIN_A8 = _MXC_BUILD_NON_GPIO_PIN(0x48, 0x388), + MX35_PIN_A9 = _MXC_BUILD_NON_GPIO_PIN(0x4C, 0x38C), + MX35_PIN_A10 = _MXC_BUILD_NON_GPIO_PIN(0x50, 0x390), + MX35_PIN_MA10 = _MXC_BUILD_NON_GPIO_PIN(0x54, 0x394), + MX35_PIN_A11 = _MXC_BUILD_NON_GPIO_PIN(0x58, 0x398), + MX35_PIN_A12 = _MXC_BUILD_NON_GPIO_PIN(0x5C, 0x39C), + MX35_PIN_A13 = _MXC_BUILD_NON_GPIO_PIN(0x60, 0x3A0), + MX35_PIN_A14 = _MXC_BUILD_NON_GPIO_PIN(0x64, 0x3A4), + MX35_PIN_A15 = _MXC_BUILD_NON_GPIO_PIN(0x68, 0x3A8), + MX35_PIN_A16 = _MXC_BUILD_NON_GPIO_PIN(0x6C, 0x3AC), + MX35_PIN_A17 = _MXC_BUILD_NON_GPIO_PIN(0x70, 0x3B0), + MX35_PIN_A18 = _MXC_BUILD_NON_GPIO_PIN(0x74, 0x3B4), + MX35_PIN_A19 = _MXC_BUILD_NON_GPIO_PIN(0x78, 0x3B8), + MX35_PIN_A20 = _MXC_BUILD_NON_GPIO_PIN(0x7C, 0x3BC), + MX35_PIN_A21 = _MXC_BUILD_NON_GPIO_PIN(0x80, 0x3C0), + MX35_PIN_A22 = _MXC_BUILD_NON_GPIO_PIN(0x84, 0x3C4), + MX35_PIN_A23 = _MXC_BUILD_NON_GPIO_PIN(0x88, 0x3C8), + MX35_PIN_A24 = _MXC_BUILD_NON_GPIO_PIN(0x8C, 0x3CC), + MX35_PIN_A25 = _MXC_BUILD_NON_GPIO_PIN(0x90, 0x3D0), + + MX35_PIN_EB0 = _MXC_BUILD_NON_GPIO_PIN(0x94, 0x46C), + MX35_PIN_EB1 = _MXC_BUILD_NON_GPIO_PIN(0x98, 0x470), + MX35_PIN_OE = _MXC_BUILD_NON_GPIO_PIN(0x9C, 0x474), + MX35_PIN_CS0 = _MXC_BUILD_NON_GPIO_PIN(0xA0, 0x478), + MX35_PIN_CS1 = _MXC_BUILD_NON_GPIO_PIN(0xA4, 0x47C), + MX35_PIN_CS2 = _MXC_BUILD_NON_GPIO_PIN(0xA8, 0x480), + MX35_PIN_CS3 = _MXC_BUILD_NON_GPIO_PIN(0xAC, 0x484), + MX35_PIN_CS4 = _MXC_BUILD_GPIO_PIN(0, 20, 0xB0, 0x488), + MX35_PIN_CS5 = _MXC_BUILD_GPIO_PIN(0, 21, 0xB4, 0x48C), + MX35_PIN_NFCE_B = _MXC_BUILD_GPIO_PIN(0, 22, 0xB8, 0x490), + + MX35_PIN_LBA = _MXC_BUILD_NON_GPIO_PIN(0xBC, 0x498), + MX35_PIN_BCLK = _MXC_BUILD_NON_GPIO_PIN(0xC0, 0x49C), + MX35_PIN_RW = _MXC_BUILD_NON_GPIO_PIN(0xC4, 0x4A0), + + MX35_PIN_NFWE_B = _MXC_BUILD_GPIO_PIN(1, 18, 0xC8, 0x4CC), + MX35_PIN_NFRE_B = _MXC_BUILD_GPIO_PIN(1, 19, 0xCC, 0x4D0), + MX35_PIN_NFALE = _MXC_BUILD_GPIO_PIN(1, 20, 0xD0, 0x4D4), + MX35_PIN_NFCLE = _MXC_BUILD_GPIO_PIN(1, 21, 0xD4, 0x4D8), + MX35_PIN_NFWP_B = _MXC_BUILD_GPIO_PIN(1, 22, 0xD8, 0x4DC), + MX35_PIN_NFRB = _MXC_BUILD_GPIO_PIN(1, 23, 0xDC, 0x4E0), + + MX35_PIN_D15 = _MXC_BUILD_NON_GPIO_PIN(NON_MUX_I, 0x4E4), + MX35_PIN_D14 = _MXC_BUILD_NON_GPIO_PIN(NON_MUX_I, 0x4E8), + MX35_PIN_D13 = _MXC_BUILD_NON_GPIO_PIN(NON_MUX_I, 0x4EC), + MX35_PIN_D12 = _MXC_BUILD_NON_GPIO_PIN(NON_MUX_I, 0x4F0), + MX35_PIN_D11 = _MXC_BUILD_NON_GPIO_PIN(NON_MUX_I, 0x4F4), + MX35_PIN_D10 = _MXC_BUILD_NON_GPIO_PIN(NON_MUX_I, 0x4F8), + MX35_PIN_D9 = _MXC_BUILD_NON_GPIO_PIN(NON_MUX_I, 0x4FC), + MX35_PIN_D8 = _MXC_BUILD_NON_GPIO_PIN(NON_MUX_I, 0x500), + MX35_PIN_D7 = _MXC_BUILD_NON_GPIO_PIN(NON_MUX_I, 0x504), + MX35_PIN_D6 = _MXC_BUILD_NON_GPIO_PIN(NON_MUX_I, 0x508), + MX35_PIN_D5 = _MXC_BUILD_NON_GPIO_PIN(NON_MUX_I, 0x50C), + MX35_PIN_D4 = _MXC_BUILD_NON_GPIO_PIN(NON_MUX_I, 0x510), + MX35_PIN_D3 = _MXC_BUILD_NON_GPIO_PIN(NON_MUX_I, 0x514), + MX35_PIN_D2 = _MXC_BUILD_NON_GPIO_PIN(NON_MUX_I, 0x518), + MX35_PIN_D1 = _MXC_BUILD_NON_GPIO_PIN(NON_MUX_I, 0x51C), + MX35_PIN_D0 = _MXC_BUILD_NON_GPIO_PIN(NON_MUX_I, 0x520), + + MX35_PIN_CSI_D8 = _MXC_BUILD_GPIO_PIN(0, 20, 0xE0, 0x524), + MX35_PIN_CSI_D9 = _MXC_BUILD_GPIO_PIN(0, 21, 0xE4, 0x528), + MX35_PIN_CSI_D10 = _MXC_BUILD_GPIO_PIN(0, 22, 0xE8, 0x52C), + MX35_PIN_CSI_D11 = _MXC_BUILD_GPIO_PIN(0, 23, 0xEC, 0x530), + MX35_PIN_CSI_D12 = _MXC_BUILD_GPIO_PIN(0, 24, 0xF0, 0x534), + MX35_PIN_CSI_D13 = _MXC_BUILD_GPIO_PIN(0, 25, 0xF4, 0x538), + MX35_PIN_CSI_D14 = _MXC_BUILD_GPIO_PIN(0, 26, 0xF8, 0x53C), + MX35_PIN_CSI_D15 = _MXC_BUILD_GPIO_PIN(0, 27, 0xFC, 0x540), + MX35_PIN_CSI_MCLK = _MXC_BUILD_GPIO_PIN(0, 28, 0x100, 0x544), + MX35_PIN_CSI_VSYNC = _MXC_BUILD_GPIO_PIN(0, 29, 0x104, 0x548), + MX35_PIN_CSI_HSYNC = _MXC_BUILD_GPIO_PIN(0, 30, 0x108, 0x54C), + MX35_PIN_CSI_PIXCLK = _MXC_BUILD_GPIO_PIN(0, 31, 0x10C, 0x550), + + MX35_PIN_I2C1_CLK = _MXC_BUILD_GPIO_PIN(1, 24, 0x110, 0x554), + MX35_PIN_I2C1_DAT = _MXC_BUILD_GPIO_PIN(1, 25, 0x114, 0x558), + MX35_PIN_I2C2_CLK = _MXC_BUILD_GPIO_PIN(1, 26, 0x118, 0x55C), + MX35_PIN_I2C2_DAT = _MXC_BUILD_GPIO_PIN(1, 27, 0x11C, 0x560), + + MX35_PIN_STXD4 = _MXC_BUILD_GPIO_PIN(1, 28, 0x120, 0x564), + MX35_PIN_SRXD4 = _MXC_BUILD_GPIO_PIN(1, 29, 0x124, 0x568), + MX35_PIN_SCK4 = _MXC_BUILD_GPIO_PIN(1, 30, 0x128, 0x56C), + MX35_PIN_STXFS4 = _MXC_BUILD_GPIO_PIN(1, 31, 0x12C, 0x570), + MX35_PIN_STXD5 = _MXC_BUILD_GPIO_PIN(0, 0, 0x130, 0x574), + MX35_PIN_SRXD5 = _MXC_BUILD_GPIO_PIN(0, 1, 0x134, 0x578), + MX35_PIN_SCK5 = _MXC_BUILD_GPIO_PIN(0, 2, 0x138, 0x57C), + MX35_PIN_STXFS5 = _MXC_BUILD_GPIO_PIN(0, 3, 0x13C, 0x580), + + MX35_PIN_SCKR = _MXC_BUILD_GPIO_PIN(0, 4, 0x140, 0x584), + MX35_PIN_FSR = _MXC_BUILD_GPIO_PIN(0, 5, 0x144, 0x588), + MX35_PIN_HCKR = _MXC_BUILD_GPIO_PIN(0, 6, 0x148, 0x58C), + MX35_PIN_SCKT = _MXC_BUILD_GPIO_PIN(0, 7, 0x14C, 0x590), + MX35_PIN_FST = _MXC_BUILD_GPIO_PIN(0, 8, 0x150, 0x594), + MX35_PIN_HCKT = _MXC_BUILD_GPIO_PIN(0, 9, 0x154, 0x598), + MX35_PIN_TX5_RX0 = _MXC_BUILD_GPIO_PIN(0, 10, 0x158, 0x59C), + MX35_PIN_TX4_RX1 = _MXC_BUILD_GPIO_PIN(0, 11, 0x15C, 0x5A0), + MX35_PIN_TX3_RX2 = _MXC_BUILD_GPIO_PIN(0, 12, 0x160, 0x5A4), + MX35_PIN_TX2_RX3 = _MXC_BUILD_GPIO_PIN(0, 13, 0x164, 0x5A8), + MX35_PIN_TX1 = _MXC_BUILD_GPIO_PIN(0, 14, 0x168, 0x5AC), + MX35_PIN_TX0 = _MXC_BUILD_GPIO_PIN(0, 15, 0x16C, 0x5B0), + + MX35_PIN_CSPI1_MOSI = _MXC_BUILD_GPIO_PIN(0, 16, 0x170, 0x5B4), + MX35_PIN_CSPI1_MISO = _MXC_BUILD_GPIO_PIN(0, 17, 0x174, 0x5B8), + MX35_PIN_CSPI1_SS0 = _MXC_BUILD_GPIO_PIN(0, 18, 0x178, 0x5BC), + MX35_PIN_CSPI1_SS1 = _MXC_BUILD_GPIO_PIN(0, 19, 0x17C, 0x5C0), + MX35_PIN_CSPI1_SCLK = _MXC_BUILD_GPIO_PIN(2, 4, 0x180, 0x5C4), + MX35_PIN_CSPI1_SPI_RDY = _MXC_BUILD_GPIO_PIN(2, 5, 0x184, 0x5C8), + + MX35_PIN_RXD1 = _MXC_BUILD_GPIO_PIN(2, 6, 0x188, 0x5CC), + MX35_PIN_TXD1 = _MXC_BUILD_GPIO_PIN(2, 7, 0x18C, 0x5D0), + MX35_PIN_RTS1 = _MXC_BUILD_GPIO_PIN(2, 8, 0x190, 0x5D4), + MX35_PIN_CTS1 = _MXC_BUILD_GPIO_PIN(2, 9, 0x194, 0x5D8), + MX35_PIN_RXD2 = _MXC_BUILD_GPIO_PIN(2, 10, 0x198, 0x5DC), + MX35_PIN_TXD2 = _MXC_BUILD_GPIO_PIN(2, 11, 0x19C, 0x5E0), + MX35_PIN_RTS2 = _MXC_BUILD_GPIO_PIN(2, 12, 0x1A0, 0x5E4), + MX35_PIN_CTS2 = _MXC_BUILD_GPIO_PIN(2, 13, 0x1A4, 0x5E8), + + MX35_PIN_USBOTG_PWR = _MXC_BUILD_GPIO_PIN(2, 14, 0x1A8, 0x60C), + MX35_PIN_USBOTG_OC = _MXC_BUILD_GPIO_PIN(2, 15, 0x1AC, 0x610), + + MX35_PIN_LD0 = _MXC_BUILD_GPIO_PIN(1, 0, 0x1B0, 0x614), + MX35_PIN_LD1 = _MXC_BUILD_GPIO_PIN(1, 1, 0x1B4, 0x618), + MX35_PIN_LD2 = _MXC_BUILD_GPIO_PIN(1, 2, 0x1B8, 0x61C), + MX35_PIN_LD3 = _MXC_BUILD_GPIO_PIN(1, 3, 0x1BC, 0x620), + MX35_PIN_LD4 = _MXC_BUILD_GPIO_PIN(1, 4, 0x1C0, 0x624), + MX35_PIN_LD5 = _MXC_BUILD_GPIO_PIN(1, 5, 0x1C4, 0x628), + MX35_PIN_LD6 = _MXC_BUILD_GPIO_PIN(1, 6, 0x1C8, 0x62C), + MX35_PIN_LD7 = _MXC_BUILD_GPIO_PIN(1, 7, 0x1CC, 0x630), + MX35_PIN_LD8 = _MXC_BUILD_GPIO_PIN(1, 8, 0x1D0, 0x634), + MX35_PIN_LD9 = _MXC_BUILD_GPIO_PIN(1, 9, 0x1D4, 0x638), + MX35_PIN_LD10 = _MXC_BUILD_GPIO_PIN(1, 10, 0x1D8, 0x63C), + MX35_PIN_LD11 = _MXC_BUILD_GPIO_PIN(1, 11, 0x1DC, 0x640), + MX35_PIN_LD12 = _MXC_BUILD_GPIO_PIN(1, 12, 0x1E0, 0x644), + MX35_PIN_LD13 = _MXC_BUILD_GPIO_PIN(1, 13, 0x1E4, 0x648), + MX35_PIN_LD14 = _MXC_BUILD_GPIO_PIN(1, 14, 0x1E8, 0x64C), + MX35_PIN_LD15 = _MXC_BUILD_GPIO_PIN(1, 15, 0x1EC, 0x650), + MX35_PIN_LD16 = _MXC_BUILD_GPIO_PIN(1, 16, 0x1F0, 0x654), + MX35_PIN_LD17 = _MXC_BUILD_GPIO_PIN(1, 17, 0x1F4, 0x658), + MX35_PIN_LD18 = _MXC_BUILD_GPIO_PIN(2, 24, 0x1F8, 0x65C), + MX35_PIN_LD19 = _MXC_BUILD_GPIO_PIN(2, 25, 0x1FC, 0x660), + MX35_PIN_LD20 = _MXC_BUILD_GPIO_PIN(2, 26, 0x200, 0x664), + MX35_PIN_LD21 = _MXC_BUILD_GPIO_PIN(2, 27, 0x204, 0x668), + MX35_PIN_LD22 = _MXC_BUILD_GPIO_PIN(2, 28, 0x208, 0x66C), + MX35_PIN_LD23 = _MXC_BUILD_GPIO_PIN(2, 29, 0x20C, 0x670), + + MX35_PIN_D3_HSYNC = _MXC_BUILD_GPIO_PIN(2, 30, 0x210, 0x674), + MX35_PIN_D3_FPSHIFT = _MXC_BUILD_GPIO_PIN(2, 31, 0x214, 0x678), + MX35_PIN_D3_DRDY = _MXC_BUILD_GPIO_PIN(0, 0, 0x218, 0x67C), + MX35_PIN_CONTRAST = _MXC_BUILD_GPIO_PIN(0, 1, 0x21C, 0x680), + MX35_PIN_D3_VSYNC = _MXC_BUILD_GPIO_PIN(0, 2, 0x220, 0x684), + MX35_PIN_D3_REV = _MXC_BUILD_GPIO_PIN(0, 3, 0x224, 0x688), + MX35_PIN_D3_CLS = _MXC_BUILD_GPIO_PIN(0, 4, 0x228, 0x68C), + MX35_PIN_D3_SPL = _MXC_BUILD_GPIO_PIN(0, 5, 0x22C, 0x690), + + MX35_PIN_SD1_CMD = _MXC_BUILD_GPIO_PIN(0, 6, 0x230, 0x694), + MX35_PIN_SD1_CLK = _MXC_BUILD_GPIO_PIN(0, 7, 0x234, 0x698), + MX35_PIN_SD1_DATA0 = _MXC_BUILD_GPIO_PIN(0, 8, 0x238, 0x69C), + MX35_PIN_SD1_DATA1 = _MXC_BUILD_GPIO_PIN(0, 9, 0x23C, 0x6A0), + MX35_PIN_SD1_DATA2 = _MXC_BUILD_GPIO_PIN(0, 10, 0x240, 0x6A4), + MX35_PIN_SD1_DATA3 = _MXC_BUILD_GPIO_PIN(0, 11, 0x244, 0x6A8), + MX35_PIN_SD2_CMD = _MXC_BUILD_GPIO_PIN(1, 0, 0x248, 0x6AC), + MX35_PIN_SD2_CLK = _MXC_BUILD_GPIO_PIN(1, 1, 0x24C, 0x6B0), + MX35_PIN_SD2_DATA0 = _MXC_BUILD_GPIO_PIN(1, 2, 0x250, 0x6B4), + MX35_PIN_SD2_DATA1 = _MXC_BUILD_GPIO_PIN(1, 3, 0x254, 0x6B8), + MX35_PIN_SD2_DATA2 = _MXC_BUILD_GPIO_PIN(1, 4, 0x258, 0x6BC), + MX35_PIN_SD2_DATA3 = _MXC_BUILD_GPIO_PIN(1, 5, 0x25C, 0x6C0), + + MX35_PIN_ATA_CS0 = _MXC_BUILD_GPIO_PIN(1, 6, 0x260, 0x6C4), + MX35_PIN_ATA_CS1 = _MXC_BUILD_GPIO_PIN(1, 7, 0x264, 0x6C8), + MX35_PIN_ATA_DIOR = _MXC_BUILD_GPIO_PIN(1, 8, 0x268, 0x6CC), + MX35_PIN_ATA_DIOW = _MXC_BUILD_GPIO_PIN(1, 9, 0x26C, 0x6D0), + MX35_PIN_ATA_DMACK = _MXC_BUILD_GPIO_PIN(1, 10, 0x270, 0x6D4), + MX35_PIN_ATA_RESET_B = _MXC_BUILD_GPIO_PIN(1, 11, 0x274, 0x6D8), + MX35_PIN_ATA_IORDY = _MXC_BUILD_GPIO_PIN(1, 12, 0x278, 0x6DC), + MX35_PIN_ATA_DATA0 = _MXC_BUILD_GPIO_PIN(1, 13, 0x27C, 0x6E0), + MX35_PIN_ATA_DATA1 = _MXC_BUILD_GPIO_PIN(1, 14, 0x280, 0x6E4), + MX35_PIN_ATA_DATA2 = _MXC_BUILD_GPIO_PIN(1, 15, 0x284, 0x6E8), + MX35_PIN_ATA_DATA3 = _MXC_BUILD_GPIO_PIN(1, 16, 0x288, 0x6EC), + MX35_PIN_ATA_DATA4 = _MXC_BUILD_GPIO_PIN(1, 17, 0x28C, 0x6F0), + MX35_PIN_ATA_DATA5 = _MXC_BUILD_GPIO_PIN(1, 18, 0x290, 0x6F4), + MX35_PIN_ATA_DATA6 = _MXC_BUILD_GPIO_PIN(1, 19, 0x294, 0x6F8), + MX35_PIN_ATA_DATA7 = _MXC_BUILD_GPIO_PIN(1, 20, 0x298, 0x6FC), + MX35_PIN_ATA_DATA8 = _MXC_BUILD_GPIO_PIN(1, 21, 0x29C, 0x700), + MX35_PIN_ATA_DATA9 = _MXC_BUILD_GPIO_PIN(1, 22, 0x2A0, 0x704), + MX35_PIN_ATA_DATA10 = _MXC_BUILD_GPIO_PIN(1, 23, 0x2A4, 0x708), + MX35_PIN_ATA_DATA11 = _MXC_BUILD_GPIO_PIN(1, 24, 0x2A8, 0x70C), + MX35_PIN_ATA_DATA12 = _MXC_BUILD_GPIO_PIN(1, 25, 0x2AC, 0x710), + MX35_PIN_ATA_DATA13 = _MXC_BUILD_GPIO_PIN(1, 26, 0x2B0, 0x714), + MX35_PIN_ATA_DATA14 = _MXC_BUILD_GPIO_PIN(1, 27, 0x2B4, 0x718), + MX35_PIN_ATA_DATA15 = _MXC_BUILD_GPIO_PIN(1, 28, 0x2B8, 0x71C), + MX35_PIN_ATA_INTRQ = _MXC_BUILD_GPIO_PIN(1, 29, 0x2BC, 0x720), + MX35_PIN_ATA_BUFF_EN = _MXC_BUILD_GPIO_PIN(1, 30, 0x2C0, 0x724), + MX35_PIN_ATA_DMARQ = _MXC_BUILD_GPIO_PIN(1, 31, 0x2C4, 0x728), + MX35_PIN_ATA_DA0 = _MXC_BUILD_GPIO_PIN(2, 0, 0x2C8, 0x72C), + MX35_PIN_ATA_DA1 = _MXC_BUILD_GPIO_PIN(2, 1, 0x2CC, 0x730), + MX35_PIN_ATA_DA2 = _MXC_BUILD_GPIO_PIN(2, 2, 0x2D0, 0x734), + + MX35_PIN_MLB_CLK = _MXC_BUILD_GPIO_PIN(2, 3, 0x2D4, 0x738), + MX35_PIN_MLB_DAT = _MXC_BUILD_GPIO_PIN(2, 4, 0x2D8, 0x73C), + MX35_PIN_MLB_SIG = _MXC_BUILD_GPIO_PIN(2, 5, 0x2DC, 0x740), + + MX35_PIN_FEC_TX_CLK = _MXC_BUILD_GPIO_PIN(2, 6, 0x2E0, 0x744), + MX35_PIN_FEC_RX_CLK = _MXC_BUILD_GPIO_PIN(2, 7, 0x2E4, 0x748), + MX35_PIN_FEC_RX_DV = _MXC_BUILD_GPIO_PIN(2, 8, 0x2E8, 0x74C), + MX35_PIN_FEC_COL = _MXC_BUILD_GPIO_PIN(2, 9, 0x2EC, 0x750), + MX35_PIN_FEC_RDATA0 = _MXC_BUILD_GPIO_PIN(2, 10, 0x2F0, 0x754), + MX35_PIN_FEC_TDATA0 = _MXC_BUILD_GPIO_PIN(2, 11, 0x2F4, 0x758), + MX35_PIN_FEC_TX_EN = _MXC_BUILD_GPIO_PIN(2, 12, 0x2F8, 0x75C), + MX35_PIN_FEC_MDC = _MXC_BUILD_GPIO_PIN(2, 13, 0x2FC, 0x760), + MX35_PIN_FEC_MDIO = _MXC_BUILD_GPIO_PIN(2, 14, 0x300, 0x764), + MX35_PIN_FEC_TX_ERR = _MXC_BUILD_GPIO_PIN(2, 15, 0x304, 0x768), + MX35_PIN_FEC_RX_ERR = _MXC_BUILD_GPIO_PIN(2, 16, 0x308, 0x76C), + MX35_PIN_FEC_CRS = _MXC_BUILD_GPIO_PIN(2, 17, 0x30C, 0x770), + MX35_PIN_FEC_RDATA1 = _MXC_BUILD_GPIO_PIN(2, 18, 0x310, 0x774), + MX35_PIN_FEC_TDATA1 = _MXC_BUILD_GPIO_PIN(2, 19, 0x314, 0x778), + MX35_PIN_FEC_RDATA2 = _MXC_BUILD_GPIO_PIN(2, 20, 0x318, 0x77C), + MX35_PIN_FEC_TDATA2 = _MXC_BUILD_GPIO_PIN(2, 21, 0x31C, 0x780), + MX35_PIN_FEC_RDATA3 = _MXC_BUILD_GPIO_PIN(2, 22, 0x320, 0x784), + MX35_PIN_FEC_TDATA3 = _MXC_BUILD_GPIO_PIN(2, 23, 0x324, 0x788), +}; + +#endif +#endif diff --git a/arch/arm/mach-mx35/pm.c b/arch/arm/mach-mx35/pm.c new file mode 100644 index 000000000000..6a7c8c8a0844 --- /dev/null +++ b/arch/arm/mach-mx35/pm.c @@ -0,0 +1,80 @@ +/* + * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved. + */ + +/* + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ + +#include <linux/kernel.h> +#include <linux/suspend.h> +#include <mach/hardware.h> + +/*! + * @defgroup MSL_MX35 i.MX35 Machine Specific Layer (MSL) + */ + +/*! + * @file mach-mx35/pm.c + * @brief This file contains suspend operations + * + * @ingroup MSL_MX35 + */ +static int mx35_suspend_enter(suspend_state_t state) +{ + switch (state) { + case PM_SUSPEND_MEM: + mxc_cpu_lp_set(STOP_POWER_OFF); + break; + case PM_SUSPEND_STANDBY: + mxc_cpu_lp_set(STOP_POWER_ON); + break; + default: + return -EINVAL; + } + /* Executing CP15 (Wait-for-Interrupt) Instruction */ + cpu_do_idle(); + return 0; +} + +/* + * Called after processes are frozen, but before we shut down devices. + */ +static int mx35_suspend_prepare(void) +{ + return 0; +} + +/* + * Called after devices are re-setup, but before processes are thawed. + */ +static void mx35_suspend_finish(void) +{ +} + +static int mx35_pm_valid(suspend_state_t state) +{ + return (state > PM_SUSPEND_ON && state <= PM_SUSPEND_MAX); +} + +struct platform_suspend_ops mx35_suspend_ops = { + .valid = mx35_pm_valid, + .prepare = mx35_suspend_prepare, + .enter = mx35_suspend_enter, + .finish = mx35_suspend_finish, +}; + +static int __init mx35_pm_init(void) +{ + pr_info("Static Power Management for Freescale i.MX35\n"); + suspend_set_ops(&mx35_suspend_ops); + + return 0; +} + +late_initcall(mx35_pm_init); diff --git a/arch/arm/mach-mx35/sdma_script_code.h b/arch/arm/mach-mx35/sdma_script_code.h new file mode 100644 index 000000000000..e1b6b59bc31e --- /dev/null +++ b/arch/arm/mach-mx35/sdma_script_code.h @@ -0,0 +1,254 @@ +/* + * 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_RINGO" + +*******************************************************************************/ + +#ifndef __SDMA_SCRIPT_CODE_H__ +#define __SDMA_SCRIPT_CODE_H__ + +/*! +* SDMA ROM scripts start addresses and sizes +*/ + +#define start_ADDR 0 +#define start_SIZE 22 + +#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 per_2_shp_ADDR 1033 +#define per_2_shp_SIZE 78 + +#define shp_2_per_ADDR 1111 +#define shp_2_per_SIZE 72 + +#define uartsh_2_mcu_ADDR 1183 +#define uartsh_2_mcu_SIZE 69 + +#define mcu_2_ata_ADDR 1252 +#define mcu_2_ata_SIZE 81 + +#define ata_2_mcu_ADDR 1333 +#define ata_2_mcu_SIZE 96 + +#define loop_DMAs_routines_ADDR 1429 +#define loop_DMAs_routines_SIZE 227 + +#define test_ADDR 1656 +#define test_SIZE 63 + +#define signature_ADDR 1023 +#define signature_SIZE 1 + +/*! +* SDMA RAM scripts start addresses and sizes +*/ + +#define app_2_per_ADDR 6144 +#define app_2_per_SIZE 66 + +#define asrc__mcu_ADDR 6210 +#define asrc__mcu_SIZE 114 + +#define ext_mem__ipu_ram_ADDR 6324 +#define ext_mem__ipu_ram_SIZE 123 + +#define mcu_2_spdif_ADDR 6447 +#define mcu_2_spdif_SIZE 103 + +#define p_2_p_ADDR 6550 +#define p_2_p_SIZE 254 + +#define per_2_app_ADDR 6804 +#define per_2_app_SIZE 74 + +#define spdif_2_mcu_ADDR 6878 +#define spdif_2_mcu_SIZE 47 + +#define uart_2_per_ADDR 6925 +#define uart_2_per_SIZE 73 + +#define uartsh_2_per_ADDR 6998 +#define uartsh_2_per_SIZE 67 + +/*! +* SDMA RAM image start address and size +*/ + +#define RAM_CODE_START_ADDR 6144 +#define RAM_CODE_SIZE 921 + +/*! +* Buffer that holds the SDMA RAM image +*/ +__attribute__ ((__aligned__(4))) +#ifndef CONFIG_XIP_KERNEL +const +#endif +static const short sdma_code[] = { + 0xc1e3, 0x57db, 0x52fb, 0x6ac3, 0x52f3, 0x6ad7, 0x008f, 0x00d5, + 0x7d01, 0x008d, 0x05a0, 0x0478, 0x7d03, 0x0479, 0x7d1c, 0x7c21, + 0x0479, 0x7c14, 0x6ddd, 0x56ee, 0x62c8, 0x7e28, 0x0660, 0x7d02, + 0x0210, 0x0212, 0x6ac8, 0x7f22, 0x0212, 0x6ac8, 0x7f1f, 0x0212, + 0x6ac8, 0x7f1c, 0x2003, 0x4800, 0x7cef, 0x9836, 0x6ddd, 0x7802, + 0x62c8, 0x6ac8, 0x9835, 0x6dde, 0x0015, 0x7802, 0x62c8, 0x6ac8, + 0x9835, 0x0015, 0x0015, 0x7801, 0x62d8, 0x7c08, 0x6ddf, 0x7f06, + 0x0000, 0x4d00, 0x7d05, 0xc1fa, 0x57db, 0x9806, 0xc273, 0x0454, + 0xc20a, 0x9801, 0xc1d9, 0xc1e3, 0x56f3, 0x57db, 0x047a, 0x7d07, + 0x072f, 0x076e, 0x7d02, 0x6ec7, 0x9855, 0x6ed7, 0x9855, 0x074f, + 0x076e, 0x7d02, 0x6e01, 0x9855, 0x6e05, 0x5ce3, 0x048f, 0x0410, + 0x3c0f, 0x5c93, 0x0eff, 0x06bf, 0x06d5, 0x7d01, 0x068d, 0x05a6, + 0x5deb, 0x55fb, 0x008e, 0x0768, 0x7d02, 0x0769, 0x7c04, 0x06d4, + 0x7d01, 0x008c, 0x04a0, 0x06a0, 0x076f, 0x7d0c, 0x076e, 0x7d05, + 0x7802, 0x62c8, 0x5a05, 0x7c2b, 0x9887, 0x7802, 0x5205, 0x6ac8, + 0x7c26, 0x9887, 0x076e, 0x7d05, 0x7802, 0x620b, 0x5a05, 0x7c21, + 0x9887, 0x7802, 0x5205, 0x6a0b, 0x7c1c, 0x6a28, 0x7f1a, 0x0768, + 0x7d02, 0x0769, 0x7c0a, 0x4c00, 0x7c08, 0x0768, 0x7d03, 0x5a05, + 0x7f11, 0x9894, 0x5205, 0x7e0e, 0x5493, 0x4e00, 0x7ccb, 0x0000, + 0x54e3, 0x55eb, 0x4d00, 0x7d0a, 0xc1fa, 0x57db, 0x9856, 0x68cc, + 0x98a2, 0x680c, 0x009e, 0x0007, 0x54e3, 0xd8a8, 0xc20a, 0x9844, + 0x55eb, 0x009d, 0x058c, 0x0aff, 0x0211, 0x1aff, 0x05ba, 0x05a0, + 0x04b2, 0x04ad, 0x0454, 0x0006, 0x0e70, 0x0611, 0x5616, 0xc13c, + 0x7d2a, 0x5ade, 0x008e, 0xc14e, 0x7c26, 0x5be0, 0x5ef0, 0x5ce8, + 0x0688, 0x08ff, 0x0011, 0x28ff, 0x00bc, 0x53f6, 0x05df, 0x7d0b, + 0x6dc5, 0x03df, 0x7d03, 0x6bd5, 0xd903, 0x98df, 0x6b05, 0xc5f5, + 0x7e27, 0x7f29, 0x98df, 0x6d01, 0x03df, 0x7d05, 0x6bd5, 0xc61f, + 0x7e18, 0x7f1a, 0x98df, 0x6b05, 0xc595, 0x7e07, 0x7f06, 0x52de, + 0x53e6, 0xc159, 0x7dd7, 0x0200, 0x98b7, 0x0007, 0x6004, 0x680c, + 0x53f6, 0x028e, 0x00a3, 0xc256, 0x048b, 0x0498, 0x0454, 0x068a, + 0x98df, 0x0207, 0x680c, 0x6ddf, 0x0107, 0x68ff, 0x60d0, 0x98e8, + 0x0207, 0x68ff, 0x6d28, 0x0107, 0x6004, 0x680c, 0x98e8, 0x0007, + 0x68ff, 0x60d0, 0x98e8, 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, 0x047a, 0x7d06, 0x0479, 0x7c02, 0x6ac6, + 0x993c, 0x6ac7, 0x993c, 0x6a01, 0x008f, 0x00d5, 0x7d01, 0x008d, + 0x05a0, 0x5deb, 0x56fb, 0x0478, 0x7d4e, 0x0479, 0x7c1f, 0x0015, + 0x0388, 0x047a, 0x7d03, 0x62c8, 0x7e39, 0x9950, 0x620a, 0x7e38, + 0x0808, 0x7801, 0x0217, 0x5a06, 0x7f34, 0x2301, 0x047a, 0x7d03, + 0x62c8, 0x7e2c, 0x995d, 0x620a, 0x7e2b, 0x0808, 0x7801, 0x0217, + 0x5a26, 0x7f27, 0x2301, 0x4b00, 0x7ce4, 0x997c, 0x0015, 0x0015, + 0x0015, 0x047a, 0x7d09, 0x7806, 0x0b00, 0x62c8, 0x5a06, 0x0b01, + 0x62c8, 0x5a26, 0x7c13, 0x997c, 0x7806, 0x0b00, 0x620b, 0x5a06, + 0x0b01, 0x620b, 0x5a26, 0x7c0c, 0x0b70, 0x0311, 0x5313, 0x0000, + 0x55eb, 0x4d00, 0x7d11, 0xc1fa, 0x57db, 0x993c, 0x68cc, 0x9989, + 0x680c, 0x0007, 0x0479, 0x7c02, 0x008b, 0x9990, 0x0017, 0x00a3, + 0x0b70, 0x0311, 0x5313, 0xc213, 0xc20a, 0x9931, 0x0b70, 0x0311, + 0x5313, 0x076c, 0x7c01, 0xc1d9, 0x5efb, 0x068a, 0x076b, 0x7c01, + 0xc1d9, 0x5ef3, 0x59db, 0x58d3, 0x018f, 0x0110, 0x390f, 0x008b, + 0xc13c, 0x7d2b, 0x5ac0, 0x5bc8, 0xc14e, 0x7c27, 0x0388, 0x0689, + 0x5ce3, 0x0dff, 0x0511, 0x1dff, 0x05bc, 0x073e, 0x4d00, 0x7d18, + 0x0870, 0x0011, 0x077e, 0x7d09, 0x077d, 0x7d02, 0x5228, 0x99c1, + 0x52f8, 0x54db, 0x02bc, 0x02cc, 0x7c09, 0x077c, 0x7d02, 0x5228, + 0x99ca, 0x52f8, 0x54d3, 0x02bc, 0x02cc, 0x7d09, 0x0400, 0x99b8, + 0x008b, 0x52c0, 0x53c8, 0xc159, 0x7dd6, 0x0200, 0x99a8, 0x08ff, + 0x00bf, 0x077f, 0x7d15, 0x0488, 0x00d5, 0x7d01, 0x008d, 0x05a0, + 0x5deb, 0x028f, 0x0212, 0x0212, 0x3aff, 0x05da, 0x7c02, 0x073e, + 0x99f3, 0x02a4, 0x02dd, 0x7d02, 0x073e, 0x99f3, 0x075e, 0x99f3, + 0x55eb, 0x0598, 0x5deb, 0x52f3, 0x54fb, 0x076a, 0x7d26, 0x076c, + 0x7d01, 0x9a30, 0x076b, 0x7c57, 0x0769, 0x7d04, 0x0768, 0x7d02, + 0x0e01, 0x9a0a, 0x5893, 0x00d6, 0x7d01, 0x008e, 0x5593, 0x05a0, + 0x5d93, 0x06a0, 0x7802, 0x5502, 0x5d04, 0x7c1d, 0x4e00, 0x7c08, + 0x0769, 0x7d03, 0x5502, 0x7e17, 0x9a17, 0x5d04, 0x7f14, 0x0689, + 0x5093, 0x4800, 0x7d01, 0x9a02, 0x9a7b, 0x0015, 0x7806, 0x5502, + 0x5d04, 0x074f, 0x5502, 0x5d24, 0x072f, 0x7c01, 0x9a7b, 0x0017, + 0x076f, 0x7c01, 0x2001, 0x5593, 0x009d, 0x0007, 0xda82, 0x99d0, + 0x6cd3, 0x0769, 0x7d04, 0x0768, 0x7d02, 0x0e01, 0x9a3f, 0x5893, + 0x00d6, 0x7d01, 0x008e, 0x5593, 0x05a0, 0x5d93, 0x06a0, 0x7802, + 0x5502, 0x6dc8, 0x7c0f, 0x4e00, 0x7c08, 0x0769, 0x7d03, 0x5502, + 0x7e09, 0x9a4c, 0x6dc8, 0x7f06, 0x0689, 0x5093, 0x4800, 0x7d01, + 0x9a37, 0x9a7b, 0x9a75, 0x6ac3, 0x0769, 0x7d04, 0x0768, 0x7d02, + 0x0e01, 0x9a62, 0x5893, 0x00d6, 0x7d01, 0x008e, 0x5593, 0x05a0, + 0x5d93, 0x06a0, 0x7802, 0x65c8, 0x5d04, 0x7c0f, 0x4e00, 0x7c08, + 0x0769, 0x7d03, 0x65c8, 0x7e09, 0x9a6f, 0x5d04, 0x7f06, 0x0689, + 0x5093, 0x4800, 0x7d01, 0x9a5a, 0x9a7b, 0x5593, 0x009d, 0x0007, + 0x6cff, 0xda82, 0x99d0, 0x0000, 0x54e3, 0x55eb, 0x4d00, 0x7c01, + 0x99d0, 0x99b8, 0x54e3, 0x55eb, 0x0aff, 0x0211, 0x1aff, 0x077f, + 0x7c02, 0x05a0, 0x9a8f, 0x009d, 0x058c, 0x05ba, 0x05a0, 0x0210, + 0x04ba, 0x04ad, 0x0454, 0x0006, 0xc1e3, 0x57db, 0x52f3, 0x6ac5, + 0x52fb, 0x6ad3, 0x008f, 0x00d5, 0x7d01, 0x008d, 0x05a0, 0x5deb, + 0x0478, 0x7d03, 0x0479, 0x7d20, 0x7c25, 0x0479, 0x7c19, 0x59e3, + 0x56ee, 0x61c8, 0x7e2e, 0x62c8, 0x7e2c, 0x65c8, 0x7e2a, 0x0660, + 0x7d03, 0x0112, 0x0112, 0x9ab6, 0x0512, 0x0512, 0x0211, 0x02a9, + 0x02ad, 0x6ac8, 0x7f1e, 0x2003, 0x4800, 0x7ceb, 0x51e3, 0x9ad0, + 0x7802, 0x62c8, 0x6ac8, 0x9acf, 0x6dce, 0x0015, 0x7802, 0x62c8, + 0x6ac8, 0x9acf, 0x6dcf, 0x0015, 0x0015, 0x7801, 0x62d8, 0x7c09, + 0x6ddf, 0x7f07, 0x0000, 0x55eb, 0x4d00, 0x7d06, 0xc1fa, 0x57db, + 0x9a9a, 0x0007, 0x68ff, 0xc213, 0xc20a, 0x9a95, 0xc1d9, 0xc1e3, + 0x57db, 0x52f3, 0x047a, 0x7d02, 0x6ad7, 0x9ae7, 0x6a05, 0x008f, + 0x00d5, 0x7d01, 0x008d, 0x05a0, 0x56fb, 0x0015, 0x0015, 0x0015, + 0x047a, 0x7d07, 0x7804, 0x5206, 0x6ac8, 0x5226, 0x6ac8, 0x7c0f, + 0x9b01, 0x7804, 0x5206, 0x6a0b, 0x5226, 0x6a0b, 0x7c0a, 0x6a28, + 0x7f08, 0x0000, 0x4d00, 0x7d07, 0xc1fa, 0x57db, 0x9ae7, 0xc273, + 0x9b0a, 0xc277, 0x0454, 0xc20a, 0x9ae0, 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, 0x9b52, 0x6ee3, 0x008f, + 0x2001, 0x00d5, 0x7d01, 0x008d, 0x05a0, 0x62c8, 0x026e, 0x7d0e, + 0x6ac8, 0x7f0a, 0x2001, 0x7cf9, 0x6add, 0x7f06, 0x0000, 0x4d00, + 0x7d09, 0xc1fa, 0x57db, 0x9b11, 0x0007, 0x6aff, 0x62d0, 0xc27a, + 0x0458, 0x0454, 0x6add, 0x7ff8, 0xc20a, 0x9b0e, 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, 0x9b95, + 0x008f, 0x2001, 0x00d5, 0x7d01, 0x008d, 0x05a0, 0x5206, 0x026e, + 0x7d0e, 0x6ac8, 0x7f0a, 0x2001, 0x7cf9, 0x6add, 0x7f06, 0x0000, + 0x4d00, 0x7d0b, 0xc1fa, 0x57db, 0x9b5b, 0x0007, 0x6aff, 0x6add, + 0x7ffc, 0x62d0, 0xc27a, 0x0458, 0x0454, 0x6add, 0x7ff6, 0xc20a, + 0x9b58 +}; +#endif diff --git a/arch/arm/mach-mx35/sdma_script_code_v2.h b/arch/arm/mach-mx35/sdma_script_code_v2.h new file mode 100644 index 000000000000..1bd949e6c992 --- /dev/null +++ b/arch/arm/mach-mx35/sdma_script_code_v2.h @@ -0,0 +1,234 @@ +/* + * 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: "SDMA_RINGO.03.00.00" + +*******************************************************************************/ + +#ifndef SDMA_SCRIPT_CODE_V2_H +#define SDMA_SCRIPT_CODE_V2_H + +/*! +* SDMA ROM scripts start addresses and sizes +*/ + +#define start_ADDR_V2 0 +#define start_SIZE_V2 24 + +#define core_ADDR_V2 80 +#define core_SIZE_V2 233 + +#define common_ADDR_V2 313 +#define common_SIZE_V2 416 + +#define ap_2_ap_ADDR_V2 729 +#define ap_2_ap_SIZE_V2 41 + +#define app_2_mcu_ADDR_V2 770 +#define app_2_mcu_SIZE_V2 64 + +#define mcu_2_app_ADDR_V2 834 +#define mcu_2_app_SIZE_V2 70 + +#define uart_2_mcu_ADDR_V2 904 +#define uart_2_mcu_SIZE_V2 75 + +#define shp_2_mcu_ADDR_V2 979 +#define shp_2_mcu_SIZE_V2 69 + +#define mcu_2_shp_ADDR_V2 1048 +#define mcu_2_shp_SIZE_V2 72 + +#define per_2_shp_ADDR_V2 1120 +#define per_2_shp_SIZE_V2 78 + +#define shp_2_per_ADDR_V2 1198 +#define shp_2_per_SIZE_V2 72 + +#define uartsh_2_mcu_ADDR_V2 1270 +#define uartsh_2_mcu_SIZE_V2 69 + +#define mcu_2_ata_ADDR_V2 1339 +#define mcu_2_ata_SIZE_V2 90 + +#define ata_2_mcu_ADDR_V2 1429 +#define ata_2_mcu_SIZE_V2 102 + +#define app_2_per_ADDR_V2 1531 +#define app_2_per_SIZE_V2 66 + +#define per_2_app_ADDR_V2 1597 +#define per_2_app_SIZE_V2 74 + +#define loop_DMAs_routines_ADDR_V2 1671 +#define loop_DMAs_routines_SIZE_V2 240 + +#define test_ADDR_V2 1911 +#define test_SIZE_V2 63 + +#define signature_ADDR_V2 1022 +#define signature_SIZE_V2 1 + +/*! +* SDMA RAM scripts start addresses and sizes +*/ + +#define asrc__mcu_ADDR_V2 6144 +#define asrc__mcu_SIZE_V2 116 + +#define ext_mem__ipu_ram_ADDR_V2 6260 +#define ext_mem__ipu_ram_SIZE_V2 123 + +#define mcu_2_spdif_ADDR_V2 6383 +#define mcu_2_spdif_SIZE_V2 103 + +#define p_2_p_ADDR_V2 6486 +#define p_2_p_SIZE_V2 260 + +#define spdif_2_mcu_ADDR_V2 6746 +#define spdif_2_mcu_SIZE_V2 47 + +#define uart_2_per_ADDR_V2 6793 +#define uart_2_per_SIZE_V2 73 + +#define uartsh_2_per_ADDR_V2 6866 +#define uartsh_2_per_SIZE_V2 67 + +/*! +* SDMA RAM image start address and size +*/ + +#define RAM_CODE_START_ADDR_V2 6144 +#define RAM_CODE_SIZE_V2 789 + +/*! +* Buffer that holds the SDMA RAM image +*/ + +static const short sdma_code_v2[] = { + 0xc230, 0xc23a, 0x56f3, 0x57db, 0x047a, 0x7d07, 0x072f, 0x076e, + 0x7d02, 0x6ec7, 0x9813, 0x6ed7, 0x9813, 0x074f, 0x076e, 0x7d02, + 0x6e01, 0x9813, 0x6e05, 0x5ce3, 0x048f, 0x0410, 0x3c0f, 0x5c93, + 0x0e03, 0x0611, 0x1eff, 0x06bf, 0x06d5, 0x7d01, 0x068d, 0x05a6, + 0x5deb, 0x55fb, 0x008e, 0x076a, 0x7d02, 0x076b, 0x7c04, 0x06d4, + 0x7d01, 0x008c, 0x04a0, 0x06a0, 0x076f, 0x7d0c, 0x076e, 0x7d05, + 0x7802, 0x62c8, 0x5a05, 0x7c2b, 0x9847, 0x7802, 0x5205, 0x6ac8, + 0x7c26, 0x9847, 0x076e, 0x7d05, 0x7802, 0x620b, 0x5a05, 0x7c21, + 0x9847, 0x7802, 0x5205, 0x6a0b, 0x7c1c, 0x6a28, 0x7f1a, 0x076a, + 0x7d02, 0x076b, 0x7c0a, 0x4c00, 0x7c08, 0x076a, 0x7d03, 0x5a05, + 0x7f11, 0x9854, 0x5205, 0x7e0e, 0x5493, 0x4e00, 0x7ccb, 0x0000, + 0x54e3, 0x55eb, 0x4d00, 0x7d0a, 0xc251, 0x57db, 0x9814, 0x68cc, + 0x9862, 0x680c, 0x009e, 0x0007, 0x54e3, 0xd868, 0xc261, 0x9802, + 0x55eb, 0x009d, 0x058c, 0x0aff, 0x0211, 0x1aff, 0x05ba, 0x05a0, + 0x04b2, 0x04ad, 0x0454, 0x0006, 0x0e70, 0x0611, 0x5616, 0xc18a, + 0x7d2a, 0x5ade, 0x008e, 0xc19c, 0x7c26, 0x5be0, 0x5ef0, 0x5ce8, + 0x0688, 0x08ff, 0x0011, 0x28ff, 0x00bc, 0x53f6, 0x05df, 0x7d0b, + 0x6dc5, 0x03df, 0x7d03, 0x6bd5, 0xd8c3, 0x989f, 0x6b05, 0xc6e7, + 0x7e27, 0x7f29, 0x989f, 0x6d01, 0x03df, 0x7d05, 0x6bd5, 0xc711, + 0x7e18, 0x7f1a, 0x989f, 0x6b05, 0xc687, 0x7e07, 0x7f06, 0x52de, + 0x53e6, 0xc1a8, 0x7dd7, 0x0200, 0x9877, 0x0007, 0x6004, 0x680c, + 0x53f6, 0x028e, 0x00a3, 0xc2ad, 0x048b, 0x0498, 0x0454, 0x068a, + 0x989f, 0x0207, 0x680c, 0x6ddf, 0x0107, 0x68ff, 0x60d0, 0x98a8, + 0x0207, 0x68ff, 0x6d28, 0x0107, 0x6004, 0x680c, 0x98a8, 0x0007, + 0x68ff, 0x60d0, 0x98a8, 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, 0xc230, + 0xc23a, 0x57db, 0x52f3, 0x047a, 0x7d06, 0x0479, 0x7c02, 0x6ac6, + 0x98fc, 0x6ac7, 0x98fc, 0x6a01, 0x008f, 0x00d5, 0x7d01, 0x008d, + 0x05a0, 0x5deb, 0x56fb, 0x0478, 0x7d4e, 0x0479, 0x7c1f, 0x0015, + 0x0388, 0x047a, 0x7d03, 0x62c8, 0x7e39, 0x9910, 0x620a, 0x7e38, + 0x0808, 0x7801, 0x0217, 0x5a06, 0x7f34, 0x2301, 0x047a, 0x7d03, + 0x62c8, 0x7e2c, 0x991d, 0x620a, 0x7e2b, 0x0808, 0x7801, 0x0217, + 0x5a26, 0x7f27, 0x2301, 0x4b00, 0x7ce4, 0x993c, 0x0015, 0x0015, + 0x0015, 0x047a, 0x7d09, 0x7806, 0x0b00, 0x62c8, 0x5a06, 0x0b01, + 0x62c8, 0x5a26, 0x7c13, 0x993c, 0x7806, 0x0b00, 0x620b, 0x5a06, + 0x0b01, 0x620b, 0x5a26, 0x7c0c, 0x0b70, 0x0311, 0x5313, 0x0000, + 0x55eb, 0x4d00, 0x7d11, 0xc251, 0x57db, 0x98fc, 0x68cc, 0x9949, + 0x680c, 0x0007, 0x0479, 0x7c02, 0x008b, 0x9950, 0x0017, 0x00a3, + 0x0b70, 0x0311, 0x5313, 0xc26a, 0xc261, 0x98f1, 0x0b70, 0x0311, + 0x5313, 0x076c, 0x7c01, 0xc230, 0x5efb, 0x068a, 0x076b, 0x7c01, + 0xc230, 0x5ef3, 0x59db, 0x58d3, 0x018f, 0x0110, 0x390f, 0x008b, + 0xc18a, 0x7d2b, 0x5ac0, 0x5bc8, 0xc19c, 0x7c27, 0x0388, 0x0689, + 0x5ce3, 0x0dff, 0x0511, 0x1dff, 0x05bc, 0x073e, 0x4d00, 0x7d18, + 0x0870, 0x0011, 0x077e, 0x7d09, 0x077d, 0x7d02, 0x5228, 0x9981, + 0x52f8, 0x54db, 0x02bc, 0x02cc, 0x7c09, 0x077c, 0x7d02, 0x5228, + 0x998a, 0x52f8, 0x54d3, 0x02bc, 0x02cc, 0x7d09, 0x0400, 0x9978, + 0x008b, 0x52c0, 0x53c8, 0xc1a8, 0x7dd6, 0x0200, 0x9968, 0x08ff, + 0x00bf, 0x077f, 0x7d1b, 0x0488, 0x00d5, 0x7d01, 0x008d, 0x05a0, + 0x5deb, 0x028f, 0x32ff, 0x0210, 0x32ff, 0x0210, 0x0212, 0x0217, + 0x0217, 0x32ff, 0x0212, 0x05da, 0x7c02, 0x073e, 0x99b9, 0x02a4, + 0x02dd, 0x7d02, 0x073e, 0x99b9, 0x075e, 0x99b9, 0x55eb, 0x0598, + 0x5deb, 0x52f3, 0x54fb, 0x076a, 0x7d26, 0x076c, 0x7d01, 0x99f6, + 0x076b, 0x7c57, 0x0769, 0x7d04, 0x0768, 0x7d02, 0x0e01, 0x99d0, + 0x5893, 0x00d6, 0x7d01, 0x008e, 0x5593, 0x05a0, 0x5d93, 0x06a0, + 0x7802, 0x5502, 0x5d04, 0x7c1d, 0x4e00, 0x7c08, 0x0769, 0x7d03, + 0x5502, 0x7e17, 0x99dd, 0x5d04, 0x7f14, 0x0689, 0x5093, 0x4800, + 0x7d01, 0x99c8, 0x9a41, 0x0015, 0x7806, 0x5502, 0x5d04, 0x074d, + 0x5502, 0x5d24, 0x072d, 0x7c01, 0x9a41, 0x0017, 0x076d, 0x7c01, + 0x2001, 0x5593, 0x009d, 0x0007, 0xda48, 0x9990, 0x6cd3, 0x0769, + 0x7d04, 0x0768, 0x7d02, 0x0e01, 0x9a05, 0x5893, 0x00d6, 0x7d01, + 0x008e, 0x5593, 0x05a0, 0x5d93, 0x06a0, 0x7802, 0x5502, 0x6dc8, + 0x7c0f, 0x4e00, 0x7c08, 0x0769, 0x7d03, 0x5502, 0x7e09, 0x9a12, + 0x6dc8, 0x7f06, 0x0689, 0x5093, 0x4800, 0x7d01, 0x99fd, 0x9a41, + 0x9a3b, 0x6ac3, 0x0769, 0x7d04, 0x0768, 0x7d02, 0x0e01, 0x9a28, + 0x5893, 0x00d6, 0x7d01, 0x008e, 0x5593, 0x05a0, 0x5d93, 0x06a0, + 0x7802, 0x65c8, 0x5d04, 0x7c0f, 0x4e00, 0x7c08, 0x0769, 0x7d03, + 0x65c8, 0x7e09, 0x9a35, 0x5d04, 0x7f06, 0x0689, 0x5093, 0x4800, + 0x7d01, 0x9a20, 0x9a41, 0x5593, 0x009d, 0x0007, 0x6cff, 0xda48, + 0x9990, 0x0000, 0x54e3, 0x55eb, 0x4d00, 0x7c01, 0x9990, 0x9978, + 0x54e3, 0x55eb, 0x0aff, 0x0211, 0x1aff, 0x077f, 0x7c02, 0x05a0, + 0x9a55, 0x009d, 0x058c, 0x05ba, 0x05a0, 0x0210, 0x04ba, 0x04ad, + 0x0454, 0x0006, 0xc230, 0xc23a, 0x57db, 0x52f3, 0x047a, 0x7d02, + 0x6ad7, 0x9a63, 0x6a05, 0x008f, 0x00d5, 0x7d01, 0x008d, 0x05a0, + 0x56fb, 0x0015, 0x0015, 0x0015, 0x047a, 0x7d07, 0x7804, 0x5206, + 0x6ac8, 0x5226, 0x6ac8, 0x7c0f, 0x9a7d, 0x7804, 0x5206, 0x6a0b, + 0x5226, 0x6a0b, 0x7c0a, 0x6a28, 0x7f08, 0x0000, 0x4d00, 0x7d07, + 0xc251, 0x57db, 0x9a63, 0xc2ca, 0x9a86, 0xc2ce, 0x0454, 0xc261, + 0x9a5c, 0xc23a, 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, + 0xc2d1, 0x9ace, 0x6ee3, 0x008f, 0x2001, 0x00d5, 0x7d01, 0x008d, + 0x05a0, 0x62c8, 0x026e, 0x7d0e, 0x6ac8, 0x7f0a, 0x2001, 0x7cf9, + 0x6add, 0x7f06, 0x0000, 0x4d00, 0x7d09, 0xc251, 0x57db, 0x9a8d, + 0x0007, 0x6aff, 0x62d0, 0xc2d1, 0x0458, 0x0454, 0x6add, 0x7ff8, + 0xc261, 0x9a8a, 0xc230, 0xc23a, 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, 0xc2d1, 0x9b11, 0x008f, 0x2001, 0x00d5, 0x7d01, + 0x008d, 0x05a0, 0x5206, 0x026e, 0x7d0e, 0x6ac8, 0x7f0a, 0x2001, + 0x7cf9, 0x6add, 0x7f06, 0x0000, 0x4d00, 0x7d0b, 0xc251, 0x57db, + 0x9ad7, 0x0007, 0x6aff, 0x6add, 0x7ffc, 0x62d0, 0xc2d1, 0x0458, + 0x0454, 0x6add, 0x7ff6, 0xc261, 0x9ad4 +}; +#endif diff --git a/arch/arm/mach-mx35/serial.c b/arch/arm/mach-mx35/serial.c new file mode 100644 index 000000000000..74068f1c39dd --- /dev/null +++ b/arch/arm/mach-mx35/serial.c @@ -0,0 +1,179 @@ +/* + * 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-mx35/serial.c + * + * @brief This file contains the UART initiliazation. + * + * @ingroup MSL_MX35 + */ +#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-mx35_3stack.h" + +#if defined(CONFIG_SERIAL_MXC) || defined(CONFIG_SERIAL_MXC_MODULE) + +/*! + * This is an array where each element holds information about a UART port, + * like base address of the UART, interrupt numbers etc. This structure is + * passed to the serial_core.c file. Based on which UART is used, the core file + * passes back the appropriate port structure as an argument to the control + * functions. + */ +static uart_mxc_port mxc_ports[] = { + [0] = { + .port = { + .membase = (void *)IO_ADDRESS(UART1_BASE_ADDR), + .mapbase = UART1_BASE_ADDR, + .iotype = SERIAL_IO_MEM, + .irq = UART1_INT1, + .fifosize = 32, + .flags = ASYNC_BOOT_AUTOCONF, + .line = 0, + }, + .ints_muxed = UART1_MUX_INTS, + .irqs = {UART1_INT2, UART1_INT3}, + .mode = UART1_MODE, + .ir_mode = UART1_IR, + .enabled = UART1_ENABLED, + .hardware_flow = UART1_HW_FLOW, + .cts_threshold = UART1_UCR4_CTSTL, + .dma_enabled = UART1_DMA_ENABLE, + .dma_rxbuf_size = UART1_DMA_RXBUFSIZE, + .rx_threshold = UART1_UFCR_RXTL, + .tx_threshold = UART1_UFCR_TXTL, + .shared = UART1_SHARED_PERI, + .dma_tx_id = MXC_DMA_UART1_TX, + .dma_rx_id = MXC_DMA_UART1_RX, + .rxd_mux = MXC_UART_RXDMUX, + .ir_tx_inv = MXC_IRDA_TX_INV, + .ir_rx_inv = MXC_IRDA_RX_INV, + }, + [1] = { + .port = { + .membase = (void *)IO_ADDRESS(UART2_BASE_ADDR), + .mapbase = UART2_BASE_ADDR, + .iotype = SERIAL_IO_MEM, + .irq = UART2_INT1, + .fifosize = 32, + .flags = ASYNC_BOOT_AUTOCONF, + .line = 1, + }, + .ints_muxed = UART2_MUX_INTS, + .irqs = {UART2_INT2, UART2_INT3}, + .mode = UART2_MODE, + .ir_mode = UART2_IR, + .enabled = UART2_ENABLED, + .hardware_flow = UART2_HW_FLOW, + .cts_threshold = UART2_UCR4_CTSTL, + .dma_enabled = UART2_DMA_ENABLE, + .dma_rxbuf_size = UART2_DMA_RXBUFSIZE, + .rx_threshold = UART2_UFCR_RXTL, + .tx_threshold = UART2_UFCR_TXTL, + .shared = UART2_SHARED_PERI, + .dma_tx_id = MXC_DMA_UART2_TX, + .dma_rx_id = MXC_DMA_UART2_RX, + .rxd_mux = MXC_UART_IR_RXDMUX, + .ir_tx_inv = MXC_IRDA_TX_INV, + .ir_rx_inv = MXC_IRDA_RX_INV, + }, +#if UART3_ENABLED == 1 + [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, + .ir_tx_inv = MXC_IRDA_TX_INV, + .ir_rx_inv = MXC_IRDA_RX_INV, + }, +#endif +}; + +static struct platform_device mxc_uart_device1 = { + .name = "mxcintuart", + .id = 0, + .dev = { + .platform_data = &mxc_ports[0], + }, +}; + +static struct platform_device mxc_uart_device2 = { + .name = "mxcintuart", + .id = 1, + .dev = { + .platform_data = &mxc_ports[1], + }, +}; + +#if UART3_ENABLED == 1 +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 */ + platform_device_register(&mxc_uart_device1); + platform_device_register(&mxc_uart_device2); + + /* Grab ownership of shared UARTs 3 and 4, only when enabled */ +#if UART3_ENABLED == 1 +#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-mx35/serial.h b/arch/arm/mach-mx35/serial.h new file mode 100644 index 000000000000..467a4a437525 --- /dev/null +++ b/arch/arm/mach-mx35/serial.h @@ -0,0 +1,132 @@ +/* + * 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_MX35_SERIAL_H__ +#define __ARCH_ARM_MACH_MX35_SERIAL_H__ + +/*! + * @file mach-mx35/serial.h + * + * @ingroup MSL_MX35 + */ +#include <mach/mxc_uart.h> + +/* UART 1 configuration */ +/*! + * This option allows to choose either an interrupt-driven software controlled + * hardware flow control (set this option to 0) or hardware-driven hardware + * flow control (set this option to 1). + */ +#define UART1_HW_FLOW 1 +/*! + * This specifies the threshold at which the CTS pin is deasserted by the + * RXFIFO. Set this value in Decimal to anything from 0 to 32 for + * hardware-driven hardware flow control. Read the HW spec while specifying + * this value. When using interrupt-driven software controlled hardware + * flow control set this option to -1. + */ +#define UART1_UCR4_CTSTL 16 +/*! + * This is option to enable (set this option to 1) or disable DMA data transfer + */ +#define UART1_DMA_ENABLE 0 +/*! + * Specify the size of the DMA receive buffer. The 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 1 +#define UART2_UCR4_CTSTL 16 +#define UART2_DMA_ENABLE 0 +#define UART2_DMA_RXBUFSIZE 1024 +#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_MX35_SERIAL_H__ */ diff --git a/arch/arm/mach-mx35/system.c b/arch/arm/mach-mx35/system.c new file mode 100644 index 000000000000..71a4e8c27599 --- /dev/null +++ b/arch/arm/mach-mx35/system.c @@ -0,0 +1,126 @@ +/* + * 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/clk.h> +#include <linux/module.h> +#include <linux/io.h> +#include <mach/hardware.h> +#include <asm/proc-fns.h> +#include <asm/system.h> +#include <mach/clock.h> +#include <mach/hardware.h> +#include "crm_regs.h" + +/*! + * @defgroup MSL_MX35 i.MX35 Machine Specific Layer (MSL) + */ + +/*! + * @file mach-mx35/system.c + * @brief This file contains idle and reset functions. + * + * @ingroup MSL_MX35 + */ + +/*! +* MX35 low-power mode +*/ +enum mx35_low_pwr_mode { + MX35_RUN_MODE, + MX35_WAIT_MODE, + MX35_DOZE_MODE, + MX35_STOP_MODE +}; + +extern int mxc_jtag_enabled; + +/*! + * This function is used to set cpu low power mode before WFI instruction + * + * @param mode indicates different kinds of power modes + */ +void mxc_cpu_lp_set(enum mxc_cpu_pwr_mode mode) +{ + unsigned int lpm; + unsigned long reg; + + /*read CCMR value */ + reg = __raw_readl(MXC_CCM_CCMR); + + switch (mode) { + case WAIT_UNCLOCKED_POWER_OFF: + lpm = MX35_DOZE_MODE; + break; + + case STOP_POWER_ON: + case STOP_POWER_OFF: + lpm = MX35_STOP_MODE; + /* Enabled Well Bias */ + reg |= MXC_CCM_CCMR_WBEN; + if (!board_is_rev(BOARD_REV_1)) + reg |= MXC_CCM_CCMR_VSTBY; + break; + + case WAIT_CLOCKED: + case WAIT_UNCLOCKED: + default: + /* Wait is the default mode used when idle. */ + lpm = MX35_WAIT_MODE; + break; + } + + /* program LPM bit */ + reg = (reg & (~MXC_CCM_CCMR_LPM_MASK)) | lpm << MXC_CCM_CCMR_LPM_OFFSET; + /* program Interrupt holdoff bit */ + reg = reg | MXC_CCM_CCMR_WFI; + /* TBD: PMIC has put the voltage back to Normal if the voltage ready */ + /* counter finished */ + reg = reg | MXC_CCM_CCMR_STBY_EXIT_SRC; + + __raw_writel(reg, MXC_CCM_CCMR); +} + +EXPORT_SYMBOL(mxc_cpu_lp_set); + +/*! + * This function puts the CPU into idle mode. It is called by default_idle() + * in process.c file. + */ +void arch_idle(void) +{ + /* + * This should do all the clock switching + * and wait for interrupt tricks. + */ + if (!mxc_jtag_enabled) { +#ifdef CONFIG_MX35_DOZE_DURING_IDLE + /*set as Doze mode */ + mxc_cpu_lp_set(WAIT_UNCLOCKED_POWER_OFF); +#else + /* set as Wait mode */ + mxc_cpu_lp_set(WAIT_UNCLOCKED); +#endif + cpu_do_idle(); + } +} + +/* + * This function resets the system. It is called by machine_restart(). + * + * @param mode indicates different kinds of resets + */ +void arch_reset(char mode) +{ + /* Assert SRS signal */ + mxc_wd_reset(); +} diff --git a/arch/arm/mach-mx35/usb.h b/arch/arm/mach-mx35/usb.h new file mode 100644 index 000000000000..52b6f803bb50 --- /dev/null +++ b/arch/arm/mach-mx35/usb.h @@ -0,0 +1,104 @@ +/* + * Copyright 2005-2008 Freescale Semiconductor, Inc. All Rights Reserved. + */ + +/* + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ + + +extern int usbotg_init(struct platform_device *pdev); +extern void usbotg_uninit(struct fsl_usb2_platform_data *pdata); +extern 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_usbh2_active(void); +extern void gpio_usbh2_inactive(void); +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. + */ +static struct fsl_usb2_platform_data __maybe_unused dr_utmi_config; +#define PDATA (&dr_utmi_config) + + +/* + * 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-mx35/usb_dr.c b/arch/arm/mach-mx35/usb_dr.c new file mode 100644 index 000000000000..18f76b90907a --- /dev/null +++ b/arch/arm/mach-mx35/usb_dr.c @@ -0,0 +1,110 @@ +/* + * Copyright 2005-2009 Freescale Semiconductor, Inc. All Rights Reserved. + */ + +/* + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ + +#include <linux/kernel.h> +#include <linux/types.h> +#include <linux/platform_device.h> +#include <linux/fsl_devices.h> +#include <mach/hardware.h> +#include <mach/arc_otg.h> +#include "usb.h" + +/* + * platform data structs + * - Which one to use is determined by CONFIG options in usb.h + * - operating_mode plugged at run time + */ +static struct fsl_usb2_platform_data __maybe_unused dr_utmi_config = { + .name = "DR", + .platform_init = usbotg_init, + .platform_uninit = usbotg_uninit, + .phy_mode = FSL_USB2_PHY_UTMI_WIDE, + .power_budget = 500, /* 500 mA max power */ + .gpio_usb_active = gpio_usbotg_utmi_active, + .gpio_usb_inactive = gpio_usbotg_utmi_inactive, + .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_USBOTG, + .flags = IORESOURCE_IRQ, + }, +}; + + +static u64 dr_udc_dmamask = ~(u32) 0; +static void dr_udc_release(struct device *dev) +{ +} + +static u64 dr_otg_dmamask = ~(u32) 0; +static void dr_otg_release(struct device *dev) +{ +} + +/* + * platform device structs + * dev.platform_data field plugged at run time + */ +static struct platform_device __maybe_unused dr_udc_device = { + .name = "fsl-usb2-udc", + .id = -1, + .dev = { + .release = dr_udc_release, + .dma_mask = &dr_udc_dmamask, + .coherent_dma_mask = 0xffffffff, + }, + .resource = otg_resources, + .num_resources = ARRAY_SIZE(otg_resources), +}; + +static struct platform_device __maybe_unused dr_otg_device = { + .name = "fsl-usb2-otg", + .id = -1, + .dev = { + .release = dr_otg_release, + .dma_mask = &dr_otg_dmamask, + .coherent_dma_mask = 0xffffffff, + }, + .resource = otg_resources, + .num_resources = ARRAY_SIZE(otg_resources), +}; + +static int __init usb_dr_init(void) +{ + pr_debug("%s: \n", __func__); + + /* i.MX35 1.0 should work in INCR mode */ + if (cpu_is_mx35_rev(CHIP_REV_2_0) < 0) { + PDATA->change_ahb_burst = 1; + PDATA->ahb_burst_mode = 0; + } + + 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-mx35/usb_h2.c b/arch/arm/mach-mx35/usb_h2.c new file mode 100644 index 000000000000..3590dc5daf1d --- /dev/null +++ b/arch/arm/mach-mx35/usb_h2.c @@ -0,0 +1,63 @@ +/* + * Copyright 2005-2009 Freescale Semiconductor, Inc. All Rights Reserved. + */ + +/* + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ + +#include <linux/kernel.h> +#include <linux/types.h> +#include <linux/platform_device.h> +#include <linux/fsl_devices.h> +#include <linux/usb/fsl_xcvr.h> + +#include <mach/hardware.h> +#include <mach/arc_otg.h> +#include "usb.h" + +static struct fsl_usb2_platform_data usbh2_config = { + .name = "Host 2", + .platform_init = fsl_usb_host_init, + .platform_uninit = fsl_usb_host_uninit, + .operating_mode = FSL_USB2_MPH_HOST, + .phy_mode = FSL_USB2_PHY_SERIAL, + .power_budget = 500, /* 500 mA max power */ + .gpio_usb_active = gpio_usbh2_active, + .gpio_usb_inactive = gpio_usbh2_inactive, + .transceiver = "serial", +}; + +static struct resource usbh2_resources[] = { + [0] = { + .start = (u32) (USB_H2REGS_BASE), + .end = (u32) (USB_H2REGS_BASE + 0x1ff), + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = MXC_INT_USBHS, + .flags = IORESOURCE_IRQ, + }, +}; + + +static int __init usbh2_init(void) +{ + pr_debug("%s: \n", __func__); + + /* i.MX35 1.0 should work in INCR mode */ + if (cpu_is_mx35_rev(CHIP_REV_2_0) < 0) { + usbh2_config.change_ahb_burst = 1; + usbh2_config.ahb_burst_mode = 0; + } + + host_pdev_register(usbh2_resources, ARRAY_SIZE(usbh2_resources), + &usbh2_config); + return 0; +} +module_init(usbh2_init); |