|
@@ -1224,3 +1224,191 @@ at32_spi_setup_slaves(unsigned int bus_num, struct spi_board_info *b, unsigned i
|
|
}
|
|
}
|
|
|
|
|
|
struct platform_device *__init
|
|
struct platform_device *__init
|
|
|
|
+at32_add_device_spi(unsigned int id, struct spi_board_info *b, unsigned int n)
|
|
|
|
+{
|
|
|
|
+ struct platform_device *pdev;
|
|
|
|
+ u32 pin_mask;
|
|
|
|
+
|
|
|
|
+ switch (id) {
|
|
|
|
+ case 0:
|
|
|
|
+ pdev = &atmel_spi0_device;
|
|
|
|
+ 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);
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case 1:
|
|
|
|
+ pdev = &atmel_spi1_device;
|
|
|
|
+ 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);
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ default:
|
|
|
|
+ return NULL;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ spi_register_board_info(b, n);
|
|
|
|
+ platform_device_register(pdev);
|
|
|
|
+ return pdev;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/* --------------------------------------------------------------------
|
|
|
|
+ * 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 i2c_board_info *b,
|
|
|
|
+ unsigned int n)
|
|
|
|
+{
|
|
|
|
+ struct platform_device *pdev;
|
|
|
|
+ u32 pin_mask;
|
|
|
|
+
|
|
|
|
+ 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;
|
|
|
|
+
|
|
|
|
+ pin_mask = (1 << 6) | (1 << 7); /* SDA & SDL */
|
|
|
|
+
|
|
|
|
+ select_peripheral(PIOA, pin_mask, PERIPH_A, 0);
|
|
|
|
+
|
|
|
|
+ atmel_twi0_pclk.dev = &pdev->dev;
|
|
|
|
+
|
|
|
|
+ if (b)
|
|
|
|
+ i2c_register_board_info(id, b, n);
|
|
|
|
+
|
|
|
|
+ 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 mci_platform_data *data)
|
|
|
|
+{
|
|
|
|
+ struct platform_device *pdev;
|
|
|
|
+ struct mci_dma_data *slave;
|
|
|
|
+ u32 pioa_mask;
|
|
|
|
+ u32 piob_mask;
|
|
|
|
+
|
|
|
|
+ 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)
|
|
|
|
+ goto fail;
|
|
|
|
+
|
|
|
|
+ if (platform_device_add_resources(pdev, atmel_mci0_resource,
|
|
|
|
+ ARRAY_SIZE(atmel_mci0_resource)))
|
|
|
|
+ goto fail;
|
|
|
|
+
|
|
|
|
+ slave = kzalloc(sizeof(struct mci_dma_data), GFP_KERNEL);
|
|
|
|
+ if (!slave)
|
|
|
|
+ goto fail;
|
|
|
|
+
|
|
|
|
+ slave->sdata.dma_dev = &dw_dmac0_device.dev;
|
|
|
|
+ slave->sdata.cfg_hi = (DWC_CFGH_SRC_PER(0)
|
|
|
|
+ | DWC_CFGH_DST_PER(1));
|
|
|
|
+ slave->sdata.cfg_lo &= ~(DWC_CFGL_HS_DST_POL
|
|
|
|
+ | DWC_CFGL_HS_SRC_POL);
|
|
|
|
+
|
|
|
|
+ data->dma_slave = slave;
|
|
|
|
+
|
|
|
|
+ if (platform_device_add_data(pdev, data,
|
|
|
|
+ sizeof(struct mci_platform_data)))
|
|
|
|
+ goto fail_free;
|
|
|
|
+
|
|
|
|
+ /* 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_free;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ 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;
|