diff options
Diffstat (limited to 'arch/arm/mach-ixp4xx/common.c')
-rw-r--r-- | arch/arm/mach-ixp4xx/common.c | 77 |
1 files changed, 69 insertions, 8 deletions
diff --git a/arch/arm/mach-ixp4xx/common.c b/arch/arm/mach-ixp4xx/common.c index 6d68aed6548a..fc4b7b24265e 100644 --- a/arch/arm/mach-ixp4xx/common.c +++ b/arch/arm/mach-ixp4xx/common.c | |||
@@ -23,15 +23,14 @@ | |||
23 | #include <linux/interrupt.h> | 23 | #include <linux/interrupt.h> |
24 | #include <linux/bitops.h> | 24 | #include <linux/bitops.h> |
25 | #include <linux/time.h> | 25 | #include <linux/time.h> |
26 | #include <linux/timex.h> | ||
27 | #include <linux/clocksource.h> | 26 | #include <linux/clocksource.h> |
28 | #include <linux/clockchips.h> | 27 | #include <linux/clockchips.h> |
29 | #include <linux/io.h> | 28 | #include <linux/io.h> |
30 | #include <linux/export.h> | 29 | #include <linux/export.h> |
31 | #include <linux/gpio.h> | 30 | #include <linux/gpio.h> |
32 | #include <linux/cpu.h> | 31 | #include <linux/cpu.h> |
32 | #include <linux/pci.h> | ||
33 | #include <linux/sched_clock.h> | 33 | #include <linux/sched_clock.h> |
34 | |||
35 | #include <mach/udc.h> | 34 | #include <mach/udc.h> |
36 | #include <mach/hardware.h> | 35 | #include <mach/hardware.h> |
37 | #include <mach/io.h> | 36 | #include <mach/io.h> |
@@ -40,11 +39,21 @@ | |||
40 | #include <asm/page.h> | 39 | #include <asm/page.h> |
41 | #include <asm/irq.h> | 40 | #include <asm/irq.h> |
42 | #include <asm/system_misc.h> | 41 | #include <asm/system_misc.h> |
43 | |||
44 | #include <asm/mach/map.h> | 42 | #include <asm/mach/map.h> |
45 | #include <asm/mach/irq.h> | 43 | #include <asm/mach/irq.h> |
46 | #include <asm/mach/time.h> | 44 | #include <asm/mach/time.h> |
47 | 45 | ||
46 | #define IXP4XX_TIMER_FREQ 66666000 | ||
47 | |||
48 | /* | ||
49 | * The timer register doesn't allow to specify the two least significant bits of | ||
50 | * the timeout value and assumes them being zero. So make sure IXP4XX_LATCH is | ||
51 | * the best value with the two least significant bits unset. | ||
52 | */ | ||
53 | #define IXP4XX_LATCH DIV_ROUND_CLOSEST(IXP4XX_TIMER_FREQ, \ | ||
54 | (IXP4XX_OST_RELOAD_MASK + 1) * HZ) * \ | ||
55 | (IXP4XX_OST_RELOAD_MASK + 1) | ||
56 | |||
48 | static void __init ixp4xx_clocksource_init(void); | 57 | static void __init ixp4xx_clocksource_init(void); |
49 | static void __init ixp4xx_clockevent_init(void); | 58 | static void __init ixp4xx_clockevent_init(void); |
50 | static struct clock_event_device clockevent_ixp4xx; | 59 | static struct clock_event_device clockevent_ixp4xx; |
@@ -312,7 +321,7 @@ static irqreturn_t ixp4xx_timer_interrupt(int irq, void *dev_id) | |||
312 | 321 | ||
313 | static struct irqaction ixp4xx_timer_irq = { | 322 | static struct irqaction ixp4xx_timer_irq = { |
314 | .name = "timer1", | 323 | .name = "timer1", |
315 | .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, | 324 | .flags = IRQF_TIMER | IRQF_IRQPOLL, |
316 | .handler = ixp4xx_timer_interrupt, | 325 | .handler = ixp4xx_timer_interrupt, |
317 | .dev_id = &clockevent_ixp4xx, | 326 | .dev_id = &clockevent_ixp4xx, |
318 | }; | 327 | }; |
@@ -520,7 +529,7 @@ static void ixp4xx_set_mode(enum clock_event_mode mode, | |||
520 | 529 | ||
521 | switch (mode) { | 530 | switch (mode) { |
522 | case CLOCK_EVT_MODE_PERIODIC: | 531 | case CLOCK_EVT_MODE_PERIODIC: |
523 | osrt = LATCH & ~IXP4XX_OST_RELOAD_MASK; | 532 | osrt = IXP4XX_LATCH & ~IXP4XX_OST_RELOAD_MASK; |
524 | opts = IXP4XX_OST_ENABLE; | 533 | opts = IXP4XX_OST_ENABLE; |
525 | break; | 534 | break; |
526 | case CLOCK_EVT_MODE_ONESHOT: | 535 | case CLOCK_EVT_MODE_ONESHOT: |
@@ -578,6 +587,54 @@ void ixp4xx_restart(enum reboot_mode mode, const char *cmd) | |||
578 | } | 587 | } |
579 | } | 588 | } |
580 | 589 | ||
590 | #ifdef CONFIG_PCI | ||
591 | static int ixp4xx_needs_bounce(struct device *dev, dma_addr_t dma_addr, size_t size) | ||
592 | { | ||
593 | return (dma_addr + size) > SZ_64M; | ||
594 | } | ||
595 | |||
596 | static int ixp4xx_platform_notify_remove(struct device *dev) | ||
597 | { | ||
598 | if (dev_is_pci(dev)) | ||
599 | dmabounce_unregister_dev(dev); | ||
600 | |||
601 | return 0; | ||
602 | } | ||
603 | #endif | ||
604 | |||
605 | /* | ||
606 | * Setup DMA mask to 64MB on PCI devices and 4 GB on all other things. | ||
607 | */ | ||
608 | static int ixp4xx_platform_notify(struct device *dev) | ||
609 | { | ||
610 | dev->dma_mask = &dev->coherent_dma_mask; | ||
611 | |||
612 | #ifdef CONFIG_PCI | ||
613 | if (dev_is_pci(dev)) { | ||
614 | dev->coherent_dma_mask = DMA_BIT_MASK(28); /* 64 MB */ | ||
615 | dmabounce_register_dev(dev, 2048, 4096, ixp4xx_needs_bounce); | ||
616 | return 0; | ||
617 | } | ||
618 | #endif | ||
619 | |||
620 | dev->coherent_dma_mask = DMA_BIT_MASK(32); | ||
621 | return 0; | ||
622 | } | ||
623 | |||
624 | int dma_set_coherent_mask(struct device *dev, u64 mask) | ||
625 | { | ||
626 | if (dev_is_pci(dev)) | ||
627 | mask &= DMA_BIT_MASK(28); /* 64 MB */ | ||
628 | |||
629 | if ((mask & DMA_BIT_MASK(28)) == DMA_BIT_MASK(28)) { | ||
630 | dev->coherent_dma_mask = mask; | ||
631 | return 0; | ||
632 | } | ||
633 | |||
634 | return -EIO; /* device wanted sub-64MB mask */ | ||
635 | } | ||
636 | EXPORT_SYMBOL(dma_set_coherent_mask); | ||
637 | |||
581 | #ifdef CONFIG_IXP4XX_INDIRECT_PCI | 638 | #ifdef CONFIG_IXP4XX_INDIRECT_PCI |
582 | /* | 639 | /* |
583 | * In the case of using indirect PCI, we simply return the actual PCI | 640 | * In the case of using indirect PCI, we simply return the actual PCI |
@@ -600,12 +657,16 @@ static void ixp4xx_iounmap(void __iomem *addr) | |||
600 | if (!is_pci_memory((__force u32)addr)) | 657 | if (!is_pci_memory((__force u32)addr)) |
601 | __iounmap(addr); | 658 | __iounmap(addr); |
602 | } | 659 | } |
660 | #endif | ||
603 | 661 | ||
604 | void __init ixp4xx_init_early(void) | 662 | void __init ixp4xx_init_early(void) |
605 | { | 663 | { |
664 | platform_notify = ixp4xx_platform_notify; | ||
665 | #ifdef CONFIG_PCI | ||
666 | platform_notify_remove = ixp4xx_platform_notify_remove; | ||
667 | #endif | ||
668 | #ifdef CONFIG_IXP4XX_INDIRECT_PCI | ||
606 | arch_ioremap_caller = ixp4xx_ioremap_caller; | 669 | arch_ioremap_caller = ixp4xx_ioremap_caller; |
607 | arch_iounmap = ixp4xx_iounmap; | 670 | arch_iounmap = ixp4xx_iounmap; |
608 | } | ||
609 | #else | ||
610 | void __init ixp4xx_init_early(void) {} | ||
611 | #endif | 671 | #endif |
672 | } | ||