Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit eaf5f925 authored by Haavard Skinnemoen's avatar Haavard Skinnemoen
Browse files

[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
Loading
Loading
Loading
Loading
+102 −31
Original line number Diff line number Diff line
@@ -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_ide0_resource[] = {
static struct resource at32_smc_cs4_resource[] __initdata = {
	{
		.start	= 0x04000000,
		.end	= 0x07ffffff,
@@ -1341,45 +1340,63 @@ static struct resource at32_ide0_resource[] = {
	},
	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
at32_add_device_ide(unsigned int id, unsigned int extint,
		    struct ide_platform_data *data)
static int __init at32_init_ide_or_cf(struct platform_device *pdev,
		unsigned int cs, unsigned int extint)
{
	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;
	int ret;

	switch (extint) {
	case 0:
		extint_pin = GPIO_PIN_PB(25);
		break;
	case 1:
		extint_pin = GPIO_PIN_PB(26);
		break;
	case 2:
		extint_pin = GPIO_PIN_PB(27);
	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 3:
		extint_pin = GPIO_PIN_PB(28);
	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 NULL;
		return -EINVAL;
	}

	switch (id) {
	case 0:
		pdev = &at32_ide0_device;
	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(21), PERIPH_A, 0); /* NCS4   -> OE_N  */
		select_peripheral(PE(23), PERIPH_A, 0); /* CFRNW  -> DIR   */
		select_peripheral(PE(24), PERIPH_A, 0); /* NWAIT  <- IORDY */
		set_ebi_sfr_bits(HMATRIX_BIT(CS4A));
		data->cs = 4;
		break;
	default:
		return NULL;
		common_pins_initialized = true;
	}

	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,
	pdev->resource[1].start = EIM_IRQ_BASE + extint;
	pdev->resource[1].end = pdev->resource[1].start;

	memcpy(pdev->dev.platform_data, data, sizeof(struct ide_platform_data));
	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;

	platform_device_register(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;
}

/* --------------------------------------------------------------------
+11 −0
Original line number Diff line number Diff line
@@ -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_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 */