Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/hskinnemoen/atmel-mci-2.6.28

Conflicts:
	drivers/mmc/host/atmel-mci.c
This commit is contained in:
Pierre Ossman 2008-10-12 11:08:46 +02:00
commit 6ee6c6adf1
9 changed files with 1136 additions and 422 deletions

View File

@ -53,8 +53,11 @@ static struct spi_board_info spi0_board_info[] __initdata = {
}; };
static struct mci_platform_data __initdata mci0_data = { static struct mci_platform_data __initdata mci0_data = {
.slot[0] = {
.bus_width = 4,
.detect_pin = GPIO_PIN_PC(25), .detect_pin = GPIO_PIN_PC(25),
.wp_pin = GPIO_PIN_PE(0), .wp_pin = GPIO_PIN_PE(0),
},
}; };
/* /*

View File

@ -264,16 +264,20 @@ void __init setup_board(void)
#ifndef CONFIG_BOARD_ATSTK100X_SW2_CUSTOM #ifndef CONFIG_BOARD_ATSTK100X_SW2_CUSTOM
static struct mci_platform_data __initdata mci0_data = {
.slot[0] = {
.bus_width = 4,
/* MMC card detect requires MACB0 *NOT* be used */ /* MMC card detect requires MACB0 *NOT* be used */
#ifdef CONFIG_BOARD_ATSTK1002_SW6_CUSTOM #ifdef CONFIG_BOARD_ATSTK1002_SW6_CUSTOM
static struct mci_platform_data __initdata mci0_data = {
.detect_pin = GPIO_PIN_PC(14), /* gpio30/sdcd */ .detect_pin = GPIO_PIN_PC(14), /* gpio30/sdcd */
.wp_pin = GPIO_PIN_PC(15), /* gpio31/sdwp */ .wp_pin = GPIO_PIN_PC(15), /* gpio31/sdwp */
};
#define MCI_PDATA &mci0_data
#else #else
#define MCI_PDATA NULL .detect_pin = -ENODEV,
.wp_pin = -ENODEV,
#endif /* SW6 for sd{cd,wp} routing */ #endif /* SW6 for sd{cd,wp} routing */
},
};
#endif /* SW2 for MMC signal routing */ #endif /* SW2 for MMC signal routing */
@ -326,7 +330,7 @@ static int __init atstk1002_init(void)
at32_add_device_spi(1, spi1_board_info, ARRAY_SIZE(spi1_board_info)); at32_add_device_spi(1, spi1_board_info, ARRAY_SIZE(spi1_board_info));
#endif #endif
#ifndef CONFIG_BOARD_ATSTK100X_SW2_CUSTOM #ifndef CONFIG_BOARD_ATSTK100X_SW2_CUSTOM
at32_add_device_mci(0, MCI_PDATA); at32_add_device_mci(0, &mci0_pdata);
#endif #endif
#ifdef CONFIG_BOARD_ATSTK1002_SW5_CUSTOM #ifdef CONFIG_BOARD_ATSTK1002_SW5_CUSTOM
set_hw_addr(at32_add_device_eth(1, &eth_data[1])); set_hw_addr(at32_add_device_eth(1, &eth_data[1]));

View File

@ -66,6 +66,16 @@ static struct spi_board_info spi1_board_info[] __initdata = { {
} }; } };
#endif #endif
#ifndef CONFIG_BOARD_ATSTK100X_SW2_CUSTOM
static struct mci_platform_data __initdata mci0_data = {
.slot[0] = {
.bus_width = 4,
.detect_pin = -ENODEV,
.wp_pin = -ENODEV,
},
};
#endif
#ifdef CONFIG_BOARD_ATSTK1000_EXTDAC #ifdef CONFIG_BOARD_ATSTK1000_EXTDAC
static void __init atstk1003_setup_extdac(void) static void __init atstk1003_setup_extdac(void)
{ {
@ -154,7 +164,7 @@ static int __init atstk1003_init(void)
at32_add_device_spi(1, spi1_board_info, ARRAY_SIZE(spi1_board_info)); at32_add_device_spi(1, spi1_board_info, ARRAY_SIZE(spi1_board_info));
#endif #endif
#ifndef CONFIG_BOARD_ATSTK100X_SW2_CUSTOM #ifndef CONFIG_BOARD_ATSTK100X_SW2_CUSTOM
at32_add_device_mci(0, NULL); at32_add_device_mci(0, &mci0_data);
#endif #endif
at32_add_device_usba(0, NULL); at32_add_device_usba(0, NULL);
#ifndef CONFIG_BOARD_ATSTK100X_SW3_CUSTOM #ifndef CONFIG_BOARD_ATSTK100X_SW3_CUSTOM

View File

@ -71,6 +71,16 @@ static struct spi_board_info spi1_board_info[] __initdata = { {
} }; } };
#endif #endif
#ifndef CONFIG_BOARD_ATSTK100X_SW2_CUSTOM
static struct mci_platform_data __initdata mci0_data = {
.slot[0] = {
.bus_width = 4,
.detect_pin = -ENODEV,
.wp_pin = -ENODEV,
},
};
#endif
#ifdef CONFIG_BOARD_ATSTK1000_EXTDAC #ifdef CONFIG_BOARD_ATSTK1000_EXTDAC
static void __init atstk1004_setup_extdac(void) static void __init atstk1004_setup_extdac(void)
{ {
@ -137,7 +147,7 @@ static int __init atstk1004_init(void)
at32_add_device_spi(1, spi1_board_info, ARRAY_SIZE(spi1_board_info)); at32_add_device_spi(1, spi1_board_info, ARRAY_SIZE(spi1_board_info));
#endif #endif
#ifndef CONFIG_BOARD_ATSTK100X_SW2_CUSTOM #ifndef CONFIG_BOARD_ATSTK100X_SW2_CUSTOM
at32_add_device_mci(0, NULL); at32_add_device_mci(0, &mci0_data);
#endif #endif
at32_add_device_lcdc(0, &atstk1000_lcdc_data, at32_add_device_lcdc(0, &atstk1000_lcdc_data,
fbmem_start, fbmem_size, 0); fbmem_start, fbmem_size, 0);

View File

@ -1,9 +1,39 @@
#ifndef __ASM_AVR32_ATMEL_MCI_H #ifndef __ASM_AVR32_ATMEL_MCI_H
#define __ASM_AVR32_ATMEL_MCI_H #define __ASM_AVR32_ATMEL_MCI_H
struct mci_platform_data { #define ATMEL_MCI_MAX_NR_SLOTS 2
struct dma_slave;
/**
* struct mci_slot_pdata - board-specific per-slot configuration
* @bus_width: Number of data lines wired up the slot
* @detect_pin: GPIO pin wired to the card detect switch
* @wp_pin: GPIO pin wired to the write protect sensor
*
* If a given slot is not present on the board, @bus_width should be
* set to 0. The other fields are ignored in this case.
*
* Any pins that aren't available should be set to a negative value.
*
* Note that support for multiple slots is experimental -- some cards
* might get upset if we don't get the clock management exactly right.
* But in most cases, it should work just fine.
*/
struct mci_slot_pdata {
unsigned int bus_width;
int detect_pin; int detect_pin;
int wp_pin; int wp_pin;
}; };
/**
* struct mci_platform_data - board-specific MMC/SDcard configuration
* @dma_slave: DMA slave interface to use in data transfers, or NULL.
* @slot: Per-slot configuration data.
*/
struct mci_platform_data {
struct dma_slave *dma_slave;
struct mci_slot_pdata slot[ATMEL_MCI_MAX_NR_SLOTS];
};
#endif /* __ASM_AVR32_ATMEL_MCI_H */ #endif /* __ASM_AVR32_ATMEL_MCI_H */

View File

@ -1272,10 +1272,14 @@ static struct clk atmel_mci0_pclk = {
struct platform_device *__init struct platform_device *__init
at32_add_device_mci(unsigned int id, struct mci_platform_data *data) at32_add_device_mci(unsigned int id, struct mci_platform_data *data)
{ {
struct mci_platform_data _data;
struct platform_device *pdev; struct platform_device *pdev;
struct dw_dma_slave *dws;
if (id != 0) 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; return NULL;
pdev = platform_device_alloc("atmel_mci", id); pdev = platform_device_alloc("atmel_mci", id);
@ -1286,28 +1290,76 @@ at32_add_device_mci(unsigned int id, struct mci_platform_data *data)
ARRAY_SIZE(atmel_mci0_resource))) ARRAY_SIZE(atmel_mci0_resource)))
goto fail; goto fail;
if (!data) { if (data->dma_slave)
data = &_data; dws = kmemdup(to_dw_dma_slave(data->dma_slave),
memset(data, -1, sizeof(struct mci_platform_data)); sizeof(struct dw_dma_slave), GFP_KERNEL);
data->detect_pin = GPIO_PIN_NONE; else
data->wp_pin = GPIO_PIN_NONE; dws = kzalloc(sizeof(struct dw_dma_slave), GFP_KERNEL);
}
dws->slave.dev = &pdev->dev;
dws->slave.dma_dev = &dw_dmac0_device.dev;
dws->slave.reg_width = DMA_SLAVE_WIDTH_32BIT;
dws->cfg_hi = (DWC_CFGH_SRC_PER(0)
| DWC_CFGH_DST_PER(1));
dws->cfg_lo &= ~(DWC_CFGL_HS_DST_POL
| DWC_CFGL_HS_SRC_POL);
data->dma_slave = &dws->slave;
if (platform_device_add_data(pdev, data, if (platform_device_add_data(pdev, data,
sizeof(struct mci_platform_data))) sizeof(struct mci_platform_data)))
goto fail; goto fail;
select_peripheral(PA(10), PERIPH_A, 0); /* CLK */ /* CLK line is common to both slots */
select_peripheral(PA(11), PERIPH_A, 0); /* CMD */ select_peripheral(PA(10), PERIPH_A, 0);
select_peripheral(PA(12), PERIPH_A, 0); /* DATA0 */
switch (data->slot[0].bus_width) {
case 4:
select_peripheral(PA(13), PERIPH_A, 0); /* DATA1 */ select_peripheral(PA(13), PERIPH_A, 0); /* DATA1 */
select_peripheral(PA(14), PERIPH_A, 0); /* DATA2 */ select_peripheral(PA(14), PERIPH_A, 0); /* DATA2 */
select_peripheral(PA(15), PERIPH_A, 0); /* DATA3 */ select_peripheral(PA(15), PERIPH_A, 0); /* DATA3 */
/* fall through */
case 1:
select_peripheral(PA(11), PERIPH_A, 0); /* CMD */
select_peripheral(PA(12), PERIPH_A, 0); /* DATA0 */
if (gpio_is_valid(data->detect_pin)) if (gpio_is_valid(data->slot[0].detect_pin))
at32_select_gpio(data->detect_pin, 0); at32_select_gpio(data->slot[0].detect_pin, 0);
if (gpio_is_valid(data->wp_pin)) if (gpio_is_valid(data->slot[0].wp_pin))
at32_select_gpio(data->wp_pin, 0); at32_select_gpio(data->slot[0].wp_pin, 0);
break;
case 0:
/* Slot is unused */
break;
default:
goto fail;
}
switch (data->slot[1].bus_width) {
case 4:
select_peripheral(PB(8), PERIPH_B, 0); /* DATA1 */
select_peripheral(PB(9), PERIPH_B, 0); /* DATA2 */
select_peripheral(PB(10), PERIPH_B, 0); /* DATA3 */
/* fall through */
case 1:
select_peripheral(PB(6), PERIPH_B, 0); /* CMD */
select_peripheral(PB(7), PERIPH_B, 0); /* DATA0 */
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;
default:
if (!data->slot[0].bus_width)
goto fail;
data->slot[1].bus_width = 0;
break;
}
atmel_mci0_pclk.dev = &pdev->dev; atmel_mci0_pclk.dev = &pdev->dev;

View File

@ -114,6 +114,17 @@ config MMC_ATMELMCI
If unsure, say N. If unsure, say N.
config MMC_ATMELMCI_DMA
bool "Atmel MCI DMA support (EXPERIMENTAL)"
depends on MMC_ATMELMCI && DMA_ENGINE && EXPERIMENTAL
help
Say Y here to have the Atmel MCI driver use a DMA engine to
do data transfers and thus increase the throughput and
reduce the CPU utilization. Note that this is highly
experimental and may cause the driver to lock up.
If unsure, say N.
config MMC_IMX config MMC_IMX
tristate "Motorola i.MX Multimedia Card Interface support" tristate "Motorola i.MX Multimedia Card Interface support"
depends on ARCH_IMX depends on ARCH_IMX

View File

@ -25,8 +25,10 @@
#define MCI_SDCR 0x000c /* SD Card / SDIO */ #define MCI_SDCR 0x000c /* SD Card / SDIO */
# define MCI_SDCSEL_SLOT_A ( 0 << 0) /* Select SD slot A */ # define MCI_SDCSEL_SLOT_A ( 0 << 0) /* Select SD slot A */
# define MCI_SDCSEL_SLOT_B ( 1 << 0) /* Select SD slot A */ # define MCI_SDCSEL_SLOT_B ( 1 << 0) /* Select SD slot A */
# define MCI_SDCBUS_1BIT ( 0 << 7) /* 1-bit data bus */ # define MCI_SDCSEL_MASK ( 3 << 0)
# define MCI_SDCBUS_4BIT ( 1 << 7) /* 4-bit data bus */ # define MCI_SDCBUS_1BIT ( 0 << 6) /* 1-bit data bus */
# define MCI_SDCBUS_4BIT ( 2 << 6) /* 4-bit data bus */
# define MCI_SDCBUS_MASK ( 3 << 6)
#define MCI_ARGR 0x0010 /* Command Argument */ #define MCI_ARGR 0x0010 /* Command Argument */
#define MCI_CMDR 0x0014 /* Command */ #define MCI_CMDR 0x0014 /* Command */
# define MCI_CMDR_CMDNB(x) ((x) << 0) /* Command Opcode */ # define MCI_CMDR_CMDNB(x) ((x) << 0) /* Command Opcode */

File diff suppressed because it is too large Load Diff