mirror of https://gitee.com/openkylin/linux.git
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:
commit
6ee6c6adf1
|
@ -53,8 +53,11 @@ static struct spi_board_info spi0_board_info[] __initdata = {
|
|||
};
|
||||
|
||||
static struct mci_platform_data __initdata mci0_data = {
|
||||
.slot[0] = {
|
||||
.bus_width = 4,
|
||||
.detect_pin = GPIO_PIN_PC(25),
|
||||
.wp_pin = GPIO_PIN_PE(0),
|
||||
},
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
@ -264,16 +264,20 @@ void __init setup_board(void)
|
|||
|
||||
#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 */
|
||||
#ifdef CONFIG_BOARD_ATSTK1002_SW6_CUSTOM
|
||||
static struct mci_platform_data __initdata mci0_data = {
|
||||
.detect_pin = GPIO_PIN_PC(14), /* gpio30/sdcd */
|
||||
.wp_pin = GPIO_PIN_PC(15), /* gpio31/sdwp */
|
||||
};
|
||||
#define MCI_PDATA &mci0_data
|
||||
#else
|
||||
#define MCI_PDATA NULL
|
||||
.detect_pin = -ENODEV,
|
||||
.wp_pin = -ENODEV,
|
||||
#endif /* SW6 for sd{cd,wp} 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));
|
||||
#endif
|
||||
#ifndef CONFIG_BOARD_ATSTK100X_SW2_CUSTOM
|
||||
at32_add_device_mci(0, MCI_PDATA);
|
||||
at32_add_device_mci(0, &mci0_pdata);
|
||||
#endif
|
||||
#ifdef CONFIG_BOARD_ATSTK1002_SW5_CUSTOM
|
||||
set_hw_addr(at32_add_device_eth(1, ð_data[1]));
|
||||
|
|
|
@ -66,6 +66,16 @@ static struct spi_board_info spi1_board_info[] __initdata = { {
|
|||
} };
|
||||
#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
|
||||
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));
|
||||
#endif
|
||||
#ifndef CONFIG_BOARD_ATSTK100X_SW2_CUSTOM
|
||||
at32_add_device_mci(0, NULL);
|
||||
at32_add_device_mci(0, &mci0_data);
|
||||
#endif
|
||||
at32_add_device_usba(0, NULL);
|
||||
#ifndef CONFIG_BOARD_ATSTK100X_SW3_CUSTOM
|
||||
|
|
|
@ -71,6 +71,16 @@ static struct spi_board_info spi1_board_info[] __initdata = { {
|
|||
} };
|
||||
#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
|
||||
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));
|
||||
#endif
|
||||
#ifndef CONFIG_BOARD_ATSTK100X_SW2_CUSTOM
|
||||
at32_add_device_mci(0, NULL);
|
||||
at32_add_device_mci(0, &mci0_data);
|
||||
#endif
|
||||
at32_add_device_lcdc(0, &atstk1000_lcdc_data,
|
||||
fbmem_start, fbmem_size, 0);
|
||||
|
|
|
@ -1,9 +1,39 @@
|
|||
#ifndef __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 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 */
|
||||
|
|
|
@ -1272,10 +1272,14 @@ static struct clk atmel_mci0_pclk = {
|
|||
struct platform_device *__init
|
||||
at32_add_device_mci(unsigned int id, struct mci_platform_data *data)
|
||||
{
|
||||
struct mci_platform_data _data;
|
||||
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;
|
||||
|
||||
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)))
|
||||
goto fail;
|
||||
|
||||
if (!data) {
|
||||
data = &_data;
|
||||
memset(data, -1, sizeof(struct mci_platform_data));
|
||||
data->detect_pin = GPIO_PIN_NONE;
|
||||
data->wp_pin = GPIO_PIN_NONE;
|
||||
}
|
||||
if (data->dma_slave)
|
||||
dws = kmemdup(to_dw_dma_slave(data->dma_slave),
|
||||
sizeof(struct dw_dma_slave), GFP_KERNEL);
|
||||
else
|
||||
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,
|
||||
sizeof(struct mci_platform_data)))
|
||||
goto fail;
|
||||
|
||||
select_peripheral(PA(10), PERIPH_A, 0); /* CLK */
|
||||
select_peripheral(PA(11), PERIPH_A, 0); /* CMD */
|
||||
select_peripheral(PA(12), PERIPH_A, 0); /* DATA0 */
|
||||
/* CLK line is common to both slots */
|
||||
select_peripheral(PA(10), PERIPH_A, 0);
|
||||
|
||||
switch (data->slot[0].bus_width) {
|
||||
case 4:
|
||||
select_peripheral(PA(13), PERIPH_A, 0); /* DATA1 */
|
||||
select_peripheral(PA(14), PERIPH_A, 0); /* DATA2 */
|
||||
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))
|
||||
at32_select_gpio(data->detect_pin, 0);
|
||||
if (gpio_is_valid(data->wp_pin))
|
||||
at32_select_gpio(data->wp_pin, 0);
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
|
|
|
@ -114,6 +114,17 @@ config MMC_ATMELMCI
|
|||
|
||||
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
|
||||
tristate "Motorola i.MX Multimedia Card Interface support"
|
||||
depends on ARCH_IMX
|
||||
|
|
|
@ -25,8 +25,10 @@
|
|||
#define MCI_SDCR 0x000c /* SD Card / SDIO */
|
||||
# define MCI_SDCSEL_SLOT_A ( 0 << 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_SDCBUS_4BIT ( 1 << 7) /* 4-bit data bus */
|
||||
# define MCI_SDCSEL_MASK ( 3 << 0)
|
||||
# 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_CMDR 0x0014 /* Command */
|
||||
# define MCI_CMDR_CMDNB(x) ((x) << 0) /* Command Opcode */
|
||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue