Commit eaf5f925 authored by Haavard Skinnemoen's avatar Haavard Skinnemoen

[AVR32] Implement at32_add_device_cf()

Implement at32_add_device_cf() which will add a platform_device for
the at32_cf driver (not merged yet). Separate out most of the
at32_add_device_ide() code and use it to implement
at32_add_device_cf() as well.

This changes the API in the following ways:
  * The board code must initialize data->cs to the chipselect ID to
    use before calling any of these functions.
  * The board code must use GPIO_PIN_NONE to indicate unused CF pins.
Signed-off-by: default avatarHaavard Skinnemoen <hskinnemoen@atmel.com>
parent 2042c1c4
...@@ -1330,10 +1330,9 @@ at32_add_device_usba(unsigned int id, struct usba_platform_data *data) ...@@ -1330,10 +1330,9 @@ at32_add_device_usba(unsigned int id, struct usba_platform_data *data)
} }
/* -------------------------------------------------------------------- /* --------------------------------------------------------------------
* IDE * IDE / CompactFlash
* -------------------------------------------------------------------- */ * -------------------------------------------------------------------- */
static struct ide_platform_data at32_ide0_data; static struct resource at32_smc_cs4_resource[] __initdata = {
static struct resource at32_ide0_resource[] = {
{ {
.start = 0x04000000, .start = 0x04000000,
.end = 0x07ffffff, .end = 0x07ffffff,
...@@ -1341,45 +1340,63 @@ static struct resource at32_ide0_resource[] = { ...@@ -1341,45 +1340,63 @@ static struct resource at32_ide0_resource[] = {
}, },
IRQ(~0UL), /* Magic IRQ will be overridden */ IRQ(~0UL), /* Magic IRQ will be overridden */
}; };
DEFINE_DEV_DATA(at32_ide, 0); static struct resource at32_smc_cs5_resource[] __initdata = {
{
.start = 0x20000000,
.end = 0x23ffffff,
.flags = IORESOURCE_MEM,
},
IRQ(~0UL), /* Magic IRQ will be overridden */
};
struct platform_device *__init static int __init at32_init_ide_or_cf(struct platform_device *pdev,
at32_add_device_ide(unsigned int id, unsigned int extint, unsigned int cs, unsigned int extint)
struct ide_platform_data *data)
{ {
struct platform_device *pdev; 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; unsigned int extint_pin;
int ret;
switch (extint) { if (extint >= ARRAY_SIZE(extint_pin_map))
case 0: return -EINVAL;
extint_pin = GPIO_PIN_PB(25); extint_pin = extint_pin_map[extint];
break;
case 1: switch (cs) {
extint_pin = GPIO_PIN_PB(26); case 4:
break; ret = platform_device_add_resources(pdev,
case 2: at32_smc_cs4_resource,
extint_pin = GPIO_PIN_PB(27); 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; break;
case 3: case 5:
extint_pin = GPIO_PIN_PB(28); 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; break;
default: default:
return NULL; return -EINVAL;
} }
switch (id) { if (!common_pins_initialized) {
case 0:
pdev = &at32_ide0_device;
select_peripheral(PE(19), PERIPH_A, 0); /* CFCE1 -> CS0_N */ select_peripheral(PE(19), PERIPH_A, 0); /* CFCE1 -> CS0_N */
select_peripheral(PE(20), PERIPH_A, 0); /* CFCE2 -> CS1_N */ select_peripheral(PE(20), PERIPH_A, 0); /* CFCE2 -> CS1_N */
select_peripheral(PE(21), PERIPH_A, 0); /* NCS4 -> OE_N */
select_peripheral(PE(23), PERIPH_A, 0); /* CFRNW -> DIR */ select_peripheral(PE(23), PERIPH_A, 0); /* CFRNW -> DIR */
select_peripheral(PE(24), PERIPH_A, 0); /* NWAIT <- IORDY */ select_peripheral(PE(24), PERIPH_A, 0); /* NWAIT <- IORDY */
set_ebi_sfr_bits(HMATRIX_BIT(CS4A)); common_pins_initialized = true;
data->cs = 4;
break;
default:
return NULL;
} }
at32_select_periph(extint_pin, GPIO_PERIPH_A, AT32_GPIOF_DEGLITCH); at32_select_periph(extint_pin, GPIO_PERIPH_A, AT32_GPIOF_DEGLITCH);
...@@ -1387,11 +1404,65 @@ at32_add_device_ide(unsigned int id, unsigned int extint, ...@@ -1387,11 +1404,65 @@ at32_add_device_ide(unsigned int id, unsigned int extint,
pdev->resource[1].start = EIM_IRQ_BASE + extint; pdev->resource[1].start = EIM_IRQ_BASE + extint;
pdev->resource[1].end = pdev->resource[1].start; pdev->resource[1].end = pdev->resource[1].start;
memcpy(pdev->dev.platform_data, data, sizeof(struct ide_platform_data)); return 0;
}
platform_device_register(pdev); 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; return pdev;
fail:
platform_device_put(pdev);
return NULL;
} }
/* -------------------------------------------------------------------- /* --------------------------------------------------------------------
......
...@@ -70,4 +70,15 @@ struct platform_device *at32_add_device_mci(unsigned int id); ...@@ -70,4 +70,15 @@ struct platform_device *at32_add_device_mci(unsigned int id);
struct platform_device *at32_add_device_ac97c(unsigned int id); struct platform_device *at32_add_device_ac97c(unsigned int id);
struct platform_device *at32_add_device_abdac(unsigned int id); struct platform_device *at32_add_device_abdac(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);
#endif /* __ASM_ARCH_BOARD_H */ #endif /* __ASM_ARCH_BOARD_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment