diff mbox

[4/4] omap3: Add minimal OMAP3 IGEP module support.

Message ID 1280836574-32467-5-git-send-email-eballetbo@gmail.com (mailing list archive)
State New, archived
Headers show

Commit Message

Enric Balletbo Serra Aug. 3, 2010, 11:56 a.m. UTC
None
diff mbox

Patch

diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig
index b31b6f1..db8bd18 100644
--- a/arch/arm/mach-omap2/Kconfig
+++ b/arch/arm/mach-omap2/Kconfig
@@ -142,6 +142,11 @@  config MACH_IGEP0020
 	depends on ARCH_OMAP3
 	select OMAP_PACKAGE_CBB
 
+config MACH_IGEP0030
+	bool "IGEP OMAP3 module"
+	depends on ARCH_OMAP3
+	select OMAP_PACKAGE_CBB
+
 config MACH_SBC3530
 	bool "OMAP3 SBC STALKER board"
 	depends on ARCH_OMAP3
diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
index ea52b03..fab0222 100644
--- a/arch/arm/mach-omap2/Makefile
+++ b/arch/arm/mach-omap2/Makefile
@@ -136,6 +136,8 @@  obj-$(CONFIG_MACH_CM_T35)		+= board-cm-t35.o \
 					   hsmmc.o
 obj-$(CONFIG_MACH_IGEP0020)		+= board-igep0020.o \
 					   hsmmc.o
+obj-$(CONFIG_MACH_IGEP0030)		+= board-igep0030.o \
+					   hsmmc.o
 obj-$(CONFIG_MACH_OMAP3_TOUCHBOOK)	+= board-omap3touchbook.o \
 					   hsmmc.o
 obj-$(CONFIG_MACH_OMAP_4430SDP)		+= board-4430sdp.o \
diff --git a/arch/arm/mach-omap2/board-igep0030.c b/arch/arm/mach-omap2/board-igep0030.c
new file mode 100644
index 0000000..936bf98
--- /dev/null
+++ b/arch/arm/mach-omap2/board-igep0030.c
@@ -0,0 +1,436 @@ 
+/*
+ * Copyright (C) 2010 Integration Software and Electronic Engineering.
+ *
+ * Modified from mach-omap2/board-generic.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+#include <linux/interrupt.h>
+
+#include <linux/regulator/machine.h>
+#include <linux/i2c/twl.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+
+#include <plat/board.h>
+#include <plat/common.h>
+#include <plat/gpmc.h>
+#include <plat/usb.h>
+#include <plat/onenand.h>
+
+#include "mux.h"
+#include "hsmmc.h"
+#include "sdram-numonyx-m65kxxxxam.h"
+
+#define IGEP3_GPIO_LED0_GREEN	54
+#define IGEP3_GPIO_LED0_RED	53
+#define IGEP3_GPIO_LED1_RED	16
+
+#define IGEP3_GPIO_WIFI_NPD	138
+#define IGEP3_GPIO_WIFI_NRESET	139
+#define IGEP3_GPIO_BT_NRESET	137
+
+#define IGEP3_GPIO_USBH_NRESET  115
+
+
+#if defined(CONFIG_MTD_ONENAND_OMAP2) || \
+	defined(CONFIG_MTD_ONENAND_OMAP2_MODULE)
+
+#define ONENAND_MAP             0x20000000
+
+/* x2 Flash built-in COMBO POP MEMORY
+ * Since the device is equipped with two DataRAMs, and two-plane NAND
+ * Flash memory array, these two component enables simultaneous program
+ * of 4KiB. Plane1 has only even blocks such as block0, block2, block4
+ * while Plane2 has only odd blocks such as block1, block3, block5.
+ * So MTD regards it as 4KiB page size and 256KiB block size 64*(2*2048)
+ */
+
+static struct mtd_partition igep3_onenand_partitions[] = {
+	{
+		.name           = "X-Loader",
+		.offset         = 0,
+		.size           = 2 * (64*(2*2048))
+	},
+	{
+		.name           = "U-Boot",
+		.offset         = MTDPART_OFS_APPEND,
+		.size           = 6 * (64*(2*2048)),
+	},
+	{
+		.name           = "Environment",
+		.offset         = MTDPART_OFS_APPEND,
+		.size           = 2 * (64*(2*2048)),
+	},
+	{
+		.name           = "Kernel",
+		.offset         = MTDPART_OFS_APPEND,
+		.size           = 12 * (64*(2*2048)),
+	},
+	{
+		.name           = "File System",
+		.offset         = MTDPART_OFS_APPEND,
+		.size           = MTDPART_SIZ_FULL,
+	},
+};
+
+static int igep3_onenand_setup(void __iomem *onenand_base, int freq)
+{
+       /* nothing is required to be setup for onenand as of now */
+       return 0;
+}
+
+static struct omap_onenand_platform_data igep3_onenand_data = {
+	.parts = igep3_onenand_partitions,
+	.nr_parts = ARRAY_SIZE(igep3_onenand_partitions),
+	.onenand_setup = igep3_onenand_setup,
+	.dma_channel	= -1,	/* disable DMA in OMAP OneNAND driver */
+};
+
+static struct platform_device igep3_onenand_device = {
+	.name		= "omap2-onenand",
+	.id		= -1,
+	.dev = {
+		.platform_data = &igep3_onenand_data,
+	},
+};
+
+void __init igep3_flash_init(void)
+{
+	u8		cs = 0;
+	u8		onenandcs = GPMC_CS_NUM + 1;
+
+	while (cs < GPMC_CS_NUM) {
+		u32 ret = 0;
+		ret = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
+
+		/* Check if NAND/oneNAND is configured */
+		if ((ret & 0xC00) == 0x800)
+			/* NAND found */
+			pr_err("IGEP: Unsupported NAND found\n");
+		else {
+			ret = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG7);
+			if ((ret & 0x3F) == (ONENAND_MAP >> 24))
+				/* ONENAND found */
+				onenandcs = cs;
+		}
+		cs++;
+	}
+	if (onenandcs > GPMC_CS_NUM) {
+		pr_err("IGEP: Unable to find configuration in GPMC\n");
+		return;
+	}
+
+	if (onenandcs < GPMC_CS_NUM) {
+		igep3_onenand_data.cs = onenandcs;
+		if (platform_device_register(&igep3_onenand_device) < 0)
+			pr_err("IGEP: Unable to register OneNAND device\n");
+	}
+}
+
+#else
+void __init igep3_flash_init(void) {}
+#endif
+
+static struct omap_board_config_kernel igep3_config[] __initdata = {
+};
+
+static struct regulator_consumer_supply igep3_vmmc1_supply = {
+	.supply		= "vmmc",
+};
+
+static struct regulator_consumer_supply igep3_vmmc2_supply = {
+	.supply		= "vmmc",
+};
+
+/* VMMC1 for OMAP VDD_MMC1 (i/o) and MMC1 card */
+static struct regulator_init_data igep3_vmmc1 = {
+	.constraints = {
+		.min_uV			= 1850000,
+		.max_uV			= 3150000,
+		.valid_modes_mask	= REGULATOR_MODE_NORMAL
+					| REGULATOR_MODE_STANDBY,
+		.valid_ops_mask		= REGULATOR_CHANGE_VOLTAGE
+					| REGULATOR_CHANGE_MODE
+					| REGULATOR_CHANGE_STATUS,
+	},
+	.num_consumer_supplies  = 1,
+	.consumer_supplies      = &igep3_vmmc1_supply,
+};
+
+/* VMMC2 for OMAP VDD_MMC2 (i/o) and MMC2 WIFI */
+static struct regulator_init_data igep3_vmmc2 = {
+	.constraints = {
+		.min_uV			= 1850000,
+		.max_uV			= 3150000,
+		.valid_modes_mask	= REGULATOR_MODE_NORMAL
+					| REGULATOR_MODE_STANDBY,
+		.valid_ops_mask		= REGULATOR_CHANGE_VOLTAGE
+					| REGULATOR_CHANGE_MODE
+					| REGULATOR_CHANGE_STATUS,
+	},
+	.num_consumer_supplies  = 1,
+	.consumer_supplies      = &igep3_vmmc2_supply,
+};
+
+static struct omap2_hsmmc_info mmc[] = {
+	[0] = {
+		.mmc		= 1,
+		.wires		= 4,
+		.gpio_cd	= -EINVAL,
+		.gpio_wp	= -EINVAL,
+	},
+	[1] = {
+		.mmc		= 2,
+		.wires		= 4,
+		.gpio_cd	= -EINVAL,
+		.gpio_wp	= -EINVAL,
+	},
+	{}      /* Terminator */
+};
+
+#if defined(CONFIG_LEDS_GPIO) || defined(CONFIG_LEDS_GPIO_MODULE)
+#include <linux/leds.h>
+
+static struct gpio_led igep3_gpio_leds[] = {
+	[0] = {
+		.name = "led0:red",
+		.gpio = IGEP3_GPIO_LED0_RED,
+		.default_trigger = "default-off",
+		.active_low = true,
+	},
+	[1] = {
+		.name = "led0:green",
+		.gpio = IGEP3_GPIO_LED0_GREEN,
+		.default_trigger = "default-off",
+		.active_low = true,
+	},
+	[2] = {
+		.name = "led1:red",
+		.gpio = IGEP3_GPIO_LED1_RED,
+		.default_trigger = "default-off",
+		.active_low = true,
+	},
+	[3] = {
+		.name = "led1:green",
+		.default_trigger = "heartbeat",
+		.gpio = -EINVAL, /* gets replaced */
+		.active_low = true,
+	},
+};
+
+static struct gpio_led_platform_data igep3_led_pdata = {
+	.leds           = igep3_gpio_leds,
+	.num_leds       = ARRAY_SIZE(igep3_gpio_leds),
+};
+
+static struct platform_device igep3_led_device = {
+	 .name   = "leds-gpio",
+	 .id     = -1,
+	 .dev    = {
+		 .platform_data = &igep3_led_pdata,
+	},
+};
+
+static void __init igep3_init_led(void)
+{
+	platform_device_register(&igep3_led_device);
+}
+
+#else
+static inline void igep3_init_led(void)
+{
+	if ((gpio_request(IGEP3_GPIO_LED0_RED, "led0:red") == 0) &&
+		(gpio_direction_output(IGEP3_GPIO_LED0_RED, 1) == 0)) {
+		gpio_export(IGEP3_GPIO_LED0_RED, 0);
+		gpio_set_value(IGEP3_GPIO_LED0_RED, 1);
+	} else
+		pr_warning("IGEP: Could not obtain gpio GPIO_LED0_RED\n");
+
+	if ((gpio_request(IGEP3_GPIO_LED0_GREEN, "led0:green") == 0) &&
+		(gpio_direction_output(IGEP3_GPIO_LED0_GREEN, 1) == 0)) {
+		gpio_export(IGEP3_GPIO_LED0_GREEN, 0);
+		gpio_set_value(IGEP3_GPIO_LED0_GREEN, 1);
+	} else
+		pr_warning("IGEP: Could not obtain gpio GPIO_LED0_GREEN\n");
+
+	if ((gpio_request(IGEP3_GPIO_LED1_RED, "led1:red") == 0) &&
+		(gpio_direction_output(IGEP3_GPIO_LED1_RED, 1) == 0)) {
+		gpio_export(IGEP3_GPIO_LED1_RED, 0);
+		gpio_set_value(IGEP3_GPIO_LED1_RED, 1);
+	} else
+		pr_warning("IGEP: Could not obtain gpio GPIO_LED1_RED\n");
+}
+#endif
+
+static int igep3_twl_gpio_setup(struct device *dev,
+		unsigned gpio, unsigned ngpio)
+{
+	/* gpio + 0 is "mmc0_cd" (input/IRQ) */
+	mmc[0].gpio_cd = gpio + 0;
+	omap2_hsmmc_init(mmc);
+
+	/* link regulators to MMC adapters ... we "know" the
+	 * regulators will be set up only *after* we return.
+	*/
+	igep3_vmmc1_supply.dev = mmc[0].dev;
+	igep3_vmmc2_supply.dev = mmc[1].dev;
+
+	/* REVISIT: need ehci-omap hooks for external VBUS
+	 * power switch and overcurrent detect
+	 */
+	gpio_request(gpio + 1, "GPIO_EHCI_NOC");
+	gpio_direction_input(gpio + 1);
+
+	/* TWL4030_GPIO_MAX + 0 == ledA, GPIO_USBH_CPEN (out, active low) */
+	gpio_request(gpio + TWL4030_GPIO_MAX, "GPIO_USB_CPEN");
+	gpio_direction_output(gpio + TWL4030_GPIO_MAX, 0);
+
+	/* TWL4030_GPIO_MAX + 1 == ledB (out, active low LED) */
+#if !defined(CONFIG_LEDS_GPIO) && !defined(CONFIG_LEDS_GPIO_MODULE)
+	if ((gpio_request(gpio + TWL4030_GPIO_MAX + 1, "led1:green") == 0) &&
+	    (gpio_direction_output(gpio + TWL4030_GPIO_MAX + 1, 1) == 0)) {
+		gpio_export(gpio + TWL4030_GPIO_MAX + 1, 0);
+		gpio_set_value(gpio + TWL4030_GPIO_MAX + 1, 0);
+	} else
+		pr_warning("IGEP: Could not obtain gpio GPIO_LED1_GREEN\n");
+#else
+	igep3_gpio_leds[3].gpio = gpio + TWL4030_GPIO_MAX + 1;
+#endif
+
+	return 0;
+};
+
+static struct twl4030_gpio_platform_data igep3_gpio_data = {
+	.gpio_base	= OMAP_MAX_GPIO_LINES,
+	.irq_base	= TWL4030_GPIO_IRQ_BASE,
+	.irq_end	= TWL4030_GPIO_IRQ_END,
+	.use_leds	= true,
+	.setup		= igep3_twl_gpio_setup,
+};
+
+static struct twl4030_usb_data igep3_usb_data = {
+	.usb_mode	= T2_USB_MODE_ULPI,
+};
+
+static void __init igep3_init_irq(void)
+{
+	omap_board_config = igep3_config;
+	omap_board_config_size = ARRAY_SIZE(igep3_config);
+	omap2_init_common_hw(m65kxxxxam_sdrc_params, m65kxxxxam_sdrc_params);
+	omap_init_irq();
+	omap_gpio_init();
+}
+
+static struct twl4030_platform_data igep3_twldata = {
+	.irq_base	= TWL4030_IRQ_BASE,
+	.irq_end	= TWL4030_IRQ_END,
+
+	/* platform_data for children goes here */
+	.usb		= &igep3_usb_data,
+	.gpio		= &igep3_gpio_data,
+	.vmmc1		= &igep3_vmmc1,
+	.vmmc2		= &igep3_vmmc2,
+};
+
+static struct i2c_board_info __initdata igep3_i2c_boardinfo[] = {
+	{
+		I2C_BOARD_INFO("twl4030", 0x48),
+		.flags		= I2C_CLIENT_WAKE,
+		.irq		= INT_34XX_SYS_NIRQ,
+		.platform_data	= &igep3_twldata,
+	},
+};
+
+static int __init igep3_i2c_init(void)
+{
+	omap_register_i2c_bus(1, 2600, igep3_i2c_boardinfo,
+			ARRAY_SIZE(igep3_i2c_boardinfo));
+
+	return 0;
+}
+
+static struct omap_musb_board_data musb_board_data = {
+	.interface_type	= MUSB_INTERFACE_ULPI,
+	.mode		= MUSB_OTG,
+	.power		= 100,
+};
+
+static void __init igep3_init_wifi_bt(void)
+{
+	/* Configure MUX values for W-LAN + Bluetooth GPIO's */
+	omap_mux_init_gpio(IGEP3_GPIO_WIFI_NPD, OMAP_PIN_OUTPUT);
+	omap_mux_init_gpio(IGEP3_GPIO_WIFI_NRESET, OMAP_PIN_OUTPUT);
+	omap_mux_init_gpio(IGEP3_GPIO_BT_NRESET, OMAP_PIN_OUTPUT);
+
+	/* Set GPIO's for  W-LAN + Bluetooth combo module */
+	if ((gpio_request(IGEP3_GPIO_WIFI_NPD, "GPIO_WIFI_NPD") == 0) &&
+	    (gpio_direction_output(IGEP3_GPIO_WIFI_NPD, 1) == 0)) {
+		gpio_export(IGEP3_GPIO_WIFI_NPD, 0);
+	} else
+		pr_warning("IGEP: Could not obtain gpio GPIO_WIFI_NPD\n");
+
+	if ((gpio_request(IGEP3_GPIO_WIFI_NRESET, "GPIO_WIFI_NRESET") == 0) &&
+	    (gpio_direction_output(IGEP3_GPIO_WIFI_NRESET, 1) == 0)) {
+		gpio_export(IGEP3_GPIO_WIFI_NRESET, 0);
+		gpio_set_value(IGEP3_GPIO_WIFI_NRESET, 0);
+		udelay(10);
+		gpio_set_value(IGEP3_GPIO_WIFI_NRESET, 1);
+	} else
+		pr_warning("IGEP: Could not obtain gpio GPIO_WIFI_NRESET\n");
+
+	if ((gpio_request(IGEP3_GPIO_BT_NRESET, "GPIO_BT_NRESET") == 0) &&
+	    (gpio_direction_output(IGEP3_GPIO_BT_NRESET, 1) == 0)) {
+		gpio_export(IGEP3_GPIO_BT_NRESET, 0);
+	} else
+		pr_warning("IGEP: Could not obtain gpio GPIO_BT_NRESET\n");
+}
+
+#ifdef CONFIG_OMAP_MUX
+static struct omap_board_mux board_mux[] __initdata = {
+	{ .reg_offset = OMAP_MUX_TERMINATOR },
+};
+#else
+#define board_mux	NULL
+#endif
+
+static void __init igep3_init(void)
+{
+	omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
+
+	omap_serial_init();
+	usb_musb_init(&musb_board_data);
+
+	igep3_i2c_init();
+	igep3_flash_init();
+	igep3_init_wifi_bt();
+	igep3_init_led();
+}
+
+static void __init igep3_map_io(void)
+{
+	omap2_set_globals_343x();
+	omap34xx_map_common_io();
+}
+
+MACHINE_START(IGEP0030, "IGEP OMAP3 module")
+	.phys_io	= 0x48000000,
+	.io_pg_offst	= ((0xfa000000) >> 18) & 0xfffc,
+	.boot_params	= 0x80000100,
+	.map_io		= igep3_map_io,
+	.init_irq	= igep3_init_irq,
+	.init_machine	= igep3_init,
+	.timer		= &omap_timer,
+MACHINE_END