[PATCH] [ARM] mx27: Add ARMadeus Systems APF27 board support
julien.boibessot at free.fr
julien.boibessot at free.fr
Mon Apr 4 10:55:50 EDT 2011
From: Julien Boibessot <julien.boibessot at armadeus.com>
The APF27 is an i.M27 based SOM (System On Module) that can be plugged on
several docking/development boards. Here only basic module support
is added (Ethernet, Serial, NAND Flash, USB OTG).
Signed-off-by: Julien Boibessot <julien.boibessot at armadeus.com>
Signed-off-by: Eric Jarrige <eric.jarrige at armadeus.org>
Signed-off-by: Nicolas Colombain <nicolas.colombain at armadeus.com>
---
arch/arm/mach-imx/Kconfig | 13 ++
arch/arm/mach-imx/Makefile | 1 +
arch/arm/mach-imx/mach-apf27.c | 258 +++++++++++++++++++++++++++
arch/arm/plat-mxc/include/mach/uncompress.h | 1 +
4 files changed, 273 insertions(+), 0 deletions(-)
create mode 100644 arch/arm/mach-imx/mach-apf27.c
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index 5eec099..433a420 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -312,4 +312,17 @@ config MACH_IMX27IPCAM
Include support for IMX27 IPCAM platform. This includes specific
configurations for the board and its peripherals.
+config MACH_APF27
+ bool "Armadeus Systems APF27"
+ select SOC_IMX27
+ select IMX_HAVE_PLATFORM_FSL_USB2_UDC
+ select IMX_HAVE_PLATFORM_IMX2_WDT
+ select IMX_HAVE_PLATFORM_IMX_I2C
+ select IMX_HAVE_PLATFORM_IMX_UART
+ select IMX_HAVE_PLATFORM_MXC_NAND
+ select MXC_ULPI if USB_ULPI
+ help
+ Include support for APF27 platform. This includes specific
+ configurations for the module and its peripherals.
+
endif
diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
index b85794d..8d557a4 100644
--- a/arch/arm/mach-imx/Makefile
+++ b/arch/arm/mach-imx/Makefile
@@ -37,3 +37,4 @@ obj-$(CONFIG_MACH_EUKREA_MBIMX27_BASEBOARD) += eukrea_mbimx27-baseboard.o
obj-$(CONFIG_MACH_PCA100) += mach-pca100.o
obj-$(CONFIG_MACH_MXT_TD60) += mach-mxt_td60.o
obj-$(CONFIG_MACH_IMX27IPCAM) += mach-imx27ipcam.o
+obj-$(CONFIG_MACH_APF27) += mach-apf27.o
diff --git a/arch/arm/mach-imx/mach-apf27.c b/arch/arm/mach-imx/mach-apf27.c
new file mode 100644
index 0000000..f963953
--- /dev/null
+++ b/arch/arm/mach-imx/mach-apf27.c
@@ -0,0 +1,258 @@
+ /*
+ * Support for the APF27 System On Module
+ *
+ * Copyright (C) 2008-2011 ARMadeus Systems <support at armadeus.com>
+ *
+ * Based on code which is:
+ * Copyright 2007 Robert Schwebel <r.schwebel at pengutronix.de>, Pengutronix
+ * Copyright (C) 2008 Juergen Beisert (kernel at pengutronix.de)
+ * Copyright 2009 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+#include <linux/platform_device.h>
+#include <linux/i2c.h>
+#include <linux/serial.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/usb/otg.h>
+#include <linux/usb/ulpi.h>
+#include <linux/phy.h>
+
+#include <asm/mach/flash.h>
+#include <asm/mach/arch.h>
+#include <asm/mach-types.h>
+#include <asm/mach/time.h>
+#include <mach/common.h>
+#include <mach/hardware.h>
+#include <mach/iomux-mx27.h>
+#include <mach/gpio.h>
+#include <mach/imx-uart.h>
+#include <mach/mxc_nand.h>
+#include <mach/mxc_ehci.h>
+#include <mach/ulpi.h>
+
+#include "devices-imx27.h"
+
+
+static const int apf27_pins[] __initconst = {
+ /* UART1 */
+ PE12_PF_UART1_TXD,
+ PE13_PF_UART1_RXD,
+ /* USB_OTG */
+ PE0_PF_USBOTG_NXT,
+ PE1_PF_USBOTG_STP,
+ PE2_PF_USBOTG_DIR,
+ PE24_PF_USBOTG_CLK,
+ PE25_PF_USBOTG_DATA7,
+ PC7_PF_USBOTG_DATA5,
+ PC8_PF_USBOTG_DATA6,
+ PC9_PF_USBOTG_DATA0,
+ PC10_PF_USBOTG_DATA2,
+ PC11_PF_USBOTG_DATA1,
+ PC12_PF_USBOTG_DATA4,
+ PC13_PF_USBOTG_DATA3,
+ /* UART3 */
+ PE8_PF_UART3_TXD,
+ PE9_PF_UART3_RXD,
+ PE10_PF_UART3_CTS,
+ PE11_PF_UART3_RTS,
+ /* ETHERNET */
+ PD0_AIN_FEC_TXD0,
+ PD1_AIN_FEC_TXD1,
+ PD2_AIN_FEC_TXD2,
+ PD3_AIN_FEC_TXD3,
+ PD4_AOUT_FEC_RX_ER,
+ PD5_AOUT_FEC_RXD1,
+ PD6_AOUT_FEC_RXD2,
+ PD7_AOUT_FEC_RXD3,
+ PD8_AF_FEC_MDIO,
+ PD9_AIN_FEC_MDC,
+ PD10_AOUT_FEC_CRS,
+ PD11_AOUT_FEC_TX_CLK,
+ PD12_AOUT_FEC_RXD0,
+ PD13_AOUT_FEC_RX_DV,
+ PD14_AOUT_FEC_RX_CLK,
+ PD15_AOUT_FEC_COL,
+ PD16_AIN_FEC_TX_ER,
+ PF23_AIN_FEC_TX_EN,
+ /* I2C2 */
+ PC5_PF_I2C2_SDA,
+ PC6_PF_I2C2_SCL,
+};
+
+/* APF27 has an "on module" Ethernet transceiver */
+int lan8700_wakeup(struct phy_device *phydev)
+{
+#define LAN87xx_SPECIAL_REG 0x12
+
+ int rc = phy_read(phydev, LAN87xx_SPECIAL_REG);
+
+ phy_write(phydev, LAN87xx_SPECIAL_REG, rc | 0xE0);
+ phy_write(phydev, MII_BMCR, BMCR_RESET);
+ udelay(1000);
+ return 0;
+}
+
+/* APF27 has a Micron 128MiB 1,8V NAND flash, 16 bits width */
+static const struct mxc_nand_platform_data apf27_nand_board_info __initconst = {
+ .width = 2,
+ .hw_ecc = 1,
+ .flash_bbt = 1, /* we handle Bad Block Table */
+};
+
+/* APF27 has an I2C EEPROM on I2C2 Bus */
+static const struct imxi2c_platform_data apf27_i2c_1_data __initconst = {
+ .bitrate = 100000,
+};
+
+static struct i2c_board_info apf27_i2c_devices_bus1[] = {
+ {
+ I2C_BOARD_INFO("24c02", 0x50),
+ },
+};
+
+/* APF27 has an RS232 debug port/console on UART1 with "on module"
+ transceiver */
+static struct imxuart_platform_data uart0_pdata = {
+ .flags = 0,
+};
+
+/* APF27 has an "on module" transceiver for UART3 */
+static struct imxuart_platform_data uart2_pdata = {
+ .flags = IMXUART_HAVE_RTSCTS,
+};
+
+/* APF27 has an "on module" transceiver for USB OTG */
+static int otg_mode_host = 1;
+
+static int __init apf27_otg_mode(char *options)
+{
+ if (!strcmp(options, "host"))
+ otg_mode_host = 1;
+ else if (!strcmp(options, "device"))
+ otg_mode_host = 0;
+ else
+ pr_info("otg_mode neither \"host\" nor \"device\". "
+ "Defaulting to host\n");
+
+ return 0;
+}
+__setup("otg_mode=", apf27_otg_mode);
+
+static void apf27_usbotg_phy_init(void)
+{
+#define USBCTRL_OFFSET 0x600
+#define USBCTRL_UIE_BIT (1 << 28)
+#define USBCTRL_WIE_BIT (1 << 27)
+#define USBCMD_OFFSET 0x140
+#define USBCMD_RST_BIT (1 << 1)
+#define PORTSC1_OFFSET 0x184
+#define PORTSC_PTS_MASK (3 << 30)
+#define PORTSC_PTS_ULPI (2 << 30)
+
+ unsigned int reg;
+
+ /* Tweak power/wake up handling */
+ reg = readl(MX27_IO_ADDRESS(MX27_USB_BASE_ADDR) + USBCTRL_OFFSET);
+ reg |= USBCTRL_WIE_BIT | USBCTRL_UIE_BIT;
+ writel(reg, MX27_IO_ADDRESS(MX27_USB_BASE_ADDR) + USBCTRL_OFFSET);
+
+ /* Select ULPI PHY */
+ reg = readl(MX27_IO_ADDRESS(MX27_USB_BASE_ADDR) + PORTSC1_OFFSET);
+ reg = (reg & ~PORTSC_PTS_MASK) | PORTSC_PTS_ULPI;
+ writel(reg, MX27_IO_ADDRESS(MX27_USB_BASE_ADDR) + PORTSC1_OFFSET);
+ mdelay(10);
+
+ /* Reset PHY */
+ reg = readl(MX27_IO_ADDRESS(MX27_USB_BASE_ADDR) + USBCMD_OFFSET);
+ reg |= USBCMD_RST_BIT;
+ writel(reg, MX27_IO_ADDRESS(MX27_USB_BASE_ADDR) + USBCMD_OFFSET);
+ mdelay(10);
+}
+
+static int apf27_otg_init(struct platform_device *pdev)
+{
+ int ret;
+
+ ret = mx27_initialize_usb_hw(pdev->id, MXC_EHCI_INTERFACE_DIFF_UNI);
+ apf27_usbotg_phy_init(); /* PHY is in powerdown mode by default */
+
+ return ret;
+}
+
+static struct mxc_usbh_platform_data otg_pdata __initdata = {
+ .init = apf27_otg_init,
+ .portsc = MXC_EHCI_MODE_ULPI,
+};
+
+static const struct fsl_usb2_platform_data otg_device_pdata __initconst = {
+ .operating_mode = FSL_USB2_DR_DEVICE,
+ .phy_mode = FSL_USB2_PHY_ULPI,
+};
+
+static void __init apf27_init(void)
+{
+ int ret;
+
+ ret = mxc_gpio_setup_multiple_pins(apf27_pins,
+ ARRAY_SIZE(apf27_pins), "APF27");
+ if (ret)
+ printk(KERN_ERR "apf27: Failed to setup pins (%d)\n", ret);
+
+ imx27_add_imx_uart0(&uart0_pdata);
+ imx27_add_imx_uart2(&uart2_pdata);
+
+ /* bring lan8700 out of power down mode */
+ phy_register_fixup_for_id("1:1f", lan8700_wakeup);
+ imx27_add_fec(NULL);
+
+ imx27_add_mxc_nand(&apf27_nand_board_info);
+
+ imx27_add_imx2_wdt(NULL);
+
+ if (otg_mode_host) {
+ otg_pdata.otg = imx_otg_ulpi_create(ULPI_OTG_DRVVBUS |
+ ULPI_OTG_DRVVBUS_EXT);
+ if (otg_pdata.otg)
+ imx27_add_mxc_ehci_otg(&otg_pdata);
+ }
+ if (!otg_mode_host)
+ imx27_add_fsl_usb2_udc(&otg_device_pdata);
+
+ i2c_register_board_info(1, apf27_i2c_devices_bus1,
+ ARRAY_SIZE(apf27_i2c_devices_bus1));
+ imx27_add_imx_i2c(1, &apf27_i2c_1_data);
+}
+
+static void __init apf27_timer_init(void)
+{
+ mx27_clocks_init(26000000); /* init ext ref, even if not used */
+}
+
+static struct sys_timer apf27_timer = {
+ .init = apf27_timer_init,
+};
+
+MACHINE_START(APF27, "Armadeus APF27")
+ /* Maintainer: Julien Boibessot <julien.boibessot at armadeus.com> */
+ .boot_params = MX27_PHYS_OFFSET + 0x100,
+ .map_io = mx27_map_io,
+ .init_early = imx27_init_early,
+ .init_irq = mx27_init_irq,
+ .timer = &apf27_timer,
+ .init_machine = apf27_init,
+MACHINE_END
diff --git a/arch/arm/plat-mxc/include/mach/uncompress.h b/arch/arm/plat-mxc/include/mach/uncompress.h
index 4864b0a..e3ef62c 100644
--- a/arch/arm/plat-mxc/include/mach/uncompress.h
+++ b/arch/arm/plat-mxc/include/mach/uncompress.h
@@ -85,6 +85,7 @@ static __inline__ void __arch_decomp_setup(unsigned long arch_id)
case MACH_TYPE_PCA100:
case MACH_TYPE_MXT_TD60:
case MACH_TYPE_IMX27IPCAM:
+ case MACH_TYPE_APF27:
uart_base = MX2X_UART1_BASE_ADDR;
break;
case MACH_TYPE_MX31LITE:
--
1.6.0.4
More information about the linux-arm-kernel
mailing list