summaryrefslogtreecommitdiff
path: root/arch/arm/mach-mvf
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-mvf')
-rw-r--r--arch/arm/mach-mvf/Kconfig45
-rw-r--r--arch/arm/mach-mvf/Makefile1
-rw-r--r--arch/arm/mach-mvf/board-colibri_vf.c734
-rw-r--r--arch/arm/mach-mvf/clock.c316
-rw-r--r--arch/arm/mach-mvf/crm_regs.h9
-rw-r--r--arch/arm/mach-mvf/mvf_fec.c2
-rw-r--r--arch/arm/mach-mvf/system.c73
7 files changed, 1082 insertions, 98 deletions
diff --git a/arch/arm/mach-mvf/Kconfig b/arch/arm/mach-mvf/Kconfig
index 931ef6af6dd4..a19fa1bae723 100644
--- a/arch/arm/mach-mvf/Kconfig
+++ b/arch/arm/mach-mvf/Kconfig
@@ -25,6 +25,51 @@ config FORCE_MAX_ZONEORDER
config SOC_MVFA5
bool
+config MACH_COLIBRI_VF50
+ bool "Support Toradex Colibri VF50 module"
+ select COLIBRI_VF
+ help
+ Include support for Toradex Colibri VF50 module on Iris carrier board. This
+ includes specific configurations for the board and its peripherals.
+
+config MACH_COLIBRI_VF61
+ bool "Support Toradex Colibri VF61 module"
+ select COLIBRI_VF
+ help
+ Include support for Toradex Colibri VF61 module on Iris carrier board. This
+ includes specific configurations for the board and its peripherals.
+
+config COLIBRI_VF
+ bool
+ select ARCH_MVFA5
+ select SOC_MVFA5
+ select IMX_HAVE_PLATFORM_IMX_UART
+ select IMX_HAVE_PLATFORM_DMA
+ select IMX_HAVE_PLATFORM_FEC
+ select IMX_HAVE_PLATFORM_GPMI_NFC
+ select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
+ select IMX_HAVE_PLATFORM_IMX_I2C
+ select IMX_HAVE_PLATFORM_VIV_GPU
+ select IMX_HAVE_PLATFORM_IMX_VPU
+ select IMX_HAVE_PLATFORM_IMX_SSI
+ select IMX_HAVE_PLATFORM_FSL_USB2_UDC
+ select IMX_HAVE_PLATFORM_MXC_EHCI
+ select IMX_HAVE_PLATFORM_FSL_OTG
+ select IMX_HAVE_PLATFORM_FSL_USB_WAKEUP
+ select IMX_HAVE_PLATFORM_AHCI
+ select IMX_HAVE_PLATFORM_IMX_OCOTP
+ select IMX_HAVE_PLATFORM_IMX2_WDT
+ select IMX_HAVE_PLATFORM_IMX_SNVS_RTC
+ select IMX_HAVE_PLATFORM_IMX_PM
+ select IMX_HAVE_PLATFORM_MXC_HDMI
+ select IMX_HAVE_PLATFORM_IMX_ASRC
+ select IMX_HAVE_PLATFORM_FLEXCAN
+ select IMX_HAVE_PLATFORM_MVF_SPI
+ select IMX_HAVE_PLATFORM_MVF_DCU
+ select IMX_HAVE_PLATFORM_MVF_SAI
+ select IMX_HAVE_PLATFORM_MXC_NAND
+ select IMX_HAVE_PLATFORM_MVF_CAAM
+
config MACH_MVFA5_TWR_VF700
bool "Support MVF CORTEX-A5 TWR-VF700 platform"
select ARCH_MVFA5
diff --git a/arch/arm/mach-mvf/Makefile b/arch/arm/mach-mvf/Makefile
index fdbd22479609..373166a97adc 100644
--- a/arch/arm/mach-mvf/Makefile
+++ b/arch/arm/mach-mvf/Makefile
@@ -7,4 +7,5 @@ obj-y := cpu.o mm.o system.o devices.o dummy_gpio.o irq.o bus_freq.o mvf_fec.o
obj-y += l2switch.o
obj-$(CONFIG_ARCH_MVFA5) += clock.o mvf_suspend.o
+obj-$(CONFIG_COLIBRI_VF) += board-colibri_vf.o
obj-$(CONFIG_MACH_MVFA5_TWR_VF700) += board-twr-vf700.o
diff --git a/arch/arm/mach-mvf/board-colibri_vf.c b/arch/arm/mach-mvf/board-colibri_vf.c
new file mode 100644
index 000000000000..782d8d7b2ddd
--- /dev/null
+++ b/arch/arm/mach-mvf/board-colibri_vf.c
@@ -0,0 +1,734 @@
+/*
+ * Copyright 2013 Toradex, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/init.h>
+#include <linux/input.h>
+#include <linux/nodemask.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/fsl_devices.h>
+#include <linux/spi/spi.h>
+#include <linux/i2c.h>
+#include <linux/pmic_external.h>
+#include <linux/pmic_status.h>
+#include <linux/pwm_backlight.h>
+#include <linux/leds_pwm.h>
+#include <linux/fec.h>
+#include <linux/memblock.h>
+#include <linux/gpio.h>
+#include <linux/etherdevice.h>
+#include <linux/regulator/anatop-regulator.h>
+#include <linux/regulator/consumer.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/fixed.h>
+#include <linux/input/fusion_F0710A.h>
+#include <linux/can/platform/mcp251x.h>
+#include <sound/pcm.h>
+
+#include <mach/common.h>
+#include <mach/hardware.h>
+#include <mach/memory.h>
+#include <mach/iomux-mvf.h>
+#include <mach/spi-mvf.h>
+#include <mach/mxc_asrc.h>
+#include <mach/mxc.h>
+#include <mach/colibri-ts.h>
+#include <asm/irq.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+
+#include "devices-mvf.h"
+#include "regs-pm.h"
+#include "usb.h"
+#include "crm_regs.h"
+
+#define MVF600_SD1_CD 42
+
+#define colibri_vf50_bl_enb 45 /* BL_ON */
+
+static iomux_v3_cfg_t mvf600_pads[] = {
+ /* SDHC1: MMC/SD */
+ MVF600_PAD14_PTA24__SDHC1_CLK,
+ MVF600_PAD15_PTA25__SDHC1_CMD,
+ MVF600_PAD16_PTA26__SDHC1_DAT0,
+ MVF600_PAD17_PTA27__SDHC1_DAT1,
+ MVF600_PAD18_PTA28__SDHC1_DAT2,
+ MVF600_PAD19_PTA29__SDHC1_DAT3,
+ /* set PTB20 as GPIO for sdhc card detecting */
+ MVF600_PAD42_PTB20__SDHC1_SW_CD,
+
+ /* I2C0: I2C_SDA/SCL on SODIMM pin 194/196 (e.g. RTC on carrier board)
+ */
+ MVF600_PAD36_PTB14__I2C0_SCL,
+ MVF600_PAD37_PTB15__I2C0_SDA,
+
+#if 0 /* optional secondary pinmux */
+ /* CAN0 */
+ MVF600_PAD36_PTB14__CAN0_RX, /* conflicts with
+ MVF600_PAD36_PTB14__I2C0_SCL */
+ MVF600_PAD37_PTB15__CAN0_TX, /* conflicts with
+ MVF600_PAD37_PTB15__I2C0_SDA */
+
+ /*CAN1*/
+ MVF600_PAD38_PTB16__CAN1_RX, /* conflicts with
+ MVF600_PAD38_PTB16_GPIO */
+ MVF600_PAD39_PTB17__CAN1_TX, /* conflicts with
+ MVF600_PAD39_PTB17_GPIO */
+#endif
+
+ /* DSPI1: SSP on SODIMM pin 86, 88, 90 and 92 */
+ MVF600_PAD84_PTD5__DSPI1_PCS0,
+ MVF600_PAD85_PTD6__DSPI1_SIN,
+ MVF600_PAD86_PTD7__DSPI1_SOUT,
+ MVF600_PAD87_PTD8__DSPI1_SCK,
+
+ /* GPIO for CAN Interrupt */
+ MVF600_PAD43_PTB21__CAN_INT,
+
+ /* FEC1: Ethernet */
+ MVF600_PAD0_PTA6__RMII_CLKOUT,
+ MVF600_PAD54_PTC9__RMII1_MDC,
+ MVF600_PAD55_PTC10__RMII1_MDIO,
+ MVF600_PAD56_PTC11__RMII1_CRS_DV,
+ MVF600_PAD57_PTC12__RMII1_RXD1,
+ MVF600_PAD58_PTC13__RMII1_RXD0,
+ MVF600_PAD59_PTC14__RMII1_RXER,
+ MVF600_PAD60_PTC15__RMII1_TXD1,
+ MVF600_PAD61_PTC16__RMII1_TXD0,
+ MVF600_PAD62_PTC17__RMII1_TXEN,
+
+ /* ADC */
+//ADC0_SE8
+//ADC0_SE9
+//ADC1_SE8
+//ADC1_SE9
+
+ /* DCU0: Display */
+ MVF600_PAD105_PTE0_DCU0_HSYNC,
+ MVF600_PAD106_PTE1_DCU0_VSYNC,
+ MVF600_PAD107_PTE2_DCU0_PCLK,
+ MVF600_PAD109_PTE4_DCU0_DE, /* L_BIAS */
+ MVF600_PAD110_PTE5_DCU0_R0,
+ MVF600_PAD111_PTE6_DCU0_R1,
+ MVF600_PAD112_PTE7_DCU0_R2,
+ MVF600_PAD113_PTE8_DCU0_R3,
+ MVF600_PAD114_PTE9_DCU0_R4,
+ MVF600_PAD115_PTE10_DCU0_R5,
+ MVF600_PAD116_PTE11_DCU0_R6,
+ MVF600_PAD117_PTE12_DCU0_R7,
+ MVF600_PAD118_PTE13_DCU0_G0,
+ MVF600_PAD119_PTE14_DCU0_G1,
+ MVF600_PAD120_PTE15_DCU0_G2,
+ MVF600_PAD121_PTE16_DCU0_G3,
+ MVF600_PAD122_PTE17_DCU0_G4,
+ MVF600_PAD123_PTE18_DCU0_G5,
+ MVF600_PAD124_PTE19_DCU0_G6,
+ MVF600_PAD125_PTE20_DCU0_G7,
+ MVF600_PAD126_PTE21_DCU0_B0,
+ MVF600_PAD127_PTE22_DCU0_B1,
+ MVF600_PAD128_PTE23_DCU0_B2,
+ MVF600_PAD129_PTE24_DCU0_B3,
+ MVF600_PAD130_PTE25_DCU0_B4,
+ MVF600_PAD131_PTE26_DCU0_B5,
+ MVF600_PAD132_PTE27_DCU0_B6,
+ MVF600_PAD133_PTE28_DCU0_B7,
+ MVF600_PAD45_PTC0_BL_ON,
+
+ /* UART1: UART_C */
+ MVF600_PAD26_PTB4_UART1_TX,
+ MVF600_PAD27_PTB5_UART1_RX,
+
+ /* UART0: UART_A */
+//MVF600_PAD10_PTA20_UART0_DTR,
+//MVF600_PAD11_PTA21_UART0_DCD,
+//MVF600_PAD20_PTA30_UART0_RI,
+//MVF600_PAD21_PTA31_UART0_DSR,
+ MVF600_PAD32_PTB10_UART0_TX,
+ MVF600_PAD33_PTB11_UART0_RX,
+ MVF600_PAD34_PTB12_UART0_RTS,
+ MVF600_PAD35_PTB13_UART0_CTS,
+
+ /* UART2: UART_B */
+ MVF600_PAD79_PTD0_UART2_TX,
+ MVF600_PAD80_PTD1_UART2_RX,
+ MVF600_PAD81_PTD2_UART2_RTS,
+ MVF600_PAD82_PTD3_UART2_CTS,
+
+ /* USB */
+ MVF600_PAD83_PTD4__USBH_PEN,
+ MVF600_PAD102_PTC29__USBC_DET, /* multiplexed USB0_VBUS_DET */
+ MVF600_PAD108_PTE3__USB_OC,
+
+ /* PWM */
+ MVF600_PAD22_PTB0_FTM0CH0, //PWM<A> multiplexed MVF600_PAD52_PTC7_VID7
+ MVF600_PAD23_PTB1_FTM0CH1, //PWM<c>
+ MVF600_PAD30_PTB8_FTM1CH0, //PWM<B>
+ MVF600_PAD31_PTB9_FTM1CH1, //PWM<D> multiplexed MVF600_PAD51_PTC6_VID6
+
+ /* Wake-Up GPIO */
+ MVF600_PAD41_PTB19__GPIO,
+#if 0
+ /* NAND */
+ MVF600_PAD71_PTD23_NF_IO7,
+ MVF600_PAD72_PTD22_NF_IO6,
+ MVF600_PAD73_PTD21_NF_IO5,
+ MVF600_PAD74_PTD20_NF_IO4,
+ MVF600_PAD75_PTD19_NF_IO3,
+ MVF600_PAD76_PTD18_NF_IO2,
+ MVF600_PAD77_PTD17_NF_IO1,
+ MVF600_PAD78_PTD16_NF_IO0,
+ MVF600_PAD94_PTB24_NF_WE,
+ MVF600_PAD95_PTB25_NF_CE0,
+ MVF600_PAD97_PTB27_NF_RE,
+ MVF600_PAD99_PTC26_NF_RB,
+ MVF600_PAD100_PTC27_NF_ALE,
+ MVF600_PAD101_PTC28_NF_CLE,
+#endif
+
+//MVF600_PAD2_PTA9_GPIO, /* carefull also used for JTAG JTDI, may be used
+// for RMII_CLKOUT */
+//MVF600_PAD7_PTA17_GPIO,
+//MVF600_PAD38_PTB16_GPIO, /* carefull also used as SW1_WAKEUP_PIN */
+//MVF600_PAD39_PTB17_GPIO,
+//MVF600_PAD40_PTB18_GPIO, /* IOMUXC_CCM_AUD_EXT_CLK_SELECT_INPUT 2
+// Selecting Pad: PTB18 for Mode: ALT2. */
+//MVF600_PAD43_PTB21_GPIO, /* CAN_INT */
+//MVF600_PAD44_PTB22_GPIO,
+//MVF600_PAD63_PTD31_GPIO,
+//MVF600_PAD65_PTD29_GPIO,
+//MVF600_PAD66_PTD28_GPIO,
+//MVF600_PAD67_PTD27_GPIO,
+//MVF600_PAD68_PTD26_GPIO,
+//MVF600_PAD69_PTD25_GPIO,
+//MVF600_PAD70_PTD24_GPIO,
+//MVF600_PAD88_PTD9_GPIO,
+//MVF600_PAD89_PTD10_GPIO,
+//MVF600_PAD90_PTD11_GPIO,
+//MVF600_PAD92_PTD13_GPIO,
+//MVF600_PAD93_PTB23_GPIO,
+//MVF600_PAD96_PTB26_GPIO,
+//MVF600_PAD98_PTB28_GPIO,
+//MVF600_PAD103_PTC30_GPIO,
+
+//optional secondary pinmux
+//MVF600_PAD28_PTB6_VIDHSYNC,
+//MVF600_PAD29_PTB7_VIDVSYNC,
+//MVF600_PAD46_PTC1_VID1,
+//MVF600_PAD47_PTC2_VID2,
+//MVF600_PAD48_PTC3_VID3,
+//MVF600_PAD49_PTC4_VID4,
+//MVF600_PAD50_PTC5_VID5,
+//MVF600_PAD51_PTC6_VID6, /* multiplexed MVF600_PAD31_PTB9_FTM1CH1 */
+//MVF600_PAD52_PTC7_VID7, /* multiplexed MVF600_PAD22_PTB0_FTM0CH0 */
+//MVF600_PAD53_PTC8_VID8,
+//MVF600_PAD64_PTD30_VID10,
+//MVF600_PAD91_PTD12_VID, /* VIDMCLK? */
+//MVF600_PAD134_PTA7_VIDPCLK, /* IOMUXC_VIDEO_IN0_IPP_IND_PIX_CLK_SELECT_INPUT
+// 1 Selecting Pad: PTA7 for Mode: ALT1. */
+
+//MVF600_PAD104_PTC31_ADC1_SE5, /* nVDD_FAULT/SENSE */
+//MVF600_PAD25_PTB3_ADC1_SE3, /* nBATT_FAULT/SENSE */
+
+//VADCSE0
+//VADCSE1
+//VADCSE2
+//VADCSE3
+
+//EXT_TAMPER0
+//EXT_TAMPER1
+//EXT_TAMPER2/EXT_WM0_TAMPER_IN
+//EXT_TAMPER3/EXT_WM0_TAMPER_OUT
+//EXT_TAMPER4/EXT_WM1_TAMPER_IN
+//EXT_TAMPER5/EXT_WM1_TAMPER_OUT
+
+//IOMUXC_VIDEO_IN0_IPP_IND_DE_SELECT_INPUT: PTB5, PTB8 or PTB10 as ALT5
+};
+
+static iomux_v3_cfg_t colibri_vf50_pads[] = {
+ /* Touchscreen */
+ MVF600_PAD4_PTA11,
+ MVF600_PAD5_PTA12,
+ MVF600_PAD6_PTA16_ADC1_SE0,
+ MVF600_PAD8_PTA18_ADC0_SE0,
+ MVF600_PAD9_PTA19_ADC0_SE1,
+ MVF600_PAD12_PTA22,
+ MVF600_PAD13_PTA23,
+ MVF600_PAD24_PTB2_ADC1_SE2,
+};
+
+static iomux_v3_cfg_t colibri_vf61_pads[] = {
+ /* SAI2: AC97/Touchscreen */
+ MVF600_PAD4_PTA11_WM9715L_PENDOWN, /* carefull also used for JTAG
+ JTMS/SWDIO */
+ MVF600_PAD6_PTA16_SAI2_TX_BCLK, /* AC97_BIT_CLK */
+ MVF600_PAD8_PTA18_WM9715L_SDATAOUT, /* AC97_SDATA_OUT, initially
+ driven low to avoid wolfson entering test mode */
+ MVF600_PAD9_PTA19_WM9715L_SYNC, /* AC97_SYNC, initially used to
+ do wolfson warm reset by toggling it as a GPIO */
+ MVF600_PAD12_PTA22_SAI2_RX_DATA, /* AC97_SDATA_IN */
+ MVF600_PAD13_PTA23_WM9715L_RESET,
+ MVF600_PAD24_PTB2_WM9715L_GENIRQ,
+ MVF600_PAD93_PTB23_SAI0_TX_BCLK, /* AC97_MCLK */
+};
+
+static struct imxuart_platform_data mvf_uart0_pdata = {
+//IMXUART_USE_DCEDTE not supported on Vybrid (i.MX only)
+//IMXUART_EDMA
+//IMXUART_FIFO
+//49.4.8 ISO-7816/smartcard support
+//49.4.9 Infrared interface (aka IrDA up to 115.2 kbits/s)
+//49.8.7.2 Transceiver driver enable using RTS (e.g. for RS485 driver)
+ .flags = IMXUART_FIFO | IMXUART_EDMA | IMXUART_HAVE_RTSCTS,
+ .dma_req_rx = DMA_MUX03_UART0_RX,
+ .dma_req_tx = DMA_MUX03_UART0_TX,
+};
+
+static struct imxuart_platform_data mvf_uart1_pdata = {
+ .flags = IMXUART_FIFO | IMXUART_EDMA,
+ .dma_req_rx = DMA_MUX03_UART1_RX,
+ .dma_req_tx = DMA_MUX03_UART1_TX,
+};
+
+static struct imxuart_platform_data mvf_uart2_pdata = {
+ .flags = IMXUART_FIFO | IMXUART_EDMA | IMXUART_HAVE_RTSCTS,
+ .dma_req_rx = DMA_MUX03_UART2_RX,
+ .dma_req_tx = DMA_MUX03_UART2_TX,
+};
+
+static inline void mvf_vf700_init_uart(void)
+{
+ mvf_add_imx_uart(0, &mvf_uart0_pdata);
+ mvf_add_imx_uart(1, &mvf_uart1_pdata);
+ mvf_add_imx_uart(2, &mvf_uart2_pdata);
+}
+
+static int colibri_ts_mux_pen_interrupt(struct platform_device *pdev)
+{
+ mxc_iomux_v3_setup_pad(MVF600_PAD8_PTA18);
+ mxc_iomux_v3_setup_pad(MVF600_PAD9_PTA19);
+
+ dev_dbg(&pdev->dev, "Muxed XP/XM as GPIO\n");
+
+ return 0;
+}
+
+static int colibri_ts_mux_adc(struct platform_device *pdev)
+{
+ mxc_iomux_v3_setup_pad(MVF600_PAD8_PTA18_ADC0_SE0);
+ mxc_iomux_v3_setup_pad(MVF600_PAD9_PTA19_ADC0_SE1);
+
+ dev_dbg(&pdev->dev, "Muxed XP/XM for ADC mode\n");
+
+ return 0;
+}
+
+
+static struct colibri_ts_platform_data colibri_ts_pdata = {
+ .mux_pen_interrupt = &colibri_ts_mux_pen_interrupt,
+ .mux_adc = &colibri_ts_mux_adc,
+ .gpio_pen = 8, /* PAD8 */
+};
+
+struct platform_device *__init colibri_add_touchdev(
+ const struct colibri_ts_platform_data *pdata)
+{
+ return imx_add_platform_device("colibri-vf50-ts", 0, NULL, 0,
+ pdata, sizeof(*pdata));
+}
+
+/*
+ * Fusion touch screen GPIOs (using Toradex display/touch adapater)
+ * Iris X16-38, SODIMM pin 28 (PWM B), pen down interrupt
+ * Iris X16-39, SODIMM pin 30 (PWM C), reset
+ */
+static int colibri_mux_fusion(void)
+{
+ mxc_iomux_v3_setup_pad(MVF600_PAD30_PTB8_INT);
+ mxc_iomux_v3_setup_pad(MVF600_PAD23_PTB1_RESET);
+
+ return 0;
+}
+
+static struct fusion_f0710a_init_data colibri_fusion_pdata = {
+ .pinmux_fusion_pins = &colibri_mux_fusion,
+ .gpio_int = 30, /* SO-DIMM 28: Pen down interrupt */
+ .gpio_reset = 23, /* SO-DIMM 30: Reset interrupt */
+};
+
+static struct fec_platform_data fec_data __initdata = {
+ .phy = PHY_INTERFACE_MODE_RMII,
+};
+
+static int mvf_vf600_spi_cs[] = {
+ 84,
+};
+
+static const struct spi_mvf_master mvf_vf600_spi_data __initconst = {
+ .bus_num = 1,
+ .chipselect = mvf_vf600_spi_cs,
+ .num_chipselect = ARRAY_SIZE(mvf_vf600_spi_cs),
+ .cs_control = NULL,
+};
+
+static struct spi_mvf_chip spidev_chip_info = {
+ .mode = SPI_MODE_0,
+ .bits_per_word = 8,
+ .void_write_data = 0,
+ .dbr = 0,
+ .pbr = 0,
+ .br = 0,
+ .pcssck = 0,
+ .pasc = 0,
+ .pdt = 0,
+ .cssck = 0,
+ .asc = 0,
+ .dt = 0,
+};
+
+#if defined(CONFIG_CAN_MCP251X)
+#define CAN_INTERRUPT_GPIO 43 /* active low interrupt (MCP2515 nINT) */
+
+static struct mcp251x_platform_data mcp251x_pdata = {
+ .board_specific_setup = NULL,
+ .oscillator_frequency = 16000000,
+ .power_enable = NULL,
+ .transceiver_enable = NULL
+};
+#endif
+
+static struct spi_board_info mvf_spi_board_info[] __initdata = {
+#if defined(CONFIG_CAN_MCP251X)
+ {
+ .bus_num = 1,
+ .chip_select = 0,
+ .max_speed_hz = 10000000,
+ .modalias = "mcp2515",
+ .platform_data = &mcp251x_pdata,
+ .controller_data = &spidev_chip_info,
+ },
+#elif defined(CONFIG_SPI_SPIDEV)
+ {
+ .bus_num = 1, /* DSPI1: Colibri SSP */
+ .chip_select = 0,
+ .irq = 0,
+ .max_speed_hz = 50000000,
+ .modalias = "spidev",
+ .mode = SPI_MODE_0,
+ .platform_data = NULL,
+ .controller_data = &spidev_chip_info,
+ },
+#endif
+};
+
+static void spi_device_init(void)
+{
+#if defined(CONFIG_CAN_MCP251X)
+ mvf_spi_board_info[0].irq = gpio_to_irq(CAN_INTERRUPT_GPIO);
+#endif
+ spi_register_board_info(mvf_spi_board_info,
+ ARRAY_SIZE(mvf_spi_board_info));
+}
+
+static void vf600_suspend_enter(void)
+{
+ /* suspend preparation */
+}
+
+static void vf600_suspend_exit(void)
+{
+ /* resmue resore */
+}
+
+static const struct pm_platform_data mvf_vf600_pm_data __initconst = {
+ .name = "mvf_pm",
+ .suspend_enter = vf600_suspend_enter,
+ .suspend_exit = vf600_suspend_exit,
+};
+
+static int colibri_vf50_backlight_init(struct device *dev) {
+ int ret;
+
+ ret = gpio_request(colibri_vf50_bl_enb, "BL_ON");
+ if (ret < 0)
+ return ret;
+
+ ret = gpio_direction_output(colibri_vf50_bl_enb, 1);
+ if (ret < 0)
+ gpio_free(colibri_vf50_bl_enb);
+
+ return ret;
+};
+
+static void colibri_vf50_backlight_exit(struct device *dev) {
+ gpio_set_value(colibri_vf50_bl_enb, 0);
+ gpio_free(colibri_vf50_bl_enb);
+}
+
+static int colibri_vf50_backlight_notify(struct device *dev, int brightness)
+{
+ struct platform_pwm_backlight_data *pdata = dev->platform_data;
+
+ gpio_set_value(colibri_vf50_bl_enb, !!brightness);
+
+ /* Unified TFT interface displays (e.g. EDT ET070080DH6) LEDCTRL pin
+ with inverted behaviour (e.g. 0V brightest vs. 3.3V darkest)
+ Note: brightness polarity display model specific */
+ if (brightness) return pdata->max_brightness - brightness;
+ else return brightness;
+}
+
+static struct platform_pwm_backlight_data colibri_vf50_backlight_data = {
+ .pwm_id = 1, /* PWM<A> (FTM0CH0) */
+ .max_brightness = 255,
+ .dft_brightness = 127,
+ .pwm_period_ns = 1000000, /* 1 kHz */
+ .init = colibri_vf50_backlight_init,
+ .exit = colibri_vf50_backlight_exit,
+ .notify = colibri_vf50_backlight_notify,
+};
+
+static struct mvf_dcu_platform_data mvf_dcu_pdata = {
+ .mode_str = "640x480",
+ .default_bpp = 16,
+};
+
+static void __init fixup_mxc_board(struct machine_desc *desc, struct tag *tags,
+ char **cmdline, struct meminfo *mi)
+{
+ if (!mi->nr_banks)
+ arm_add_memory(PHYS_OFFSET, SZ_128M);
+}
+
+/*
+ * Not defined the cd/wp so far, set it always present for debug */
+static const struct esdhc_platform_data mvfa5_sd1_data __initconst = {
+ .cd_gpio = MVF600_SD1_CD,
+ .wp_gpio = -1,
+};
+
+static struct imxi2c_platform_data mvf600_i2c_data = {
+ .bitrate = 100000,
+};
+
+static struct i2c_board_info mxc_i2c0_board_info[] __initdata = {
+ {
+ /* M41T0M6 real time clock on Iris carrier board */
+ I2C_BOARD_INFO("rtc-ds1307", 0x68),
+ .type = "m41t00",
+ },
+ {
+ /* TouchRevolution Fusion 7 and 10 multi-touch controller */
+ I2C_BOARD_INFO("fusion_F0710A", 0x10),
+ .platform_data = &colibri_fusion_pdata,
+ },
+};
+
+static struct mxc_nand_platform_data mvf_data __initdata = {
+ .width = 1,
+};
+
+/* PWM LEDs */
+static struct led_pwm tegra_leds_pwm[] = {
+#if 0
+ {
+ .name = "PWM<A>",
+ .pwm_id = 1,
+ .max_brightness = 255,
+ .pwm_period_ns = 19600,
+ },
+#endif
+ {
+ .name = "PWM<B>",
+ .pwm_id = 2,
+ .max_brightness = 255,
+ .pwm_period_ns = 19600,
+ },
+ {
+ .name = "PWM<C>",
+ .pwm_id = 3,
+ .max_brightness = 255,
+ .pwm_period_ns = 19600,
+ },
+ {
+ .name = "PWM<D>",
+ .pwm_id = 4,
+ .max_brightness = 255,
+ .pwm_period_ns = 19600,
+ },
+};
+
+static struct led_pwm_platform_data tegra_leds_pwm_data = {
+ .num_leds = ARRAY_SIZE(tegra_leds_pwm),
+ .leds = tegra_leds_pwm,
+};
+
+static struct imx_asrc_platform_data imx_asrc_data = {
+ .channel_bits = 4,
+ .clk_map_ver = 3,
+};
+
+static void __init mvf_twr_init_usb(void)
+{
+ imx_otg_base = MVF_IO_ADDRESS(MVF_USBC0_BASE_ADDR);
+ /*mvf_set_otghost_vbus_func(mvf_twr_usbotg_vbus);*/
+ gpio_request(83, "USBH_PEN");
+ gpio_direction_output(83, 0);
+#ifdef CONFIG_USB_EHCI_ARC
+ mvf_usb_dr2_init();
+#endif
+#ifdef CONFIG_USB_GADGET_ARC
+ mvf_usb_dr_init();
+#endif
+}
+
+static void __init mvf_init_adc(void)
+{
+ mvf_add_adc(0);
+ mvf_add_adc(1);
+}
+
+static void mvf_power_off(void)
+{
+ void __iomem *gpc_base = MVF_GPC_BASE;
+ u32 gpc_pgcr;
+
+ /*
+ * Power gate Power Domain 1
+ */
+ gpc_pgcr = __raw_readl(gpc_base + GPC_PGCR_OFFSET);
+ gpc_pgcr |= GPC_PGCR_PG_PD1;
+ __raw_writel(gpc_pgcr, gpc_base + GPC_PGCR_OFFSET);
+
+ /* Set low power mode */
+ mvf_cpu_lp_set(STOP_MODE);
+}
+
+/*!
+ * Board specific initialization.
+ */
+static void __init mvf_board_init(void)
+{
+ mxc_iomux_v3_setup_multiple_pads(mvf600_pads,
+ ARRAY_SIZE(mvf600_pads));
+ mvf_vf700_init_uart();
+
+#ifdef CONFIG_FEC
+ mvf_init_fec(fec_data);
+#endif
+
+ mvf_add_snvs_rtc();
+
+ mvf_init_adc();
+
+ mvf_add_pm_imx(0, &mvf_vf600_pm_data);
+
+ mvf700_add_caam();
+
+ mvf_add_sdhci_esdhc_imx(1, &mvfa5_sd1_data);
+
+ mvf_add_imx_i2c(0, &mvf600_i2c_data);
+
+ i2c_register_board_info(0, mxc_i2c0_board_info,
+ ARRAY_SIZE(mxc_i2c0_board_info));
+
+ mvf_add_dspi(1, &mvf_vf600_spi_data);
+ spi_device_init();
+
+ mvfa5_add_dcu(0, &mvf_dcu_pdata);
+ mvf_add_mxc_pwm(0);
+ mvf_add_mxc_pwm_backlight(0, &colibri_vf50_backlight_data);
+
+ mvf_add_wdt(0);
+
+ mvf_twr_init_usb();
+
+ mvf_add_nand(&mvf_data);
+
+ mvf_add_mxc_pwm(1);
+ mvf_add_mxc_pwm(2);
+ mvf_add_mxc_pwm(3);
+ mvf_add_pwm_leds(&tegra_leds_pwm_data);
+
+ imx_asrc_data.asrc_core_clk = clk_get(NULL, "asrc_clk");
+ imx_asrc_data.asrc_audio_clk = clk_get(NULL, "asrc_serial_clk");
+ mvf_add_asrc(&imx_asrc_data);
+
+ pm_power_off = mvf_power_off;
+}
+
+static void __init colibri_vf50_init(void)
+{
+ mxc_iomux_v3_setup_multiple_pads(colibri_vf50_pads,
+ ARRAY_SIZE(colibri_vf50_pads));
+
+ mvf_board_init();
+
+ colibri_add_touchdev(&colibri_ts_pdata);
+}
+
+static void __init colibri_vf61_init(void)
+{
+ mxc_iomux_v3_setup_multiple_pads(colibri_vf61_pads,
+ ARRAY_SIZE(colibri_vf61_pads));
+
+ mvf_board_init();
+
+ mvfa5_add_sai(2, NULL);
+}
+
+static void __init mvf_timer_init(void)
+{
+ struct clk *uart_clk;
+ uart_clk = clk_get_sys("mvf-uart.0", NULL);
+ early_console_setup(MVF_UART0_BASE_ADDR, uart_clk);
+
+ mvf_clocks_init(32768, 24000000, 0, 0);
+}
+
+static struct sys_timer mxc_timer = {
+ .init = mvf_timer_init,
+};
+
+/*
+ * initialize __mach_desc_ data structure.
+ */
+MACHINE_START(COLIBRI_VF50, "Toradex Colibri VF50 Module")
+ .boot_params = MVF_PHYS_OFFSET + 0x100,
+ .fixup = fixup_mxc_board,
+ .init_irq = mvf_init_irq,
+ .init_machine = colibri_vf50_init,
+ .map_io = mvf_map_io,
+ .timer = &mxc_timer,
+MACHINE_END
+
+MACHINE_START(COLIBRI_VF61, "Toradex Colibri VF61 Module")
+ .boot_params = MVF_PHYS_OFFSET + 0x100,
+ .fixup = fixup_mxc_board,
+ .init_irq = mvf_init_irq,
+ .init_machine = colibri_vf61_init,
+ .map_io = mvf_map_io,
+ .timer = &mxc_timer,
+MACHINE_END
diff --git a/arch/arm/mach-mvf/clock.c b/arch/arm/mach-mvf/clock.c
index b37992318170..7c95a2638128 100644
--- a/arch/arm/mach-mvf/clock.c
+++ b/arch/arm/mach-mvf/clock.c
@@ -1,4 +1,3 @@
-
/*
* Copyright 2012 Freescale Semiconductor, Inc.
*
@@ -38,7 +37,6 @@
#define __INIT_CLK_DEBUG(n)
#endif
-
void __iomem *apll_base;
static struct clk pll1_sys_main_clk;
static struct clk pll2_528_bus_main_clk;
@@ -50,11 +48,6 @@ static struct clk pll5_enet_main_clk;
static struct clk pll1_pfd3_396M;
static struct clk pll1_pfd4_528M;
-unsigned long arm_core_clk = 396000000; /* cpu core clk, up to 452MHZ */
-unsigned long arm_sys_clk = 396000000; /* ARM_CLK_DIV, system bus clock */
-unsigned long platform_bus_clk = 132000000; /* BUS_CLK_DIV, up to 166MHZ */
-unsigned long ipg_bus_clk = 66000000; /* IPS clk */
-
#define SPIN_DELAY 3000000 /* in nanoseconds */
#define AUDIO_VIDEO_MIN_CLK_FREQ 650000000
@@ -88,7 +81,6 @@ static unsigned long external_high_reference, external_low_reference;
static unsigned long oscillator_reference, ckih2_reference;
static unsigned long anaclk_1_reference, anaclk_2_reference;
-
static int _clk_enable(struct clk *clk)
{
u32 reg;
@@ -106,7 +98,6 @@ static void _clk_disable(struct clk *clk)
reg = __raw_readl(clk->enable_reg);
reg &= ~(MXC_CCM_CCGRx_CG_MASK << clk->enable_shift);
__raw_writel(reg, clk->enable_reg);
-
}
/* Clock off in wait mode */
@@ -165,7 +156,6 @@ static inline void __iomem *_get_pll_base(struct clk *pll)
return NULL;
}
-
/*
* For the 6-to-1 muxed input clock
*/
@@ -288,7 +278,6 @@ static unsigned long pfd_get_rate(struct clk *clk)
u64 tmp;
tmp = (u64)clk_get_rate(clk->parent) * 18;
-
frac = (__raw_readl(clk->enable_reg) >> clk->enable_shift) &
ANADIG_PFD_FRAC_MASK;
@@ -303,7 +292,6 @@ static int pfd_set_rate(struct clk *clk, unsigned long rate)
u64 tmp;
tmp = (u64)clk_get_rate(clk->parent) * 18;
-
/* Round up the divider so that we don't set a rate
* higher than what is requested. */
tmp += rate/2;
@@ -341,7 +329,6 @@ static void _clk_pfd_disable(struct clk *clk)
/* set clk gate bit */
__raw_writel(reg | (1 << (clk->enable_shift + 7)),
clk->enable_reg);
-
}
static int _clk_pll_enable(struct clk *clk)
@@ -403,7 +390,6 @@ static void _clk_pll_disable(struct clk *clk)
reg &= ~ANADIG_PLL_ENABLE;
__raw_writel(reg, pllbase);
-
}
/* PLL sys: 528 or 480 MHz*/
@@ -523,11 +509,9 @@ static int _clk_pll1_sw_set_parent(struct clk *clk, struct clk *parent)
if (parent == &pll1_sys_main_clk) {
reg &= ~MXC_CCM_CCSR_PLL1_PFD_CLK_SEL_MASK;
-
} else if (parent == &pll1_pfd2_452M) {
reg &= ~MXC_CCM_CCSR_PLL1_PFD_CLK_SEL_MASK;
reg |= (0x2 << MXC_CCM_CCSR_PLL1_PFD_CLK_SEL_OFFSET);
-
} else if (parent == &pll1_pfd3_396M) {
reg &= ~MXC_CCM_CCSR_PLL1_PFD_CLK_SEL_MASK;
reg |= (0x3 << MXC_CCM_CCSR_PLL1_PFD_CLK_SEL_OFFSET);
@@ -554,7 +538,6 @@ static unsigned long _clk_pll1_sw_get_rate(struct clk *clk)
return 396000000;
else
return 528000000;
-
}
static struct clk pll1_sw_clk = {
@@ -678,7 +661,6 @@ static int _clk_pll3_usb_otg_set_rate(struct clk *clk, unsigned long rate)
return 0;
}
-
/* same as pll3_main_clk. These two clocks should always be the same */
static struct clk pll3_usb_otg_main_clk = {
__INIT_CLK_DEBUG(pll3_usb_otg_main_clk)
@@ -715,7 +697,6 @@ static struct clk usb_phy1_clk = {
.get_rate = _clk_pll3_usb_otg_get_rate,
};
-
static struct clk pll3_pfd2_396M = {
__INIT_CLK_DEBUG(pll3_pfd2_396M)
.parent = &pll3_usb_otg_main_clk,
@@ -769,26 +750,26 @@ static struct clk pll3_sw_clk = {
static unsigned long _clk_audio_video_get_rate(struct clk *clk)
{
unsigned int div, mfn, mfd;
- unsigned long rate;
unsigned int parent_rate = clk_get_rate(clk->parent);
+ unsigned long long ll;
void __iomem *pllbase;
- unsigned int test_div_sel, control3, post_div = 1;
-
if (clk == &pll4_audio_main_clk)
pllbase = PLL4_AUDIO_BASE_ADDR;
else
pllbase = PLL6_VIDEO_BASE_ADDR;
-
+ /* Multiplication Factor Integer (MFI) */
div = __raw_readl(pllbase) & ANADIG_PLL_SYS_DIV_SELECT_MASK;
+ /* Multiplication Factor Numerator (MFN) */
mfn = __raw_readl(pllbase + PLL_NUM_DIV_OFFSET);
+ /* Multiplication Factor Denominator (MFD) */
mfd = __raw_readl(pllbase + PLL_DENOM_DIV_OFFSET);
- rate = (parent_rate * div) + ((parent_rate / mfd) * mfn);
- rate = rate / post_div;
+ ll = (unsigned long long)parent_rate * mfn;
+ do_div(ll, mfd);
- return rate;
+ return (parent_rate * div) + ll;
}
static int _clk_audio_video_set_rate(struct clk *clk, unsigned long rate)
@@ -803,7 +784,6 @@ static int _clk_audio_video_set_rate(struct clk *clk, unsigned long rate)
u32 test_div_sel = 2;
u32 control3 = 0;
-
if (clk == &pll4_audio_main_clk)
min_clk_rate = AUDIO_VIDEO_MIN_CLK_FREQ / 4;
else
@@ -929,6 +909,54 @@ static struct clk pll6_video_main_clk = {
.set_parent = _clk_audio_video_set_parent,
};
+static unsigned long _clk_pll4_audio_div_get_rate(struct clk *clk)
+{
+ u32 reg, div;
+ unsigned int parent_rate = clk_get_rate(clk->parent);
+
+ reg = __raw_readl(MXC_CCM_CACRR);
+ div = (((reg & MXC_CCM_CACRR_PLL4_CLK_DIV_MASK) >>
+ MXC_CCM_CACRR_PLL4_CLK_DIV_OFFSET) + 1) * 2;
+ if (2 == div)
+ div = 1;
+
+ return parent_rate / div;
+}
+
+static int _clk_pll4_audio_div_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 reg, div;
+ unsigned int parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+
+ /* Make sure rate is not greater than the maximum value for the clock.
+ * Also prevent a div of 0.
+ */
+ if (0 == div)
+ div++;
+
+ if (16 < div)
+ div = 16;
+
+ div /= 2;
+ if (1 <= div)
+ div -= 1;
+
+ reg = __raw_readl(MXC_CCM_CACRR);
+ reg &= ~MXC_CCM_CACRR_PLL4_CLK_DIV_MASK;
+ reg |= (div << MXC_CCM_CACRR_PLL4_CLK_DIV_OFFSET);
+ __raw_writel(reg, MXC_CCM_CACRR);
+
+ return 0;
+}
+
+static struct clk pll4_audio_div_clk = {
+ __INIT_CLK_DEBUG(pll4_audio_div_clk)
+ .parent = &pll4_audio_main_clk,
+ .set_rate = _clk_pll4_audio_div_set_rate,
+ .get_rate = _clk_pll4_audio_div_get_rate,
+};
static struct clk pll5_enet_main_clk = {
__INIT_CLK_DEBUG(pll5_enet_main_clk)
@@ -942,9 +970,9 @@ static unsigned long _clk_arm_get_rate(struct clk *clk)
u32 cacrr, div;
cacrr = __raw_readl(MXC_CCM_CACRR);
- div = (cacrr & MXC_CCM_CACRR_ARM_CLK_DIV_MASK) + 1;
- return arm_core_clk;
- /*return clk_get_rate(clk->parent) / div;*/
+ div = ((cacrr & MXC_CCM_CACRR_ARM_CLK_DIV_MASK) >>
+ MXC_CCM_CACRR_ARM_CLK_DIV_OFFSET) + 1;
+ return clk_get_rate(clk->parent) / div;
}
static int _clk_arm_set_rate(struct clk *clk, unsigned long rate)
@@ -956,10 +984,10 @@ static int _clk_arm_set_rate(struct clk *clk, unsigned long rate)
return 0;
}
-
static struct clk cpu_clk = {
__INIT_CLK_DEBUG(cpu_clk)
- .parent = &pll1_sw_clk, /* A5 clock from PLL1 pfd3 out 396MHZ */
+ .parent = &pll1_sw_clk, /* A5 clock from PLL1 pfd1 out 500 MHz resp.
+ pfd3 out 396MHZ */
.set_rate = _clk_arm_set_rate,
.get_rate = _clk_arm_get_rate,
};
@@ -983,8 +1011,8 @@ static int _clk_periph_set_parent(struct clk *clk, struct clk *parent)
__raw_writel(reg, MXC_CCM_CCSR);
/*
- * Set the BUS_CLK_DIV to 3, 396/3=132
- * Set IPG_CLK_DIV to 2, 132/2=66
+ * Set the BUS_CLK_DIV to 3, 396/3=132 resp. 500/3=166
+ * Set IPG_CLK_DIV to 2, 132/2=66 resp. 166/2=83
*/
reg = __raw_readl(MXC_CCM_CACRR);
reg &= ~MXC_CCM_CACRR_BUS_CLK_DIV_MASK;
@@ -998,24 +1026,30 @@ static int _clk_periph_set_parent(struct clk *clk, struct clk *parent)
static unsigned long _clk_periph_get_rate(struct clk *clk)
{
- unsigned long val = 132000000;
- return val;
+ u32 cacrr, div;
+
+ cacrr = __raw_readl(MXC_CCM_CACRR);
+ div = ((cacrr & MXC_CCM_CACRR_BUS_CLK_DIV_MASK) >>
+ MXC_CCM_CACRR_BUS_CLK_DIV_OFFSET) + 1;
+ return clk_get_rate(clk->parent) / div;
}
static struct clk periph_clk = {
__INIT_CLK_DEBUG(periph_clk)
- .parent = &pll2_pfd2_396M,
+ .parent = &pll1_sw_clk,
.set_parent = _clk_periph_set_parent,
.get_rate = _clk_periph_get_rate,
};
-
-
static unsigned long _clk_ipg_get_rate(struct clk *clk)
{
- return 66000000;
-}
+ u32 cacrr, div;
+ cacrr = __raw_readl(MXC_CCM_CACRR);
+ div = ((cacrr & MXC_CCM_CACRR_IPG_CLK_DIV_MASK) >>
+ MXC_CCM_CACRR_IPG_CLK_DIV_OFFSET) + 1;
+ return clk_get_rate(clk->parent) / div;
+}
static struct clk ipg_clk = {
__INIT_CLK_DEBUG(ipg_clk)
@@ -1023,13 +1057,11 @@ static struct clk ipg_clk = {
.get_rate = _clk_ipg_get_rate,
};
-
static struct clk scu_clk = {
__INIT_CLK_DEBUG(scu_clk)
.parent = &periph_clk,
};
-
static int _clk_enet_set_parent(struct clk *clk, struct clk *parent)
{
int mux;
@@ -1147,8 +1179,6 @@ static struct clk enet_clk[] = {
},
};
-
-
static unsigned long _clk_uart_round_rate(struct clk *clk,
unsigned long rate)
{
@@ -1168,6 +1198,7 @@ static unsigned long _clk_uart_round_rate(struct clk *clk,
return parent_rate / div;
}
+
/*
*/
static unsigned long _clk_uart_get_rate(struct clk *clk)
@@ -1209,6 +1240,15 @@ static struct clk dspi_clk[] = {
.enable = _clk_enable,
.disable = _clk_disable,
},
+ {
+ __INIT_CLK_DEBUG(dspi1_clk)
+ .id = 1,
+ .parent = &ipg_clk,
+ .enable_reg = MXC_CCM_CCGR0,
+ .enable_shift = MXC_CCM_CCGRx_CG13_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ },
};
static int _clk_esdhc1_set_parent(struct clk *clk, struct clk *parent)
@@ -1345,7 +1385,7 @@ static int _clk_dcu0_set_rate(struct clk *clk, unsigned long rate)
u32 reg, div;
u32 parent_rate = clk_get_rate(clk->parent);
- div = (parent_rate + rate - 1) / rate;
+ div = parent_rate / rate;
if (div == 0)
div++;
if (((parent_rate / div) != rate) || (div > 8))
@@ -1401,34 +1441,34 @@ static struct clk audio_external_clk = {
.get_rate = get_audio_external_clock_rate,
};
-static int _clk_sai2_set_parent(struct clk *clk, struct clk *parent)
+static int _clk_sai0_set_parent(struct clk *clk, struct clk *parent)
{
int mux;
u32 reg = __raw_readl(MXC_CCM_CSCMR1)
- & ~MXC_CCM_CSCMR1_SAI2_CLK_SEL_MASK;
+ & ~MXC_CCM_CSCMR1_SAI0_CLK_SEL_MASK;
mux = _get_mux6(parent, &audio_external_clk, NULL,
- NULL, &pll4_audio_main_clk, NULL, NULL);
+ NULL /* spdif */, &pll4_audio_div_clk, NULL, NULL);
- reg |= (mux << MXC_CCM_CSCMR1_SAI2_CLK_SEL_OFFSET);
+ reg |= (mux << MXC_CCM_CSCMR1_SAI0_CLK_SEL_OFFSET);
__raw_writel(reg, MXC_CCM_CSCMR1);
return 0;
}
-static unsigned long _clk_sai2_get_rate(struct clk *clk)
+static unsigned long _clk_sai0_get_rate(struct clk *clk)
{
u32 reg, div;
reg = __raw_readl(MXC_CCM_CSCDR1);
- div = ((reg & MXC_CCM_CSCDR1_SAI2_DIV_MASK) >>
- MXC_CCM_CSCDR1_SAI2_DIV_OFFSET) + 1;
+ div = ((reg & MXC_CCM_CSCDR1_SAI0_DIV_MASK) >>
+ MXC_CCM_CSCDR1_SAI0_DIV_OFFSET) + 1;
return clk_get_rate(clk->parent) / div;
}
-static int _clk_sai2_set_rate(struct clk *clk, unsigned long rate)
+static int _clk_sai0_set_rate(struct clk *clk, unsigned long rate)
{
u32 reg, div;
u32 parent_rate = clk_get_rate(clk->parent);
@@ -1440,31 +1480,30 @@ static int _clk_sai2_set_rate(struct clk *clk, unsigned long rate)
return -EINVAL;
reg = __raw_readl(MXC_CCM_CSCDR1);
- reg &= ~MXC_CCM_CSCDR1_SAI2_DIV_MASK;
- reg |= (div - 1) << MXC_CCM_CSCDR1_SAI2_DIV_OFFSET;
- reg |= MXC_CCM_CSCDR1_SAI2_EN;
+ reg &= ~MXC_CCM_CSCDR1_SAI0_DIV_MASK;
+ reg |= (div - 1) << MXC_CCM_CSCDR1_SAI0_DIV_OFFSET;
__raw_writel(reg, MXC_CCM_CSCDR1);
return 0;
}
-static int _clk_sai2_enable(struct clk *clk)
+static int _clk_sai0_enable(struct clk *clk)
{
u32 reg;
reg = __raw_readl(MXC_CCM_CSCDR1);
- reg |= MXC_CCM_CSCDR1_SAI2_EN;
+ reg |= MXC_CCM_CSCDR1_SAI0_EN;
__raw_writel(reg, MXC_CCM_CSCDR1);
return 0;
}
-static void _clk_sai2_disable(struct clk *clk)
+static void _clk_sai0_disable(struct clk *clk)
{
u32 reg;
reg = __raw_readl(MXC_CCM_CSCDR1);
- reg &= ~MXC_CCM_CSCDR1_SAI2_EN;
+ reg &= ~MXC_CCM_CSCDR1_SAI0_EN;
__raw_writel(reg, MXC_CCM_CSCDR1);
return 0;
@@ -1490,6 +1529,87 @@ static unsigned long _clk_sai_round_rate(struct clk *clk,
return parent_rate / div;
}
+static struct clk sai0_clk = {
+ __INIT_CLK_DEBUG(sai0_clk)
+ .parent = &audio_external_clk,
+ .enable_reg = MXC_CCM_CCGR0,
+ .enable_shift = MXC_CCM_CCGRx_CG15_OFFSET,
+ .enable = _clk_sai0_enable,
+ .disable = _clk_sai0_disable,
+ .set_parent = _clk_sai0_set_parent,
+ .round_rate = _clk_sai_round_rate,
+ .set_rate = _clk_sai0_set_rate,
+ .get_rate = _clk_sai0_get_rate,
+};
+
+static int _clk_sai2_set_parent(struct clk *clk, struct clk *parent)
+{
+ int mux;
+ u32 reg = __raw_readl(MXC_CCM_CSCMR1)
+ & ~MXC_CCM_CSCMR1_SAI2_CLK_SEL_MASK;
+
+ mux = _get_mux6(parent, &audio_external_clk, NULL,
+ NULL /* spdif */, &pll4_audio_div_clk, NULL, NULL);
+
+ reg |= (mux << MXC_CCM_CSCMR1_SAI2_CLK_SEL_OFFSET);
+
+ __raw_writel(reg, MXC_CCM_CSCMR1);
+
+ return 0;
+}
+
+static unsigned long _clk_sai2_get_rate(struct clk *clk)
+{
+ u32 reg, div;
+
+ reg = __raw_readl(MXC_CCM_CSCDR1);
+ div = ((reg & MXC_CCM_CSCDR1_SAI2_DIV_MASK) >>
+ MXC_CCM_CSCDR1_SAI2_DIV_OFFSET) + 1;
+
+ return clk_get_rate(clk->parent) / div;
+}
+
+static int _clk_sai2_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 reg, div;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+ if (div == 0)
+ div++;
+ if (((parent_rate / div) != rate) || (div > 16))
+ return -EINVAL;
+
+ reg = __raw_readl(MXC_CCM_CSCDR1);
+ reg &= ~MXC_CCM_CSCDR1_SAI2_DIV_MASK;
+ reg |= (div - 1) << MXC_CCM_CSCDR1_SAI2_DIV_OFFSET;
+ __raw_writel(reg, MXC_CCM_CSCDR1);
+
+ return 0;
+}
+
+static int _clk_sai2_enable(struct clk *clk)
+{
+ u32 reg;
+
+ reg = __raw_readl(MXC_CCM_CSCDR1);
+ reg |= MXC_CCM_CSCDR1_SAI2_EN;
+ __raw_writel(reg, MXC_CCM_CSCDR1);
+
+ return 0;
+}
+
+static void _clk_sai2_disable(struct clk *clk)
+{
+ u32 reg;
+
+ reg = __raw_readl(MXC_CCM_CSCDR1);
+ reg &= ~MXC_CCM_CSCDR1_SAI2_EN;
+ __raw_writel(reg, MXC_CCM_CSCDR1);
+
+ return 0;
+}
+
static struct clk sai2_clk = {
__INIT_CLK_DEBUG(sai2_clk)
.parent = &audio_external_clk,
@@ -1534,15 +1654,32 @@ static int _clk_clko_set_parent(struct clk *clk, struct clk *parent)
else if (parent == &pll6_video_main_clk)
sel = 3;
else if (parent == &pll4_audio_main_clk)
+ sel = 6;
+ else if (parent == &pll4_audio_div_clk)
+ sel = 7;
+ else if (parent == &pll4_audio_main_clk)
sel = 15;
else
return -EINVAL;
+
+ reg = __raw_readl(MXC_CCM_CCOSR)
+ & ~MXC_CCM_CCOSR_CKO1_SEL_MASK;
+ reg |= (sel << MXC_CCM_CCOSR_CKO1_SEL_OFFSET);
+ __raw_writel(reg, MXC_CCM_CCOSR);
+
return 0;
}
static unsigned long _clk_clko_get_rate(struct clk *clk)
{
- return 0;
+ u32 reg, div;
+ unsigned int parent_rate = clk_get_rate(clk->parent);
+
+ reg = __raw_readl(MXC_CCM_CCOSR);
+ div = ((reg & MXC_CCM_CCOSR_CKO1_DIV_MASK) >>
+ MXC_CCM_CCOSR_CKO1_DIV_OFFSET) + 1;
+
+ return parent_rate / div;
}
static int _clk_clko_set_rate(struct clk *clk, unsigned long rate)
@@ -1553,9 +1690,14 @@ static int _clk_clko_set_rate(struct clk *clk, unsigned long rate)
if (div == 0)
div++;
- if (((parent_rate / div) != rate) || (div > 8))
+ if (((parent_rate / div) != rate) || (div > 16))
return -EINVAL;
+ reg = __raw_readl(MXC_CCM_CCOSR)
+ & ~MXC_CCM_CCOSR_CKO1_DIV_MASK;
+ reg |= ((div -1) << MXC_CCM_CCOSR_CKO1_DIV_OFFSET);
+ __raw_writel(reg, MXC_CCM_CCOSR);
+
return 0;
}
@@ -1601,7 +1743,9 @@ static int _clk_clko2_set_rate(struct clk *clk, unsigned long rate)
static struct clk clko_clk = {
__INIT_CLK_DEBUG(clko_clk)
- .parent = &pll2_528_bus_main_clk,
+ .parent = &pll4_audio_div_clk,
+ .enable_reg = MXC_CCM_CCOSR,
+ .enable_shift = MXC_CCM_CCOSR_CKO1_EN_OFFSET,
.enable = _clk_enable1,
.disable = _clk_disable1,
.set_parent = _clk_clko_set_parent,
@@ -1650,6 +1794,15 @@ static struct clk adc_clk[] = {
.enable = _clk_enable,
.disable = _clk_disable,
},
+ {
+ __INIT_CLK_DEBUG(adc_clk)
+ .id = 1,
+ .parent = &ipg_clk,
+ .enable_reg = MXC_CCM_CCGR7,
+ .enable_shift = MXC_CCM_CCGRx_CG11_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ },
};
static struct clk i2c_clk[] = {
@@ -1692,7 +1845,6 @@ static void ftm_pwm_clk_disable(struct clk *pwm_clk)
reg = __raw_readl(MXC_CCM_CSCDR1);
reg &= ~(0x0F << 25);
__raw_writel(reg, MXC_CCM_CSCDR1);
-
}
static struct clk ftm_pwm_clk = {
@@ -1700,7 +1852,6 @@ static struct clk ftm_pwm_clk = {
.parent = &ipg_clk,
.enable = ftm_pwm_clk_enable,
.disable = ftm_pwm_clk_disable,
-
};
static int _clk_qspi0_set_parent(struct clk *clk, struct clk *parent)
@@ -1878,7 +2029,6 @@ static struct clk dummy_clk = {
.clk = &c, \
}
-
static struct clk_lookup lookups[] = {
_REGISTER_CLOCK(NULL, "osc", osc_clk),
_REGISTER_CLOCK(NULL, "ckih", ckih_clk),
@@ -1898,6 +2048,7 @@ static struct clk_lookup lookups[] = {
_REGISTER_CLOCK(NULL, "pll3_pfd3_308M", pll3_pfd3_308M),
_REGISTER_CLOCK(NULL, "pll3_pfd4_320M", pll3_pfd4_320M),
_REGISTER_CLOCK(NULL, "pll4", pll4_audio_main_clk),
+ _REGISTER_CLOCK(NULL, "pll4_div", pll4_audio_div_clk),
_REGISTER_CLOCK(NULL, "pll5", pll6_video_main_clk),
_REGISTER_CLOCK(NULL, "pll6", pll5_enet_main_clk),
_REGISTER_CLOCK(NULL, "cpu_clk", cpu_clk), /* arm core clk */
@@ -1910,10 +2061,12 @@ static struct clk_lookup lookups[] = {
_REGISTER_CLOCK(NULL, "mvf-uart.2", uart_clk[0]),
_REGISTER_CLOCK(NULL, "mvf-uart.3", uart_clk[0]),
_REGISTER_CLOCK("mvf-dspi.0", NULL, dspi_clk[0]),
+ _REGISTER_CLOCK("mvf-dspi.1", NULL, dspi_clk[1]),
_REGISTER_CLOCK("pit", NULL, pit_clk),
_REGISTER_CLOCK("fec.0", NULL, enet_clk[0]),
_REGISTER_CLOCK("fec.1", NULL, enet_clk[1]),
_REGISTER_CLOCK("mvf-adc.0", NULL, adc_clk[0]),
+ _REGISTER_CLOCK("mvf-adc.1", NULL, adc_clk[1]),
_REGISTER_CLOCK("switch.0", NULL, enet_clk[0]),
_REGISTER_CLOCK("imx2-wdt.0", NULL, dummy_clk),
_REGISTER_CLOCK("sdhci-esdhc-imx.1", NULL, esdhc1_clk),
@@ -1949,7 +2102,6 @@ static void clk_tree_init(void)
__raw_writel(reg, MXC_CCM_CCGR11);
}
-
int __init mvf_clocks_init(unsigned long ckil, unsigned long osc,
unsigned long ckih1, unsigned long ckih2)
{
@@ -1963,8 +2115,10 @@ int __init mvf_clocks_init(unsigned long ckil, unsigned long osc,
apll_base = MVF_IO_ADDRESS(MVF_ANATOP_BASE_ADDR);
- for (i = 0; i < ARRAY_SIZE(lookups); i++)
+ for (i = 0; i < ARRAY_SIZE(lookups); i++) {
clkdev_add(&lookups[i]);
+ clk_debug_register(lookups[i].clk);
+ }
clk_tree_init();
@@ -1976,11 +2130,7 @@ int __init mvf_clocks_init(unsigned long ckil, unsigned long osc,
pll2_528_bus_main_clk.usecount += 5;
periph_clk.usecount++;
ipg_clk.usecount++;
-#if 0
- clk_set_parent(&periph_clk, &pll2_pfd2_396M);
- clk_enable(&periph_clk); /* platform bus clk */
- clk_enable(&ipg_clk); /* ips bus clk */
-#endif
+
clk_enable(&pll3_usb_otg_main_clk);
#ifdef CONFIG_MXC_USE_PIT
@@ -1997,14 +2147,28 @@ int __init mvf_clocks_init(unsigned long ckil, unsigned long osc,
clk_set_parent(&esdhc1_clk, &pll1_pfd3_396M);
clk_set_rate(&esdhc1_clk, 200000000);
+//only for 640x480 and 1024x768
clk_set_parent(&dcu0_clk, &pll1_pfd2_452M);
+//480 MHz
+// clk_set_parent(&dcu0_clk, &pll3_usb_otg_main_clk);
+#if !defined(CONFIG_COLIBRI_VF)
clk_set_rate(&dcu0_clk, 113000000);
-
clk_set_parent(&sai2_clk, &audio_external_clk);
+#else
+ clk_set_rate(&dcu0_clk, 452000000);
+// clk_set_rate(&dcu0_clk, 480000000);
+ clk_set_rate(&pll4_audio_div_clk, 147456000);
+ clk_set_parent(&sai0_clk, &pll4_audio_div_clk);
+ clk_set_parent(&sai2_clk, &pll4_audio_div_clk);
+ clk_set_rate(&sai0_clk, 147456000);
+ clk_enable(&sai0_clk);
+#endif
clk_set_rate(&sai2_clk, 24576000);
+#if !defined(CONFIG_COLIBRI_VF)
clk_set_parent(&qspi0_clk, &pll1_pfd4_528M);
clk_set_rate(&qspi0_clk, 66000000);
- return 0;
+#endif
+ return 0;
}
diff --git a/arch/arm/mach-mvf/crm_regs.h b/arch/arm/mach-mvf/crm_regs.h
index 57fac5bbe973..51a898700baa 100644
--- a/arch/arm/mach-mvf/crm_regs.h
+++ b/arch/arm/mach-mvf/crm_regs.h
@@ -199,6 +199,7 @@
#define MXC_CCM_CLPCR (MXC_CCM_BASE + 0x2c)
#define MXC_CCM_CISR (MXC_CCM_BASE + 0x30)
#define MXC_CCM_CIMR (MXC_CCM_BASE + 0x34)
+#define MXC_CCM_CCOSR (MXC_CCM_BASE + 0x38)
#define MXC_CCM_CGPR (MXC_CCM_BASE + 0x3c)
#define MXC_CCM_CCGR0 (MXC_CCM_BASE + 0x40)
#define MXC_CCM_CCGR1 (MXC_CCM_BASE + 0x44)
@@ -435,6 +436,14 @@
#define MXC_CCM_CIMR_LRF_PLL2 (1 << 1)
#define MXC_CCM_CIMR_LRF_PLL1 (1)
+/* CCOSR */
+#define MXC_CCM_CCOSR_CKO1_EN_OFFSET (10)
+#define MXC_CCM_CCOSR_CKO1_DIV_MASK (0xF << 6)
+#define MXC_CCM_CCOSR_CKO1_DIV_OFFSET (6)
+
+#define MXC_CCM_CCOSR_CKO1_SEL_MASK (0x3F << 0)
+#define MXC_CCM_CCOSR_CKO1_SEL_OFFSET (0)
+
/* Define the bits in registers CGPR */
#define MXC_CCM_CGPR_EFUSE_PROG (1 << 4)
#define MXC_CCM_CGPR_QSPI1_ACCZ (1 << 1)
diff --git a/arch/arm/mach-mvf/mvf_fec.c b/arch/arm/mach-mvf/mvf_fec.c
index d51f20519c0b..55ba44bf73f0 100644
--- a/arch/arm/mach-mvf/mvf_fec.c
+++ b/arch/arm/mach-mvf/mvf_fec.c
@@ -52,7 +52,9 @@ void __init mvf_init_fec(struct fec_platform_data fec_data)
if (!is_valid_ether_addr(fec_data.mac))
memcpy(fec_data.mac, default_mac, ETH_ALEN);
+#if !defined(CONFIG_COLIBRI_VF)
mvf_add_fec(0, &fec_data);
+#endif
#ifdef CONFIG_FEC1
mvf_add_fec(1, &fec_data);
#endif
diff --git a/arch/arm/mach-mvf/system.c b/arch/arm/mach-mvf/system.c
index 989c75a02ed1..6eaefb0dbbb6 100644
--- a/arch/arm/mach-mvf/system.c
+++ b/arch/arm/mach-mvf/system.c
@@ -32,16 +32,24 @@
#include "regs-anadig.h"
#include "regs-pm.h"
-#define SW1_WAKEUP_PIN 38
-#define SW1_PORT1_PCR6_ADDR 0x4004a018
+/* PTB19, GPIO 41, SO-DIMM 45 */
+#define SW1_WAKEUP_GPIO 41
+#define SW1_WAKEUP_PIN 12
+#define SW1_PORT1_PCR9_ADDR MVF_IO_ADDRESS(0x4004a024)
+
+/* PTB20, GPIO 42, SO-DIMM 43 */
+#define SW2_WAKEUP_GPIO 42
+#define SW2_WAKEUP_PIN 13
+#define SW2_PORT1_PCR10_ADDR MVF_IO_ADDRESS(0x4004a028)
static void __iomem *gpc_base = MVF_GPC_BASE;
void gpc_set_wakeup(void)
{
__raw_writel(0xffffffff, gpc_base + GPC_IMR1_OFFSET);
- __raw_writel(0xffffffff, gpc_base + GPC_IMR2_OFFSET);
- /* unmask WKPU0 interrupt */
+ /* unmask UART0 */
+ __raw_writel(0xdfffffff, gpc_base + GPC_IMR2_OFFSET);
+ /* unmask WKPU12/13 interrupt */
__raw_writel(0xefffffff, gpc_base + GPC_IMR3_OFFSET);
/* unmask GPIO4 interrupt */
__raw_writel(0xffff7fff, gpc_base + GPC_IMR4_OFFSET);
@@ -51,13 +59,22 @@ void gpc_set_wakeup(void)
void enable_wkpu(u32 source, u32 rise_fall)
{
- __raw_writel(1 << source, MVF_WKPU_BASE + WKPU_IRER_OFFSET);
- __raw_writel(1 << source, MVF_WKPU_BASE + WKPU_WRER_OFFSET);
-
- if (rise_fall == RISING_EDGE_ENABLED)
- __raw_writel(1 << source, MVF_WKPU_BASE + WKPU_WIREER_OFFSET);
- else
- __raw_writel(1 << source, MVF_WKPU_BASE + WKPU_WIFEER_OFFSET);
+ u32 tmp;
+ tmp = __raw_readl(MVF_WKPU_BASE + WKPU_IRER_OFFSET);
+ __raw_writel(tmp | 1 << source, MVF_WKPU_BASE + WKPU_IRER_OFFSET);
+
+ tmp = __raw_readl(MVF_WKPU_BASE + WKPU_WRER_OFFSET);
+ __raw_writel(tmp | 1 << source, MVF_WKPU_BASE + WKPU_WRER_OFFSET);
+
+ if (rise_fall == RISING_EDGE_ENABLED) {
+ tmp = __raw_readl(MVF_WKPU_BASE + WKPU_WIREER_OFFSET);
+ tmp |= 1 << source;
+ __raw_writel(tmp, MVF_WKPU_BASE + WKPU_WIREER_OFFSET);
+ } else {
+ tmp = __raw_readl(MVF_WKPU_BASE + WKPU_WIFEER_OFFSET);
+ tmp |= 1 << source;
+ __raw_writel(tmp, MVF_WKPU_BASE + WKPU_WIFEER_OFFSET);
+ }
}
static irqreturn_t wkpu_irq(int irq, void *dev_id)
@@ -71,29 +88,41 @@ static irqreturn_t wkpu_irq(int irq, void *dev_id)
return IRQ_NONE;
}
+static void mvf_configure_wakeup_pin(int gpio, int wkup_pin,
+ const volatile void __iomem *pinctl_addr)
+{
+ u32 tmp;
+
+ /* config SW1 for waking up system */
+ gpio_request_one(gpio, GPIOF_IN, "SW wakeup");
+ gpio_set_value(gpio, 0);
+
+ /* Disable IRQC interrupt/dma request in pin contorl register */
+ tmp = __raw_readl(pinctl_addr);
+ tmp &= ~0x000f0000;
+ __raw_writel(tmp, pinctl_addr);
+
+ /* enable WKPU interrupt for this wakeup pin */
+ enable_wkpu(wkup_pin, FALLING_EDGE_ENABLED);
+}
+
/* set cpu multiple modes before WFI instruction */
void mvf_cpu_lp_set(enum mvf_cpu_pwr_mode mode)
{
u32 ccm_ccsr, ccm_clpcr, ccm_ccr;
- u32 tmp;
int ret;
if ((mode == LOW_POWER_STOP) || (mode == STOP_MODE)) {
- /* config SW1 for waking up system */
- gpio_request_one(SW1_WAKEUP_PIN, GPIOF_IN, "SW1 wakeup");
- gpio_set_value(SW1_WAKEUP_PIN, 0);
- /* PORT1_PCR6 IRQC interrupt/dma request disabled */
- tmp = __raw_readl(MVF_IO_ADDRESS(SW1_PORT1_PCR6_ADDR));
- tmp &= ~0x000f0000;
- __raw_writel(tmp, MVF_IO_ADDRESS(SW1_PORT1_PCR6_ADDR));
-
ret = request_irq(MVF_INT_WKPU0, wkpu_irq,
IRQF_DISABLED, "wkpu irq", NULL);
+
if (ret)
printk(KERN_ERR "Request wkpu IRQ failed\n");
- /* enable WKPU interrupt */
- enable_wkpu(11, FALLING_EDGE_ENABLED);
+ mvf_configure_wakeup_pin(SW1_WAKEUP_GPIO, SW1_WAKEUP_PIN,
+ SW1_PORT1_PCR9_ADDR);
+ mvf_configure_wakeup_pin(SW2_WAKEUP_GPIO, SW2_WAKEUP_PIN,
+ SW2_PORT1_PCR10_ADDR);
}
ccm_ccr = __raw_readl(MXC_CCM_CCR);