From 914ab06279f15d3f368f4fae74db58fdcf03a2ed Mon Sep 17 00:00:00 2001 From: David Brownell Date: Tue, 23 Jan 2007 20:12:15 -0800 Subject: [AVR32] /proc/interrupts display The /proc/interrupts file should also display the irq_chip associated with each irq ... e.g. INTC, EIM, GPIO. Signed-off-by: David Brownell Signed-off-by: Haavard Skinnemoen --- arch/avr32/kernel/irq.c | 1 + 1 file changed, 1 insertion(+) (limited to 'arch') diff --git a/arch/avr32/kernel/irq.c b/arch/avr32/kernel/irq.c index 856f354..fd31124 100644 --- a/arch/avr32/kernel/irq.c +++ b/arch/avr32/kernel/irq.c @@ -57,6 +57,7 @@ int show_interrupts(struct seq_file *p, void *v) seq_printf(p, "%3d: ", i); for_each_online_cpu(cpu) seq_printf(p, "%10u ", kstat_cpu(cpu).irqs[i]); + seq_printf(p, " %8s", irq_desc[i].chip->name ? : "-"); seq_printf(p, " %s", action->name); for (action = action->next; action; action = action->next) seq_printf(p, ", %s", action->name); -- cgit v1.1 From a3d912c8fa709c4078ceaabf4d71001190e19325 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Tue, 23 Jan 2007 20:14:02 -0800 Subject: [AVR32] fix serial port setup on ATSTK1000 Fixes to USART setup on the stk-1000 ... don't configure USART 2, since its TXD/RXD are used for INT-A and INT-B buttons; and configure USART 0 (for IRDA, and with corrected IRQ) iff SW2 has a non-default setting. Signed-off-by: David Brownell Signed-off-by: Haavard Skinnemoen --- arch/avr32/boards/atstk1000/atstk1002.c | 16 +++++++++++++--- arch/avr32/mach-at32ap/at32ap7000.c | 4 ++-- 2 files changed, 15 insertions(+), 5 deletions(-) (limited to 'arch') diff --git a/arch/avr32/boards/atstk1000/atstk1002.c b/arch/avr32/boards/atstk1000/atstk1002.c index 32b361f..3787d6b 100644 --- a/arch/avr32/boards/atstk1000/atstk1002.c +++ b/arch/avr32/boards/atstk1000/atstk1002.c @@ -20,6 +20,9 @@ #include #include + +#define SW2_DEFAULT /* MMCI and UART_A available */ + struct eth_addr { u8 addr[6]; }; @@ -86,9 +89,13 @@ static void __init set_hw_addr(struct platform_device *pdev) void __init setup_board(void) { - at32_map_usart(1, 0); /* /dev/ttyS0 */ - at32_map_usart(2, 1); /* /dev/ttyS1 */ - at32_map_usart(3, 2); /* /dev/ttyS2 */ +#ifdef SW2_DEFAULT + at32_map_usart(1, 0); /* USART 1/A: /dev/ttyS0, DB9 */ +#else + at32_map_usart(0, 1); /* USART 0/B: /dev/ttyS1, IRDA */ +#endif + /* USART 2/unused: expansion connector */ + at32_map_usart(3, 2); /* USART 3/C: /dev/ttyS2, DB9 */ at32_setup_serial_console(0); } @@ -97,8 +104,11 @@ static int __init atstk1002_init(void) { at32_add_system_devices(); +#ifdef SW2_DEFAULT at32_add_device_usart(0); +#else at32_add_device_usart(1); +#endif at32_add_device_usart(2); set_hw_addr(at32_add_device_eth(0, ð_data[0])); diff --git a/arch/avr32/mach-at32ap/at32ap7000.c b/arch/avr32/mach-at32ap/at32ap7000.c index 48f4ef3..175853a 100644 --- a/arch/avr32/mach-at32ap/at32ap7000.c +++ b/arch/avr32/mach-at32ap/at32ap7000.c @@ -521,7 +521,7 @@ static struct atmel_uart_data atmel_usart0_data = { }; static struct resource atmel_usart0_resource[] = { PBMEM(0xffe00c00), - IRQ(7), + IRQ(6), }; DEFINE_DEV_DATA(atmel_usart, 0); DEV_CLK(usart, atmel_usart0, pba, 4); @@ -583,7 +583,7 @@ static inline void configure_usart3_pins(void) select_peripheral(PB(17), PERIPH_B, 0); /* TXD */ } -static struct platform_device *at32_usarts[4]; +static struct platform_device *__initdata at32_usarts[4]; void __init at32_map_usart(unsigned int hw_id, unsigned int line) { -- cgit v1.1 From 58febc0b1374de7506277d3aa9e9cddaea62ba65 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Tue, 23 Jan 2007 20:21:36 -0800 Subject: [AVR32] ext int fixes Bugfixes for external irq handler set_irq_type(): - If set_irq_type() can't set the type, don't change anything! - It's not OK to change the flow handler as part of set_irq_type(), among other issues that violates spinlock rules. Instead, we can call the relevant handler when we demux the external interrupts. - The external irq demux has no need to grab the spinlock. And in fact grabbing it that way was wrong, since that code might be pre-empted by an irq at a different priority level, and that code might then have tried to grab that spinlock... Signed-off-by: David Brownell Signed-off-by: Haavard Skinnemoen --- arch/avr32/mach-at32ap/extint.c | 36 +++++++++++++++++------------------- 1 file changed, 17 insertions(+), 19 deletions(-) (limited to 'arch') diff --git a/arch/avr32/mach-at32ap/extint.c b/arch/avr32/mach-at32ap/extint.c index b59272e..4a60ecc 100644 --- a/arch/avr32/mach-at32ap/extint.c +++ b/arch/avr32/mach-at32ap/extint.c @@ -55,20 +55,11 @@ static int eim_set_irq_type(unsigned int irq, unsigned int flow_type) unsigned long flags; int ret = 0; + flow_type &= IRQ_TYPE_SENSE_MASK; if (flow_type == IRQ_TYPE_NONE) flow_type = IRQ_TYPE_LEVEL_LOW; desc = &irq_desc[irq]; - desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL); - desc->status |= flow_type & IRQ_TYPE_SENSE_MASK; - - if (flow_type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH)) { - desc->status |= IRQ_LEVEL; - set_irq_handler(irq, handle_level_irq); - } else { - set_irq_handler(irq, handle_edge_irq); - } - spin_lock_irqsave(&sm->lock, flags); mode = sm_readl(sm, EIM_MODE); @@ -97,9 +88,16 @@ static int eim_set_irq_type(unsigned int irq, unsigned int flow_type) break; } - sm_writel(sm, EIM_MODE, mode); - sm_writel(sm, EIM_EDGE, edge); - sm_writel(sm, EIM_LEVEL, level); + if (ret == 0) { + sm_writel(sm, EIM_MODE, mode); + sm_writel(sm, EIM_EDGE, edge); + sm_writel(sm, EIM_LEVEL, level); + + if (flow_type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH)) + flow_type |= IRQ_LEVEL; + desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL); + desc->status |= flow_type; + } spin_unlock_irqrestore(&sm->lock, flags); @@ -122,8 +120,6 @@ static void demux_eim_irq(unsigned int irq, struct irq_desc *desc) unsigned long status, pending; unsigned int i, ext_irq; - spin_lock(&sm->lock); - status = sm_readl(sm, EIM_ISR); pending = status & sm_readl(sm, EIM_IMR); @@ -133,10 +129,11 @@ static void demux_eim_irq(unsigned int irq, struct irq_desc *desc) ext_irq = i + sm->eim_first_irq; ext_desc = irq_desc + ext_irq; - ext_desc->handle_irq(ext_irq, ext_desc); + if (ext_desc->status & IRQ_LEVEL) + handle_level_irq(ext_irq, ext_desc); + else + handle_edge_irq(ext_irq, ext_desc); } - - spin_unlock(&sm->lock); } static int __init eim_init(void) @@ -168,8 +165,9 @@ static int __init eim_init(void) sm->eim_chip = &eim_chip; for (i = 0; i < nr_irqs; i++) { + /* NOTE the handler we set here is ignored by the demux */ set_irq_chip_and_handler(sm->eim_first_irq + i, &eim_chip, - handle_edge_irq); + handle_level_irq); set_irq_chip_data(sm->eim_first_irq + i, sm); } -- cgit v1.1 From 212868d387d0033b7e0029326a900126fe5e3d52 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Sun, 28 Jan 2007 12:56:42 -0800 Subject: [AVR32] Fix incorrect invalidation of shared cachelines Fix bug in dma_map_single(..., DMA_FROM_DEVICE) caused by incorrect invalidation of shared cachelines at the beginning and/or end of the specified buffer. Those shared cachelines need to be flushed, since they may hold valid data (which must not be discarded). Signed-off-by: David Brownell Signed-off-by: Haavard Skinnemoen --- arch/avr32/mm/cache.c | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) (limited to 'arch') diff --git a/arch/avr32/mm/cache.c b/arch/avr32/mm/cache.c index 450515b..fb13f72 100644 --- a/arch/avr32/mm/cache.c +++ b/arch/avr32/mm/cache.c @@ -22,18 +22,34 @@ void invalidate_dcache_region(void *start, size_t size) { - unsigned long v, begin, end, linesz; + unsigned long v, begin, end, linesz, mask; + int flush = 0; linesz = boot_cpu_data.dcache.linesz; + mask = linesz - 1; + + /* when first and/or last cachelines are shared, flush them + * instead of invalidating ... never discard valid data! + */ + begin = (unsigned long)start; + end = begin + size - 1; + + if (begin & mask) { + flush_dcache_line(start); + begin += linesz; + flush = 1; + } + if ((end & mask) != mask) { + flush_dcache_line((void *)end); + end -= linesz; + flush = 1; + } - //printk("invalidate dcache: %p + %u\n", start, size); - - /* You asked for it, you got it */ - begin = (unsigned long)start & ~(linesz - 1); - end = ((unsigned long)start + size + linesz - 1) & ~(linesz - 1); - - for (v = begin; v < end; v += linesz) + /* remaining cachelines only need invalidation */ + for (v = begin; v <= end; v += linesz) invalidate_dcache_line((void *)v); + if (flush) + flush_write_buffer(); } void clean_dcache_region(void *start, size_t size) -- cgit v1.1 From 10b50b7dd2716b944299d45452d0875dbeb5f0c2 Mon Sep 17 00:00:00 2001 From: "Ahmed S. Darwish" Date: Mon, 5 Feb 2007 04:41:27 +0200 Subject: [AVR32] Use ARRAY_SIZE macro when appropriate A patch to use ARRAY_SIZE macro already defined in linux/kernel.h Signed-off-by: Ahmed S. Darwish Signed-off-by: Haavard Skinnemoen --- arch/avr32/kernel/setup.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/avr32/kernel/setup.c b/arch/avr32/kernel/setup.c index a342116..c6734ae 100644 --- a/arch/avr32/kernel/setup.c +++ b/arch/avr32/kernel/setup.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -174,8 +175,7 @@ static int __init parse_tag_mem_range(struct tag *tag, * Copy the data so the bootmem init code doesn't need to care * about it. */ - if (mem_range_next_free >= - (sizeof(mem_range_cache) / sizeof(mem_range_cache[0]))) + if (mem_range_next_free >= ARRAY_SIZE(mem_range_cache)) panic("Physical memory map too complex!\n"); new = &mem_range_cache[mem_range_next_free++]; -- cgit v1.1 From 6a4e5227a33f60f918b30cf2001fb0bb259d9396 Mon Sep 17 00:00:00 2001 From: Haavard Skinnemoen Date: Mon, 5 Feb 2007 16:57:13 +0100 Subject: [AVR32] GPIO API implementation Arch-neutral GPIO calls for AVR32. GPIO IRQ support written by David Brownell. Signed-off-by: Haavard Skinnemoen --- arch/avr32/mach-at32ap/Makefile | 2 +- arch/avr32/mach-at32ap/at32ap7000.c | 2 +- arch/avr32/mach-at32ap/pio.c | 233 +++++++++++++++++++++++++++++++++--- 3 files changed, 221 insertions(+), 16 deletions(-) (limited to 'arch') diff --git a/arch/avr32/mach-at32ap/Makefile b/arch/avr32/mach-at32ap/Makefile index f62eb69..b21bea9 100644 --- a/arch/avr32/mach-at32ap/Makefile +++ b/arch/avr32/mach-at32ap/Makefile @@ -1,2 +1,2 @@ -obj-y += at32ap.o clock.o pio.o intc.o extint.o hsmc.o +obj-y += at32ap.o clock.o intc.o extint.o pio.o hsmc.o obj-$(CONFIG_CPU_AT32AP7000) += at32ap7000.o diff --git a/arch/avr32/mach-at32ap/at32ap7000.c b/arch/avr32/mach-at32ap/at32ap7000.c index 175853a..21561ab 100644 --- a/arch/avr32/mach-at32ap/at32ap7000.c +++ b/arch/avr32/mach-at32ap/at32ap7000.c @@ -498,7 +498,7 @@ DEV_CLK(mck, pio3, pba, 13); void __init at32_add_system_devices(void) { - system_manager.eim_first_irq = NR_INTERNAL_IRQS; + system_manager.eim_first_irq = EIM_IRQ_BASE; platform_device_register(&at32_sm_device); platform_device_register(&at32_intc0_device); diff --git a/arch/avr32/mach-at32ap/pio.c b/arch/avr32/mach-at32ap/pio.c index f1280ed..17e835d 100644 --- a/arch/avr32/mach-at32ap/pio.c +++ b/arch/avr32/mach-at32ap/pio.c @@ -12,7 +12,9 @@ #include #include #include +#include +#include #include #include @@ -26,7 +28,8 @@ struct pio_device { const struct platform_device *pdev; struct clk *clk; u32 pinmux_mask; - char name[32]; + u32 gpio_mask; + char name[8]; }; static struct pio_device pio_dev[MAX_NR_PIO_DEVICES]; @@ -76,6 +79,9 @@ void __init at32_select_periph(unsigned int pin, unsigned int periph, if (!(flags & AT32_GPIOF_PULLUP)) pio_writel(pio, PUDR, mask); + /* gpio_request NOT allowed */ + set_bit(pin_index, &pio->gpio_mask); + return; fail: @@ -99,19 +105,29 @@ void __init at32_select_gpio(unsigned int pin, unsigned long flags) goto fail; } - pio_writel(pio, PUER, mask); - if (flags & AT32_GPIOF_HIGH) - pio_writel(pio, SODR, mask); - else - pio_writel(pio, CODR, mask); - if (flags & AT32_GPIOF_OUTPUT) + if (flags & AT32_GPIOF_OUTPUT) { + if (flags & AT32_GPIOF_HIGH) + pio_writel(pio, SODR, mask); + else + pio_writel(pio, CODR, mask); + pio_writel(pio, PUDR, mask); pio_writel(pio, OER, mask); - else + } else { + if (flags & AT32_GPIOF_PULLUP) + pio_writel(pio, PUER, mask); + else + pio_writel(pio, PUDR, mask); + if (flags & AT32_GPIOF_DEGLITCH) + pio_writel(pio, IFER, mask); + else + pio_writel(pio, IFDR, mask); pio_writel(pio, ODR, mask); + } pio_writel(pio, PER, mask); - if (!(flags & AT32_GPIOF_PULLUP)) - pio_writel(pio, PUDR, mask); + + /* gpio_request now allowed */ + clear_bit(pin_index, &pio->gpio_mask); return; @@ -119,20 +135,199 @@ fail: dump_stack(); } +/*--------------------------------------------------------------------------*/ + +/*--------------------------------------------------------------------------*/ + +/* GPIO API */ + +int gpio_request(unsigned int gpio, const char *label) +{ + struct pio_device *pio; + unsigned int pin; + + pio = gpio_to_pio(gpio); + if (!pio) + return -ENODEV; + + pin = gpio & 0x1f; + if (test_and_set_bit(pin, &pio->gpio_mask)) + return -EBUSY; + + return 0; +} +EXPORT_SYMBOL(gpio_request); + +void gpio_free(unsigned int gpio) +{ + struct pio_device *pio; + unsigned int pin; + + pio = gpio_to_pio(gpio); + if (!pio) { + printk(KERN_ERR + "gpio: attempted to free invalid pin %u\n", gpio); + return; + } + + pin = gpio & 0x1f; + if (!test_and_clear_bit(pin, &pio->gpio_mask)) + printk(KERN_ERR "gpio: freeing free or non-gpio pin %s-%u\n", + pio->name, pin); +} +EXPORT_SYMBOL(gpio_free); + +int gpio_direction_input(unsigned int gpio) +{ + struct pio_device *pio; + unsigned int pin; + + pio = gpio_to_pio(gpio); + if (!pio) + return -ENODEV; + + pin = gpio & 0x1f; + pio_writel(pio, ODR, 1 << pin); + + return 0; +} +EXPORT_SYMBOL(gpio_direction_input); + +int gpio_direction_output(unsigned int gpio) +{ + struct pio_device *pio; + unsigned int pin; + + pio = gpio_to_pio(gpio); + if (!pio) + return -ENODEV; + + pin = gpio & 0x1f; + pio_writel(pio, OER, 1 << pin); + + return 0; +} +EXPORT_SYMBOL(gpio_direction_output); + +int gpio_get_value(unsigned int gpio) +{ + struct pio_device *pio = &pio_dev[gpio >> 5]; + + return (pio_readl(pio, PDSR) >> (gpio & 0x1f)) & 1; +} +EXPORT_SYMBOL(gpio_get_value); + +void gpio_set_value(unsigned int gpio, int value) +{ + struct pio_device *pio = &pio_dev[gpio >> 5]; + u32 mask; + + mask = 1 << (gpio & 0x1f); + if (value) + pio_writel(pio, SODR, mask); + else + pio_writel(pio, CODR, mask); +} +EXPORT_SYMBOL(gpio_set_value); + +/*--------------------------------------------------------------------------*/ + +/* GPIO IRQ support */ + +static void gpio_irq_mask(unsigned irq) +{ + unsigned gpio = irq_to_gpio(irq); + struct pio_device *pio = &pio_dev[gpio >> 5]; + + pio_writel(pio, IDR, 1 << (gpio & 0x1f)); +} + +static void gpio_irq_unmask(unsigned irq) +{ + unsigned gpio = irq_to_gpio(irq); + struct pio_device *pio = &pio_dev[gpio >> 5]; + + pio_writel(pio, IER, 1 << (gpio & 0x1f)); +} + +static int gpio_irq_type(unsigned irq, unsigned type) +{ + if (type != IRQ_TYPE_EDGE_BOTH && type != IRQ_TYPE_NONE) + return -EINVAL; + + return 0; +} + +static struct irq_chip gpio_irqchip = { + .name = "gpio", + .mask = gpio_irq_mask, + .unmask = gpio_irq_unmask, + .set_type = gpio_irq_type, +}; + +static void gpio_irq_handler(unsigned irq, struct irq_desc *desc) +{ + struct pio_device *pio = get_irq_chip_data(irq); + unsigned gpio_irq; + + gpio_irq = (unsigned) get_irq_data(irq); + for (;;) { + u32 isr; + struct irq_desc *d; + + /* ack pending GPIO interrupts */ + isr = pio_readl(pio, ISR) & pio_readl(pio, IMR); + if (!isr) + break; + do { + int i; + + i = ffs(isr) - 1; + isr &= ~(1 << i); + + i += gpio_irq; + d = &irq_desc[i]; + + d->handle_irq(i, d); + } while (isr); + } +} + +static void __init +gpio_irq_setup(struct pio_device *pio, int irq, int gpio_irq) +{ + unsigned i; + + set_irq_chip_data(irq, pio); + set_irq_data(irq, (void *) gpio_irq); + + for (i = 0; i < 32; i++, gpio_irq++) { + set_irq_chip_data(gpio_irq, pio); + set_irq_chip_and_handler(gpio_irq, &gpio_irqchip, + handle_simple_irq); + } + + set_irq_chained_handler(irq, gpio_irq_handler); +} + +/*--------------------------------------------------------------------------*/ + static int __init pio_probe(struct platform_device *pdev) { struct pio_device *pio = NULL; + int irq = platform_get_irq(pdev, 0); + int gpio_irq_base = GPIO_IRQ_BASE + pdev->id * 32; BUG_ON(pdev->id >= MAX_NR_PIO_DEVICES); pio = &pio_dev[pdev->id]; BUG_ON(!pio->regs); - /* TODO: Interrupts */ + gpio_irq_setup(pio, irq, gpio_irq_base); platform_set_drvdata(pdev, pio); - printk(KERN_INFO "%s: Atmel Port Multiplexer at 0x%p (irq %d)\n", - pio->name, pio->regs, platform_get_irq(pdev, 0)); + printk(KERN_DEBUG "%s: base 0x%p, irq %d chains %d..%d\n", + pio->name, pio->regs, irq, gpio_irq_base, gpio_irq_base + 31); return 0; } @@ -148,7 +343,7 @@ static int __init pio_init(void) { return platform_driver_register(&pio_driver); } -subsys_initcall(pio_init); +postcore_initcall(pio_init); void __init at32_init_pio(struct platform_device *pdev) { @@ -184,6 +379,16 @@ void __init at32_init_pio(struct platform_device *pdev) pio->pdev = pdev; pio->regs = ioremap(regs->start, regs->end - regs->start + 1); + /* + * request_gpio() is only valid for pins that have been + * explicitly configured as GPIO and not previously requested + */ + pio->gpio_mask = ~0UL; + pio_writel(pio, ODR, ~0UL); pio_writel(pio, PER, ~0UL); + + /* start with irqs disabled and acked */ + pio_writel(pio, IDR, ~0UL); + (void) pio_readl(pio, ISR); } -- cgit v1.1 From dde251033f3e54619317269a908ce40e6f3a8d04 Mon Sep 17 00:00:00 2001 From: Haavard Skinnemoen Date: Mon, 29 Jan 2007 17:59:40 +0100 Subject: [AVR32] Don't reset PIO state at bootup Leave the PIO lines as the bootloader left them. This allows us to use PIOE without disturbing the SDRAM muxing. Signed-off-by: Haavard Skinnemoen --- arch/avr32/mach-at32ap/pio.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'arch') diff --git a/arch/avr32/mach-at32ap/pio.c b/arch/avr32/mach-at32ap/pio.c index 17e835d..c3f596c 100644 --- a/arch/avr32/mach-at32ap/pio.c +++ b/arch/avr32/mach-at32ap/pio.c @@ -385,9 +385,6 @@ void __init at32_init_pio(struct platform_device *pdev) */ pio->gpio_mask = ~0UL; - pio_writel(pio, ODR, ~0UL); - pio_writel(pio, PER, ~0UL); - /* start with irqs disabled and acked */ pio_writel(pio, IDR, ~0UL); (void) pio_readl(pio, ISR); -- cgit v1.1 From e7f70b8cc69b1bcc56ed8d70f8e3671ec3956374 Mon Sep 17 00:00:00 2001 From: Haavard Skinnemoen Date: Tue, 30 Jan 2007 11:01:23 +0100 Subject: [AVR32] Introduce at32_reserve_pin() at32_reserve_pin() can be used for reserving portmux pins without altering their configuration. Useful for e.g. SDRAM pins where we really don't want to change the bootloader-provided configuration. Signed-off-by: Haavard Skinnemoen --- arch/avr32/mach-at32ap/pio.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/avr32/mach-at32ap/pio.c b/arch/avr32/mach-at32ap/pio.c index c3f596c..9ba5654 100644 --- a/arch/avr32/mach-at32ap/pio.c +++ b/arch/avr32/mach-at32ap/pio.c @@ -135,7 +135,28 @@ fail: dump_stack(); } -/*--------------------------------------------------------------------------*/ +/* Reserve a pin, preventing anyone else from changing its configuration. */ +void __init at32_reserve_pin(unsigned int pin) +{ + struct pio_device *pio; + unsigned int pin_index = pin & 0x1f; + + pio = gpio_to_pio(pin); + if (unlikely(!pio)) { + printk("pio: invalid pin %u\n", pin); + goto fail; + } + + if (unlikely(test_and_set_bit(pin_index, &pio->pinmux_mask))) { + printk("%s: pin %u is busy\n", pio->name, pin_index); + goto fail; + } + + return; + +fail: + dump_stack(); +} /*--------------------------------------------------------------------------*/ -- cgit v1.1 From 7f9f4678637f9ee1a999cc0870c4668f32e1a7eb Mon Sep 17 00:00:00 2001 From: Haavard Skinnemoen Date: Tue, 30 Jan 2007 11:16:16 +0100 Subject: [AVR32] Add PIOE device and reserve SDRAM pins The PIOE device was left out before because it muxes SDRAM pins (and is therefore a bit dangerous to mess with) and because no existing drivers had any use for it. It is needed for CompactFlash, however, and now that we have a way to protect the SDRAM pins, it can be safely added. Signed-off-by: Haavard Skinnemoen --- arch/avr32/boards/atstk1000/atstk1002.c | 23 +++++++++++++++++++++++ arch/avr32/mach-at32ap/at32ap7000.c | 10 ++++++++++ 2 files changed, 33 insertions(+) (limited to 'arch') diff --git a/arch/avr32/boards/atstk1000/atstk1002.c b/arch/avr32/boards/atstk1000/atstk1002.c index 3787d6b..bca815f 100644 --- a/arch/avr32/boards/atstk1000/atstk1002.c +++ b/arch/avr32/boards/atstk1000/atstk1002.c @@ -19,6 +19,7 @@ #include #include #include +#include #define SW2_DEFAULT /* MMCI and UART_A available */ @@ -102,6 +103,28 @@ void __init setup_board(void) static int __init atstk1002_init(void) { + /* + * ATSTK1000 uses 32-bit SDRAM interface. Reserve the + * SDRAM-specific pins so that nobody messes with them. + */ + at32_reserve_pin(GPIO_PIN_PE(0)); /* DATA[16] */ + at32_reserve_pin(GPIO_PIN_PE(1)); /* DATA[17] */ + at32_reserve_pin(GPIO_PIN_PE(2)); /* DATA[18] */ + at32_reserve_pin(GPIO_PIN_PE(3)); /* DATA[19] */ + at32_reserve_pin(GPIO_PIN_PE(4)); /* DATA[20] */ + at32_reserve_pin(GPIO_PIN_PE(5)); /* DATA[21] */ + at32_reserve_pin(GPIO_PIN_PE(6)); /* DATA[22] */ + at32_reserve_pin(GPIO_PIN_PE(7)); /* DATA[23] */ + at32_reserve_pin(GPIO_PIN_PE(8)); /* DATA[24] */ + at32_reserve_pin(GPIO_PIN_PE(9)); /* DATA[25] */ + at32_reserve_pin(GPIO_PIN_PE(10)); /* DATA[26] */ + at32_reserve_pin(GPIO_PIN_PE(11)); /* DATA[27] */ + at32_reserve_pin(GPIO_PIN_PE(12)); /* DATA[28] */ + at32_reserve_pin(GPIO_PIN_PE(13)); /* DATA[29] */ + at32_reserve_pin(GPIO_PIN_PE(14)); /* DATA[30] */ + at32_reserve_pin(GPIO_PIN_PE(15)); /* DATA[31] */ + at32_reserve_pin(GPIO_PIN_PE(26)); /* SDCS */ + at32_add_system_devices(); #ifdef SW2_DEFAULT diff --git a/arch/avr32/mach-at32ap/at32ap7000.c b/arch/avr32/mach-at32ap/at32ap7000.c index 21561ab..981d553 100644 --- a/arch/avr32/mach-at32ap/at32ap7000.c +++ b/arch/avr32/mach-at32ap/at32ap7000.c @@ -496,6 +496,13 @@ static struct resource pio3_resource[] = { DEFINE_DEV(pio, 3); DEV_CLK(mck, pio3, pba, 13); +static struct resource pio4_resource[] = { + PBMEM(0xffe03800), + IRQ(17), +}; +DEFINE_DEV(pio, 4); +DEV_CLK(mck, pio4, pba, 14); + void __init at32_add_system_devices(void) { system_manager.eim_first_irq = EIM_IRQ_BASE; @@ -509,6 +516,7 @@ void __init at32_add_system_devices(void) platform_device_register(&pio1_device); platform_device_register(&pio2_device); platform_device_register(&pio3_device); + platform_device_register(&pio4_device); } /* -------------------------------------------------------------------- @@ -860,6 +868,7 @@ struct clk *at32_clock_list[] = { &pio1_mck, &pio2_mck, &pio3_mck, + &pio4_mck, &atmel_usart0_usart, &atmel_usart1_usart, &atmel_usart2_usart, @@ -880,6 +889,7 @@ void __init at32_portmux_init(void) at32_init_pio(&pio1_device); at32_init_pio(&pio2_device); at32_init_pio(&pio3_device); + at32_init_pio(&pio4_device); } void __init at32_clock_init(void) -- cgit v1.1 From 3d60ee1b04320d0695e071828dbadf3564d4568a Mon Sep 17 00:00:00 2001 From: Haavard Skinnemoen Date: Wed, 10 Jan 2007 20:20:02 +0100 Subject: [AVR32] SPI platform code update Move stuff in spi.c into ATSTK1002 board code and update SPI platform device definitions according to the new GPIO API. Signed-off-by: Haavard Skinnemoen --- arch/avr32/boards/atstk1000/Makefile | 2 +- arch/avr32/boards/atstk1000/atstk1002.c | 14 +++++++++++ arch/avr32/boards/atstk1000/spi.c | 27 -------------------- arch/avr32/mach-at32ap/at32ap7000.c | 44 +++++++++++++++++++++++++++------ 4 files changed, 51 insertions(+), 36 deletions(-) delete mode 100644 arch/avr32/boards/atstk1000/spi.c (limited to 'arch') diff --git a/arch/avr32/boards/atstk1000/Makefile b/arch/avr32/boards/atstk1000/Makefile index df94994..8e09922 100644 --- a/arch/avr32/boards/atstk1000/Makefile +++ b/arch/avr32/boards/atstk1000/Makefile @@ -1,2 +1,2 @@ -obj-y += setup.o spi.o flash.o +obj-y += setup.o flash.o obj-$(CONFIG_BOARD_ATSTK1002) += atstk1002.o diff --git a/arch/avr32/boards/atstk1000/atstk1002.c b/arch/avr32/boards/atstk1000/atstk1002.c index bca815f..d47e39f 100644 --- a/arch/avr32/boards/atstk1000/atstk1002.c +++ b/arch/avr32/boards/atstk1000/atstk1002.c @@ -8,15 +8,18 @@ * published by the Free Software Foundation. */ #include +#include #include #include #include #include #include #include +#include #include #include +#include #include #include #include @@ -33,6 +36,16 @@ static struct eth_addr __initdata hw_addr[2]; static struct eth_platform_data __initdata eth_data[2]; extern struct lcdc_platform_data atstk1000_fb0_data; +static struct spi_board_info spi_board_info[] __initdata = { + { + .modalias = "ltv350qv", + .controller_data = (void *)GPIO_PIN_PA(4), + .max_speed_hz = 16000000, + .bus_num = 0, + .chip_select = 1, + }, +}; + /* * The next two functions should go away as the boot loader is * supposed to initialize the macb address registers with a valid @@ -136,6 +149,7 @@ static int __init atstk1002_init(void) set_hw_addr(at32_add_device_eth(0, ð_data[0])); + spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info)); at32_add_device_spi(0); at32_add_device_lcdc(0, &atstk1000_fb0_data); diff --git a/arch/avr32/boards/atstk1000/spi.c b/arch/avr32/boards/atstk1000/spi.c deleted file mode 100644 index 567726c..0000000 --- a/arch/avr32/boards/atstk1000/spi.c +++ /dev/null @@ -1,27 +0,0 @@ -/* - * ATSTK1000 SPI devices - * - * Copyright (C) 2005 Atmel Norway - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ -#include -#include - -static struct spi_board_info spi_board_info[] __initdata = { - { - .modalias = "ltv350qv", - .max_speed_hz = 16000000, - .bus_num = 0, - .chip_select = 1, - }, -}; - -static int board_init_spi(void) -{ - spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info)); - return 0; -} -arch_initcall(board_init_spi); diff --git a/arch/avr32/mach-at32ap/at32ap7000.c b/arch/avr32/mach-at32ap/at32ap7000.c index 981d553..c1e477e 100644 --- a/arch/avr32/mach-at32ap/at32ap7000.c +++ b/arch/avr32/mach-at32ap/at32ap7000.c @@ -736,12 +736,19 @@ at32_add_device_eth(unsigned int id, struct eth_platform_data *data) /* -------------------------------------------------------------------- * SPI * -------------------------------------------------------------------- */ -static struct resource spi0_resource[] = { +static struct resource atmel_spi0_resource[] = { PBMEM(0xffe00000), IRQ(3), }; -DEFINE_DEV(spi, 0); -DEV_CLK(mck, spi0, pba, 0); +DEFINE_DEV(atmel_spi, 0); +DEV_CLK(spi_clk, atmel_spi0, pba, 0); + +static struct resource atmel_spi1_resource[] = { + PBMEM(0xffe00400), + IRQ(4), +}; +DEFINE_DEV(atmel_spi, 1); +DEV_CLK(spi_clk, atmel_spi1, pba, 1); struct platform_device *__init at32_add_device_spi(unsigned int id) { @@ -749,13 +756,33 @@ struct platform_device *__init at32_add_device_spi(unsigned int id) switch (id) { case 0: - pdev = &spi0_device; + pdev = &atmel_spi0_device; select_peripheral(PA(0), PERIPH_A, 0); /* MISO */ select_peripheral(PA(1), PERIPH_A, 0); /* MOSI */ select_peripheral(PA(2), PERIPH_A, 0); /* SCK */ - select_peripheral(PA(3), PERIPH_A, 0); /* NPCS0 */ - select_peripheral(PA(4), PERIPH_A, 0); /* NPCS1 */ - select_peripheral(PA(5), PERIPH_A, 0); /* NPCS2 */ + + /* NPCS[2:0] */ + at32_select_gpio(GPIO_PIN_PA(3), + AT32_GPIOF_OUTPUT | AT32_GPIOF_HIGH); + at32_select_gpio(GPIO_PIN_PA(4), + AT32_GPIOF_OUTPUT | AT32_GPIOF_HIGH); + at32_select_gpio(GPIO_PIN_PA(5), + AT32_GPIOF_OUTPUT | AT32_GPIOF_HIGH); + break; + + case 1: + pdev = &atmel_spi1_device; + select_peripheral(PB(0), PERIPH_B, 0); /* MISO */ + select_peripheral(PB(1), PERIPH_B, 0); /* MOSI */ + select_peripheral(PB(5), PERIPH_B, 0); /* SCK */ + + /* NPCS[2:0] */ + at32_select_gpio(GPIO_PIN_PB(2), + AT32_GPIOF_OUTPUT | AT32_GPIOF_HIGH); + at32_select_gpio(GPIO_PIN_PB(3), + AT32_GPIOF_OUTPUT | AT32_GPIOF_HIGH); + at32_select_gpio(GPIO_PIN_PB(4), + AT32_GPIOF_OUTPUT | AT32_GPIOF_HIGH); break; default: @@ -877,7 +904,8 @@ struct clk *at32_clock_list[] = { &macb0_pclk, &macb1_hclk, &macb1_pclk, - &spi0_mck, + &atmel_spi0_spi_clk, + &atmel_spi1_spi_clk, &lcdc0_hclk, &lcdc0_pixclk, }; -- cgit v1.1 From 9d4ad801372c688c6ae7e080f6fc6f802f53cbe3 Mon Sep 17 00:00:00 2001 From: Haavard Skinnemoen Date: Fri, 9 Feb 2007 11:43:09 +0100 Subject: [AVR32] Remove last remains of libgcc Two libgcc headers were left around even though all the actual code borrowed from libgcc is gone. Delete them. Signed-off-by: Haavard Skinnemoen --- arch/avr32/lib/libgcc.h | 33 ---------------- arch/avr32/lib/longlong.h | 98 ----------------------------------------------- 2 files changed, 131 deletions(-) delete mode 100644 arch/avr32/lib/libgcc.h delete mode 100644 arch/avr32/lib/longlong.h (limited to 'arch') diff --git a/arch/avr32/lib/libgcc.h b/arch/avr32/lib/libgcc.h deleted file mode 100644 index 5a091b5..0000000 --- a/arch/avr32/lib/libgcc.h +++ /dev/null @@ -1,33 +0,0 @@ -/* Definitions for various functions 'borrowed' from gcc-3.4.3 */ - -#define BITS_PER_UNIT 8 - -typedef int QItype __attribute__ ((mode (QI))); -typedef unsigned int UQItype __attribute__ ((mode (QI))); -typedef int HItype __attribute__ ((mode (HI))); -typedef unsigned int UHItype __attribute__ ((mode (HI))); -typedef int SItype __attribute__ ((mode (SI))); -typedef unsigned int USItype __attribute__ ((mode (SI))); -typedef int DItype __attribute__ ((mode (DI))); -typedef unsigned int UDItype __attribute__ ((mode (DI))); -typedef float SFtype __attribute__ ((mode (SF))); -typedef float DFtype __attribute__ ((mode (DF))); -typedef int word_type __attribute__ ((mode (__word__))); - -#define W_TYPE_SIZE (4 * BITS_PER_UNIT) -#define Wtype SItype -#define UWtype USItype -#define HWtype SItype -#define UHWtype USItype -#define DWtype DItype -#define UDWtype UDItype -#define __NW(a,b) __ ## a ## si ## b -#define __NDW(a,b) __ ## a ## di ## b - -struct DWstruct {Wtype high, low;}; - -typedef union -{ - struct DWstruct s; - DWtype ll; -} DWunion; diff --git a/arch/avr32/lib/longlong.h b/arch/avr32/lib/longlong.h deleted file mode 100644 index cd5e369..0000000 --- a/arch/avr32/lib/longlong.h +++ /dev/null @@ -1,98 +0,0 @@ -/* longlong.h -- definitions for mixed size 32/64 bit arithmetic. - Copyright (C) 1991, 1992, 1994, 1995, 1996, 1997, 1998, 1999, 2000 - Free Software Foundation, Inc. - - This definition file 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, or (at your option) any later version. - - This definition file is distributed in the hope that it will be - useful, but WITHOUT ANY WARRANTY; without even the implied - warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -/* Borrowed from gcc-3.4.3 */ - -#define __BITS4 (W_TYPE_SIZE / 4) -#define __ll_B ((UWtype) 1 << (W_TYPE_SIZE / 2)) -#define __ll_lowpart(t) ((UWtype) (t) & (__ll_B - 1)) -#define __ll_highpart(t) ((UWtype) (t) >> (W_TYPE_SIZE / 2)) - -#define count_leading_zeros(count, x) ((count) = __builtin_clz(x)) - -#define __udiv_qrnnd_c(q, r, n1, n0, d) \ - do { \ - UWtype __d1, __d0, __q1, __q0; \ - UWtype __r1, __r0, __m; \ - __d1 = __ll_highpart (d); \ - __d0 = __ll_lowpart (d); \ - \ - __r1 = (n1) % __d1; \ - __q1 = (n1) / __d1; \ - __m = (UWtype) __q1 * __d0; \ - __r1 = __r1 * __ll_B | __ll_highpart (n0); \ - if (__r1 < __m) \ - { \ - __q1--, __r1 += (d); \ - if (__r1 >= (d)) /* i.e. we didn't get carry when adding to __r1 */\ - if (__r1 < __m) \ - __q1--, __r1 += (d); \ - } \ - __r1 -= __m; \ - \ - __r0 = __r1 % __d1; \ - __q0 = __r1 / __d1; \ - __m = (UWtype) __q0 * __d0; \ - __r0 = __r0 * __ll_B | __ll_lowpart (n0); \ - if (__r0 < __m) \ - { \ - __q0--, __r0 += (d); \ - if (__r0 >= (d)) \ - if (__r0 < __m) \ - __q0--, __r0 += (d); \ - } \ - __r0 -= __m; \ - \ - (q) = (UWtype) __q1 * __ll_B | __q0; \ - (r) = __r0; \ - } while (0) - -#define udiv_qrnnd __udiv_qrnnd_c - -#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ - do { \ - UWtype __x; \ - __x = (al) - (bl); \ - (sh) = (ah) - (bh) - (__x > (al)); \ - (sl) = __x; \ - } while (0) - -#define umul_ppmm(w1, w0, u, v) \ - do { \ - UWtype __x0, __x1, __x2, __x3; \ - UHWtype __ul, __vl, __uh, __vh; \ - \ - __ul = __ll_lowpart (u); \ - __uh = __ll_highpart (u); \ - __vl = __ll_lowpart (v); \ - __vh = __ll_highpart (v); \ - \ - __x0 = (UWtype) __ul * __vl; \ - __x1 = (UWtype) __ul * __vh; \ - __x2 = (UWtype) __uh * __vl; \ - __x3 = (UWtype) __uh * __vh; \ - \ - __x1 += __ll_highpart (__x0);/* this can't give carry */ \ - __x1 += __x2; /* but this indeed can */ \ - if (__x1 < __x2) /* did we get it? */ \ - __x3 += __ll_B; /* yes, add it in the proper pos. */ \ - \ - (w1) = __x3 + __ll_highpart (__x1); \ - (w0) = __ll_lowpart (__x1) * __ll_B + __ll_lowpart (__x0); \ - } while (0) -- cgit v1.1 From 4ffabefb456f140eb47c7294e9158a9027a64ccc Mon Sep 17 00:00:00 2001 From: Haavard Skinnemoen Date: Fri, 9 Feb 2007 15:23:46 +0100 Subject: [AVR32] Add missing #include arch/avr32/kernel/cpu.c needs THIS_MODULE, so it must include linux/module.h. Signed-off-by: Haavard Skinnemoen --- arch/avr32/kernel/cpu.c | 1 + 1 file changed, 1 insertion(+) (limited to 'arch') diff --git a/arch/avr32/kernel/cpu.c b/arch/avr32/kernel/cpu.c index 342452b..2e72fd2 100644 --- a/arch/avr32/kernel/cpu.c +++ b/arch/avr32/kernel/cpu.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include -- cgit v1.1