]> nv-tegra.nvidia Code Review - linux-2.6.git/commitdiff
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/hskinnemoen...
authorLinus Torvalds <torvalds@woody.linux-foundation.org>
Wed, 18 Jul 2007 19:57:52 +0000 (12:57 -0700)
committerLinus Torvalds <torvalds@woody.linux-foundation.org>
Wed, 18 Jul 2007 19:57:52 +0000 (12:57 -0700)
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/hskinnemoen/avr32-2.6:
  [AVR32] Initialize phy_mask for both macb devices
  [AVR32] Fix atomic_add_unless() and atomic_sub_unless()
  [AVR32] Correct misspelled CONFIG_BLK_DEV_INITRD variable.
  [AVR32] Fix build error in parse_tag_rdimg()
  [AVR32] Don't wire up macb0 unless SW6 is in default position
  [AVR32] Wire up SSC platform device 0 as TX on ATSTK1000 board
  [AVR32] Add Atmel SSC driver platform device to AT32AP architecture
  [AVR32] Remove optimization of unaligned word loads
  [AVR32] Make STK1000 mux settings configurable
  [AVR32] CPU frequency scaling for AT32AP
  [AVR32] Split SM device into PM, RTC, WDT and EIC
  [AVR32] faster avr32 unaligned access

15 files changed:
arch/avr32/Kconfig
arch/avr32/boards/atstk1000/Kconfig [new file with mode: 0644]
arch/avr32/boards/atstk1000/atstk1002.c
arch/avr32/kernel/setup.c
arch/avr32/mach-at32ap/Makefile
arch/avr32/mach-at32ap/at32ap.c
arch/avr32/mach-at32ap/at32ap7000.c
arch/avr32/mach-at32ap/cpufreq.c [new file with mode: 0644]
arch/avr32/mach-at32ap/extint.c
arch/avr32/mach-at32ap/pm.h [new file with mode: 0644]
arch/avr32/mach-at32ap/sm.h [deleted file]
include/asm-avr32/arch-at32ap/board.h
include/asm-avr32/arch-at32ap/sm.h [deleted file]
include/asm-avr32/atomic.h
include/asm-avr32/unaligned.h

index 3ec76586877ef0f462afbd54296d1db0c29ab320..d12346aaa88bdb19a76c54f1bd876657571271fa 100644 (file)
@@ -113,6 +113,10 @@ config BOARD_ATNGW100
        bool "ATNGW100 Network Gateway"
 endchoice
 
+if BOARD_ATSTK1000
+source "arch/avr32/boards/atstk1000/Kconfig"
+endif
+
 choice
        prompt "Boot loader type"
        default LOADER_U_BOOT
@@ -185,6 +189,27 @@ config CMDLINE
 
 endmenu
 
+menu "Power managment options"
+
+menu "CPU Frequency scaling"
+
+source "drivers/cpufreq/Kconfig"
+
+config CPU_FREQ_AT32AP
+       bool "CPU frequency driver for AT32AP"
+       depends on CPU_FREQ && PLATFORM_AT32AP
+       default n
+       help
+         This enables the CPU frequency driver for AT32AP processors.
+
+         For details, take a look in <file:Documentation/cpu-freq>.
+
+         If in doubt, say N.
+
+endmenu
+
+endmenu
+
 menu "Bus options"
 
 config PCI
diff --git a/arch/avr32/boards/atstk1000/Kconfig b/arch/avr32/boards/atstk1000/Kconfig
new file mode 100644 (file)
index 0000000..71bc7d3
--- /dev/null
@@ -0,0 +1,53 @@
+# STK1000 customization
+
+if BOARD_ATSTK1002
+
+config BOARD_ATSTK1002_CUSTOM
+       bool "Non-default STK-1002 jumper settings"
+       help
+         You will normally leave the jumpers on the CPU card at their
+         default settings.  If you need to use certain peripherals,
+         you will need to change some of those jumpers.
+
+if BOARD_ATSTK1002_CUSTOM
+
+config BOARD_ATSTK1002_SW1_CUSTOM
+       bool "SW1: use SSC1 (not SPI0)"
+       help
+         This also prevents using the external DAC as an audio interface,
+         and means you can't initialize the on-board QVGA display.
+
+config BOARD_ATSTK1002_SW2_CUSTOM
+       bool "SW2: use IRDA or TIMER0 (not UART-A, MMC/SD, and PS2-A)"
+       help
+         If you change this you'll want an updated boot loader putting
+         the console on UART-C not UART-A.
+
+config BOARD_ATSTK1002_SW3_CUSTOM
+       bool "SW3: use TIMER1 (not SSC0 and GCLK)"
+       help
+         This also prevents using the external DAC as an audio interface.
+
+config BOARD_ATSTK1002_SW4_CUSTOM
+       bool "SW4: use ISI/Camera (not GPIOs, SPI1, and PS2-B)"
+       help
+         To use the camera interface you'll need a custom card (on the
+         PCI-format connector) connect a video sensor.
+
+config BOARD_ATSTK1002_SW5_CUSTOM
+       bool "SW5: use MACB1 (not LCDC)"
+
+config BOARD_ATSTK1002_SW6_CUSTOM
+       bool "SW6: more GPIOs (not MACB0)"
+
+endif  # custom
+
+config BOARD_ATSTK1002_SPI1
+       bool "Configure SPI1 controller"
+       depends on !BOARD_ATSTK1002_SW4_CUSTOM
+       help
+         All the signals for the second SPI controller are available on
+         GPIO lines and accessed through the J1 jumper block.  Say "y"
+         here to configure that SPI controller.
+
+endif  # stk 1002
index e253e86a1a39205b478a047b33d87fbad974c70d..cb93eabb9c6c4145947df0bda8afaefd0d734340 100644 (file)
 
 #include "atstk1000.h"
 
-#define        SW2_DEFAULT             /* MMCI and UART_A available */
 
 struct eth_addr {
        u8 addr[6];
 };
 
 static struct eth_addr __initdata hw_addr[2];
-static struct eth_platform_data __initdata eth_data[2];
+static struct eth_platform_data __initdata eth_data[2] = {
+       {
+               /*
+                * The MDIO pullups on STK1000 are a bit too weak for
+                * the autodetection to work properly, so we have to
+                * mask out everything but the correct address.
+                */
+               .phy_mask       = ~(1U << 16),
+       },
+       {
+               .phy_mask       = ~(1U << 17),
+       },
+};
 
+#ifndef CONFIG_BOARD_ATSTK1002_SW1_CUSTOM
 static struct spi_board_info spi0_board_info[] __initdata = {
        {
                /* QVGA display */
@@ -45,6 +57,13 @@ static struct spi_board_info spi0_board_info[] __initdata = {
                .mode           = SPI_MODE_3,
        },
 };
+#endif
+
+#ifdef CONFIG_BOARD_ATSTK1002_SPI1
+static struct spi_board_info spi1_board_info[] __initdata = { {
+       /* patch in custom entries here */
+} };
+#endif
 
 /*
  * The next two functions should go away as the boot loader is
@@ -103,10 +122,10 @@ static void __init set_hw_addr(struct platform_device *pdev)
 
 void __init setup_board(void)
 {
-#ifdef SW2_DEFAULT
-       at32_map_usart(1, 0);   /* USART 1/A: /dev/ttyS0, DB9 */
-#else
+#ifdef CONFIG_BOARD_ATSTK1002_SW2_CUSTOM
        at32_map_usart(0, 1);   /* USART 0/B: /dev/ttyS1, IRDA */
+#else
+       at32_map_usart(1, 0);   /* USART 1/A: /dev/ttyS0, DB9 */
 #endif
        /* USART 2/unused: expansion connector */
        at32_map_usart(3, 2);   /* USART 3/C: /dev/ttyS2, DB9 */
@@ -140,18 +159,31 @@ static int __init atstk1002_init(void)
 
        at32_add_system_devices();
 
-#ifdef SW2_DEFAULT
-       at32_add_device_usart(0);
-#else
+#ifdef CONFIG_BOARD_ATSTK1002_SW2_CUSTOM
        at32_add_device_usart(1);
+#else
+       at32_add_device_usart(0);
 #endif
        at32_add_device_usart(2);
 
+#ifndef CONFIG_BOARD_ATSTK1002_SW6_CUSTOM
        set_hw_addr(at32_add_device_eth(0, &eth_data[0]));
-
+#endif
+#ifndef CONFIG_BOARD_ATSTK1002_SW1_CUSTOM
        at32_add_device_spi(0, spi0_board_info, ARRAY_SIZE(spi0_board_info));
+#endif
+#ifdef CONFIG_BOARD_ATSTK1002_SPI1
+       at32_add_device_spi(1, spi1_board_info, ARRAY_SIZE(spi1_board_info));
+#endif
+#ifdef CONFIG_BOARD_ATSTK1002_SW5_CUSTOM
+       set_hw_addr(at32_add_device_eth(1, &eth_data[1]));
+#else
        at32_add_device_lcdc(0, &atstk1000_lcdc_data,
                             fbmem_start, fbmem_size);
+#endif
+#ifndef CONFIG_BOARD_ATSTK1002_SW3_CUSTOM
+       at32_add_device_ssc(0, ATMEL_SSC_TX);
+#endif
 
        return 0;
 }
index b279d66acf5fa09600a3901fa83cfda18d2706a3..d08b0bc6b2bbc31338f9f0cbc2f0e2b1da282ee9 100644 (file)
@@ -313,7 +313,7 @@ __tagtable(ATAG_MEM, parse_tag_mem);
 
 static int __init parse_tag_rdimg(struct tag *tag)
 {
-#ifdef CONFIG_INITRD
+#ifdef CONFIG_BLK_DEV_INITRD
        struct tag_mem_range *mem = &tag->u.mem_range;
        int ret;
 
@@ -323,7 +323,7 @@ static int __init parse_tag_rdimg(struct tag *tag)
                return 0;
        }
 
-       ret = add_reserved_region(mem->start, mem->start + mem->size - 1,
+       ret = add_reserved_region(mem->addr, mem->addr + mem->size - 1,
                                  "initrd");
        if (ret) {
                printk(KERN_WARNING
index f1d395724ac63aed5ba6c6731c07e3aa8ea31e0f..a8b445046e3e3843135f2a1e4c21b93239b79d8b 100644 (file)
@@ -1,3 +1,4 @@
 obj-y                          += at32ap.o clock.o intc.o extint.o pio.o hsmc.o
 obj-$(CONFIG_CPU_AT32AP7000)   += at32ap7000.o
 obj-$(CONFIG_CPU_AT32AP7000)   += time-tc.o
+obj-$(CONFIG_CPU_FREQ_AT32AP)  += cpufreq.o
index 90f207e8e96d809c1e14ac3348e90772e1d87826..7c4987f3287a7ca52d944ee30bc435225bdaac56 100644 (file)
 #include <linux/init.h>
 #include <linux/platform_device.h>
 
-#include <asm/io.h>
-
 #include <asm/arch/init.h>
-#include <asm/arch/sm.h>
-
-struct at32_sm system_manager;
-
-static 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;
-}
 
 void __init setup_platform(void)
 {
-       at32_sm_init();
        at32_clock_init();
        at32_portmux_init();
 }
index 4dda42d3f6d5fdd8c070cbc6d6d2a215d70395b0..64cc5583ddfb0a5feb89669d00ce853055421a68 100644 (file)
 #include <asm/arch/at32ap7000.h>
 #include <asm/arch/board.h>
 #include <asm/arch/portmux.h>
-#include <asm/arch/sm.h>
 
 #include <video/atmel_lcdc.h>
 
 #include "clock.h"
 #include "hmatrix.h"
 #include "pio.h"
-#include "sm.h"
+#include "pm.h"
+
+/*
+ * We can reduce the code size a bit by using a constant here. Since
+ * this file is completely chip-specific, it's safe to not use
+ * ioremap. Generic drivers should of course never do this.
+ */
+#define AT32_PM_BASE   0xfff00000
 
 #define PBMEM(base)                                    \
        {                                               \
@@ -88,6 +94,8 @@ static struct clk devname##_##_name = {                               \
        .index          = _index,                               \
 }
 
+static DEFINE_SPINLOCK(pm_lock);
+
 unsigned long at32ap7000_osc_rates[3] = {
        [0] = 32768,
        /* FIXME: these are ATSTK1002-specific */
@@ -104,11 +112,11 @@ static unsigned long pll_get_rate(struct clk *clk, unsigned long control)
 {
        unsigned long div, mul, rate;
 
-       if (!(control & SM_BIT(PLLEN)))
+       if (!(control & PM_BIT(PLLEN)))
                return 0;
 
-       div = SM_BFEXT(PLLDIV, control) + 1;
-       mul = SM_BFEXT(PLLMUL, control) + 1;
+       div = PM_BFEXT(PLLDIV, control) + 1;
+       mul = PM_BFEXT(PLLMUL, control) + 1;
 
        rate = clk->parent->get_rate(clk->parent);
        rate = (rate + div / 2) / div;
@@ -121,7 +129,7 @@ static unsigned long pll0_get_rate(struct clk *clk)
 {
        u32 control;
 
-       control = sm_readl(&system_manager, PM_PLL0);
+       control = pm_readl(PLL0);
 
        return pll_get_rate(clk, control);
 }
@@ -130,7 +138,7 @@ static unsigned long pll1_get_rate(struct clk *clk)
 {
        u32 control;
 
-       control = sm_readl(&system_manager, PM_PLL1);
+       control = pm_readl(PLL1);
 
        return pll_get_rate(clk, control);
 }
@@ -187,108 +195,139 @@ static unsigned long bus_clk_get_rate(struct clk *clk, unsigned int shift)
 
 static void cpu_clk_mode(struct clk *clk, int enabled)
 {
-       struct at32_sm *sm = &system_manager;
        unsigned long flags;
        u32 mask;
 
-       spin_lock_irqsave(&sm->lock, flags);
-       mask = sm_readl(sm, PM_CPU_MASK);
+       spin_lock_irqsave(&pm_lock, flags);
+       mask = pm_readl(CPU_MASK);
        if (enabled)
                mask |= 1 << clk->index;
        else
                mask &= ~(1 << clk->index);
-       sm_writel(sm, PM_CPU_MASK, mask);
-       spin_unlock_irqrestore(&sm->lock, flags);
+       pm_writel(CPU_MASK, mask);
+       spin_unlock_irqrestore(&pm_lock, flags);
 }
 
 static unsigned long cpu_clk_get_rate(struct clk *clk)
 {
        unsigned long cksel, shift = 0;
 
-       cksel = sm_readl(&system_manager, PM_CKSEL);
-       if (cksel & SM_BIT(CPUDIV))
-               shift = SM_BFEXT(CPUSEL, cksel) + 1;
+       cksel = pm_readl(CKSEL);
+       if (cksel & PM_BIT(CPUDIV))
+               shift = PM_BFEXT(CPUSEL, cksel) + 1;
 
        return bus_clk_get_rate(clk, shift);
 }
 
+static long cpu_clk_set_rate(struct clk *clk, unsigned long rate, int apply)
+{
+       u32 control;
+       unsigned long parent_rate, child_div, actual_rate, div;
+
+       parent_rate = clk->parent->get_rate(clk->parent);
+       control = pm_readl(CKSEL);
+
+       if (control & PM_BIT(HSBDIV))
+               child_div = 1 << (PM_BFEXT(HSBSEL, control) + 1);
+       else
+               child_div = 1;
+
+       if (rate > 3 * (parent_rate / 4) || child_div == 1) {
+               actual_rate = parent_rate;
+               control &= ~PM_BIT(CPUDIV);
+       } else {
+               unsigned int cpusel;
+               div = (parent_rate + rate / 2) / rate;
+               if (div > child_div)
+                       div = child_div;
+               cpusel = (div > 1) ? (fls(div) - 2) : 0;
+               control = PM_BIT(CPUDIV) | PM_BFINS(CPUSEL, cpusel, control);
+               actual_rate = parent_rate / (1 << (cpusel + 1));
+       }
+
+       pr_debug("clk %s: new rate %lu (actual rate %lu)\n",
+                       clk->name, rate, actual_rate);
+
+       if (apply)
+               pm_writel(CKSEL, control);
+
+       return actual_rate;
+}
+
 static void hsb_clk_mode(struct clk *clk, int enabled)
 {
-       struct at32_sm *sm = &system_manager;
        unsigned long flags;
        u32 mask;
 
-       spin_lock_irqsave(&sm->lock, flags);
-       mask = sm_readl(sm, PM_HSB_MASK);
+       spin_lock_irqsave(&pm_lock, flags);
+       mask = pm_readl(HSB_MASK);
        if (enabled)
                mask |= 1 << clk->index;
        else
                mask &= ~(1 << clk->index);
-       sm_writel(sm, PM_HSB_MASK, mask);
-       spin_unlock_irqrestore(&sm->lock, flags);
+       pm_writel(HSB_MASK, mask);
+       spin_unlock_irqrestore(&pm_lock, flags);
 }
 
 static unsigned long hsb_clk_get_rate(struct clk *clk)
 {
        unsigned long cksel, shift = 0;
 
-       cksel = sm_readl(&system_manager, PM_CKSEL);
-       if (cksel & SM_BIT(HSBDIV))
-               shift = SM_BFEXT(HSBSEL, cksel) + 1;
+       cksel = pm_readl(CKSEL);
+       if (cksel & PM_BIT(HSBDIV))
+               shift = PM_BFEXT(HSBSEL, cksel) + 1;
 
        return bus_clk_get_rate(clk, shift);
 }
 
 static void pba_clk_mode(struct clk *clk, int enabled)
 {
-       struct at32_sm *sm = &system_manager;
        unsigned long flags;
        u32 mask;
 
-       spin_lock_irqsave(&sm->lock, flags);
-       mask = sm_readl(sm, PM_PBA_MASK);
+       spin_lock_irqsave(&pm_lock, flags);
+       mask = pm_readl(PBA_MASK);
        if (enabled)
                mask |= 1 << clk->index;
        else
                mask &= ~(1 << clk->index);
-       sm_writel(sm, PM_PBA_MASK, mask);
-       spin_unlock_irqrestore(&sm->lock, flags);
+       pm_writel(PBA_MASK, mask);
+       spin_unlock_irqrestore(&pm_lock, flags);
 }
 
 static unsigned long pba_clk_get_rate(struct clk *clk)
 {
        unsigned long cksel, shift = 0;
 
-       cksel = sm_readl(&system_manager, PM_CKSEL);
-       if (cksel & SM_BIT(PBADIV))
-               shift = SM_BFEXT(PBASEL, cksel) + 1;
+       cksel = pm_readl(CKSEL);
+       if (cksel & PM_BIT(PBADIV))
+               shift = PM_BFEXT(PBASEL, cksel) + 1;
 
        return bus_clk_get_rate(clk, shift);
 }
 
 static void pbb_clk_mode(struct clk *clk, int enabled)
 {
-       struct at32_sm *sm = &system_manager;
        unsigned long flags;
        u32 mask;
 
-       spin_lock_irqsave(&sm->lock, flags);
-       mask = sm_readl(sm, PM_PBB_MASK);
+       spin_lock_irqsave(&pm_lock, flags);
+       mask = pm_readl(PBB_MASK);
        if (enabled)
                mask |= 1 << clk->index;
        else
                mask &= ~(1 << clk->index);
-       sm_writel(sm, PM_PBB_MASK, mask);
-       spin_unlock_irqrestore(&sm->lock, flags);
+       pm_writel(PBB_MASK, mask);
+       spin_unlock_irqrestore(&pm_lock, flags);
 }
 
 static unsigned long pbb_clk_get_rate(struct clk *clk)
 {
        unsigned long cksel, shift = 0;
 
-       cksel = sm_readl(&system_manager, PM_CKSEL);
-       if (cksel & SM_BIT(PBBDIV))
-               shift = SM_BFEXT(PBBSEL, cksel) + 1;
+       cksel = pm_readl(CKSEL);
+       if (cksel & PM_BIT(PBBDIV))
+               shift = PM_BFEXT(PBBSEL, cksel) + 1;
 
        return bus_clk_get_rate(clk, shift);
 }
@@ -296,6 +335,7 @@ static unsigned long pbb_clk_get_rate(struct clk *clk)
 static struct clk cpu_clk = {
        .name           = "cpu",
        .get_rate       = cpu_clk_get_rate,
+       .set_rate       = cpu_clk_set_rate,
        .users          = 1,
 };
 static struct clk hsb_clk = {
@@ -327,12 +367,12 @@ static void genclk_mode(struct clk *clk, int enabled)
 {
        u32 control;
 
-       control = sm_readl(&system_manager, PM_GCCTRL + 4 * clk->index);
+       control = pm_readl(GCCTRL(clk->index));
        if (enabled)
-               control |= SM_BIT(CEN);
+               control |= PM_BIT(CEN);
        else
-               control &= ~SM_BIT(CEN);
-       sm_writel(&system_manager, PM_GCCTRL + 4 * clk->index, control);
+               control &= ~PM_BIT(CEN);
+       pm_writel(GCCTRL(clk->index), control);
 }
 
 static unsigned long genclk_get_rate(struct clk *clk)
@@ -340,9 +380,9 @@ static unsigned long genclk_get_rate(struct clk *clk)
        u32 control;
        unsigned long div = 1;
 
-       control = sm_readl(&system_manager, PM_GCCTRL + 4 * clk->index);
-       if (control & SM_BIT(DIVEN))
-               div = 2 * (SM_BFEXT(DIV, control) + 1);
+       control = pm_readl(GCCTRL(clk->index));
+       if (control & PM_BIT(DIVEN))
+               div = 2 * (PM_BFEXT(DIV, control) + 1);
 
        return clk->parent->get_rate(clk->parent) / div;
 }
@@ -353,23 +393,22 @@ static long genclk_set_rate(struct clk *clk, unsigned long rate, int apply)
        unsigned long parent_rate, actual_rate, div;
 
        parent_rate = clk->parent->get_rate(clk->parent);
-       control = sm_readl(&system_manager, PM_GCCTRL + 4 * clk->index);
+       control = pm_readl(GCCTRL(clk->index));
 
        if (rate > 3 * parent_rate / 4) {
                actual_rate = parent_rate;
-               control &= ~SM_BIT(DIVEN);
+               control &= ~PM_BIT(DIVEN);
        } else {
                div = (parent_rate + rate) / (2 * rate) - 1;
-               control = SM_BFINS(DIV, div, control) | SM_BIT(DIVEN);
+               control = PM_BFINS(DIV, div, control) | PM_BIT(DIVEN);
                actual_rate = parent_rate / (2 * (div + 1));
        }
 
-       printk("clk %s: new rate %lu (actual rate %lu)\n",
-              clk->name, rate, actual_rate);
+       dev_dbg(clk->dev, "clk %s: new rate %lu (actual rate %lu)\n",
+               clk->name, rate, actual_rate);
 
        if (apply)
-               sm_writel(&system_manager, PM_GCCTRL + 4 * clk->index,
-                         control);
+               pm_writel(GCCTRL(clk->index), control);
 
        return actual_rate;
 }
@@ -378,24 +417,24 @@ int genclk_set_parent(struct clk *clk, struct clk *parent)
 {
        u32 control;
 
-       printk("clk %s: new parent %s (was %s)\n",
-              clk->name, parent->name, clk->parent->name);
+       dev_dbg(clk->dev, "clk %s: new parent %s (was %s)\n",
+               clk->name, parent->name, clk->parent->name);
 
-       control = sm_readl(&system_manager, PM_GCCTRL + 4 * clk->index);
+       control = pm_readl(GCCTRL(clk->index));
 
        if (parent == &osc1 || parent == &pll1)
-               control |= SM_BIT(OSCSEL);
+               control |= PM_BIT(OSCSEL);
        else if (parent == &osc0 || parent == &pll0)
-               control &= ~SM_BIT(OSCSEL);
+               control &= ~PM_BIT(OSCSEL);
        else
                return -EINVAL;
 
        if (parent == &pll0 || parent == &pll1)
-               control |= SM_BIT(PLLSEL);
+               control |= PM_BIT(PLLSEL);
        else
-               control &= ~SM_BIT(PLLSEL);
+               control &= ~PM_BIT(PLLSEL);
 
-       sm_writel(&system_manager, PM_GCCTRL + 4 * clk->index, control);
+       pm_writel(GCCTRL(clk->index), control);
        clk->parent = parent;
 
        return 0;
@@ -408,11 +447,11 @@ static void __init genclk_init_parent(struct clk *clk)
 
        BUG_ON(clk->index > 7);
 
-       control = sm_readl(&system_manager, PM_GCCTRL + 4 * clk->index);
-       if (control & SM_BIT(OSCSEL))
-               parent = (control & SM_BIT(PLLSEL)) ? &pll1 : &osc1;
+       control = pm_readl(GCCTRL(clk->index));
+       if (control & PM_BIT(OSCSEL))
+               parent = (control & PM_BIT(PLLSEL)) ? &pll1 : &osc1;
        else
-               parent = (control & SM_BIT(PLLSEL)) ? &pll0 : &osc0;
+               parent = (control & PM_BIT(PLLSEL)) ? &pll0 : &osc0;
 
        clk->parent = parent;
 }
@@ -420,21 +459,53 @@ static void __init genclk_init_parent(struct clk *clk)
 /* --------------------------------------------------------------------
  *  System peripherals
  * -------------------------------------------------------------------- */
-static struct resource sm_resource[] = {
-       PBMEM(0xfff00000),
-       NAMED_IRQ(19, "eim"),
-       NAMED_IRQ(20, "pm"),
-       NAMED_IRQ(21, "rtc"),
+static struct resource at32_pm0_resource[] = {
+       {
+               .start  = 0xfff00000,
+               .end    = 0xfff0007f,
+               .flags  = IORESOURCE_MEM,
+       },
+       IRQ(20),
 };
-struct platform_device at32_sm_device = {
-       .name           = "sm",
-       .id             = 0,
-       .resource       = sm_resource,
-       .num_resources  = ARRAY_SIZE(sm_resource),
+
+static struct resource at32ap700x_rtc0_resource[] = {
+       {
+               .start  = 0xfff00080,
+               .end    = 0xfff000af,
+               .flags  = IORESOURCE_MEM,
+       },
+       IRQ(21),
+};
+
+static struct resource at32_wdt0_resource[] = {
+       {
+               .start  = 0xfff000b0,
+               .end    = 0xfff000bf,
+               .flags  = IORESOURCE_MEM,
+       },
+};
+
+static struct resource at32_eic0_resource[] = {
+       {
+               .start  = 0xfff00100,
+               .end    = 0xfff0013f,
+               .flags  = IORESOURCE_MEM,
+       },
+       IRQ(19),
 };
-static struct clk at32_sm_pclk = {
+
+DEFINE_DEV(at32_pm, 0);
+DEFINE_DEV(at32ap700x_rtc, 0);
+DEFINE_DEV(at32_wdt, 0);
+DEFINE_DEV(at32_eic, 0);
+
+/*
+ * Peripheral clock for PM, RTC, WDT and EIC. PM will ensure that this
+ * is always running.
+ */
+static struct clk at32_pm_pclk = {
        .name           = "pclk",
-       .dev            = &at32_sm_device.dev,
+       .dev            = &at32_pm0_device.dev,
        .parent         = &pbb_clk,
        .mode           = pbb_clk_mode,
        .get_rate       = pbb_clk_get_rate,
@@ -583,10 +654,11 @@ DEV_CLK(mck, pio4, pba, 14);
 
 void __init at32_add_system_devices(void)
 {
-       system_manager.eim_first_irq = EIM_IRQ_BASE;
-
-       platform_device_register(&at32_sm_device);
+       platform_device_register(&at32_pm0_device);
        platform_device_register(&at32_intc0_device);
+       platform_device_register(&at32ap700x_rtc0_device);
+       platform_device_register(&at32_wdt0_device);
+       platform_device_register(&at32_eic0_device);
        platform_device_register(&smc0_device);
        platform_device_register(&pdc_device);
 
@@ -1012,6 +1084,89 @@ err_dup_modedb:
        return NULL;
 }
 
+/* --------------------------------------------------------------------
+ *  SSC
+ * -------------------------------------------------------------------- */
+static struct resource ssc0_resource[] = {
+       PBMEM(0xffe01c00),
+       IRQ(10),
+};
+DEFINE_DEV(ssc, 0);
+DEV_CLK(pclk, ssc0, pba, 7);
+
+static struct resource ssc1_resource[] = {
+       PBMEM(0xffe02000),
+       IRQ(11),
+};
+DEFINE_DEV(ssc, 1);
+DEV_CLK(pclk, ssc1, pba, 8);
+
+static struct resource ssc2_resource[] = {
+       PBMEM(0xffe02400),
+       IRQ(12),
+};
+DEFINE_DEV(ssc, 2);
+DEV_CLK(pclk, ssc2, pba, 9);
+
+struct platform_device *__init
+at32_add_device_ssc(unsigned int id, unsigned int flags)
+{
+       struct platform_device *pdev;
+
+       switch (id) {
+       case 0:
+               pdev = &ssc0_device;
+               if (flags & ATMEL_SSC_RF)
+                       select_peripheral(PA(21), PERIPH_A, 0); /* RF */
+               if (flags & ATMEL_SSC_RK)
+                       select_peripheral(PA(22), PERIPH_A, 0); /* RK */
+               if (flags & ATMEL_SSC_TK)
+                       select_peripheral(PA(23), PERIPH_A, 0); /* TK */
+               if (flags & ATMEL_SSC_TF)
+                       select_peripheral(PA(24), PERIPH_A, 0); /* TF */
+               if (flags & ATMEL_SSC_TD)
+                       select_peripheral(PA(25), PERIPH_A, 0); /* TD */
+               if (flags & ATMEL_SSC_RD)
+                       select_peripheral(PA(26), PERIPH_A, 0); /* RD */
+               break;
+       case 1:
+               pdev = &ssc1_device;
+               if (flags & ATMEL_SSC_RF)
+                       select_peripheral(PA(0), PERIPH_B, 0);  /* RF */
+               if (flags & ATMEL_SSC_RK)
+                       select_peripheral(PA(1), PERIPH_B, 0);  /* RK */
+               if (flags & ATMEL_SSC_TK)
+                       select_peripheral(PA(2), PERIPH_B, 0);  /* TK */
+               if (flags & ATMEL_SSC_TF)
+                       select_peripheral(PA(3), PERIPH_B, 0);  /* TF */
+               if (flags & ATMEL_SSC_TD)
+                       select_peripheral(PA(4), PERIPH_B, 0);  /* TD */
+               if (flags & ATMEL_SSC_RD)
+                       select_peripheral(PA(5), PERIPH_B, 0);  /* RD */
+               break;
+       case 2:
+               pdev = &ssc2_device;
+               if (flags & ATMEL_SSC_TD)
+                       select_peripheral(PB(13), PERIPH_A, 0); /* TD */
+               if (flags & ATMEL_SSC_RD)
+                       select_peripheral(PB(14), PERIPH_A, 0); /* RD */
+               if (flags & ATMEL_SSC_TK)
+                       select_peripheral(PB(15), PERIPH_A, 0); /* TK */
+               if (flags & ATMEL_SSC_TF)
+                       select_peripheral(PB(16), PERIPH_A, 0); /* TF */
+               if (flags & ATMEL_SSC_RF)
+                       select_peripheral(PB(17), PERIPH_A, 0); /* RF */
+               if (flags & ATMEL_SSC_RK)
+                       select_peripheral(PB(18), PERIPH_A, 0); /* RK */
+               break;
+       default:
+               return NULL;
+       }
+
+       platform_device_register(pdev);
+       return pdev;
+}
+
 /* --------------------------------------------------------------------
  *  GCLK
  * -------------------------------------------------------------------- */
@@ -1066,7 +1221,7 @@ struct clk *at32_clock_list[] = {
        &hsb_clk,
        &pba_clk,
        &pbb_clk,
-       &at32_sm_pclk,
+       &at32_pm_pclk,
        &at32_intc0_pclk,
        &hmatrix_clk,
        &ebi_clk,
@@ -1094,6 +1249,9 @@ struct clk *at32_clock_list[] = {
        &atmel_spi1_spi_clk,
        &atmel_lcdfb0_hck1,
        &atmel_lcdfb0_pixclk,
+       &ssc0_pclk,
+       &ssc1_pclk,
+       &ssc2_pclk,
        &gclk0,
        &gclk1,
        &gclk2,
@@ -1113,18 +1271,20 @@ void __init at32_portmux_init(void)
 
 void __init at32_clock_init(void)
 {
-       struct at32_sm *sm = &system_manager;
        u32 cpu_mask = 0, hsb_mask = 0, pba_mask = 0, pbb_mask = 0;
        int i;
 
-       if (sm_readl(sm, PM_MCCTRL) & SM_BIT(PLLSEL))
+       if (pm_readl(MCCTRL) & PM_BIT(PLLSEL)) {
                main_clock = &pll0;
-       else
+               cpu_clk.parent = &pll0;
+       } else {
                main_clock = &osc0;
+               cpu_clk.parent = &osc0;
+       }
 
-       if (sm_readl(sm, PM_PLL0) & SM_BIT(PLLOSC))
+       if (pm_readl(PLL0) & PM_BIT(PLLOSC))
                pll0.parent = &osc1;
-       if (sm_readl(sm, PM_PLL1) & SM_BIT(PLLOSC))
+       if (pm_readl(PLL1) & PM_BIT(PLLOSC))
                pll1.parent = &osc1;
 
        genclk_init_parent(&gclk0);
@@ -1157,8 +1317,8 @@ void __init at32_clock_init(void)
                        pbb_mask |= 1 << clk->index;
        }
 
-       sm_writel(sm, PM_CPU_MASK, cpu_mask);
-       sm_writel(sm, PM_HSB_MASK, hsb_mask);
-       sm_writel(sm, PM_PBA_MASK, pba_mask);
-       sm_writel(sm, PM_PBB_MASK, pbb_mask);
+       pm_writel(CPU_MASK, cpu_mask);
+       pm_writel(HSB_MASK, hsb_mask);
+       pm_writel(PBA_MASK, pba_mask);
+       pm_writel(PBB_MASK, pbb_mask);
 }
diff --git a/arch/avr32/mach-at32ap/cpufreq.c b/arch/avr32/mach-at32ap/cpufreq.c
new file mode 100644 (file)
index 0000000..235524b
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2004-2007 Atmel Corporation
+ *
+ * Based on MIPS implementation arch/mips/kernel/time.c
+ *   Copyright 2001 MontaVista Software Inc.
+ *
+ * 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.
+ */
+
+/*#define DEBUG*/
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/cpufreq.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <asm/system.h>
+
+static struct clk *cpuclk;
+
+static int at32_verify_speed(struct cpufreq_policy *policy)
+{
+       if (policy->cpu != 0)
+               return -EINVAL;
+
+       cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq,
+                       policy->cpuinfo.max_freq);
+       return 0;
+}
+
+static unsigned int at32_get_speed(unsigned int cpu)
+{
+       /* No SMP support */
+       if (cpu)
+               return 0;
+       return (unsigned int)((clk_get_rate(cpuclk) + 500) / 1000);
+}
+
+static int at32_set_target(struct cpufreq_policy *policy,
+                         unsigned int target_freq,
+                         unsigned int relation)
+{
+       struct cpufreq_freqs freqs;
+       long freq;
+
+       /* Convert target_freq from kHz to Hz */
+       freq = clk_round_rate(cpuclk, target_freq * 1000);
+
+       /* Check if policy->min <= new_freq <= policy->max */
+       if(freq < (policy->min * 1000) || freq > (policy->max * 1000))
+               return -EINVAL;
+
+       pr_debug("cpufreq: requested frequency %u Hz\n", target_freq * 1000);
+
+       freqs.old = at32_get_speed(0);
+       freqs.new = (freq + 500) / 1000;
+       freqs.cpu = 0;
+       freqs.flags = 0;
+
+       cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+       clk_set_rate(cpuclk, freq);
+       cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+
+       pr_debug("cpufreq: set frequency %lu Hz\n", freq);
+
+       return 0;
+}
+
+static int __init at32_cpufreq_driver_init(struct cpufreq_policy *policy)
+{
+       if (policy->cpu != 0)
+               return -EINVAL;
+
+       cpuclk = clk_get(NULL, "cpu");
+       if (IS_ERR(cpuclk)) {
+               pr_debug("cpufreq: could not get CPU clk\n");
+               return PTR_ERR(cpuclk);
+       }
+
+       policy->cpuinfo.min_freq = (clk_round_rate(cpuclk, 1) + 500) / 1000;
+       policy->cpuinfo.max_freq = (clk_round_rate(cpuclk, ~0UL) + 500) / 1000;
+       policy->cpuinfo.transition_latency = 0;
+       policy->cur = at32_get_speed(0);
+       policy->min = policy->cpuinfo.min_freq;
+       policy->max = policy->cpuinfo.max_freq;
+       policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
+
+       printk("cpufreq: AT32AP CPU frequency driver\n");
+
+       return 0;
+}
+
+static struct cpufreq_driver at32_driver = {
+       .name           = "at32ap",
+       .owner          = THIS_MODULE,
+       .init           = at32_cpufreq_driver_init,
+       .verify         = at32_verify_speed,
+       .target         = at32_set_target,
+       .get            = at32_get_speed,
+       .flags          = CPUFREQ_STICKY,
+};
+
+static int __init at32_cpufreq_init(void)
+{
+       return cpufreq_register_driver(&at32_driver);
+}
+
+arch_initcall(at32_cpufreq_init);
index 4a60eccfebd240762e751a3c43bd4191cb5fe714..8acd010900313af2194ea5652be7c5abde1b83bd 100644 (file)
 
 #include <asm/io.h>
 
-#include <asm/arch/sm.h>
-
-#include "sm.h"
+/* EIC register offsets */
+#define EIC_IER                                        0x0000
+#define EIC_IDR                                        0x0004
+#define EIC_IMR                                        0x0008
+#define EIC_ISR                                        0x000c
+#define EIC_ICR                                        0x0010
+#define EIC_MODE                               0x0014
+#define EIC_EDGE                               0x0018
+#define EIC_LEVEL                              0x001c
+#define EIC_TEST                               0x0020
+#define EIC_NMIC                               0x0024
+
+/* Bitfields in TEST */
+#define EIC_TESTEN_OFFSET                      31
+#define EIC_TESTEN_SIZE                                1
+
+/* Bitfields in NMIC */
+#define EIC_EN_OFFSET                          0
+#define EIC_EN_SIZE                            1
+
+/* Bit manipulation macros */
+#define EIC_BIT(name)                                  \
+       (1 << EIC_##name##_OFFSET)
+#define EIC_BF(name,value)                             \
+       (((value) & ((1 << EIC_##name##_SIZE) - 1))     \
+        << EIC_##name##_OFFSET)
+#define EIC_BFEXT(name,value)                          \
+       (((value) >> EIC_##name##_OFFSET)               \
+        & ((1 << EIC_##name##_SIZE) - 1))
+#define EIC_BFINS(name,value,old)                      \
+       (((old) & ~(((1 << EIC_##name##_SIZE) - 1)      \
+                   << EIC_##name##_OFFSET))            \
+        | EIC_BF(name,value))
+
+/* Register access macros */
+#define eic_readl(port,reg)                            \
+       __raw_readl((port)->regs + EIC_##reg)
+#define eic_writel(port,reg,value)                     \
+       __raw_writel((value), (port)->regs + EIC_##reg)
+
+struct eic {
+       void __iomem *regs;
+       struct irq_chip *chip;
+       unsigned int first_irq;
+};
 
-static void eim_ack_irq(unsigned int irq)
+static void eic_ack_irq(unsigned int irq)
 {
-       struct at32_sm *sm = get_irq_chip_data(irq);
-       sm_writel(sm, EIM_ICR, 1 << (irq - sm->eim_first_irq));
+       struct eic *eic = get_irq_chip_data(irq);
+       eic_writel(eic, ICR, 1 << (irq - eic->first_irq));
 }
 
-static void eim_mask_irq(unsigned int irq)
+static void eic_mask_irq(unsigned int irq)
 {
-       struct at32_sm *sm = get_irq_chip_data(irq);
-       sm_writel(sm, EIM_IDR, 1 << (irq - sm->eim_first_irq));
+       struct eic *eic = get_irq_chip_data(irq);
+       eic_writel(eic, IDR, 1 << (irq - eic->first_irq));
 }
 
-static void eim_mask_ack_irq(unsigned int irq)
+static void eic_mask_ack_irq(unsigned int irq)
 {
-       struct at32_sm *sm = get_irq_chip_data(irq);
-       sm_writel(sm, EIM_ICR, 1 << (irq - sm->eim_first_irq));
-       sm_writel(sm, EIM_IDR, 1 << (irq - sm->eim_first_irq));
+       struct eic *eic = get_irq_chip_data(irq);
+       eic_writel(eic, ICR, 1 << (irq - eic->first_irq));
+       eic_writel(eic, IDR, 1 << (irq - eic->first_irq));
 }
 
-static void eim_unmask_irq(unsigned int irq)
+static void eic_unmask_irq(unsigned int irq)
 {
-       struct at32_sm *sm = get_irq_chip_data(irq);
-       sm_writel(sm, EIM_IER, 1 << (irq - sm->eim_first_irq));
+       struct eic *eic = get_irq_chip_data(irq);
+       eic_writel(eic, IER, 1 << (irq - eic->first_irq));
 }
 
-static int eim_set_irq_type(unsigned int irq, unsigned int flow_type)
+static int eic_set_irq_type(unsigned int irq, unsigned int flow_type)
 {
-       struct at32_sm *sm = get_irq_chip_data(irq);
+       struct eic *eic = get_irq_chip_data(irq);
        struct irq_desc *desc;
-       unsigned int i = irq - sm->eim_first_irq;
+       unsigned int i = irq - eic->first_irq;
        u32 mode, edge, level;
-       unsigned long flags;
        int ret = 0;
 
        flow_type &= IRQ_TYPE_SENSE_MASK;
@@ -60,11 +101,10 @@ static int eim_set_irq_type(unsigned int irq, unsigned int flow_type)
                flow_type = IRQ_TYPE_LEVEL_LOW;
 
        desc = &irq_desc[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);
+       mode = eic_readl(eic, MODE);
+       edge = eic_readl(eic, EDGE);
+       level = eic_readl(eic, LEVEL);
 
        switch (flow_type) {
        case IRQ_TYPE_LEVEL_LOW:
@@ -89,9 +129,9 @@ static int eim_set_irq_type(unsigned int irq, unsigned int flow_type)
        }
 
        if (ret == 0) {
-               sm_writel(sm, EIM_MODE, mode);
-               sm_writel(sm, EIM_EDGE, edge);
-               sm_writel(sm, EIM_LEVEL, level);
+               eic_writel(eic, MODE, mode);
+               eic_writel(eic, EDGE, edge);
+               eic_writel(eic, LEVEL, level);
 
                if (flow_type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
                        flow_type |= IRQ_LEVEL;
@@ -99,35 +139,33 @@ static int eim_set_irq_type(unsigned int irq, unsigned int flow_type)
                desc->status |= flow_type;
        }
 
-       spin_unlock_irqrestore(&sm->lock, flags);
-
        return ret;
 }
 
-struct irq_chip eim_chip = {
-       .name           = "eim",
-       .ack            = eim_ack_irq,
-       .mask           = eim_mask_irq,
-       .mask_ack       = eim_mask_ack_irq,
-       .unmask         = eim_unmask_irq,
-       .set_type       = eim_set_irq_type,
+struct irq_chip eic_chip = {
+       .name           = "eic",
+       .ack            = eic_ack_irq,
+       .mask           = eic_mask_irq,
+       .mask_ack       = eic_mask_ack_irq,
+       .unmask         = eic_unmask_irq,
+       .set_type       = eic_set_irq_type,
 };
 
-static void demux_eim_irq(unsigned int irq, struct irq_desc *desc)
+static void demux_eic_irq(unsigned int irq, struct irq_desc *desc)
 {
-       struct at32_sm *sm = desc->handler_data;
+       struct eic *eic = desc->handler_data;
        struct irq_desc *ext_desc;
        unsigned long status, pending;
        unsigned int i, ext_irq;
 
-       status = sm_readl(sm, EIM_ISR);
-       pending = status & sm_readl(sm, EIM_IMR);
+       status = eic_readl(eic, ISR);
+       pending = status & eic_readl(eic, IMR);
 
        while (pending) {
                i = fls(pending) - 1;
                pending &= ~(1 << i);
 
-               ext_irq = i + sm->eim_first_irq;
+               ext_irq = i + eic->first_irq;
                ext_desc = irq_desc + ext_irq;
                if (ext_desc->status & IRQ_LEVEL)
                        handle_level_irq(ext_irq, ext_desc);
@@ -136,51 +174,85 @@ static void demux_eim_irq(unsigned int irq, struct irq_desc *desc)
        }
 }
 
-static int __init eim_init(void)
+static int __init eic_probe(struct platform_device *pdev)
 {
-       struct at32_sm *sm = &system_manager;
+       struct eic *eic;
+       struct resource *regs;
        unsigned int i;
        unsigned int nr_irqs;
        unsigned int int_irq;
+       int ret;
        u32 pattern;
 
-       /*
-        * The EIM is really the same module as SM, so register
-        * mapping, etc. has been taken care of already.
-        */
+       regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       int_irq = platform_get_irq(pdev, 0);
+       if (!regs || !int_irq) {
+               dev_dbg(&pdev->dev, "missing regs and/or irq resource\n");
+               return -ENXIO;
+       }
+
+       ret = -ENOMEM;
+       eic = kzalloc(sizeof(struct eic), GFP_KERNEL);
+       if (!eic) {
+               dev_dbg(&pdev->dev, "no memory for eic structure\n");
+               goto err_kzalloc;
+       }
+
+       eic->first_irq = EIM_IRQ_BASE + 32 * pdev->id;
+       eic->regs = ioremap(regs->start, regs->end - regs->start + 1);
+       if (!eic->regs) {
+               dev_dbg(&pdev->dev, "failed to map regs\n");
+               goto err_ioremap;
+       }
 
        /*
         * 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);
+       eic_writel(eic, IDR, ~0UL);
+       eic_writel(eic, MODE, ~0UL);
+       pattern = eic_readl(eic, 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);
+       eic_writel(eic, MODE, 0UL);
+       eic_writel(eic, EDGE, 0UL);
 
-       sm->eim_chip = &eim_chip;
+       eic->chip = &eic_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,
+               set_irq_chip_and_handler(eic->first_irq + i, &eic_chip,
                                         handle_level_irq);
-               set_irq_chip_data(sm->eim_first_irq + i, sm);
+               set_irq_chip_data(eic->first_irq + i, eic);
        }
 
-       int_irq = platform_get_irq_byname(sm->pdev, "eim");
-
-       set_irq_chained_handler(int_irq, demux_eim_irq);
-       set_irq_data(int_irq, sm);
+       set_irq_chained_handler(int_irq, demux_eic_irq);
+       set_irq_data(int_irq, eic);
 
-       printk("EIM: External Interrupt Module at 0x%p, IRQ %u\n",
-              sm->regs, int_irq);
-       printk("EIM: Handling %u external IRQs, starting with IRQ %u\n",
-              nr_irqs, sm->eim_first_irq);
+       dev_info(&pdev->dev,
+                "External Interrupt Controller at 0x%p, IRQ %u\n",
+                eic->regs, int_irq);
+       dev_info(&pdev->dev,
+                "Handling %u external IRQs, starting with IRQ %u\n",
+                nr_irqs, eic->first_irq);
 
        return 0;
+
+err_ioremap:
+       kfree(eic);
+err_kzalloc:
+       return ret;
+}
+
+static struct platform_driver eic_driver = {
+       .driver = {
+               .name = "at32_eic",
+       },
+};
+
+static int __init eic_init(void)
+{
+       return platform_driver_probe(&eic_driver, eic_probe);
 }
-arch_initcall(eim_init);
+arch_initcall(eic_init);
diff --git a/arch/avr32/mach-at32ap/pm.h b/arch/avr32/mach-at32ap/pm.h
new file mode 100644 (file)
index 0000000..a1f8ace
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * Register definitions for the Power Manager (PM)
+ */
+#ifndef __ARCH_AVR32_MACH_AT32AP_PM_H__
+#define __ARCH_AVR32_MACH_AT32AP_PM_H__
+
+/* PM register offsets */
+#define PM_MCCTRL                              0x0000
+#define PM_CKSEL                               0x0004
+#define PM_CPU_MASK                            0x0008
+#define PM_HSB_MASK                            0x000c
+#define PM_PBA_MASK                            0x0010
+#define PM_PBB_MASK                            0x0014
+#define PM_PLL0                                        0x0020
+#define PM_PLL1                                        0x0024
+#define PM_IER                                 0x0040
+#define PM_IDR                                 0x0044
+#define PM_IMR                                 0x0048
+#define PM_ISR                                 0x004c
+#define PM_ICR                                 0x0050
+#define PM_GCCTRL(x)                           (0x0060 + 4 * (x))
+#define PM_RCAUSE                              0x00c0
+
+/* Bitfields in CKSEL */
+#define PM_CPUSEL_OFFSET                       0
+#define PM_CPUSEL_SIZE                         3
+#define PM_CPUDIV_OFFSET                       7
+#define PM_CPUDIV_SIZE                         1
+#define PM_HSBSEL_OFFSET                       8
+#define PM_HSBSEL_SIZE                         3
+#define PM_HSBDIV_OFFSET                       15
+#define PM_HSBDIV_SIZE                         1
+#define PM_PBASEL_OFFSET                       16
+#define PM_PBASEL_SIZE                         3
+#define PM_PBADIV_OFFSET                       23
+#define PM_PBADIV_SIZE                         1
+#define PM_PBBSEL_OFFSET                       24
+#define PM_PBBSEL_SIZE                         3
+#define PM_PBBDIV_OFFSET                       31
+#define PM_PBBDIV_SIZE                         1
+
+/* Bitfields in PLL0 */
+#define PM_PLLEN_OFFSET                                0
+#define PM_PLLEN_SIZE                          1
+#define PM_PLLOSC_OFFSET                       1
+#define PM_PLLOSC_SIZE                         1
+#define PM_PLLOPT_OFFSET                       2
+#define PM_PLLOPT_SIZE                         3
+#define PM_PLLDIV_OFFSET                       8
+#define PM_PLLDIV_SIZE                         8
+#define PM_PLLMUL_OFFSET                       16
+#define PM_PLLMUL_SIZE                         8
+#define PM_PLLCOUNT_OFFSET                     24
+#define PM_PLLCOUNT_SIZE                       6
+#define PM_PLLTEST_OFFSET                      31
+#define PM_PLLTEST_SIZE                                1
+
+/* Bitfields in ICR */
+#define PM_LOCK0_OFFSET                                0
+#define PM_LOCK0_SIZE                          1
+#define PM_LOCK1_OFFSET                                1
+#define PM_LOCK1_SIZE                          1
+#define PM_WAKE_OFFSET                         2
+#define PM_WAKE_SIZE                           1
+#define PM_CKRDY_OFFSET                                5
+#define PM_CKRDY_SIZE                          1
+#define PM_MSKRDY_OFFSET                       6
+#define PM_MSKRDY_SIZE                         1
+
+/* Bitfields in GCCTRL0 */
+#define PM_OSCSEL_OFFSET                       0
+#define PM_OSCSEL_SIZE                         1
+#define PM_PLLSEL_OFFSET                       1
+#define PM_PLLSEL_SIZE                         1
+#define PM_CEN_OFFSET                          2
+#define PM_CEN_SIZE                            1
+#define PM_DIVEN_OFFSET                                4
+#define PM_DIVEN_SIZE                          1
+#define PM_DIV_OFFSET                          8
+#define PM_DIV_SIZE                            8
+
+/* Bitfields in RCAUSE */
+#define PM_POR_OFFSET                          0
+#define PM_POR_SIZE                            1
+#define PM_EXT_OFFSET                          2
+#define PM_EXT_SIZE                            1
+#define PM_WDT_OFFSET                          3
+#define PM_WDT_SIZE                            1
+#define PM_NTAE_OFFSET                         4
+#define PM_NTAE_SIZE                           1
+
+/* Bit manipulation macros */
+#define PM_BIT(name)                                   \
+       (1 << PM_##name##_OFFSET)
+#define PM_BF(name,value)                              \
+       (((value) & ((1 << PM_##name##_SIZE) - 1))      \
+        << PM_##name##_OFFSET)
+#define PM_BFEXT(name,value)                           \
+       (((value) >> PM_##name##_OFFSET)                \
+        & ((1 << PM_##name##_SIZE) - 1))
+#define PM_BFINS(name,value,old)\
+       (((old) & ~(((1 << PM_##name##_SIZE) - 1)       \
+                   << PM_##name##_OFFSET))             \
+        | PM_BF(name,value))
+
+/* Register access macros */
+#define pm_readl(reg)                                                  \
+       __raw_readl((void __iomem *)AT32_PM_BASE + PM_##reg)
+#define pm_writel(reg,value)                                           \
+       __raw_writel((value), (void __iomem *)AT32_PM_BASE + PM_##reg)
+
+#endif /* __ARCH_AVR32_MACH_AT32AP_PM_H__ */
diff --git a/arch/avr32/mach-at32ap/sm.h b/arch/avr32/mach-at32ap/sm.h
deleted file mode 100644 (file)
index cad02b5..0000000
+++ /dev/null
@@ -1,242 +0,0 @@
-/*
- * Register definitions for SM
- *
- * System Manager
- */
-#ifndef __ASM_AVR32_SM_H__
-#define __ASM_AVR32_SM_H__
-
-/* SM register offsets */
-#define SM_PM_MCCTRL                            0x0000
-#define SM_PM_CKSEL                             0x0004
-#define SM_PM_CPU_MASK                          0x0008
-#define SM_PM_HSB_MASK                          0x000c
-#define SM_PM_PBA_MASK                         0x0010
-#define SM_PM_PBB_MASK                         0x0014
-#define SM_PM_PLL0                              0x0020
-#define SM_PM_PLL1                              0x0024
-#define SM_PM_VCTRL                             0x0030
-#define SM_PM_VMREF                             0x0034
-#define SM_PM_VMV                               0x0038
-#define SM_PM_IER                               0x0040
-#define SM_PM_IDR                               0x0044
-#define SM_PM_IMR                               0x0048
-#define SM_PM_ISR                               0x004c
-#define SM_PM_ICR                               0x0050
-#define SM_PM_GCCTRL                            0x0060
-#define SM_RTC_CTRL                             0x0080
-#define SM_RTC_VAL                              0x0084
-#define SM_RTC_TOP                              0x0088
-#define SM_RTC_IER                              0x0090
-#define SM_RTC_IDR                              0x0094
-#define SM_RTC_IMR                              0x0098
-#define SM_RTC_ISR                              0x009c
-#define SM_RTC_ICR                              0x00a0
-#define SM_WDT_CTRL                             0x00b0
-#define SM_WDT_CLR                              0x00b4
-#define SM_WDT_EXT                              0x00b8
-#define SM_RC_RCAUSE                            0x00c0
-#define SM_EIM_IER                              0x0100
-#define SM_EIM_IDR                              0x0104
-#define SM_EIM_IMR                              0x0108
-#define SM_EIM_ISR                              0x010c
-#define SM_EIM_ICR                              0x0110
-#define SM_EIM_MODE                             0x0114
-#define SM_EIM_EDGE                             0x0118
-#define SM_EIM_LEVEL                            0x011c
-#define SM_EIM_TEST                             0x0120
-#define SM_EIM_NMIC                             0x0124
-
-/* Bitfields in PM_MCCTRL */
-
-/* Bitfields in PM_CKSEL */
-#define SM_CPUSEL_OFFSET                        0
-#define SM_CPUSEL_SIZE                          3
-#define SM_CPUDIV_OFFSET                        7
-#define SM_CPUDIV_SIZE                          1
-#define SM_HSBSEL_OFFSET                        8
-#define SM_HSBSEL_SIZE                          3
-#define SM_HSBDIV_OFFSET                        15
-#define SM_HSBDIV_SIZE                          1
-#define SM_PBASEL_OFFSET                       16
-#define SM_PBASEL_SIZE                         3
-#define SM_PBADIV_OFFSET                       23
-#define SM_PBADIV_SIZE                         1
-#define SM_PBBSEL_OFFSET                       24
-#define SM_PBBSEL_SIZE                         3
-#define SM_PBBDIV_OFFSET                       31
-#define SM_PBBDIV_SIZE                         1
-
-/* Bitfields in PM_CPU_MASK */
-
-/* Bitfields in PM_HSB_MASK */
-
-/* Bitfields in PM_PBA_MASK */
-
-/* Bitfields in PM_PBB_MASK */
-
-/* Bitfields in PM_PLL0 */
-#define SM_PLLEN_OFFSET                         0
-#define SM_PLLEN_SIZE                           1
-#define SM_PLLOSC_OFFSET                        1
-#define SM_PLLOSC_SIZE                          1
-#define SM_PLLOPT_OFFSET                        2
-#define SM_PLLOPT_SIZE                          3
-#define SM_PLLDIV_OFFSET                        8
-#define SM_PLLDIV_SIZE                          8
-#define SM_PLLMUL_OFFSET                        16
-#define SM_PLLMUL_SIZE                          8
-#define SM_PLLCOUNT_OFFSET                      24
-#define SM_PLLCOUNT_SIZE                        6
-#define SM_PLLTEST_OFFSET                       31
-#define SM_PLLTEST_SIZE                         1
-
-/* Bitfields in PM_PLL1 */
-
-/* Bitfields in PM_VCTRL */
-#define SM_VAUTO_OFFSET                         0
-#define SM_VAUTO_SIZE                           1
-#define SM_PM_VCTRL_VAL_OFFSET                  8
-#define SM_PM_VCTRL_VAL_SIZE                    7
-
-/* Bitfields in PM_VMREF */
-#define SM_REFSEL_OFFSET                        0
-#define SM_REFSEL_SIZE                          4
-
-/* Bitfields in PM_VMV */
-#define SM_PM_VMV_VAL_OFFSET                    0
-#define SM_PM_VMV_VAL_SIZE                      8
-
-/* Bitfields in PM_IER */
-
-/* Bitfields in PM_IDR */
-
-/* Bitfields in PM_IMR */
-
-/* Bitfields in PM_ISR */
-
-/* Bitfields in PM_ICR */
-#define SM_LOCK0_OFFSET                         0
-#define SM_LOCK0_SIZE                           1
-#define SM_LOCK1_OFFSET                         1
-#define SM_LOCK1_SIZE                           1
-#define SM_WAKE_OFFSET                          2
-#define SM_WAKE_SIZE                            1
-#define SM_VOK_OFFSET                           3
-#define SM_VOK_SIZE                             1
-#define SM_VMRDY_OFFSET                         4
-#define SM_VMRDY_SIZE                           1
-#define SM_CKRDY_OFFSET                         5
-#define SM_CKRDY_SIZE                           1
-
-/* Bitfields in PM_GCCTRL */
-#define SM_OSCSEL_OFFSET                        0
-#define SM_OSCSEL_SIZE                          1
-#define SM_PLLSEL_OFFSET                        1
-#define SM_PLLSEL_SIZE                          1
-#define SM_CEN_OFFSET                           2
-#define SM_CEN_SIZE                             1
-#define SM_CPC_OFFSET                           3
-#define SM_CPC_SIZE                             1
-#define SM_DIVEN_OFFSET                         4
-#define SM_DIVEN_SIZE                           1
-#define SM_DIV_OFFSET                           8
-#define SM_DIV_SIZE                             8
-
-/* Bitfields in RTC_CTRL */
-#define SM_PCLR_OFFSET                          1
-#define SM_PCLR_SIZE                            1
-#define SM_TOPEN_OFFSET                         2
-#define SM_TOPEN_SIZE                           1
-#define SM_CLKEN_OFFSET                         3
-#define SM_CLKEN_SIZE                           1
-#define SM_PSEL_OFFSET                          8
-#define SM_PSEL_SIZE                            16
-
-/* Bitfields in RTC_VAL */
-#define SM_RTC_VAL_VAL_OFFSET                   0
-#define SM_RTC_VAL_VAL_SIZE                     31
-
-/* Bitfields in RTC_TOP */
-#define SM_RTC_TOP_VAL_OFFSET                   0
-#define SM_RTC_TOP_VAL_SIZE                     32
-
-/* Bitfields in RTC_IER */
-
-/* Bitfields in RTC_IDR */
-
-/* Bitfields in RTC_IMR */
-
-/* Bitfields in RTC_ISR */
-
-/* Bitfields in RTC_ICR */
-#define SM_TOPI_OFFSET                          0
-#define SM_TOPI_SIZE                            1
-
-/* Bitfields in WDT_CTRL */
-#define SM_KEY_OFFSET                           24
-#define SM_KEY_SIZE                             8
-
-/* Bitfields in WDT_CLR */
-
-/* Bitfields in WDT_EXT */
-
-/* Bitfields in RC_RCAUSE */
-#define SM_POR_OFFSET                           0
-#define SM_POR_SIZE                             1
-#define SM_BOD_OFFSET                           1
-#define SM_BOD_SIZE                             1
-#define SM_EXT_OFFSET                           2
-#define SM_EXT_SIZE                             1
-#define SM_WDT_OFFSET                           3
-#define SM_WDT_SIZE                             1
-#define SM_NTAE_OFFSET                          4
-#define SM_NTAE_SIZE                            1
-#define SM_SERP_OFFSET                          5
-#define SM_SERP_SIZE                            1
-
-/* Bitfields in EIM_IER */
-
-/* Bitfields in EIM_IDR */
-
-/* Bitfields in EIM_IMR */
-
-/* Bitfields in EIM_ISR */
-
-/* Bitfields in EIM_ICR */
-
-/* Bitfields in EIM_MODE */
-
-/* Bitfields in EIM_EDGE */
-#define SM_INT0_OFFSET                          0
-#define SM_INT0_SIZE                            1
-#define SM_INT1_OFFSET                          1
-#define SM_INT1_SIZE                            1
-#define SM_INT2_OFFSET                          2
-#define SM_INT2_SIZE                            1
-#define SM_INT3_OFFSET                          3
-#define SM_INT3_SIZE                            1
-
-/* Bitfields in EIM_LEVEL */
-
-/* Bitfields in EIM_TEST */
-#define SM_TESTEN_OFFSET                        31
-#define SM_TESTEN_SIZE                          1
-
-/* Bitfields in EIM_NMIC */
-#define SM_EN_OFFSET                            0
-#define SM_EN_SIZE                              1
-
-/* Bit manipulation macros */
-#define SM_BIT(name)                            (1 << SM_##name##_OFFSET)
-#define SM_BF(name,value)                       (((value) & ((1 << SM_##name##_SIZE) - 1)) << SM_##name##_OFFSET)
-#define SM_BFEXT(name,value)                    (((value) >> SM_##name##_OFFSET) & ((1 << SM_##name##_SIZE) - 1))
-#define SM_BFINS(name,value,old)                (((old) & ~(((1 << SM_##name##_SIZE) - 1) << SM_##name##_OFFSET)) | SM_BF(name,value))
-
-/* Register access macros */
-#define sm_readl(port,reg)                                     \
-       __raw_readl((port)->regs + SM_##reg)
-#define sm_writel(port,reg,value)                              \
-       __raw_writel((value), (port)->regs + SM_##reg)
-
-#endif /* __ASM_AVR32_SM_H__ */
index 9744804388494aec75a26ac8ecc54c71c1183d28..0215965dc586d4db7037299ef56e735e9cb5a0b4 100644 (file)
@@ -36,4 +36,18 @@ struct platform_device *
 at32_add_device_lcdc(unsigned int id, struct atmel_lcdfb_info *data,
                     unsigned long fbmem_start, unsigned long fbmem_len);
 
+/* depending on what's hooked up, not all SSC pins will be used */
+#define        ATMEL_SSC_TK            0x01
+#define        ATMEL_SSC_TF            0x02
+#define        ATMEL_SSC_TD            0x04
+#define        ATMEL_SSC_TX            (ATMEL_SSC_TK | ATMEL_SSC_TF | ATMEL_SSC_TD)
+
+#define        ATMEL_SSC_RK            0x10
+#define        ATMEL_SSC_RF            0x20
+#define        ATMEL_SSC_RD            0x40
+#define        ATMEL_SSC_RX            (ATMEL_SSC_RK | ATMEL_SSC_RF | ATMEL_SSC_RD)
+
+struct platform_device *
+at32_add_device_ssc(unsigned int id, unsigned int flags);
+
 #endif /* __ASM_ARCH_BOARD_H */
diff --git a/include/asm-avr32/arch-at32ap/sm.h b/include/asm-avr32/arch-at32ap/sm.h
deleted file mode 100644 (file)
index 265a9ea..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * AT32 System Manager interface.
- *
- * 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_AVR32_AT32_SM_H__
-#define __ASM_AVR32_AT32_SM_H__
-
-struct irq_chip;
-struct platform_device;
-
-struct at32_sm {
-       spinlock_t lock;
-       void __iomem *regs;
-       struct irq_chip *eim_chip;
-       unsigned int eim_first_irq;
-       struct platform_device *pdev;
-};
-
-extern struct platform_device at32_sm_device;
-extern struct at32_sm system_manager;
-
-#endif /* __ASM_AVR32_AT32_SM_H__ */
index b9c2548a52f33d0807add5872424f88cc6342967..7ef3862a73d02443d95eaf6520ff45417f3f00d5 100644 (file)
@@ -101,7 +101,7 @@ static inline int atomic_sub_unless(atomic_t *v, int a, int u)
                "       mov     %1, 1\n"
                "1:"
                : "=&r"(tmp), "=&r"(result), "=o"(v->counter)
-               : "m"(v->counter), "rKs21"(a), "rKs21"(u)
+               : "m"(v->counter), "rKs21"(a), "rKs21"(u), "1"(result)
                : "cc", "memory");
 
        return result;
@@ -137,7 +137,7 @@ static inline int atomic_add_unless(atomic_t *v, int a, int u)
                        "       mov     %1, 1\n"
                        "1:"
                        : "=&r"(tmp), "=&r"(result), "=o"(v->counter)
-                       : "m"(v->counter), "r"(a), "ir"(u)
+                       : "m"(v->counter), "r"(a), "ir"(u), "1"(result)
                        : "cc", "memory");
        }
 
index 3042723fcbfd69b267ba8e8216be5d7090cb771c..36f5fd430543ec5d088335f52d357d58e7c75ea7 100644 (file)
@@ -7,19 +7,10 @@
  * words, but halfwords must be halfword-aligned, and doublewords must
  * be word-aligned.
  *
- * TODO: Make all this CPU-specific and optimize.
+ * However, swapped word loads must be word-aligned so we can't
+ * optimize word loads in general.
  */
 
-#include <linux/string.h>
-
-/* Use memmove here, so gcc does not insert a __builtin_memcpy. */
-
-#define get_unaligned(ptr) \
-  ({ __typeof__(*(ptr)) __tmp; memmove(&__tmp, (ptr), sizeof(*(ptr))); __tmp; })
-
-#define put_unaligned(val, ptr)                                \
-  ({ __typeof__(*(ptr)) __tmp = (val);                 \
-     memmove((ptr), &__tmp, sizeof(*(ptr)));           \
-     (void)0; })
+#include <asm-generic/unaligned.h>
 
 #endif /* __ASM_AVR32_UNALIGNED_H */