aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@woody.osdl.org>2006-12-11 21:28:59 -0500
committerLinus Torvalds <torvalds@woody.osdl.org>2006-12-11 21:28:59 -0500
commitcd39301a68f9604854f3543117b01dc73cbe193f (patch)
tree0be77134407d73aece97050151d80ed4b07b23bc /arch
parent13d7d84e078f49f08b657a3fba0d7a0b7b44ba65 (diff)
parent3fc0eb47aa96b1d9230ff85b722c45c3b9e83d14 (diff)
Merge branch 'for-linus' of git://www.atmel.no/~hskinnemoen/linux/kernel/avr32
* 'for-linus' of git://www.atmel.no/~hskinnemoen/linux/kernel/avr32: [AVR32] Add missing #include <linux/param.h> to delay.c [AVR32] Pass dev parameter to dma_cache_sync() [AVR32] Implement intc_get_pending() [AVR32] Don't include <asm/delay.h> [AVR32] Put the chip in "stop" mode when halting the system [AVR32] Set flow handler for external interrupts [AVR32] Remove unused file [AVR32] Remove mii_phy_addr and eth_addr from eth_platform_data [AVR32] Move ethernet tag parsing to board-specific code [AVR32] Add macb1 platform_device [AVR32] Portmux API update
Diffstat (limited to 'arch')
-rw-r--r--arch/avr32/boards/atstk1000/atstk1002.c76
-rw-r--r--arch/avr32/kernel/avr32_ksyms.c2
-rw-r--r--arch/avr32/kernel/process.c7
-rw-r--r--arch/avr32/kernel/setup.c24
-rw-r--r--arch/avr32/lib/delay.c2
-rw-r--r--arch/avr32/mach-at32ap/at32ap7000.c182
-rw-r--r--arch/avr32/mach-at32ap/extint.c22
-rw-r--r--arch/avr32/mach-at32ap/intc.c4
-rw-r--r--arch/avr32/mach-at32ap/pio.c85
-rw-r--r--arch/avr32/mach-at32ap/sm.c289
10 files changed, 287 insertions, 406 deletions
diff --git a/arch/avr32/boards/atstk1000/atstk1002.c b/arch/avr32/boards/atstk1000/atstk1002.c
index cced73c58115..32b361f31c2c 100644
--- a/arch/avr32/boards/atstk1000/atstk1002.c
+++ b/arch/avr32/boards/atstk1000/atstk1002.c
@@ -7,20 +7,83 @@
7 * it under the terms of the GNU General Public License version 2 as 7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation. 8 * published by the Free Software Foundation.
9 */ 9 */
10#include <linux/clk.h>
11#include <linux/etherdevice.h>
10#include <linux/init.h> 12#include <linux/init.h>
13#include <linux/kernel.h>
14#include <linux/platform_device.h>
15#include <linux/string.h>
16#include <linux/types.h>
11 17
18#include <asm/io.h>
19#include <asm/setup.h>
12#include <asm/arch/board.h> 20#include <asm/arch/board.h>
13#include <asm/arch/init.h> 21#include <asm/arch/init.h>
14 22
15struct eth_platform_data __initdata eth0_data = { 23struct eth_addr {
16 .valid = 1, 24 u8 addr[6];
17 .mii_phy_addr = 0x10,
18 .is_rmii = 0,
19 .hw_addr = { 0x6a, 0x87, 0x71, 0x14, 0xcd, 0xcb },
20}; 25};
21 26
27static struct eth_addr __initdata hw_addr[2];
28
29static struct eth_platform_data __initdata eth_data[2];
22extern struct lcdc_platform_data atstk1000_fb0_data; 30extern struct lcdc_platform_data atstk1000_fb0_data;
23 31
32/*
33 * The next two functions should go away as the boot loader is
34 * supposed to initialize the macb address registers with a valid
35 * ethernet address. But we need to keep it around for a while until
36 * we can be reasonably sure the boot loader does this.
37 *
38 * The phy_id is ignored as the driver will probe for it.
39 */
40static int __init parse_tag_ethernet(struct tag *tag)
41{
42 int i;
43
44 i = tag->u.ethernet.mac_index;
45 if (i < ARRAY_SIZE(hw_addr))
46 memcpy(hw_addr[i].addr, tag->u.ethernet.hw_address,
47 sizeof(hw_addr[i].addr));
48
49 return 0;
50}
51__tagtable(ATAG_ETHERNET, parse_tag_ethernet);
52
53static void __init set_hw_addr(struct platform_device *pdev)
54{
55 struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
56 const u8 *addr;
57 void __iomem *regs;
58 struct clk *pclk;
59
60 if (!res)
61 return;
62 if (pdev->id >= ARRAY_SIZE(hw_addr))
63 return;
64
65 addr = hw_addr[pdev->id].addr;
66 if (!is_valid_ether_addr(addr))
67 return;
68
69 /*
70 * Since this is board-specific code, we'll cheat and use the
71 * physical address directly as we happen to know that it's
72 * the same as the virtual address.
73 */
74 regs = (void __iomem __force *)res->start;
75 pclk = clk_get(&pdev->dev, "pclk");
76 if (!pclk)
77 return;
78
79 clk_enable(pclk);
80 __raw_writel((addr[3] << 24) | (addr[2] << 16)
81 | (addr[1] << 8) | addr[0], regs + 0x98);
82 __raw_writel((addr[5] << 8) | addr[4], regs + 0x9c);
83 clk_disable(pclk);
84 clk_put(pclk);
85}
86
24void __init setup_board(void) 87void __init setup_board(void)
25{ 88{
26 at32_map_usart(1, 0); /* /dev/ttyS0 */ 89 at32_map_usart(1, 0); /* /dev/ttyS0 */
@@ -38,7 +101,8 @@ static int __init atstk1002_init(void)
38 at32_add_device_usart(1); 101 at32_add_device_usart(1);
39 at32_add_device_usart(2); 102 at32_add_device_usart(2);
40 103
41 at32_add_device_eth(0, &eth0_data); 104 set_hw_addr(at32_add_device_eth(0, &eth_data[0]));
105
42 at32_add_device_spi(0); 106 at32_add_device_spi(0);
43 at32_add_device_lcdc(0, &atstk1000_fb0_data); 107 at32_add_device_lcdc(0, &atstk1000_fb0_data);
44 108
diff --git a/arch/avr32/kernel/avr32_ksyms.c b/arch/avr32/kernel/avr32_ksyms.c
index 372e3f8b2417..7c4c76114bba 100644
--- a/arch/avr32/kernel/avr32_ksyms.c
+++ b/arch/avr32/kernel/avr32_ksyms.c
@@ -7,12 +7,12 @@
7 * it under the terms of the GNU General Public License version 2 as 7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation. 8 * published by the Free Software Foundation.
9 */ 9 */
10#include <linux/delay.h>
10#include <linux/io.h> 11#include <linux/io.h>
11#include <linux/module.h> 12#include <linux/module.h>
12 13
13#include <asm/checksum.h> 14#include <asm/checksum.h>
14#include <asm/uaccess.h> 15#include <asm/uaccess.h>
15#include <asm/delay.h>
16 16
17/* 17/*
18 * GCC functions 18 * GCC functions
diff --git a/arch/avr32/kernel/process.c b/arch/avr32/kernel/process.c
index 317dc50945f2..0b4325946a41 100644
--- a/arch/avr32/kernel/process.c
+++ b/arch/avr32/kernel/process.c
@@ -38,6 +38,13 @@ void cpu_idle(void)
38 38
39void machine_halt(void) 39void machine_halt(void)
40{ 40{
41 /*
42 * Enter Stop mode. The 32 kHz oscillator will keep running so
43 * the RTC will keep the time properly and the system will
44 * boot quickly.
45 */
46 asm volatile("sleep 3\n\t"
47 "sub pc, -2");
41} 48}
42 49
43void machine_power_off(void) 50void machine_power_off(void)
diff --git a/arch/avr32/kernel/setup.c b/arch/avr32/kernel/setup.c
index ea2d1ffee478..a34211601008 100644
--- a/arch/avr32/kernel/setup.c
+++ b/arch/avr32/kernel/setup.c
@@ -229,30 +229,6 @@ static int __init parse_tag_rsvd_mem(struct tag *tag)
229} 229}
230__tagtable(ATAG_RSVD_MEM, parse_tag_rsvd_mem); 230__tagtable(ATAG_RSVD_MEM, parse_tag_rsvd_mem);
231 231
232static int __init parse_tag_ethernet(struct tag *tag)
233{
234#if 0
235 const struct platform_device *pdev;
236
237 /*
238 * We really need a bus type that supports "classes"...this
239 * will do for now (until we must handle other kinds of
240 * ethernet controllers)
241 */
242 pdev = platform_get_device("macb", tag->u.ethernet.mac_index);
243 if (pdev && pdev->dev.platform_data) {
244 struct eth_platform_data *data = pdev->dev.platform_data;
245
246 data->valid = 1;
247 data->mii_phy_addr = tag->u.ethernet.mii_phy_addr;
248 memcpy(data->hw_addr, tag->u.ethernet.hw_address,
249 sizeof(data->hw_addr));
250 }
251#endif
252 return 0;
253}
254__tagtable(ATAG_ETHERNET, parse_tag_ethernet);
255
256/* 232/*
257 * Scan the tag table for this tag, and call its parse function. The 233 * Scan the tag table for this tag, and call its parse function. The
258 * tag table is built by the linker from all the __tagtable 234 * tag table is built by the linker from all the __tagtable
diff --git a/arch/avr32/lib/delay.c b/arch/avr32/lib/delay.c
index 462c8307b680..b3bc0b56e2c6 100644
--- a/arch/avr32/lib/delay.c
+++ b/arch/avr32/lib/delay.c
@@ -12,9 +12,9 @@
12 12
13#include <linux/delay.h> 13#include <linux/delay.h>
14#include <linux/module.h> 14#include <linux/module.h>
15#include <linux/param.h>
15#include <linux/types.h> 16#include <linux/types.h>
16 17
17#include <asm/delay.h>
18#include <asm/processor.h> 18#include <asm/processor.h>
19#include <asm/sysreg.h> 19#include <asm/sysreg.h>
20 20
diff --git a/arch/avr32/mach-at32ap/at32ap7000.c b/arch/avr32/mach-at32ap/at32ap7000.c
index 7ff6ad8bab5f..48f4ef38c70e 100644
--- a/arch/avr32/mach-at32ap/at32ap7000.c
+++ b/arch/avr32/mach-at32ap/at32ap7000.c
@@ -11,6 +11,7 @@
11 11
12#include <asm/io.h> 12#include <asm/io.h>
13 13
14#include <asm/arch/at32ap7000.h>
14#include <asm/arch/board.h> 15#include <asm/arch/board.h>
15#include <asm/arch/portmux.h> 16#include <asm/arch/portmux.h>
16#include <asm/arch/sm.h> 17#include <asm/arch/sm.h>
@@ -57,6 +58,9 @@ static struct platform_device _name##_id##_device = { \
57 .num_resources = ARRAY_SIZE(_name##_id##_resource), \ 58 .num_resources = ARRAY_SIZE(_name##_id##_resource), \
58} 59}
59 60
61#define select_peripheral(pin, periph, flags) \
62 at32_select_periph(GPIO_PIN_##pin, GPIO_##periph, flags)
63
60#define DEV_CLK(_name, devname, bus, _index) \ 64#define DEV_CLK(_name, devname, bus, _index) \
61static struct clk devname##_##_name = { \ 65static struct clk devname##_##_name = { \
62 .name = #_name, \ 66 .name = #_name, \
@@ -67,18 +71,6 @@ static struct clk devname##_##_name = { \
67 .index = _index, \ 71 .index = _index, \
68} 72}
69 73
70enum {
71 PIOA,
72 PIOB,
73 PIOC,
74 PIOD,
75};
76
77enum {
78 FUNC_A,
79 FUNC_B,
80};
81
82unsigned long at32ap7000_osc_rates[3] = { 74unsigned long at32ap7000_osc_rates[3] = {
83 [0] = 32768, 75 [0] = 32768,
84 /* FIXME: these are ATSTK1002-specific */ 76 /* FIXME: these are ATSTK1002-specific */
@@ -569,26 +561,26 @@ DEV_CLK(usart, atmel_usart3, pba, 6);
569 561
570static inline void configure_usart0_pins(void) 562static inline void configure_usart0_pins(void)
571{ 563{
572 portmux_set_func(PIOA, 8, FUNC_B); /* RXD */ 564 select_peripheral(PA(8), PERIPH_B, 0); /* RXD */
573 portmux_set_func(PIOA, 9, FUNC_B); /* TXD */ 565 select_peripheral(PA(9), PERIPH_B, 0); /* TXD */
574} 566}
575 567
576static inline void configure_usart1_pins(void) 568static inline void configure_usart1_pins(void)
577{ 569{
578 portmux_set_func(PIOA, 17, FUNC_A); /* RXD */ 570 select_peripheral(PA(17), PERIPH_A, 0); /* RXD */
579 portmux_set_func(PIOA, 18, FUNC_A); /* TXD */ 571 select_peripheral(PA(18), PERIPH_A, 0); /* TXD */
580} 572}
581 573
582static inline void configure_usart2_pins(void) 574static inline void configure_usart2_pins(void)
583{ 575{
584 portmux_set_func(PIOB, 26, FUNC_B); /* RXD */ 576 select_peripheral(PB(26), PERIPH_B, 0); /* RXD */
585 portmux_set_func(PIOB, 27, FUNC_B); /* TXD */ 577 select_peripheral(PB(27), PERIPH_B, 0); /* TXD */
586} 578}
587 579
588static inline void configure_usart3_pins(void) 580static inline void configure_usart3_pins(void)
589{ 581{
590 portmux_set_func(PIOB, 18, FUNC_B); /* RXD */ 582 select_peripheral(PB(18), PERIPH_B, 0); /* RXD */
591 portmux_set_func(PIOB, 17, FUNC_B); /* TXD */ 583 select_peripheral(PB(17), PERIPH_B, 0); /* TXD */
592} 584}
593 585
594static struct platform_device *at32_usarts[4]; 586static struct platform_device *at32_usarts[4];
@@ -654,6 +646,15 @@ DEFINE_DEV_DATA(macb, 0);
654DEV_CLK(hclk, macb0, hsb, 8); 646DEV_CLK(hclk, macb0, hsb, 8);
655DEV_CLK(pclk, macb0, pbb, 6); 647DEV_CLK(pclk, macb0, pbb, 6);
656 648
649static struct eth_platform_data macb1_data;
650static struct resource macb1_resource[] = {
651 PBMEM(0xfff01c00),
652 IRQ(26),
653};
654DEFINE_DEV_DATA(macb, 1);
655DEV_CLK(hclk, macb1, hsb, 9);
656DEV_CLK(pclk, macb1, pbb, 7);
657
657struct platform_device *__init 658struct platform_device *__init
658at32_add_device_eth(unsigned int id, struct eth_platform_data *data) 659at32_add_device_eth(unsigned int id, struct eth_platform_data *data)
659{ 660{
@@ -663,27 +664,54 @@ at32_add_device_eth(unsigned int id, struct eth_platform_data *data)
663 case 0: 664 case 0:
664 pdev = &macb0_device; 665 pdev = &macb0_device;
665 666
666 portmux_set_func(PIOC, 3, FUNC_A); /* TXD0 */ 667 select_peripheral(PC(3), PERIPH_A, 0); /* TXD0 */
667 portmux_set_func(PIOC, 4, FUNC_A); /* TXD1 */ 668 select_peripheral(PC(4), PERIPH_A, 0); /* TXD1 */
668 portmux_set_func(PIOC, 7, FUNC_A); /* TXEN */ 669 select_peripheral(PC(7), PERIPH_A, 0); /* TXEN */
669 portmux_set_func(PIOC, 8, FUNC_A); /* TXCK */ 670 select_peripheral(PC(8), PERIPH_A, 0); /* TXCK */
670 portmux_set_func(PIOC, 9, FUNC_A); /* RXD0 */ 671 select_peripheral(PC(9), PERIPH_A, 0); /* RXD0 */
671 portmux_set_func(PIOC, 10, FUNC_A); /* RXD1 */ 672 select_peripheral(PC(10), PERIPH_A, 0); /* RXD1 */
672 portmux_set_func(PIOC, 13, FUNC_A); /* RXER */ 673 select_peripheral(PC(13), PERIPH_A, 0); /* RXER */
673 portmux_set_func(PIOC, 15, FUNC_A); /* RXDV */ 674 select_peripheral(PC(15), PERIPH_A, 0); /* RXDV */
674 portmux_set_func(PIOC, 16, FUNC_A); /* MDC */ 675 select_peripheral(PC(16), PERIPH_A, 0); /* MDC */
675 portmux_set_func(PIOC, 17, FUNC_A); /* MDIO */ 676 select_peripheral(PC(17), PERIPH_A, 0); /* MDIO */
677
678 if (!data->is_rmii) {
679 select_peripheral(PC(0), PERIPH_A, 0); /* COL */
680 select_peripheral(PC(1), PERIPH_A, 0); /* CRS */
681 select_peripheral(PC(2), PERIPH_A, 0); /* TXER */
682 select_peripheral(PC(5), PERIPH_A, 0); /* TXD2 */
683 select_peripheral(PC(6), PERIPH_A, 0); /* TXD3 */
684 select_peripheral(PC(11), PERIPH_A, 0); /* RXD2 */
685 select_peripheral(PC(12), PERIPH_A, 0); /* RXD3 */
686 select_peripheral(PC(14), PERIPH_A, 0); /* RXCK */
687 select_peripheral(PC(18), PERIPH_A, 0); /* SPD */
688 }
689 break;
690
691 case 1:
692 pdev = &macb1_device;
693
694 select_peripheral(PD(13), PERIPH_B, 0); /* TXD0 */
695 select_peripheral(PD(14), PERIPH_B, 0); /* TXD1 */
696 select_peripheral(PD(11), PERIPH_B, 0); /* TXEN */
697 select_peripheral(PD(12), PERIPH_B, 0); /* TXCK */
698 select_peripheral(PD(10), PERIPH_B, 0); /* RXD0 */
699 select_peripheral(PD(6), PERIPH_B, 0); /* RXD1 */
700 select_peripheral(PD(5), PERIPH_B, 0); /* RXER */
701 select_peripheral(PD(4), PERIPH_B, 0); /* RXDV */
702 select_peripheral(PD(3), PERIPH_B, 0); /* MDC */
703 select_peripheral(PD(2), PERIPH_B, 0); /* MDIO */
676 704
677 if (!data->is_rmii) { 705 if (!data->is_rmii) {
678 portmux_set_func(PIOC, 0, FUNC_A); /* COL */ 706 select_peripheral(PC(19), PERIPH_B, 0); /* COL */
679 portmux_set_func(PIOC, 1, FUNC_A); /* CRS */ 707 select_peripheral(PC(23), PERIPH_B, 0); /* CRS */
680 portmux_set_func(PIOC, 2, FUNC_A); /* TXER */ 708 select_peripheral(PC(26), PERIPH_B, 0); /* TXER */
681 portmux_set_func(PIOC, 5, FUNC_A); /* TXD2 */ 709 select_peripheral(PC(27), PERIPH_B, 0); /* TXD2 */
682 portmux_set_func(PIOC, 6, FUNC_A); /* TXD3 */ 710 select_peripheral(PC(28), PERIPH_B, 0); /* TXD3 */
683 portmux_set_func(PIOC, 11, FUNC_A); /* RXD2 */ 711 select_peripheral(PC(29), PERIPH_B, 0); /* RXD2 */
684 portmux_set_func(PIOC, 12, FUNC_A); /* RXD3 */ 712 select_peripheral(PC(30), PERIPH_B, 0); /* RXD3 */
685 portmux_set_func(PIOC, 14, FUNC_A); /* RXCK */ 713 select_peripheral(PC(24), PERIPH_B, 0); /* RXCK */
686 portmux_set_func(PIOC, 18, FUNC_A); /* SPD */ 714 select_peripheral(PD(15), PERIPH_B, 0); /* SPD */
687 } 715 }
688 break; 716 break;
689 717
@@ -714,12 +742,12 @@ struct platform_device *__init at32_add_device_spi(unsigned int id)
714 switch (id) { 742 switch (id) {
715 case 0: 743 case 0:
716 pdev = &spi0_device; 744 pdev = &spi0_device;
717 portmux_set_func(PIOA, 0, FUNC_A); /* MISO */ 745 select_peripheral(PA(0), PERIPH_A, 0); /* MISO */
718 portmux_set_func(PIOA, 1, FUNC_A); /* MOSI */ 746 select_peripheral(PA(1), PERIPH_A, 0); /* MOSI */
719 portmux_set_func(PIOA, 2, FUNC_A); /* SCK */ 747 select_peripheral(PA(2), PERIPH_A, 0); /* SCK */
720 portmux_set_func(PIOA, 3, FUNC_A); /* NPCS0 */ 748 select_peripheral(PA(3), PERIPH_A, 0); /* NPCS0 */
721 portmux_set_func(PIOA, 4, FUNC_A); /* NPCS1 */ 749 select_peripheral(PA(4), PERIPH_A, 0); /* NPCS1 */
722 portmux_set_func(PIOA, 5, FUNC_A); /* NPCS2 */ 750 select_peripheral(PA(5), PERIPH_A, 0); /* NPCS2 */
723 break; 751 break;
724 752
725 default: 753 default:
@@ -762,37 +790,37 @@ at32_add_device_lcdc(unsigned int id, struct lcdc_platform_data *data)
762 switch (id) { 790 switch (id) {
763 case 0: 791 case 0:
764 pdev = &lcdc0_device; 792 pdev = &lcdc0_device;
765 portmux_set_func(PIOC, 19, FUNC_A); /* CC */ 793 select_peripheral(PC(19), PERIPH_A, 0); /* CC */
766 portmux_set_func(PIOC, 20, FUNC_A); /* HSYNC */ 794 select_peripheral(PC(20), PERIPH_A, 0); /* HSYNC */
767 portmux_set_func(PIOC, 21, FUNC_A); /* PCLK */ 795 select_peripheral(PC(21), PERIPH_A, 0); /* PCLK */
768 portmux_set_func(PIOC, 22, FUNC_A); /* VSYNC */ 796 select_peripheral(PC(22), PERIPH_A, 0); /* VSYNC */
769 portmux_set_func(PIOC, 23, FUNC_A); /* DVAL */ 797 select_peripheral(PC(23), PERIPH_A, 0); /* DVAL */
770 portmux_set_func(PIOC, 24, FUNC_A); /* MODE */ 798 select_peripheral(PC(24), PERIPH_A, 0); /* MODE */
771 portmux_set_func(PIOC, 25, FUNC_A); /* PWR */ 799 select_peripheral(PC(25), PERIPH_A, 0); /* PWR */
772 portmux_set_func(PIOC, 26, FUNC_A); /* DATA0 */ 800 select_peripheral(PC(26), PERIPH_A, 0); /* DATA0 */
773 portmux_set_func(PIOC, 27, FUNC_A); /* DATA1 */ 801 select_peripheral(PC(27), PERIPH_A, 0); /* DATA1 */
774 portmux_set_func(PIOC, 28, FUNC_A); /* DATA2 */ 802 select_peripheral(PC(28), PERIPH_A, 0); /* DATA2 */
775 portmux_set_func(PIOC, 29, FUNC_A); /* DATA3 */ 803 select_peripheral(PC(29), PERIPH_A, 0); /* DATA3 */
776 portmux_set_func(PIOC, 30, FUNC_A); /* DATA4 */ 804 select_peripheral(PC(30), PERIPH_A, 0); /* DATA4 */
777 portmux_set_func(PIOC, 31, FUNC_A); /* DATA5 */ 805 select_peripheral(PC(31), PERIPH_A, 0); /* DATA5 */
778 portmux_set_func(PIOD, 0, FUNC_A); /* DATA6 */ 806 select_peripheral(PD(0), PERIPH_A, 0); /* DATA6 */
779 portmux_set_func(PIOD, 1, FUNC_A); /* DATA7 */ 807 select_peripheral(PD(1), PERIPH_A, 0); /* DATA7 */
780 portmux_set_func(PIOD, 2, FUNC_A); /* DATA8 */ 808 select_peripheral(PD(2), PERIPH_A, 0); /* DATA8 */
781 portmux_set_func(PIOD, 3, FUNC_A); /* DATA9 */ 809 select_peripheral(PD(3), PERIPH_A, 0); /* DATA9 */
782 portmux_set_func(PIOD, 4, FUNC_A); /* DATA10 */ 810 select_peripheral(PD(4), PERIPH_A, 0); /* DATA10 */
783 portmux_set_func(PIOD, 5, FUNC_A); /* DATA11 */ 811 select_peripheral(PD(5), PERIPH_A, 0); /* DATA11 */
784 portmux_set_func(PIOD, 6, FUNC_A); /* DATA12 */ 812 select_peripheral(PD(6), PERIPH_A, 0); /* DATA12 */
785 portmux_set_func(PIOD, 7, FUNC_A); /* DATA13 */ 813 select_peripheral(PD(7), PERIPH_A, 0); /* DATA13 */
786 portmux_set_func(PIOD, 8, FUNC_A); /* DATA14 */ 814 select_peripheral(PD(8), PERIPH_A, 0); /* DATA14 */
787 portmux_set_func(PIOD, 9, FUNC_A); /* DATA15 */ 815 select_peripheral(PD(9), PERIPH_A, 0); /* DATA15 */
788 portmux_set_func(PIOD, 10, FUNC_A); /* DATA16 */ 816 select_peripheral(PD(10), PERIPH_A, 0); /* DATA16 */
789 portmux_set_func(PIOD, 11, FUNC_A); /* DATA17 */ 817 select_peripheral(PD(11), PERIPH_A, 0); /* DATA17 */
790 portmux_set_func(PIOD, 12, FUNC_A); /* DATA18 */ 818 select_peripheral(PD(12), PERIPH_A, 0); /* DATA18 */
791 portmux_set_func(PIOD, 13, FUNC_A); /* DATA19 */ 819 select_peripheral(PD(13), PERIPH_A, 0); /* DATA19 */
792 portmux_set_func(PIOD, 14, FUNC_A); /* DATA20 */ 820 select_peripheral(PD(14), PERIPH_A, 0); /* DATA20 */
793 portmux_set_func(PIOD, 15, FUNC_A); /* DATA21 */ 821 select_peripheral(PD(15), PERIPH_A, 0); /* DATA21 */
794 portmux_set_func(PIOD, 16, FUNC_A); /* DATA22 */ 822 select_peripheral(PD(16), PERIPH_A, 0); /* DATA22 */
795 portmux_set_func(PIOD, 17, FUNC_A); /* DATA23 */ 823 select_peripheral(PD(17), PERIPH_A, 0); /* DATA23 */
796 824
797 clk_set_parent(&lcdc0_pixclk, &pll0); 825 clk_set_parent(&lcdc0_pixclk, &pll0);
798 clk_set_rate(&lcdc0_pixclk, clk_get_rate(&pll0)); 826 clk_set_rate(&lcdc0_pixclk, clk_get_rate(&pll0));
@@ -838,6 +866,8 @@ struct clk *at32_clock_list[] = {
838 &atmel_usart3_usart, 866 &atmel_usart3_usart,
839 &macb0_hclk, 867 &macb0_hclk,
840 &macb0_pclk, 868 &macb0_pclk,
869 &macb1_hclk,
870 &macb1_pclk,
841 &spi0_mck, 871 &spi0_mck,
842 &lcdc0_hclk, 872 &lcdc0_hclk,
843 &lcdc0_pixclk, 873 &lcdc0_pixclk,
diff --git a/arch/avr32/mach-at32ap/extint.c b/arch/avr32/mach-at32ap/extint.c
index 4dff1f988900..b59272e81b9a 100644
--- a/arch/avr32/mach-at32ap/extint.c
+++ b/arch/avr32/mach-at32ap/extint.c
@@ -49,12 +49,25 @@ static void eim_unmask_irq(unsigned int irq)
49static int eim_set_irq_type(unsigned int irq, unsigned int flow_type) 49static int eim_set_irq_type(unsigned int irq, unsigned int flow_type)
50{ 50{
51 struct at32_sm *sm = get_irq_chip_data(irq); 51 struct at32_sm *sm = get_irq_chip_data(irq);
52 struct irq_desc *desc;
52 unsigned int i = irq - sm->eim_first_irq; 53 unsigned int i = irq - sm->eim_first_irq;
53 u32 mode, edge, level; 54 u32 mode, edge, level;
54 unsigned long flags; 55 unsigned long flags;
55 int ret = 0; 56 int ret = 0;
56 57
57 flow_type &= IRQ_TYPE_SENSE_MASK; 58 if (flow_type == IRQ_TYPE_NONE)
59 flow_type = IRQ_TYPE_LEVEL_LOW;
60
61 desc = &irq_desc[irq];
62 desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL);
63 desc->status |= flow_type & IRQ_TYPE_SENSE_MASK;
64
65 if (flow_type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH)) {
66 desc->status |= IRQ_LEVEL;
67 set_irq_handler(irq, handle_level_irq);
68 } else {
69 set_irq_handler(irq, handle_edge_irq);
70 }
58 71
59 spin_lock_irqsave(&sm->lock, flags); 72 spin_lock_irqsave(&sm->lock, flags);
60 73
@@ -148,10 +161,15 @@ static int __init eim_init(void)
148 pattern = sm_readl(sm, EIM_MODE); 161 pattern = sm_readl(sm, EIM_MODE);
149 nr_irqs = fls(pattern); 162 nr_irqs = fls(pattern);
150 163
164 /* Trigger on falling edge unless overridden by driver */
165 sm_writel(sm, EIM_MODE, 0UL);
166 sm_writel(sm, EIM_EDGE, 0UL);
167
151 sm->eim_chip = &eim_chip; 168 sm->eim_chip = &eim_chip;
152 169
153 for (i = 0; i < nr_irqs; i++) { 170 for (i = 0; i < nr_irqs; i++) {
154 set_irq_chip(sm->eim_first_irq + i, &eim_chip); 171 set_irq_chip_and_handler(sm->eim_first_irq + i, &eim_chip,
172 handle_edge_irq);
155 set_irq_chip_data(sm->eim_first_irq + i, sm); 173 set_irq_chip_data(sm->eim_first_irq + i, sm);
156 } 174 }
157 175
diff --git a/arch/avr32/mach-at32ap/intc.c b/arch/avr32/mach-at32ap/intc.c
index eb87a18ad7b2..dd5c009cf224 100644
--- a/arch/avr32/mach-at32ap/intc.c
+++ b/arch/avr32/mach-at32ap/intc.c
@@ -136,3 +136,7 @@ fail:
136 panic("Interrupt controller initialization failed!\n"); 136 panic("Interrupt controller initialization failed!\n");
137} 137}
138 138
139unsigned long intc_get_pending(int group)
140{
141 return intc_readl(&intc0, INTREQ0 + 4 * group);
142}
diff --git a/arch/avr32/mach-at32ap/pio.c b/arch/avr32/mach-at32ap/pio.c
index d3aabfca8598..f1280ed8ed6d 100644
--- a/arch/avr32/mach-at32ap/pio.c
+++ b/arch/avr32/mach-at32ap/pio.c
@@ -25,27 +25,98 @@ struct pio_device {
25 void __iomem *regs; 25 void __iomem *regs;
26 const struct platform_device *pdev; 26 const struct platform_device *pdev;
27 struct clk *clk; 27 struct clk *clk;
28 u32 alloc_mask; 28 u32 pinmux_mask;
29 char name[32]; 29 char name[32];
30}; 30};
31 31
32static struct pio_device pio_dev[MAX_NR_PIO_DEVICES]; 32static struct pio_device pio_dev[MAX_NR_PIO_DEVICES];
33 33
34void portmux_set_func(unsigned int portmux_id, unsigned int pin_id, 34static struct pio_device *gpio_to_pio(unsigned int gpio)
35 unsigned int function_id)
36{ 35{
37 struct pio_device *pio; 36 struct pio_device *pio;
38 u32 mask = 1 << pin_id; 37 unsigned int index;
39 38
40 BUG_ON(portmux_id >= MAX_NR_PIO_DEVICES); 39 index = gpio >> 5;
40 if (index >= MAX_NR_PIO_DEVICES)
41 return NULL;
42 pio = &pio_dev[index];
43 if (!pio->regs)
44 return NULL;
41 45
42 pio = &pio_dev[portmux_id]; 46 return pio;
47}
48
49/* Pin multiplexing API */
50
51void __init at32_select_periph(unsigned int pin, unsigned int periph,
52 unsigned long flags)
53{
54 struct pio_device *pio;
55 unsigned int pin_index = pin & 0x1f;
56 u32 mask = 1 << pin_index;
57
58 pio = gpio_to_pio(pin);
59 if (unlikely(!pio)) {
60 printk("pio: invalid pin %u\n", pin);
61 goto fail;
62 }
43 63
44 if (function_id) 64 if (unlikely(test_and_set_bit(pin_index, &pio->pinmux_mask))) {
65 printk("%s: pin %u is busy\n", pio->name, pin_index);
66 goto fail;
67 }
68
69 pio_writel(pio, PUER, mask);
70 if (periph)
45 pio_writel(pio, BSR, mask); 71 pio_writel(pio, BSR, mask);
46 else 72 else
47 pio_writel(pio, ASR, mask); 73 pio_writel(pio, ASR, mask);
74
48 pio_writel(pio, PDR, mask); 75 pio_writel(pio, PDR, mask);
76 if (!(flags & AT32_GPIOF_PULLUP))
77 pio_writel(pio, PUDR, mask);
78
79 return;
80
81fail:
82 dump_stack();
83}
84
85void __init at32_select_gpio(unsigned int pin, unsigned long flags)
86{
87 struct pio_device *pio;
88 unsigned int pin_index = pin & 0x1f;
89 u32 mask = 1 << pin_index;
90
91 pio = gpio_to_pio(pin);
92 if (unlikely(!pio)) {
93 printk("pio: invalid pin %u\n", pin);
94 goto fail;
95 }
96
97 if (unlikely(test_and_set_bit(pin_index, &pio->pinmux_mask))) {
98 printk("%s: pin %u is busy\n", pio->name, pin_index);
99 goto fail;
100 }
101
102 pio_writel(pio, PUER, mask);
103 if (flags & AT32_GPIOF_HIGH)
104 pio_writel(pio, SODR, mask);
105 else
106 pio_writel(pio, CODR, mask);
107 if (flags & AT32_GPIOF_OUTPUT)
108 pio_writel(pio, OER, mask);
109 else
110 pio_writel(pio, ODR, mask);
111
112 pio_writel(pio, PER, mask);
113 if (!(flags & AT32_GPIOF_PULLUP))
114 pio_writel(pio, PUDR, mask);
115
116 return;
117
118fail:
119 dump_stack();
49} 120}
50 121
51static int __init pio_probe(struct platform_device *pdev) 122static int __init pio_probe(struct platform_device *pdev)
diff --git a/arch/avr32/mach-at32ap/sm.c b/arch/avr32/mach-at32ap/sm.c
deleted file mode 100644
index 03306eb0345e..000000000000
--- a/arch/avr32/mach-at32ap/sm.c
+++ /dev/null
@@ -1,289 +0,0 @@
1/*
2 * System Manager driver for AT32AP CPUs
3 *
4 * Copyright (C) 2006 Atmel Corporation
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10
11#include <linux/errno.h>
12#include <linux/init.h>
13#include <linux/interrupt.h>
14#include <linux/kernel.h>
15#include <linux/platform_device.h>
16#include <linux/random.h>
17#include <linux/spinlock.h>
18
19#include <asm/intc.h>
20#include <asm/io.h>
21#include <asm/irq.h>
22
23#include <asm/arch/sm.h>
24
25#include "sm.h"
26
27#define SM_EIM_IRQ_RESOURCE 1
28#define SM_PM_IRQ_RESOURCE 2
29#define SM_RTC_IRQ_RESOURCE 3
30
31#define to_eim(irqc) container_of(irqc, struct at32_sm, irqc)
32
33struct at32_sm system_manager;
34
35int __init at32_sm_init(void)
36{
37 struct resource *regs;
38 struct at32_sm *sm = &system_manager;
39 int ret = -ENXIO;
40
41 regs = platform_get_resource(&at32_sm_device, IORESOURCE_MEM, 0);
42 if (!regs)
43 goto fail;
44
45 spin_lock_init(&sm->lock);
46 sm->pdev = &at32_sm_device;
47
48 ret = -ENOMEM;
49 sm->regs = ioremap(regs->start, regs->end - regs->start + 1);
50 if (!sm->regs)
51 goto fail;
52
53 return 0;
54
55fail:
56 printk(KERN_ERR "Failed to initialize System Manager: %d\n", ret);
57 return ret;
58}
59
60/*
61 * External Interrupt Module (EIM).
62 *
63 * EIM gets level- or edge-triggered interrupts of either polarity
64 * from the outside and converts it to active-high level-triggered
65 * interrupts that the internal interrupt controller can handle. EIM
66 * also provides masking/unmasking of interrupts, as well as
67 * acknowledging of edge-triggered interrupts.
68 */
69
70static irqreturn_t spurious_eim_interrupt(int irq, void *dev_id,
71 struct pt_regs *regs)
72{
73 printk(KERN_WARNING "Spurious EIM interrupt %d\n", irq);
74 disable_irq(irq);
75 return IRQ_NONE;
76}
77
78static struct irqaction eim_spurious_action = {
79 .handler = spurious_eim_interrupt,
80};
81
82static irqreturn_t eim_handle_irq(int irq, void *dev_id, struct pt_regs *regs)
83{
84 struct irq_controller * irqc = dev_id;
85 struct at32_sm *sm = to_eim(irqc);
86 unsigned long pending;
87
88 /*
89 * No need to disable interrupts globally. The interrupt
90 * level relevant to this group must be masked all the time,
91 * so we know that this particular EIM instance will not be
92 * re-entered.
93 */
94 spin_lock(&sm->lock);
95
96 pending = intc_get_pending(sm->irqc.irq_group);
97 if (unlikely(!pending)) {
98 printk(KERN_ERR "EIM (group %u): No interrupts pending!\n",
99 sm->irqc.irq_group);
100 goto unlock;
101 }
102
103 do {
104 struct irqaction *action;
105 unsigned int i;
106
107 i = fls(pending) - 1;
108 pending &= ~(1 << i);
109 action = sm->action[i];
110
111 /* Acknowledge the interrupt */
112 sm_writel(sm, EIM_ICR, 1 << i);
113
114 spin_unlock(&sm->lock);
115
116 if (action->flags & SA_INTERRUPT)
117 local_irq_disable();
118 action->handler(sm->irqc.first_irq + i, action->dev_id, regs);
119 local_irq_enable();
120 spin_lock(&sm->lock);
121 if (action->flags & SA_SAMPLE_RANDOM)
122 add_interrupt_randomness(sm->irqc.first_irq + i);
123 } while (pending);
124
125unlock:
126 spin_unlock(&sm->lock);
127 return IRQ_HANDLED;
128}
129
130static void eim_mask(struct irq_controller *irqc, unsigned int irq)
131{
132 struct at32_sm *sm = to_eim(irqc);
133 unsigned int i;
134
135 i = irq - sm->irqc.first_irq;
136 sm_writel(sm, EIM_IDR, 1 << i);
137}
138
139static void eim_unmask(struct irq_controller *irqc, unsigned int irq)
140{
141 struct at32_sm *sm = to_eim(irqc);
142 unsigned int i;
143
144 i = irq - sm->irqc.first_irq;
145 sm_writel(sm, EIM_IER, 1 << i);
146}
147
148static int eim_setup(struct irq_controller *irqc, unsigned int irq,
149 struct irqaction *action)
150{
151 struct at32_sm *sm = to_eim(irqc);
152 sm->action[irq - sm->irqc.first_irq] = action;
153 /* Acknowledge earlier interrupts */
154 sm_writel(sm, EIM_ICR, (1<<(irq - sm->irqc.first_irq)));
155 eim_unmask(irqc, irq);
156 return 0;
157}
158
159static void eim_free(struct irq_controller *irqc, unsigned int irq,
160 void *dev)
161{
162 struct at32_sm *sm = to_eim(irqc);
163 eim_mask(irqc, irq);
164 sm->action[irq - sm->irqc.first_irq] = &eim_spurious_action;
165}
166
167static int eim_set_type(struct irq_controller *irqc, unsigned int irq,
168 unsigned int type)
169{
170 struct at32_sm *sm = to_eim(irqc);
171 unsigned long flags;
172 u32 value, pattern;
173
174 spin_lock_irqsave(&sm->lock, flags);
175
176 pattern = 1 << (irq - sm->irqc.first_irq);
177
178 value = sm_readl(sm, EIM_MODE);
179 if (type & IRQ_TYPE_LEVEL)
180 value |= pattern;
181 else
182 value &= ~pattern;
183 sm_writel(sm, EIM_MODE, value);
184 value = sm_readl(sm, EIM_EDGE);
185 if (type & IRQ_EDGE_RISING)
186 value |= pattern;
187 else
188 value &= ~pattern;
189 sm_writel(sm, EIM_EDGE, value);
190 value = sm_readl(sm, EIM_LEVEL);
191 if (type & IRQ_LEVEL_HIGH)
192 value |= pattern;
193 else
194 value &= ~pattern;
195 sm_writel(sm, EIM_LEVEL, value);
196
197 spin_unlock_irqrestore(&sm->lock, flags);
198
199 return 0;
200}
201
202static unsigned int eim_get_type(struct irq_controller *irqc,
203 unsigned int irq)
204{
205 struct at32_sm *sm = to_eim(irqc);
206 unsigned long flags;
207 unsigned int type = 0;
208 u32 mode, edge, level, pattern;
209
210 pattern = 1 << (irq - sm->irqc.first_irq);
211
212 spin_lock_irqsave(&sm->lock, flags);
213 mode = sm_readl(sm, EIM_MODE);
214 edge = sm_readl(sm, EIM_EDGE);
215 level = sm_readl(sm, EIM_LEVEL);
216 spin_unlock_irqrestore(&sm->lock, flags);
217
218 if (mode & pattern)
219 type |= IRQ_TYPE_LEVEL;
220 if (edge & pattern)
221 type |= IRQ_EDGE_RISING;
222 if (level & pattern)
223 type |= IRQ_LEVEL_HIGH;
224
225 return type;
226}
227
228static struct irq_controller_class eim_irq_class = {
229 .typename = "EIM",
230 .handle = eim_handle_irq,
231 .setup = eim_setup,
232 .free = eim_free,
233 .mask = eim_mask,
234 .unmask = eim_unmask,
235 .set_type = eim_set_type,
236 .get_type = eim_get_type,
237};
238
239static int __init eim_init(void)
240{
241 struct at32_sm *sm = &system_manager;
242 unsigned int i;
243 u32 pattern;
244 int ret;
245
246 /*
247 * The EIM is really the same module as SM, so register
248 * mapping, etc. has been taken care of already.
249 */
250
251 /*
252 * Find out how many interrupt lines that are actually
253 * implemented in hardware.
254 */
255 sm_writel(sm, EIM_IDR, ~0UL);
256 sm_writel(sm, EIM_MODE, ~0UL);
257 pattern = sm_readl(sm, EIM_MODE);
258 sm->irqc.nr_irqs = fls(pattern);
259
260 ret = -ENOMEM;
261 sm->action = kmalloc(sizeof(*sm->action) * sm->irqc.nr_irqs,
262 GFP_KERNEL);
263 if (!sm->action)
264 goto out;
265
266 for (i = 0; i < sm->irqc.nr_irqs; i++)
267 sm->action[i] = &eim_spurious_action;
268
269 spin_lock_init(&sm->lock);
270 sm->irqc.irq_group = sm->pdev->resource[SM_EIM_IRQ_RESOURCE].start;
271 sm->irqc.class = &eim_irq_class;
272
273 ret = intc_register_controller(&sm->irqc);
274 if (ret < 0)
275 goto out_free_actions;
276
277 printk("EIM: External Interrupt Module at 0x%p, IRQ group %u\n",
278 sm->regs, sm->irqc.irq_group);
279 printk("EIM: Handling %u external IRQs, starting with IRQ%u\n",
280 sm->irqc.nr_irqs, sm->irqc.first_irq);
281
282 return 0;
283
284out_free_actions:
285 kfree(sm->action);
286out:
287 return ret;
288}
289arch_initcall(eim_init);