summaryrefslogtreecommitdiffstats
path: root/arch/avr32/mach-at32ap
diff options
context:
space:
mode:
Diffstat (limited to 'arch/avr32/mach-at32ap')
-rw-r--r--arch/avr32/mach-at32ap/Makefile8
-rw-r--r--arch/avr32/mach-at32ap/at32ap700x.c707
-rw-r--r--arch/avr32/mach-at32ap/clock.c54
-rw-r--r--arch/avr32/mach-at32ap/clock.h8
-rw-r--r--arch/avr32/mach-at32ap/hmatrix.c88
-rw-r--r--arch/avr32/mach-at32ap/hmatrix.h182
-rw-r--r--arch/avr32/mach-at32ap/hsmc.c4
-rw-r--r--arch/avr32/mach-at32ap/include/mach/at32ap700x.h214
-rw-r--r--arch/avr32/mach-at32ap/include/mach/board.h121
-rw-r--r--arch/avr32/mach-at32ap/include/mach/chip.h19
-rw-r--r--arch/avr32/mach-at32ap/include/mach/cpu.h35
-rw-r--r--arch/avr32/mach-at32ap/include/mach/gpio.h45
-rw-r--r--arch/avr32/mach-at32ap/include/mach/hmatrix.h55
-rw-r--r--arch/avr32/mach-at32ap/include/mach/init.h18
-rw-r--r--arch/avr32/mach-at32ap/include/mach/io.h38
-rw-r--r--arch/avr32/mach-at32ap/include/mach/irq.h14
-rw-r--r--arch/avr32/mach-at32ap/include/mach/pm.h51
-rw-r--r--arch/avr32/mach-at32ap/include/mach/portmux.h30
-rw-r--r--arch/avr32/mach-at32ap/include/mach/smc.h113
-rw-r--r--arch/avr32/mach-at32ap/include/mach/sram.h30
-rw-r--r--arch/avr32/mach-at32ap/intc.c80
-rw-r--r--arch/avr32/mach-at32ap/pdc.c (renamed from arch/avr32/mach-at32ap/at32ap.c)11
-rw-r--r--arch/avr32/mach-at32ap/pio.c69
-rw-r--r--arch/avr32/mach-at32ap/pio.h2
-rw-r--r--arch/avr32/mach-at32ap/pm-at32ap700x.S110
-rw-r--r--arch/avr32/mach-at32ap/pm.c243
-rw-r--r--arch/avr32/mach-at32ap/pm.h12
-rw-r--r--arch/avr32/mach-at32ap/sdramc.h76
28 files changed, 1986 insertions, 451 deletions
diff --git a/arch/avr32/mach-at32ap/Makefile b/arch/avr32/mach-at32ap/Makefile
index e89009439e4..514c9a9b009 100644
--- a/arch/avr32/mach-at32ap/Makefile
+++ b/arch/avr32/mach-at32ap/Makefile
@@ -1,3 +1,9 @@
-obj-y += at32ap.o clock.o intc.o extint.o pio.o hsmc.o
+obj-y += pdc.o clock.o intc.o extint.o pio.o hsmc.o
+obj-y += hmatrix.o
obj-$(CONFIG_CPU_AT32AP700X) += at32ap700x.o pm-at32ap700x.o
obj-$(CONFIG_CPU_FREQ_AT32AP) += cpufreq.o
+obj-$(CONFIG_PM) += pm.o
+
+ifeq ($(CONFIG_PM_DEBUG),y)
+CFLAGS_pm.o += -DDEBUG
+endif
diff --git a/arch/avr32/mach-at32ap/at32ap700x.c b/arch/avr32/mach-at32ap/at32ap700x.c
index 0f24b4f85c1..813b6844cdf 100644
--- a/arch/avr32/mach-at32ap/at32ap700x.c
+++ b/arch/avr32/mach-at32ap/at32ap700x.c
@@ -7,24 +7,28 @@
*/
#include <linux/clk.h>
#include <linux/delay.h>
+#include <linux/dw_dmac.h>
#include <linux/fb.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
+#include <linux/gpio.h>
#include <linux/spi/spi.h>
#include <linux/usb/atmel_usba_udc.h>
+#include <asm/atmel-mci.h>
#include <asm/io.h>
#include <asm/irq.h>
-#include <asm/arch/at32ap700x.h>
-#include <asm/arch/board.h>
-#include <asm/arch/portmux.h>
+#include <mach/at32ap700x.h>
+#include <mach/board.h>
+#include <mach/hmatrix.h>
+#include <mach/portmux.h>
+#include <mach/sram.h>
#include <video/atmel_lcdc.h>
#include "clock.h"
-#include "hmatrix.h"
#include "pio.h"
#include "pm.h"
@@ -78,8 +82,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 select_peripheral(port, pin_mask, periph, flags) \
+ at32_select_periph(GPIO_##port##_BASE, pin_mask, \
+ GPIO_##periph, flags)
#define DEV_CLK(_name, devname, bus, _index) \
static struct clk devname##_##_name = { \
@@ -93,19 +98,12 @@ static struct clk devname##_##_name = { \
static DEFINE_SPINLOCK(pm_lock);
-unsigned long at32ap7000_osc_rates[3] = {
- [0] = 32768,
- /* FIXME: these are ATSTK1002-specific */
- [1] = 20000000,
- [2] = 12000000,
-};
-
static struct clk osc0;
static struct clk osc1;
static unsigned long osc_get_rate(struct clk *clk)
{
- return at32ap7000_osc_rates[clk->index];
+ return at32_board_osc_rates[clk->index];
}
static unsigned long pll_get_rate(struct clk *clk, unsigned long control)
@@ -599,6 +597,17 @@ static void __init genclk_init_parent(struct clk *clk)
clk->parent = parent;
}
+static struct dw_dma_platform_data dw_dmac0_data = {
+ .nr_channels = 3,
+};
+
+static struct resource dw_dmac0_resource[] = {
+ PBMEM(0xff200000),
+ IRQ(2),
+};
+DEFINE_DEV_DATA(dw_dmac, 0);
+DEV_CLK(hclk, dw_dmac0, hsb, 10);
+
/* --------------------------------------------------------------------
* System peripherals
* -------------------------------------------------------------------- */
@@ -682,6 +691,14 @@ static struct clk hramc_clk = {
.users = 1,
.index = 3,
};
+static struct clk sdramc_clk = {
+ .name = "sdramc_clk",
+ .parent = &pbb_clk,
+ .mode = pbb_clk_mode,
+ .get_rate = pbb_clk_get_rate,
+ .users = 1,
+ .index = 14,
+};
static struct resource smc0_resource[] = {
PBMEM(0xfff03400),
@@ -705,22 +722,11 @@ static struct clk pico_clk = {
.users = 1,
};
-static struct resource dmaca0_resource[] = {
- {
- .start = 0xff200000,
- .end = 0xff20ffff,
- .flags = IORESOURCE_MEM,
- },
- IRQ(2),
-};
-DEFINE_DEV(dmaca, 0);
-DEV_CLK(hclk, dmaca0, hsb, 10);
-
/* --------------------------------------------------------------------
* HMATRIX
* -------------------------------------------------------------------- */
-static struct clk hmatrix_clk = {
+struct clk at32_hmatrix_clk = {
.name = "hmatrix_clk",
.parent = &pbb_clk,
.mode = pbb_clk_mode,
@@ -728,12 +734,6 @@ static struct clk hmatrix_clk = {
.index = 2,
.users = 1,
};
-#define HMATRIX_BASE ((void __iomem *)0xfff00800)
-
-#define hmatrix_readl(reg) \
- __raw_readl((HMATRIX_BASE) + HMATRIX_##reg)
-#define hmatrix_writel(reg,value) \
- __raw_writel((value), (HMATRIX_BASE) + HMATRIX_##reg)
/*
* Set bits in the HMATRIX Special Function Register (SFR) used by the
@@ -743,13 +743,7 @@ static struct clk hmatrix_clk = {
*/
static inline void set_ebi_sfr_bits(u32 mask)
{
- u32 sfr;
-
- clk_enable(&hmatrix_clk);
- sfr = hmatrix_readl(SFR4);
- sfr |= mask;
- hmatrix_writel(SFR4, sfr);
- clk_disable(&hmatrix_clk);
+ hmatrix_sfr_set_bits(HMATRIX_SLAVE_EBI, mask);
}
/* --------------------------------------------------------------------
@@ -828,7 +822,7 @@ void __init at32_add_system_devices(void)
platform_device_register(&at32_eic0_device);
platform_device_register(&smc0_device);
platform_device_register(&pdc_device);
- platform_device_register(&dmaca0_device);
+ platform_device_register(&dw_dmac0_device);
platform_device_register(&at32_tcb0_device);
platform_device_register(&at32_tcb1_device);
@@ -841,6 +835,84 @@ void __init at32_add_system_devices(void)
}
/* --------------------------------------------------------------------
+ * PSIF
+ * -------------------------------------------------------------------- */
+static struct resource atmel_psif0_resource[] __initdata = {
+ {
+ .start = 0xffe03c00,
+ .end = 0xffe03cff,
+ .flags = IORESOURCE_MEM,
+ },
+ IRQ(18),
+};
+static struct clk atmel_psif0_pclk = {
+ .name = "pclk",
+ .parent = &pba_clk,
+ .mode = pba_clk_mode,
+ .get_rate = pba_clk_get_rate,
+ .index = 15,
+};
+
+static struct resource atmel_psif1_resource[] __initdata = {
+ {
+ .start = 0xffe03d00,
+ .end = 0xffe03dff,
+ .flags = IORESOURCE_MEM,
+ },
+ IRQ(18),
+};
+static struct clk atmel_psif1_pclk = {
+ .name = "pclk",
+ .parent = &pba_clk,
+ .mode = pba_clk_mode,
+ .get_rate = pba_clk_get_rate,
+ .index = 15,
+};
+
+struct platform_device *__init at32_add_device_psif(unsigned int id)
+{
+ struct platform_device *pdev;
+ u32 pin_mask;
+
+ if (!(id == 0 || id == 1))
+ return NULL;
+
+ pdev = platform_device_alloc("atmel_psif", id);
+ if (!pdev)
+ return NULL;
+
+ switch (id) {
+ case 0:
+ pin_mask = (1 << 8) | (1 << 9); /* CLOCK & DATA */
+
+ if (platform_device_add_resources(pdev, atmel_psif0_resource,
+ ARRAY_SIZE(atmel_psif0_resource)))
+ goto err_add_resources;
+ atmel_psif0_pclk.dev = &pdev->dev;
+ select_peripheral(PIOA, pin_mask, PERIPH_A, 0);
+ break;
+ case 1:
+ pin_mask = (1 << 11) | (1 << 12); /* CLOCK & DATA */
+
+ if (platform_device_add_resources(pdev, atmel_psif1_resource,
+ ARRAY_SIZE(atmel_psif1_resource)))
+ goto err_add_resources;
+ atmel_psif1_pclk.dev = &pdev->dev;
+ select_peripheral(PIOB, pin_mask, PERIPH_A, 0);
+ break;
+ default:
+ return NULL;
+ }
+
+ platform_device_add(pdev);
+ return pdev;
+
+err_add_resources:
+ platform_device_put(pdev);
+ return NULL;
+}
+
+/* --------------------------------------------------------------------
* USART
* -------------------------------------------------------------------- */
@@ -890,26 +962,30 @@ DEV_CLK(usart, atmel_usart3, pba, 6);
static inline void configure_usart0_pins(void)
{
- select_peripheral(PA(8), PERIPH_B, 0); /* RXD */
- select_peripheral(PA(9), PERIPH_B, 0); /* TXD */
+ u32 pin_mask = (1 << 8) | (1 << 9); /* RXD & TXD */
+
+ select_peripheral(PIOA, pin_mask, PERIPH_B, 0);
}
static inline void configure_usart1_pins(void)
{
- select_peripheral(PA(17), PERIPH_A, 0); /* RXD */
- select_peripheral(PA(18), PERIPH_A, 0); /* TXD */
+ u32 pin_mask = (1 << 17) | (1 << 18); /* RXD & TXD */
+
+ select_peripheral(PIOA, pin_mask, PERIPH_A, 0);
}
static inline void configure_usart2_pins(void)
{
- select_peripheral(PB(26), PERIPH_B, 0); /* RXD */
- select_peripheral(PB(27), PERIPH_B, 0); /* TXD */
+ u32 pin_mask = (1 << 26) | (1 << 27); /* RXD & TXD */
+
+ select_peripheral(PIOB, pin_mask, PERIPH_B, 0);
}
static inline void configure_usart3_pins(void)
{
- select_peripheral(PB(18), PERIPH_B, 0); /* RXD */
- select_peripheral(PB(17), PERIPH_B, 0); /* TXD */
+ u32 pin_mask = (1 << 18) | (1 << 17); /* RXD & TXD */
+
+ select_peripheral(PIOB, pin_mask, PERIPH_B, 0);
}
static struct platform_device *__initdata at32_usarts[4];
@@ -989,59 +1065,69 @@ struct platform_device *__init
at32_add_device_eth(unsigned int id, struct eth_platform_data *data)
{
struct platform_device *pdev;
+ u32 pin_mask;
switch (id) {
case 0:
pdev = &macb0_device;
- 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 */
+ pin_mask = (1 << 3); /* TXD0 */
+ pin_mask |= (1 << 4); /* TXD1 */
+ pin_mask |= (1 << 7); /* TXEN */
+ pin_mask |= (1 << 8); /* TXCK */
+ pin_mask |= (1 << 9); /* RXD0 */
+ pin_mask |= (1 << 10); /* RXD1 */
+ pin_mask |= (1 << 13); /* RXER */
+ pin_mask |= (1 << 15); /* RXDV */
+ pin_mask |= (1 << 16); /* MDC */
+ pin_mask |= (1 << 17); /* 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 */
+ pin_mask |= (1 << 0); /* COL */
+ pin_mask |= (1 << 1); /* CRS */
+ pin_mask |= (1 << 2); /* TXER */
+ pin_mask |= (1 << 5); /* TXD2 */
+ pin_mask |= (1 << 6); /* TXD3 */
+ pin_mask |= (1 << 11); /* RXD2 */
+ pin_mask |= (1 << 12); /* RXD3 */
+ pin_mask |= (1 << 14); /* RXCK */
+ pin_mask |= (1 << 18); /* SPD */
}
+
+ select_peripheral(PIOC, pin_mask, PERIPH_A, 0);
+
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 */
+ pin_mask = (1 << 13); /* TXD0 */
+ pin_mask |= (1 << 14); /* TXD1 */
+ pin_mask |= (1 << 11); /* TXEN */
+ pin_mask |= (1 << 12); /* TXCK */
+ pin_mask |= (1 << 10); /* RXD0 */
+ pin_mask |= (1 << 6); /* RXD1 */
+ pin_mask |= (1 << 5); /* RXER */
+ pin_mask |= (1 << 4); /* RXDV */
+ pin_mask |= (1 << 3); /* MDC */
+ pin_mask |= (1 << 2); /* MDIO */
+
+ if (!data->is_rmii)
+ pin_mask |= (1 << 15); /* SPD */
+
+ select_peripheral(PIOD, pin_mask, PERIPH_B, 0);
if (!data->is_rmii) {
- 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 */
+ pin_mask = (1 << 19); /* COL */
+ pin_mask |= (1 << 23); /* CRS */
+ pin_mask |= (1 << 26); /* TXER */
+ pin_mask |= (1 << 27); /* TXD2 */
+ pin_mask |= (1 << 28); /* TXD3 */
+ pin_mask |= (1 << 29); /* RXD2 */
+ pin_mask |= (1 << 30); /* RXD3 */
+ pin_mask |= (1 << 24); /* RXCK */
+
+ select_peripheral(PIOC, pin_mask, PERIPH_B, 0);
}
break;
@@ -1109,21 +1195,28 @@ at32_add_device_spi(unsigned int id, struct spi_board_info *b, unsigned int n)
{ GPIO_PIN_PB(2), GPIO_PIN_PB(3),
GPIO_PIN_PB(4), GPIO_PIN_PA(27), };
struct platform_device *pdev;
+ u32 pin_mask;
switch (id) {
case 0:
pdev = &atmel_spi0_device;
- select_peripheral(PA(0), PERIPH_A, 0); /* MISO */
- select_peripheral(PA(1), PERIPH_A, 0); /* MOSI */
- select_peripheral(PA(2), PERIPH_A, 0); /* SCK */
+ pin_mask = (1 << 1) | (1 << 2); /* MOSI & SCK */
+
+ /* pullup MISO so a level is always defined */
+ select_peripheral(PIOA, (1 << 0), PERIPH_A, AT32_GPIOF_PULLUP);
+ select_peripheral(PIOA, pin_mask, PERIPH_A, 0);
+
at32_spi_setup_slaves(0, b, n, spi0_pins);
break;
case 1:
pdev = &atmel_spi1_device;
- select_peripheral(PB(0), PERIPH_B, 0); /* MISO */
- select_peripheral(PB(1), PERIPH_B, 0); /* MOSI */
- select_peripheral(PB(5), PERIPH_B, 0); /* SCK */
+ pin_mask = (1 << 1) | (1 << 5); /* MOSI */
+
+ /* pullup MISO so a level is always defined */
+ select_peripheral(PIOB, (1 << 0), PERIPH_B, AT32_GPIOF_PULLUP);
+ select_peripheral(PIOB, pin_mask, PERIPH_B, 0);
+
at32_spi_setup_slaves(1, b, n, spi1_pins);
break;
@@ -1156,6 +1249,7 @@ struct platform_device *__init at32_add_device_twi(unsigned int id,
unsigned int n)
{
struct platform_device *pdev;
+ u32 pin_mask;
if (id != 0)
return NULL;
@@ -1168,8 +1262,9 @@ struct platform_device *__init at32_add_device_twi(unsigned int id,
ARRAY_SIZE(atmel_twi0_resource)))
goto err_add_resources;
- select_peripheral(PA(6), PERIPH_A, 0); /* SDA */
- select_peripheral(PA(7), PERIPH_A, 0); /* SDL */
+ pin_mask = (1 << 6) | (1 << 7); /* SDA & SDL */
+
+ select_peripheral(PIOA, pin_mask, PERIPH_A, 0);
atmel_twi0_pclk.dev = &pdev->dev;
@@ -1199,34 +1294,110 @@ static struct clk atmel_mci0_pclk = {
.index = 9,
};
-struct platform_device *__init at32_add_device_mci(unsigned int id)
+struct platform_device *__init
+at32_add_device_mci(unsigned int id, struct mci_platform_data *data)
{
- struct platform_device *pdev;
+ struct platform_device *pdev;
+ struct dw_dma_slave *dws;
+ u32 pioa_mask;
+ u32 piob_mask;
- if (id != 0)
+ if (id != 0 || !data)
+ return NULL;
+
+ /* Must have at least one usable slot */
+ if (!data->slot[0].bus_width && !data->slot[1].bus_width)
return NULL;
pdev = platform_device_alloc("atmel_mci", id);
if (!pdev)
- return NULL;
+ goto fail;
if (platform_device_add_resources(pdev, atmel_mci0_resource,
ARRAY_SIZE(atmel_mci0_resource)))
- goto err_add_resources;
+ goto fail;
+
+ if (data->dma_slave)
+ dws = kmemdup(to_dw_dma_slave(data->dma_slave),
+ sizeof(struct dw_dma_slave), GFP_KERNEL);
+ else
+ dws = kzalloc(sizeof(struct dw_dma_slave), GFP_KERNEL);
+
+ dws->slave.dev = &pdev->dev;
+ dws->slave.dma_dev = &dw_dmac0_device.dev;
+ dws->slave.reg_width = DMA_SLAVE_WIDTH_32BIT;
+ dws->cfg_hi = (DWC_CFGH_SRC_PER(0)
+ | DWC_CFGH_DST_PER(1));
+ dws->cfg_lo &= ~(DWC_CFGL_HS_DST_POL
+ | DWC_CFGL_HS_SRC_POL);
- select_peripheral(PA(10), PERIPH_A, 0); /* CLK */
- select_peripheral(PA(11), PERIPH_A, 0); /* CMD */
- select_peripheral(PA(12), PERIPH_A, 0); /* DATA0 */
- select_peripheral(PA(13), PERIPH_A, 0); /* DATA1 */
- select_peripheral(PA(14), PERIPH_A, 0); /* DATA2 */
- select_peripheral(PA(15), PERIPH_A, 0); /* DATA3 */
+ data->dma_slave = &dws->slave;
+
+ if (platform_device_add_data(pdev, data,
+ sizeof(struct mci_platform_data)))
+ goto fail;
+
+ /* CLK line is common to both slots */
+ pioa_mask = 1 << 10;
+
+ switch (data->slot[0].bus_width) {
+ case 4:
+ pioa_mask |= 1 << 13; /* DATA1 */
+ pioa_mask |= 1 << 14; /* DATA2 */
+ pioa_mask |= 1 << 15; /* DATA3 */
+ /* fall through */
+ case 1:
+ pioa_mask |= 1 << 11; /* CMD */
+ pioa_mask |= 1 << 12; /* DATA0 */
+
+ if (gpio_is_valid(data->slot[0].detect_pin))
+ at32_select_gpio(data->slot[0].detect_pin, 0);
+ if (gpio_is_valid(data->slot[0].wp_pin))
+ at32_select_gpio(data->slot[0].wp_pin, 0);
+ break;
+ case 0:
+ /* Slot is unused */
+ break;
+ default:
+ goto fail;
+ }
+
+ select_peripheral(PIOA, pioa_mask, PERIPH_A, 0);
+ piob_mask = 0;
+
+ switch (data->slot[1].bus_width) {
+ case 4:
+ piob_mask |= 1 << 8; /* DATA1 */
+ piob_mask |= 1 << 9; /* DATA2 */
+ piob_mask |= 1 << 10; /* DATA3 */
+ /* fall through */
+ case 1:
+ piob_mask |= 1 << 6; /* CMD */
+ piob_mask |= 1 << 7; /* DATA0 */
+ select_peripheral(PIOB, piob_mask, PERIPH_B, 0);
+
+ if (gpio_is_valid(data->slot[1].detect_pin))
+ at32_select_gpio(data->slot[1].detect_pin, 0);
+ if (gpio_is_valid(data->slot[1].wp_pin))
+ at32_select_gpio(data->slot[1].wp_pin, 0);
+ break;
+ case 0:
+ /* Slot is unused */
+ break;
+ default:
+ if (!data->slot[0].bus_width)
+ goto fail;
+
+ data->slot[1].bus_width = 0;
+ break;
+ }
atmel_mci0_pclk.dev = &pdev->dev;
platform_device_add(pdev);
return pdev;
-err_add_resources:
+fail:
platform_device_put(pdev);
return NULL;
}
@@ -1264,13 +1435,15 @@ static struct clk atmel_lcdfb0_pixclk = {
struct platform_device *__init
at32_add_device_lcdc(unsigned int id, struct atmel_lcdfb_info *data,
- unsigned long fbmem_start, unsigned long fbmem_len)
+ unsigned long fbmem_start, unsigned long fbmem_len,
+ u64 pin_mask)
{
struct platform_device *pdev;
struct atmel_lcdfb_info *info;
struct fb_monspecs *monspecs;
struct fb_videomode *modedb;
unsigned int modedb_size;
+ u32 portc_mask, portd_mask, porte_mask;
/*
* Do a deep copy of the fb data, monspecs and modedb. Make
@@ -1291,37 +1464,22 @@ at32_add_device_lcdc(unsigned int id, struct atmel_lcdfb_info *data,
switch (id) {
case 0:
pdev = &atmel_lcdfb0_device;
- 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 */
+
+ if (pin_mask == 0ULL)
+ /* Default to "full" lcdc control signals and 24bit */
+ pin_mask = ATMEL_LCDC_PRI_24BIT | ATMEL_LCDC_PRI_CONTROL;
+
+ /* LCDC on port C */
+ portc_mask = (pin_mask & 0xfff80000) >> 19;
+ select_peripheral(PIOC, portc_mask, PERIPH_A, 0);
+
+ /* LCDC on port D */
+ portd_mask = pin_mask & 0x0003ffff;
+ select_peripheral(PIOD, portd_mask, PERIPH_A, 0);
+
+ /* LCDC on port E */
+ porte_mask = (pin_mask >> 32) & 0x0007ffff;
+ select_peripheral(PIOE, porte_mask, PERIPH_B, 0);
clk_set_parent(&atmel_lcdfb0_pixclk, &pll0);
clk_set_rate(&atmel_lcdfb0_pixclk, clk_get_rate(&pll0));
@@ -1360,7 +1518,7 @@ static struct resource atmel_pwm0_resource[] __initdata = {
IRQ(24),
};
static struct clk atmel_pwm0_mck = {
- .name = "mck",
+ .name = "pwm_clk",
.parent = &pbb_clk,
.mode = pbb_clk_mode,
.get_rate = pbb_clk_get_rate,
@@ -1370,6 +1528,7 @@ static struct clk atmel_pwm0_mck = {
struct platform_device *__init at32_add_device_pwm(u32 mask)
{
struct platform_device *pdev;
+ u32 pin_mask;
if (!mask)
return NULL;
@@ -1385,14 +1544,21 @@ struct platform_device *__init at32_add_device_pwm(u32 mask)
if (platform_device_add_data(pdev, &mask, sizeof(mask)))
goto out_free_pdev;
+ pin_mask = 0;
if (mask & (1 << 0))
- select_peripheral(PA(28), PERIPH_A, 0);
+ pin_mask |= (1 << 28);
if (mask & (1 << 1))
- select_peripheral(PA(29), PERIPH_A, 0);
+ pin_mask |= (1 << 29);
+ if (pin_mask > 0)
+ select_peripheral(PIOA, pin_mask, PERIPH_A, 0);
+
+ pin_mask = 0;
if (mask & (1 << 2))
- select_peripheral(PA(21), PERIPH_B, 0);
+ pin_mask |= (1 << 21);
if (mask & (1 << 3))
- select_peripheral(PA(22), PERIPH_B, 0);
+ pin_mask |= (1 << 22);
+ if (pin_mask > 0)
+ select_peripheral(PIOA, pin_mask, PERIPH_B, 0);
atmel_pwm0_mck.dev = &pdev->dev;
@@ -1433,52 +1599,65 @@ struct platform_device *__init
at32_add_device_ssc(unsigned int id, unsigned int flags)
{
struct platform_device *pdev;
+ u32 pin_mask = 0;
switch (id) {
case 0:
pdev = &ssc0_device;
if (flags & ATMEL_SSC_RF)
- select_peripheral(PA(21), PERIPH_A, 0); /* RF */
+ pin_mask |= (1 << 21); /* RF */
if (flags & ATMEL_SSC_RK)
- select_peripheral(PA(22), PERIPH_A, 0); /* RK */
+ pin_mask |= (1 << 22); /* RK */
if (flags & ATMEL_SSC_TK)
- select_peripheral(PA(23), PERIPH_A, 0); /* TK */
+ pin_mask |= (1 << 23); /* TK */
if (flags & ATMEL_SSC_TF)
- select_peripheral(PA(24), PERIPH_A, 0); /* TF */
+ pin_mask |= (1 << 24); /* TF */
if (flags & ATMEL_SSC_TD)
- select_peripheral(PA(25), PERIPH_A, 0); /* TD */
+ pin_mask |= (1 << 25); /* TD */
if (flags & ATMEL_SSC_RD)
- select_peripheral(PA(26), PERIPH_A, 0); /* RD */
+ pin_mask |= (1 << 26); /* RD */
+
+ if (pin_mask > 0)
+ select_peripheral(PIOA, pin_mask, PERIPH_A, 0);
+
break;
case 1:
pdev = &ssc1_device;
if (flags & ATMEL_SSC_RF)
- select_peripheral(PA(0), PERIPH_B, 0); /* RF */
+ pin_mask |= (1 << 0); /* RF */
if (flags & ATMEL_SSC_RK)
- select_peripheral(PA(1), PERIPH_B, 0); /* RK */
+ pin_mask |= (1 << 1); /* RK */
if (flags & ATMEL_SSC_TK)
- select_peripheral(PA(2), PERIPH_B, 0); /* TK */
+ pin_mask |= (1 << 2); /* TK */
if (flags & ATMEL_SSC_TF)
- select_peripheral(PA(3), PERIPH_B, 0); /* TF */
+ pin_mask |= (1 << 3); /* TF */
if (flags & ATMEL_SSC_TD)
- select_peripheral(PA(4), PERIPH_B, 0); /* TD */
+ pin_mask |= (1 << 4); /* TD */
if (flags & ATMEL_SSC_RD)
- select_peripheral(PA(5), PERIPH_B, 0); /* RD */
+ pin_mask |= (1 << 5); /* RD */
+
+ if (pin_mask > 0)
+ select_peripheral(PIOA, pin_mask, PERIPH_B, 0);
+
break;
case 2:
pdev = &ssc2_device;
if (flags & ATMEL_SSC_TD)
- select_peripheral(PB(13), PERIPH_A, 0); /* TD */
+ pin_mask |= (1 << 13); /* TD */
if (flags & ATMEL_SSC_RD)
- select_peripheral(PB(14), PERIPH_A, 0); /* RD */
+ pin_mask |= (1 << 14); /* RD */
if (flags & ATMEL_SSC_TK)
- select_peripheral(PB(15), PERIPH_A, 0); /* TK */
+ pin_mask |= (1 << 15); /* TK */
if (flags & ATMEL_SSC_TF)
- select_peripheral(PB(16), PERIPH_A, 0); /* TF */
+ pin_mask |= (1 << 16); /* TF */
if (flags & ATMEL_SSC_RF)
- select_peripheral(PB(17), PERIPH_A, 0); /* RF */
+ pin_mask |= (1 << 17); /* RF */
if (flags & ATMEL_SSC_RK)
- select_peripheral(PB(18), PERIPH_A, 0); /* RK */
+ pin_mask |= (1 << 18); /* RK */
+
+ if (pin_mask > 0)
+ select_peripheral(PIOB, pin_mask, PERIPH_A, 0);
+
break;
default:
return NULL;
@@ -1616,14 +1795,15 @@ static int __init at32_init_ide_or_cf(struct platform_device *pdev,
unsigned int cs, unsigned int extint)
{
static unsigned int extint_pin_map[4] __initdata = {
- GPIO_PIN_PB(25),
- GPIO_PIN_PB(26),
- GPIO_PIN_PB(27),
- GPIO_PIN_PB(28),
+ (1 << 25),
+ (1 << 26),
+ (1 << 27),
+ (1 << 28),
};
static bool common_pins_initialized __initdata = false;
unsigned int extint_pin;
int ret;
+ u32 pin_mask;
if (extint >= ARRAY_SIZE(extint_pin_map))
return -EINVAL;
@@ -1637,8 +1817,9 @@ static int __init at32_init_ide_or_cf(struct platform_device *pdev,
if (ret)
return ret;
- select_peripheral(PE(21), PERIPH_A, 0); /* NCS4 -> OE_N */
- set_ebi_sfr_bits(HMATRIX_BIT(CS4A));
+ /* NCS4 -> OE_N */
+ select_peripheral(PIOE, (1 << 21), PERIPH_A, 0);
+ hmatrix_sfr_set_bits(HMATRIX_SLAVE_EBI, HMATRIX_EBI_CF0_ENABLE);
break;
case 5:
ret = platform_device_add_resources(pdev,
@@ -1647,22 +1828,26 @@ static int __init at32_init_ide_or_cf(struct platform_device *pdev,
if (ret)
return ret;
- select_peripheral(PE(22), PERIPH_A, 0); /* NCS5 -> OE_N */
- set_ebi_sfr_bits(HMATRIX_BIT(CS5A));
+ /* NCS5 -> OE_N */
+ select_peripheral(PIOE, (1 << 22), PERIPH_A, 0);
+ hmatrix_sfr_set_bits(HMATRIX_SLAVE_EBI, HMATRIX_EBI_CF1_ENABLE);
break;
default:
return -EINVAL;
}
if (!common_pins_initialized) {
- select_peripheral(PE(19), PERIPH_A, 0); /* CFCE1 -> CS0_N */
- select_peripheral(PE(20), PERIPH_A, 0); /* CFCE2 -> CS1_N */
- select_peripheral(PE(23), PERIPH_A, 0); /* CFRNW -> DIR */
- select_peripheral(PE(24), PERIPH_A, 0); /* NWAIT <- IORDY */
+ pin_mask = (1 << 19); /* CFCE1 -> CS0_N */
+ pin_mask |= (1 << 20); /* CFCE2 -> CS1_N */
+ pin_mask |= (1 << 23); /* CFRNW -> DIR */
+ pin_mask |= (1 << 24); /* NWAIT <- IORDY */
+
+ select_peripheral(PIOE, pin_mask, PERIPH_A, 0);
+
common_pins_initialized = true;
}
- at32_select_periph(extint_pin, GPIO_PERIPH_A, AT32_GPIOF_DEGLITCH);
+ select_peripheral(PIOB, extint_pin, PERIPH_A, AT32_GPIOF_DEGLITCH);
pdev->resource[1].start = EIM_IRQ_BASE + extint;
pdev->resource[1].end = pdev->resource[1].start;
@@ -1712,11 +1897,11 @@ at32_add_device_cf(unsigned int id, unsigned int extint,
if (at32_init_ide_or_cf(pdev, data->cs, extint))
goto fail;
- if (data->detect_pin != GPIO_PIN_NONE)
+ if (gpio_is_valid(data->detect_pin))
at32_select_gpio(data->detect_pin, AT32_GPIOF_DEGLITCH);
- if (data->reset_pin != GPIO_PIN_NONE)
+ if (gpio_is_valid(data->reset_pin))
at32_select_gpio(data->reset_pin, 0);
- if (data->vcc_pin != GPIO_PIN_NONE)
+ if (gpio_is_valid(data->vcc_pin))
at32_select_gpio(data->vcc_pin, 0);
/* READY is used as extint, so we can't select it as gpio */
@@ -1730,6 +1915,58 @@ fail:
#endif
/* --------------------------------------------------------------------
+ * NAND Flash / SmartMedia
+ * -------------------------------------------------------------------- */
+static struct resource smc_cs3_resource[] __initdata = {
+ {
+ .start = 0x0c000000,
+ .end = 0x0fffffff,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .start = 0xfff03c00,
+ .end = 0xfff03fff,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+struct platform_device *__init
+at32_add_device_nand(unsigned int id, struct atmel_nand_data *data)
+{
+ struct platform_device *pdev;
+
+ if (id != 0 || !data)
+ return NULL;
+
+ pdev = platform_device_alloc("atmel_nand", id);
+ if (!pdev)
+ goto fail;
+
+ if (platform_device_add_resources(pdev, smc_cs3_resource,
+ ARRAY_SIZE(smc_cs3_resource)))
+ goto fail;
+
+ if (platform_device_add_data(pdev, data,
+ sizeof(struct atmel_nand_data)))
+ goto fail;
+
+ hmatrix_sfr_set_bits(HMATRIX_SLAVE_EBI, HMATRIX_EBI_NAND_ENABLE);
+ if (data->enable_pin)
+ at32_select_gpio(data->enable_pin,
+ AT32_GPIOF_OUTPUT | AT32_GPIOF_HIGH);
+ if (data->rdy_pin)
+ at32_select_gpio(data->rdy_pin, 0);
+ if (data->det_pin)
+ at32_select_gpio(data->det_pin, 0);
+
+ platform_device_add(pdev);
+ return pdev;
+
+fail:
+ platform_device_put(pdev);
+ return NULL;
+}
+
+/* --------------------------------------------------------------------
* AC97C
* -------------------------------------------------------------------- */
static struct resource atmel_ac97c0_resource[] __initdata = {
@@ -1744,9 +1981,12 @@ static struct clk atmel_ac97c0_pclk = {
.index = 10,
};
-struct platform_device *__init at32_add_device_ac97c(unsigned int id)
+struct platform_device *__init
+at32_add_device_ac97c(unsigned int id, struct ac97c_platform_data *data)
{
struct platform_device *pdev;
+ struct ac97c_platform_data _data;
+ u32 pin_mask;
if (id != 0)
return NULL;
@@ -1757,19 +1997,37 @@ struct platform_device *__init at32_add_device_ac97c(unsigned int id)
if (platform_device_add_resources(pdev, atmel_ac97c0_resource,
ARRAY_SIZE(atmel_ac97c0_resource)))
- goto err_add_resources;
+ goto fail;
- select_peripheral(PB(20), PERIPH_B, 0); /* SYNC */
- select_peripheral(PB(21), PERIPH_B, 0); /* SDO */
- select_peripheral(PB(22), PERIPH_B, 0); /* SDI */
- select_peripheral(PB(23), PERIPH_B, 0); /* SCLK */
+ if (!data) {
+ data = &_data;
+ memset(data, 0, sizeof(struct ac97c_platform_data));
+ data->reset_pin = GPIO_PIN_NONE;
+ }
+
+ data->dma_rx_periph_id = 3;
+ data->dma_tx_periph_id = 4;
+ data->dma_controller_id = 0;
+
+ if (platform_device_add_data(pdev, data,
+ sizeof(struct ac97c_platform_data)))
+ goto fail;
+
+ pin_mask = (1 << 20) | (1 << 21); /* SDO & SYNC */
+ pin_mask |= (1 << 22) | (1 << 23); /* SCLK & SDI */
+
+ select_peripheral(PIOB, pin_mask, PERIPH_B, 0);
+
+ /* TODO: gpio_is_valid(data->reset_pin) with kernel 2.6.26. */
+ if (data->reset_pin != GPIO_PIN_NONE)
+ at32_select_gpio(data->reset_pin, 0);
atmel_ac97c0_pclk.dev = &pdev->dev;
platform_device_add(pdev);
return pdev;
-err_add_resources:
+fail:
platform_device_put(pdev);
return NULL;
}
@@ -1800,6 +2058,7 @@ static struct clk abdac0_sample_clk = {
struct platform_device *__init at32_add_device_abdac(unsigned int id)
{
struct platform_device *pdev;
+ u32 pin_mask;
if (id != 0)
return NULL;
@@ -1812,10 +2071,10 @@ struct platform_device *__init at32_add_device_abdac(unsigned int id)
ARRAY_SIZE(abdac0_resource)))
goto err_add_resources;
- select_peripheral(PB(20), PERIPH_A, 0); /* DATA1 */
- select_peripheral(PB(21), PERIPH_A, 0); /* DATA0 */
- select_peripheral(PB(22), PERIPH_A, 0); /* DATAN1 */
- select_peripheral(PB(23), PERIPH_A, 0); /* DATAN0 */
+ pin_mask = (1 << 20) | (1 << 22); /* DATA1 & DATAN1 */
+ pin_mask |= (1 << 21) | (1 << 23); /* DATA0 & DATAN0 */
+
+ select_peripheral(PIOB, pin_mask, PERIPH_A, 0);
abdac0_pclk.dev = &pdev->dev;
abdac0_sample_clk.dev = &pdev->dev;
@@ -1872,7 +2131,7 @@ static struct clk gclk4 = {
.index = 4,
};
-struct clk *at32_clock_list[] = {
+static __initdata struct clk *init_clocks[] = {
&osc32k,
&osc0,
&osc1,
@@ -1884,14 +2143,15 @@ struct clk *at32_clock_list[] = {
&pbb_clk,
&at32_pm_pclk,
&at32_intc0_pclk,
- &hmatrix_clk,
+ &at32_hmatrix_clk,
&ebi_clk,
&hramc_clk,
+ &sdramc_clk,
&smc0_pclk,
&smc0_mck,
&pdc_hclk,
&pdc_pclk,
- &dmaca0_hclk,
+ &dw_dmac0_hclk,
&pico_clk,
&pio0_mck,
&pio1_mck,
@@ -1900,6 +2160,8 @@ struct clk *at32_clock_list[] = {
&pio4_mck,
&at32_tcb0_t0_clk,
&at32_tcb1_t0_clk,
+ &atmel_psif0_pclk,
+ &atmel_psif1_pclk,
&atmel_usart0_usart,
&atmel_usart1_usart,
&atmel_usart2_usart,
@@ -1933,18 +2195,8 @@ struct clk *at32_clock_list[] = {
&gclk3,
&gclk4,
};
-unsigned int at32_nr_clocks = ARRAY_SIZE(at32_clock_list);
-void __init at32_portmux_init(void)
-{
- at32_init_pio(&pio0_device);
- at32_init_pio(&pio1_device);
- at32_init_pio(&pio2_device);
- at32_init_pio(&pio3_device);
- at32_init_pio(&pio4_device);
-}
-
-void __init at32_clock_init(void)
+void __init setup_platform(void)
{
u32 cpu_mask = 0, hsb_mask = 0, pba_mask = 0, pbb_mask = 0;
int i;
@@ -1973,14 +2225,19 @@ void __init at32_clock_init(void)
genclk_init_parent(&abdac0_sample_clk);
/*
- * Turn on all clocks that have at least one user already, and
- * turn off everything else. We only do this for module
- * clocks, and even though it isn't particularly pretty to
- * check the address of the mode function, it should do the
- * trick...
+ * Build initial dynamic clock list by registering all clocks
+ * from the array.
+ * At the same time, turn on all clocks that have at least one
+ * user already, and turn off everything else. We only do this
+ * for module clocks, and even though it isn't particularly
+ * pretty to check the address of the mode function, it should
+ * do the trick...
*/
- for (i = 0; i < ARRAY_SIZE(at32_clock_list); i++) {
- struct clk *clk = at32_clock_list[i];
+ for (i = 0; i < ARRAY_SIZE(init_clocks); i++) {
+ struct clk *clk = init_clocks[i];
+
+ /* first, register clock */
+ at32_clk_register(clk);
if (clk->users == 0)
continue;
@@ -1999,4 +2256,36 @@ void __init at32_clock_init(void)
pm_writel(HSB_MASK, hsb_mask);
pm_writel(PBA_MASK, pba_mask);
pm_writel(PBB_MASK, pbb_mask);
+
+ /* Initialize the port muxes */
+ at32_init_pio(&pio0_device);
+ at32_init_pio(&pio1_device);
+ at32_init_pio(&pio2_device);
+ at32_init_pio(&pio3_device);
+ at32_init_pio(&pio4_device);
+}
+
+struct gen_pool *sram_pool;
+
+static int __init sram_init(void)
+{
+ struct gen_pool *pool;
+
+ /* 1KiB granularity */
+ pool = gen_pool_create(10, -1);
+ if (!pool)
+ goto fail;
+
+ if (gen_pool_add(pool, 0x24000000, 0x8000, -1))
+ goto err_pool_add;
+
+ sram_pool = pool;
+ return 0;
+
+err_pool_add:
+ gen_pool_destroy(pool);
+fail:
+ pr_err("Failed to create SRAM pool\n");
+ return -ENOMEM;
}
+core_initcall(sram_init);
diff --git a/arch/avr32/mach-at32ap/clock.c b/arch/avr32/mach-at32ap/clock.c
index 4642117cc9a..138a00a2a2d 100644
--- a/arch/avr32/mach-at32ap/clock.c
+++ b/arch/avr32/mach-at32ap/clock.c
@@ -15,22 +15,40 @@
#include <linux/err.h>
#include <linux/device.h>
#include <linux/string.h>
+#include <linux/list.h>
+
+#include <mach/chip.h>
#include "clock.h"
+/* at32 clock list */
+static LIST_HEAD(at32_clock_list);
+
static DEFINE_SPINLOCK(clk_lock);
+static DEFINE_SPINLOCK(clk_list_lock);
+
+void at32_clk_register(struct clk *clk)
+{
+ spin_lock(&clk_list_lock);
+ /* add the new item to the end of the list */
+ list_add_tail(&clk->list, &at32_clock_list);
+ spin_unlock(&clk_list_lock);
+}
struct clk *clk_get(struct device *dev, const char *id)
{
- int i;
+ struct clk *clk;
- for (i = 0; i < at32_nr_clocks; i++) {
- struct clk *clk = at32_clock_list[i];
+ spin_lock(&clk_list_lock);
- if (clk->dev == dev && strcmp(id, clk->name) == 0)
+ list_for_each_entry(clk, &at32_clock_list, list) {
+ if (clk->dev == dev && strcmp(id, clk->name) == 0) {
+ spin_unlock(&clk_list_lock);
return clk;
+ }
}
+ spin_unlock(&clk_list_lock);
return ERR_PTR(-ENOENT);
}
EXPORT_SYMBOL(clk_get);
@@ -201,8 +219,8 @@ dump_clock(struct clk *parent, struct clkinf *r)
/* cost of this scan is small, but not linear... */
r->nest = nest + NEST_DELTA;
- for (i = 3; i < at32_nr_clocks; i++) {
- clk = at32_clock_list[i];
+
+ list_for_each_entry(clk, &at32_clock_list, list) {
if (clk->parent == parent)
dump_clock(clk, r);
}
@@ -213,6 +231,7 @@ static int clk_show(struct seq_file *s, void *unused)
{
struct clkinf r;
int i;
+ struct clk *clk;
/* show all the power manager registers */
seq_printf(s, "MCCTRL = %8x\n", pm_readl(MCCTRL));
@@ -232,14 +251,25 @@ static int clk_show(struct seq_file *s, void *unused)
seq_printf(s, "\n");
- /* show clock tree as derived from the three oscillators
- * we "know" are at the head of the list
- */
r.s = s;
r.nest = 0;
- dump_clock(at32_clock_list[0], &r);
- dump_clock(at32_clock_list[1], &r);
- dump_clock(at32_clock_list[2], &r);
+ /* protected from changes on the list while dumping */
+ spin_lock(&clk_list_lock);
+
+ /* show clock tree as derived from the three oscillators */
+ clk = clk_get(NULL, "osc32k");
+ dump_clock(clk, &r);
+ clk_put(clk);
+
+ clk = clk_get(NULL, "osc0");
+ dump_clock(clk, &r);
+ clk_put(clk);
+
+ clk = clk_get(NULL, "osc1");
+ dump_clock(clk, &r);
+ clk_put(clk);
+
+ spin_unlock(&clk_list_lock);
return 0;
}
diff --git a/arch/avr32/mach-at32ap/clock.h b/arch/avr32/mach-at32ap/clock.h
index bb8e1f29583..623bf0e9a1e 100644
--- a/arch/avr32/mach-at32ap/clock.h
+++ b/arch/avr32/mach-at32ap/clock.h
@@ -12,8 +12,13 @@
* published by the Free Software Foundation.
*/
#include <linux/clk.h>
+#include <linux/list.h>
+
+
+void at32_clk_register(struct clk *clk);
struct clk {
+ struct list_head list; /* linking element */
const char *name; /* Clock name/function */
struct device *dev; /* Device the clock is used by */
struct clk *parent; /* Parent clock, if any */
@@ -25,6 +30,3 @@ struct clk {
u16 users; /* Enabled if non-zero */
u16 index; /* Sibling index */
};
-
-extern struct clk *at32_clock_list[];
-extern unsigned int at32_nr_clocks;
diff --git a/arch/avr32/mach-at32ap/hmatrix.c b/arch/avr32/mach-at32ap/hmatrix.c
new file mode 100644
index 00000000000..48f5ede7746
--- /dev/null
+++ b/arch/avr32/mach-at32ap/hmatrix.c
@@ -0,0 +1,88 @@
+/*
+ * High-Speed Bus Matrix helper functions
+ *
+ * Copyright (C) 2008 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/clk.h>
+#include <linux/io.h>
+
+#include <mach/chip.h>
+#include <mach/hmatrix.h>
+
+static inline void __hmatrix_write_reg(unsigned long offset, u32 value)
+{
+ __raw_writel(value, (void __iomem __force *)(HMATRIX_BASE + offset));
+}
+
+static inline u32 __hmatrix_read_reg(unsigned long offset)
+{
+ return __raw_readl((void __iomem __force *)(HMATRIX_BASE + offset));
+}
+
+/**
+ * hmatrix_write_reg - write HMATRIX configuration register
+ * @offset: register offset
+ * @value: value to be written to the register at @offset
+ */
+void hmatrix_write_reg(unsigned long offset, u32 value)
+{
+ clk_enable(&at32_hmatrix_clk);
+ __hmatrix_write_reg(offset, value);
+ __hmatrix_read_reg(offset);
+ clk_disable(&at32_hmatrix_clk);
+}
+
+/**
+ * hmatrix_read_reg - read HMATRIX configuration register
+ * @offset: register offset
+ *
+ * Returns the value of the register at @offset.
+ */
+u32 hmatrix_read_reg(unsigned long offset)
+{
+ u32 value;
+
+ clk_enable(&at32_hmatrix_clk);
+ value = __hmatrix_read_reg(offset);
+ clk_disable(&at32_hmatrix_clk);
+
+ return value;
+}
+
+/**
+ * hmatrix_sfr_set_bits - set bits in a slave's Special Function Register
+ * @slave_id: operate on the SFR belonging to this slave
+ * @mask: mask of bits to be set in the SFR
+ */
+void hmatrix_sfr_set_bits(unsigned int slave_id, u32 mask)
+{
+ u32 value;
+
+ clk_enable(&at32_hmatrix_clk);
+ value = __hmatrix_read_reg(HMATRIX_SFR(slave_id));
+ value |= mask;
+ __hmatrix_write_reg(HMATRIX_SFR(slave_id), value);
+ __hmatrix_read_reg(HMATRIX_SFR(slave_id));
+ clk_disable(&at32_hmatrix_clk);
+}
+
+/**
+ * hmatrix_sfr_set_bits - clear bits in a slave's Special Function Register
+ * @slave_id: operate on the SFR belonging to this slave
+ * @mask: mask of bits to be cleared in the SFR
+ */
+void hmatrix_sfr_clear_bits(unsigned int slave_id, u32 mask)
+{
+ u32 value;
+
+ clk_enable(&at32_hmatrix_clk);
+ value = __hmatrix_read_reg(HMATRIX_SFR(slave_id));
+ value &= ~mask;
+ __hmatrix_write_reg(HMATRIX_SFR(slave_id), value);
+ __hmatrix_read_reg(HMATRIX_SFR(slave_id));
+ clk_disable(&at32_hmatrix_clk);
+}
diff --git a/arch/avr32/mach-at32ap/hmatrix.h b/arch/avr32/mach-at32ap/hmatrix.h
deleted file mode 100644
index d10bfb60d68..00000000000
--- a/arch/avr32/mach-at32ap/hmatrix.h
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * Register definitions for High-Speed Bus Matrix
- */
-#ifndef __HMATRIX_H
-#define __HMATRIX_H
-
-/* HMATRIX register offsets */
-#define HMATRIX_MCFG0 0x0000
-#define HMATRIX_MCFG1 0x0004
-#define HMATRIX_MCFG2 0x0008
-#define HMATRIX_MCFG3 0x000c
-#define HMATRIX_MCFG4 0x0010
-#define HMATRIX_MCFG5 0x0014
-#define HMATRIX_MCFG6 0x0018
-#define HMATRIX_MCFG7 0x001c
-#define HMATRIX_MCFG8 0x0020
-#define HMATRIX_MCFG9 0x0024
-#define HMATRIX_MCFG10 0x0028
-#define HMATRIX_MCFG11 0x002c
-#define HMATRIX_MCFG12 0x0030
-#define HMATRIX_MCFG13 0x0034
-#define HMATRIX_MCFG14 0x0038
-#define HMATRIX_MCFG15 0x003c
-#define HMATRIX_SCFG0 0x0040
-#define HMATRIX_SCFG1 0x0044
-#define HMATRIX_SCFG2 0x0048
-#define HMATRIX_SCFG3 0x004c
-#define HMATRIX_SCFG4 0x0050
-#define HMATRIX_SCFG5 0x0054
-#define HMATRIX_SCFG6 0x0058
-#define HMATRIX_SCFG7 0x005c
-#define HMATRIX_SCFG8 0x0060
-#define HMATRIX_SCFG9 0x0064
-#define HMATRIX_SCFG10 0x0068
-#define HMATRIX_SCFG11 0x006c
-#define HMATRIX_SCFG12 0x0070
-#define HMATRIX_SCFG13 0x0074
-#define HMATRIX_SCFG14 0x0078
-#define HMATRIX_SCFG15 0x007c
-#define HMATRIX_PRAS0 0x0080
-#define HMATRIX_PRBS0 0x0084
-#define HMATRIX_PRAS1 0x0088
-#define HMATRIX_PRBS1 0x008c
-#define HMATRIX_PRAS2 0x0090
-#define HMATRIX_PRBS2 0x0094
-#define HMATRIX_PRAS3 0x0098
-#define HMATRIX_PRBS3 0x009c
-#define HMATRIX_PRAS4 0x00a0
-#define HMATRIX_PRBS4 0x00a4
-#define HMATRIX_PRAS5 0x00a8
-#define HMATRIX_PRBS5 0x00ac
-#define HMATRIX_PRAS6 0x00b0
-#define HMATRIX_PRBS6 0x00b4
-#define HMATRIX_PRAS7 0x00b8
-#define HMATRIX_PRBS7 0x00bc
-#define HMATRIX_PRAS8 0x00c0
-#define HMATRIX_PRBS8 0x00c4
-#define HMATRIX_PRAS9 0x00c8
-#define HMATRIX_PRBS9 0x00cc
-#define HMATRIX_PRAS10 0x00d0
-#define HMATRIX_PRBS10 0x00d4
-#define HMATRIX_PRAS11 0x00d8
-#define HMATRIX_PRBS11 0x00dc
-#define HMATRIX_PRAS12 0x00e0
-#define HMATRIX_PRBS12 0x00e4
-#define HMATRIX_PRAS13 0x00e8
-#define HMATRIX_PRBS13 0x00ec
-#define HMATRIX_PRAS14 0x00f0
-#define HMATRIX_PRBS14 0x00f4
-#define HMATRIX_PRAS15 0x00f8
-#define HMATRIX_PRBS15 0x00fc
-#define HMATRIX_MRCR 0x0100
-#define HMATRIX_SFR0 0x0110
-#define HMATRIX_SFR1 0x0114
-#define HMATRIX_SFR2 0x0118
-#define HMATRIX_SFR3 0x011c
-#define HMATRIX_SFR4 0x0120
-#define HMATRIX_SFR5 0x0124
-#define HMATRIX_SFR6 0x0128
-#define HMATRIX_SFR7 0x012c
-#define HMATRIX_SFR8 0x0130
-#define HMATRIX_SFR9 0x0134
-#define HMATRIX_SFR10 0x0138
-#define HMATRIX_SFR11 0x013c
-#define HMATRIX_SFR12 0x0140
-#define HMATRIX_SFR13 0x0144
-#define HMATRIX_SFR14 0x0148
-#define HMATRIX_SFR15 0x014c
-
-/* Bitfields in MCFGx */
-#define HMATRIX_ULBT_OFFSET 0
-#define HMATRIX_ULBT_SIZE 3
-
-/* Bitfields in SCFGx */
-#define HMATRIX_SLOT_CYCLE_OFFSET 0
-#define HMATRIX_SLOT_CYCLE_SIZE 8
-#define HMATRIX_DEFMSTR_TYPE_OFFSET 16
-#define HMATRIX_DEFMSTR_TYPE_SIZE 2
-#define HMATRIX_FIXED_DEFMSTR_OFFSET 18
-#define HMATRIX_FIXED_DEFMSTR_SIZE 4
-#define HMATRIX_ARBT_OFFSET 24
-#define HMATRIX_ARBT_SIZE 2
-
-/* Bitfields in PRASx */
-#define HMATRIX_M0PR_OFFSET 0
-#define HMATRIX_M0PR_SIZE 4
-#define HMATRIX_M1PR_OFFSET 4
-#define HMATRIX_M1PR_SIZE 4
-#define HMATRIX_M2PR_OFFSET 8
-#define HMATRIX_M2PR_SIZE 4
-#define HMATRIX_M3PR_OFFSET 12
-#define HMATRIX_M3PR_SIZE 4
-#define HMATRIX_M4PR_OFFSET 16
-#define HMATRIX_M4PR_SIZE 4
-#define HMATRIX_M5PR_OFFSET 20
-#define HMATRIX_M5PR_SIZE 4
-#define HMATRIX_M6PR_OFFSET 24
-#define HMATRIX_M6PR_SIZE 4
-#define HMATRIX_M7PR_OFFSET 28
-#define HMATRIX_M7PR_SIZE 4
-
-/* Bitfields in PRBSx */
-#define HMATRIX_M8PR_OFFSET 0
-#define HMATRIX_M8PR_SIZE 4
-#define HMATRIX_M9PR_OFFSET 4
-#define HMATRIX_M9PR_SIZE 4
-#define HMATRIX_M10PR_OFFSET 8
-#define HMATRIX_M10PR_SIZE 4
-#define HMATRIX_M11PR_OFFSET 12
-#define HMATRIX_M11PR_SIZE 4
-#define HMATRIX_M12PR_OFFSET 16
-#define HMATRIX_M12PR_SIZE 4
-#define HMATRIX_M13PR_OFFSET 20
-#define HMATRIX_M13PR_SIZE 4
-#define HMATRIX_M14PR_OFFSET 24
-#define HMATRIX_M14PR_SIZE 4
-#define HMATRIX_M15PR_OFFSET 28
-#define HMATRIX_M15PR_SIZE 4
-
-/* Bitfields in SFR4 */
-#define HMATRIX_CS1A_OFFSET 1
-#define HMATRIX_CS1A_SIZE 1
-#define HMATRIX_CS3A_OFFSET 3
-#define HMATRIX_CS3A_SIZE 1
-#define HMATRIX_CS4A_OFFSET 4
-#define HMATRIX_CS4A_SIZE 1
-#define HMATRIX_CS5A_OFFSET 5
-#define HMATRIX_CS5A_SIZE 1
-#define HMATRIX_DBPUC_OFFSET 8
-#define HMATRIX_DBPUC_SIZE 1
-
-/* Constants for ULBT */
-#define HMATRIX_ULBT_INFINITE 0
-#define HMATRIX_ULBT_SINGLE 1
-#define HMATRIX_ULBT_FOUR_BEAT 2
-#define HMATRIX_ULBT_EIGHT_BEAT 3
-#define HMATRIX_ULBT_SIXTEEN_BEAT 4
-
-/* Constants for DEFMSTR_TYPE */
-#define HMATRIX_DEFMSTR_TYPE_NO_DEFAULT 0
-#define HMATRIX_DEFMSTR_TYPE_LAST_DEFAULT 1
-#define HMATRIX_DEFMSTR_TYPE_FIXED_DEFAULT 2
-
-/* Constants for ARBT */
-#define HMATRIX_ARBT_ROUND_ROBIN 0
-#define HMATRIX_ARBT_FIXED_PRIORITY 1
-
-/* Bit manipulation macros */
-#define HMATRIX_BIT(name) \
- (1 << HMATRIX_##name##_OFFSET)
-#define HMATRIX_BF(name,value) \
- (((value) & ((1 << HMATRIX_##name##_SIZE) - 1)) \
- << HMATRIX_##name##_OFFSET)
-#define HMATRIX_BFEXT(name,value) \
- (((value) >> HMATRIX_##name##_OFFSET) \
- & ((1 << HMATRIX_##name##_SIZE) - 1))
-#define HMATRIX_BFINS(name,value,old) \
- (((old) & ~(((1 << HMATRIX_##name##_SIZE) - 1) \
- << HMATRIX_##name##_OFFSET)) \
- | HMATRIX_BF(name,value))
-
-#endif /* __HMATRIX_H */
diff --git a/arch/avr32/mach-at32ap/hsmc.c b/arch/avr32/mach-at32ap/hsmc.c
index fa427ed4278..2875c11be95 100644
--- a/arch/avr32/mach-at32ap/hsmc.c
+++ b/arch/avr32/mach-at32ap/hsmc.c
@@ -14,7 +14,7 @@
#include <linux/platform_device.h>
#include <asm/io.h>
-#include <asm/arch/smc.h>
+#include <mach/smc.h>
#include "hsmc.h"
@@ -278,4 +278,4 @@ static int __init hsmc_init(void)
{
return platform_driver_register(&hsmc_driver);
}
-arch_initcall(hsmc_init);
+core_initcall(hsmc_init);
diff --git a/arch/avr32/mach-at32ap/include/mach/at32ap700x.h b/arch/avr32/mach-at32ap/include/mach/at32ap700x.h
new file mode 100644
index 00000000000..a77d372f6f3
--- /dev/null
+++ b/arch/avr32/mach-at32ap/include/mach/at32ap700x.h
@@ -0,0 +1,214 @@
+/*
+ * 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_AT32AP700X_H__
+#define __ASM_ARCH_AT32AP700X_H__
+
+#define GPIO_PERIPH_A 0
+#define GPIO_PERIPH_B 1
+
+/*
+ * 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_PIOE_BASE (GPIO_PIOD_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))
+#define GPIO_PIN_PE(N) (GPIO_PIOE_BASE + (N))
+
+
+/*
+ * DMAC peripheral hardware handshaking interfaces, used with dw_dmac
+ */
+#define DMAC_MCI_RX 0
+#define DMAC_MCI_TX 1
+#define DMAC_DAC_TX 2
+#define DMAC_AC97_A_RX 3
+#define DMAC_AC97_A_TX 4
+#define DMAC_AC97_B_RX 5
+#define DMAC_AC97_B_TX 6
+#define DMAC_DMAREQ_0 7
+#define DMAC_DMAREQ_1 8
+#define DMAC_DMAREQ_2 9
+#define DMAC_DMAREQ_3 10
+
+/* HSB master IDs */
+#define HMATRIX_MASTER_CPU_DCACHE 0
+#define HMATRIX_MASTER_CPU_ICACHE 1
+#define HMATRIX_MASTER_PDC 2
+#define HMATRIX_MASTER_ISI 3
+#define HMATRIX_MASTER_USBA 4
+#define HMATRIX_MASTER_LCDC 5
+#define HMATRIX_MASTER_MACB0 6
+#define HMATRIX_MASTER_MACB1 7
+#define HMATRIX_MASTER_DMACA_M0 8
+#define HMATRIX_MASTER_DMACA_M1 9
+
+/* HSB slave IDs */
+#define HMATRIX_SLAVE_SRAM0 0
+#define HMATRIX_SLAVE_SRAM1 1
+#define HMATRIX_SLAVE_PBA 2
+#define HMATRIX_SLAVE_PBB 3
+#define HMATRIX_SLAVE_EBI 4
+#define HMATRIX_SLAVE_USBA 5
+#define HMATRIX_SLAVE_LCDC 6
+#define HMATRIX_SLAVE_DMACA 7
+
+/* Bits in HMATRIX SFR4 (EBI) */
+#define HMATRIX_EBI_SDRAM_ENABLE (1 << 1)
+#define HMATRIX_EBI_NAND_ENABLE (1 << 3)
+#define HMATRIX_EBI_CF0_ENABLE (1 << 4)
+#define HMATRIX_EBI_CF1_ENABLE (1 << 5)
+#define HMATRIX_EBI_PULLUP_DISABLE (1 << 8)
+
+/*
+ * Base addresses of controllers that may be accessed early by
+ * platform code.
+ */
+#define PM_BASE 0xfff00000
+#define HMATRIX_BASE 0xfff00800
+#define SDRAMC_BASE 0xfff03800
+
+/* LCDC on port C */
+#define ATMEL_LCDC_PC_CC (1ULL << 19)
+#define ATMEL_LCDC_PC_HSYNC (1ULL << 20)
+#define ATMEL_LCDC_PC_PCLK (1ULL << 21)
+#define ATMEL_LCDC_PC_VSYNC (1ULL << 22)
+#define ATMEL_LCDC_PC_DVAL (1ULL << 23)
+#define ATMEL_LCDC_PC_MODE (1ULL << 24)
+#define ATMEL_LCDC_PC_PWR (1ULL << 25)
+#define ATMEL_LCDC_PC_DATA0 (1ULL << 26)
+#define ATMEL_LCDC_PC_DATA1 (1ULL << 27)
+#define ATMEL_LCDC_PC_DATA2 (1ULL << 28)
+#define ATMEL_LCDC_PC_DATA3 (1ULL << 29)
+#define ATMEL_LCDC_PC_DATA4 (1ULL << 30)
+#define ATMEL_LCDC_PC_DATA5 (1ULL << 31)
+
+/* LCDC on port D */
+#define ATMEL_LCDC_PD_DATA6 (1ULL << 0)
+#define ATMEL_LCDC_PD_DATA7 (1ULL << 1)
+#define ATMEL_LCDC_PD_DATA8 (1ULL << 2)
+#define ATMEL_LCDC_PD_DATA9 (1ULL << 3)
+#define ATMEL_LCDC_PD_DATA10 (1ULL << 4)
+#define ATMEL_LCDC_PD_DATA11 (1ULL << 5)
+#define ATMEL_LCDC_PD_DATA12 (1ULL << 6)
+#define ATMEL_LCDC_PD_DATA13 (1ULL << 7)
+#define ATMEL_LCDC_PD_DATA14 (1ULL << 8)
+#define ATMEL_LCDC_PD_DATA15 (1ULL << 9)
+#define ATMEL_LCDC_PD_DATA16 (1ULL << 10)
+#define ATMEL_LCDC_PD_DATA17 (1ULL << 11)
+#define ATMEL_LCDC_PD_DATA18 (1ULL << 12)
+#define ATMEL_LCDC_PD_DATA19 (1ULL << 13)
+#define ATMEL_LCDC_PD_DATA20 (1ULL << 14)
+#define ATMEL_LCDC_PD_DATA21 (1ULL << 15)
+#define ATMEL_LCDC_PD_DATA22 (1ULL << 16)
+#define ATMEL_LCDC_PD_DATA23 (1ULL << 17)
+
+/* LCDC on port E */
+#define ATMEL_LCDC_PE_CC (1ULL << (32 + 0))
+#define ATMEL_LCDC_PE_DVAL (1ULL << (32 + 1))
+#define ATMEL_LCDC_PE_MODE (1ULL << (32 + 2))
+#define ATMEL_LCDC_PE_DATA0 (1ULL << (32 + 3))
+#define ATMEL_LCDC_PE_DATA1 (1ULL << (32 + 4))
+#define ATMEL_LCDC_PE_DATA2 (1ULL << (32 + 5))
+#define ATMEL_LCDC_PE_DATA3 (1ULL << (32 + 6))
+#define ATMEL_LCDC_PE_DATA4 (1ULL << (32 + 7))
+#define ATMEL_LCDC_PE_DATA8 (1ULL << (32 + 8))
+#define ATMEL_LCDC_PE_DATA9 (1ULL << (32 + 9))
+#define ATMEL_LCDC_PE_DATA10 (1ULL << (32 + 10))
+#define ATMEL_LCDC_PE_DATA11 (1ULL << (32 + 11))
+#define ATMEL_LCDC_PE_DATA12 (1ULL << (32 + 12))
+#define ATMEL_LCDC_PE_DATA16 (1ULL << (32 + 13))
+#define ATMEL_LCDC_PE_DATA17 (1ULL << (32 + 14))
+#define ATMEL_LCDC_PE_DATA18 (1ULL << (32 + 15))
+#define ATMEL_LCDC_PE_DATA19 (1ULL << (32 + 16))
+#define ATMEL_LCDC_PE_DATA20 (1ULL << (32 + 17))
+#define ATMEL_LCDC_PE_DATA21 (1ULL << (32 + 18))
+
+
+#define ATMEL_LCDC(PORT, PIN) (ATMEL_LCDC_##PORT##_##PIN)
+
+
+#define ATMEL_LCDC_PRI_24B_DATA ( \
+ ATMEL_LCDC(PC, DATA0) | ATMEL_LCDC(PC, DATA1) | \
+ ATMEL_LCDC(PC, DATA2) | ATMEL_LCDC(PC, DATA3) | \
+ ATMEL_LCDC(PC, DATA4) | ATMEL_LCDC(PC, DATA5) | \
+ ATMEL_LCDC(PD, DATA6) | ATMEL_LCDC(PD, DATA7) | \
+ ATMEL_LCDC(PD, DATA8) | ATMEL_LCDC(PD, DATA9) | \
+ ATMEL_LCDC(PD, DATA10) | ATMEL_LCDC(PD, DATA11) | \
+ ATMEL_LCDC(PD, DATA12) | ATMEL_LCDC(PD, DATA13) | \
+ ATMEL_LCDC(PD, DATA14) | ATMEL_LCDC(PD, DATA15) | \
+ ATMEL_LCDC(PD, DATA16) | ATMEL_LCDC(PD, DATA17) | \
+ ATMEL_LCDC(PD, DATA18) | ATMEL_LCDC(PD, DATA19) | \
+ ATMEL_LCDC(PD, DATA20) | ATMEL_LCDC(PD, DATA21) | \
+ ATMEL_LCDC(PD, DATA22) | ATMEL_LCDC(PD, DATA23))
+
+#define ATMEL_LCDC_ALT_24B_DATA ( \
+ ATMEL_LCDC(PE, DATA0) | ATMEL_LCDC(PE, DATA1) | \
+ ATMEL_LCDC(PE, DATA2) | ATMEL_LCDC(PE, DATA3) | \
+ ATMEL_LCDC(PE, DATA4) | ATMEL_LCDC(PC, DATA5) | \
+ ATMEL_LCDC(PD, DATA6) | ATMEL_LCDC(PD, DATA7) | \
+ ATMEL_LCDC(PE, DATA8) | ATMEL_LCDC(PE, DATA9) | \
+ ATMEL_LCDC(PE, DATA10) | ATMEL_LCDC(PE, DATA11) | \
+ ATMEL_LCDC(PE, DATA12) | ATMEL_LCDC(PD, DATA13) | \
+ ATMEL_LCDC(PD, DATA14) | ATMEL_LCDC(PD, DATA15) | \
+ ATMEL_LCDC(PE, DATA16) | ATMEL_LCDC(PE, DATA17) | \
+ ATMEL_LCDC(PE, DATA18) | ATMEL_LCDC(PE, DATA19) | \
+ ATMEL_LCDC(PE, DATA20) | ATMEL_LCDC(PE, DATA21) | \
+ ATMEL_LCDC(PD, DATA22) | ATMEL_LCDC(PD, DATA23))
+
+#define ATMEL_LCDC_PRI_15B_DATA ( \
+ ATMEL_LCDC(PC, DATA0) | ATMEL_LCDC(PC, DATA1) | \
+ ATMEL_LCDC(PC, DATA2) | ATMEL_LCDC(PC, DATA3) | \
+ ATMEL_LCDC(PC, DATA4) | ATMEL_LCDC(PC, DATA5) | \
+ ATMEL_LCDC(PD, DATA8) | ATMEL_LCDC(PD, DATA9) | \
+ ATMEL_LCDC(PD, DATA10) | ATMEL_LCDC(PD, DATA11) | \
+ ATMEL_LCDC(PD, DATA12) | ATMEL_LCDC(PD, DATA16) | \
+ ATMEL_LCDC(PD, DATA17) | ATMEL_LCDC(PD, DATA18) | \
+ ATMEL_LCDC(PD, DATA19) | ATMEL_LCDC(PD, DATA20))
+
+#define ATMEL_LCDC_ALT_15B_DATA ( \
+ ATMEL_LCDC(PE, DATA0) | ATMEL_LCDC(PE, DATA1) | \
+ ATMEL_LCDC(PE, DATA2) | ATMEL_LCDC(PE, DATA3) | \
+ ATMEL_LCDC(PE, DATA4) | ATMEL_LCDC(PC, DATA5) | \
+ ATMEL_LCDC(PE, DATA8) | ATMEL_LCDC(PE, DATA9) | \
+ ATMEL_LCDC(PE, DATA10) | ATMEL_LCDC(PE, DATA11) | \
+ ATMEL_LCDC(PE, DATA12) | ATMEL_LCDC(PE, DATA16) | \
+ ATMEL_LCDC(PE, DATA17) | ATMEL_LCDC(PE, DATA18) | \
+ ATMEL_LCDC(PE, DATA19) | ATMEL_LCDC(PE, DATA20))
+
+#define ATMEL_LCDC_PRI_CONTROL ( \
+ ATMEL_LCDC(PC, CC) | ATMEL_LCDC(PC, DVAL) | \
+ ATMEL_LCDC(PC, MODE) | ATMEL_LCDC(PC, PWR))
+
+#define ATMEL_LCDC_ALT_CONTROL ( \
+ ATMEL_LCDC(PE, CC) | ATMEL_LCDC(PE, DVAL) | \
+ ATMEL_LCDC(PE, MODE) | ATMEL_LCDC(PC, PWR))
+
+#define ATMEL_LCDC_CONTROL ( \
+ ATMEL_LCDC(PC, HSYNC) | ATMEL_LCDC(PC, VSYNC) | \
+ ATMEL_LCDC(PC, PCLK))
+
+#define ATMEL_LCDC_PRI_24BIT (ATMEL_LCDC_CONTROL | ATMEL_LCDC_PRI_24B_DATA)
+
+#define ATMEL_LCDC_ALT_24BIT (ATMEL_LCDC_CONTROL | ATMEL_LCDC_ALT_24B_DATA)
+
+#define ATMEL_LCDC_PRI_15BIT (ATMEL_LCDC_CONTROL | ATMEL_LCDC_PRI_15B_DATA)
+
+#define ATMEL_LCDC_ALT_15BIT (ATMEL_LCDC_CONTROL | ATMEL_LCDC_ALT_15B_DATA)
+
+#endif /* __ASM_ARCH_AT32AP700X_H__ */
diff --git a/arch/avr32/mach-at32ap/include/mach/board.h b/arch/avr32/mach-at32ap/include/mach/board.h
new file mode 100644
index 00000000000..c48386d66bc
--- /dev/null
+++ b/arch/avr32/mach-at32ap/include/mach/board.h
@@ -0,0 +1,121 @@
+/*
+ * Platform data definitions.
+ */
+#ifndef __ASM_ARCH_BOARD_H
+#define __ASM_ARCH_BOARD_H
+
+#include <linux/types.h>
+
+#define GPIO_PIN_NONE (-1)
+
+/*
+ * Clock rates for various on-board oscillators. The number of entries
+ * in this array is chip-dependent.
+ */
+extern unsigned long at32_board_osc_rates[];
+
+/* Add basic devices: system manager, interrupt controller, portmuxes, etc. */
+void at32_add_system_devices(void);
+
+#define ATMEL_MAX_UART 4
+extern struct platform_device *atmel_default_console_device;
+
+struct atmel_uart_data {
+ short use_dma_tx; /* use transmit DMA? */
+ short use_dma_rx; /* use receive DMA? */
+ void __iomem *regs; /* virtual base address, if any */
+};
+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 {
+ u32 phy_mask;
+ u8 is_rmii;
+};
+struct platform_device *
+at32_add_device_eth(unsigned int id, struct eth_platform_data *data);
+
+struct spi_board_info;
+struct platform_device *
+at32_add_device_spi(unsigned int id, struct spi_board_info *b, unsigned int n);
+
+struct atmel_lcdfb_info;
+struct platform_device *
+at32_add_device_lcdc(unsigned int id, struct atmel_lcdfb_info *data,
+ unsigned long fbmem_start, unsigned long fbmem_len,
+ u64 pin_mask);
+
+struct usba_platform_data;
+struct platform_device *
+at32_add_device_usba(unsigned int id, struct usba_platform_data *data);
+
+struct ide_platform_data {
+ u8 cs;
+};
+struct platform_device *
+at32_add_device_ide(unsigned int id, unsigned int extint,
+ struct ide_platform_data *data);
+
+/* mask says which PWM channels to mux */
+struct platform_device *at32_add_device_pwm(u32 mask);
+
+/* 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);
+
+struct i2c_board_info;
+struct platform_device *at32_add_device_twi(unsigned int id,
+ struct i2c_board_info *b,
+ unsigned int n);
+
+struct mci_platform_data;
+struct platform_device *
+at32_add_device_mci(unsigned int id, struct mci_platform_data *data);
+
+struct ac97c_platform_data {
+ unsigned short dma_rx_periph_id;
+ unsigned short dma_tx_periph_id;
+ unsigned short dma_controller_id;
+ int reset_pin;
+};
+struct platform_device *
+at32_add_device_ac97c(unsigned int id, struct ac97c_platform_data *data);
+
+struct platform_device *at32_add_device_abdac(unsigned int id);
+struct platform_device *at32_add_device_psif(unsigned int id);
+
+struct cf_platform_data {
+ int detect_pin;
+ int reset_pin;
+ int vcc_pin;
+ int ready_pin;
+ u8 cs;
+};
+struct platform_device *
+at32_add_device_cf(unsigned int id, unsigned int extint,
+ struct cf_platform_data *data);
+
+/* NAND / SmartMedia */
+struct atmel_nand_data {
+ int enable_pin; /* chip enable */
+ int det_pin; /* card detect */
+ int rdy_pin; /* ready/busy */
+ u8 ale; /* address line number connected to ALE */
+ u8 cle; /* address line number connected to CLE */
+ u8 bus_width_16; /* buswidth is 16 bit */
+ struct mtd_partition *(*partition_info)(int size, int *num_partitions);
+};
+struct platform_device *
+at32_add_device_nand(unsigned int id, struct atmel_nand_data *data);
+
+#endif /* __ASM_ARCH_BOARD_H */
diff --git a/arch/avr32/mach-at32ap/include/mach/chip.h b/arch/avr32/mach-at32ap/include/mach/chip.h
new file mode 100644
index 00000000000..5efca6da6ac
--- /dev/null
+++ b/arch/avr32/mach-at32ap/include/mach/chip.h
@@ -0,0 +1,19 @@
+/*
+ * AVR32 chip-specific definitions
+ *
+ * Copyright (C) 2008 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_ARCH_CHIP_H__
+#define __ASM_AVR32_ARCH_CHIP_H__
+
+#if defined(CONFIG_CPU_AT32AP700X)
+# include <mach/at32ap700x.h>
+#else
+# error Unknown chip type selected
+#endif
+
+#endif /* __ASM_AVR32_ARCH_CHIP_H__ */
diff --git a/arch/avr32/mach-at32ap/include/mach/cpu.h b/arch/avr32/mach-at32ap/include/mach/cpu.h
new file mode 100644
index 00000000000..44d0bfa1f40
--- /dev/null
+++ b/arch/avr32/mach-at32ap/include/mach/cpu.h
@@ -0,0 +1,35 @@
+/*
+ * AVR32 and (fake) AT91 CPU identification
+ *
+ * Copyright (C) 2007 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_CPU_H
+#define __ASM_ARCH_CPU_H
+
+/*
+ * Only AT32AP7000 is defined for now. We can identify the specific
+ * chip at runtime, but I'm not sure if it's really worth it.
+ */
+#ifdef CONFIG_CPU_AT32AP700X
+# define cpu_is_at32ap7000() (1)
+#else
+# define cpu_is_at32ap7000() (0)
+#endif
+
+/*
+ * Since this is AVR32, we will never run on any AT91 CPU. But these
+ * definitions may reduce clutter in common drivers.
+ */
+#define cpu_is_at91rm9200() (0)
+#define cpu_is_at91sam9xe() (0)
+#define cpu_is_at91sam9260() (0)
+#define cpu_is_at91sam9261() (0)
+#define cpu_is_at91sam9263() (0)
+#define cpu_is_at91sam9rl() (0)
+#define cpu_is_at91cap9() (0)
+
+#endif /* __ASM_ARCH_CPU_H */
diff --git a/arch/avr32/mach-at32ap/include/mach/gpio.h b/arch/avr32/mach-at32ap/include/mach/gpio.h
new file mode 100644
index 00000000000..0180f584ef0
--- /dev/null
+++ b/arch/avr32/mach-at32ap/include/mach/gpio.h
@@ -0,0 +1,45 @@
+#ifndef __ASM_AVR32_ARCH_GPIO_H
+#define __ASM_AVR32_ARCH_GPIO_H
+
+#include <linux/compiler.h>
+#include <asm/irq.h>
+
+
+/* Some GPIO chips can manage IRQs; some can't. The exact numbers can
+ * be changed if needed, but for the moment they're not configurable.
+ */
+#define ARCH_NR_GPIOS (NR_GPIO_IRQS + 2 * 32)
+
+
+/* Arch-neutral GPIO API, supporting both "native" and external GPIOs. */
+#include <asm-generic/gpio.h>
+
+static inline int gpio_get_value(unsigned int gpio)
+{
+ return __gpio_get_value(gpio);
+}
+
+static inline void gpio_set_value(unsigned int gpio, int value)
+{
+ __gpio_set_value(gpio, value);
+}
+
+static inline int gpio_cansleep(unsigned int gpio)
+{
+ return __gpio_cansleep(gpio);
+}
+
+
+static inline int gpio_to_irq(unsigned int gpio)
+{
+ if (gpio < NR_GPIO_IRQS)
+ return gpio + GPIO_IRQ_BASE;
+ return -EINVAL;
+}
+
+static inline int irq_to_gpio(unsigned int irq)
+{
+ return irq - GPIO_IRQ_BASE;
+}
+
+#endif /* __ASM_AVR32_ARCH_GPIO_H */
diff --git a/arch/avr32/mach-at32ap/include/mach/hmatrix.h b/arch/avr32/mach-at32ap/include/mach/hmatrix.h
new file mode 100644
index 00000000000..7a368f227eb
--- /dev/null
+++ b/arch/avr32/mach-at32ap/include/mach/hmatrix.h
@@ -0,0 +1,55 @@
+/*
+ * High-Speed Bus Matrix configuration registers
+ *
+ * Copyright (C) 2008 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 __HMATRIX_H
+#define __HMATRIX_H
+
+extern struct clk at32_hmatrix_clk;
+
+void hmatrix_write_reg(unsigned long offset, u32 value);
+u32 hmatrix_read_reg(unsigned long offset);
+
+void hmatrix_sfr_set_bits(unsigned int slave_id, u32 mask);
+void hmatrix_sfr_clear_bits(unsigned int slave_id, u32 mask);
+
+/* Master Configuration register */
+#define HMATRIX_MCFG(m) (0x0000 + 4 * (m))
+/* Undefined length burst limit */
+# define HMATRIX_MCFG_ULBT_INFINITE 0 /* Infinite length */
+# define HMATRIX_MCFG_ULBT_SINGLE 1 /* Single Access */
+# define HMATRIX_MCFG_ULBT_FOUR_BEAT 2 /* Four beat */
+# define HMATRIX_MCFG_ULBT_EIGHT_BEAT 3 /* Eight beat */
+# define HMATRIX_MCFG_ULBT_SIXTEEN_BEAT 4 /* Sixteen beat */
+
+/* Slave Configuration register */
+#define HMATRIX_SCFG(s) (0x0040 + 4 * (s))
+# define HMATRIX_SCFG_SLOT_CYCLE(x) ((x) << 0) /* Max burst cycles */
+# define HMATRIX_SCFG_DEFMSTR_NONE ( 0 << 16) /* No default master */
+# define HMATRIX_SCFG_DEFMSTR_LAST ( 1 << 16) /* Last def master */
+# define HMATRIX_SCFG_DEFMSTR_FIXED ( 2 << 16) /* Fixed def master */
+# define HMATRIX_SCFG_FIXED_DEFMSTR(m) ((m) << 18) /* Fixed master ID */
+# define HMATRIX_SCFG_ARBT_ROUND_ROBIN ( 0 << 24) /* RR arbitration */
+# define HMATRIX_SCFG_ARBT_FIXED_PRIO ( 1 << 24) /* Fixed priority */
+
+/* Slave Priority register A (master 0..7) */
+#define HMATRIX_PRAS(s) (0x0080 + 8 * (s))
+# define HMATRIX_PRAS_PRIO(m, p) ((p) << ((m) * 4))
+
+/* Slave Priority register A (master 8..15) */
+#define HMATRIX_PRBS(s) (0x0084 + 8 * (s))
+# define HMATRIX_PRBS_PRIO(m, p) ((p) << (((m) - 8) * 4))
+
+/* Master Remap Control Register */
+#define HMATRIX_MRCR 0x0100
+# define HMATRIX_MRCR_REMAP(m) ( 1 << (m)) /* Remap master m */
+
+/* Special Function Register. Bit definitions are chip-specific */
+#define HMATRIX_SFR(s) (0x0110 + 4 * (s))
+
+#endif /* __HMATRIX_H */
diff --git a/arch/avr32/mach-at32ap/include/mach/init.h b/arch/avr32/mach-at32ap/include/mach/init.h
new file mode 100644
index 00000000000..bc40e3d4615
--- /dev/null
+++ b/arch/avr32/mach-at32ap/include/mach/init.h
@@ -0,0 +1,18 @@
+/*
+ * AT32AP platform initialization calls.
+ *
+ * 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_AT32AP_INIT_H__
+#define __ASM_AVR32_AT32AP_INIT_H__
+
+void setup_platform(void);
+void setup_board(void);
+
+void at32_setup_serial_console(unsigned int usart_id);
+
+#endif /* __ASM_AVR32_AT32AP_INIT_H__ */
diff --git a/arch/avr32/mach-at32ap/include/mach/io.h b/arch/avr32/mach-at32ap/include/mach/io.h
new file mode 100644
index 00000000000..22ea79b7405
--- /dev/null
+++ b/arch/avr32/mach-at32ap/include/mach/io.h
@@ -0,0 +1,38 @@
+#ifndef __ASM_AVR32_ARCH_AT32AP_IO_H
+#define __ASM_AVR32_ARCH_AT32AP_IO_H
+
+#include <linux/swab.h>
+
+#if defined(CONFIG_AP700X_32_BIT_SMC)
+# define __swizzle_addr_b(addr) (addr ^ 3UL)
+# define __swizzle_addr_w(addr) (addr ^ 2UL)
+# define __swizzle_addr_l(addr) (addr)
+# define ioswabb(a, x) (x)
+# define ioswabw(a, x) (x)
+# define ioswabl(a, x) (x)
+# define __mem_ioswabb(a, x) (x)
+# define __mem_ioswabw(a, x) swab16(x)
+# define __mem_ioswabl(a, x) swab32(x)
+#elif defined(CONFIG_AP700X_16_BIT_SMC)
+# define __swizzle_addr_b(addr) (addr ^ 1UL)
+# define __swizzle_addr_w(addr) (addr)
+# define __swizzle_addr_l(addr) (addr)
+# define ioswabb(a, x) (x)
+# define ioswabw(a, x) (x)
+# define ioswabl(a, x) swahw32(x)
+# define __mem_ioswabb(a, x) (x)
+# define __mem_ioswabw(a, x) swab16(x)
+# define __mem_ioswabl(a, x) swahb32(x)
+#else
+# define __swizzle_addr_b(addr) (addr)
+# define __swizzle_addr_w(addr) (addr)
+# define __swizzle_addr_l(addr) (addr)
+# define ioswabb(a, x) (x)
+# define ioswabw(a, x) swab16(x)
+# define ioswabl(a, x) swab32(x)
+# define __mem_ioswabb(a, x) (x)
+# define __mem_ioswabw(a, x) (x)
+# define __mem_ioswabl(a, x) (x)
+#endif
+
+#endif /* __ASM_AVR32_ARCH_AT32AP_IO_H */
diff --git a/arch/avr32/mach-at32ap/include/mach/irq.h b/arch/avr32/mach-at32ap/include/mach/irq.h
new file mode 100644
index 00000000000..608e350368c
--- /dev/null
+++ b/arch/avr32/mach-at32ap/include/mach/irq.h
@@ -0,0 +1,14 @@
+#ifndef __ASM_AVR32_ARCH_IRQ_H
+#define __ASM_AVR32_ARCH_IRQ_H
+
+#define EIM_IRQ_BASE NR_INTERNAL_IRQS
+#define NR_EIM_IRQS 32
+#define AT32_EXTINT(n) (EIM_IRQ_BASE + (n))
+
+#define GPIO_IRQ_BASE (EIM_IRQ_BASE + NR_EIM_IRQS)
+#define NR_GPIO_CTLR (5 /*internal*/ + 1 /*external*/)
+#define NR_GPIO_IRQS (NR_GPIO_CTLR * 32)
+
+#define NR_IRQS (GPIO_IRQ_BASE + NR_GPIO_IRQS)
+
+#endif /* __ASM_AVR32_ARCH_IRQ_H */
diff --git a/arch/avr32/mach-at32ap/include/mach/pm.h b/arch/avr32/mach-at32ap/include/mach/pm.h
new file mode 100644
index 00000000000..979b355b77b
--- /dev/null
+++ b/arch/avr32/mach-at32ap/include/mach/pm.h
@@ -0,0 +1,51 @@
+/*
+ * AVR32 AP Power Management.
+ *
+ * Copyright (C) 2008 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_ARCH_PM_H
+#define __ASM_AVR32_ARCH_PM_H
+
+/* Possible arguments to the "sleep" instruction */
+#define CPU_SLEEP_IDLE 0
+#define CPU_SLEEP_FROZEN 1
+#define CPU_SLEEP_STANDBY 2
+#define CPU_SLEEP_STOP 3
+#define CPU_SLEEP_STATIC 5
+
+#ifndef __ASSEMBLY__
+extern void cpu_enter_idle(void);
+extern void cpu_enter_standby(unsigned long sdramc_base);
+
+extern bool disable_idle_sleep;
+
+static inline void cpu_disable_idle_sleep(void)
+{
+ disable_idle_sleep = true;
+}
+
+static inline void cpu_enable_idle_sleep(void)
+{
+ disable_idle_sleep = false;
+}
+
+static inline void cpu_idle_sleep(void)
+{
+ /*
+ * If we're using the COUNT and COMPARE registers for
+ * timekeeping, we can't use the IDLE state.
+ */
+ if (disable_idle_sleep)
+ cpu_relax();
+ else
+ cpu_enter_idle();
+}
+
+void intc_set_suspend_handler(unsigned long offset);
+#endif
+
+#endif /* __ASM_AVR32_ARCH_PM_H */
diff --git a/arch/avr32/mach-at32ap/include/mach/portmux.h b/arch/avr32/mach-at32ap/include/mach/portmux.h
new file mode 100644
index 00000000000..21c79373b53
--- /dev/null
+++ b/arch/avr32/mach-at32ap/include/mach/portmux.h
@@ -0,0 +1,30 @@
+/*
+ * AT32 portmux 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_ARCH_PORTMUX_H__
+#define __ASM_ARCH_PORTMUX_H__
+
+/*
+ * Set up pin multiplexing, called from board init only.
+ *
+ * The following flags determine the initial state of the pin.
+ */
+#define AT32_GPIOF_PULLUP 0x00000001 /* (not-OUT) Enable pull-up */
+#define AT32_GPIOF_OUTPUT 0x00000002 /* (OUT) Enable output driver */
+#define AT32_GPIOF_HIGH 0x00000004 /* (OUT) Set output high */
+#define AT32_GPIOF_DEGLITCH 0x00000008 /* (IN) Filter glitches */
+#define AT32_GPIOF_MULTIDRV 0x00000010 /* Enable multidriver option */
+
+void at32_select_periph(unsigned int port, unsigned int pin,
+ unsigned int periph, unsigned long flags);
+void at32_select_gpio(unsigned int pin, unsigned long flags);
+void at32_deselect_pin(unsigned int pin);
+void at32_reserve_pin(unsigned int pin);
+
+#endif /* __ASM_ARCH_PORTMUX_H__ */
diff --git a/arch/avr32/mach-at32ap/include/mach/smc.h b/arch/avr32/mach-at32ap/include/mach/smc.h
new file mode 100644
index 00000000000..c98eea44a70
--- /dev/null
+++ b/arch/avr32/mach-at32ap/include/mach/smc.h
@@ -0,0 +1,113 @@
+/*
+ * Static Memory Controller for AT32 chips
+ *
+ * Copyright (C) 2006 Atmel Corporation
+ *
+ * Inspired by the OMAP2 General-Purpose Memory Controller interface
+ *
+ * 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 __ARCH_AT32AP_SMC_H
+#define __ARCH_AT32AP_SMC_H
+
+/*
+ * All timing parameters are in nanoseconds.
+ */
+struct smc_timing {
+ /* Delay from address valid to assertion of given strobe */
+ int ncs_read_setup;
+ int nrd_setup;
+ int ncs_write_setup;
+ int nwe_setup;
+
+ /* Pulse length of given strobe */
+ int ncs_read_pulse;
+ int nrd_pulse;
+ int ncs_write_pulse;
+ int nwe_pulse;
+
+ /* Total cycle length of given operation */
+ int read_cycle;
+ int write_cycle;
+
+ /* Minimal recovery times, will extend cycle if needed */
+ int ncs_read_recover;
+ int nrd_recover;
+ int ncs_write_recover;
+ int nwe_recover;
+};
+
+/*
+ * All timing parameters are in clock cycles.
+ */
+struct smc_config {
+
+ /* Delay from address valid to assertion of given strobe */
+ u8 ncs_read_setup;
+ u8 nrd_setup;
+ u8 ncs_write_setup;
+ u8 nwe_setup;
+
+ /* Pulse length of given strobe */
+ u8 ncs_read_pulse;
+ u8 nrd_pulse;
+ u8 ncs_write_pulse;
+ u8 nwe_pulse;
+
+ /* Total cycle length of given operation */
+ u8 read_cycle;
+ u8 write_cycle;
+
+ /* Bus width in bytes */
+ u8 bus_width;
+
+ /*
+ * 0: Data is sampled on rising edge of NCS
+ * 1: Data is sampled on rising edge of NRD
+ */
+ unsigned int nrd_controlled:1;
+
+ /*
+ * 0: Data is driven on falling edge of NCS
+ * 1: Data is driven on falling edge of NWR
+ */
+ unsigned int nwe_controlled:1;
+
+ /*
+ * 0: NWAIT is disabled
+ * 1: Reserved
+ * 2: NWAIT is frozen mode
+ * 3: NWAIT in ready mode
+ */
+ unsigned int nwait_mode:2;
+
+ /*
+ * 0: Byte select access type
+ * 1: Byte write access type
+ */
+ unsigned int byte_write:1;
+
+ /*
+ * Number of clock cycles before data is released after
+ * the rising edge of the read controlling signal
+ *
+ * Total cycles from SMC is tdf_cycles + 1
+ */
+ unsigned int tdf_cycles:4;
+
+ /*
+ * 0: TDF optimization disabled
+ * 1: TDF optimization enabled
+ */
+ unsigned int tdf_mode:1;
+};
+
+extern void smc_set_timing(struct smc_config *config,
+ const struct smc_timing *timing);
+
+extern int smc_set_configuration(int cs, const struct smc_config *config);
+extern struct smc_config *smc_get_configuration(int cs);
+
+#endif /* __ARCH_AT32AP_SMC_H */
diff --git a/arch/avr32/mach-at32ap/include/mach/sram.h b/arch/avr32/mach-at32ap/include/mach/sram.h
new file mode 100644
index 00000000000..4838dae7601
--- /dev/null
+++ b/arch/avr32/mach-at32ap/include/mach/sram.h
@@ -0,0 +1,30 @@
+/*
+ * Simple SRAM allocator
+ *
+ * Copyright (C) 2008 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_ARCH_SRAM_H
+#define __ASM_AVR32_ARCH_SRAM_H
+
+#include <linux/genalloc.h>
+
+extern struct gen_pool *sram_pool;
+
+static inline unsigned long sram_alloc(size_t len)
+{
+ if (!sram_pool)
+ return 0UL;
+
+ return gen_pool_alloc(sram_pool, len);
+}
+
+static inline void sram_free(unsigned long addr, size_t len)
+{
+ return gen_pool_free(sram_pool, addr, len);
+}
+
+#endif /* __ASM_AVR32_ARCH_SRAM_H */
diff --git a/arch/avr32/mach-at32ap/intc.c b/arch/avr32/mach-at32ap/intc.c
index 097cf4e8405..994c4545e2b 100644
--- a/arch/avr32/mach-at32ap/intc.c
+++ b/arch/avr32/mach-at32ap/intc.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006 Atmel Corporation
+ * Copyright (C) 2006, 2008 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
@@ -12,14 +12,20 @@
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/platform_device.h>
+#include <linux/sysdev.h>
#include <asm/io.h>
#include "intc.h"
struct intc {
- void __iomem *regs;
- struct irq_chip chip;
+ void __iomem *regs;
+ struct irq_chip chip;
+ struct sys_device sysdev;
+#ifdef CONFIG_PM
+ unsigned long suspend_ipr;
+ unsigned long saved_ipr[64];
+#endif
};
extern struct platform_device at32_intc0_device;
@@ -136,6 +142,74 @@ fail:
panic("Interrupt controller initialization failed!\n");
}
+#ifdef CONFIG_PM
+void intc_set_suspend_handler(unsigned long offset)
+{
+ intc0.suspend_ipr = offset;
+}
+
+static int intc_suspend(struct sys_device *sdev, pm_message_t state)
+{
+ struct intc *intc = container_of(sdev, struct intc, sysdev);
+ int i;
+
+ if (unlikely(!irqs_disabled())) {
+ pr_err("intc_suspend: called with interrupts enabled\n");
+ return -EINVAL;
+ }
+
+ if (unlikely(!intc->suspend_ipr)) {
+ pr_err("intc_suspend: suspend_ipr not initialized\n");
+ return -EINVAL;
+ }
+
+ for (i = 0; i < 64; i++) {
+ intc->saved_ipr[i] = intc_readl(intc, INTPR0 + 4 * i);
+ intc_writel(intc, INTPR0 + 4 * i, intc->suspend_ipr);
+ }
+
+ return 0;
+}
+
+static int intc_resume(struct sys_device *sdev)
+{
+ struct intc *intc = container_of(sdev, struct intc, sysdev);
+ int i;
+
+ WARN_ON(!irqs_disabled());
+
+ for (i = 0; i < 64; i++)
+ intc_writel(intc, INTPR0 + 4 * i, intc->saved_ipr[i]);
+
+ return 0;
+}
+#else
+#define intc_suspend NULL
+#define intc_resume NULL
+#endif
+
+static struct sysdev_class intc_class = {
+ .name = "intc",
+ .suspend = intc_suspend,
+ .resume = intc_resume,
+};
+
+static int __init intc_init_sysdev(void)
+{
+ int ret;
+
+ ret = sysdev_class_register(&intc_class);
+ if (ret)
+ return ret;
+
+ intc0.sysdev.id = 0;
+ intc0.sysdev.cls = &intc_class;
+ ret = sysdev_register(&intc0.sysdev);
+
+ return ret;
+}
+device_initcall(intc_init_sysdev);
+
unsigned long intc_get_pending(unsigned int group)
{
return intc_readl(&intc0, INTREQ0 + 4 * group);
diff --git a/arch/avr32/mach-at32ap/at32ap.c b/arch/avr32/mach-at32ap/pdc.c
index 7c4987f3287..61ab15aae97 100644
--- a/arch/avr32/mach-at32ap/at32ap.c
+++ b/arch/avr32/mach-at32ap/pdc.c
@@ -11,14 +11,6 @@
#include <linux/init.h>
#include <linux/platform_device.h>
-#include <asm/arch/init.h>
-
-void __init setup_platform(void)
-{
- at32_clock_init();
- at32_portmux_init();
-}
-
static int __init pdc_probe(struct platform_device *pdev)
{
struct clk *pclk, *hclk;
@@ -43,7 +35,6 @@ static int __init pdc_probe(struct platform_device *pdev)
}
static struct platform_driver pdc_driver = {
- .probe = pdc_probe,
.driver = {
.name = "pdc",
},
@@ -51,6 +42,6 @@ static struct platform_driver pdc_driver = {
static int __init pdc_init(void)
{
- return platform_driver_register(&pdc_driver);
+ return platform_driver_probe(&pdc_driver, pdc_probe);
}
arch_initcall(pdc_init);
diff --git a/arch/avr32/mach-at32ap/pio.c b/arch/avr32/mach-at32ap/pio.c
index 38a8fa31c0b..ed81a8bcb22 100644
--- a/arch/avr32/mach-at32ap/pio.c
+++ b/arch/avr32/mach-at32ap/pio.c
@@ -17,7 +17,7 @@
#include <asm/gpio.h>
#include <asm/io.h>
-#include <asm/arch/portmux.h>
+#include <mach/portmux.h>
#include "pio.h"
@@ -50,35 +50,48 @@ static struct pio_device *gpio_to_pio(unsigned int gpio)
}
/* Pin multiplexing API */
+static DEFINE_SPINLOCK(pio_lock);
-void __init at32_select_periph(unsigned int pin, unsigned int periph,
- unsigned long flags)
+void __init at32_select_periph(unsigned int port, u32 pin_mask,
+ 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);
+ /* assign and verify pio */
+ pio = gpio_to_pio(port);
if (unlikely(!pio)) {
- printk("pio: invalid pin %u\n", pin);
+ printk(KERN_WARNING "pio: invalid port %u\n", port);
goto fail;
}
- if (unlikely(test_and_set_bit(pin_index, &pio->pinmux_mask)
- || gpiochip_is_requested(&pio->chip, pin_index))) {
- printk("%s: pin %u is busy\n", pio->name, pin_index);
+ /* Test if any of the requested pins is already muxed */
+ spin_lock(&pio_lock);
+ if (unlikely(pio->pinmux_mask & pin_mask)) {
+ printk(KERN_WARNING "%s: pin(s) busy (requested 0x%x, busy 0x%x)\n",
+ pio->name, pin_mask, pio->pinmux_mask & pin_mask);
+ spin_unlock(&pio_lock);
goto fail;
}
- pio_writel(pio, PUER, mask);
+ pio->pinmux_mask |= pin_mask;
+
+ /* enable pull ups */
+ pio_writel(pio, PUER, pin_mask);
+
+ /* select either peripheral A or B */
if (periph)
- pio_writel(pio, BSR, mask);
+ pio_writel(pio, BSR, pin_mask);
else
- pio_writel(pio, ASR, mask);
+ pio_writel(pio, ASR, pin_mask);
+
+ /* enable peripheral control */
+ pio_writel(pio, PDR, pin_mask);
- pio_writel(pio, PDR, mask);
+ /* Disable pull ups if not requested. */
if (!(flags & AT32_GPIOF_PULLUP))
- pio_writel(pio, PUDR, mask);
+ pio_writel(pio, PUDR, pin_mask);
+
+ spin_unlock(&pio_lock);
return;
@@ -134,6 +147,25 @@ fail:
dump_stack();
}
+/*
+ * Undo a previous pin reservation. Will not affect the hardware
+ * configuration.
+ */
+void at32_deselect_pin(unsigned int pin)
+{
+ struct pio_device *pio;
+ unsigned int pin_index = pin & 0x1f;
+
+ pio = gpio_to_pio(pin);
+ if (unlikely(!pio)) {
+ printk("pio: invalid pin %u\n", pin);
+ dump_stack();
+ return;
+ }
+
+ clear_bit(pin_index, &pio->pinmux_mask);
+}
+
/* Reserve a pin, preventing anyone else from changing its configuration. */
void __init at32_reserve_pin(unsigned int pin)
{
@@ -318,6 +350,8 @@ static void pio_bank_show(struct seq_file *s, struct gpio_chip *chip)
const char *label;
label = gpiochip_is_requested(chip, i);
+ if (!label && (imr & mask))
+ label = "[irq]";
if (!label)
continue;
@@ -358,6 +392,8 @@ static int __init pio_probe(struct platform_device *pdev)
pio->chip.label = pio->name;
pio->chip.base = pdev->id * 32;
pio->chip.ngpio = 32;
+ pio->chip.dev = &pdev->dev;
+ pio->chip.owner = THIS_MODULE;
pio->chip.direction_input = direction_input;
pio->chip.get = gpio_get;
@@ -378,7 +414,6 @@ static int __init pio_probe(struct platform_device *pdev)
}
static struct platform_driver pio_driver = {
- .probe = pio_probe,
.driver = {
.name = "pio",
},
@@ -386,7 +421,7 @@ static struct platform_driver pio_driver = {
static int __init pio_init(void)
{
- return platform_driver_register(&pio_driver);
+ return platform_driver_probe(&pio_driver, pio_probe);
}
postcore_initcall(pio_init);
diff --git a/arch/avr32/mach-at32ap/pio.h b/arch/avr32/mach-at32ap/pio.h
index 7795116a483..9484dfcc08f 100644
--- a/arch/avr32/mach-at32ap/pio.h
+++ b/arch/avr32/mach-at32ap/pio.h
@@ -57,7 +57,7 @@
/* Bitfields in IFDR */
-/* Bitfields in ISFR */
+/* Bitfields in IFSR */
/* Bitfields in SODR */
diff --git a/arch/avr32/mach-at32ap/pm-at32ap700x.S b/arch/avr32/mach-at32ap/pm-at32ap700x.S
index 949e2485e27..17503b0ed6c 100644
--- a/arch/avr32/mach-at32ap/pm-at32ap700x.S
+++ b/arch/avr32/mach-at32ap/pm-at32ap700x.S
@@ -10,7 +10,13 @@
#include <asm/asm.h>
#include <asm/asm-offsets.h>
#include <asm/thread_info.h>
-#include <asm/arch/pm.h>
+#include <mach/pm.h>
+
+#include "pm.h"
+#include "sdramc.h"
+
+/* Same as 0xfff00000 but fits in a 21 bit signed immediate */
+#define PM_BASE -0x100000
.section .bss, "wa", @nobits
.global disable_idle_sleep
@@ -64,3 +70,105 @@ cpu_idle_skip_sleep:
unmask_interrupts
retal r12
.size cpu_idle_skip_sleep, . - cpu_idle_skip_sleep
+
+#ifdef CONFIG_PM
+ .section .init.text, "ax", @progbits
+
+ .global pm_exception
+ .type pm_exception, @function
+pm_exception:
+ /*
+ * Exceptions are masked when we switch to this handler, so
+ * we'll only get "unrecoverable" exceptions (offset 0.)
+ */
+ sub r12, pc, . - .Lpanic_msg
+ lddpc pc, .Lpanic_addr
+
+ .align 2
+.Lpanic_addr:
+ .long panic
+.Lpanic_msg:
+ .asciz "Unrecoverable exception during suspend\n"
+ .size pm_exception, . - pm_exception
+
+ .global pm_irq0
+ .type pm_irq0, @function
+pm_irq0:
+ /* Disable interrupts and return after the sleep instruction */
+ mfsr r9, SYSREG_RSR_INT0
+ mtsr SYSREG_RAR_INT0, r8
+ sbr r9, SYSREG_GM_OFFSET
+ mtsr SYSREG_RSR_INT0, r9
+ rete
+
+ /*
+ * void cpu_enter_standby(unsigned long sdramc_base)
+ *
+ * Enter PM_SUSPEND_STANDBY mode. At this point, all drivers
+ * are suspended and interrupts are disabled. Interrupts
+ * marked as 'wakeup' event sources may still come along and
+ * get us out of here.
+ *
+ * The SDRAM will be put into self-refresh mode (which does
+ * not require a clock from the CPU), and the CPU will be put
+ * into "frozen" mode (HSB bus stopped). The SDRAM controller
+ * will automatically bring the SDRAM into normal mode on the
+ * first access, and the power manager will automatically
+ * start the HSB and CPU clocks upon a wakeup event.
+ *
+ * This code uses the same "skip sleep" technique as above.
+ * It is very important that we jump directly to
+ * cpu_after_sleep after the sleep instruction since that's
+ * where we'll end up if the interrupt handler decides that we
+ * need to skip the sleep instruction.
+ */
+ .global pm_standby
+ .type pm_standby, @function
+pm_standby:
+ /*
+ * interrupts are already masked at this point, and EVBA
+ * points to pm_exception above.
+ */
+ ld.w r10, r12[SDRAMC_LPR]
+ sub r8, pc, . - 1f /* return address for irq handler */
+ mov r11, SDRAMC_LPR_LPCB_SELF_RFR
+ bfins r10, r11, 0, 2 /* LPCB <- self Refresh */
+ sync 0 /* flush write buffer */
+ st.w r12[SDRAMC_LPR], r10 /* put SDRAM in self-refresh mode */
+ ld.w r11, r12[SDRAMC_LPR]
+ unmask_interrupts
+ sleep CPU_SLEEP_FROZEN
+1: mask_interrupts
+ retal r12
+ .size pm_standby, . - pm_standby
+
+ .global pm_suspend_to_ram
+ .type pm_suspend_to_ram, @function
+pm_suspend_to_ram:
+ /*
+ * interrupts are already masked at this point, and EVBA
+ * points to pm_exception above.
+ */
+ mov r11, 0
+ cache r11[2], 8 /* clean all dcache lines */
+ sync 0 /* flush write buffer */
+ ld.w r10, r12[SDRAMC_LPR]
+ sub r8, pc, . - 1f /* return address for irq handler */
+ mov r11, SDRAMC_LPR_LPCB_SELF_RFR
+ bfins r10, r11, 0, 2 /* LPCB <- self refresh */
+ st.w r12[SDRAMC_LPR], r10 /* put SDRAM in self-refresh mode */
+ ld.w r11, r12[SDRAMC_LPR]
+
+ unmask_interrupts
+ sleep CPU_SLEEP_STOP
+1: mask_interrupts
+
+ retal r12
+ .size pm_suspend_to_ram, . - pm_suspend_to_ram
+
+ .global pm_sram_end
+ .type pm_sram_end, @function
+pm_sram_end:
+ .size pm_sram_end, 0
+
+#endif /* CONFIG_PM */
diff --git a/arch/avr32/mach-at32ap/pm.c b/arch/avr32/mach-at32ap/pm.c
new file mode 100644
index 00000000000..f021edfeaab
--- /dev/null
+++ b/arch/avr32/mach-at32ap/pm.c
@@ -0,0 +1,243 @@
+/*
+ * AVR32 AP Power Management
+ *
+ * Copyright (C) 2008 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/io.h>
+#include <linux/suspend.h>
+#include <linux/vmalloc.h>
+
+#include <asm/cacheflush.h>
+#include <asm/sysreg.h>
+
+#include <mach/chip.h>
+#include <mach/pm.h>
+#include <mach/sram.h>
+
+#include "sdramc.h"
+
+#define SRAM_PAGE_FLAGS (SYSREG_BIT(TLBELO_D) | SYSREG_BF(SZ, 1) \
+ | SYSREG_BF(AP, 3) | SYSREG_BIT(G))
+
+
+static unsigned long pm_sram_start;
+static size_t pm_sram_size;
+static struct vm_struct *pm_sram_area;
+
+static void (*avr32_pm_enter_standby)(unsigned long sdramc_base);
+static void (*avr32_pm_enter_str)(unsigned long sdramc_base);
+
+/*
+ * Must be called with interrupts disabled. Exceptions will be masked
+ * on return (i.e. all exceptions will be "unrecoverable".)
+ */
+static void *avr32_pm_map_sram(void)
+{
+ unsigned long vaddr;
+ unsigned long page_addr;
+ u32 tlbehi;
+ u32 mmucr;
+
+ vaddr = (unsigned long)pm_sram_area->addr;
+ page_addr = pm_sram_start & PAGE_MASK;
+
+ /*
+ * Mask exceptions and grab the first TLB entry. We won't be
+ * needing it while sleeping.
+ */
+ asm volatile("ssrf %0" : : "i"(SYSREG_EM_OFFSET) : "memory");
+
+ mmucr = sysreg_read(MMUCR);
+ tlbehi = sysreg_read(TLBEHI);
+ sysreg_write(MMUCR, SYSREG_BFINS(DRP, 0, mmucr));
+
+ tlbehi = SYSREG_BF(ASID, SYSREG_BFEXT(ASID, tlbehi));
+ tlbehi |= vaddr & PAGE_MASK;
+ tlbehi |= SYSREG_BIT(TLBEHI_V);
+
+ sysreg_write(TLBELO, page_addr | SRAM_PAGE_FLAGS);
+ sysreg_write(TLBEHI, tlbehi);
+ __builtin_tlbw();
+
+ return (void *)(vaddr + pm_sram_start - page_addr);
+}
+
+/*
+ * Must be called with interrupts disabled. Exceptions will be
+ * unmasked on return.
+ */
+static void avr32_pm_unmap_sram(void)
+{
+ u32 mmucr;
+ u32 tlbehi;
+ u32 tlbarlo;
+
+ /* Going to update TLB entry at index 0 */
+ mmucr = sysreg_read(MMUCR);
+ tlbehi = sysreg_read(TLBEHI);
+ sysreg_write(MMUCR, SYSREG_BFINS(DRP, 0, mmucr));
+
+ /* Clear the "valid" bit */
+ tlbehi = SYSREG_BF(ASID, SYSREG_BFEXT(ASID, tlbehi));
+ sysreg_write(TLBEHI, tlbehi);
+
+ /* Mark it as "not accessed" */
+ tlbarlo = sysreg_read(TLBARLO);
+ sysreg_write(TLBARLO, tlbarlo | 0x80000000U);
+
+ /* Update the TLB */
+ __builtin_tlbw();
+
+ /* Unmask exceptions */
+ asm volatile("csrf %0" : : "i"(SYSREG_EM_OFFSET) : "memory");
+}
+
+static int avr32_pm_valid_state(suspend_state_t state)
+{
+ switch (state) {
+ case PM_SUSPEND_ON:
+ case PM_SUSPEND_STANDBY:
+ case PM_SUSPEND_MEM:
+ return 1;
+
+ default:
+ return 0;
+ }
+}
+
+static int avr32_pm_enter(suspend_state_t state)
+{
+ u32 lpr_saved;
+ u32 evba_saved;
+ void *sram;
+
+ switch (state) {
+ case PM_SUSPEND_STANDBY:
+ sram = avr32_pm_map_sram();
+
+ /* Switch to in-sram exception handlers */
+ evba_saved = sysreg_read(EVBA);
+ sysreg_write(EVBA, (unsigned long)sram);
+
+ /*
+ * Save the LPR register so that we can re-enable
+ * SDRAM Low Power mode on resume.
+ */
+ lpr_saved = sdramc_readl(LPR);
+ pr_debug("%s: Entering standby...\n", __func__);
+ avr32_pm_enter_standby(SDRAMC_BASE);
+ sdramc_writel(LPR, lpr_saved);
+
+ /* Switch back to regular exception handlers */
+ sysreg_write(EVBA, evba_saved);
+
+ avr32_pm_unmap_sram();
+ break;
+
+ case PM_SUSPEND_MEM:
+ sram = avr32_pm_map_sram();
+
+ /* Switch to in-sram exception handlers */
+ evba_saved = sysreg_read(EVBA);
+ sysreg_write(EVBA, (unsigned long)sram);
+
+ /*
+ * Save the LPR register so that we can re-enable
+ * SDRAM Low Power mode on resume.
+ */
+ lpr_saved = sdramc_readl(LPR);
+ pr_debug("%s: Entering suspend-to-ram...\n", __func__);
+ avr32_pm_enter_str(SDRAMC_BASE);
+ sdramc_writel(LPR, lpr_saved);
+
+ /* Switch back to regular exception handlers */
+ sysreg_write(EVBA, evba_saved);
+
+ avr32_pm_unmap_sram();
+ break;
+
+ case PM_SUSPEND_ON:
+ pr_debug("%s: Entering idle...\n", __func__);
+ cpu_enter_idle();
+ break;
+
+ default:
+ pr_debug("%s: Invalid suspend state %d\n", __func__, state);
+ goto out;
+ }
+
+ pr_debug("%s: wakeup\n", __func__);
+
+out:
+ return 0;
+}
+
+static struct platform_suspend_ops avr32_pm_ops = {
+ .valid = avr32_pm_valid_state,
+ .enter = avr32_pm_enter,
+};
+
+static unsigned long avr32_pm_offset(void *symbol)
+{
+ extern u8 pm_exception[];
+
+ return (unsigned long)symbol - (unsigned long)pm_exception;
+}
+
+static int __init avr32_pm_init(void)
+{
+ extern u8 pm_exception[];
+ extern u8 pm_irq0[];
+ extern u8 pm_standby[];
+ extern u8 pm_suspend_to_ram[];
+ extern u8 pm_sram_end[];
+ void *dst;
+
+ /*
+ * To keep things simple, we depend on not needing more than a
+ * single page.
+ */
+ pm_sram_size = avr32_pm_offset(pm_sram_end);
+ if (pm_sram_size > PAGE_SIZE)
+ goto err;
+
+ pm_sram_start = sram_alloc(pm_sram_size);
+ if (!pm_sram_start)
+ goto err_alloc_sram;
+
+ /* Grab a virtual area we can use later on. */
+ pm_sram_area = get_vm_area(pm_sram_size, VM_IOREMAP);
+ if (!pm_sram_area)
+ goto err_vm_area;
+ pm_sram_area->phys_addr = pm_sram_start;
+
+ local_irq_disable();
+ dst = avr32_pm_map_sram();
+ memcpy(dst, pm_exception, pm_sram_size);
+ flush_dcache_region(dst, pm_sram_size);
+ invalidate_icache_region(dst, pm_sram_size);
+ avr32_pm_unmap_sram();
+ local_irq_enable();
+
+ avr32_pm_enter_standby = dst + avr32_pm_offset(pm_standby);
+ avr32_pm_enter_str = dst + avr32_pm_offset(pm_suspend_to_ram);
+ intc_set_suspend_handler(avr32_pm_offset(pm_irq0));
+
+ suspend_set_ops(&avr32_pm_ops);
+
+ printk("AVR32 AP Power Management enabled\n");
+
+ return 0;
+
+err_vm_area:
+ sram_free(pm_sram_start, pm_sram_size);
+err_alloc_sram:
+err:
+ pr_err("AVR32 Power Management initialization failed\n");
+ return -ENOMEM;
+}
+arch_initcall(avr32_pm_init);
diff --git a/arch/avr32/mach-at32ap/pm.h b/arch/avr32/mach-at32ap/pm.h
index 694d521edc2..532a3732c21 100644
--- a/arch/avr32/mach-at32ap/pm.h
+++ b/arch/avr32/mach-at32ap/pm.h
@@ -4,14 +4,6 @@
#ifndef __ARCH_AVR32_MACH_AT32AP_PM_H__
#define __ARCH_AVR32_MACH_AT32AP_PM_H__
-/*
- * We can reduce the code size a bit by using a constant here. Since
- * this file is only used on AVR32 AP CPUs with segmentation enabled,
- * it's safe to not use ioremap. Generic drivers should of course
- * never do this.
- */
-#define AT32_PM_BASE 0xfff00000
-
/* PM register offsets */
#define PM_MCCTRL 0x0000
#define PM_CKSEL 0x0004
@@ -113,8 +105,8 @@
/* Register access macros */
#define pm_readl(reg) \
- __raw_readl((void __iomem __force *)AT32_PM_BASE + PM_##reg)
+ __raw_readl((void __iomem __force *)PM_BASE + PM_##reg)
#define pm_writel(reg,value) \
- __raw_writel((value), (void __iomem __force *)AT32_PM_BASE + PM_##reg)
+ __raw_writel((value), (void __iomem __force *)PM_BASE + PM_##reg)
#endif /* __ARCH_AVR32_MACH_AT32AP_PM_H__ */
diff --git a/arch/avr32/mach-at32ap/sdramc.h b/arch/avr32/mach-at32ap/sdramc.h
new file mode 100644
index 00000000000..66eeaed4907
--- /dev/null
+++ b/arch/avr32/mach-at32ap/sdramc.h
@@ -0,0 +1,76 @@
+/*
+ * Register definitions for the AT32AP SDRAM Controller
+ *
+ * Copyright (C) 2008 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.
+ */
+
+/* Register offsets */
+#define SDRAMC_MR 0x0000
+#define SDRAMC_TR 0x0004
+#define SDRAMC_CR 0x0008
+#define SDRAMC_HSR 0x000c
+#define SDRAMC_LPR 0x0010
+#define SDRAMC_IER 0x0014
+#define SDRAMC_IDR 0x0018
+#define SDRAMC_IMR 0x001c
+#define SDRAMC_ISR 0x0020
+#define SDRAMC_MDR 0x0024
+
+/* MR - Mode Register */
+#define SDRAMC_MR_MODE_NORMAL ( 0 << 0)
+#define SDRAMC_MR_MODE_NOP ( 1 << 0)
+#define SDRAMC_MR_MODE_BANKS_PRECHARGE ( 2 << 0)
+#define SDRAMC_MR_MODE_LOAD_MODE ( 3 << 0)
+#define SDRAMC_MR_MODE_AUTO_REFRESH ( 4 << 0)
+#define SDRAMC_MR_MODE_EXT_LOAD_MODE ( 5 << 0)
+#define SDRAMC_MR_MODE_POWER_DOWN ( 6 << 0)
+
+/* CR - Configuration Register */
+#define SDRAMC_CR_NC_8_BITS ( 0 << 0)
+#define SDRAMC_CR_NC_9_BITS ( 1 << 0)
+#define SDRAMC_CR_NC_10_BITS ( 2 << 0)
+#define SDRAMC_CR_NC_11_BITS ( 3 << 0)
+#define SDRAMC_CR_NR_11_BITS ( 0 << 2)
+#define SDRAMC_CR_NR_12_BITS ( 1 << 2)
+#define SDRAMC_CR_NR_13_BITS ( 2 << 2)
+#define SDRAMC_CR_NB_2_BANKS ( 0 << 4)
+#define SDRAMC_CR_NB_4_BANKS ( 1 << 4)
+#define SDRAMC_CR_CAS(x) ((x) << 5)
+#define SDRAMC_CR_DBW_32_BITS ( 0 << 7)
+#define SDRAMC_CR_DBW_16_BITS ( 1 << 7)
+#define SDRAMC_CR_TWR(x) ((x) << 8)
+#define SDRAMC_CR_TRC(x) ((x) << 12)
+#define SDRAMC_CR_TRP(x) ((x) << 16)
+#define SDRAMC_CR_TRCD(x) ((x) << 20)
+#define SDRAMC_CR_TRAS(x) ((x) << 24)
+#define SDRAMC_CR_TXSR(x) ((x) << 28)
+
+/* HSR - High Speed Register */
+#define SDRAMC_HSR_DA ( 1 << 0)
+
+/* LPR - Low Power Register */
+#define SDRAMC_LPR_LPCB_INHIBIT ( 0 << 0)
+#define SDRAMC_LPR_LPCB_SELF_RFR ( 1 << 0)
+#define SDRAMC_LPR_LPCB_PDOWN ( 2 << 0)
+#define SDRAMC_LPR_LPCB_DEEP_PDOWN ( 3 << 0)
+#define SDRAMC_LPR_PASR(x) ((x) << 4)
+#define SDRAMC_LPR_TCSR(x) ((x) << 8)
+#define SDRAMC_LPR_DS(x) ((x) << 10)
+#define SDRAMC_LPR_TIMEOUT(x) ((x) << 12)
+
+/* IER/IDR/IMR/ISR - Interrupt Enable/Disable/Mask/Status Register */
+#define SDRAMC_ISR_RES ( 1 << 0)
+
+/* MDR - Memory Device Register */
+#define SDRAMC_MDR_MD_SDRAM ( 0 << 0)
+#define SDRAMC_MDR_MD_LOW_PWR_SDRAM ( 1 << 0)
+
+/* Register access macros */
+#define sdramc_readl(reg) \
+ __raw_readl((void __iomem __force *)SDRAMC_BASE + SDRAMC_##reg)
+#define sdramc_writel(reg, value) \
+ __raw_writel(value, (void __iomem __force *)SDRAMC_BASE + SDRAMC_##reg)