diff options
author | Russell King <rmk@dyn-67.arm.linux.org.uk> | 2008-10-09 21:33:05 +0100 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2008-10-09 21:33:05 +0100 |
commit | c97f68145e8067b3ac4b126a6faebf90f9ffc302 (patch) | |
tree | eb2060681552a00e9efa98224b95f69a3dc84390 /arch/arm/mach-davinci | |
parent | b1add0480a95b6ceaece5caf6c50614771eae9b2 (diff) | |
parent | 7bff3c4ce44ea48f50dc47a5994454984bd08c59 (diff) |
Merge branch 'for-rmk' of git://source.mvista.com/git/linux-davinci-2.6.git
Merge branch 'davinci' into devel
Diffstat (limited to 'arch/arm/mach-davinci')
-rw-r--r-- | arch/arm/mach-davinci/Makefile | 2 | ||||
-rw-r--r-- | arch/arm/mach-davinci/board-evm.c | 339 | ||||
-rw-r--r-- | arch/arm/mach-davinci/devices.c | 48 | ||||
-rw-r--r-- | arch/arm/mach-davinci/gpio.c | 133 | ||||
-rw-r--r-- | arch/arm/mach-davinci/include/mach/common.h | 3 | ||||
-rw-r--r-- | arch/arm/mach-davinci/include/mach/gpio.h | 73 | ||||
-rw-r--r-- | arch/arm/mach-davinci/include/mach/i2c.h | 7 | ||||
-rw-r--r-- | arch/arm/mach-davinci/include/mach/io.h | 43 | ||||
-rw-r--r-- | arch/arm/mach-davinci/usb.c | 116 |
9 files changed, 614 insertions, 150 deletions
diff --git a/arch/arm/mach-davinci/Makefile b/arch/arm/mach-davinci/Makefile index 99ac2e55774..4dc458597f4 100644 --- a/arch/arm/mach-davinci/Makefile +++ b/arch/arm/mach-davinci/Makefile @@ -5,7 +5,7 @@ # Common objects obj-y := time.o irq.o clock.o serial.o io.o id.o psc.o \ - gpio.o mux.o + gpio.o mux.o devices.o usb.o # Board specific obj-$(CONFIG_MACH_DAVINCI_EVM) += board-evm.o diff --git a/arch/arm/mach-davinci/board-evm.c b/arch/arm/mach-davinci/board-evm.c index 41f3cc4ac4a..a957d239a68 100644 --- a/arch/arm/mach-davinci/board-evm.c +++ b/arch/arm/mach-davinci/board-evm.c @@ -13,6 +13,13 @@ #include <linux/init.h> #include <linux/dma-mapping.h> #include <linux/platform_device.h> +#include <linux/gpio.h> +#include <linux/leds.h> + +#include <linux/i2c.h> +#include <linux/i2c/pcf857x.h> +#include <linux/i2c/at24.h> + #include <linux/mtd/mtd.h> #include <linux/mtd/partitions.h> #include <linux/mtd/physmap.h> @@ -20,13 +27,14 @@ #include <asm/setup.h> #include <asm/mach-types.h> -#include <mach/hardware.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> #include <asm/mach/flash.h> +#include <mach/hardware.h> #include <mach/common.h> +#include <mach/i2c.h> /* other misc. init functions */ void __init davinci_psc_init(void); @@ -34,10 +42,10 @@ void __init davinci_irq_init(void); void __init davinci_map_common_io(void); void __init davinci_init_common_hw(void); -/* NOR Flash base address set to CS0 by default */ -#define NOR_FLASH_PHYS 0x02000000 +#if defined(CONFIG_MTD_PHYSMAP) || \ + defined(CONFIG_MTD_PHYSMAP_MODULE) -static struct mtd_partition davinci_evm_partitions[] = { +static struct mtd_partition davinci_evm_norflash_partitions[] = { /* bootloader (U-Boot, etc) in first 4 sectors */ { .name = "bootloader", @@ -68,32 +76,323 @@ static struct mtd_partition davinci_evm_partitions[] = { } }; -static struct physmap_flash_data davinci_evm_flash_data = { +static struct physmap_flash_data davinci_evm_norflash_data = { .width = 2, - .parts = davinci_evm_partitions, - .nr_parts = ARRAY_SIZE(davinci_evm_partitions), + .parts = davinci_evm_norflash_partitions, + .nr_parts = ARRAY_SIZE(davinci_evm_norflash_partitions), }; /* NOTE: CFI probe will correctly detect flash part as 32M, but EMIF * limits addresses to 16M, so using addresses past 16M will wrap */ -static struct resource davinci_evm_flash_resource = { - .start = NOR_FLASH_PHYS, - .end = NOR_FLASH_PHYS + SZ_16M - 1, +static struct resource davinci_evm_norflash_resource = { + .start = DAVINCI_ASYNC_EMIF_DATA_CE0_BASE, + .end = DAVINCI_ASYNC_EMIF_DATA_CE0_BASE + SZ_16M - 1, .flags = IORESOURCE_MEM, }; -static struct platform_device davinci_evm_flash_device = { +static struct platform_device davinci_evm_norflash_device = { .name = "physmap-flash", .id = 0, .dev = { - .platform_data = &davinci_evm_flash_data, + .platform_data = &davinci_evm_norflash_data, }, .num_resources = 1, - .resource = &davinci_evm_flash_resource, + .resource = &davinci_evm_norflash_resource, +}; + +#endif + +#if defined(CONFIG_BLK_DEV_PALMCHIP_BK3710) || \ + defined(CONFIG_BLK_DEV_PALMCHIP_BK3710_MODULE) + +static struct resource ide_resources[] = { + { + .start = DAVINCI_CFC_ATA_BASE, + .end = DAVINCI_CFC_ATA_BASE + 0x7ff, + .flags = IORESOURCE_MEM, + }, + { + .start = IRQ_IDE, + .end = IRQ_IDE, + .flags = IORESOURCE_IRQ, + }, +}; + +static u64 ide_dma_mask = DMA_32BIT_MASK; + +static struct platform_device ide_dev = { + .name = "palm_bk3710", + .id = -1, + .resource = ide_resources, + .num_resources = ARRAY_SIZE(ide_resources), + .dev = { + .dma_mask = &ide_dma_mask, + .coherent_dma_mask = DMA_32BIT_MASK, + }, +}; + +#endif + +/*----------------------------------------------------------------------*/ + +/* + * I2C GPIO expanders + */ + +#define PCF_Uxx_BASE(x) (DAVINCI_N_GPIO + ((x) * 8)) + + +/* U2 -- LEDs */ + +static struct gpio_led evm_leds[] = { + { .name = "DS8", .active_low = 1, + .default_trigger = "heartbeat", }, + { .name = "DS7", .active_low = 1, }, + { .name = "DS6", .active_low = 1, }, + { .name = "DS5", .active_low = 1, }, + { .name = "DS4", .active_low = 1, }, + { .name = "DS3", .active_low = 1, }, + { .name = "DS2", .active_low = 1, + .default_trigger = "mmc0", }, + { .name = "DS1", .active_low = 1, + .default_trigger = "ide-disk", }, +}; + +static const struct gpio_led_platform_data evm_led_data = { + .num_leds = ARRAY_SIZE(evm_leds), + .leds = evm_leds, +}; + +static struct platform_device *evm_led_dev; + +static int +evm_led_setup(struct i2c_client *client, int gpio, unsigned ngpio, void *c) +{ + struct gpio_led *leds = evm_leds; + int status; + + while (ngpio--) { + leds->gpio = gpio++; + leds++; + } + + /* what an extremely annoying way to be forced to handle + * device unregistration ... + */ + evm_led_dev = platform_device_alloc("leds-gpio", 0); + platform_device_add_data(evm_led_dev, + &evm_led_data, sizeof evm_led_data); + + evm_led_dev->dev.parent = &client->dev; + status = platform_device_add(evm_led_dev); + if (status < 0) { + platform_device_put(evm_led_dev); + evm_led_dev = NULL; + } + return status; +} + +static int +evm_led_teardown(struct i2c_client *client, int gpio, unsigned ngpio, void *c) +{ + if (evm_led_dev) { + platform_device_unregister(evm_led_dev); + evm_led_dev = NULL; + } + return 0; +} + +static struct pcf857x_platform_data pcf_data_u2 = { + .gpio_base = PCF_Uxx_BASE(0), + .setup = evm_led_setup, + .teardown = evm_led_teardown, +}; + + +/* U18 - A/V clock generator and user switch */ + +static int sw_gpio; + +static ssize_t +sw_show(struct device *d, struct device_attribute *a, char *buf) +{ + char *s = gpio_get_value_cansleep(sw_gpio) ? "on\n" : "off\n"; + + strcpy(buf, s); + return strlen(s); +} + +static DEVICE_ATTR(user_sw, S_IRUGO, sw_show, NULL); + +static int +evm_u18_setup(struct i2c_client *client, int gpio, unsigned ngpio, void *c) +{ + int status; + + /* export dip switch option */ + sw_gpio = gpio + 7; + status = gpio_request(sw_gpio, "user_sw"); + if (status == 0) + status = gpio_direction_input(sw_gpio); + if (status == 0) + status = device_create_file(&client->dev, &dev_attr_user_sw); + else + gpio_free(sw_gpio); + if (status != 0) + sw_gpio = -EINVAL; + + /* audio PLL: 48 kHz (vs 44.1 or 32), single rate (vs double) */ + gpio_request(gpio + 3, "pll_fs2"); + gpio_direction_output(gpio + 3, 0); + + gpio_request(gpio + 2, "pll_fs1"); + gpio_direction_output(gpio + 2, 0); + + gpio_request(gpio + 1, "pll_sr"); + gpio_direction_output(gpio + 1, 0); + + return 0; +} + +static int +evm_u18_teardown(struct i2c_client *client, int gpio, unsigned ngpio, void *c) +{ + gpio_free(gpio + 1); + gpio_free(gpio + 2); + gpio_free(gpio + 3); + + if (sw_gpio > 0) { + device_remove_file(&client->dev, &dev_attr_user_sw); + gpio_free(sw_gpio); + } + return 0; +} + +static struct pcf857x_platform_data pcf_data_u18 = { + .gpio_base = PCF_Uxx_BASE(1), + .n_latch = (1 << 3) | (1 << 2) | (1 << 1), + .setup = evm_u18_setup, + .teardown = evm_u18_teardown, }; + +/* U35 - various I/O signals used to manage USB, CF, ATA, etc */ + +static int +evm_u35_setup(struct i2c_client *client, int gpio, unsigned ngpio, void *c) +{ + /* p0 = nDRV_VBUS (initial: don't supply it) */ + gpio_request(gpio + 0, "nDRV_VBUS"); + gpio_direction_output(gpio + 0, 1); + + /* p1 = VDDIMX_EN */ + gpio_request(gpio + 1, "VDDIMX_EN"); + gpio_direction_output(gpio + 1, 1); + + /* p2 = VLYNQ_EN */ + gpio_request(gpio + 2, "VLYNQ_EN"); + gpio_direction_output(gpio + 2, 1); + + /* p3 = n3V3_CF_RESET (initial: stay in reset) */ + gpio_request(gpio + 3, "nCF_RESET"); + gpio_direction_output(gpio + 3, 0); + + /* (p4 unused) */ + + /* p5 = 1V8_WLAN_RESET (initial: stay in reset) */ + gpio_request(gpio + 5, "WLAN_RESET"); + gpio_direction_output(gpio + 5, 1); + + /* p6 = nATA_SEL (initial: select) */ + gpio_request(gpio + 6, "nATA_SEL"); + gpio_direction_output(gpio + 6, 0); + + /* p7 = nCF_SEL (initial: deselect) */ + gpio_request(gpio + 7, "nCF_SEL"); + gpio_direction_output(gpio + 7, 1); + + return 0; +} + +static int +evm_u35_teardown(struct i2c_client *client, int gpio, unsigned ngpio, void *c) +{ + gpio_free(gpio + 7); + gpio_free(gpio + 6); + gpio_free(gpio + 5); + gpio_free(gpio + 3); + gpio_free(gpio + 2); + gpio_free(gpio + 1); + gpio_free(gpio + 0); + return 0; +} + +static struct pcf857x_platform_data pcf_data_u35 = { + .gpio_base = PCF_Uxx_BASE(2), + .setup = evm_u35_setup, + .teardown = evm_u35_teardown, +}; + +/*----------------------------------------------------------------------*/ + +/* Most of this EEPROM is unused, but U-Boot uses some data: + * - 0x7f00, 6 bytes Ethernet Address + * - 0x0039, 1 byte NTSC vs PAL (bit 0x80 == PAL) + * - ... newer boards may have more + */ +static struct at24_platform_data eeprom_info = { + .byte_len = (256*1024) / 8, + .page_size = 64, + .flags = AT24_FLAG_ADDR16, +}; + +static struct i2c_board_info __initdata i2c_info[] = { + { + I2C_BOARD_INFO("pcf8574", 0x38), + .platform_data = &pcf_data_u2, + }, + { + I2C_BOARD_INFO("pcf8574", 0x39), + .platform_data = &pcf_data_u18, + }, + { + I2C_BOARD_INFO("pcf8574", 0x3a), + .platform_data = &pcf_data_u35, + }, + { + I2C_BOARD_INFO("24c256", 0x50), + .platform_data = &eeprom_info, + }, + /* ALSO: + * - tvl320aic33 audio codec (0x1b) + * - msp430 microcontroller (0x23) + * - tvp5146 video decoder (0x5d) + */ +}; + +/* The msp430 uses a slow bitbanged I2C implementation (ergo 20 KHz), + * which requires 100 usec of idle bus after i2c writes sent to it. + */ +static struct davinci_i2c_platform_data i2c_pdata = { + .bus_freq = 20 /* kHz */, + .bus_delay = 100 /* usec */, +}; + +static void __init evm_init_i2c(void) +{ + davinci_init_i2c(&i2c_pdata); + i2c_register_board_info(1, i2c_info, ARRAY_SIZE(i2c_info)); +} + static struct platform_device *davinci_evm_devices[] __initdata = { - &davinci_evm_flash_device, +#if defined(CONFIG_MTD_PHYSMAP) || \ + defined(CONFIG_MTD_PHYSMAP_MODULE) + &davinci_evm_norflash_device, +#endif +#if defined(CONFIG_BLK_DEV_PALMCHIP_BK3710) || \ + defined(CONFIG_BLK_DEV_PALMCHIP_BK3710_MODULE) + &ide_dev, +#endif }; static void __init @@ -106,13 +405,21 @@ static __init void davinci_evm_init(void) { davinci_psc_init(); -#if defined(CONFIG_BLK_DEV_DAVINCI) || defined(CONFIG_BLK_DEV_DAVINCI_MODULE) +#if defined(CONFIG_BLK_DEV_PALMCHIP_BK3710) || \ + defined(CONFIG_BLK_DEV_PALMCHIP_BK3710_MODULE) +#if defined(CONFIG_MTD_PHYSMAP) || \ + defined(CONFIG_MTD_PHYSMAP_MODULE) printk(KERN_WARNING "WARNING: both IDE and NOR flash are enabled, " "but share pins.\n\t Disable IDE for NOR support.\n"); #endif +#endif platform_add_devices(davinci_evm_devices, ARRAY_SIZE(davinci_evm_devices)); + evm_init_i2c(); + + /* irlml6401 sustains over 3A, switches 5V in under 8 msec */ + setup_usb(500, 8); } static __init void davinci_evm_irq_init(void) @@ -124,7 +431,7 @@ static __init void davinci_evm_irq_init(void) MACHINE_START(DAVINCI_EVM, "DaVinci EVM") /* Maintainer: MontaVista Software <source@mvista.com> */ .phys_io = IO_PHYS, - .io_pg_offst = (io_p2v(IO_PHYS) >> 18) & 0xfffc, + .io_pg_offst = (__IO_ADDRESS(IO_PHYS) >> 18) & 0xfffc, .boot_params = (DAVINCI_DDR_BASE + 0x100), .map_io = davinci_evm_map_io, .init_irq = davinci_evm_irq_init, diff --git a/arch/arm/mach-davinci/devices.c b/arch/arm/mach-davinci/devices.c new file mode 100644 index 00000000000..3d4b1de8f89 --- /dev/null +++ b/arch/arm/mach-davinci/devices.c @@ -0,0 +1,48 @@ +/* + * mach-davinci/devices.c + * + * DaVinci platform device setup/initialization + * + * 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. + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/platform_device.h> +#include <linux/dma-mapping.h> +#include <linux/io.h> + +#include <asm/mach/map.h> + +#include <mach/hardware.h> +#include <mach/i2c.h> + +static struct resource i2c_resources[] = { + { + .start = DAVINCI_I2C_BASE, + .end = DAVINCI_I2C_BASE + 0x40, + .flags = IORESOURCE_MEM, + }, + { + .start = IRQ_I2C, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device davinci_i2c_device = { + .name = "i2c_davinci", + .id = 1, + .num_resources = ARRAY_SIZE(i2c_resources), + .resource = i2c_resources, +}; + +void __init davinci_init_i2c(struct davinci_i2c_platform_data *pdata) +{ + davinci_i2c_device.dev.platform_data = pdata; + (void) platform_device_register(&davinci_i2c_device); +} + diff --git a/arch/arm/mach-davinci/gpio.c b/arch/arm/mach-davinci/gpio.c index 574cb810a50..b49e9d092aa 100644 --- a/arch/arm/mach-davinci/gpio.c +++ b/arch/arm/mach-davinci/gpio.c @@ -1,7 +1,7 @@ /* * TI DaVinci GPIO Support * - * Copyright (c) 2006 David Brownell + * Copyright (c) 2006-2007 David Brownell * Copyright (c) 2007, MontaVista Software, Inc. <source@mvista.com> * * This program is free software; you can redistribute it and/or modify @@ -26,47 +26,45 @@ #include <asm/mach/irq.h> -static DEFINE_SPINLOCK(gpio_lock); -static DECLARE_BITMAP(gpio_in_use, DAVINCI_N_GPIO); -int gpio_request(unsigned gpio, const char *tag) -{ - if (gpio >= DAVINCI_N_GPIO) - return -EINVAL; +static DEFINE_SPINLOCK(gpio_lock); - if (test_and_set_bit(gpio, gpio_in_use)) - return -EBUSY; +struct davinci_gpio { + struct gpio_chip chip; + struct gpio_controller *__iomem regs; +}; - return 0; -} -EXPORT_SYMBOL(gpio_request); +static struct davinci_gpio chips[DIV_ROUND_UP(DAVINCI_N_GPIO, 32)]; -void gpio_free(unsigned gpio) -{ - if (gpio >= DAVINCI_N_GPIO) - return; - - clear_bit(gpio, gpio_in_use); -} -EXPORT_SYMBOL(gpio_free); /* create a non-inlined version */ -static struct gpio_controller *__iomem gpio2controller(unsigned gpio) +static struct gpio_controller *__iomem __init gpio2controller(unsigned gpio) { return __gpio_to_controller(gpio); } + +/*--------------------------------------------------------------------------*/ + /* - * Assuming the pin is muxed as a gpio output, set its output value. + * board setup code *MUST* set PINMUX0 and PINMUX1 as + * needed, and enable the GPIO clock. */ -void __gpio_set(unsigned gpio, int value) + +static int davinci_direction_in(struct gpio_chip *chip, unsigned offset) { - struct gpio_controller *__iomem g = gpio2controller(gpio); + struct davinci_gpio *d = container_of(chip, struct davinci_gpio, chip); + struct gpio_controller *__iomem g = d->regs; + u32 temp; - __raw_writel(__gpio_mask(gpio), value ? &g->set_data : &g->clr_data); -} -EXPORT_SYMBOL(__gpio_set); + spin_lock(&gpio_lock); + temp = __raw_readl(&g->dir); + temp |= (1 << offset); + __raw_writel(temp, &g->dir); + spin_unlock(&gpio_lock); + return 0; +} /* * Read the pin's value (works even if it's set up as output); @@ -75,61 +73,72 @@ EXPORT_SYMBOL(__gpio_set); * Note that changes are synched to the GPIO clock, so reading values back * right after you've set them may give old values. */ -int __gpio_get(unsigned gpio) +static int davinci_gpio_get(struct gpio_chip *chip, unsigned offset) { - struct gpio_controller *__iomem g = gpio2controller(gpio); + struct davinci_gpio *d = container_of(chip, struct davinci_gpio, chip); + struct gpio_controller *__iomem g = d->regs; - return !!(__gpio_mask(gpio) & __raw_readl(&g->in_data)); + return (1 << offset) & __raw_readl(&g->in_data); } -EXPORT_SYMBOL(__gpio_get); - -/*--------------------------------------------------------------------------*/ - -/* - * board setup code *MUST* set PINMUX0 and PINMUX1 as - * needed, and enable the GPIO clock. - */ - -int gpio_direction_input(unsigned gpio) +static int +davinci_direction_out(struct gpio_chip *chip, unsigned offset, int value) { - struct gpio_controller *__iomem g = gpio2controller(gpio); + struct davinci_gpio *d = container_of(chip, struct davinci_gpio, chip); + struct gpio_controller *__iomem g = d->regs; u32 temp; - u32 mask; - - if (!g) - return -EINVAL; + u32 mask = 1 << offset; spin_lock(&gpio_lock); - mask = __gpio_mask(gpio); temp = __raw_readl(&g->dir); - temp |= mask; + temp &= ~mask; + __raw_writel(mask, value ? &g->set_data : &g->clr_data); __raw_writel(temp, &g->dir); spin_unlock(&gpio_lock); return 0; } -EXPORT_SYMBOL(gpio_direction_input); -int gpio_direction_output(unsigned gpio, int value) +/* + * Assuming the pin is muxed as a gpio output, set its output value. + */ +static void +davinci_gpio_set(struct gpio_chip *chip, unsigned offset, int value) { - struct gpio_controller *__iomem g = gpio2controller(gpio); - u32 temp; - u32 mask; + struct davinci_gpio *d = container_of(chip, struct davinci_gpio, chip); + struct gpio_controller *__iomem g = d->regs; - if (!g) - return -EINVAL; + __raw_writel((1 << offset), value ? &g->set_data : &g->clr_data); +} + +static int __init davinci_gpio_setup(void) +{ + int i, base; + + for (i = 0, base = 0; + i < ARRAY_SIZE(chips); + i++, base += 32) { + chips[i].chip.label = "DaVinci"; + + chips[i].chip.direction_input = davinci_direction_in; + chips[i].chip.get = davinci_gpio_get; + chips[i].chip.direction_output = davinci_direction_out; + chips[i].chip.set = davinci_gpio_set; + + chips[i].chip.base = base; + chips[i].chip.ngpio = DAVINCI_N_GPIO - base; + if (chips[i].chip.ngpio > 32) + chips[i].chip.ngpio = 32; + + chips[i].regs = gpio2controller(base); + + gpiochip_add(&chips[i].chip); + } - spin_lock(&gpio_lock); - mask = __gpio_mask(gpio); - temp = __raw_readl(&g->dir); - temp &= ~mask; - __raw_writel(mask, value ? &g->set_data : &g->clr_data); - __raw_writel(temp, &g->dir); - spin_unlock(&gpio_lock); return 0; } -EXPORT_SYMBOL(gpio_direction_output); +pure_initcall(davinci_gpio_setup); +/*--------------------------------------------------------------------------*/ /* * We expect irqs will normally be set up as input pins, but they can also be * used as output pins ... which is convenient for testing. diff --git a/arch/arm/mach-davinci/include/mach/common.h b/arch/arm/mach-davinci/include/mach/common.h index a97dfbb15e5..4b522e5c70e 100644 --- a/arch/arm/mach-davinci/include/mach/common.h +++ b/arch/arm/mach-davinci/include/mach/common.h @@ -16,4 +16,7 @@ struct sys_timer; extern struct sys_timer davinci_timer; +/* parameters describe VBUS sourcing for host mode */ +extern void setup_usb(unsigned mA, unsigned potpgt_msec); + #endif /* __ARCH_ARM_MACH_DAVINCI_COMMON_H */ diff --git a/arch/arm/mach-davinci/include/mach/gpio.h b/arch/arm/mach-davinci/include/mach/gpio.h index ec151ccf1e8..b3a2961f0f4 100644 --- a/arch/arm/mach-davinci/include/mach/gpio.h +++ b/arch/arm/mach-davinci/include/mach/gpio.h @@ -14,6 +14,7 @@ #define __DAVINCI_GPIO_H #include <linux/io.h> +#include <asm-generic/gpio.h> #include <mach/hardware.h> /* @@ -27,13 +28,16 @@ * need to pay attention to PINMUX0 and PINMUX1 to be sure those pins are * used as gpios, not with other peripherals. * - * GPIOs are numbered 0..(DAVINCI_N_GPIO-1). For documentation, and maybe - * for later updates, code should write GPIO(N) or: + * On-chip GPIOs are numbered 0..(DAVINCI_N_GPIO-1). For documentation, + * and maybe for later updates, code should write GPIO(N) or: * - GPIOV18(N) for 1.8V pins, N in 0..53; same as GPIO(0)..GPIO(53) * - GPIOV33(N) for 3.3V pins, N in 0..17; same as GPIO(54)..GPIO(70) * * For GPIO IRQs use gpio_to_irq(GPIO(N)) or gpio_to_irq(GPIOV33(N)) etc * for now, that's != GPIO(N) + * + * GPIOs can also be on external chips, numbered after the ones built-in + * to the DaVinci chip. For now, they won't be usable as IRQ sources. */ #define GPIO(X) (X) /* 0 <= X <= 70 */ #define GPIOV18(X) (X) /* 1.8V i/o; 0 <= X <= 53 */ @@ -67,11 +71,11 @@ __gpio_to_controller(unsigned gpio) void *__iomem ptr; if (gpio < 32) - ptr = (void *__iomem)IO_ADDRESS(DAVINCI_GPIO_BASE + 0x10); + ptr = IO_ADDRESS(DAVINCI_GPIO_BASE + 0x10); else if (gpio < 64) - ptr = (void *__iomem)IO_ADDRESS(DAVINCI_GPIO_BASE + 0x38); + ptr = IO_ADDRESS(DAVINCI_GPIO_BASE + 0x38); else if (gpio < DAVINCI_N_GPIO) - ptr = (void *__iomem)IO_ADDRESS(DAVINCI_GPIO_BASE + 0x60); + ptr = IO_ADDRESS(DAVINCI_GPIO_BASE + 0x60); else ptr = NULL; return ptr; @@ -83,25 +87,17 @@ static inline u32 __gpio_mask(unsigned gpio) } /* The get/set/clear functions will inline when called with constant - * parameters, for low-overhead bitbanging. Illegal constant parameters - * cause link-time errors. + * parameters referencing built-in GPIOs, for low-overhead bitbanging. * - * Otherwise, calls with variable parameters use outlined functions. + * Otherwise, calls with variable parameters or referencing external + * GPIOs (e.g. on GPIO expander chips) use outlined functions. */ -extern int __error_inval_gpio(void); - -extern void __gpio_set(unsigned gpio, int value); -extern int __gpio_get(unsigned gpio); - static inline void gpio_set_value(unsigned gpio, int value) { - if (__builtin_constant_p(value)) { + if (__builtin_constant_p(value) && gpio < DAVINCI_N_GPIO) { struct gpio_controller *__iomem g; u32 mask; - if (gpio >= DAVINCI_N_GPIO) - __error_inval_gpio(); - g = __gpio_to_controller(gpio); mask = __gpio_mask(gpio); if (value) @@ -111,48 +107,47 @@ static inline void gpio_set_value(unsigned gpio, int value) return; } - __gpio_set(gpio, value); + __gpio_set_value(gpio, value); } /* Returns zero or nonzero; works for gpios configured as inputs OR - * as outputs. + * as outputs, at least for built-in GPIOs. * - * NOTE: changes in reported values are synchronized to the GPIO clock. - * This is most easily seen after calling gpio_set_value() and then immediatly - * gpio_get_value(), where the gpio_get_value() would return the old value - * until the GPIO clock ticks and the new value gets latched. + * NOTE: for built-in GPIOs, changes in reported values are synchronized + * to the GPIO clock. This is easily seen after calling gpio_set_value() + * and then immediately gpio_get_value(), where the gpio_get_value() will + * return the old value until the GPIO clock ticks and the new value gets + * latched. */ - static inline int gpio_get_value(unsigned gpio) { - struct gpio_controller *__iomem g; - - if (!__builtin_constant_p(gpio)) - return __gpio_get(gpio); + struct gpio_controller *__iomem g; - if (gpio >= DAVINCI_N_GPIO) - return __error_inval_gpio(); + if (!__builtin_constant_p(gpio) || gpio >= DAVINCI_N_GPIO) + return __gpio_get_value(gpio); g = __gpio_to_controller(gpio); - return !!(__gpio_mask(gpio) & __raw_readl(&g->in_data)); + return __gpio_mask(gpio) & __raw_readl(&g->in_data); } -/* powerup default direction is IN */ -extern int gpio_direction_input(unsigned gpio); -extern int gpio_direction_output(unsigned gpio, int value); - -#include <asm-generic/gpio.h> /* cansleep wrappers */ - -extern int gpio_request(unsigned gpio, const char *tag); -extern void gpio_free(unsigned gpio); +static inline int gpio_cansleep(unsigned gpio) +{ + if (__builtin_constant_p(gpio) && gpio < DAVINCI_N_GPIO) + return 0; + else + return __gpio_cansleep(gpio); +} static inline int gpio_to_irq(unsigned gpio) { + if (gpio >= DAVINCI_N_GPIO) + return -EINVAL; return DAVINCI_N_AINTC_IRQ + gpio; } static inline int irq_to_gpio(unsigned irq) { + /* caller guarantees gpio_to_irq() succeeded */ return irq - DAVINCI_N_AINTC_IRQ; } diff --git a/arch/arm/mach-davinci/include/mach/i2c.h b/arch/arm/mach-davinci/include/mach/i2c.h index e2f54168abd..c248e9b7e82 100644 --- a/arch/arm/mach-davinci/include/mach/i2c.h +++ b/arch/arm/mach-davinci/include/mach/i2c.h @@ -14,8 +14,11 @@ /* All frequencies are expressed in kHz */ struct davinci_i2c_platform_data { - unsigned int bus_freq; /* standard bus frequency */ - unsigned int bus_delay; /* transaction delay */ + unsigned int bus_freq; /* standard bus frequency (kHz) */ + unsigned int bus_delay; /* post-transaction delay (usec) */ }; +/* for board setup code */ +void davinci_init_i2c(struct davinci_i2c_platform_data *); + #endif /* __ASM_ARCH_I2C_H */ diff --git a/arch/arm/mach-davinci/include/mach/io.h b/arch/arm/mach-davinci/include/mach/io.h index e7accb91086..b78ee914049 100644 --- a/arch/arm/mach-davinci/include/mach/io.h +++ b/arch/arm/mach-davinci/include/mach/io.h @@ -22,9 +22,8 @@ #define IO_OFFSET 0xfd000000 /* Virtual IO = 0xfec00000 */ #define IO_SIZE 0x00400000 #define IO_VIRT (IO_PHYS + IO_OFFSET) -#define io_p2v(pa) ((pa) + IO_OFFSET) #define io_v2p(va) ((va) - IO_OFFSET) -#define IO_ADDRESS(x) io_p2v(x) +#define __IO_ADDRESS(x) ((x) + IO_OFFSET) /* * We don't actually have real ISA nor PCI buses, but there is so many @@ -35,7 +34,12 @@ #define __mem_pci(a) (a) #define __mem_isa(a) (a) -#ifndef __ASSEMBLER__ +#define IO_ADDRESS(pa) IOMEM(__IO_ADDRESS(pa)) + +#ifdef __ASSEMBLER__ +#define IOMEM(x) x +#else +#define IOMEM(x) ((void __force __iomem *)(x)) /* * Functions to access the DaVinci IO region @@ -46,34 +50,13 @@ * - DO NOT use hardcoded virtual addresses to allow changing the * IO address space again if needed */ -#define davinci_readb(a) (*(volatile unsigned char *)IO_ADDRESS(a)) -#define davinci_readw(a) (*(volatile unsigned short *)IO_ADDRESS(a)) -#define davinci_readl(a) (*(volatile unsigned int *)IO_ADDRESS(a)) - -#define davinci_writeb(v,a) (*(volatile unsigned char *)IO_ADDRESS(a) = (v)) -#define davinci_writew(v,a) (*(volatile unsigned short *)IO_ADDRESS(a) = (v)) -#define davinci_writel(v,a) (*(volatile unsigned int *)IO_ADDRESS(a) = (v)) - -/* 16 bit uses LDRH/STRH, base +/- offset_8 */ -typedef struct { volatile u16 offset[256]; } __regbase16; -#define __REGV16(vaddr) ((__regbase16 *)((vaddr)&~0xff)) \ - ->offset[((vaddr)&0xff)>>1] -#define __REG16(paddr) __REGV16(io_p2v(paddr)) - -/* 8/32 bit uses LDR/STR, base +/- offset_12 */ -typedef struct { volatile u8 offset[4096]; } __regbase8; -#define __REGV8(vaddr) ((__regbase8 *)((vaddr)&~4095)) \ - ->offset[((vaddr)&4095)>>0] -#define __REG8(paddr) __REGV8(io_p2v(paddr)) - -typedef struct { volatile u32 offset[4096]; } __regbase32; -#define __REGV32(vaddr) ((__regbase32 *)((vaddr)&~4095)) \ - ->offset[((vaddr)&4095)>>2] - -#define __REG(paddr) __REGV32(io_p2v(paddr)) -#else +#define davinci_readb(a) __raw_readb(IO_ADDRESS(a)) +#define davinci_readw(a) __raw_readw(IO_ADDRESS(a)) +#define davinci_readl(a) __raw_readl(IO_ADDRESS(a)) -#define __REG(x) (*((volatile unsigned long *)io_p2v(x))) +#define davinci_writeb(v, a) __raw_writeb(v, IO_ADDRESS(a)) +#define davinci_writew(v, a) __raw_writew(v, IO_ADDRESS(a)) +#define davinci_writel(v, a) __raw_writel(v, IO_ADDRESS(a)) #endif /* __ASSEMBLER__ */ #endif /* __ASM_ARCH_IO_H */ diff --git a/arch/arm/mach-davinci/usb.c b/arch/arm/mach-davinci/usb.c new file mode 100644 index 00000000000..fe182a85159 --- /dev/null +++ b/arch/arm/mach-davinci/usb.c @@ -0,0 +1,116 @@ +/* + * USB + */ +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/platform_device.h> +#include <linux/dma-mapping.h> + +#include <linux/usb/musb.h> +#include <linux/usb/otg.h> + +#include <mach/common.h> +#include <mach/hardware.h> + +#if defined(CONFIG_USB_MUSB_HDRC) || defined(CONFIG_USB_MUSB_HDRC_MODULE) +static struct musb_hdrc_eps_bits musb_eps[] = { + { "ep1_tx", 8, }, + { "ep1_rx", 8, }, + { "ep2_tx", 8, }, + { "ep2_rx", 8, }, + { "ep3_tx", 5, }, + { "ep3_rx", 5, }, + { "ep4_tx", 5, }, + { "ep4_rx", 5, }, +}; + +static struct musb_hdrc_config musb_config = { + .multipoint = true, + .dyn_fifo = true, + .soft_con = true, + .dma = true, + + .num_eps = 5, + .dma_channels = 8, + .ram_bits = 10, + .eps_bits = musb_eps, +}; + +static struct musb_hdrc_platform_data usb_data = { +#if defined(CONFIG_USB_MUSB_OTG) + /* OTG requires a Mini-AB connector */ + .mode = MUSB_OTG, +#elif defined(CONFIG_USB_MUSB_PERIPHERAL) + .mode = MUSB_PERIPHERAL, +#elif defined(CONFIG_USB_MUSB_HOST) + .mode = MUSB_HOST, +#endif + .config = &musb_config, +}; + +static struct resource usb_resources[] = { + { + /* physical address */ + .start = DAVINCI_USB_OTG_BASE, + .end = DAVINCI_USB_OTG_BASE + 0x5ff, + .flags = IORESOURCE_MEM, + }, + { + .start = IRQ_USBINT, + .flags = IORESOURCE_IRQ, + }, +}; + +static u64 usb_dmamask = DMA_32BIT_MASK; + +static struct platform_device usb_dev = { + .name = "musb_hdrc", + .id = -1, + .dev = { + .platform_data = &usb_data, + .dma_mask = &usb_dmamask, + .coherent_dma_mask = DMA_32BIT_MASK, + }, + .resource = usb_resources, + .num_resources = ARRAY_SIZE(usb_resources), +}; + +#ifdef CONFIG_USB_MUSB_OTG + +static struct otg_transceiver *xceiv; + +struct otg_transceiver *otg_get_transceiver(void) +{ + if (xceiv) + get_device(xceiv->dev); + return xceiv; +} +EXPORT_SYMBOL(otg_get_transceiver); + +int otg_set_transceiver(struct otg_transceiver *x) +{ + if (xceiv && x) + return -EBUSY; + xceiv = x; + return 0; +} +EXPORT_SYMBOL(otg_set_transceiver); + +#endif + +void __init setup_usb(unsigned mA, unsigned potpgt_msec) +{ + usb_data.power = mA / 2; + usb_data.potpgt = potpgt_msec / 2; + platform_device_register(&usb_dev); +} + +#else + +void __init setup_usb(unsigned mA, unsigned potpgt_msec) +{ +} + +#endif /* CONFIG_USB_MUSB_HDRC */ + |