[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