| /* | 
 |  * Board support file for OMAP4430 based PandaBoard. | 
 |  * | 
 |  * Copyright (C) 2010 Texas Instruments | 
 |  * | 
 |  * Author: David Anders <x0132446@ti.com> | 
 |  * | 
 |  * Based on mach-omap2/board-4430sdp.c | 
 |  * | 
 |  * Author: Santosh Shilimkar <santosh.shilimkar@ti.com> | 
 |  * | 
 |  * Based on mach-omap2/board-3430sdp.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/io.h> | 
 | #include <linux/leds.h> | 
 | #include <linux/gpio.h> | 
 | #include <linux/usb/otg.h> | 
 | #include <linux/i2c/twl.h> | 
 | #include <linux/regulator/machine.h> | 
 |  | 
 | #include <mach/hardware.h> | 
 | #include <mach/omap4-common.h> | 
 | #include <asm/mach-types.h> | 
 | #include <asm/mach/arch.h> | 
 | #include <asm/mach/map.h> | 
 |  | 
 | #include <plat/board.h> | 
 | #include <plat/common.h> | 
 | #include <plat/usb.h> | 
 | #include <plat/mmc.h> | 
 | #include "timer-gp.h" | 
 |  | 
 | #include "hsmmc.h" | 
 | #include "control.h" | 
 |  | 
 | #define GPIO_HUB_POWER		1 | 
 | #define GPIO_HUB_NRESET		62 | 
 |  | 
 | static struct gpio_led gpio_leds[] = { | 
 | 	{ | 
 | 		.name			= "pandaboard::status1", | 
 | 		.default_trigger	= "heartbeat", | 
 | 		.gpio			= 7, | 
 | 	}, | 
 | 	{ | 
 | 		.name			= "pandaboard::status2", | 
 | 		.default_trigger	= "mmc0", | 
 | 		.gpio			= 8, | 
 | 	}, | 
 | }; | 
 |  | 
 | static struct gpio_led_platform_data gpio_led_info = { | 
 | 	.leds		= gpio_leds, | 
 | 	.num_leds	= ARRAY_SIZE(gpio_leds), | 
 | }; | 
 |  | 
 | static struct platform_device leds_gpio = { | 
 | 	.name	= "leds-gpio", | 
 | 	.id	= -1, | 
 | 	.dev	= { | 
 | 		.platform_data	= &gpio_led_info, | 
 | 	}, | 
 | }; | 
 |  | 
 | static struct platform_device *panda_devices[] __initdata = { | 
 | 	&leds_gpio, | 
 | }; | 
 |  | 
 | static void __init omap4_panda_init_irq(void) | 
 | { | 
 | 	omap2_init_common_hw(NULL, NULL); | 
 | 	gic_init_irq(); | 
 | 	omap_gpio_init(); | 
 | } | 
 |  | 
 | static const struct ehci_hcd_omap_platform_data ehci_pdata __initconst = { | 
 | 	.port_mode[0] = EHCI_HCD_OMAP_MODE_PHY, | 
 | 	.port_mode[1] = EHCI_HCD_OMAP_MODE_UNKNOWN, | 
 | 	.port_mode[2] = EHCI_HCD_OMAP_MODE_UNKNOWN, | 
 | 	.phy_reset  = false, | 
 | 	.reset_gpio_port[0]  = -EINVAL, | 
 | 	.reset_gpio_port[1]  = -EINVAL, | 
 | 	.reset_gpio_port[2]  = -EINVAL | 
 | }; | 
 |  | 
 | static void __init omap4_ehci_init(void) | 
 | { | 
 | 	int ret; | 
 |  | 
 |  | 
 | 	/* disable the power to the usb hub prior to init */ | 
 | 	ret = gpio_request(GPIO_HUB_POWER, "hub_power"); | 
 | 	if (ret) { | 
 | 		pr_err("Cannot request GPIO %d\n", GPIO_HUB_POWER); | 
 | 		goto error1; | 
 | 	} | 
 | 	gpio_export(GPIO_HUB_POWER, 0); | 
 | 	gpio_direction_output(GPIO_HUB_POWER, 0); | 
 | 	gpio_set_value(GPIO_HUB_POWER, 0); | 
 |  | 
 | 	/* reset phy+hub */ | 
 | 	ret = gpio_request(GPIO_HUB_NRESET, "hub_nreset"); | 
 | 	if (ret) { | 
 | 		pr_err("Cannot request GPIO %d\n", GPIO_HUB_NRESET); | 
 | 		goto error2; | 
 | 	} | 
 | 	gpio_export(GPIO_HUB_NRESET, 0); | 
 | 	gpio_direction_output(GPIO_HUB_NRESET, 0); | 
 | 	gpio_set_value(GPIO_HUB_NRESET, 0); | 
 | 	gpio_set_value(GPIO_HUB_NRESET, 1); | 
 |  | 
 | 	usb_ehci_init(&ehci_pdata); | 
 |  | 
 | 	/* enable power to hub */ | 
 | 	gpio_set_value(GPIO_HUB_POWER, 1); | 
 | 	return; | 
 |  | 
 | error2: | 
 | 	gpio_free(GPIO_HUB_POWER); | 
 | error1: | 
 | 	pr_err("Unable to initialize EHCI power/reset\n"); | 
 | 	return; | 
 |  | 
 | } | 
 |  | 
 | static struct omap_musb_board_data musb_board_data = { | 
 | 	.interface_type		= MUSB_INTERFACE_UTMI, | 
 | 	.mode			= MUSB_PERIPHERAL, | 
 | 	.power			= 100, | 
 | }; | 
 |  | 
 | static struct omap2_hsmmc_info mmc[] = { | 
 | 	{ | 
 | 		.mmc		= 1, | 
 | 		.caps		= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA, | 
 | 		.gpio_wp	= -EINVAL, | 
 | 	}, | 
 | 	{}	/* Terminator */ | 
 | }; | 
 |  | 
 | static struct regulator_consumer_supply omap4_panda_vmmc_supply[] = { | 
 | 	{ | 
 | 		.supply = "vmmc", | 
 | 		.dev_name = "mmci-omap-hs.0", | 
 | 	}, | 
 | }; | 
 |  | 
 | static int omap4_twl6030_hsmmc_late_init(struct device *dev) | 
 | { | 
 | 	int ret = 0; | 
 | 	struct platform_device *pdev = container_of(dev, | 
 | 				struct platform_device, dev); | 
 | 	struct omap_mmc_platform_data *pdata = dev->platform_data; | 
 |  | 
 | 	if (!pdata) { | 
 | 		dev_err(dev, "%s: NULL platform data\n", __func__); | 
 | 		return -EINVAL; | 
 | 	} | 
 | 	/* Setting MMC1 Card detect Irq */ | 
 | 	if (pdev->id == 0) { | 
 | 		ret = twl6030_mmc_card_detect_config(); | 
 | 		 if (ret) | 
 | 			dev_err(dev, "%s: Error card detect config(%d)\n", | 
 | 				__func__, ret); | 
 | 		 else | 
 | 			pdata->slots[0].card_detect = twl6030_mmc_card_detect; | 
 | 	} | 
 | 	return ret; | 
 | } | 
 |  | 
 | static __init void omap4_twl6030_hsmmc_set_late_init(struct device *dev) | 
 | { | 
 | 	struct omap_mmc_platform_data *pdata; | 
 |  | 
 | 	/* dev can be null if CONFIG_MMC_OMAP_HS is not set */ | 
 | 	if (!dev) { | 
 | 		pr_err("Failed omap4_twl6030_hsmmc_set_late_init\n"); | 
 | 		return; | 
 | 	} | 
 | 	pdata = dev->platform_data; | 
 |  | 
 | 	pdata->init =	omap4_twl6030_hsmmc_late_init; | 
 | } | 
 |  | 
 | static int __init omap4_twl6030_hsmmc_init(struct omap2_hsmmc_info *controllers) | 
 | { | 
 | 	struct omap2_hsmmc_info *c; | 
 |  | 
 | 	omap2_hsmmc_init(controllers); | 
 | 	for (c = controllers; c->mmc; c++) | 
 | 		omap4_twl6030_hsmmc_set_late_init(c->dev); | 
 |  | 
 | 	return 0; | 
 | } | 
 |  | 
 | static struct regulator_init_data omap4_panda_vaux1 = { | 
 | 	.constraints = { | 
 | 		.min_uV			= 1000000, | 
 | 		.max_uV			= 3000000, | 
 | 		.apply_uV		= true, | 
 | 		.valid_modes_mask	= REGULATOR_MODE_NORMAL | 
 | 					| REGULATOR_MODE_STANDBY, | 
 | 		.valid_ops_mask	 = REGULATOR_CHANGE_VOLTAGE | 
 | 					| REGULATOR_CHANGE_MODE | 
 | 					| REGULATOR_CHANGE_STATUS, | 
 | 	}, | 
 | }; | 
 |  | 
 | static struct regulator_init_data omap4_panda_vaux2 = { | 
 | 	.constraints = { | 
 | 		.min_uV			= 1200000, | 
 | 		.max_uV			= 2800000, | 
 | 		.apply_uV		= true, | 
 | 		.valid_modes_mask	= REGULATOR_MODE_NORMAL | 
 | 					| REGULATOR_MODE_STANDBY, | 
 | 		.valid_ops_mask	 = REGULATOR_CHANGE_VOLTAGE | 
 | 					| REGULATOR_CHANGE_MODE | 
 | 					| REGULATOR_CHANGE_STATUS, | 
 | 	}, | 
 | }; | 
 |  | 
 | static struct regulator_init_data omap4_panda_vaux3 = { | 
 | 	.constraints = { | 
 | 		.min_uV			= 1000000, | 
 | 		.max_uV			= 3000000, | 
 | 		.apply_uV		= true, | 
 | 		.valid_modes_mask	= REGULATOR_MODE_NORMAL | 
 | 					| REGULATOR_MODE_STANDBY, | 
 | 		.valid_ops_mask	 = REGULATOR_CHANGE_VOLTAGE | 
 | 					| REGULATOR_CHANGE_MODE | 
 | 					| REGULATOR_CHANGE_STATUS, | 
 | 	}, | 
 | }; | 
 |  | 
 | /* VMMC1 for MMC1 card */ | 
 | static struct regulator_init_data omap4_panda_vmmc = { | 
 | 	.constraints = { | 
 | 		.min_uV			= 1200000, | 
 | 		.max_uV			= 3000000, | 
 | 		.apply_uV		= true, | 
 | 		.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      = omap4_panda_vmmc_supply, | 
 | }; | 
 |  | 
 | static struct regulator_init_data omap4_panda_vpp = { | 
 | 	.constraints = { | 
 | 		.min_uV			= 1800000, | 
 | 		.max_uV			= 2500000, | 
 | 		.apply_uV		= true, | 
 | 		.valid_modes_mask	= REGULATOR_MODE_NORMAL | 
 | 					| REGULATOR_MODE_STANDBY, | 
 | 		.valid_ops_mask	 = REGULATOR_CHANGE_VOLTAGE | 
 | 					| REGULATOR_CHANGE_MODE | 
 | 					| REGULATOR_CHANGE_STATUS, | 
 | 	}, | 
 | }; | 
 |  | 
 | static struct regulator_init_data omap4_panda_vusim = { | 
 | 	.constraints = { | 
 | 		.min_uV			= 1200000, | 
 | 		.max_uV			= 2900000, | 
 | 		.apply_uV		= true, | 
 | 		.valid_modes_mask	= REGULATOR_MODE_NORMAL | 
 | 					| REGULATOR_MODE_STANDBY, | 
 | 		.valid_ops_mask	 = REGULATOR_CHANGE_VOLTAGE | 
 | 					| REGULATOR_CHANGE_MODE | 
 | 					| REGULATOR_CHANGE_STATUS, | 
 | 	}, | 
 | }; | 
 |  | 
 | static struct regulator_init_data omap4_panda_vana = { | 
 | 	.constraints = { | 
 | 		.min_uV			= 2100000, | 
 | 		.max_uV			= 2100000, | 
 | 		.apply_uV		= true, | 
 | 		.valid_modes_mask	= REGULATOR_MODE_NORMAL | 
 | 					| REGULATOR_MODE_STANDBY, | 
 | 		.valid_ops_mask	 = REGULATOR_CHANGE_MODE | 
 | 					| REGULATOR_CHANGE_STATUS, | 
 | 	}, | 
 | }; | 
 |  | 
 | static struct regulator_init_data omap4_panda_vcxio = { | 
 | 	.constraints = { | 
 | 		.min_uV			= 1800000, | 
 | 		.max_uV			= 1800000, | 
 | 		.apply_uV		= true, | 
 | 		.valid_modes_mask	= REGULATOR_MODE_NORMAL | 
 | 					| REGULATOR_MODE_STANDBY, | 
 | 		.valid_ops_mask	 = REGULATOR_CHANGE_MODE | 
 | 					| REGULATOR_CHANGE_STATUS, | 
 | 	}, | 
 | }; | 
 |  | 
 | static struct regulator_init_data omap4_panda_vdac = { | 
 | 	.constraints = { | 
 | 		.min_uV			= 1800000, | 
 | 		.max_uV			= 1800000, | 
 | 		.apply_uV		= true, | 
 | 		.valid_modes_mask	= REGULATOR_MODE_NORMAL | 
 | 					| REGULATOR_MODE_STANDBY, | 
 | 		.valid_ops_mask	 = REGULATOR_CHANGE_MODE | 
 | 					| REGULATOR_CHANGE_STATUS, | 
 | 	}, | 
 | }; | 
 |  | 
 | static struct regulator_init_data omap4_panda_vusb = { | 
 | 	.constraints = { | 
 | 		.min_uV			= 3300000, | 
 | 		.max_uV			= 3300000, | 
 | 		.apply_uV		= true, | 
 | 		.valid_modes_mask	= REGULATOR_MODE_NORMAL | 
 | 					| REGULATOR_MODE_STANDBY, | 
 | 		.valid_ops_mask	 =	REGULATOR_CHANGE_MODE | 
 | 					| REGULATOR_CHANGE_STATUS, | 
 | 	}, | 
 | }; | 
 |  | 
 | static struct twl4030_platform_data omap4_panda_twldata = { | 
 | 	.irq_base	= TWL6030_IRQ_BASE, | 
 | 	.irq_end	= TWL6030_IRQ_END, | 
 |  | 
 | 	/* Regulators */ | 
 | 	.vmmc		= &omap4_panda_vmmc, | 
 | 	.vpp		= &omap4_panda_vpp, | 
 | 	.vusim		= &omap4_panda_vusim, | 
 | 	.vana		= &omap4_panda_vana, | 
 | 	.vcxio		= &omap4_panda_vcxio, | 
 | 	.vdac		= &omap4_panda_vdac, | 
 | 	.vusb		= &omap4_panda_vusb, | 
 | 	.vaux1		= &omap4_panda_vaux1, | 
 | 	.vaux2		= &omap4_panda_vaux2, | 
 | 	.vaux3		= &omap4_panda_vaux3, | 
 | }; | 
 |  | 
 | static struct i2c_board_info __initdata omap4_panda_i2c_boardinfo[] = { | 
 | 	{ | 
 | 		I2C_BOARD_INFO("twl6030", 0x48), | 
 | 		.flags = I2C_CLIENT_WAKE, | 
 | 		.irq = OMAP44XX_IRQ_SYS_1N, | 
 | 		.platform_data = &omap4_panda_twldata, | 
 | 	}, | 
 | }; | 
 | static int __init omap4_panda_i2c_init(void) | 
 | { | 
 | 	/* | 
 | 	 * Phoenix Audio IC needs I2C1 to | 
 | 	 * start with 400 KHz or less | 
 | 	 */ | 
 | 	omap_register_i2c_bus(1, 400, omap4_panda_i2c_boardinfo, | 
 | 			ARRAY_SIZE(omap4_panda_i2c_boardinfo)); | 
 | 	omap_register_i2c_bus(2, 400, NULL, 0); | 
 | 	omap_register_i2c_bus(3, 400, NULL, 0); | 
 | 	omap_register_i2c_bus(4, 400, NULL, 0); | 
 | 	return 0; | 
 | } | 
 | static void __init omap4_panda_init(void) | 
 | { | 
 | 	omap4_panda_i2c_init(); | 
 | 	platform_add_devices(panda_devices, ARRAY_SIZE(panda_devices)); | 
 | 	omap_serial_init(); | 
 | 	omap4_twl6030_hsmmc_init(mmc); | 
 | 	/* OMAP4 Panda uses internal transceiver so register nop transceiver */ | 
 | 	usb_nop_xceiv_register(); | 
 | 	omap4_ehci_init(); | 
 | 	/* FIXME: allow multi-omap to boot until musb is updated for omap4 */ | 
 | 	if (!cpu_is_omap44xx()) | 
 | 		usb_musb_init(&musb_board_data); | 
 | } | 
 |  | 
 | static void __init omap4_panda_map_io(void) | 
 | { | 
 | 	omap2_set_globals_443x(); | 
 | 	omap44xx_map_common_io(); | 
 | } | 
 |  | 
 | MACHINE_START(OMAP4_PANDA, "OMAP4 Panda board") | 
 | 	/* Maintainer: David Anders - Texas Instruments Inc */ | 
 | 	.boot_params	= 0x80000100, | 
 | 	.map_io		= omap4_panda_map_io, | 
 | 	.init_irq	= omap4_panda_init_irq, | 
 | 	.init_machine	= omap4_panda_init, | 
 | 	.timer		= &omap_timer, | 
 | MACHINE_END |