From 27494059a5d005b8cad4e0e8640ff031b86220dc Mon Sep 17 00:00:00 2001
From: Koen Kooi <koen@dominion.thruhere.net>
Date: Fri, 20 May 2011 13:06:24 +0200
Subject: [PATCH 2/7] OMAP3: beagle: add support for expansionboards

Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
---
 arch/arm/mach-omap2/board-omap3beagle.c |  272 ++++++++++++++++++++++++++++++-
 1 files changed, 269 insertions(+), 3 deletions(-)

diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
index 77bafa8..db285e1 100644
--- a/arch/arm/mach-omap2/board-omap3beagle.c
+++ b/arch/arm/mach-omap2/board-omap3beagle.c
@@ -21,6 +21,7 @@
 #include <linux/io.h>
 #include <linux/leds.h>
 #include <linux/gpio.h>
+#include <linux/irq.h>
 #include <linux/input.h>
 #include <linux/gpio_keys.h>
 #include <linux/opp.h>
@@ -154,6 +155,167 @@ fail0:
 	return;
 }
 
+char expansionboard_name[16];
+
+#if defined(CONFIG_WL12XX) || defined(CONFIG_WL12XX_MODULE)
+#include <linux/regulator/fixed.h>
+#include <linux/wl12xx.h>
+
+#define OMAP_BEAGLE_WLAN_EN_GPIO    (139)
+#define OMAP_BEAGLE_BT_EN_GPIO      (138)
+#define OMAP_BEAGLE_WLAN_IRQ_GPIO   (137)
+#define OMAP_BEAGLE_FM_EN_BT_WU     (136)
+
+struct wl12xx_platform_data omap_beagle_wlan_data __initdata = {
+	.irq = OMAP_GPIO_IRQ(OMAP_BEAGLE_WLAN_IRQ_GPIO),
+	.board_ref_clock = 2, /* 38.4 MHz */
+};
+
+static int gpios[] = {OMAP_BEAGLE_BT_EN_GPIO, OMAP_BEAGLE_FM_EN_BT_WU, -1};
+static struct platform_device wl12xx_device = {
+		.name		= "kim",
+		.id			= -1,
+		.dev.platform_data = &gpios,
+};
+
+static struct omap2_hsmmc_info mmcbbt[] = {
+ 	{
+ 		.mmc		= 1,
+ 		.caps		= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
+ 		.gpio_wp	= 29,
+ 	},
+	{
+		.name		= "wl1271",
+		.mmc		= 2,
+		.caps		= MMC_CAP_4_BIT_DATA | MMC_CAP_POWER_OFF_CARD,
+		.gpio_wp	= -EINVAL,
+		.gpio_cd	= -EINVAL,
+		.ocr_mask	= MMC_VDD_165_195,
+		.nonremovable	= true,
+	},
+ 	{}	/* Terminator */
+ };
+
+static struct regulator_consumer_supply beagle_vmmc2_supply = 
+	REGULATOR_SUPPLY("vmmc", "omap_hsmmc.1");
+
+static struct regulator_init_data beagle_vmmc2 = {
+	.constraints = {
+		.min_uV			= 1850000,
+		.max_uV			= 1850000,
+		.apply_uV		= true,
+		.valid_modes_mask	= REGULATOR_MODE_NORMAL
+					| REGULATOR_MODE_STANDBY,
+		.valid_ops_mask		= REGULATOR_CHANGE_MODE
+					| REGULATOR_CHANGE_STATUS,
+	},
+	.num_consumer_supplies = 1,
+	.consumer_supplies = &beagle_vmmc2_supply,
+};
+
+static struct fixed_voltage_config beagle_vwlan = {
+	.supply_name = "vwl1271",
+	.microvolts = 1800000,  /* 1.8V */
+	.gpio = OMAP_BEAGLE_WLAN_EN_GPIO,
+	.startup_delay = 70000, /* 70ms */
+	.enable_high = 1,
+	.enabled_at_boot = 0,
+	.init_data = &beagle_vmmc2,
+};
+
+static struct platform_device omap_vwlan_device = {
+	.name           = "reg-fixed-voltage",
+	.id             = 1,
+	.dev = {
+		.platform_data = &beagle_vwlan,
+	},
+};
+#endif
+
+#if defined(CONFIG_ENC28J60) || defined(CONFIG_ENC28J60_MODULE)
+
+#include <plat/mcspi.h>
+#include <linux/spi/spi.h>
+
+#define OMAP3BEAGLE_GPIO_ENC28J60_IRQ 157
+
+static struct omap2_mcspi_device_config enc28j60_spi_chip_info = {
+	.turbo_mode	= 0,
+	.single_channel	= 1,	/* 0: slave, 1: master */
+};
+
+static struct spi_board_info omap3beagle_zippy_spi_board_info[] __initdata = {
+	{
+		.modalias		= "enc28j60",
+		.bus_num		= 4,
+		.chip_select		= 0,
+		.max_speed_hz		= 20000000,
+		.controller_data	= &enc28j60_spi_chip_info,
+	},
+};
+
+static void __init omap3beagle_enc28j60_init(void)
+{
+	if ((gpio_request(OMAP3BEAGLE_GPIO_ENC28J60_IRQ, "ENC28J60_IRQ") == 0) &&
+	    (gpio_direction_input(OMAP3BEAGLE_GPIO_ENC28J60_IRQ) == 0)) {
+		gpio_export(OMAP3BEAGLE_GPIO_ENC28J60_IRQ, 0);
+		omap3beagle_zippy_spi_board_info[0].irq	= OMAP_GPIO_IRQ(OMAP3BEAGLE_GPIO_ENC28J60_IRQ);
+		irq_set_irq_type(omap3beagle_zippy_spi_board_info[0].irq, IRQ_TYPE_EDGE_FALLING);
+	} else {
+		printk(KERN_ERR "could not obtain gpio for ENC28J60_IRQ\n");
+		return;
+	}
+
+	spi_register_board_info(omap3beagle_zippy_spi_board_info,
+			ARRAY_SIZE(omap3beagle_zippy_spi_board_info));
+}
+
+#else
+static inline void __init omap3beagle_enc28j60_init(void) { return; }
+#endif
+
+#if defined(CONFIG_KS8851) || defined(CONFIG_KS8851_MODULE)
+
+#include <plat/mcspi.h>
+#include <linux/spi/spi.h>
+
+#define OMAP3BEAGLE_GPIO_KS8851_IRQ 157
+
+static struct omap2_mcspi_device_config ks8851_spi_chip_info = {
+	.turbo_mode	= 0,
+	.single_channel	= 1,	/* 0: slave, 1: master */
+};
+
+static struct spi_board_info omap3beagle_zippy2_spi_board_info[] __initdata = {
+	{
+		.modalias		= "ks8851",
+		.bus_num		= 4,
+		.chip_select		= 0,
+		.max_speed_hz		= 36000000,
+		.controller_data	= &ks8851_spi_chip_info,
+	},
+};
+
+static void __init omap3beagle_ks8851_init(void)
+{
+	if ((gpio_request(OMAP3BEAGLE_GPIO_KS8851_IRQ, "KS8851_IRQ") == 0) &&
+	    (gpio_direction_input(OMAP3BEAGLE_GPIO_KS8851_IRQ) == 0)) {
+		gpio_export(OMAP3BEAGLE_GPIO_KS8851_IRQ, 0);
+		omap3beagle_zippy2_spi_board_info[0].irq	= OMAP_GPIO_IRQ(OMAP3BEAGLE_GPIO_KS8851_IRQ);
+		irq_set_irq_type(omap3beagle_zippy2_spi_board_info[0].irq, IRQ_TYPE_EDGE_FALLING);
+	} else {
+		printk(KERN_ERR "could not obtain gpio for KS8851_IRQ\n");
+		return;
+	}
+	
+	spi_register_board_info(omap3beagle_zippy2_spi_board_info,
+							ARRAY_SIZE(omap3beagle_zippy2_spi_board_info));
+}
+
+#else
+static inline void __init omap3beagle_ks8851_init(void) { return; }
+#endif
+
 static struct mtd_partition omap3beagle_nand_partitions[] = {
 	/* All the partition sizes are listed in terms of NAND block size */
 	{
@@ -272,6 +434,12 @@ static struct omap2_hsmmc_info mmc[] = {
 		.caps		= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
 		.gpio_wp	= 29,
 	},
+	{
+		.mmc		= 2,
+		.caps       = MMC_CAP_4_BIT_DATA,
+		.transceiver	= true,
+		.ocr_mask	= 0x00100000,	/* 3.3V */
+	},
 	{}	/* Terminator */
 };
 
@@ -301,11 +469,25 @@ static int beagle_twl_gpio_setup(struct device *dev,
 	}
 	/* gpio + 0 is "mmc0_cd" (input/IRQ) */
 	mmc[0].gpio_cd = gpio + 0;
+#if defined(CONFIG_WL12XX) || defined(CONFIG_WL12XX_MODULE)
+	if(!strcmp(expansionboard_name, "bbtoys-wifi")) { 
+		omap2_hsmmc_init(mmcbbt);
+		/* link regulators to MMC adapters */
+		beagle_vmmc1_supply.dev = mmcbbt[0].dev;
+		beagle_vsim_supply.dev = mmcbbt[0].dev;
+	} else {
+		omap2_hsmmc_init(mmc);
+		/* link regulators to MMC adapters */
+		beagle_vmmc1_supply.dev = mmc[0].dev;
+		beagle_vsim_supply.dev = mmc[0].dev;
+	}
+#else
 	omap2_hsmmc_init(mmc);
 
 	/* link regulators to MMC adapters */
 	beagle_vmmc1_supply.dev = mmc[0].dev;
 	beagle_vsim_supply.dev = mmc[0].dev;
+#endif
 
 	/* REVISIT: need ehci-omap hooks for external VBUS
 	 * power switch and overcurrent detect
@@ -466,7 +648,7 @@ static struct twl4030_platform_data beagle_twldata = {
 	.vpll2		= &beagle_vpll2,
 };
 
-static struct i2c_board_info __initdata beagle_i2c_boardinfo[] = {
+static struct i2c_board_info __initdata beagle_i2c1_boardinfo[] = {
 	{
 		I2C_BOARD_INFO("twl4030", 0x48),
 		.flags = I2C_CLIENT_WAKE,
@@ -481,10 +663,24 @@ static struct i2c_board_info __initdata beagle_i2c_eeprom[] = {
        },
 };
 
+#if defined(CONFIG_RTC_DRV_DS1307) || \
+	defined(CONFIG_RTC_DRV_DS1307_MODULE)
+
+static struct i2c_board_info __initdata beagle_i2c2_boardinfo[] = {
+	{
+		I2C_BOARD_INFO("ds1307", 0x68),
+	},
+};
+#else
+static struct i2c_board_info __initdata beagle_i2c2_boardinfo[] = {};
+#endif
+
 static int __init omap3_beagle_i2c_init(void)
 {
-	omap_register_i2c_bus(1, 2600, beagle_i2c_boardinfo,
-			ARRAY_SIZE(beagle_i2c_boardinfo));
+	omap_register_i2c_bus(1, 2600, beagle_i2c1_boardinfo,
+			ARRAY_SIZE(beagle_i2c1_boardinfo));
+	omap_register_i2c_bus(2, 400,  beagle_i2c2_boardinfo,
+			ARRAY_SIZE(beagle_i2c2_boardinfo));
 	/* Bus 3 is attached to the DVI port where devices like the pico DLP
 	 * projector don't work reliably with 400kHz */
 	omap_register_i2c_bus(3, 100, beagle_i2c_eeprom, ARRAY_SIZE(beagle_i2c_eeprom));
@@ -627,6 +823,15 @@ static struct omap_musb_board_data musb_board_data = {
 	.power			= 100,
 };
 
+static int __init expansionboard_setup(char *str)
+{
+	if (!str)
+		return -EINVAL;
+	strncpy(expansionboard_name, str, 16);
+	printk(KERN_INFO "Beagle expansionboard: %s\n", expansionboard_name);
+	return 0;
+}
+
 static void __init beagle_opp_init(void)
 {
 	int r = 0;
@@ -693,6 +898,65 @@ static void __init omap3_beagle_init(void)
 	/* REVISIT leave DVI powered down until it's needed ... */
 	gpio_direction_output(170, true);
 
+	if(!strcmp(expansionboard_name, "zippy")) 
+	{
+		printk(KERN_INFO "Beagle expansionboard: initializing enc28j60\n");
+		omap3beagle_enc28j60_init();
+		printk(KERN_INFO "Beagle expansionboard: assigning GPIO 141 and 162 to MMC1\n");
+		mmc[1].gpio_wp = 141;
+		mmc[1].gpio_cd = 162;
+	}
+	
+	if(!strcmp(expansionboard_name, "zippy2")) 
+	{
+		printk(KERN_INFO "Beagle expansionboard: initializing ks_8851\n");
+		omap3beagle_ks8851_init();
+		printk(KERN_INFO "Beagle expansionboard: assigning GPIO 141 and 162 to MMC1\n");
+		mmc[1].gpio_wp = 141;
+		mmc[1].gpio_cd = 162;
+	}
+
+	if(!strcmp(expansionboard_name, "trainer"))
+	{
+		printk(KERN_INFO "Beagle expansionboard: exporting GPIOs 130-141,162 to userspace\n");
+		gpio_request(130, "sysfs");
+		gpio_export(130, 1);
+		gpio_request(131, "sysfs");
+		gpio_export(131, 1);
+		gpio_request(132, "sysfs");
+		gpio_export(132, 1);
+		gpio_request(133, "sysfs");
+		gpio_export(133, 1);
+		gpio_request(134, "sysfs");
+		gpio_export(134, 1);
+		gpio_request(135, "sysfs");
+		gpio_export(135, 1);
+		gpio_request(136, "sysfs");
+		gpio_export(136, 1);
+		gpio_request(137, "sysfs");
+		gpio_export(137, 1);
+		gpio_request(138, "sysfs");
+		gpio_export(138, 1);
+		gpio_request(139, "sysfs");
+		gpio_export(139, 1);
+		gpio_request(140, "sysfs");
+		gpio_export(140, 1);
+		gpio_request(141, "sysfs");
+		gpio_export(141, 1);
+		gpio_request(162, "sysfs");
+		gpio_export(162, 1);
+	}
+
+	if(!strcmp(expansionboard_name, "bbtoys-wifi"))
+	{
+		if (wl12xx_set_platform_data(&omap_beagle_wlan_data))
+			pr_err("error setting wl12xx data\n");
+		printk(KERN_INFO "Beagle expansionboard: registering wl12xx bt platform device\n");
+		platform_device_register(&wl12xx_device);
+		printk(KERN_INFO "Beagle expansionboard: registering wl12xx wifi platform device\n");
+		platform_device_register(&omap_vwlan_device);
+	}
+
 	usb_musb_init(&musb_board_data);
 	usbhs_init(&usbhs_bdata);
 	omap3beagle_flash_init();
@@ -705,6 +969,8 @@ static void __init omap3_beagle_init(void)
 	beagle_opp_init();
 }
 
+early_param("buddy", expansionboard_setup);
+
 MACHINE_START(OMAP3_BEAGLE, "OMAP3 Beagle Board")
 	/* Maintainer: Syed Mohammed Khasim - http://beagleboard.org */
 	.boot_params	= 0x80000100,
-- 
1.6.6.1

