90c62bf08f
Add low-level initialization for hsmmc controller. Merged into this patch patch are various improvments and board support by Grazvydas Ignotas and David Brownell. Also change wire4 to be wires, as some newer controllers support 8 data lines. Cc: Pierre Ossman <drzeus-mmc@drzeus.cx> Signed-off-by: Grazvydas Ignotas <notasas@gmail.com> Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> Signed-off-by: Tony Lindgren <tony@atomide.com>
335 lines
7.8 KiB
C
335 lines
7.8 KiB
C
/*
|
|
* linux/arch/arm/mach-omap2/board-omap3beagle.c
|
|
*
|
|
* Copyright (C) 2008 Texas Instruments
|
|
*
|
|
* Modified from mach-omap2/board-3430sdp.c
|
|
*
|
|
* Initial code: Syed Mohammed Khasim
|
|
*
|
|
* 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/leds.h>
|
|
#include <linux/gpio.h>
|
|
#include <linux/input.h>
|
|
#include <linux/gpio_keys.h>
|
|
|
|
#include <linux/mtd/mtd.h>
|
|
#include <linux/mtd/partitions.h>
|
|
#include <linux/mtd/nand.h>
|
|
|
|
#include <mach/hardware.h>
|
|
#include <asm/mach-types.h>
|
|
#include <asm/mach/arch.h>
|
|
#include <asm/mach/map.h>
|
|
#include <asm/mach/flash.h>
|
|
|
|
#include <mach/board.h>
|
|
#include <mach/common.h>
|
|
#include <mach/gpmc.h>
|
|
#include <mach/nand.h>
|
|
#include <mach/mux.h>
|
|
|
|
#include "mmc-twl4030.h"
|
|
|
|
#define GPMC_CS0_BASE 0x60
|
|
#define GPMC_CS_SIZE 0x30
|
|
|
|
#define NAND_BLOCK_SIZE SZ_128K
|
|
|
|
static struct mtd_partition omap3beagle_nand_partitions[] = {
|
|
/* All the partition sizes are listed in terms of NAND block size */
|
|
{
|
|
.name = "X-Loader",
|
|
.offset = 0,
|
|
.size = 4 * NAND_BLOCK_SIZE,
|
|
.mask_flags = MTD_WRITEABLE, /* force read-only */
|
|
},
|
|
{
|
|
.name = "U-Boot",
|
|
.offset = MTDPART_OFS_APPEND, /* Offset = 0x80000 */
|
|
.size = 15 * NAND_BLOCK_SIZE,
|
|
.mask_flags = MTD_WRITEABLE, /* force read-only */
|
|
},
|
|
{
|
|
.name = "U-Boot Env",
|
|
.offset = MTDPART_OFS_APPEND, /* Offset = 0x260000 */
|
|
.size = 1 * NAND_BLOCK_SIZE,
|
|
},
|
|
{
|
|
.name = "Kernel",
|
|
.offset = MTDPART_OFS_APPEND, /* Offset = 0x280000 */
|
|
.size = 32 * NAND_BLOCK_SIZE,
|
|
},
|
|
{
|
|
.name = "File System",
|
|
.offset = MTDPART_OFS_APPEND, /* Offset = 0x680000 */
|
|
.size = MTDPART_SIZ_FULL,
|
|
},
|
|
};
|
|
|
|
static struct omap_nand_platform_data omap3beagle_nand_data = {
|
|
.options = NAND_BUSWIDTH_16,
|
|
.parts = omap3beagle_nand_partitions,
|
|
.nr_parts = ARRAY_SIZE(omap3beagle_nand_partitions),
|
|
.dma_channel = -1, /* disable DMA in OMAP NAND driver */
|
|
.nand_setup = NULL,
|
|
.dev_ready = NULL,
|
|
};
|
|
|
|
static struct resource omap3beagle_nand_resource = {
|
|
.flags = IORESOURCE_MEM,
|
|
};
|
|
|
|
static struct platform_device omap3beagle_nand_device = {
|
|
.name = "omap2-nand",
|
|
.id = -1,
|
|
.dev = {
|
|
.platform_data = &omap3beagle_nand_data,
|
|
},
|
|
.num_resources = 1,
|
|
.resource = &omap3beagle_nand_resource,
|
|
};
|
|
|
|
static struct omap_uart_config omap3_beagle_uart_config __initdata = {
|
|
.enabled_uarts = ((1 << 0) | (1 << 1) | (1 << 2)),
|
|
};
|
|
|
|
static struct twl4030_hsmmc_info mmc[] = {
|
|
{
|
|
.mmc = 1,
|
|
.wires = 8,
|
|
.gpio_wp = 29,
|
|
},
|
|
{} /* Terminator */
|
|
};
|
|
|
|
static struct gpio_led gpio_leds[];
|
|
|
|
static int beagle_twl_gpio_setup(struct device *dev,
|
|
unsigned gpio, unsigned ngpio)
|
|
{
|
|
/* gpio + 0 is "mmc0_cd" (input/IRQ) */
|
|
|
|
/* REVISIT: need ehci-omap hooks for external VBUS
|
|
* power switch and overcurrent detect
|
|
*/
|
|
|
|
gpio_request(gpio + 1, "EHCI_nOC");
|
|
gpio_direction_input(gpio + 1);
|
|
|
|
/* TWL4030_GPIO_MAX + 0 == ledA, EHCI nEN_USB_PWR (out, active low) */
|
|
gpio_request(gpio + TWL4030_GPIO_MAX, "nEN_USB_PWR");
|
|
gpio_direction_output(gpio + TWL4030_GPIO_MAX, 1);
|
|
|
|
/* TWL4030_GPIO_MAX + 1 == ledB, PMU_STAT (out, active low LED) */
|
|
gpio_leds[2].gpio = gpio + TWL4030_GPIO_MAX + 1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static struct twl4030_gpio_platform_data beagle_gpio_data = {
|
|
.gpio_base = OMAP_MAX_GPIO_LINES,
|
|
.irq_base = TWL4030_GPIO_IRQ_BASE,
|
|
.irq_end = TWL4030_GPIO_IRQ_END,
|
|
.use_leds = true,
|
|
.pullups = BIT(1),
|
|
.pulldowns = BIT(2) | BIT(6) | BIT(7) | BIT(8) | BIT(13)
|
|
| BIT(15) | BIT(16) | BIT(17),
|
|
.setup = beagle_twl_gpio_setup,
|
|
};
|
|
|
|
static struct twl4030_platform_data beagle_twldata = {
|
|
.irq_base = TWL4030_IRQ_BASE,
|
|
.irq_end = TWL4030_IRQ_END,
|
|
|
|
/* platform_data for children goes here */
|
|
.gpio = &beagle_gpio_data,
|
|
};
|
|
|
|
static struct i2c_board_info __initdata beagle_i2c_boardinfo[] = {
|
|
{
|
|
I2C_BOARD_INFO("twl4030", 0x48),
|
|
.flags = I2C_CLIENT_WAKE,
|
|
.irq = INT_34XX_SYS_NIRQ,
|
|
.platform_data = &beagle_twldata,
|
|
},
|
|
};
|
|
|
|
static int __init omap3_beagle_i2c_init(void)
|
|
{
|
|
omap_register_i2c_bus(1, 2600, beagle_i2c_boardinfo,
|
|
ARRAY_SIZE(beagle_i2c_boardinfo));
|
|
#ifdef CONFIG_I2C2_OMAP_BEAGLE
|
|
omap_register_i2c_bus(2, 400, NULL, 0);
|
|
#endif
|
|
omap_register_i2c_bus(3, 400, NULL, 0);
|
|
return 0;
|
|
}
|
|
|
|
static void __init omap3_beagle_init_irq(void)
|
|
{
|
|
omap2_init_common_hw();
|
|
omap_init_irq();
|
|
omap_gpio_init();
|
|
}
|
|
|
|
static struct platform_device omap3_beagle_lcd_device = {
|
|
.name = "omap3beagle_lcd",
|
|
.id = -1,
|
|
};
|
|
|
|
static struct omap_lcd_config omap3_beagle_lcd_config __initdata = {
|
|
.ctrl_name = "internal",
|
|
};
|
|
|
|
static struct gpio_led gpio_leds[] = {
|
|
{
|
|
.name = "beagleboard::usr0",
|
|
.default_trigger = "heartbeat",
|
|
.gpio = 150,
|
|
},
|
|
{
|
|
.name = "beagleboard::usr1",
|
|
.default_trigger = "mmc0",
|
|
.gpio = 149,
|
|
},
|
|
{
|
|
.name = "beagleboard::pmu_stat",
|
|
.gpio = -EINVAL, /* gets replaced */
|
|
.active_low = true,
|
|
},
|
|
};
|
|
|
|
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 gpio_keys_button gpio_buttons[] = {
|
|
{
|
|
.code = BTN_EXTRA,
|
|
.gpio = 7,
|
|
.desc = "user",
|
|
.wakeup = 1,
|
|
},
|
|
};
|
|
|
|
static struct gpio_keys_platform_data gpio_key_info = {
|
|
.buttons = gpio_buttons,
|
|
.nbuttons = ARRAY_SIZE(gpio_buttons),
|
|
};
|
|
|
|
static struct platform_device keys_gpio = {
|
|
.name = "gpio-keys",
|
|
.id = -1,
|
|
.dev = {
|
|
.platform_data = &gpio_key_info,
|
|
},
|
|
};
|
|
|
|
static struct omap_board_config_kernel omap3_beagle_config[] __initdata = {
|
|
{ OMAP_TAG_UART, &omap3_beagle_uart_config },
|
|
{ OMAP_TAG_LCD, &omap3_beagle_lcd_config },
|
|
};
|
|
|
|
static struct platform_device *omap3_beagle_devices[] __initdata = {
|
|
&omap3_beagle_lcd_device,
|
|
&leds_gpio,
|
|
&keys_gpio,
|
|
};
|
|
|
|
static void __init omap3beagle_flash_init(void)
|
|
{
|
|
u8 cs = 0;
|
|
u8 nandcs = GPMC_CS_NUM + 1;
|
|
|
|
u32 gpmc_base_add = OMAP34XX_GPMC_VIRT;
|
|
|
|
/* find out the chip-select on which NAND exists */
|
|
while (cs < GPMC_CS_NUM) {
|
|
u32 ret = 0;
|
|
ret = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
|
|
|
|
if ((ret & 0xC00) == 0x800) {
|
|
printk(KERN_INFO "Found NAND on CS%d\n", cs);
|
|
if (nandcs > GPMC_CS_NUM)
|
|
nandcs = cs;
|
|
}
|
|
cs++;
|
|
}
|
|
|
|
if (nandcs > GPMC_CS_NUM) {
|
|
printk(KERN_INFO "NAND: Unable to find configuration "
|
|
"in GPMC\n ");
|
|
return;
|
|
}
|
|
|
|
if (nandcs < GPMC_CS_NUM) {
|
|
omap3beagle_nand_data.cs = nandcs;
|
|
omap3beagle_nand_data.gpmc_cs_baseaddr = (void *)
|
|
(gpmc_base_add + GPMC_CS0_BASE + nandcs * GPMC_CS_SIZE);
|
|
omap3beagle_nand_data.gpmc_baseaddr = (void *) (gpmc_base_add);
|
|
|
|
printk(KERN_INFO "Registering NAND on CS%d\n", nandcs);
|
|
if (platform_device_register(&omap3beagle_nand_device) < 0)
|
|
printk(KERN_ERR "Unable to register NAND device\n");
|
|
}
|
|
}
|
|
|
|
static void __init omap3_beagle_init(void)
|
|
{
|
|
omap3_beagle_i2c_init();
|
|
platform_add_devices(omap3_beagle_devices,
|
|
ARRAY_SIZE(omap3_beagle_devices));
|
|
omap_board_config = omap3_beagle_config;
|
|
omap_board_config_size = ARRAY_SIZE(omap3_beagle_config);
|
|
omap_serial_init();
|
|
|
|
omap_cfg_reg(AH8_34XX_GPIO29);
|
|
mmc[0].gpio_cd = gpio + 0;
|
|
twl4030_mmc_init(mmc);
|
|
|
|
omap_cfg_reg(J25_34XX_GPIO170);
|
|
gpio_request(170, "DVI_nPD");
|
|
/* REVISIT leave DVI powered down until it's needed ... */
|
|
gpio_direction_output(170, true);
|
|
|
|
omap3beagle_flash_init();
|
|
}
|
|
|
|
static void __init omap3_beagle_map_io(void)
|
|
{
|
|
omap2_set_globals_343x();
|
|
omap2_map_common_io();
|
|
}
|
|
|
|
MACHINE_START(OMAP3_BEAGLE, "OMAP3 Beagle Board")
|
|
/* Maintainer: Syed Mohammed Khasim - http://beagleboard.org */
|
|
.phys_io = 0x48000000,
|
|
.io_pg_offst = ((0xd8000000) >> 18) & 0xfffc,
|
|
.boot_params = 0x80000100,
|
|
.map_io = omap3_beagle_map_io,
|
|
.init_irq = omap3_beagle_init_irq,
|
|
.init_machine = omap3_beagle_init,
|
|
.timer = &omap_timer,
|
|
MACHINE_END
|