diff options
Diffstat (limited to 'arch/arm/mach-ep93xx/core.c')
-rw-r--r-- | arch/arm/mach-ep93xx/core.c | 202 |
1 files changed, 166 insertions, 36 deletions
diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c index 204dc5cbd0b8..16b92c37ec99 100644 --- a/arch/arm/mach-ep93xx/core.c +++ b/arch/arm/mach-ep93xx/core.c | |||
@@ -16,40 +16,24 @@ | |||
16 | 16 | ||
17 | #include <linux/kernel.h> | 17 | #include <linux/kernel.h> |
18 | #include <linux/init.h> | 18 | #include <linux/init.h> |
19 | #include <linux/spinlock.h> | 19 | #include <linux/platform_device.h> |
20 | #include <linux/sched.h> | ||
21 | #include <linux/interrupt.h> | 20 | #include <linux/interrupt.h> |
22 | #include <linux/serial.h> | ||
23 | #include <linux/tty.h> | ||
24 | #include <linux/bitops.h> | ||
25 | #include <linux/serial_8250.h> | ||
26 | #include <linux/serial_core.h> | ||
27 | #include <linux/device.h> | ||
28 | #include <linux/mm.h> | ||
29 | #include <linux/dma-mapping.h> | 21 | #include <linux/dma-mapping.h> |
30 | #include <linux/time.h> | ||
31 | #include <linux/timex.h> | 22 | #include <linux/timex.h> |
32 | #include <linux/delay.h> | 23 | #include <linux/io.h> |
24 | #include <linux/gpio.h> | ||
25 | #include <linux/leds.h> | ||
33 | #include <linux/termios.h> | 26 | #include <linux/termios.h> |
34 | #include <linux/amba/bus.h> | 27 | #include <linux/amba/bus.h> |
35 | #include <linux/amba/serial.h> | 28 | #include <linux/amba/serial.h> |
36 | #include <linux/io.h> | ||
37 | #include <linux/i2c.h> | 29 | #include <linux/i2c.h> |
38 | #include <linux/i2c-gpio.h> | 30 | #include <linux/i2c-gpio.h> |
39 | 31 | ||
40 | #include <asm/types.h> | ||
41 | #include <asm/setup.h> | ||
42 | #include <asm/memory.h> | ||
43 | #include <mach/hardware.h> | 32 | #include <mach/hardware.h> |
44 | #include <asm/irq.h> | ||
45 | #include <asm/system.h> | ||
46 | #include <asm/tlbflush.h> | ||
47 | #include <asm/pgtable.h> | ||
48 | 33 | ||
49 | #include <asm/mach/map.h> | 34 | #include <asm/mach/map.h> |
50 | #include <asm/mach/time.h> | 35 | #include <asm/mach/time.h> |
51 | #include <asm/mach/irq.h> | 36 | #include <asm/mach/irq.h> |
52 | #include <mach/gpio.h> | ||
53 | 37 | ||
54 | #include <asm/hardware/vic.h> | 38 | #include <asm/hardware/vic.h> |
55 | 39 | ||
@@ -98,7 +82,7 @@ void __init ep93xx_map_io(void) | |||
98 | */ | 82 | */ |
99 | static unsigned int last_jiffy_time; | 83 | static unsigned int last_jiffy_time; |
100 | 84 | ||
101 | #define TIMER4_TICKS_PER_JIFFY ((CLOCK_TICK_RATE + (HZ/2)) / HZ) | 85 | #define TIMER4_TICKS_PER_JIFFY DIV_ROUND_CLOSEST(CLOCK_TICK_RATE, HZ) |
102 | 86 | ||
103 | static irqreturn_t ep93xx_timer_interrupt(int irq, void *dev_id) | 87 | static irqreturn_t ep93xx_timer_interrupt(int irq, void *dev_id) |
104 | { | 88 | { |
@@ -362,8 +346,8 @@ void __init ep93xx_init_irq(void) | |||
362 | { | 346 | { |
363 | int gpio_irq; | 347 | int gpio_irq; |
364 | 348 | ||
365 | vic_init((void *)EP93XX_VIC1_BASE, 0, EP93XX_VIC1_VALID_IRQ_MASK, 0); | 349 | vic_init(EP93XX_VIC1_BASE, 0, EP93XX_VIC1_VALID_IRQ_MASK, 0); |
366 | vic_init((void *)EP93XX_VIC2_BASE, 32, EP93XX_VIC2_VALID_IRQ_MASK, 0); | 350 | vic_init(EP93XX_VIC2_BASE, 32, EP93XX_VIC2_VALID_IRQ_MASK, 0); |
367 | 351 | ||
368 | for (gpio_irq = gpio_to_irq(0); | 352 | for (gpio_irq = gpio_to_irq(0); |
369 | gpio_irq <= gpio_to_irq(EP93XX_GPIO_LINE_MAX_IRQ); ++gpio_irq) { | 353 | gpio_irq <= gpio_to_irq(EP93XX_GPIO_LINE_MAX_IRQ); ++gpio_irq) { |
@@ -385,6 +369,47 @@ void __init ep93xx_init_irq(void) | |||
385 | 369 | ||
386 | 370 | ||
387 | /************************************************************************* | 371 | /************************************************************************* |
372 | * EP93xx System Controller Software Locked register handling | ||
373 | *************************************************************************/ | ||
374 | |||
375 | /* | ||
376 | * syscon_swlock prevents anything else from writing to the syscon | ||
377 | * block while a software locked register is being written. | ||
378 | */ | ||
379 | static DEFINE_SPINLOCK(syscon_swlock); | ||
380 | |||
381 | void ep93xx_syscon_swlocked_write(unsigned int val, void __iomem *reg) | ||
382 | { | ||
383 | unsigned long flags; | ||
384 | |||
385 | spin_lock_irqsave(&syscon_swlock, flags); | ||
386 | |||
387 | __raw_writel(0xaa, EP93XX_SYSCON_SWLOCK); | ||
388 | __raw_writel(val, reg); | ||
389 | |||
390 | spin_unlock_irqrestore(&syscon_swlock, flags); | ||
391 | } | ||
392 | EXPORT_SYMBOL(ep93xx_syscon_swlocked_write); | ||
393 | |||
394 | void ep93xx_devcfg_set_clear(unsigned int set_bits, unsigned int clear_bits) | ||
395 | { | ||
396 | unsigned long flags; | ||
397 | unsigned int val; | ||
398 | |||
399 | spin_lock_irqsave(&syscon_swlock, flags); | ||
400 | |||
401 | val = __raw_readl(EP93XX_SYSCON_DEVCFG); | ||
402 | val |= set_bits; | ||
403 | val &= ~clear_bits; | ||
404 | __raw_writel(0xaa, EP93XX_SYSCON_SWLOCK); | ||
405 | __raw_writel(val, EP93XX_SYSCON_DEVCFG); | ||
406 | |||
407 | spin_unlock_irqrestore(&syscon_swlock, flags); | ||
408 | } | ||
409 | EXPORT_SYMBOL(ep93xx_devcfg_set_clear); | ||
410 | |||
411 | |||
412 | /************************************************************************* | ||
388 | * EP93xx peripheral handling | 413 | * EP93xx peripheral handling |
389 | *************************************************************************/ | 414 | *************************************************************************/ |
390 | #define EP93XX_UART_MCR_OFFSET (0x0100) | 415 | #define EP93XX_UART_MCR_OFFSET (0x0100) |
@@ -517,10 +542,8 @@ static struct platform_device ep93xx_eth_device = { | |||
517 | 542 | ||
518 | void __init ep93xx_register_eth(struct ep93xx_eth_data *data, int copy_addr) | 543 | void __init ep93xx_register_eth(struct ep93xx_eth_data *data, int copy_addr) |
519 | { | 544 | { |
520 | if (copy_addr) { | 545 | if (copy_addr) |
521 | memcpy(data->dev_addr, | 546 | memcpy_fromio(data->dev_addr, EP93XX_ETHERNET_BASE + 0x50, 6); |
522 | (void *)(EP93XX_ETHERNET_BASE + 0x50), 6); | ||
523 | } | ||
524 | 547 | ||
525 | ep93xx_eth_data = *data; | 548 | ep93xx_eth_data = *data; |
526 | platform_device_register(&ep93xx_eth_device); | 549 | platform_device_register(&ep93xx_eth_device); |
@@ -546,19 +569,125 @@ void __init ep93xx_register_i2c(struct i2c_board_info *devices, int num) | |||
546 | platform_device_register(&ep93xx_i2c_device); | 569 | platform_device_register(&ep93xx_i2c_device); |
547 | } | 570 | } |
548 | 571 | ||
572 | |||
573 | /************************************************************************* | ||
574 | * EP93xx LEDs | ||
575 | *************************************************************************/ | ||
576 | static struct gpio_led ep93xx_led_pins[] = { | ||
577 | { | ||
578 | .name = "platform:grled", | ||
579 | .gpio = EP93XX_GPIO_LINE_GRLED, | ||
580 | }, { | ||
581 | .name = "platform:rdled", | ||
582 | .gpio = EP93XX_GPIO_LINE_RDLED, | ||
583 | }, | ||
584 | }; | ||
585 | |||
586 | static struct gpio_led_platform_data ep93xx_led_data = { | ||
587 | .num_leds = ARRAY_SIZE(ep93xx_led_pins), | ||
588 | .leds = ep93xx_led_pins, | ||
589 | }; | ||
590 | |||
591 | static struct platform_device ep93xx_leds = { | ||
592 | .name = "leds-gpio", | ||
593 | .id = -1, | ||
594 | .dev = { | ||
595 | .platform_data = &ep93xx_led_data, | ||
596 | }, | ||
597 | }; | ||
598 | |||
599 | |||
600 | /************************************************************************* | ||
601 | * EP93xx pwm peripheral handling | ||
602 | *************************************************************************/ | ||
603 | static struct resource ep93xx_pwm0_resource[] = { | ||
604 | { | ||
605 | .start = EP93XX_PWM_PHYS_BASE, | ||
606 | .end = EP93XX_PWM_PHYS_BASE + 0x10 - 1, | ||
607 | .flags = IORESOURCE_MEM, | ||
608 | }, | ||
609 | }; | ||
610 | |||
611 | static struct platform_device ep93xx_pwm0_device = { | ||
612 | .name = "ep93xx-pwm", | ||
613 | .id = 0, | ||
614 | .num_resources = ARRAY_SIZE(ep93xx_pwm0_resource), | ||
615 | .resource = ep93xx_pwm0_resource, | ||
616 | }; | ||
617 | |||
618 | static struct resource ep93xx_pwm1_resource[] = { | ||
619 | { | ||
620 | .start = EP93XX_PWM_PHYS_BASE + 0x20, | ||
621 | .end = EP93XX_PWM_PHYS_BASE + 0x30 - 1, | ||
622 | .flags = IORESOURCE_MEM, | ||
623 | }, | ||
624 | }; | ||
625 | |||
626 | static struct platform_device ep93xx_pwm1_device = { | ||
627 | .name = "ep93xx-pwm", | ||
628 | .id = 1, | ||
629 | .num_resources = ARRAY_SIZE(ep93xx_pwm1_resource), | ||
630 | .resource = ep93xx_pwm1_resource, | ||
631 | }; | ||
632 | |||
633 | void __init ep93xx_register_pwm(int pwm0, int pwm1) | ||
634 | { | ||
635 | if (pwm0) | ||
636 | platform_device_register(&ep93xx_pwm0_device); | ||
637 | |||
638 | /* NOTE: EP9307 does not have PWMOUT1 (pin EGPIO14) */ | ||
639 | if (pwm1) | ||
640 | platform_device_register(&ep93xx_pwm1_device); | ||
641 | } | ||
642 | |||
643 | int ep93xx_pwm_acquire_gpio(struct platform_device *pdev) | ||
644 | { | ||
645 | int err; | ||
646 | |||
647 | if (pdev->id == 0) { | ||
648 | err = 0; | ||
649 | } else if (pdev->id == 1) { | ||
650 | err = gpio_request(EP93XX_GPIO_LINE_EGPIO14, | ||
651 | dev_name(&pdev->dev)); | ||
652 | if (err) | ||
653 | return err; | ||
654 | err = gpio_direction_output(EP93XX_GPIO_LINE_EGPIO14, 0); | ||
655 | if (err) | ||
656 | goto fail; | ||
657 | |||
658 | /* PWM 1 output on EGPIO[14] */ | ||
659 | ep93xx_devcfg_set_bits(EP93XX_SYSCON_DEVCFG_PONG); | ||
660 | } else { | ||
661 | err = -ENODEV; | ||
662 | } | ||
663 | |||
664 | return err; | ||
665 | |||
666 | fail: | ||
667 | gpio_free(EP93XX_GPIO_LINE_EGPIO14); | ||
668 | return err; | ||
669 | } | ||
670 | EXPORT_SYMBOL(ep93xx_pwm_acquire_gpio); | ||
671 | |||
672 | void ep93xx_pwm_release_gpio(struct platform_device *pdev) | ||
673 | { | ||
674 | if (pdev->id == 1) { | ||
675 | gpio_direction_input(EP93XX_GPIO_LINE_EGPIO14); | ||
676 | gpio_free(EP93XX_GPIO_LINE_EGPIO14); | ||
677 | |||
678 | /* EGPIO[14] used for GPIO */ | ||
679 | ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_PONG); | ||
680 | } | ||
681 | } | ||
682 | EXPORT_SYMBOL(ep93xx_pwm_release_gpio); | ||
683 | |||
684 | |||
549 | extern void ep93xx_gpio_init(void); | 685 | extern void ep93xx_gpio_init(void); |
550 | 686 | ||
551 | void __init ep93xx_init_devices(void) | 687 | void __init ep93xx_init_devices(void) |
552 | { | 688 | { |
553 | unsigned int v; | 689 | /* Disallow access to MaverickCrunch initially */ |
554 | 690 | ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_CPENA); | |
555 | /* | ||
556 | * Disallow access to MaverickCrunch initially. | ||
557 | */ | ||
558 | v = __raw_readl(EP93XX_SYSCON_DEVICE_CONFIG); | ||
559 | v &= ~EP93XX_SYSCON_DEVICE_CONFIG_CRUNCH_ENABLE; | ||
560 | __raw_writel(0xaa, EP93XX_SYSCON_SWLOCK); | ||
561 | __raw_writel(v, EP93XX_SYSCON_DEVICE_CONFIG); | ||
562 | 691 | ||
563 | ep93xx_gpio_init(); | 692 | ep93xx_gpio_init(); |
564 | 693 | ||
@@ -568,4 +697,5 @@ void __init ep93xx_init_devices(void) | |||
568 | 697 | ||
569 | platform_device_register(&ep93xx_rtc_device); | 698 | platform_device_register(&ep93xx_rtc_device); |
570 | platform_device_register(&ep93xx_ohci_device); | 699 | platform_device_register(&ep93xx_ohci_device); |
700 | platform_device_register(&ep93xx_leds); | ||
571 | } | 701 | } |