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 = {
|
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),
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -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, ð_data[1]));
|
set_hw_addr(at32_add_device_eth(1, ð_data[1]));
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
Loading…
Reference in New Issue