|
@@ -1729,3 +1729,166 @@ static struct clk usba0_hclk = {
|
|
|
};
|
|
|
|
|
|
#define EP(nam, idx, maxpkt, maxbk, dma, isoc) \
|
|
|
+ [idx] = { \
|
|
|
+ .name = nam, \
|
|
|
+ .index = idx, \
|
|
|
+ .fifo_size = maxpkt, \
|
|
|
+ .nr_banks = maxbk, \
|
|
|
+ .can_dma = dma, \
|
|
|
+ .can_isoc = isoc, \
|
|
|
+ }
|
|
|
+
|
|
|
+static struct usba_ep_data at32_usba_ep[] __initdata = {
|
|
|
+ EP("ep0", 0, 64, 1, 0, 0),
|
|
|
+ EP("ep1", 1, 512, 2, 1, 1),
|
|
|
+ EP("ep2", 2, 512, 2, 1, 1),
|
|
|
+ EP("ep3-int", 3, 64, 3, 1, 0),
|
|
|
+ EP("ep4-int", 4, 64, 3, 1, 0),
|
|
|
+ EP("ep5", 5, 1024, 3, 1, 1),
|
|
|
+ EP("ep6", 6, 1024, 3, 1, 1),
|
|
|
+};
|
|
|
+
|
|
|
+#undef EP
|
|
|
+
|
|
|
+struct platform_device *__init
|
|
|
+at32_add_device_usba(unsigned int id, struct usba_platform_data *data)
|
|
|
+{
|
|
|
+ /*
|
|
|
+ * pdata doesn't have room for any endpoints, so we need to
|
|
|
+ * append room for the ones we need right after it.
|
|
|
+ */
|
|
|
+ struct {
|
|
|
+ struct usba_platform_data pdata;
|
|
|
+ struct usba_ep_data ep[7];
|
|
|
+ } usba_data;
|
|
|
+ struct platform_device *pdev;
|
|
|
+
|
|
|
+ if (id != 0)
|
|
|
+ return NULL;
|
|
|
+
|
|
|
+ pdev = platform_device_alloc("atmel_usba_udc", 0);
|
|
|
+ if (!pdev)
|
|
|
+ return NULL;
|
|
|
+
|
|
|
+ if (platform_device_add_resources(pdev, usba0_resource,
|
|
|
+ ARRAY_SIZE(usba0_resource)))
|
|
|
+ goto out_free_pdev;
|
|
|
+
|
|
|
+ if (data) {
|
|
|
+ usba_data.pdata.vbus_pin = data->vbus_pin;
|
|
|
+ usba_data.pdata.vbus_pin_inverted = data->vbus_pin_inverted;
|
|
|
+ } else {
|
|
|
+ usba_data.pdata.vbus_pin = -EINVAL;
|
|
|
+ usba_data.pdata.vbus_pin_inverted = -EINVAL;
|
|
|
+ }
|
|
|
+
|
|
|
+ data = &usba_data.pdata;
|
|
|
+ data->num_ep = ARRAY_SIZE(at32_usba_ep);
|
|
|
+ memcpy(data->ep, at32_usba_ep, sizeof(at32_usba_ep));
|
|
|
+
|
|
|
+ if (platform_device_add_data(pdev, data, sizeof(usba_data)))
|
|
|
+ goto out_free_pdev;
|
|
|
+
|
|
|
+ if (gpio_is_valid(data->vbus_pin))
|
|
|
+ at32_select_gpio(data->vbus_pin, 0);
|
|
|
+
|
|
|
+ usba0_pclk.dev = &pdev->dev;
|
|
|
+ usba0_hclk.dev = &pdev->dev;
|
|
|
+
|
|
|
+ platform_device_add(pdev);
|
|
|
+
|
|
|
+ return pdev;
|
|
|
+
|
|
|
+out_free_pdev:
|
|
|
+ platform_device_put(pdev);
|
|
|
+ return NULL;
|
|
|
+}
|
|
|
+
|
|
|
+/* --------------------------------------------------------------------
|
|
|
+ * IDE / CompactFlash
|
|
|
+ * -------------------------------------------------------------------- */
|
|
|
+#if defined(CONFIG_CPU_AT32AP7000) || defined(CONFIG_CPU_AT32AP7001)
|
|
|
+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 = {
|
|
|
+ (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;
|
|
|
+ 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;
|
|
|
+
|
|
|
+ /* 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,
|
|
|
+ at32_smc_cs5_resource,
|
|
|
+ ARRAY_SIZE(at32_smc_cs5_resource));
|
|
|
+ if (ret)
|
|
|
+ return ret;
|
|
|
+
|
|
|
+ /* 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) {
|
|
|
+ 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;
|
|
|
+ }
|
|
|
+
|
|
|
+ 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;
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+struct platform_device *__init
|
|
|
+at32_add_device_ide(unsigned int id, unsigned int extint,
|
|
|
+ struct ide_platform_data *data)
|