aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-ixp4xx/common.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-ixp4xx/common.c')
-rw-r--r--arch/arm/mach-ixp4xx/common.c77
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
48static void __init ixp4xx_clocksource_init(void); 57static void __init ixp4xx_clocksource_init(void);
49static void __init ixp4xx_clockevent_init(void); 58static void __init ixp4xx_clockevent_init(void);
50static struct clock_event_device clockevent_ixp4xx; 59static struct clock_event_device clockevent_ixp4xx;
@@ -312,7 +321,7 @@ static irqreturn_t ixp4xx_timer_interrupt(int irq, void *dev_id)
312 321
313static struct irqaction ixp4xx_timer_irq = { 322static 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
591static 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
596static 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 */
608static 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
624int 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}
636EXPORT_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
604void __init ixp4xx_init_early(void) 662void __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
610void __init ixp4xx_init_early(void) {}
611#endif 671#endif
672}