Merge branch 'for-linus' of git://www.atmel.no/~hskinnemoen/linux/kernel/avr32
authorLinus Torvalds <torvalds@woody.osdl.org>
Tue, 12 Dec 2006 02:28:59 +0000 (18:28 -0800)
committerLinus Torvalds <torvalds@woody.osdl.org>
Tue, 12 Dec 2006 02:28:59 +0000 (18:28 -0800)
* '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

14 files changed:
arch/avr32/boards/atstk1000/atstk1002.c
arch/avr32/kernel/avr32_ksyms.c
arch/avr32/kernel/process.c
arch/avr32/kernel/setup.c
arch/avr32/lib/delay.c
arch/avr32/mach-at32ap/at32ap7000.c
arch/avr32/mach-at32ap/extint.c
arch/avr32/mach-at32ap/intc.c
arch/avr32/mach-at32ap/pio.c
arch/avr32/mach-at32ap/sm.c [deleted file]
include/asm-avr32/arch-at32ap/at32ap7000.h [new file with mode: 0644]
include/asm-avr32/arch-at32ap/board.h
include/asm-avr32/arch-at32ap/portmux.h
include/asm-avr32/dma-mapping.h

index cced73c..32b361f 100644 (file)
@@ -7,20 +7,83 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
+#include <linux/clk.h>
+#include <linux/etherdevice.h>
 #include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/string.h>
+#include <linux/types.h>
 
+#include <asm/io.h>
+#include <asm/setup.h>
 #include <asm/arch/board.h>
 #include <asm/arch/init.h>
 
-struct eth_platform_data __initdata eth0_data = {
-       .valid          = 1,
-       .mii_phy_addr   = 0x10,
-       .is_rmii        = 0,
-       .hw_addr        = { 0x6a, 0x87, 0x71, 0x14, 0xcd, 0xcb },
+struct eth_addr {
+       u8 addr[6];
 };
 
+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;
 
+/*
+ * The next two functions should go away as the boot loader is
+ * supposed to initialize the macb address registers with a valid
+ * ethernet address. But we need to keep it around for a while until
+ * we can be reasonably sure the boot loader does this.
+ *
+ * The phy_id is ignored as the driver will probe for it.
+ */
+static int __init parse_tag_ethernet(struct tag *tag)
+{
+       int i;
+
+       i = tag->u.ethernet.mac_index;
+       if (i < ARRAY_SIZE(hw_addr))
+               memcpy(hw_addr[i].addr, tag->u.ethernet.hw_address,
+                      sizeof(hw_addr[i].addr));
+
+       return 0;
+}
+__tagtable(ATAG_ETHERNET, parse_tag_ethernet);
+
+static void __init set_hw_addr(struct platform_device *pdev)
+{
+       struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       const u8 *addr;
+       void __iomem *regs;
+       struct clk *pclk;
+
+       if (!res)
+               return;
+       if (pdev->id >= ARRAY_SIZE(hw_addr))
+               return;
+
+       addr = hw_addr[pdev->id].addr;
+       if (!is_valid_ether_addr(addr))
+               return;
+
+       /*
+        * Since this is board-specific code, we'll cheat and use the
+        * physical address directly as we happen to know that it's
+        * the same as the virtual address.
+        */
+       regs = (void __iomem __force *)res->start;
+       pclk = clk_get(&pdev->dev, "pclk");
+       if (!pclk)
+               return;
+
+       clk_enable(pclk);
+       __raw_writel((addr[3] << 24) | (addr[2] << 16)
+                    | (addr[1] << 8) | addr[0], regs + 0x98);
+       __raw_writel((addr[5] << 8) | addr[4], regs + 0x9c);
+       clk_disable(pclk);
+       clk_put(pclk);
+}
+
 void __init setup_board(void)
 {
        at32_map_usart(1, 0);   /* /dev/ttyS0 */
@@ -38,7 +101,8 @@ static int __init atstk1002_init(void)
        at32_add_device_usart(1);
        at32_add_device_usart(2);
 
-       at32_add_device_eth(0, &eth0_data);
+       set_hw_addr(at32_add_device_eth(0, &eth_data[0]));
+
        at32_add_device_spi(0);
        at32_add_device_lcdc(0, &atstk1000_fb0_data);
 
index 372e3f8..7c4c761 100644 (file)
@@ -7,12 +7,12 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
+#include <linux/delay.h>
 #include <linux/io.h>
 #include <linux/module.h>
 
 #include <asm/checksum.h>
 #include <asm/uaccess.h>
-#include <asm/delay.h>
 
 /*
  * GCC functions
index 317dc50..0b43259 100644 (file)
@@ -38,6 +38,13 @@ void cpu_idle(void)
 
 void machine_halt(void)
 {
+       /*
+        * Enter Stop mode. The 32 kHz oscillator will keep running so
+        * the RTC will keep the time properly and the system will
+        * boot quickly.
+        */
+       asm volatile("sleep 3\n\t"
+                    "sub pc, -2");
 }
 
 void machine_power_off(void)
index ea2d1ff..a342116 100644 (file)
@@ -229,30 +229,6 @@ static int __init parse_tag_rsvd_mem(struct tag *tag)
 }
 __tagtable(ATAG_RSVD_MEM, parse_tag_rsvd_mem);
 
-static int __init parse_tag_ethernet(struct tag *tag)
-{
-#if 0
-       const struct platform_device *pdev;
-
-       /*
-        * We really need a bus type that supports "classes"...this
-        * will do for now (until we must handle other kinds of
-        * ethernet controllers)
-        */
-       pdev = platform_get_device("macb", tag->u.ethernet.mac_index);
-       if (pdev && pdev->dev.platform_data) {
-               struct eth_platform_data *data = pdev->dev.platform_data;
-
-               data->valid = 1;
-               data->mii_phy_addr = tag->u.ethernet.mii_phy_addr;
-               memcpy(data->hw_addr, tag->u.ethernet.hw_address,
-                      sizeof(data->hw_addr));
-       }
-#endif
-       return 0;
-}
-__tagtable(ATAG_ETHERNET, parse_tag_ethernet);
-
 /*
  * Scan the tag table for this tag, and call its parse function. The
  * tag table is built by the linker from all the __tagtable
index 462c830..b3bc0b5 100644 (file)
@@ -12,9 +12,9 @@
 
 #include <linux/delay.h>
 #include <linux/module.h>
+#include <linux/param.h>
 #include <linux/types.h>
 
-#include <asm/delay.h>
 #include <asm/processor.h>
 #include <asm/sysreg.h>
 
index 7ff6ad8..48f4ef3 100644 (file)
@@ -11,6 +11,7 @@
 
 #include <asm/io.h>
 
+#include <asm/arch/at32ap7000.h>
 #include <asm/arch/board.h>
 #include <asm/arch/portmux.h>
 #include <asm/arch/sm.h>
@@ -57,6 +58,9 @@ static struct platform_device _name##_id##_device = {         \
        .num_resources  = ARRAY_SIZE(_name##_id##_resource),    \
 }
 
+#define select_peripheral(pin, periph, flags)                  \
+       at32_select_periph(GPIO_PIN_##pin, GPIO_##periph, flags)
+
 #define DEV_CLK(_name, devname, bus, _index)                   \
 static struct clk devname##_##_name = {                                \
        .name           = #_name,                               \
@@ -67,18 +71,6 @@ static struct clk devname##_##_name = {                              \
        .index          = _index,                               \
 }
 
-enum {
-       PIOA,
-       PIOB,
-       PIOC,
-       PIOD,
-};
-
-enum {
-       FUNC_A,
-       FUNC_B,
-};
-
 unsigned long at32ap7000_osc_rates[3] = {
        [0] = 32768,
        /* FIXME: these are ATSTK1002-specific */
@@ -569,26 +561,26 @@ DEV_CLK(usart, atmel_usart3, pba, 6);
 
 static inline void configure_usart0_pins(void)
 {
-       portmux_set_func(PIOA,  8, FUNC_B);     /* RXD  */
-       portmux_set_func(PIOA,  9, FUNC_B);     /* TXD  */
+       select_peripheral(PA(8),  PERIPH_B, 0); /* RXD  */
+       select_peripheral(PA(9),  PERIPH_B, 0); /* TXD  */
 }
 
 static inline void configure_usart1_pins(void)
 {
-       portmux_set_func(PIOA, 17, FUNC_A);     /* RXD  */
-       portmux_set_func(PIOA, 18, FUNC_A);     /* TXD  */
+       select_peripheral(PA(17), PERIPH_A, 0); /* RXD  */
+       select_peripheral(PA(18), PERIPH_A, 0); /* TXD  */
 }
 
 static inline void configure_usart2_pins(void)
 {
-       portmux_set_func(PIOB, 26, FUNC_B);     /* RXD  */
-       portmux_set_func(PIOB, 27, FUNC_B);     /* TXD  */
+       select_peripheral(PB(26), PERIPH_B, 0); /* RXD  */
+       select_peripheral(PB(27), PERIPH_B, 0); /* TXD  */
 }
 
 static inline void configure_usart3_pins(void)
 {
-       portmux_set_func(PIOB, 18, FUNC_B);     /* RXD  */
-       portmux_set_func(PIOB, 17, FUNC_B);     /* TXD  */
+       select_peripheral(PB(18), PERIPH_B, 0); /* RXD  */
+       select_peripheral(PB(17), PERIPH_B, 0); /* TXD  */
 }
 
 static struct platform_device *at32_usarts[4];
@@ -654,6 +646,15 @@ DEFINE_DEV_DATA(macb, 0);
 DEV_CLK(hclk, macb0, hsb, 8);
 DEV_CLK(pclk, macb0, pbb, 6);
 
+static struct eth_platform_data macb1_data;
+static struct resource macb1_resource[] = {
+       PBMEM(0xfff01c00),
+       IRQ(26),
+};
+DEFINE_DEV_DATA(macb, 1);
+DEV_CLK(hclk, macb1, hsb, 9);
+DEV_CLK(pclk, macb1, pbb, 7);
+
 struct platform_device *__init
 at32_add_device_eth(unsigned int id, struct eth_platform_data *data)
 {
@@ -663,27 +664,54 @@ at32_add_device_eth(unsigned int id, struct eth_platform_data *data)
        case 0:
                pdev = &macb0_device;
 
-               portmux_set_func(PIOC,  3, FUNC_A);     /* TXD0 */
-               portmux_set_func(PIOC,  4, FUNC_A);     /* TXD1 */
-               portmux_set_func(PIOC,  7, FUNC_A);     /* TXEN */
-               portmux_set_func(PIOC,  8, FUNC_A);     /* TXCK */
-               portmux_set_func(PIOC,  9, FUNC_A);     /* RXD0 */
-               portmux_set_func(PIOC, 10, FUNC_A);     /* RXD1 */
-               portmux_set_func(PIOC, 13, FUNC_A);     /* RXER */
-               portmux_set_func(PIOC, 15, FUNC_A);     /* RXDV */
-               portmux_set_func(PIOC, 16, FUNC_A);     /* MDC  */
-               portmux_set_func(PIOC, 17, FUNC_A);     /* MDIO */
+               select_peripheral(PC(3),  PERIPH_A, 0); /* TXD0 */
+               select_peripheral(PC(4),  PERIPH_A, 0); /* TXD1 */
+               select_peripheral(PC(7),  PERIPH_A, 0); /* TXEN */
+               select_peripheral(PC(8),  PERIPH_A, 0); /* TXCK */
+               select_peripheral(PC(9),  PERIPH_A, 0); /* RXD0 */
+               select_peripheral(PC(10), PERIPH_A, 0); /* RXD1 */
+               select_peripheral(PC(13), PERIPH_A, 0); /* RXER */
+               select_peripheral(PC(15), PERIPH_A, 0); /* RXDV */
+               select_peripheral(PC(16), PERIPH_A, 0); /* MDC  */
+               select_peripheral(PC(17), PERIPH_A, 0); /* MDIO */
+
+               if (!data->is_rmii) {
+                       select_peripheral(PC(0),  PERIPH_A, 0); /* COL  */
+                       select_peripheral(PC(1),  PERIPH_A, 0); /* CRS  */
+                       select_peripheral(PC(2),  PERIPH_A, 0); /* TXER */
+                       select_peripheral(PC(5),  PERIPH_A, 0); /* TXD2 */
+                       select_peripheral(PC(6),  PERIPH_A, 0); /* TXD3 */
+                       select_peripheral(PC(11), PERIPH_A, 0); /* RXD2 */
+                       select_peripheral(PC(12), PERIPH_A, 0); /* RXD3 */
+                       select_peripheral(PC(14), PERIPH_A, 0); /* RXCK */
+                       select_peripheral(PC(18), PERIPH_A, 0); /* SPD  */
+               }
+               break;
+
+       case 1:
+               pdev = &macb1_device;
+
+               select_peripheral(PD(13), PERIPH_B, 0);         /* TXD0 */
+               select_peripheral(PD(14), PERIPH_B, 0);         /* TXD1 */
+               select_peripheral(PD(11), PERIPH_B, 0);         /* TXEN */
+               select_peripheral(PD(12), PERIPH_B, 0);         /* TXCK */
+               select_peripheral(PD(10), PERIPH_B, 0);         /* RXD0 */
+               select_peripheral(PD(6),  PERIPH_B, 0);         /* RXD1 */
+               select_peripheral(PD(5),  PERIPH_B, 0);         /* RXER */
+               select_peripheral(PD(4),  PERIPH_B, 0);         /* RXDV */
+               select_peripheral(PD(3),  PERIPH_B, 0);         /* MDC  */
+               select_peripheral(PD(2),  PERIPH_B, 0);         /* MDIO */
 
                if (!data->is_rmii) {
-                       portmux_set_func(PIOC,  0, FUNC_A);     /* COL  */
-                       portmux_set_func(PIOC,  1, FUNC_A);     /* CRS  */
-                       portmux_set_func(PIOC,  2, FUNC_A);     /* TXER */
-                       portmux_set_func(PIOC,  5, FUNC_A);     /* TXD2 */
-                       portmux_set_func(PIOC,  6, FUNC_A);     /* TXD3 */
-                       portmux_set_func(PIOC, 11, FUNC_A);     /* RXD2 */
-                       portmux_set_func(PIOC, 12, FUNC_A);     /* RXD3 */
-                       portmux_set_func(PIOC, 14, FUNC_A);     /* RXCK */
-                       portmux_set_func(PIOC, 18, FUNC_A);     /* SPD  */
+                       select_peripheral(PC(19), PERIPH_B, 0); /* COL  */
+                       select_peripheral(PC(23), PERIPH_B, 0); /* CRS  */
+                       select_peripheral(PC(26), PERIPH_B, 0); /* TXER */
+                       select_peripheral(PC(27), PERIPH_B, 0); /* TXD2 */
+                       select_peripheral(PC(28), PERIPH_B, 0); /* TXD3 */
+                       select_peripheral(PC(29), PERIPH_B, 0); /* RXD2 */
+                       select_peripheral(PC(30), PERIPH_B, 0); /* RXD3 */
+                       select_peripheral(PC(24), PERIPH_B, 0); /* RXCK */
+                       select_peripheral(PD(15), PERIPH_B, 0); /* SPD  */
                }
                break;
 
@@ -714,12 +742,12 @@ struct platform_device *__init at32_add_device_spi(unsigned int id)
        switch (id) {
        case 0:
                pdev = &spi0_device;
-               portmux_set_func(PIOA,  0, FUNC_A);     /* MISO  */
-               portmux_set_func(PIOA,  1, FUNC_A);     /* MOSI  */
-               portmux_set_func(PIOA,  2, FUNC_A);     /* SCK   */
-               portmux_set_func(PIOA,  3, FUNC_A);     /* NPCS0 */
-               portmux_set_func(PIOA,  4, FUNC_A);     /* NPCS1 */
-               portmux_set_func(PIOA,  5, FUNC_A);     /* NPCS2 */
+               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 */
                break;
 
        default:
@@ -762,37 +790,37 @@ at32_add_device_lcdc(unsigned int id, struct lcdc_platform_data *data)
        switch (id) {
        case 0:
                pdev = &lcdc0_device;
-               portmux_set_func(PIOC, 19, FUNC_A);     /* CC     */
-               portmux_set_func(PIOC, 20, FUNC_A);     /* HSYNC  */
-               portmux_set_func(PIOC, 21, FUNC_A);     /* PCLK   */
-               portmux_set_func(PIOC, 22, FUNC_A);     /* VSYNC  */
-               portmux_set_func(PIOC, 23, FUNC_A);     /* DVAL   */
-               portmux_set_func(PIOC, 24, FUNC_A);     /* MODE   */
-               portmux_set_func(PIOC, 25, FUNC_A);     /* PWR    */
-               portmux_set_func(PIOC, 26, FUNC_A);     /* DATA0  */
-               portmux_set_func(PIOC, 27, FUNC_A);     /* DATA1  */
-               portmux_set_func(PIOC, 28, FUNC_A);     /* DATA2  */
-               portmux_set_func(PIOC, 29, FUNC_A);     /* DATA3  */
-               portmux_set_func(PIOC, 30, FUNC_A);     /* DATA4  */
-               portmux_set_func(PIOC, 31, FUNC_A);     /* DATA5  */
-               portmux_set_func(PIOD,  0, FUNC_A);     /* DATA6  */
-               portmux_set_func(PIOD,  1, FUNC_A);     /* DATA7  */
-               portmux_set_func(PIOD,  2, FUNC_A);     /* DATA8  */
-               portmux_set_func(PIOD,  3, FUNC_A);     /* DATA9  */
-               portmux_set_func(PIOD,  4, FUNC_A);     /* DATA10 */
-               portmux_set_func(PIOD,  5, FUNC_A);     /* DATA11 */
-               portmux_set_func(PIOD,  6, FUNC_A);     /* DATA12 */
-               portmux_set_func(PIOD,  7, FUNC_A);     /* DATA13 */
-               portmux_set_func(PIOD,  8, FUNC_A);     /* DATA14 */
-               portmux_set_func(PIOD,  9, FUNC_A);     /* DATA15 */
-               portmux_set_func(PIOD, 10, FUNC_A);     /* DATA16 */
-               portmux_set_func(PIOD, 11, FUNC_A);     /* DATA17 */
-               portmux_set_func(PIOD, 12, FUNC_A);     /* DATA18 */
-               portmux_set_func(PIOD, 13, FUNC_A);     /* DATA19 */
-               portmux_set_func(PIOD, 14, FUNC_A);     /* DATA20 */
-               portmux_set_func(PIOD, 15, FUNC_A);     /* DATA21 */
-               portmux_set_func(PIOD, 16, FUNC_A);     /* DATA22 */
-               portmux_set_func(PIOD, 17, FUNC_A);     /* DATA23 */
+               select_peripheral(PC(19), PERIPH_A, 0); /* CC     */
+               select_peripheral(PC(20), PERIPH_A, 0); /* HSYNC  */
+               select_peripheral(PC(21), PERIPH_A, 0); /* PCLK   */
+               select_peripheral(PC(22), PERIPH_A, 0); /* VSYNC  */
+               select_peripheral(PC(23), PERIPH_A, 0); /* DVAL   */
+               select_peripheral(PC(24), PERIPH_A, 0); /* MODE   */
+               select_peripheral(PC(25), PERIPH_A, 0); /* PWR    */
+               select_peripheral(PC(26), PERIPH_A, 0); /* DATA0  */
+               select_peripheral(PC(27), PERIPH_A, 0); /* DATA1  */
+               select_peripheral(PC(28), PERIPH_A, 0); /* DATA2  */
+               select_peripheral(PC(29), PERIPH_A, 0); /* DATA3  */
+               select_peripheral(PC(30), PERIPH_A, 0); /* DATA4  */
+               select_peripheral(PC(31), PERIPH_A, 0); /* DATA5  */
+               select_peripheral(PD(0),  PERIPH_A, 0); /* DATA6  */
+               select_peripheral(PD(1),  PERIPH_A, 0); /* DATA7  */
+               select_peripheral(PD(2),  PERIPH_A, 0); /* DATA8  */
+               select_peripheral(PD(3),  PERIPH_A, 0); /* DATA9  */
+               select_peripheral(PD(4),  PERIPH_A, 0); /* DATA10 */
+               select_peripheral(PD(5),  PERIPH_A, 0); /* DATA11 */
+               select_peripheral(PD(6),  PERIPH_A, 0); /* DATA12 */
+               select_peripheral(PD(7),  PERIPH_A, 0); /* DATA13 */
+               select_peripheral(PD(8),  PERIPH_A, 0); /* DATA14 */
+               select_peripheral(PD(9),  PERIPH_A, 0); /* DATA15 */
+               select_peripheral(PD(10), PERIPH_A, 0); /* DATA16 */
+               select_peripheral(PD(11), PERIPH_A, 0); /* DATA17 */
+               select_peripheral(PD(12), PERIPH_A, 0); /* DATA18 */
+               select_peripheral(PD(13), PERIPH_A, 0); /* DATA19 */
+               select_peripheral(PD(14), PERIPH_A, 0); /* DATA20 */
+               select_peripheral(PD(15), PERIPH_A, 0); /* DATA21 */
+               select_peripheral(PD(16), PERIPH_A, 0); /* DATA22 */
+               select_peripheral(PD(17), PERIPH_A, 0); /* DATA23 */
 
                clk_set_parent(&lcdc0_pixclk, &pll0);
                clk_set_rate(&lcdc0_pixclk, clk_get_rate(&pll0));
@@ -838,6 +866,8 @@ struct clk *at32_clock_list[] = {
        &atmel_usart3_usart,
        &macb0_hclk,
        &macb0_pclk,
+       &macb1_hclk,
+       &macb1_pclk,
        &spi0_mck,
        &lcdc0_hclk,
        &lcdc0_pixclk,
index 4dff1f9..b59272e 100644 (file)
@@ -49,12 +49,25 @@ static void eim_unmask_irq(unsigned int irq)
 static int eim_set_irq_type(unsigned int irq, unsigned int flow_type)
 {
        struct at32_sm *sm = get_irq_chip_data(irq);
+       struct irq_desc *desc;
        unsigned int i = irq - sm->eim_first_irq;
        u32 mode, edge, level;
        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);
 
@@ -148,10 +161,15 @@ static int __init eim_init(void)
        pattern = sm_readl(sm, EIM_MODE);
        nr_irqs = fls(pattern);
 
+       /* Trigger on falling edge unless overridden by driver */
+       sm_writel(sm, EIM_MODE, 0UL);
+       sm_writel(sm, EIM_EDGE, 0UL);
+
        sm->eim_chip = &eim_chip;
 
        for (i = 0; i < nr_irqs; i++) {
-               set_irq_chip(sm->eim_first_irq + i, &eim_chip);
+               set_irq_chip_and_handler(sm->eim_first_irq + i, &eim_chip,
+                                        handle_edge_irq);
                set_irq_chip_data(sm->eim_first_irq + i, sm);
        }
 
index eb87a18..dd5c009 100644 (file)
@@ -136,3 +136,7 @@ fail:
        panic("Interrupt controller initialization failed!\n");
 }
 
+unsigned long intc_get_pending(int group)
+{
+       return intc_readl(&intc0, INTREQ0 + 4 * group);
+}
index d3aabfc..f1280ed 100644 (file)
@@ -25,27 +25,98 @@ struct pio_device {
        void __iomem *regs;
        const struct platform_device *pdev;
        struct clk *clk;
-       u32 alloc_mask;
+       u32 pinmux_mask;
        char name[32];
 };
 
 static struct pio_device pio_dev[MAX_NR_PIO_DEVICES];
 
-void portmux_set_func(unsigned int portmux_id, unsigned int pin_id,
-                     unsigned int function_id)
+static struct pio_device *gpio_to_pio(unsigned int gpio)
 {
        struct pio_device *pio;
-       u32 mask = 1 << pin_id;
+       unsigned int index;
 
-       BUG_ON(portmux_id >= MAX_NR_PIO_DEVICES);
+       index = gpio >> 5;
+       if (index >= MAX_NR_PIO_DEVICES)
+               return NULL;
+       pio = &pio_dev[index];
+       if (!pio->regs)
+               return NULL;
 
-       pio = &pio_dev[portmux_id];
+       return pio;
+}
+
+/* Pin multiplexing API */
+
+void __init at32_select_periph(unsigned int pin, unsigned int periph,
+                              unsigned long flags)
+{
+       struct pio_device *pio;
+       unsigned int pin_index = pin & 0x1f;
+       u32 mask = 1 << pin_index;
+
+       pio = gpio_to_pio(pin);
+       if (unlikely(!pio)) {
+               printk("pio: invalid pin %u\n", pin);
+               goto fail;
+       }
 
-       if (function_id)
+       if (unlikely(test_and_set_bit(pin_index, &pio->pinmux_mask))) {
+               printk("%s: pin %u is busy\n", pio->name, pin_index);
+               goto fail;
+       }
+
+       pio_writel(pio, PUER, mask);
+       if (periph)
                pio_writel(pio, BSR, mask);
        else
                pio_writel(pio, ASR, mask);
+
        pio_writel(pio, PDR, mask);
+       if (!(flags & AT32_GPIOF_PULLUP))
+               pio_writel(pio, PUDR, mask);
+
+       return;
+
+fail:
+       dump_stack();
+}
+
+void __init at32_select_gpio(unsigned int pin, unsigned long flags)
+{
+       struct pio_device *pio;
+       unsigned int pin_index = pin & 0x1f;
+       u32 mask = 1 << pin_index;
+
+       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;
+       }
+
+       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)
+               pio_writel(pio, OER, mask);
+       else
+               pio_writel(pio, ODR, mask);
+
+       pio_writel(pio, PER, mask);
+       if (!(flags & AT32_GPIOF_PULLUP))
+               pio_writel(pio, PUDR, mask);
+
+       return;
+
+fail:
+       dump_stack();
 }
 
 static 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 (file)
index 03306eb..0000000
+++ /dev/null
@@ -1,289 +0,0 @@
-/*
- * System Manager driver for AT32AP CPUs
- *
- * Copyright (C) 2006 Atmel Corporation
- *
- * 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 <linux/errno.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/kernel.h>
-#include <linux/platform_device.h>
-#include <linux/random.h>
-#include <linux/spinlock.h>
-
-#include <asm/intc.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-
-#include <asm/arch/sm.h>
-
-#include "sm.h"
-
-#define SM_EIM_IRQ_RESOURCE    1
-#define SM_PM_IRQ_RESOURCE     2
-#define SM_RTC_IRQ_RESOURCE    3
-
-#define to_eim(irqc) container_of(irqc, struct at32_sm, irqc)
-
-struct at32_sm system_manager;
-
-int __init at32_sm_init(void)
-{
-       struct resource *regs;
-       struct at32_sm *sm = &system_manager;
-       int ret = -ENXIO;
-
-       regs = platform_get_resource(&at32_sm_device, IORESOURCE_MEM, 0);
-       if (!regs)
-               goto fail;
-
-       spin_lock_init(&sm->lock);
-       sm->pdev = &at32_sm_device;
-
-       ret = -ENOMEM;
-       sm->regs = ioremap(regs->start, regs->end - regs->start + 1);
-       if (!sm->regs)
-               goto fail;
-
-       return 0;
-
-fail:
-       printk(KERN_ERR "Failed to initialize System Manager: %d\n", ret);
-       return ret;
-}
-
-/*
- * External Interrupt Module (EIM).
- *
- * EIM gets level- or edge-triggered interrupts of either polarity
- * from the outside and converts it to active-high level-triggered
- * interrupts that the internal interrupt controller can handle. EIM
- * also provides masking/unmasking of interrupts, as well as
- * acknowledging of edge-triggered interrupts.
- */
-
-static irqreturn_t spurious_eim_interrupt(int irq, void *dev_id,
-                                         struct pt_regs *regs)
-{
-       printk(KERN_WARNING "Spurious EIM interrupt %d\n", irq);
-       disable_irq(irq);
-       return IRQ_NONE;
-}
-
-static struct irqaction eim_spurious_action = {
-       .handler = spurious_eim_interrupt,
-};
-
-static irqreturn_t eim_handle_irq(int irq, void *dev_id, struct pt_regs *regs)
-{
-       struct irq_controller * irqc = dev_id;
-       struct at32_sm *sm = to_eim(irqc);
-       unsigned long pending;
-
-       /*
-        * No need to disable interrupts globally.  The interrupt
-        * level relevant to this group must be masked all the time,
-        * so we know that this particular EIM instance will not be
-        * re-entered.
-        */
-       spin_lock(&sm->lock);
-
-       pending = intc_get_pending(sm->irqc.irq_group);
-       if (unlikely(!pending)) {
-               printk(KERN_ERR "EIM (group %u): No interrupts pending!\n",
-                      sm->irqc.irq_group);
-               goto unlock;
-       }
-
-       do {
-               struct irqaction *action;
-               unsigned int i;
-
-               i = fls(pending) - 1;
-               pending &= ~(1 << i);
-               action = sm->action[i];
-
-               /* Acknowledge the interrupt */
-               sm_writel(sm, EIM_ICR, 1 << i);
-
-               spin_unlock(&sm->lock);
-
-               if (action->flags & SA_INTERRUPT)
-                       local_irq_disable();
-               action->handler(sm->irqc.first_irq + i, action->dev_id, regs);
-               local_irq_enable();
-               spin_lock(&sm->lock);
-               if (action->flags & SA_SAMPLE_RANDOM)
-                       add_interrupt_randomness(sm->irqc.first_irq + i);
-       } while (pending);
-
-unlock:
-       spin_unlock(&sm->lock);
-       return IRQ_HANDLED;
-}
-
-static void eim_mask(struct irq_controller *irqc, unsigned int irq)
-{
-       struct at32_sm *sm = to_eim(irqc);
-       unsigned int i;
-
-       i = irq - sm->irqc.first_irq;
-       sm_writel(sm, EIM_IDR, 1 << i);
-}
-
-static void eim_unmask(struct irq_controller *irqc, unsigned int irq)
-{
-       struct at32_sm *sm = to_eim(irqc);
-       unsigned int i;
-
-       i = irq - sm->irqc.first_irq;
-       sm_writel(sm, EIM_IER, 1 << i);
-}
-
-static int eim_setup(struct irq_controller *irqc, unsigned int irq,
-               struct irqaction *action)
-{
-       struct at32_sm *sm = to_eim(irqc);
-       sm->action[irq - sm->irqc.first_irq] = action;
-       /* Acknowledge earlier interrupts */
-       sm_writel(sm, EIM_ICR, (1<<(irq - sm->irqc.first_irq)));
-       eim_unmask(irqc, irq);
-       return 0;
-}
-
-static void eim_free(struct irq_controller *irqc, unsigned int irq,
-               void *dev)
-{
-       struct at32_sm *sm = to_eim(irqc);
-       eim_mask(irqc, irq);
-       sm->action[irq - sm->irqc.first_irq] = &eim_spurious_action;
-}
-
-static int eim_set_type(struct irq_controller *irqc, unsigned int irq,
-                       unsigned int type)
-{
-       struct at32_sm *sm = to_eim(irqc);
-       unsigned long flags;
-       u32 value, pattern;
-
-       spin_lock_irqsave(&sm->lock, flags);
-
-       pattern = 1 << (irq - sm->irqc.first_irq);
-
-       value = sm_readl(sm, EIM_MODE);
-       if (type & IRQ_TYPE_LEVEL)
-               value |= pattern;
-       else
-               value &= ~pattern;
-       sm_writel(sm, EIM_MODE, value);
-       value = sm_readl(sm, EIM_EDGE);
-       if (type & IRQ_EDGE_RISING)
-               value |= pattern;
-       else
-               value &= ~pattern;
-       sm_writel(sm, EIM_EDGE, value);
-       value = sm_readl(sm, EIM_LEVEL);
-       if (type & IRQ_LEVEL_HIGH)
-               value |= pattern;
-       else
-               value &= ~pattern;
-       sm_writel(sm, EIM_LEVEL, value);
-
-       spin_unlock_irqrestore(&sm->lock, flags);
-
-       return 0;
-}
-
-static unsigned int eim_get_type(struct irq_controller *irqc,
-                                unsigned int irq)
-{
-       struct at32_sm *sm = to_eim(irqc);
-       unsigned long flags;
-       unsigned int type = 0;
-       u32 mode, edge, level, pattern;
-
-       pattern = 1 << (irq - sm->irqc.first_irq);
-
-       spin_lock_irqsave(&sm->lock, flags);
-       mode = sm_readl(sm, EIM_MODE);
-       edge = sm_readl(sm, EIM_EDGE);
-       level = sm_readl(sm, EIM_LEVEL);
-       spin_unlock_irqrestore(&sm->lock, flags);
-
-       if (mode & pattern)
-               type |= IRQ_TYPE_LEVEL;
-       if (edge & pattern)
-               type |= IRQ_EDGE_RISING;
-       if (level & pattern)
-               type |= IRQ_LEVEL_HIGH;
-
-       return type;
-}
-
-static struct irq_controller_class eim_irq_class = {
-       .typename       = "EIM",
-       .handle         = eim_handle_irq,
-       .setup          = eim_setup,
-       .free           = eim_free,
-       .mask           = eim_mask,
-       .unmask         = eim_unmask,
-       .set_type       = eim_set_type,
-       .get_type       = eim_get_type,
-};
-
-static int __init eim_init(void)
-{
-       struct at32_sm *sm = &system_manager;
-       unsigned int i;
-       u32 pattern;
-       int ret;
-
-       /*
-        * The EIM is really the same module as SM, so register
-        * mapping, etc. has been taken care of already.
-        */
-
-       /*
-        * Find out how many interrupt lines that are actually
-        * implemented in hardware.
-        */
-       sm_writel(sm, EIM_IDR, ~0UL);
-       sm_writel(sm, EIM_MODE, ~0UL);
-       pattern = sm_readl(sm, EIM_MODE);
-       sm->irqc.nr_irqs = fls(pattern);
-
-       ret = -ENOMEM;
-       sm->action = kmalloc(sizeof(*sm->action) * sm->irqc.nr_irqs,
-                            GFP_KERNEL);
-       if (!sm->action)
-               goto out;
-
-       for (i = 0; i < sm->irqc.nr_irqs; i++)
-               sm->action[i] = &eim_spurious_action;
-
-       spin_lock_init(&sm->lock);
-       sm->irqc.irq_group = sm->pdev->resource[SM_EIM_IRQ_RESOURCE].start;
-       sm->irqc.class = &eim_irq_class;
-
-       ret = intc_register_controller(&sm->irqc);
-       if (ret < 0)
-               goto out_free_actions;
-
-       printk("EIM: External Interrupt Module at 0x%p, IRQ group %u\n",
-              sm->regs, sm->irqc.irq_group);
-       printk("EIM: Handling %u external IRQs, starting with IRQ%u\n",
-              sm->irqc.nr_irqs, sm->irqc.first_irq);
-
-       return 0;
-
-out_free_actions:
-       kfree(sm->action);
-out:
-       return ret;
-}
-arch_initcall(eim_init);
diff --git a/include/asm-avr32/arch-at32ap/at32ap7000.h b/include/asm-avr32/arch-at32ap/at32ap7000.h
new file mode 100644 (file)
index 0000000..ba85e04
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Pin definitions for AT32AP7000.
+ *
+ * Copyright (C) 2006 Atmel Corporation
+ *
+ * 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.
+ */
+#ifndef __ASM_ARCH_AT32AP7000_H__
+#define __ASM_ARCH_AT32AP7000_H__
+
+#define GPIO_PERIPH_A  0
+#define GPIO_PERIPH_B  1
+
+#define NR_GPIO_CONTROLLERS    4
+
+/*
+ * Pin numbers identifying specific GPIO pins on the chip. They can
+ * also be converted to IRQ numbers by passing them through
+ * gpio_to_irq().
+ */
+#define GPIO_PIOA_BASE (0)
+#define GPIO_PIOB_BASE (GPIO_PIOA_BASE + 32)
+#define GPIO_PIOC_BASE (GPIO_PIOB_BASE + 32)
+#define GPIO_PIOD_BASE (GPIO_PIOC_BASE + 32)
+
+#define GPIO_PIN_PA(N) (GPIO_PIOA_BASE + (N))
+#define GPIO_PIN_PB(N) (GPIO_PIOB_BASE + (N))
+#define GPIO_PIN_PC(N) (GPIO_PIOC_BASE + (N))
+#define GPIO_PIN_PD(N) (GPIO_PIOD_BASE + (N))
+
+#endif /* __ASM_ARCH_AT32AP7000_H__ */
index a39b3e9..b120ee0 100644 (file)
@@ -21,10 +21,7 @@ void at32_map_usart(unsigned int hw_id, unsigned int line);
 struct platform_device *at32_add_device_usart(unsigned int id);
 
 struct eth_platform_data {
-       u8      valid;
-       u8      mii_phy_addr;
        u8      is_rmii;
-       u8      hw_addr[6];
 };
 struct platform_device *
 at32_add_device_eth(unsigned int id, struct eth_platform_data *data);
index 4d50421..83c6905 100644 (file)
@@ -7,10 +7,20 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-#ifndef __ASM_AVR32_AT32_PORTMUX_H__
-#define __ASM_AVR32_AT32_PORTMUX_H__
+#ifndef __ASM_ARCH_PORTMUX_H__
+#define __ASM_ARCH_PORTMUX_H__
 
-void portmux_set_func(unsigned int portmux_id, unsigned int pin_id,
-                     unsigned int function_id);
+/*
+ * Set up pin multiplexing, called from board init only.
+ *
+ * The following flags determine the initial state of the pin.
+ */
+#define AT32_GPIOF_PULLUP      0x00000001      /* Enable pull-up */
+#define AT32_GPIOF_OUTPUT      0x00000002      /* Enable output driver */
+#define AT32_GPIOF_HIGH                0x00000004      /* Set output high */
+
+void at32_select_periph(unsigned int pin, unsigned int periph,
+                       unsigned long flags);
+void at32_select_gpio(unsigned int pin, unsigned long flags);
 
-#endif /* __ASM_AVR32_AT32_PORTMUX_H__ */
+#endif /* __ASM_ARCH_PORTMUX_H__ */
index 0580b5d..5c01e27 100644 (file)
@@ -109,7 +109,7 @@ static inline dma_addr_t
 dma_map_single(struct device *dev, void *cpu_addr, size_t size,
               enum dma_data_direction direction)
 {
-       dma_cache_sync(cpu_addr, size, direction);
+       dma_cache_sync(dev, cpu_addr, size, direction);
        return virt_to_bus(cpu_addr);
 }
 
@@ -211,7 +211,7 @@ dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
 
                sg[i].dma_address = page_to_bus(sg[i].page) + sg[i].offset;
                virt = page_address(sg[i].page) + sg[i].offset;
-               dma_cache_sync(virt, sg[i].length, direction);
+               dma_cache_sync(dev, virt, sg[i].length, direction);
        }
 
        return nents;
@@ -256,14 +256,14 @@ static inline void
 dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle,
                        size_t size, enum dma_data_direction direction)
 {
-       dma_cache_sync(bus_to_virt(dma_handle), size, direction);
+       dma_cache_sync(dev, bus_to_virt(dma_handle), size, direction);
 }
 
 static inline void
 dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle,
                           size_t size, enum dma_data_direction direction)
 {
-       dma_cache_sync(bus_to_virt(dma_handle), size, direction);
+       dma_cache_sync(dev, bus_to_virt(dma_handle), size, direction);
 }
 
 /**
@@ -286,7 +286,7 @@ dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg,
        int i;
 
        for (i = 0; i < nents; i++) {
-               dma_cache_sync(page_address(sg[i].page) + sg[i].offset,
+               dma_cache_sync(dev, page_address(sg[i].page) + sg[i].offset,
                               sg[i].length, direction);
        }
 }
@@ -298,7 +298,7 @@ dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg,
        int i;
 
        for (i = 0; i < nents; i++) {
-               dma_cache_sync(page_address(sg[i].page) + sg[i].offset,
+               dma_cache_sync(dev, page_address(sg[i].page) + sg[i].offset,
                               sg[i].length, direction);
        }
 }