summaryrefslogtreecommitdiffstats
path: root/arch/avr32/mach-at32ap/at32ap7000.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/avr32/mach-at32ap/at32ap7000.c')
-rw-r--r--arch/avr32/mach-at32ap/at32ap7000.c344
1 files changed, 344 insertions, 0 deletions
diff --git a/arch/avr32/mach-at32ap/at32ap7000.c b/arch/avr32/mach-at32ap/at32ap7000.c
index f6d154ca4d24..a9d9ec081e3d 100644
--- a/arch/avr32/mach-at32ap/at32ap7000.c
+++ b/arch/avr32/mach-at32ap/at32ap7000.c
@@ -556,6 +556,17 @@ 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
* -------------------------------------------------------------------- */
@@ -655,6 +666,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(&at32_systc0_device);
@@ -960,6 +972,96 @@ at32_add_device_spi(unsigned int id, struct spi_board_info *b, unsigned int n)
}
/* --------------------------------------------------------------------
+ * TWI
+ * -------------------------------------------------------------------- */
+static struct resource atmel_twi0_resource[] __initdata = {
+ PBMEM(0xffe00800),
+ IRQ(5),
+};
+static struct clk atmel_twi0_pclk = {
+ .name = "twi_pclk",
+ .parent = &pba_clk,
+ .mode = pba_clk_mode,
+ .get_rate = pba_clk_get_rate,
+ .index = 2,
+};
+
+struct platform_device *__init at32_add_device_twi(unsigned int id)
+{
+ struct platform_device *pdev;
+
+ if (id != 0)
+ return NULL;
+
+ pdev = platform_device_alloc("atmel_twi", id);
+ if (!pdev)
+ return NULL;
+
+ if (platform_device_add_resources(pdev, atmel_twi0_resource,
+ 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 */
+
+ atmel_twi0_pclk.dev = &pdev->dev;
+
+ platform_device_add(pdev);
+ return pdev;
+
+err_add_resources:
+ platform_device_put(pdev);
+ return NULL;
+}
+
+/* --------------------------------------------------------------------
+ * MMC
+ * -------------------------------------------------------------------- */
+static struct resource atmel_mci0_resource[] __initdata = {
+ PBMEM(0xfff02400),
+ IRQ(28),
+};
+static struct clk atmel_mci0_pclk = {
+ .name = "mci_clk",
+ .parent = &pbb_clk,
+ .mode = pbb_clk_mode,
+ .get_rate = pbb_clk_get_rate,
+ .index = 9,
+};
+
+struct platform_device *__init at32_add_device_mci(unsigned int id)
+{
+ struct platform_device *pdev;
+
+ if (id != 0)
+ return NULL;
+
+ pdev = platform_device_alloc("atmel_mci", id);
+ if (!pdev)
+ return NULL;
+
+ if (platform_device_add_resources(pdev, atmel_mci0_resource,
+ ARRAY_SIZE(atmel_mci0_resource)))
+ goto err_add_resources;
+
+ 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 */
+
+ atmel_mci0_pclk.dev = &pdev->dev;
+
+ platform_device_add(pdev);
+ return pdev;
+
+err_add_resources:
+ platform_device_put(pdev);
+ return NULL;
+}
+
+/* --------------------------------------------------------------------
* LCDC
* -------------------------------------------------------------------- */
static struct atmel_lcdfb_info atmel_lcdfb0_data;
@@ -1228,6 +1330,241 @@ out_free_pdev:
}
/* --------------------------------------------------------------------
+ * IDE / CompactFlash
+ * -------------------------------------------------------------------- */
+static struct resource at32_smc_cs4_resource[] __initdata = {
+ {
+ .start = 0x04000000,
+ .end = 0x07ffffff,
+ .flags = IORESOURCE_MEM,
+ },
+ IRQ(~0UL), /* Magic IRQ will be overridden */
+};
+static struct resource at32_smc_cs5_resource[] __initdata = {
+ {
+ .start = 0x20000000,
+ .end = 0x23ffffff,
+ .flags = IORESOURCE_MEM,
+ },
+ IRQ(~0UL), /* Magic IRQ will be overridden */
+};
+
+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),
+ };
+ static bool common_pins_initialized __initdata = false;
+ unsigned int extint_pin;
+ int ret;
+
+ if (extint >= ARRAY_SIZE(extint_pin_map))
+ return -EINVAL;
+ extint_pin = extint_pin_map[extint];
+
+ switch (cs) {
+ case 4:
+ ret = platform_device_add_resources(pdev,
+ at32_smc_cs4_resource,
+ ARRAY_SIZE(at32_smc_cs4_resource));
+ if (ret)
+ return ret;
+
+ select_peripheral(PE(21), PERIPH_A, 0); /* NCS4 -> OE_N */
+ set_ebi_sfr_bits(HMATRIX_BIT(CS4A));
+ break;
+ case 5:
+ ret = platform_device_add_resources(pdev,
+ at32_smc_cs5_resource,
+ ARRAY_SIZE(at32_smc_cs5_resource));
+ if (ret)
+ return ret;
+
+ select_peripheral(PE(22), PERIPH_A, 0); /* NCS5 -> OE_N */
+ set_ebi_sfr_bits(HMATRIX_BIT(CS5A));
+ 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 */
+ common_pins_initialized = true;
+ }
+
+ at32_select_periph(extint_pin, GPIO_PERIPH_A, AT32_GPIOF_DEGLITCH);
+
+ pdev->resource[1].start = EIM_IRQ_BASE + extint;
+ pdev->resource[1].end = pdev->resource[1].start;
+
+ return 0;
+}
+
+struct platform_device *__init
+at32_add_device_ide(unsigned int id, unsigned int extint,
+ struct ide_platform_data *data)
+{
+ struct platform_device *pdev;
+
+ pdev = platform_device_alloc("at32_ide", id);
+ if (!pdev)
+ goto fail;
+
+ if (platform_device_add_data(pdev, data,
+ sizeof(struct ide_platform_data)))
+ goto fail;
+
+ if (at32_init_ide_or_cf(pdev, data->cs, extint))
+ goto fail;
+
+ platform_device_add(pdev);
+ return pdev;
+
+fail:
+ platform_device_put(pdev);
+ return NULL;
+}
+
+struct platform_device *__init
+at32_add_device_cf(unsigned int id, unsigned int extint,
+ struct cf_platform_data *data)
+{
+ struct platform_device *pdev;
+
+ pdev = platform_device_alloc("at32_cf", id);
+ if (!pdev)
+ goto fail;
+
+ if (platform_device_add_data(pdev, data,
+ sizeof(struct cf_platform_data)))
+ goto fail;
+
+ if (at32_init_ide_or_cf(pdev, data->cs, extint))
+ goto fail;
+
+ if (data->detect_pin != GPIO_PIN_NONE)
+ at32_select_gpio(data->detect_pin, AT32_GPIOF_DEGLITCH);
+ if (data->reset_pin != GPIO_PIN_NONE)
+ at32_select_gpio(data->reset_pin, 0);
+ if (data->vcc_pin != GPIO_PIN_NONE)
+ at32_select_gpio(data->vcc_pin, 0);
+ /* READY is used as extint, so we can't select it as gpio */
+
+ platform_device_add(pdev);
+ return pdev;
+
+fail:
+ platform_device_put(pdev);
+ return NULL;
+}
+
+/* --------------------------------------------------------------------
+ * AC97C
+ * -------------------------------------------------------------------- */
+static struct resource atmel_ac97c0_resource[] __initdata = {
+ PBMEM(0xfff02800),
+ IRQ(29),
+};
+static struct clk atmel_ac97c0_pclk = {
+ .name = "pclk",
+ .parent = &pbb_clk,
+ .mode = pbb_clk_mode,
+ .get_rate = pbb_clk_get_rate,
+ .index = 10,
+};
+
+struct platform_device *__init at32_add_device_ac97c(unsigned int id)
+{
+ struct platform_device *pdev;
+
+ if (id != 0)
+ return NULL;
+
+ pdev = platform_device_alloc("atmel_ac97c", id);
+ if (!pdev)
+ return NULL;
+
+ if (platform_device_add_resources(pdev, atmel_ac97c0_resource,
+ ARRAY_SIZE(atmel_ac97c0_resource)))
+ goto err_add_resources;
+
+ 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 */
+
+ atmel_ac97c0_pclk.dev = &pdev->dev;
+
+ platform_device_add(pdev);
+ return pdev;
+
+err_add_resources:
+ platform_device_put(pdev);
+ return NULL;
+}
+
+/* --------------------------------------------------------------------
+ * ABDAC
+ * -------------------------------------------------------------------- */
+static struct resource abdac0_resource[] __initdata = {
+ PBMEM(0xfff02000),
+ IRQ(27),
+};
+static struct clk abdac0_pclk = {
+ .name = "pclk",
+ .parent = &pbb_clk,
+ .mode = pbb_clk_mode,
+ .get_rate = pbb_clk_get_rate,
+ .index = 8,
+};
+static struct clk abdac0_sample_clk = {
+ .name = "sample_clk",
+ .mode = genclk_mode,
+ .get_rate = genclk_get_rate,
+ .set_rate = genclk_set_rate,
+ .set_parent = genclk_set_parent,
+ .index = 6,
+};
+
+struct platform_device *__init at32_add_device_abdac(unsigned int id)
+{
+ struct platform_device *pdev;
+
+ if (id != 0)
+ return NULL;
+
+ pdev = platform_device_alloc("abdac", id);
+ if (!pdev)
+ return NULL;
+
+ if (platform_device_add_resources(pdev, abdac0_resource,
+ 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 */
+
+ abdac0_pclk.dev = &pdev->dev;
+ abdac0_sample_clk.dev = &pdev->dev;
+
+ platform_device_add(pdev);
+ return pdev;
+
+err_add_resources:
+ platform_device_put(pdev);
+ return NULL;
+}
+
+/* --------------------------------------------------------------------
* GCLK
* -------------------------------------------------------------------- */
static struct clk gclk0 = {
@@ -1290,6 +1627,7 @@ struct clk *at32_clock_list[] = {
&smc0_mck,
&pdc_hclk,
&pdc_pclk,
+ &dmaca0_hclk,
&pico_clk,
&pio0_mck,
&pio1_mck,
@@ -1307,6 +1645,8 @@ struct clk *at32_clock_list[] = {
&macb1_pclk,
&atmel_spi0_spi_clk,
&atmel_spi1_spi_clk,
+ &atmel_twi0_pclk,
+ &atmel_mci0_pclk,
&atmel_lcdfb0_hck1,
&atmel_lcdfb0_pixclk,
&ssc0_pclk,
@@ -1314,6 +1654,9 @@ struct clk *at32_clock_list[] = {
&ssc2_pclk,
&usba0_hclk,
&usba0_pclk,
+ &atmel_ac97c0_pclk,
+ &abdac0_pclk,
+ &abdac0_sample_clk,
&gclk0,
&gclk1,
&gclk2,
@@ -1355,6 +1698,7 @@ void __init at32_clock_init(void)
genclk_init_parent(&gclk3);
genclk_init_parent(&gclk4);
genclk_init_parent(&atmel_lcdfb0_pixclk);
+ genclk_init_parent(&abdac0_sample_clk);
/*
* Turn on all clocks that have at least one user already, and