[PATCH 5/7] ARM i.MX51: Add support for the Efika MX Smartbook

Sascha Hauer s.hauer at pengutronix.de
Thu Dec 13 16:49:08 EST 2012


The Efika MX Smartbook is a i.MX51 based netbook. This patch adds
nearly full support for it including:

- USB
- SD card slots
- Internal SPI NOR flash
- Internal flash PATA drive
- LEDs

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 arch/arm/Makefile                                  |    1 +
 arch/arm/boards/efika-mx-smartbook/Makefile        |    3 +
 arch/arm/boards/efika-mx-smartbook/board.c         |  511 ++++++++++++++++++++
 arch/arm/boards/efika-mx-smartbook/config.h        |   24 +
 arch/arm/boards/efika-mx-smartbook/dcd-data.h      |   56 +++
 .../boards/efika-mx-smartbook/env/bin/lvds_init    |   22 +
 .../boards/efika-mx-smartbook/env/boot/hd-internal |   17 +
 .../boards/efika-mx-smartbook/env/boot/mmc-left    |   19 +
 arch/arm/boards/efika-mx-smartbook/env/config      |   29 ++
 .../boards/efika-mx-smartbook/env/init/automount   |   29 ++
 .../boards/efika-mx-smartbook/env/init/bootsource  |   10 +
 .../efika-mx-smartbook/env/init/config-board       |    9 +
 .../efika-mx-smartbook/env/network/eth0-discover   |    4 +
 arch/arm/boards/efika-mx-smartbook/flash_header.c  |   29 ++
 arch/arm/mach-imx/Kconfig                          |    8 +
 defaultenv-2/base/boot/net                         |    4 +-
 drivers/usb/core/usb.c                             |    8 +-
 drivers/usb/host/ehci-hcd.c                        |    6 +
 drivers/usb/otg/ulpi.c                             |   33 +-
 include/usb/ulpi.h                                 |   43 +-
 20 files changed, 843 insertions(+), 22 deletions(-)
 create mode 100644 arch/arm/boards/efika-mx-smartbook/Makefile
 create mode 100644 arch/arm/boards/efika-mx-smartbook/board.c
 create mode 100644 arch/arm/boards/efika-mx-smartbook/config.h
 create mode 100644 arch/arm/boards/efika-mx-smartbook/dcd-data.h
 create mode 100644 arch/arm/boards/efika-mx-smartbook/env/bin/lvds_init
 create mode 100644 arch/arm/boards/efika-mx-smartbook/env/boot/hd-internal
 create mode 100644 arch/arm/boards/efika-mx-smartbook/env/boot/mmc-left
 create mode 100644 arch/arm/boards/efika-mx-smartbook/env/config
 create mode 100644 arch/arm/boards/efika-mx-smartbook/env/init/automount
 create mode 100644 arch/arm/boards/efika-mx-smartbook/env/init/bootsource
 create mode 100644 arch/arm/boards/efika-mx-smartbook/env/init/config-board
 create mode 100644 arch/arm/boards/efika-mx-smartbook/env/network/eth0-discover
 create mode 100644 arch/arm/boards/efika-mx-smartbook/flash_header.c

diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 3bd645f..478b0d8 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -150,6 +150,7 @@ board-$(CONFIG_MACH_TINY210)			:= friendlyarm-tiny210
 board-$(CONFIG_MACH_SABRELITE)			:= freescale-mx6-sabrelite
 board-$(CONFIG_MACH_TX53)			:= karo-tx53
 board-$(CONFIG_MACH_GUF_VINCELL)		:= guf-vincell
+board-$(CONFIG_MACH_EFIKA_MX_SMARTBOOK)		:= efika-mx-smartbook
 
 machdirs := $(patsubst %,arch/arm/mach-%/,$(machine-y))
 
diff --git a/arch/arm/boards/efika-mx-smartbook/Makefile b/arch/arm/boards/efika-mx-smartbook/Makefile
new file mode 100644
index 0000000..d08bb68
--- /dev/null
+++ b/arch/arm/boards/efika-mx-smartbook/Makefile
@@ -0,0 +1,3 @@
+obj-y += board.o
+obj-y += flash_header.o
+pbl-y += flash_header.o
diff --git a/arch/arm/boards/efika-mx-smartbook/board.c b/arch/arm/boards/efika-mx-smartbook/board.c
new file mode 100644
index 0000000..aef2750
--- /dev/null
+++ b/arch/arm/boards/efika-mx-smartbook/board.c
@@ -0,0 +1,511 @@
+/*
+ * Copyright (C) 2007 Sascha Hauer, Pengutronix
+ *
+ * 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.
+ *
+ */
+
+#include <common.h>
+#include <net.h>
+#include <init.h>
+#include <environment.h>
+#include <mach/gpio.h>
+#include <asm/armlinux.h>
+#include <partition.h>
+#include <notifier.h>
+#include <fs.h>
+#include <led.h>
+#include <fcntl.h>
+#include <nand.h>
+#include <usb/ulpi.h>
+#include <usb/chipidea-imx.h>
+#include <spi/spi.h>
+#include <mfd/mc13xxx.h>
+#include <mfd/mc13892.h>
+#include <asm/io.h>
+#include <asm/mmu.h>
+#include <mach/imx-nand.h>
+#include <mach/spi.h>
+#include <mach/generic.h>
+#include <mach/imx5.h>
+#include <mach/bbu.h>
+#include <mach/iomux-mx51.h>
+#include <mach/imx51-regs.h>
+#include <mach/devices-imx51.h>
+#include <mach/imx-flash-header.h>
+#include <mach/revision.h>
+
+#define GPIO_EFIKA_SDHC1_WP	IMX_GPIO_NR(1, 1)
+#define GPIO_EFIKAMX_SDHC1_CD	IMX_GPIO_NR(1, 0)
+#define GPIO_EFIKASB_SDHC1_CD	IMX_GPIO_NR(2, 27)
+#define GPIO_EFIKASB_SDHC2_CD	IMX_GPIO_NR(1, 8)
+#define GPIO_EFIKASB_SDHC2_WP	IMX_GPIO_NR(1, 7)
+
+#define GPIO_BACKLIGHT_POWER	IMX_GPIO_NR(4, 12)
+#define GPIO_BACKLIGHT_PWM	IMX_GPIO_NR(1, 2)
+#define GPIO_LVDS_POWER		IMX_GPIO_NR(3, 7)
+#define GPIO_LVDS_RESET		IMX_GPIO_NR(3, 5)
+#define GPIO_LVDS_ENABLE	IMX_GPIO_NR(3, 12)
+#define GPIO_LCD_ENABLE		IMX_GPIO_NR(3, 13)
+
+#define GPIO_BLUETOOTH		IMX_GPIO_NR(2, 11)
+#define GPIO_WIFI_ENABLE	IMX_GPIO_NR(2, 16)
+#define GPIO_WIFI_RESET		IMX_GPIO_NR(2, 10)
+#define GPIO_HUB_RESET		IMX_GPIO_NR(1, 5)
+#define GPIO_SMSC3317_RESET	IMX_GPIO_NR(2, 9)
+
+static iomux_v3_cfg_t efika_pads[] = {
+	/* ECSPI1 */
+	MX51_PAD_CSPI1_MOSI__ECSPI1_MOSI,
+	MX51_PAD_CSPI1_MISO__ECSPI1_MISO,
+	MX51_PAD_CSPI1_SCLK__ECSPI1_SCLK,
+	MX51_PAD_CSPI1_SS0__GPIO4_24,
+	MX51_PAD_CSPI1_SS1__GPIO4_25,
+	MX51_PAD_GPIO1_6__GPIO1_6,
+
+	/* ESDHC1 */
+	MX51_PAD_SD1_CMD__SD1_CMD,
+	MX51_PAD_SD1_CLK__SD1_CLK,
+	MX51_PAD_SD1_DATA0__SD1_DATA0,
+	MX51_PAD_SD1_DATA1__SD1_DATA1,
+	MX51_PAD_SD1_DATA2__SD1_DATA2,
+	MX51_PAD_SD1_DATA3__SD1_DATA3,
+	MX51_PAD_GPIO1_1__GPIO1_1,
+
+	/* USB HOST2 */
+	MX51_PAD_EIM_D27__GPIO2_9,
+	MX51_PAD_GPIO1_5__GPIO1_5,
+	MX51_PAD_EIM_D16__USBH2_DATA0,
+	MX51_PAD_EIM_D17__USBH2_DATA1,
+	MX51_PAD_EIM_D18__USBH2_DATA2,
+	MX51_PAD_EIM_D19__USBH2_DATA3,
+	MX51_PAD_EIM_D20__USBH2_DATA4,
+	MX51_PAD_EIM_D21__USBH2_DATA5,
+	MX51_PAD_EIM_D22__USBH2_DATA6,
+	MX51_PAD_EIM_D23__USBH2_DATA7,
+	MX51_PAD_EIM_A24__USBH2_CLK,
+	MX51_PAD_EIM_A25__USBH2_DIR,
+	MX51_PAD_EIM_A26__GPIO2_20,
+	MX51_PAD_EIM_A27__USBH2_NXT,
+
+	/* USB HOST1 */
+        MX51_PAD_USBH1_CLK__USBH1_CLK,
+        MX51_PAD_USBH1_DIR__USBH1_DIR,
+        MX51_PAD_USBH1_NXT__USBH1_NXT,
+        MX51_PAD_USBH1_DATA0__USBH1_DATA0,
+        MX51_PAD_USBH1_DATA1__USBH1_DATA1,
+        MX51_PAD_USBH1_DATA2__USBH1_DATA2,
+        MX51_PAD_USBH1_DATA3__USBH1_DATA3,
+        MX51_PAD_USBH1_DATA4__USBH1_DATA4,
+        MX51_PAD_USBH1_DATA5__USBH1_DATA5,
+        MX51_PAD_USBH1_DATA6__USBH1_DATA6,
+        MX51_PAD_USBH1_DATA7__USBH1_DATA7,
+	MX51_PAD_USBH1_STP__GPIO1_27,
+	MX51_PAD_EIM_A16__GPIO2_10,
+
+	/* PATA */
+	MX51_PAD_NANDF_WE_B__PATA_DIOW,
+	MX51_PAD_NANDF_RE_B__PATA_DIOR,
+	MX51_PAD_NANDF_ALE__PATA_BUFFER_EN,
+	MX51_PAD_NANDF_CLE__PATA_RESET_B,
+	MX51_PAD_NANDF_WP_B__PATA_DMACK,
+	MX51_PAD_NANDF_RB0__PATA_DMARQ,
+	MX51_PAD_NANDF_RB1__PATA_IORDY,
+	MX51_PAD_GPIO_NAND__PATA_INTRQ,
+	MX51_PAD_NANDF_CS2__PATA_CS_0,
+	MX51_PAD_NANDF_CS3__PATA_CS_1,
+	MX51_PAD_NANDF_CS4__PATA_DA_0,
+	MX51_PAD_NANDF_CS5__PATA_DA_1,
+	MX51_PAD_NANDF_CS6__PATA_DA_2,
+	MX51_PAD_NANDF_D15__PATA_DATA15,
+	MX51_PAD_NANDF_D14__PATA_DATA14,
+	MX51_PAD_NANDF_D13__PATA_DATA13,
+	MX51_PAD_NANDF_D12__PATA_DATA12,
+	MX51_PAD_NANDF_D11__PATA_DATA11,
+	MX51_PAD_NANDF_D10__PATA_DATA10,
+	MX51_PAD_NANDF_D9__PATA_DATA9,
+	MX51_PAD_NANDF_D8__PATA_DATA8,
+	MX51_PAD_NANDF_D7__PATA_DATA7,
+	MX51_PAD_NANDF_D6__PATA_DATA6,
+	MX51_PAD_NANDF_D5__PATA_DATA5,
+	MX51_PAD_NANDF_D4__PATA_DATA4,
+	MX51_PAD_NANDF_D3__PATA_DATA3,
+	MX51_PAD_NANDF_D2__PATA_DATA2,
+	MX51_PAD_NANDF_D1__PATA_DATA1,
+	MX51_PAD_NANDF_D0__PATA_DATA0,
+
+	/* USB U-Boot */
+	MX51_PAD_EIM_A22__GPIO2_16, /* WLAN enable (1 = on) */
+	MX51_PAD_EIM_A17__GPIO2_11,
+
+	/* I2C2 */
+	MX51_PAD_KEY_COL4__I2C2_SCL,
+	MX51_PAD_KEY_COL5__I2C2_SDA,
+
+	MX51_PAD_GPIO1_2__GPIO1_2, /* Backlight (should be pwm) (1 = on) */
+	MX51_PAD_CSI2_D19__GPIO4_12, /* Backlight power (0 = on) */
+
+	MX51_PAD_DISPB2_SER_CLK__GPIO3_7, /* LVDS power (1 = on) */
+	MX51_PAD_DISPB2_SER_DIN__GPIO3_5, /* LVDS reset (1 = reset) */
+	MX51_PAD_CSI1_D8__GPIO3_12, /* LVDS enable (1 = enable) */
+	MX51_PAD_CSI1_D9__GPIO3_13, /* LCD enable (1 = on) */
+
+	MX51_PAD_DI1_PIN12__GPIO3_1, /* WLAN switch (0 = on) */
+
+	MX51_PAD_GPIO1_4__WDOG1_WDOG_B,
+};
+
+static iomux_v3_cfg_t efikasb_pads[] = {
+	/* LEDs */
+	MX51_PAD_EIM_CS0__GPIO2_25,
+	MX51_PAD_GPIO1_3__GPIO1_3,
+
+	/* ESHC2 */
+	MX51_PAD_SD2_CMD__SD2_CMD,
+	MX51_PAD_SD2_CLK__SD2_CLK,
+	MX51_PAD_SD2_DATA0__SD2_DATA0,
+	MX51_PAD_SD2_DATA1__SD2_DATA1,
+	MX51_PAD_SD2_DATA2__SD2_DATA2,
+	MX51_PAD_SD2_DATA3__SD2_DATA3,
+	MX51_PAD_GPIO1_7__GPIO1_7,
+	MX51_PAD_GPIO1_8__GPIO1_8,
+
+	MX51_PAD_EIM_CS2__GPIO2_27,
+};
+
+static iomux_v3_cfg_t efikamx_pads[] = {
+	MX51_PAD_GPIO1_0__GPIO1_0,
+};
+
+/*
+ * Generally this should work on the Efika MX smarttop aswell,
+ * but I do not have the hardware to test it, so hardcode this
+ * for the smartbook for now.
+ */
+static inline int machine_is_efikasb(void)
+{
+	return 1;
+}
+
+static int efikamx_mem_init(void)
+{
+	arm_add_mem_device("ram0", 0x90000000, SZ_512M);
+
+        return 0;
+}
+mem_initcall(efikamx_mem_init);
+
+static int spi_0_cs[] = { IMX_GPIO_NR(4, 24), IMX_GPIO_NR(4, 25) };
+
+static struct spi_imx_master spi_0_data = {
+	.chipselect = spi_0_cs,
+	.num_chipselect = ARRAY_SIZE(spi_0_cs),
+};
+
+static const struct spi_board_info efikamx_spi_board_info[] = {
+	{
+		.name = "mc13xxx-spi",
+		.max_speed_hz = 30 * 1000 * 1000,
+		.bus_num = 0,
+		.chip_select = 0,
+	}, {
+		.name = "m25p80",
+		.chip_select = 1,
+		.max_speed_hz = 20 * 1000 * 1000,
+		.bus_num = 0,
+        },
+};
+
+static void efikamx_power_init(void)
+{
+	unsigned int val;
+	struct mc13xxx *mc;
+
+	mc = mc13xxx_get();
+	if (!mc) {
+		printf("could not get mc13892\n");
+		return;
+	}
+
+	/* Write needed to Power Gate 2 register */
+	mc13xxx_reg_read(mc, MC13892_REG_POWER_MISC, &val);
+	val &= ~MC13892_POWER_MISC_PWGT2SPIEN;
+	mc13xxx_reg_write(mc, MC13892_REG_POWER_MISC, val);
+
+	/* Externally powered */
+	mc13xxx_reg_read(mc, MC13892_REG_CHARGE, &val);
+	val |= MC13782_CHARGE_ICHRG0 | MC13782_CHARGE_ICHRG1 |
+		MC13782_CHARGE_ICHRG2 | MC13782_CHARGE_ICHRG3 |
+		MC13782_CHARGE_CHGAUTOB;
+	mc13xxx_reg_write(mc, MC13892_REG_CHARGE, val);
+
+	/* power up the system first */
+	mc13xxx_reg_write(mc, MC13892_REG_POWER_MISC,
+			MC13892_POWER_MISC_PWUP);
+
+	/* Set core voltage to 1.1V */
+	mc13xxx_reg_read(mc, MC13892_REG_SW_0, &val);
+	val &= ~MC13892_SWx_SWx_VOLT_MASK;
+	val |= MC13892_SWx_SWx_1_100V;
+	mc13xxx_reg_write(mc, MC13892_REG_SW_0, val);
+
+	/* Setup VCC (SW2) to 1.25 */
+	mc13xxx_reg_read(mc, MC13892_REG_SW_1, &val);
+	val &= ~MC13892_SWx_SWx_VOLT_MASK;
+	val |= MC13892_SWx_SWx_1_250V;
+	mc13xxx_reg_write(mc, MC13892_REG_SW_1, val);
+
+	/* Setup 1V2_DIG1 (SW3) to 1.25 */
+	mc13xxx_reg_read(mc, MC13892_REG_SW_2, &val);
+	val &= ~MC13892_SWx_SWx_VOLT_MASK;
+	val |= MC13892_SWx_SWx_1_250V;
+	mc13xxx_reg_write(mc, MC13892_REG_SW_2, val);
+	udelay(50);
+
+	/* Raise the core frequency to 800MHz */
+	console_flush();	
+	imx51_init_lowlevel(800);
+	clock_notifier_call_chain();
+
+	/* Set switchers in Auto in NORMAL mode & STANDBY mode */
+	/* Setup the switcher mode for SW1 & SW2*/
+	mc13xxx_reg_read(mc, MC13892_REG_SW_4, &val);
+	val = (val & ~((MC13892_SWMODE_MASK << MC13892_SWMODE1_SHIFT) |
+			(MC13892_SWMODE_MASK << MC13892_SWMODE2_SHIFT)));
+	val |= (MC13892_SWMODE_AUTO_AUTO << MC13892_SWMODE1_SHIFT) |
+		(MC13892_SWMODE_AUTO_AUTO << MC13892_SWMODE2_SHIFT);
+	mc13xxx_reg_write(mc, MC13892_REG_SW_4, val);
+
+	/* Setup the switcher mode for SW3 & SW4 */
+	mc13xxx_reg_read(mc, MC13892_REG_SW_5, &val);
+	val = (val & ~((MC13892_SWMODE_MASK << MC13892_SWMODE3_SHIFT) |
+			(MC13892_SWMODE_MASK << MC13892_SWMODE4_SHIFT)));
+	val |= (MC13892_SWMODE_AUTO_AUTO << MC13892_SWMODE3_SHIFT) |
+		(MC13892_SWMODE_AUTO_AUTO << MC13892_SWMODE4_SHIFT);
+	mc13xxx_reg_write(mc, MC13892_REG_SW_5, val);
+
+	/* Set VDIG to 1.8V, VGEN3 to 1.8V, VCAM to 2.6V */
+	mc13xxx_reg_read(mc, MC13892_REG_SETTING_0, &val);
+	val &= ~(MC13892_SETTING_0_VCAM_MASK |
+                        MC13892_SETTING_0_VGEN3_MASK |
+                        MC13892_SETTING_0_VDIG_MASK);
+	val |= MC13892_SETTING_0_VDIG_1_8 |
+                MC13892_SETTING_0_VGEN3_1_8 |
+                MC13892_SETTING_0_VCAM_2_6;
+	mc13xxx_reg_write(mc, MC13892_REG_SETTING_0, val);
+
+	/* Set VVIDEO to 2.775V, VAUDIO to 3V, VSD to 3.15V */
+	mc13xxx_reg_read(mc, MC13892_REG_SETTING_1, &val);
+	val &= ~(MC13892_SETTING_1_VVIDEO_MASK |
+			MC13892_SETTING_1_VSD_MASK |
+			MC13892_SETTING_1_VAUDIO_MASK);
+	val |= MC13892_SETTING_1_VSD_3_15 |
+		MC13892_SETTING_1_VAUDIO_3_0 |
+		MC13892_SETTING_1_VVIDEO_2_775 |
+		MC13892_SETTING_1_VGEN1_1_2 |
+		MC13892_SETTING_1_VGEN2_3_15;
+	mc13xxx_reg_write(mc, MC13892_REG_SETTING_1, val);
+
+	/* Enable VGEN1, VGEN2, VDIG, VPLL */
+	mc13xxx_reg_read(mc, MC13892_REG_MODE_0, &val);
+	val |= MC13892_MODE_0_VGEN1EN |
+		MC13892_MODE_0_VDIGEN |
+		MC13892_MODE_0_VGEN2EN |
+		MC13892_MODE_0_VPLLEN;
+	mc13xxx_reg_write(mc, MC13892_REG_MODE_0, val);
+
+	/* Configure VGEN3 and VCAM regulators to use external PNP */
+	val = MC13892_MODE_1_VGEN3CONFIG |
+		MC13892_MODE_1_VCAMCONFIG;
+	mc13xxx_reg_write(mc, MC13892_REG_MODE_1, val);
+	udelay(200);
+
+	/* Enable VGEN3, VCAM, VAUDIO, VVIDEO, VSD regulators */
+	val = MC13892_MODE_1_VGEN3EN |
+		MC13892_MODE_1_VGEN3CONFIG |
+		MC13892_MODE_1_VCAMEN |
+		MC13892_MODE_1_VCAMCONFIG |
+		MC13892_MODE_1_VVIDEOEN |
+		MC13892_MODE_1_VAUDIOEN |
+		MC13892_MODE_1_VSDEN;
+	mc13xxx_reg_write(mc, MC13892_REG_MODE_1, val);
+
+	mc13xxx_reg_read(mc, MC13892_REG_POWER_CTL2, &val);
+	val |= MC13892_POWER_CONTROL_2_WDIRESET;
+	mc13xxx_reg_write(mc, MC13892_REG_POWER_CTL2, val);
+
+	udelay(2500);
+}
+
+static struct esdhc_platform_data efikasb_sd2_data = {
+	.cd_gpio = GPIO_EFIKASB_SDHC2_CD,
+	.wp_gpio = GPIO_EFIKASB_SDHC2_WP,
+	.cd_type = ESDHC_CD_GPIO,
+	.wp_type = ESDHC_WP_GPIO,
+	.devname = "mmc_left",
+};
+
+static struct esdhc_platform_data efikamx_sd1_data = {
+	.cd_gpio = GPIO_EFIKAMX_SDHC1_CD,
+	.wp_gpio = GPIO_EFIKA_SDHC1_WP,
+	.cd_type = ESDHC_CD_GPIO,
+	.wp_type = ESDHC_WP_GPIO,
+};
+
+static struct esdhc_platform_data efikasb_sd1_data = {
+	.cd_gpio = GPIO_EFIKASB_SDHC1_CD,
+	.wp_gpio = GPIO_EFIKA_SDHC1_WP,
+	.cd_type = ESDHC_CD_GPIO,
+	.wp_type = ESDHC_WP_GPIO,
+	.devname = "mmc_back",
+};
+
+struct imxusb_platformdata efikamx_usbh1_pdata = {
+	.flags = MXC_EHCI_MODE_ULPI | MXC_EHCI_INTERFACE_DIFF_UNI,
+	.mode = IMX_USB_MODE_HOST,
+};
+
+static int efikamx_usb_init(void)
+{
+	gpio_direction_output(GPIO_BLUETOOTH, 0);
+	gpio_direction_output(GPIO_WIFI_ENABLE, 1);
+	gpio_direction_output(GPIO_WIFI_RESET, 0);
+	gpio_direction_output(GPIO_SMSC3317_RESET, 0);
+	gpio_direction_output(GPIO_HUB_RESET, 0);
+
+	mdelay(10);
+
+	gpio_set_value(GPIO_HUB_RESET, 1);
+	gpio_set_value(GPIO_SMSC3317_RESET, 1);
+	gpio_set_value(GPIO_BLUETOOTH, 1);
+	gpio_set_value(GPIO_WIFI_RESET, 1);
+
+	mxc_iomux_v3_setup_pad(MX51_PAD_USBH1_STP__GPIO1_27);
+	gpio_set_value(IMX_GPIO_NR(1, 27), 1);
+	mdelay(1);
+	mxc_iomux_v3_setup_pad(MX51_PAD_USBH1_STP__USBH1_STP);
+
+	if (machine_is_efikasb()) {
+		mxc_iomux_v3_setup_pad(MX51_PAD_EIM_A26__GPIO2_20);
+		gpio_set_value(IMX_GPIO_NR(2, 20), 1);
+		mdelay(1);
+		mxc_iomux_v3_setup_pad(MX51_PAD_EIM_A26__USBH2_STP);
+	}
+
+	imx51_add_usbh1(&efikamx_usbh1_pdata);
+
+	/*
+	 * At least for the EfikaSB these do not seem to be interesting.
+	 * The external ports are all connected to host1.
+	 *
+	 * imx51_add_usbotg(pdata);
+	 * imx51_add_usbh2(pdate);
+	 */
+
+	return 0;
+}
+
+static struct gpio_led leds[] = {
+	{
+		.gpio = IMX_GPIO_NR(1, 3),
+		.active_low = 1,
+		.led.name = "mail",
+	}, {
+		.gpio = IMX_GPIO_NR(2, 25),
+		.led.name = "white",
+	},
+};
+
+#define DCD_NAME static struct imx_dcd_entry dcd_entry
+
+#include "dcd-data.h"
+
+static int efikamx_devices_init(void)
+{
+	int i;
+
+	mxc_iomux_v3_setup_multiple_pads(efika_pads, ARRAY_SIZE(efika_pads));
+	if (machine_is_efikasb()) {
+		gpio_direction_output(GPIO_BACKLIGHT_POWER, 1);
+		mxc_iomux_v3_setup_multiple_pads(efikasb_pads,
+				ARRAY_SIZE(efikasb_pads));
+	} else {
+		mxc_iomux_v3_setup_multiple_pads(efikamx_pads,
+				ARRAY_SIZE(efikamx_pads));
+	}
+
+	spi_register_board_info(efikamx_spi_board_info,
+			ARRAY_SIZE(efikamx_spi_board_info));
+	imx51_add_spi0(&spi_0_data);
+
+	efikamx_power_init();
+
+	if (machine_is_efikasb())
+		imx51_add_mmc0(&efikasb_sd1_data);
+	else
+		imx51_add_mmc0(&efikamx_sd1_data);
+
+	imx51_add_mmc1(&efikasb_sd2_data);
+
+	for (i = 0; i < ARRAY_SIZE(leds); i++)
+                led_gpio_register(&leds[i]);
+
+	imx51_add_i2c1(NULL);
+
+	efikamx_usb_init();
+
+	imx51_add_pata();
+
+	writew(0x0, MX51_WDOG_BASE_ADDR + 0x8);
+
+	imx51_bbu_internal_mmc_register_handler("mmc", "/dev/mmc_left",
+			BBU_HANDLER_FLAG_DEFAULT, dcd_entry, sizeof(dcd_entry),
+			0);
+
+	armlinux_set_bootparams((void *)0x90000100);
+	armlinux_set_architecture(2370);
+	armlinux_set_revision(0x5100 | imx_silicon_revision());
+
+	return 0;
+}
+device_initcall(efikamx_devices_init);
+
+static int efikamx_part_init(void)
+{
+	if (imx_bootsource() == bootsource_mmc) {
+		devfs_add_partition("mmc_left", 0x00000, 0x80000,
+				DEVFS_PARTITION_FIXED, "self0");
+		devfs_add_partition("mmc_left", 0x80000, 0x80000,
+				DEVFS_PARTITION_FIXED, "env0");
+	}
+
+	return 0;
+}
+late_initcall(efikamx_part_init);
+
+static iomux_v3_cfg_t efika_uart_pads[] = {
+	/* UART */
+	MX51_PAD_UART1_RXD__UART1_RXD,
+	MX51_PAD_UART1_TXD__UART1_TXD,
+	MX51_PAD_UART1_RTS__UART1_RTS,
+	MX51_PAD_UART1_CTS__UART1_CTS,
+};
+
+static int efikamx_console_init(void)
+{
+	mxc_iomux_v3_setup_multiple_pads(efika_uart_pads,
+			ARRAY_SIZE(efika_uart_pads));
+
+	imx51_add_uart0();
+
+	return 0;
+}
+console_initcall(efikamx_console_init);
diff --git a/arch/arm/boards/efika-mx-smartbook/config.h b/arch/arm/boards/efika-mx-smartbook/config.h
new file mode 100644
index 0000000..b7effe5
--- /dev/null
+++ b/arch/arm/boards/efika-mx-smartbook/config.h
@@ -0,0 +1,24 @@
+/**
+ * @file
+ * @brief Global defintions for the ARM i.MX51 based babbage board
+ *
+ * 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
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+#endif	/* __CONFIG_H */
diff --git a/arch/arm/boards/efika-mx-smartbook/dcd-data.h b/arch/arm/boards/efika-mx-smartbook/dcd-data.h
new file mode 100644
index 0000000..6795e19
--- /dev/null
+++ b/arch/arm/boards/efika-mx-smartbook/dcd-data.h
@@ -0,0 +1,56 @@
+DCD_NAME[] = {
+	{ .ptr_type = 4, .addr = 0x73fa88a0, .val = 0x00000000, },
+	{ .ptr_type = 4, .addr = 0x73fa850c, .val = 0x000020c5, },
+	{ .ptr_type = 4, .addr = 0x73fa8510, .val = 0x000020c5, },
+	{ .ptr_type = 4, .addr = 0x73fa883c, .val = 0x00000005, },
+	{ .ptr_type = 4, .addr = 0x73fa8848, .val = 0x00000005, },
+	{ .ptr_type = 4, .addr = 0x73fa84b8, .val = 0x000000e7, },
+	{ .ptr_type = 4, .addr = 0x73fa84bc, .val = 0x00000045, },
+	{ .ptr_type = 4, .addr = 0x73fa84c0, .val = 0x00000045, },
+	{ .ptr_type = 4, .addr = 0x73fa84c4, .val = 0x00000045, },
+	{ .ptr_type = 4, .addr = 0x73fa84c8, .val = 0x00000045, },
+	{ .ptr_type = 4, .addr = 0x73fa8820, .val = 0x00000000, },
+	{ .ptr_type = 4, .addr = 0x73fa84a4, .val = 0x00000005, },
+	{ .ptr_type = 4, .addr = 0x73fa84a8, .val = 0x00000005, },
+	{ .ptr_type = 4, .addr = 0x73fa84ac, .val = 0x000000e5, },
+	{ .ptr_type = 4, .addr = 0x73fa84b0, .val = 0x000000e5, },
+	{ .ptr_type = 4, .addr = 0x73fa84b4, .val = 0x000000e5, },
+	{ .ptr_type = 4, .addr = 0x73fa84cc, .val = 0x000000e5, },
+	{ .ptr_type = 4, .addr = 0x73fa84d0, .val = 0x000000e4, },
+	{ .ptr_type = 4, .addr = 0x73fa882c, .val = 0x00000004, },
+	{ .ptr_type = 4, .addr = 0x73fa88a4, .val = 0x00000004, },
+	{ .ptr_type = 4, .addr = 0x73fa88ac, .val = 0x00000004, },
+	{ .ptr_type = 4, .addr = 0x73fa88b8, .val = 0x00000004, },
+	{ .ptr_type = 4, .addr = 0x83fd9000, .val = 0x82a20000, },
+	{ .ptr_type = 4, .addr = 0x83fd9008, .val = 0x82a20000, },
+	{ .ptr_type = 4, .addr = 0x83fd9010, .val = 0xcaaaf6d0, },
+	{ .ptr_type = 4, .addr = 0x83fd9004, .val = 0x333574aa, },
+	{ .ptr_type = 4, .addr = 0x83fd900c, .val = 0x333574aa, },
+	{ .ptr_type = 4, .addr = 0x83fd9014, .val = 0x04008008, },
+	{ .ptr_type = 4, .addr = 0x83fd9014, .val = 0x0000801a, },
+	{ .ptr_type = 4, .addr = 0x83fd9014, .val = 0x0000801b, },
+	{ .ptr_type = 4, .addr = 0x83fd9014, .val = 0x00448019, },
+	{ .ptr_type = 4, .addr = 0x83fd9014, .val = 0x07328018, },
+	{ .ptr_type = 4, .addr = 0x83fd9014, .val = 0x04008008, },
+	{ .ptr_type = 4, .addr = 0x83fd9014, .val = 0x00008010, },
+	{ .ptr_type = 4, .addr = 0x83fd9014, .val = 0x00008010, },
+	{ .ptr_type = 4, .addr = 0x83fd9014, .val = 0x06328018, },
+	{ .ptr_type = 4, .addr = 0x83fd9014, .val = 0x03808019, },
+	{ .ptr_type = 4, .addr = 0x83fd9014, .val = 0x00008000, },
+	{ .ptr_type = 4, .addr = 0x83fd9014, .val = 0x0400800c, },
+	{ .ptr_type = 4, .addr = 0x83fd9014, .val = 0x0000801e, },
+	{ .ptr_type = 4, .addr = 0x83fd9014, .val = 0x0000801f, },
+	{ .ptr_type = 4, .addr = 0x83fd9014, .val = 0x0000801d, },
+	{ .ptr_type = 4, .addr = 0x83fd9014, .val = 0x0732801c, },
+	{ .ptr_type = 4, .addr = 0x83fd9014, .val = 0x0400800c, },
+	{ .ptr_type = 4, .addr = 0x83fd9014, .val = 0x00008014, },
+	{ .ptr_type = 4, .addr = 0x83fd9014, .val = 0x00008014, },
+	{ .ptr_type = 4, .addr = 0x83fd9014, .val = 0x0632801c, },
+	{ .ptr_type = 4, .addr = 0x83fd9014, .val = 0x0380801d, },
+	{ .ptr_type = 4, .addr = 0x83fd9014, .val = 0x00008004, },
+	{ .ptr_type = 4, .addr = 0x83fd9000, .val = 0xb2a20000, },
+	{ .ptr_type = 4, .addr = 0x83fd9008, .val = 0xb2a20000, },
+	{ .ptr_type = 4, .addr = 0x83fd9010, .val = 0x000ad6d0, },
+	{ .ptr_type = 4, .addr = 0x83fd9034, .val = 0x90000000, },
+	{ .ptr_type = 4, .addr = 0x83fd9014, .val = 0x00000000, },
+};
diff --git a/arch/arm/boards/efika-mx-smartbook/env/bin/lvds_init b/arch/arm/boards/efika-mx-smartbook/env/bin/lvds_init
new file mode 100644
index 0000000..692392c
--- /dev/null
+++ b/arch/arm/boards/efika-mx-smartbook/env/bin/lvds_init
@@ -0,0 +1,22 @@
+#!/bin/sh
+
+# Initialize lvds and backlight in case your Kernel does not handle this...
+
+GPIO_BACKLIGHT_POWER=108
+GPIO_BACKLIGHT_PWM=2
+GPIO_LVDS_POWER=71
+GPIO_LVDS_RESET=69
+GPIO_LVDS_ENABLE=76
+GPIO_LCD_ENABLE=77
+
+gpio_direction_output $GPIO_BACKLIGHT_PWM 0
+gpio_direction_output $GPIO_LVDS_RESET 1
+gpio_direction_output $GPIO_LVDS_POWER 1
+msleep 5
+gpio_direction_output $GPIO_LVDS_RESET 0
+msleep 5
+gpio_direction_output $GPIO_LVDS_ENABLE 1
+gpio_direction_output $GPIO_BACKLIGHT_POWER 0
+gpio_direction_output $GPIO_LCD_ENABLE 1
+msleep 300
+gpio_direction_output $GPIO_BACKLIGHT_PWM 1
diff --git a/arch/arm/boards/efika-mx-smartbook/env/boot/hd-internal b/arch/arm/boards/efika-mx-smartbook/env/boot/hd-internal
new file mode 100644
index 0000000..ccd0f69
--- /dev/null
+++ b/arch/arm/boards/efika-mx-smartbook/env/boot/hd-internal
@@ -0,0 +1,17 @@
+#!/bin/sh
+
+if [ "$1" = menu ]; then
+	boot-menu-add-entry "$0" "internal harddisk"
+	exit
+fi
+
+path="/mnt/internal-hd0.0"
+
+global.bootm.image="${path}/linuximage"
+
+oftree=${path}/oftree
+if [ -f $oftree ]; then
+	global.bootm.oftree="$oftree"
+fi
+
+global.linux.bootargs.dyn.root="root=/dev/sda2"
diff --git a/arch/arm/boards/efika-mx-smartbook/env/boot/mmc-left b/arch/arm/boards/efika-mx-smartbook/env/boot/mmc-left
new file mode 100644
index 0000000..21935c6
--- /dev/null
+++ b/arch/arm/boards/efika-mx-smartbook/env/boot/mmc-left
@@ -0,0 +1,19 @@
+#!/bin/sh
+
+if [ "$1" = menu ]; then
+	boot-menu-add-entry "$0" "left MMC slot"
+	exit
+fi
+
+path="/mnt/mmc-left.0"
+
+global.bootm.image="${path}/linuximage"
+
+oftree=${path}/oftree
+if [ -f $oftree ]; then
+	global.bootm.oftree="$oftree"
+fi
+
+# The rootdevice may actually be mmcblk1p2 if a card
+# is inserted to the back MMC slot
+global.linux.bootargs.dyn.root="root=/dev/mmcblk0p2"
diff --git a/arch/arm/boards/efika-mx-smartbook/env/config b/arch/arm/boards/efika-mx-smartbook/env/config
new file mode 100644
index 0000000..46aff49
--- /dev/null
+++ b/arch/arm/boards/efika-mx-smartbook/env/config
@@ -0,0 +1,29 @@
+#!/bin/sh
+
+# change network settings in /env/network/eth0
+# change mtd partition settings and automountpoints in /env/init/*
+
+#global.hostname=
+
+# set to false if you do not want to have colors
+global.allow_color=true
+
+# user (used for network filenames)
+global.user=none
+
+# timeout in seconds before the default boot entry is started
+global.autoboot_timeout=1
+
+# default boot entry (one of /env/boot/*)
+# (if not overwritten here, the bootdevice barebox comes from
+# is used)
+#global.boot.default=net
+
+# base bootargs
+global.linux.bootargs.base="console=ttymxc0,115200 console=tty1"
+
+# suitable for 800MHz
+global linux.bootargs.lpj="lpj=3997696"
+
+# speed up booting by being more quiet
+global linux.bootargs.quiet="quiet"
diff --git a/arch/arm/boards/efika-mx-smartbook/env/init/automount b/arch/arm/boards/efika-mx-smartbook/env/init/automount
new file mode 100644
index 0000000..8cb5eaf
--- /dev/null
+++ b/arch/arm/boards/efika-mx-smartbook/env/init/automount
@@ -0,0 +1,29 @@
+#!/bin/sh
+
+if [ "$1" = menu ]; then
+	init-menu-add-entry "$0" "Automountpoints"
+	exit
+fi
+
+# automount tftp server based on $eth0.serverip
+
+mkdir -p /mnt/tftp
+automount /mnt/tftp 'ifup eth0 && mount -t tftp $eth0.serverip /mnt/tftp'
+
+# automount nfs server example
+
+# internal harddisk /boot partition
+mkdir -p /mnt/internal-hd0.0
+automount -d /mnt/internal-hd0.0 'mount /dev/ata0.0 /mnt/internal-hd0.0'
+
+# internal harddisk rootfs
+mkdir -p /mnt/internal-hd0.1
+automount -d /mnt/internal-hd0.1 'mount /dev/ata0.1 /mnt/internal-hd0.1'
+
+# left SD card slot, first partition
+mkdir -p /mnt/mmc-left.0
+automount -d /mnt/mmc-left.0 'mount /dev/mmc_left.0 /mnt/mmc-left.0'
+
+# back SD card slot, first partition
+mkdir -p /mnt/mmc-back.0
+automount -d /mnt/mmc-back.0 'mount /dev/mmc_back.0 /mnt/mmc-back.0'
diff --git a/arch/arm/boards/efika-mx-smartbook/env/init/bootsource b/arch/arm/boards/efika-mx-smartbook/env/init/bootsource
new file mode 100644
index 0000000..fb08469
--- /dev/null
+++ b/arch/arm/boards/efika-mx-smartbook/env/init/bootsource
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+# by default pick kernel from MMC card if booting from
+# it, otherwise default to boot from internal harddisk
+
+if [ $barebox_loc = mmc ]; then
+	global.boot.default=mmc-left
+else
+	global.boot.default=hd-internal
+fi
diff --git a/arch/arm/boards/efika-mx-smartbook/env/init/config-board b/arch/arm/boards/efika-mx-smartbook/env/init/config-board
new file mode 100644
index 0000000..22993f9
--- /dev/null
+++ b/arch/arm/boards/efika-mx-smartbook/env/init/config-board
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+# board defaults, do not change in running system. Change /env/config
+# instead
+
+global.hostname=efikasb
+global.linux.bootargs.base="console=ttymxc0,115200"
+
+[ -f /env/config ] && /env/config
diff --git a/arch/arm/boards/efika-mx-smartbook/env/network/eth0-discover b/arch/arm/boards/efika-mx-smartbook/env/network/eth0-discover
new file mode 100644
index 0000000..f8368a5
--- /dev/null
+++ b/arch/arm/boards/efika-mx-smartbook/env/network/eth0-discover
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+usb
+sleep 3
diff --git a/arch/arm/boards/efika-mx-smartbook/flash_header.c b/arch/arm/boards/efika-mx-smartbook/flash_header.c
new file mode 100644
index 0000000..f3f1e4b
--- /dev/null
+++ b/arch/arm/boards/efika-mx-smartbook/flash_header.c
@@ -0,0 +1,29 @@
+#include <common.h>
+#include <mach/imx-flash-header.h>
+#include <asm/barebox-arm-head.h>
+
+void __naked __flash_header_start go(void)
+{
+	barebox_arm_head();
+}
+
+#define DCD_NAME struct imx_dcd_entry __dcd_entry_section dcd_entry
+
+#include "dcd-data.h"
+
+#define APP_DEST	0x90000000
+
+struct imx_flash_header __flash_header_section flash_header = {
+	.app_code_jump_vector	= APP_DEST + 0x1000,
+	.app_code_barker	= APP_CODE_BARKER,
+	.app_code_csf		= 0,
+	.dcd_ptr_ptr		= APP_DEST + 0x400 + offsetof(struct imx_flash_header, dcd),
+	.super_root_key		= 0,
+	.dcd			= APP_DEST + 0x400 + offsetof(struct imx_flash_header, dcd_barker),
+	.app_dest		= APP_DEST,
+	.dcd_barker		= DCD_BARKER,
+	.dcd_block_len		= sizeof (dcd_entry),
+};
+
+unsigned long __image_len_section barebox_len = DCD_BAREBOX_SIZE;
+
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index ec4f864..ea67731 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -29,6 +29,7 @@ config ARCH_TEXT_BASE
 	default 0x4fc00000 if MACH_SABRELITE
 	default 0x8fe00000 if MACH_TX53
 	default 0x7fc00000 if MACH_GUF_VINCELL
+	default 0x97f00000 if MACH_EFIKA_MX_SMARTBOOK
 
 config BOARDINFO
 	default "Eukrea CPUIMX25" if MACH_EUKREA_CPUIMX25
@@ -48,6 +49,7 @@ config BOARDINFO
 	default "Freescale i.MX51 PDK" if MACH_FREESCALE_MX51_PDK
 	default "Freescale i.MX53 LOCO" if MACH_FREESCALE_MX53_LOCO
 	default "Freescale i.MX53 SMD" if MACH_FREESCALE_MX53_SMD
+	default "Efika MX smartbook" if MACH_EFIKA_MX_SMARTBOOK
 	default "Garz+Fricke Cupid" if MACH_GUF_CUPID
 	default "Ka-Ro tx25" if MACH_TX25
 	default "TQ tqma53" if MACH_TQMA53
@@ -428,6 +430,12 @@ config MACH_CCMX51_BASEBOARD
 	  This adds board specific devices that can be found on Digi
 	  evaluation board for CCMX51 module.
 
+config MACH_EFIKA_MX_SMARTBOOK
+	bool "Efika MX smartbook"
+	select HAVE_DEFAULT_ENVIRONMENT_NEW
+	help
+	  Choose this to compile barebox for the Efika MX Smartbook
+
 endchoice
 
 endif
diff --git a/defaultenv-2/base/boot/net b/defaultenv-2/base/boot/net
index 90c25aa..0eac84b 100644
--- a/defaultenv-2/base/boot/net
+++ b/defaultenv-2/base/boot/net
@@ -8,7 +8,7 @@ fi
 path="/mnt/tftp"
 
 global.bootm.image="${path}/${global.user}-linux-${global.hostname}"
-#global.bootm.oftree="${path}/${global.user}-oftree-${global.hostname}"
+global.bootm.oftree="${path}/${global.user}-oftree-${global.hostname}"
 nfsroot="/home/${global.user}/nfsroot/${global.hostname}"
 bootargs-ip
-global.linux.bootargs.dyn.root="root=/dev/nfs nfsroot=$nfsroot,v3,tcp"
+global.linux.bootargs.dyn.root="root=/dev/nfs nfsroot=$nfsroot,v3,tcp rootwait"
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index 9dc931b..3b147fb 100644
--- a/drivers/usb/core/usb.c
+++ b/drivers/usb/core/usb.c
@@ -454,14 +454,14 @@ static struct usb_device *usb_alloc_new_device(void)
 	if (!usbdev)
 		return NULL;
 
-	usbdev->devnum = dev_index + 1;
+	dev_index++;
+
+	usbdev->devnum = dev_index;
 	usbdev->maxchild = 0;
 	usbdev->dev.bus = &usb_bus_type;
 	usbdev->setup_packet = dma_alloc(sizeof(*usbdev->setup_packet));
 	usbdev->descriptor = dma_alloc(sizeof(*usbdev->descriptor));
 
-	dev_index++;
-
 	return usbdev;
 }
 
@@ -494,7 +494,7 @@ void usb_rescan(void)
 		usb_new_device(dev);
 	}
 
-	printf("%d USB Device(s) found\n", dev_index);
+	printf("%d USB Device(s) found\n", dev_index - 1);
 }
 
 /*
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index d6083e0..02ec714 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -33,6 +33,7 @@
 #include "ehci.h"
 
 struct ehci_priv {
+	struct device_d *dev;
 	int rootdev;
 	struct ehci_hccr *hccr;
 	struct ehci_hcor *hcor;
@@ -610,7 +611,10 @@ ehci_submit_root(struct usb_device *dev, unsigned long pipe, void *buffer,
 				 * usb 2.0 specification say 50 ms resets on
 				 * root
 				 */
+				ehci_powerup_fixup(ehci->dev, &reg);
+
 				wait_ms(50);
+
 				ehci->portreset |= 1 << le16_to_cpu(req->index);
 				/* terminate the reset */
 				ehci_writel(status_reg, reg & ~EHCI_PS_PR);
@@ -816,6 +820,8 @@ int ehci_register(struct device_d *dev, struct ehci_data *data)
 	ehci = xzalloc(sizeof(struct ehci_priv));
 	host = &ehci->host;
 	dev->priv = ehci;
+	ehci->dev = dev;
+
 	ehci->flags = data->flags;
 	ehci->hccr = data->hccr;
 	ehci->hcor = data->hcor;
diff --git a/drivers/usb/otg/ulpi.c b/drivers/usb/otg/ulpi.c
index 61cbada..19f64e0 100644
--- a/drivers/usb/otg/ulpi.c
+++ b/drivers/usb/otg/ulpi.c
@@ -111,6 +111,23 @@ int ulpi_clear(u8 bits, int reg, void __iomem *view)
 }
 EXPORT_SYMBOL(ulpi_clear);
 
+int ulpi_write(u8 bits, int reg, void __iomem *view)
+{
+	int ret;
+
+	writel((ULPIVW_RUN | ULPIVW_WRITE |
+		      (reg << ULPIVW_ADDR_SHIFT) |
+		      ((bits & ULPIVW_WDATA_MASK) << ULPIVW_WDATA_SHIFT)),
+		     view);
+
+	/* wait for completion */
+	ret = ulpi_poll(view, ULPIVW_RUN);
+	if (ret < 0)
+		return ret;
+	return 0;
+}
+EXPORT_SYMBOL(ulpi_write);
+
 struct ulpi_info {
 	uint32_t	id;
 	char		*name;
@@ -161,18 +178,18 @@ int ulpi_set_vbus(void __iomem *view, int on)
 	int ret;
 
 	if (on) {
-		ret = ulpi_set(DRV_VBUS_EXT |		/* enable external Vbus */
-				DRV_VBUS |		/* enable internal Vbus */
-				USE_EXT_VBUS_IND |	/* use external indicator */
-				CHRG_VBUS,		/* charge Vbus */
+		ret = ulpi_set(ULPI_OTG_DRV_VBUS_EXT |		/* enable external Vbus */
+				ULPI_OTG_DRV_VBUS |		/* enable internal Vbus */
+				ULPI_OTG_USE_EXT_VBUS_IND |	/* use external indicator */
+				ULPI_OTG_CHRG_VBUS,		/* charge Vbus */
 				ULPI_OTGCTL, view);
 	} else {
-		ret = ulpi_clear(DRV_VBUS_EXT |		/* disable external Vbus */
-				DRV_VBUS,		/* disable internal Vbus */
+		ret = ulpi_clear(ULPI_OTG_DRV_VBUS_EXT |		/* disable external Vbus */
+				ULPI_OTG_DRV_VBUS,		/* disable internal Vbus */
 				ULPI_OTGCTL, view);
 
-		ret |= ulpi_set(USE_EXT_VBUS_IND |	/* use external indicator */
-				DISCHRG_VBUS,		/* discharge Vbus */
+		ret |= ulpi_set(ULPI_OTG_USE_EXT_VBUS_IND |	/* use external indicator */
+				ULPI_OTG_DISCHRG_VBUS,		/* discharge Vbus */
 				ULPI_OTGCTL, view);
 	}
 
diff --git a/include/usb/ulpi.h b/include/usb/ulpi.h
index 542993c..e45ea6e 100644
--- a/include/usb/ulpi.h
+++ b/include/usb/ulpi.h
@@ -1,6 +1,7 @@
 #ifndef __MACH_ULPI_H
 #define __MACH_ULPI_H
 
+int ulpi_write(u8 bits, int reg, void __iomem *view);
 int ulpi_set(u8 bits, int reg, void __iomem *view);
 int ulpi_clear(u8 bits, int reg, void __iomem *view);
 int ulpi_read(int reg, void __iomem *view);
@@ -11,6 +12,7 @@ int ulpi_setup(void __iomem *view, int on);
 #define ULPI_VID_HIGH		0x01	/* Vendor ID high */
 #define ULPI_PID_LOW		0x02	/* Product ID low */
 #define ULPI_PID_HIGH		0x03	/* Product ID high */
+#define ULPI_FUNCTION_CTRL	0x04
 #define ULPI_ITFCTL		0x07	/* Interface Control */
 #define ULPI_OTGCTL		0x0A	/* OTG Control */
 
@@ -18,15 +20,40 @@ int ulpi_setup(void __iomem *view, int on);
 #define ULPI_REG_SET		0x01
 #define ULPI_REG_CLEAR		0x02
 
+/* Function Control */
+#define ULPI_FC_XCVRSEL_MASK		(3 << 0)
+#define ULPI_FC_HIGH_SPEED		(0 << 0)
+#define ULPI_FC_FULL_SPEED		(1 << 0)
+#define ULPI_FC_LOW_SPEED		(2 << 0)
+#define ULPI_FC_FS4LS			(3 << 0)
+#define ULPI_FC_TERMSELECT		(1 << 2)
+#define ULPI_FC_OPMODE_MASK		(3 << 3)
+#define ULPI_FC_OPMODE_NORMAL		(0 << 3)
+#define ULPI_FC_OPMODE_NONDRIVING	(1 << 3)
+#define ULPI_FC_OPMODE_DISABLE_NRZI	(2 << 3)
+#define ULPI_FC_OPMODE_NOSYNC_NOEOP	(3 << 3)
+#define ULPI_FC_RESET			(1 << 5)
+#define ULPI_FC_SUSPENDM		(1 << 6)
+
+/* Interface Control */
+#define ULPI_IFACE_6_PIN_SERIAL_MODE	(1 << 0)
+#define ULPI_IFACE_3_PIN_SERIAL_MODE	(1 << 1)
+#define ULPI_IFACE_CARKITMODE		(1 << 2)
+#define ULPI_IFACE_CLOCKSUSPENDM	(1 << 3)
+#define ULPI_IFACE_AUTORESUME		(1 << 4)
+#define ULPI_IFACE_EXTVBUS_COMPLEMENT	(1 << 5)
+#define ULPI_IFACE_PASSTHRU		(1 << 6)
+#define ULPI_IFACE_PROTECT_IFC_DISABLE	(1 << 7)
+
 /* ULPI OTG Control Register bits */
-#define USE_EXT_VBUS_IND	(1 << 7)	/* Use ext. Vbus indicator */
-#define DRV_VBUS_EXT		(1 << 6)	/* Drive Vbus external */
-#define DRV_VBUS		(1 << 5)	/* Drive Vbus */
-#define CHRG_VBUS		(1 << 4)	/* Charge Vbus */
-#define DISCHRG_VBUS		(1 << 3)	/* Discharge Vbus */
-#define DM_PULL_DOWN		(1 << 2)	/* enable DM Pull Down */
-#define DP_PULL_DOWN		(1 << 1)	/* enable DP Pull Down */
-#define ID_PULL_UP		(1 << 0)	/* enable ID Pull Up */
+#define ULPI_OTG_USE_EXT_VBUS_IND	(1 << 7)	/* Use ext. Vbus indicator */
+#define ULPI_OTG_DRV_VBUS_EXT		(1 << 6)	/* Drive Vbus external */
+#define ULPI_OTG_DRV_VBUS		(1 << 5)	/* Drive Vbus */
+#define ULPI_OTG_CHRG_VBUS		(1 << 4)	/* Charge Vbus */
+#define ULPI_OTG_DISCHRG_VBUS		(1 << 3)	/* Discharge Vbus */
+#define ULPI_OTG_DM_PULL_DOWN		(1 << 2)	/* enable DM Pull Down */
+#define ULPI_OTG_DP_PULL_DOWN		(1 << 1)	/* enable DP Pull Down */
+#define ULPI_OTG_ID_PULL_UP		(1 << 0)	/* enable ID Pull Up */
 
 #endif /* __MACH_ULPI_H */
 
-- 
1.7.10.4




More information about the barebox mailing list