diff options
Diffstat (limited to 'arch/arm/mach-ep93xx/core.c')
| -rw-r--r-- | arch/arm/mach-ep93xx/core.c | 414 |
1 files changed, 292 insertions, 122 deletions
diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c index 8d258958871..0e571f1749d 100644 --- a/arch/arm/mach-ep93xx/core.c +++ b/arch/arm/mach-ep93xx/core.c @@ -21,6 +21,7 @@ #include <linux/platform_device.h> #include <linux/interrupt.h> #include <linux/dma-mapping.h> +#include <linux/sys_soc.h> #include <linux/timex.h> #include <linux/irq.h> #include <linux/io.h> @@ -34,18 +35,20 @@ #include <linux/i2c-gpio.h> #include <linux/spi/spi.h> #include <linux/export.h> +#include <linux/irqchip/arm-vic.h> +#include <linux/reboot.h> +#include <linux/usb/ohci_pdriver.h> #include <mach/hardware.h> -#include <mach/fb.h> -#include <mach/ep93xx_keypad.h> -#include <mach/ep93xx_spi.h> +#include <linux/platform_data/video-ep93xx.h> +#include <linux/platform_data/keypad-ep93xx.h> +#include <linux/platform_data/spi-ep93xx.h> #include <mach/gpio-ep93xx.h> +#include <asm/mach/arch.h> #include <asm/mach/map.h> #include <asm/mach/time.h> -#include <asm/hardware/vic.h> - #include "soc.h" /************************************************************************* @@ -114,7 +117,7 @@ void __init ep93xx_map_io(void) #define EP93XX_TIMER4_CLOCK 983040 #define TIMER1_RELOAD ((EP93XX_TIMER123_CLOCK / HZ) - 1) -#define TIMER4_TICKS_PER_JIFFY DIV_ROUND_CLOSEST(CLOCK_TICK_RATE, HZ) +#define TIMER4_TICKS_PER_JIFFY DIV_ROUND_CLOSEST(EP93XX_TIMER4_CLOCK, HZ) static unsigned int last_jiffy_time; @@ -136,15 +139,33 @@ static irqreturn_t ep93xx_timer_interrupt(int irq, void *dev_id) static struct irqaction ep93xx_timer_irq = { .name = "ep93xx timer", - .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, + .flags = IRQF_TIMER | IRQF_IRQPOLL, .handler = ep93xx_timer_interrupt, }; -static void __init ep93xx_timer_init(void) +static u32 ep93xx_gettimeoffset(void) +{ + int offset; + + offset = __raw_readl(EP93XX_TIMER4_VALUE_LOW) - last_jiffy_time; + + /* + * Timer 4 is based on a 983.04 kHz reference clock, + * so dividing by 983040 gives the fraction of a second, + * so dividing by 0.983040 converts to uS. + * Refactor the calculation to avoid overflow. + * Finally, multiply by 1000 to give nS. + */ + return (offset + (53 * offset / 3072)) * 1000; +} + +void __init ep93xx_timer_init(void) { u32 tmode = EP93XX_TIMER123_CONTROL_MODE | EP93XX_TIMER123_CONTROL_CLKSEL; + arch_gettimeoffset = ep93xx_gettimeoffset; + /* Enable periodic HZ timer. */ __raw_writel(tmode, EP93XX_TIMER1_CONTROL); __raw_writel(TIMER1_RELOAD, EP93XX_TIMER1_LOAD); @@ -158,21 +179,6 @@ static void __init ep93xx_timer_init(void) setup_irq(IRQ_EP93XX_TIMER1, &ep93xx_timer_irq); } -static unsigned long ep93xx_gettimeoffset(void) -{ - int offset; - - offset = __raw_readl(EP93XX_TIMER4_VALUE_LOW) - last_jiffy_time; - - /* Calculate (1000000 / 983040) * offset. */ - return offset + (53 * offset / 3072); -} - -struct sys_timer ep93xx_timer = { - .init = ep93xx_timer_init, - .offset = ep93xx_gettimeoffset, -}; - /************************************************************************* * EP93xx IRQ handling @@ -236,16 +242,13 @@ unsigned int ep93xx_chip_revision(void) v >>= EP93XX_SYSCON_SYSCFG_REV_SHIFT; return v; } +EXPORT_SYMBOL_GPL(ep93xx_chip_revision); /************************************************************************* * EP93xx GPIO *************************************************************************/ static struct resource ep93xx_gpio_resource[] = { - { - .start = EP93XX_GPIO_PHYS_BASE, - .end = EP93XX_GPIO_PHYS_BASE + 0xcc - 1, - .flags = IORESOURCE_MEM, - }, + DEFINE_RES_MEM(EP93XX_GPIO_PHYS_BASE, 0xcc), }; static struct platform_device ep93xx_gpio_device = { @@ -282,17 +285,13 @@ static AMBA_APB_DEVICE(uart1, "apb:uart1", 0x00041010, EP93XX_UART1_PHYS_BASE, { IRQ_EP93XX_UART1 }, &ep93xx_uart_data); static AMBA_APB_DEVICE(uart2, "apb:uart2", 0x00041010, EP93XX_UART2_PHYS_BASE, - { IRQ_EP93XX_UART2 }, &ep93xx_uart_data); + { IRQ_EP93XX_UART2 }, NULL); static AMBA_APB_DEVICE(uart3, "apb:uart3", 0x00041010, EP93XX_UART3_PHYS_BASE, { IRQ_EP93XX_UART3 }, &ep93xx_uart_data); static struct resource ep93xx_rtc_resource[] = { - { - .start = EP93XX_RTC_PHYS_BASE, - .end = EP93XX_RTC_PHYS_BASE + 0x10c - 1, - .flags = IORESOURCE_MEM, - }, + DEFINE_RES_MEM(EP93XX_RTC_PHYS_BASE, 0x10c), }; static struct platform_device ep93xx_rtc_device = { @@ -302,33 +301,53 @@ static struct platform_device ep93xx_rtc_device = { .resource = ep93xx_rtc_resource, }; +/************************************************************************* + * EP93xx OHCI USB Host + *************************************************************************/ + +static struct clk *ep93xx_ohci_host_clock; + +static int ep93xx_ohci_power_on(struct platform_device *pdev) +{ + if (!ep93xx_ohci_host_clock) { + ep93xx_ohci_host_clock = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(ep93xx_ohci_host_clock)) + return PTR_ERR(ep93xx_ohci_host_clock); + } + + return clk_enable(ep93xx_ohci_host_clock); +} + +static void ep93xx_ohci_power_off(struct platform_device *pdev) +{ + clk_disable(ep93xx_ohci_host_clock); +} + +static struct usb_ohci_pdata ep93xx_ohci_pdata = { + .power_on = ep93xx_ohci_power_on, + .power_off = ep93xx_ohci_power_off, + .power_suspend = ep93xx_ohci_power_off, +}; static struct resource ep93xx_ohci_resources[] = { - [0] = { - .start = EP93XX_USB_PHYS_BASE, - .end = EP93XX_USB_PHYS_BASE + 0x0fff, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = IRQ_EP93XX_USB, - .end = IRQ_EP93XX_USB, - .flags = IORESOURCE_IRQ, - }, + DEFINE_RES_MEM(EP93XX_USB_PHYS_BASE, 0x1000), + DEFINE_RES_IRQ(IRQ_EP93XX_USB), }; +static u64 ep93xx_ohci_dma_mask = DMA_BIT_MASK(32); static struct platform_device ep93xx_ohci_device = { - .name = "ep93xx-ohci", + .name = "ohci-platform", .id = -1, + .num_resources = ARRAY_SIZE(ep93xx_ohci_resources), + .resource = ep93xx_ohci_resources, .dev = { - .dma_mask = &ep93xx_ohci_device.dev.coherent_dma_mask, + .dma_mask = &ep93xx_ohci_dma_mask, .coherent_dma_mask = DMA_BIT_MASK(32), + .platform_data = &ep93xx_ohci_pdata, }, - .num_resources = ARRAY_SIZE(ep93xx_ohci_resources), - .resource = ep93xx_ohci_resources, }; - /************************************************************************* * EP93xx physmap'ed flash *************************************************************************/ @@ -372,15 +391,8 @@ void __init ep93xx_register_flash(unsigned int width, static struct ep93xx_eth_data ep93xx_eth_data; static struct resource ep93xx_eth_resource[] = { - { - .start = EP93XX_ETHERNET_PHYS_BASE, - .end = EP93XX_ETHERNET_PHYS_BASE + 0xffff, - .flags = IORESOURCE_MEM, - }, { - .start = IRQ_EP93XX_ETHERNET, - .end = IRQ_EP93XX_ETHERNET, - .flags = IORESOURCE_IRQ, - } + DEFINE_RES_MEM(EP93XX_ETHERNET_PHYS_BASE, 0x10000), + DEFINE_RES_IRQ(IRQ_EP93XX_ETHERNET), }; static u64 ep93xx_eth_dma_mask = DMA_BIT_MASK(32); @@ -461,16 +473,8 @@ void __init ep93xx_register_i2c(struct i2c_gpio_platform_data *data, static struct ep93xx_spi_info ep93xx_spi_master_data; static struct resource ep93xx_spi_resources[] = { - { - .start = EP93XX_SPI_PHYS_BASE, - .end = EP93XX_SPI_PHYS_BASE + 0x18 - 1, - .flags = IORESOURCE_MEM, - }, - { - .start = IRQ_EP93XX_SSP, - .end = IRQ_EP93XX_SSP, - .flags = IORESOURCE_IRQ, - }, + DEFINE_RES_MEM(EP93XX_SPI_PHYS_BASE, 0x18), + DEFINE_RES_IRQ(IRQ_EP93XX_SSP), }; static u64 ep93xx_spi_dma_mask = DMA_BIT_MASK(32); @@ -513,7 +517,7 @@ void __init ep93xx_register_spi(struct ep93xx_spi_info *info, /************************************************************************* * EP93xx LEDs *************************************************************************/ -static struct gpio_led ep93xx_led_pins[] = { +static const struct gpio_led ep93xx_led_pins[] __initconst = { { .name = "platform:grled", .gpio = EP93XX_GPIO_LINE_GRLED, @@ -523,29 +527,16 @@ static struct gpio_led ep93xx_led_pins[] = { }, }; -static struct gpio_led_platform_data ep93xx_led_data = { +static const struct gpio_led_platform_data ep93xx_led_data __initconst = { .num_leds = ARRAY_SIZE(ep93xx_led_pins), .leds = ep93xx_led_pins, }; -static struct platform_device ep93xx_leds = { - .name = "leds-gpio", - .id = -1, - .dev = { - .platform_data = &ep93xx_led_data, - }, -}; - - /************************************************************************* * EP93xx pwm peripheral handling *************************************************************************/ static struct resource ep93xx_pwm0_resource[] = { - { - .start = EP93XX_PWM_PHYS_BASE, - .end = EP93XX_PWM_PHYS_BASE + 0x10 - 1, - .flags = IORESOURCE_MEM, - }, + DEFINE_RES_MEM(EP93XX_PWM_PHYS_BASE, 0x10), }; static struct platform_device ep93xx_pwm0_device = { @@ -556,11 +547,7 @@ static struct platform_device ep93xx_pwm0_device = { }; static struct resource ep93xx_pwm1_resource[] = { - { - .start = EP93XX_PWM_PHYS_BASE + 0x20, - .end = EP93XX_PWM_PHYS_BASE + 0x30 - 1, - .flags = IORESOURCE_MEM, - }, + DEFINE_RES_MEM(EP93XX_PWM_PHYS_BASE + 0x20, 0x10), }; static struct platform_device ep93xx_pwm1_device = { @@ -628,11 +615,7 @@ EXPORT_SYMBOL(ep93xx_pwm_release_gpio); static struct ep93xxfb_mach_info ep93xxfb_data; static struct resource ep93xx_fb_resource[] = { - { - .start = EP93XX_RASTER_PHYS_BASE, - .end = EP93XX_RASTER_PHYS_BASE + 0x800 - 1, - .flags = IORESOURCE_MEM, - }, + DEFINE_RES_MEM(EP93XX_RASTER_PHYS_BASE, 0x800), }; static struct platform_device ep93xx_fb_device = { @@ -680,15 +663,8 @@ void __init ep93xx_register_fb(struct ep93xxfb_mach_info *data) static struct ep93xx_keypad_platform_data ep93xx_keypad_data; static struct resource ep93xx_keypad_resource[] = { - { - .start = EP93XX_KEY_MATRIX_PHYS_BASE, - .end = EP93XX_KEY_MATRIX_PHYS_BASE + 0x0c - 1, - .flags = IORESOURCE_MEM, - }, { - .start = IRQ_EP93XX_KEY, - .end = IRQ_EP93XX_KEY, - .flags = IORESOURCE_IRQ, - }, + DEFINE_RES_MEM(EP93XX_KEY_MATRIX_PHYS_BASE, 0x0c), + DEFINE_RES_IRQ(IRQ_EP93XX_KEY), }; static struct platform_device ep93xx_keypad_device = { @@ -734,7 +710,7 @@ int ep93xx_keypad_acquire_gpio(struct platform_device *pdev) fail_gpio_d: gpio_free(EP93XX_GPIO_LINE_C(i)); fail_gpio_c: - for ( ; i >= 0; --i) { + for (--i; i >= 0; --i) { gpio_free(EP93XX_GPIO_LINE_C(i)); gpio_free(EP93XX_GPIO_LINE_D(i)); } @@ -761,11 +737,7 @@ EXPORT_SYMBOL(ep93xx_keypad_release_gpio); * EP93xx I2S audio peripheral handling *************************************************************************/ static struct resource ep93xx_i2s_resource[] = { - { - .start = EP93XX_I2S_PHYS_BASE, - .end = EP93XX_I2S_PHYS_BASE + 0x100 - 1, - .flags = IORESOURCE_MEM, - }, + DEFINE_RES_MEM(EP93XX_I2S_PHYS_BASE, 0x100), }; static struct platform_device ep93xx_i2s_device = { @@ -824,16 +796,8 @@ EXPORT_SYMBOL(ep93xx_i2s_release); * EP93xx AC97 audio peripheral handling *************************************************************************/ static struct resource ep93xx_ac97_resources[] = { - { - .start = EP93XX_AAC_PHYS_BASE, - .end = EP93XX_AAC_PHYS_BASE + 0xac - 1, - .flags = IORESOURCE_MEM, - }, - { - .start = IRQ_EP93XX_AACINTR, - .end = IRQ_EP93XX_AACINTR, - .flags = IORESOURCE_IRQ, - }, + DEFINE_RES_MEM(EP93XX_AAC_PHYS_BASE, 0xac), + DEFINE_RES_IRQ(IRQ_EP93XX_AACINTR), }; static struct platform_device ep93xx_ac97_device = { @@ -868,8 +832,204 @@ static struct platform_device ep93xx_wdt_device = { .resource = ep93xx_wdt_resources, }; -void __init ep93xx_init_devices(void) +/************************************************************************* + * EP93xx IDE + *************************************************************************/ +static struct resource ep93xx_ide_resources[] = { + DEFINE_RES_MEM(EP93XX_IDE_PHYS_BASE, 0x38), + DEFINE_RES_IRQ(IRQ_EP93XX_EXT3), +}; + +static struct platform_device ep93xx_ide_device = { + .name = "ep93xx-ide", + .id = -1, + .dev = { + .dma_mask = &ep93xx_ide_device.dev.coherent_dma_mask, + .coherent_dma_mask = DMA_BIT_MASK(32), + }, + .num_resources = ARRAY_SIZE(ep93xx_ide_resources), + .resource = ep93xx_ide_resources, +}; + +void __init ep93xx_register_ide(void) +{ + platform_device_register(&ep93xx_ide_device); +} + +int ep93xx_ide_acquire_gpio(struct platform_device *pdev) +{ + int err; + int i; + + err = gpio_request(EP93XX_GPIO_LINE_EGPIO2, dev_name(&pdev->dev)); + if (err) + return err; + err = gpio_request(EP93XX_GPIO_LINE_EGPIO15, dev_name(&pdev->dev)); + if (err) + goto fail_egpio15; + for (i = 2; i < 8; i++) { + err = gpio_request(EP93XX_GPIO_LINE_E(i), dev_name(&pdev->dev)); + if (err) + goto fail_gpio_e; + } + for (i = 4; i < 8; i++) { + err = gpio_request(EP93XX_GPIO_LINE_G(i), dev_name(&pdev->dev)); + if (err) + goto fail_gpio_g; + } + for (i = 0; i < 8; i++) { + err = gpio_request(EP93XX_GPIO_LINE_H(i), dev_name(&pdev->dev)); + if (err) + goto fail_gpio_h; + } + + /* GPIO ports E[7:2], G[7:4] and H used by IDE */ + ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_EONIDE | + EP93XX_SYSCON_DEVCFG_GONIDE | + EP93XX_SYSCON_DEVCFG_HONIDE); + return 0; + +fail_gpio_h: + for (--i; i >= 0; --i) + gpio_free(EP93XX_GPIO_LINE_H(i)); + i = 8; +fail_gpio_g: + for (--i; i >= 4; --i) + gpio_free(EP93XX_GPIO_LINE_G(i)); + i = 8; +fail_gpio_e: + for (--i; i >= 2; --i) + gpio_free(EP93XX_GPIO_LINE_E(i)); + gpio_free(EP93XX_GPIO_LINE_EGPIO15); +fail_egpio15: + gpio_free(EP93XX_GPIO_LINE_EGPIO2); + return err; +} +EXPORT_SYMBOL(ep93xx_ide_acquire_gpio); + +void ep93xx_ide_release_gpio(struct platform_device *pdev) +{ + int i; + + for (i = 2; i < 8; i++) + gpio_free(EP93XX_GPIO_LINE_E(i)); + for (i = 4; i < 8; i++) + gpio_free(EP93XX_GPIO_LINE_G(i)); + for (i = 0; i < 8; i++) + gpio_free(EP93XX_GPIO_LINE_H(i)); + gpio_free(EP93XX_GPIO_LINE_EGPIO15); + gpio_free(EP93XX_GPIO_LINE_EGPIO2); + + + /* GPIO ports E[7:2], G[7:4] and H used by GPIO */ + ep93xx_devcfg_set_bits(EP93XX_SYSCON_DEVCFG_EONIDE | + EP93XX_SYSCON_DEVCFG_GONIDE | + EP93XX_SYSCON_DEVCFG_HONIDE); +} +EXPORT_SYMBOL(ep93xx_ide_release_gpio); + +/************************************************************************* + * EP93xx Security peripheral + *************************************************************************/ + +/* + * The Maverick Key is 256 bits of micro fuses blown at the factory during + * manufacturing to uniquely identify a part. + * + * See: http://arm.cirrus.com/forum/viewtopic.php?t=486&highlight=maverick+key + */ +#define EP93XX_SECURITY_REG(x) (EP93XX_SECURITY_BASE + (x)) +#define EP93XX_SECURITY_SECFLG EP93XX_SECURITY_REG(0x2400) +#define EP93XX_SECURITY_FUSEFLG EP93XX_SECURITY_REG(0x2410) +#define EP93XX_SECURITY_UNIQID EP93XX_SECURITY_REG(0x2440) +#define EP93XX_SECURITY_UNIQCHK EP93XX_SECURITY_REG(0x2450) +#define EP93XX_SECURITY_UNIQVAL EP93XX_SECURITY_REG(0x2460) +#define EP93XX_SECURITY_SECID1 EP93XX_SECURITY_REG(0x2500) +#define EP93XX_SECURITY_SECID2 EP93XX_SECURITY_REG(0x2504) +#define EP93XX_SECURITY_SECCHK1 EP93XX_SECURITY_REG(0x2520) +#define EP93XX_SECURITY_SECCHK2 EP93XX_SECURITY_REG(0x2524) +#define EP93XX_SECURITY_UNIQID2 EP93XX_SECURITY_REG(0x2700) +#define EP93XX_SECURITY_UNIQID3 EP93XX_SECURITY_REG(0x2704) +#define EP93XX_SECURITY_UNIQID4 EP93XX_SECURITY_REG(0x2708) +#define EP93XX_SECURITY_UNIQID5 EP93XX_SECURITY_REG(0x270c) + +static char ep93xx_soc_id[33]; + +static const char __init *ep93xx_get_soc_id(void) +{ + unsigned int id, id2, id3, id4, id5; + + if (__raw_readl(EP93XX_SECURITY_UNIQVAL) != 1) + return "bad Hamming code"; + + id = __raw_readl(EP93XX_SECURITY_UNIQID); + id2 = __raw_readl(EP93XX_SECURITY_UNIQID2); + id3 = __raw_readl(EP93XX_SECURITY_UNIQID3); + id4 = __raw_readl(EP93XX_SECURITY_UNIQID4); + id5 = __raw_readl(EP93XX_SECURITY_UNIQID5); + + if (id != id2) + return "invalid"; + + snprintf(ep93xx_soc_id, sizeof(ep93xx_soc_id), + "%08x%08x%08x%08x", id2, id3, id4, id5); + + return ep93xx_soc_id; +} + +static const char __init *ep93xx_get_soc_rev(void) +{ + int rev = ep93xx_chip_revision(); + + switch (rev) { + case EP93XX_CHIP_REV_D0: + return "D0"; + case EP93XX_CHIP_REV_D1: + return "D1"; + case EP93XX_CHIP_REV_E0: + return "E0"; + case EP93XX_CHIP_REV_E1: + return "E1"; + case EP93XX_CHIP_REV_E2: + return "E2"; + default: + return "unknown"; + } +} + +static const char __init *ep93xx_get_machine_name(void) +{ + return kasprintf(GFP_KERNEL,"%s", machine_desc->name); +} + +static struct device __init *ep93xx_init_soc(void) +{ + struct soc_device_attribute *soc_dev_attr; + struct soc_device *soc_dev; + + soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL); + if (!soc_dev_attr) + return NULL; + + soc_dev_attr->machine = ep93xx_get_machine_name(); + soc_dev_attr->family = "Cirrus Logic EP93xx"; + soc_dev_attr->revision = ep93xx_get_soc_rev(); + soc_dev_attr->soc_id = ep93xx_get_soc_id(); + + soc_dev = soc_device_register(soc_dev_attr); + if (IS_ERR(soc_dev)) { + kfree(soc_dev_attr->machine); + kfree(soc_dev_attr); + return NULL; + } + + return soc_device_to_device(soc_dev); +} + +struct device __init *ep93xx_init_devices(void) { + struct device *parent; + /* Disallow access to MaverickCrunch initially */ ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_CPENA); @@ -880,6 +1040,8 @@ void __init ep93xx_init_devices(void) EP93XX_SYSCON_DEVCFG_GONIDE | EP93XX_SYSCON_DEVCFG_HONIDE); + parent = ep93xx_init_soc(); + /* Get the GPIO working early, other devices need it */ platform_device_register(&ep93xx_gpio_device); @@ -889,11 +1051,14 @@ void __init ep93xx_init_devices(void) platform_device_register(&ep93xx_rtc_device); platform_device_register(&ep93xx_ohci_device); - platform_device_register(&ep93xx_leds); platform_device_register(&ep93xx_wdt_device); + + gpio_led_register_device(-1, &ep93xx_led_data); + + return parent; } -void ep93xx_restart(char mode, const char *cmd) +void ep93xx_restart(enum reboot_mode mode, const char *cmd) { /* * Set then clear the SWRST bit to initiate a software reset @@ -904,3 +1069,8 @@ void ep93xx_restart(char mode, const char *cmd) while (1) ; } + +void __init ep93xx_init_late(void) +{ + crunch_init(); +} |
