MMC highlights for 3.12:
Core: - Support Allocation Units 8MB-64MB in SD3.0, previous max was 4MB. - The slot-gpio helper can now handle GPIO debouncing card-detect. - Read supported voltages from DT "voltage-ranges" property. Drivers: - dw_mmc: Add support for ARC architecture, and support exynos5420. - mmc_spi: Support CD/RO GPIOs. - sh_mobile_sdhi: Add compatibility for more Renesas SoCs. - sh_mmcif: Add DT support for DMA channels. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.13 (GNU/Linux) iQIcBAABAgAGBQJSLxu8AAoJEHNBYZ7TNxYMkV8P/RZMkP3L88wPmvdQ4IxVD/Bg jphPsZTAlY8pLY7EcBVfbIGfBMMoVZ8CayuAbj9u5jFiMBNDUKRnKrky1m95F62n xXiS5vUiKdWpByMpfKmrqvJr6eS8SWq5z/yug1c3s1Y9T363KgfypgJLvNgbMGiv qbmjE+Zw65nMwHCk+4Rvq6s4aN6KosRZP0ABsn1foXt3kybSgemp5ShrlEyXohfS E91EiYxHFC4fdmuWiZZvL1tyHFeV25omyZA90mpkioNItiwoyOM2rfjfEfNq+WBw UrmdBesbGsF0Zi12CBa9LtzdRjYK8PugBWKW3mycS5++NX9KW6Ac/EpGqFeH9KgL WZ2v4aQjkbnzQKUB2HcWAyXm88G9MkNvpLbIrmIPtson+q0UjgPYWe5BI3dy/Y1v YS1JeseslVtSTKzGYsa1GJ7Nc1xYiILRz0RS4YGYXNjwvrl89i2UH7cglYDW36Xd vxvRBaFpVsj1mfjjITEoG6nE0v5aYH6gSITY79XR+/kN871/99/oIUaWdpjcm9yv SIYmK7ipcvxugkQ7BoMGbym/dvuUrZ+Vnf8dFlGPTJegZVsnfgrVAnRpvcVwW8+x 4Z79wUPSIETRqj2XX2I/Y0JnrXry+dLLVyeK1tELoeOKev73Ai2lcqPSz6J0tzJs IErcz0hM1znL2RtgNwio =+EYB -----END PGP SIGNATURE----- Merge tag 'mmc-updates-for-3.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/cjb/mmc Pull MMC updates from Chris Ball: "MMC highlights for 3.12: Core: - Support Allocation Units 8MB-64MB in SD3.0, previous max was 4MB. - The slot-gpio helper can now handle GPIO debouncing card-detect. - Read supported voltages from DT "voltage-ranges" property. Drivers: - dw_mmc: Add support for ARC architecture, and support exynos5420. - mmc_spi: Support CD/RO GPIOs. - sh_mobile_sdhi: Add compatibility for more Renesas SoCs. - sh_mmcif: Add DT support for DMA channels" * tag 'mmc-updates-for-3.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/cjb/mmc: (50 commits) Revert "mmc: tmio-mmc: Remove .set_pwr() callback from platform data" mmc: dw_mmc: Add support for ARC mmc: sdhci-s3c: initialize host->quirks2 for using quirks2 mmc: sdhci-s3c: fix the wrong register value, when clock is disabled mmc: esdhc: add support to get voltage from device-tree mmc: sdhci: get voltage from sdhc host mmc: core: parse voltage from device-tree mmc: omap_hsmmc: use the generic config for omap2plus devices mmc: omap_hsmmc: clear status flags before starting a new command mmc: dw_mmc: exynos: Add a new compatible string for exynos5420 mmc: sh_mmcif: revision-specific CLK_CTRL2 handling mmc: sh_mmcif: revision-specific Command Completion Signal handling mmc: sh_mmcif: add support for Device Tree DMA bindings mmc: sh_mmcif: move header include from header into .c mmc: SDHI: add DT compatibility strings for further SoCs mmc: dw_mmc-pci: enable bus-mastering mode mmc: dw_mmc-pci: get resources from a proper BAR mmc: tmio-mmc: Remove .set_pwr() callback from platform data mmc: tmio-mmc: Remove .get_cd() callback from platform data mmc: sh_mobile_sdhi: Remove .set_pwr() callback from platform data ...
This commit is contained in:
commit
d0048f0b91
|
@ -19,6 +19,9 @@ Optional properties:
|
|||
"bus-width = <1>" property.
|
||||
- sdhci,auto-cmd12: specifies that a controller can only handle auto
|
||||
CMD12.
|
||||
- voltage-ranges : two cells are required, first cell specifies minimum
|
||||
slot voltage (mV), second cell specifies maximum slot voltage (mV).
|
||||
Several ranges could be specified.
|
||||
|
||||
Example:
|
||||
|
||||
|
@ -29,4 +32,5 @@ sdhci@2e000 {
|
|||
interrupt-parent = <&ipic>;
|
||||
/* Filled in by U-Boot */
|
||||
clock-frequency = <0>;
|
||||
voltage-ranges = <3300 3300>;
|
||||
};
|
||||
|
|
|
@ -224,62 +224,15 @@ static struct ep93xx_spi_chip_ops vision_spi_flash_hw = {
|
|||
#define VISION_SPI_MMC_WP EP93XX_GPIO_LINE_F(0)
|
||||
#define VISION_SPI_MMC_CD EP93XX_GPIO_LINE_EGPIO15
|
||||
|
||||
static struct gpio vision_spi_mmc_gpios[] = {
|
||||
{ VISION_SPI_MMC_WP, GPIOF_DIR_IN, "mmc_spi:wp" },
|
||||
{ VISION_SPI_MMC_CD, GPIOF_DIR_IN, "mmc_spi:cd" },
|
||||
};
|
||||
|
||||
static int vision_spi_mmc_init(struct device *pdev,
|
||||
irqreturn_t (*func)(int, void *), void *pdata)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = gpio_request_array(vision_spi_mmc_gpios,
|
||||
ARRAY_SIZE(vision_spi_mmc_gpios));
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = gpio_set_debounce(VISION_SPI_MMC_CD, 1);
|
||||
if (err)
|
||||
goto exit_err;
|
||||
|
||||
err = request_irq(gpio_to_irq(VISION_SPI_MMC_CD), func,
|
||||
IRQ_TYPE_EDGE_BOTH, "mmc_spi:cd", pdata);
|
||||
if (err)
|
||||
goto exit_err;
|
||||
|
||||
return 0;
|
||||
|
||||
exit_err:
|
||||
gpio_free_array(vision_spi_mmc_gpios, ARRAY_SIZE(vision_spi_mmc_gpios));
|
||||
return err;
|
||||
|
||||
}
|
||||
|
||||
static void vision_spi_mmc_exit(struct device *pdev, void *pdata)
|
||||
{
|
||||
free_irq(gpio_to_irq(VISION_SPI_MMC_CD), pdata);
|
||||
gpio_free_array(vision_spi_mmc_gpios, ARRAY_SIZE(vision_spi_mmc_gpios));
|
||||
}
|
||||
|
||||
static int vision_spi_mmc_get_ro(struct device *pdev)
|
||||
{
|
||||
return !!gpio_get_value(VISION_SPI_MMC_WP);
|
||||
}
|
||||
|
||||
static int vision_spi_mmc_get_cd(struct device *pdev)
|
||||
{
|
||||
return !gpio_get_value(VISION_SPI_MMC_CD);
|
||||
}
|
||||
|
||||
static struct mmc_spi_platform_data vision_spi_mmc_data = {
|
||||
.init = vision_spi_mmc_init,
|
||||
.exit = vision_spi_mmc_exit,
|
||||
.get_ro = vision_spi_mmc_get_ro,
|
||||
.get_cd = vision_spi_mmc_get_cd,
|
||||
.detect_delay = 100,
|
||||
.powerup_msecs = 100,
|
||||
.ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34,
|
||||
.flags = MMC_SPI_USE_CD_GPIO | MMC_SPI_USE_RO_GPIO,
|
||||
.cd_gpio = VISION_SPI_MMC_CD,
|
||||
.cd_debounce = 1,
|
||||
.ro_gpio = VISION_SPI_MMC_WP,
|
||||
.caps2 = MMC_CAP2_RO_ACTIVE_HIGH,
|
||||
};
|
||||
|
||||
static int vision_spi_mmc_hw_setup(struct spi_device *spi)
|
||||
|
|
|
@ -600,37 +600,13 @@ static struct platform_device sdhi0_power = {
|
|||
},
|
||||
};
|
||||
|
||||
static void sdhi0_set_pwr(struct platform_device *pdev, int state)
|
||||
{
|
||||
static int power_gpio = -EINVAL;
|
||||
|
||||
if (power_gpio < 0) {
|
||||
int ret = gpio_request(GPIO_PTB6, NULL);
|
||||
if (!ret) {
|
||||
power_gpio = GPIO_PTB6;
|
||||
gpio_direction_output(power_gpio, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Toggle the GPIO regardless, whether we managed to grab it above or
|
||||
* the fixed regulator driver did.
|
||||
*/
|
||||
gpio_set_value(GPIO_PTB6, state);
|
||||
}
|
||||
|
||||
static int sdhi0_get_cd(struct platform_device *pdev)
|
||||
{
|
||||
return !gpio_get_value(GPIO_PTY7);
|
||||
}
|
||||
|
||||
static struct sh_mobile_sdhi_info sdhi0_info = {
|
||||
.dma_slave_tx = SHDMA_SLAVE_SDHI0_TX,
|
||||
.dma_slave_rx = SHDMA_SLAVE_SDHI0_RX,
|
||||
.set_pwr = sdhi0_set_pwr,
|
||||
.tmio_caps = MMC_CAP_SDIO_IRQ | MMC_CAP_POWER_OFF_CARD |
|
||||
MMC_CAP_NEEDS_POLL,
|
||||
.get_cd = sdhi0_get_cd,
|
||||
.tmio_flags = TMIO_MMC_USE_GPIO_CD,
|
||||
.cd_gpio = GPIO_PTY7,
|
||||
};
|
||||
|
||||
static struct resource sdhi0_resources[] = {
|
||||
|
@ -656,39 +632,15 @@ static struct platform_device sdhi0_device = {
|
|||
},
|
||||
};
|
||||
|
||||
static void cn12_set_pwr(struct platform_device *pdev, int state)
|
||||
{
|
||||
static int power_gpio = -EINVAL;
|
||||
|
||||
if (power_gpio < 0) {
|
||||
int ret = gpio_request(GPIO_PTB7, NULL);
|
||||
if (!ret) {
|
||||
power_gpio = GPIO_PTB7;
|
||||
gpio_direction_output(power_gpio, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Toggle the GPIO regardless, whether we managed to grab it above or
|
||||
* the fixed regulator driver did.
|
||||
*/
|
||||
gpio_set_value(GPIO_PTB7, state);
|
||||
}
|
||||
|
||||
#if !defined(CONFIG_MMC_SH_MMCIF) && !defined(CONFIG_MMC_SH_MMCIF_MODULE)
|
||||
/* SDHI1 */
|
||||
static int sdhi1_get_cd(struct platform_device *pdev)
|
||||
{
|
||||
return !gpio_get_value(GPIO_PTW7);
|
||||
}
|
||||
|
||||
static struct sh_mobile_sdhi_info sdhi1_info = {
|
||||
.dma_slave_tx = SHDMA_SLAVE_SDHI1_TX,
|
||||
.dma_slave_rx = SHDMA_SLAVE_SDHI1_RX,
|
||||
.tmio_caps = MMC_CAP_SDIO_IRQ | MMC_CAP_POWER_OFF_CARD |
|
||||
MMC_CAP_NEEDS_POLL,
|
||||
.set_pwr = cn12_set_pwr,
|
||||
.get_cd = sdhi1_get_cd,
|
||||
.tmio_flags = TMIO_MMC_USE_GPIO_CD,
|
||||
.cd_gpio = GPIO_PTW7,
|
||||
};
|
||||
|
||||
static struct resource sdhi1_resources[] = {
|
||||
|
@ -718,27 +670,19 @@ static struct platform_device sdhi1_device = {
|
|||
#else
|
||||
|
||||
/* MMC SPI */
|
||||
static int mmc_spi_get_ro(struct device *dev)
|
||||
{
|
||||
return gpio_get_value(GPIO_PTY6);
|
||||
}
|
||||
|
||||
static int mmc_spi_get_cd(struct device *dev)
|
||||
{
|
||||
return !gpio_get_value(GPIO_PTY7);
|
||||
}
|
||||
|
||||
static void mmc_spi_setpower(struct device *dev, unsigned int maskval)
|
||||
{
|
||||
gpio_set_value(GPIO_PTB6, maskval ? 1 : 0);
|
||||
}
|
||||
|
||||
static struct mmc_spi_platform_data mmc_spi_info = {
|
||||
.get_ro = mmc_spi_get_ro,
|
||||
.get_cd = mmc_spi_get_cd,
|
||||
.caps = MMC_CAP_NEEDS_POLL,
|
||||
.caps2 = MMC_CAP2_RO_ACTIVE_HIGH,
|
||||
.ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34, /* 3.3V only */
|
||||
.setpower = mmc_spi_setpower,
|
||||
.flags = MMC_SPI_USE_CD_GPIO | MMC_SPI_USE_RO_GPIO,
|
||||
.cd_gpio = GPIO_PTY7,
|
||||
.ro_gpio = GPIO_PTY6,
|
||||
};
|
||||
|
||||
static struct spi_board_info spi_bus[] = {
|
||||
|
@ -998,11 +942,6 @@ static struct platform_device vou_device = {
|
|||
|
||||
#if defined(CONFIG_MMC_SH_MMCIF) || defined(CONFIG_MMC_SH_MMCIF_MODULE)
|
||||
/* SH_MMCIF */
|
||||
static void mmcif_down_pwr(struct platform_device *pdev)
|
||||
{
|
||||
cn12_set_pwr(pdev, 0);
|
||||
}
|
||||
|
||||
static struct resource sh_mmcif_resources[] = {
|
||||
[0] = {
|
||||
.name = "SH_MMCIF",
|
||||
|
@ -1023,8 +962,6 @@ static struct resource sh_mmcif_resources[] = {
|
|||
};
|
||||
|
||||
static struct sh_mmcif_plat_data sh_mmcif_plat = {
|
||||
.set_pwr = cn12_set_pwr,
|
||||
.down_pwr = mmcif_down_pwr,
|
||||
.sup_pclk = 0, /* SH7724: Max Pclk/2 */
|
||||
.caps = MMC_CAP_4_BIT_DATA |
|
||||
MMC_CAP_8_BIT_DATA |
|
||||
|
@ -1341,10 +1278,6 @@ static int __init arch_setup(void)
|
|||
gpio_direction_input(GPIO_PTR6);
|
||||
|
||||
/* SD-card slot CN11 */
|
||||
/* Card-detect, used on CN11, either with SDHI0 or with SPI */
|
||||
gpio_request(GPIO_PTY7, NULL);
|
||||
gpio_direction_input(GPIO_PTY7);
|
||||
|
||||
#if defined(CONFIG_MMC_SDHI) || defined(CONFIG_MMC_SDHI_MODULE)
|
||||
/* enable SDHI0 on CN11 (needs DS2.4 set to ON) */
|
||||
gpio_request(GPIO_FN_SDHI0WP, NULL);
|
||||
|
@ -1363,8 +1296,6 @@ static int __init arch_setup(void)
|
|||
gpio_direction_output(GPIO_PTM4, 1); /* active low CS */
|
||||
gpio_request(GPIO_PTB6, NULL); /* 3.3V power control */
|
||||
gpio_direction_output(GPIO_PTB6, 0); /* disable power by default */
|
||||
gpio_request(GPIO_PTY6, NULL); /* write protect */
|
||||
gpio_direction_input(GPIO_PTY6);
|
||||
|
||||
spi_register_board_info(spi_bus, ARRAY_SIZE(spi_bus));
|
||||
#endif
|
||||
|
@ -1394,10 +1325,6 @@ static int __init arch_setup(void)
|
|||
gpio_request(GPIO_FN_SDHI1D1, NULL);
|
||||
gpio_request(GPIO_FN_SDHI1D0, NULL);
|
||||
|
||||
/* Card-detect, used on CN12 with SDHI1 */
|
||||
gpio_request(GPIO_PTW7, NULL);
|
||||
gpio_direction_input(GPIO_PTW7);
|
||||
|
||||
cn12_enabled = true;
|
||||
#endif
|
||||
|
||||
|
|
|
@ -812,7 +812,7 @@ static int mmc_blk_cmd_error(struct request *req, const char *name, int error,
|
|||
* Otherwise we don't understand what happened, so abort.
|
||||
*/
|
||||
static int mmc_blk_cmd_recovery(struct mmc_card *card, struct request *req,
|
||||
struct mmc_blk_request *brq, int *ecc_err)
|
||||
struct mmc_blk_request *brq, int *ecc_err, int *gen_err)
|
||||
{
|
||||
bool prev_cmd_status_valid = true;
|
||||
u32 status, stop_status = 0;
|
||||
|
@ -850,6 +850,16 @@ static int mmc_blk_cmd_recovery(struct mmc_card *card, struct request *req,
|
|||
(brq->cmd.resp[0] & R1_CARD_ECC_FAILED))
|
||||
*ecc_err = 1;
|
||||
|
||||
/* Flag General errors */
|
||||
if (!mmc_host_is_spi(card->host) && rq_data_dir(req) != READ)
|
||||
if ((status & R1_ERROR) ||
|
||||
(brq->stop.resp[0] & R1_ERROR)) {
|
||||
pr_err("%s: %s: general error sending stop or status command, stop cmd response %#x, card status %#x\n",
|
||||
req->rq_disk->disk_name, __func__,
|
||||
brq->stop.resp[0], status);
|
||||
*gen_err = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check the current card state. If it is in some data transfer
|
||||
* mode, tell it to stop (and hopefully transition back to TRAN.)
|
||||
|
@ -869,6 +879,13 @@ static int mmc_blk_cmd_recovery(struct mmc_card *card, struct request *req,
|
|||
return ERR_ABORT;
|
||||
if (stop_status & R1_CARD_ECC_FAILED)
|
||||
*ecc_err = 1;
|
||||
if (!mmc_host_is_spi(card->host) && rq_data_dir(req) != READ)
|
||||
if (stop_status & R1_ERROR) {
|
||||
pr_err("%s: %s: general error sending stop command, stop cmd response %#x\n",
|
||||
req->rq_disk->disk_name, __func__,
|
||||
stop_status);
|
||||
*gen_err = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check for set block count errors */
|
||||
|
@ -1097,7 +1114,7 @@ static int mmc_blk_err_check(struct mmc_card *card,
|
|||
mmc_active);
|
||||
struct mmc_blk_request *brq = &mq_mrq->brq;
|
||||
struct request *req = mq_mrq->req;
|
||||
int ecc_err = 0;
|
||||
int ecc_err = 0, gen_err = 0;
|
||||
|
||||
/*
|
||||
* sbc.error indicates a problem with the set block count
|
||||
|
@ -1111,7 +1128,7 @@ static int mmc_blk_err_check(struct mmc_card *card,
|
|||
*/
|
||||
if (brq->sbc.error || brq->cmd.error || brq->stop.error ||
|
||||
brq->data.error) {
|
||||
switch (mmc_blk_cmd_recovery(card, req, brq, &ecc_err)) {
|
||||
switch (mmc_blk_cmd_recovery(card, req, brq, &ecc_err, &gen_err)) {
|
||||
case ERR_RETRY:
|
||||
return MMC_BLK_RETRY;
|
||||
case ERR_ABORT:
|
||||
|
@ -1143,6 +1160,14 @@ static int mmc_blk_err_check(struct mmc_card *card,
|
|||
u32 status;
|
||||
unsigned long timeout;
|
||||
|
||||
/* Check stop command response */
|
||||
if (brq->stop.resp[0] & R1_ERROR) {
|
||||
pr_err("%s: %s: general error sending stop command, stop cmd response %#x\n",
|
||||
req->rq_disk->disk_name, __func__,
|
||||
brq->stop.resp[0]);
|
||||
gen_err = 1;
|
||||
}
|
||||
|
||||
timeout = jiffies + msecs_to_jiffies(MMC_BLK_TIMEOUT_MS);
|
||||
do {
|
||||
int err = get_card_status(card, &status, 5);
|
||||
|
@ -1152,6 +1177,13 @@ static int mmc_blk_err_check(struct mmc_card *card,
|
|||
return MMC_BLK_CMD_ERR;
|
||||
}
|
||||
|
||||
if (status & R1_ERROR) {
|
||||
pr_err("%s: %s: general error sending status command, card status %#x\n",
|
||||
req->rq_disk->disk_name, __func__,
|
||||
status);
|
||||
gen_err = 1;
|
||||
}
|
||||
|
||||
/* Timeout if the device never becomes ready for data
|
||||
* and never leaves the program state.
|
||||
*/
|
||||
|
@ -1171,6 +1203,13 @@ static int mmc_blk_err_check(struct mmc_card *card,
|
|||
(R1_CURRENT_STATE(status) == R1_STATE_PRG));
|
||||
}
|
||||
|
||||
/* if general error occurs, retry the write operation. */
|
||||
if (gen_err) {
|
||||
pr_warn("%s: retrying write for general error\n",
|
||||
req->rq_disk->disk_name);
|
||||
return MMC_BLK_RETRY;
|
||||
}
|
||||
|
||||
if (brq->data.error) {
|
||||
pr_err("%s: error %d transferring data, sector %u, nr %u, cmd response %#x, card status %#x\n",
|
||||
req->rq_disk->disk_name, brq->data.error,
|
||||
|
@ -2191,10 +2230,10 @@ static void mmc_blk_remove_req(struct mmc_blk_data *md)
|
|||
* is freeing the queue that stops new requests
|
||||
* from being accepted.
|
||||
*/
|
||||
card = md->queue.card;
|
||||
mmc_cleanup_queue(&md->queue);
|
||||
if (md->flags & MMC_BLK_PACKED_CMD)
|
||||
mmc_packed_clean(&md->queue);
|
||||
card = md->queue.card;
|
||||
if (md->disk->flags & GENHD_FL_UP) {
|
||||
device_remove_file(disk_to_dev(md->disk), &md->force_ro);
|
||||
if ((md->area_type & MMC_BLK_DATA_AREA_BOOT) &&
|
||||
|
|
|
@ -2849,18 +2849,12 @@ static ssize_t mtf_test_write(struct file *file, const char __user *buf,
|
|||
struct seq_file *sf = (struct seq_file *)file->private_data;
|
||||
struct mmc_card *card = (struct mmc_card *)sf->private;
|
||||
struct mmc_test_card *test;
|
||||
char lbuf[12];
|
||||
long testcase;
|
||||
int ret;
|
||||
|
||||
if (count >= sizeof(lbuf))
|
||||
return -EINVAL;
|
||||
|
||||
if (copy_from_user(lbuf, buf, count))
|
||||
return -EFAULT;
|
||||
lbuf[count] = '\0';
|
||||
|
||||
if (strict_strtol(lbuf, 10, &testcase))
|
||||
return -EINVAL;
|
||||
ret = kstrtol_from_user(buf, count, 10, &testcase);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
test = kzalloc(sizeof(struct mmc_test_card), GFP_KERNEL);
|
||||
if (!test)
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include <linux/fault-inject.h>
|
||||
#include <linux/random.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/of.h>
|
||||
|
||||
#include <linux/mmc/card.h>
|
||||
#include <linux/mmc/host.h>
|
||||
|
@ -1196,6 +1197,49 @@ u32 mmc_vddrange_to_ocrmask(int vdd_min, int vdd_max)
|
|||
}
|
||||
EXPORT_SYMBOL(mmc_vddrange_to_ocrmask);
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
|
||||
/**
|
||||
* mmc_of_parse_voltage - return mask of supported voltages
|
||||
* @np: The device node need to be parsed.
|
||||
* @mask: mask of voltages available for MMC/SD/SDIO
|
||||
*
|
||||
* 1. Return zero on success.
|
||||
* 2. Return negative errno: voltage-range is invalid.
|
||||
*/
|
||||
int mmc_of_parse_voltage(struct device_node *np, u32 *mask)
|
||||
{
|
||||
const u32 *voltage_ranges;
|
||||
int num_ranges, i;
|
||||
|
||||
voltage_ranges = of_get_property(np, "voltage-ranges", &num_ranges);
|
||||
num_ranges = num_ranges / sizeof(*voltage_ranges) / 2;
|
||||
if (!voltage_ranges || !num_ranges) {
|
||||
pr_info("%s: voltage-ranges unspecified\n", np->full_name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for (i = 0; i < num_ranges; i++) {
|
||||
const int j = i * 2;
|
||||
u32 ocr_mask;
|
||||
|
||||
ocr_mask = mmc_vddrange_to_ocrmask(
|
||||
be32_to_cpu(voltage_ranges[j]),
|
||||
be32_to_cpu(voltage_ranges[j + 1]));
|
||||
if (!ocr_mask) {
|
||||
pr_err("%s: voltage-range #%d is invalid\n",
|
||||
np->full_name, i);
|
||||
return -EINVAL;
|
||||
}
|
||||
*mask |= ocr_mask;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(mmc_of_parse_voltage);
|
||||
|
||||
#endif /* CONFIG_OF */
|
||||
|
||||
#ifdef CONFIG_REGULATOR
|
||||
|
||||
/**
|
||||
|
|
|
@ -374,7 +374,7 @@ int mmc_of_parse(struct mmc_host *host)
|
|||
if (!(flags & OF_GPIO_ACTIVE_LOW))
|
||||
gpio_inv_cd = true;
|
||||
|
||||
ret = mmc_gpio_request_cd(host, gpio);
|
||||
ret = mmc_gpio_request_cd(host, gpio, 0);
|
||||
if (ret < 0) {
|
||||
dev_err(host->parent,
|
||||
"Failed to request CD GPIO #%d: %d!\n",
|
||||
|
|
|
@ -531,6 +531,7 @@ mmc_send_bus_test(struct mmc_card *card, struct mmc_host *host, u8 opcode,
|
|||
|
||||
data.sg = &sg;
|
||||
data.sg_len = 1;
|
||||
mmc_set_data_timeout(&data, card);
|
||||
sg_init_one(&sg, data_buf, len);
|
||||
mmc_wait_for_req(host, &mrq);
|
||||
err = 0;
|
||||
|
|
|
@ -215,7 +215,7 @@ static int mmc_decode_scr(struct mmc_card *card)
|
|||
static int mmc_read_ssr(struct mmc_card *card)
|
||||
{
|
||||
unsigned int au, es, et, eo;
|
||||
int err, i;
|
||||
int err, i, max_au;
|
||||
u32 *ssr;
|
||||
|
||||
if (!(card->csd.cmdclass & CCC_APP_SPEC)) {
|
||||
|
@ -239,12 +239,15 @@ static int mmc_read_ssr(struct mmc_card *card)
|
|||
for (i = 0; i < 16; i++)
|
||||
ssr[i] = be32_to_cpu(ssr[i]);
|
||||
|
||||
/* SD3.0 increases max AU size to 64MB (0xF) from 4MB (0x9) */
|
||||
max_au = card->scr.sda_spec3 ? 0xF : 0x9;
|
||||
|
||||
/*
|
||||
* UNSTUFF_BITS only works with four u32s so we have to offset the
|
||||
* bitfield positions accordingly.
|
||||
*/
|
||||
au = UNSTUFF_BITS(ssr, 428 - 384, 4);
|
||||
if (au > 0 && au <= 9) {
|
||||
if (au > 0 && au <= max_au) {
|
||||
card->ssr.au = 1 << (au + 4);
|
||||
es = UNSTUFF_BITS(ssr, 408 - 384, 16);
|
||||
et = UNSTUFF_BITS(ssr, 402 - 384, 6);
|
||||
|
@ -942,13 +945,13 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr,
|
|||
if (!mmc_host_is_spi(host)) {
|
||||
err = mmc_send_relative_addr(host, &card->rca);
|
||||
if (err)
|
||||
return err;
|
||||
goto free_card;
|
||||
}
|
||||
|
||||
if (!oldcard) {
|
||||
err = mmc_sd_get_csd(host, card);
|
||||
if (err)
|
||||
return err;
|
||||
goto free_card;
|
||||
|
||||
mmc_decode_cid(card);
|
||||
}
|
||||
|
@ -959,7 +962,7 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr,
|
|||
if (!mmc_host_is_spi(host)) {
|
||||
err = mmc_select_card(card);
|
||||
if (err)
|
||||
return err;
|
||||
goto free_card;
|
||||
}
|
||||
|
||||
err = mmc_sd_setup_card(host, card, oldcard != NULL);
|
||||
|
|
|
@ -135,6 +135,7 @@ EXPORT_SYMBOL(mmc_gpio_request_ro);
|
|||
* mmc_gpio_request_cd - request a gpio for card-detection
|
||||
* @host: mmc host
|
||||
* @gpio: gpio number requested
|
||||
* @debounce: debounce time in microseconds
|
||||
*
|
||||
* As devm_* managed functions are used in mmc_gpio_request_cd(), client
|
||||
* drivers do not need to explicitly call mmc_gpio_free_cd() for freeing up,
|
||||
|
@ -143,9 +144,14 @@ EXPORT_SYMBOL(mmc_gpio_request_ro);
|
|||
* switching for card-detection, they are responsible for calling
|
||||
* mmc_gpio_request_cd() and mmc_gpio_free_cd() as a pair on their own.
|
||||
*
|
||||
* If GPIO debouncing is desired, set the debounce parameter to a non-zero
|
||||
* value. The caller is responsible for ensuring that the GPIO driver associated
|
||||
* with the GPIO supports debouncing, otherwise an error will be returned.
|
||||
*
|
||||
* Returns zero on success, else an error.
|
||||
*/
|
||||
int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio)
|
||||
int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio,
|
||||
unsigned int debounce)
|
||||
{
|
||||
struct mmc_gpio *ctx;
|
||||
int irq = gpio_to_irq(gpio);
|
||||
|
@ -167,6 +173,12 @@ int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio)
|
|||
*/
|
||||
return ret;
|
||||
|
||||
if (debounce) {
|
||||
ret = gpio_set_debounce(gpio, debounce);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Even if gpio_to_irq() returns a valid IRQ number, the platform might
|
||||
* still prefer to poll, e.g., because that IRQ number is already used
|
||||
|
|
|
@ -284,11 +284,11 @@ config MMC_OMAP
|
|||
|
||||
config MMC_OMAP_HS
|
||||
tristate "TI OMAP High Speed Multimedia Card Interface support"
|
||||
depends on SOC_OMAP2430 || ARCH_OMAP3 || ARCH_OMAP4
|
||||
depends on ARCH_OMAP2PLUS || COMPILE_TEST
|
||||
help
|
||||
This selects the TI OMAP High Speed Multimedia card Interface.
|
||||
If you have an OMAP2430 or OMAP3 board or OMAP4 board with a
|
||||
Multimedia Card slot, say Y or M here.
|
||||
If you have an omap2plus board with a Multimedia Card slot,
|
||||
say Y or M here.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
|
@ -530,7 +530,7 @@ config SDH_BFIN_MISSING_CMD_PULLUP_WORKAROUND
|
|||
|
||||
config MMC_DW
|
||||
tristate "Synopsys DesignWare Memory Card Interface"
|
||||
depends on ARM
|
||||
depends on ARC || ARM
|
||||
help
|
||||
This selects support for the Synopsys DesignWare Mobile Storage IP
|
||||
block, this provides host support for SD and MMC interfaces, in both
|
||||
|
@ -569,7 +569,7 @@ config MMC_DW_EXYNOS
|
|||
|
||||
config MMC_DW_SOCFPGA
|
||||
tristate "SOCFPGA specific extensions for Synopsys DW Memory Card Interface"
|
||||
depends on MMC_DW
|
||||
depends on MMC_DW && MFD_SYSCON
|
||||
select MMC_DW_PLTFM
|
||||
help
|
||||
This selects support for Altera SoCFPGA specific extensions to the
|
||||
|
|
|
@ -52,8 +52,6 @@ obj-$(CONFIG_MMC_WMT) += wmt-sdmmc.o
|
|||
|
||||
obj-$(CONFIG_MMC_REALTEK_PCI) += rtsx_pci_sdmmc.o
|
||||
|
||||
obj-$(CONFIG_MMC_REALTEK_PCI) += rtsx_pci_sdmmc.o
|
||||
|
||||
obj-$(CONFIG_MMC_SDHCI_PLTFM) += sdhci-pltfm.o
|
||||
obj-$(CONFIG_MMC_SDHCI_CNS3XXX) += sdhci-cns3xxx.o
|
||||
obj-$(CONFIG_MMC_SDHCI_ESDHC_IMX) += sdhci-esdhc-imx.o
|
||||
|
|
|
@ -378,6 +378,8 @@ static int atmci_regs_show(struct seq_file *s, void *v)
|
|||
{
|
||||
struct atmel_mci *host = s->private;
|
||||
u32 *buf;
|
||||
int ret = 0;
|
||||
|
||||
|
||||
buf = kmalloc(ATMCI_REGS_SIZE, GFP_KERNEL);
|
||||
if (!buf)
|
||||
|
@ -388,12 +390,16 @@ static int atmci_regs_show(struct seq_file *s, void *v)
|
|||
* not disabling interrupts, so IMR and SR may not be
|
||||
* consistent.
|
||||
*/
|
||||
ret = clk_prepare_enable(host->mck);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
spin_lock_bh(&host->lock);
|
||||
clk_enable(host->mck);
|
||||
memcpy_fromio(buf, host->regs, ATMCI_REGS_SIZE);
|
||||
clk_disable(host->mck);
|
||||
spin_unlock_bh(&host->lock);
|
||||
|
||||
clk_disable_unprepare(host->mck);
|
||||
|
||||
seq_printf(s, "MR:\t0x%08x%s%s ",
|
||||
buf[ATMCI_MR / 4],
|
||||
buf[ATMCI_MR / 4] & ATMCI_MR_RDPROOF ? " RDPROOF" : "",
|
||||
|
@ -442,9 +448,10 @@ static int atmci_regs_show(struct seq_file *s, void *v)
|
|||
val & ATMCI_CFG_LSYNC ? " LSYNC" : "");
|
||||
}
|
||||
|
||||
out:
|
||||
kfree(buf);
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int atmci_regs_open(struct inode *inode, struct file *file)
|
||||
|
@ -1262,6 +1269,7 @@ static void atmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
|
|||
struct atmel_mci_slot *slot = mmc_priv(mmc);
|
||||
struct atmel_mci *host = slot->host;
|
||||
unsigned int i;
|
||||
bool unprepare_clk;
|
||||
|
||||
slot->sdc_reg &= ~ATMCI_SDCBUS_MASK;
|
||||
switch (ios->bus_width) {
|
||||
|
@ -1277,9 +1285,13 @@ static void atmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
|
|||
unsigned int clock_min = ~0U;
|
||||
u32 clkdiv;
|
||||
|
||||
clk_prepare(host->mck);
|
||||
unprepare_clk = true;
|
||||
|
||||
spin_lock_bh(&host->lock);
|
||||
if (!host->mode_reg) {
|
||||
clk_enable(host->mck);
|
||||
unprepare_clk = false;
|
||||
atmci_writel(host, ATMCI_CR, ATMCI_CR_SWRST);
|
||||
atmci_writel(host, ATMCI_CR, ATMCI_CR_MCIEN);
|
||||
if (host->caps.has_cfg_reg)
|
||||
|
@ -1347,6 +1359,8 @@ static void atmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
|
|||
} else {
|
||||
bool any_slot_active = false;
|
||||
|
||||
unprepare_clk = false;
|
||||
|
||||
spin_lock_bh(&host->lock);
|
||||
slot->clock = 0;
|
||||
for (i = 0; i < ATMCI_MAX_NR_SLOTS; i++) {
|
||||
|
@ -1360,12 +1374,16 @@ static void atmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
|
|||
if (host->mode_reg) {
|
||||
atmci_readl(host, ATMCI_MR);
|
||||
clk_disable(host->mck);
|
||||
unprepare_clk = true;
|
||||
}
|
||||
host->mode_reg = 0;
|
||||
}
|
||||
spin_unlock_bh(&host->lock);
|
||||
}
|
||||
|
||||
if (unprepare_clk)
|
||||
clk_unprepare(host->mck);
|
||||
|
||||
switch (ios->power_mode) {
|
||||
case MMC_POWER_UP:
|
||||
set_bit(ATMCI_CARD_NEED_INIT, &slot->flags);
|
||||
|
@ -2376,10 +2394,12 @@ static int __init atmci_probe(struct platform_device *pdev)
|
|||
if (!host->regs)
|
||||
goto err_ioremap;
|
||||
|
||||
clk_enable(host->mck);
|
||||
ret = clk_prepare_enable(host->mck);
|
||||
if (ret)
|
||||
goto err_request_irq;
|
||||
atmci_writel(host, ATMCI_CR, ATMCI_CR_SWRST);
|
||||
host->bus_hz = clk_get_rate(host->mck);
|
||||
clk_disable(host->mck);
|
||||
clk_disable_unprepare(host->mck);
|
||||
|
||||
host->mapbase = regs->start;
|
||||
|
||||
|
@ -2482,11 +2502,11 @@ static int __exit atmci_remove(struct platform_device *pdev)
|
|||
atmci_cleanup_slot(host->slot[i], i);
|
||||
}
|
||||
|
||||
clk_enable(host->mck);
|
||||
clk_prepare_enable(host->mck);
|
||||
atmci_writel(host, ATMCI_IDR, ~0UL);
|
||||
atmci_writel(host, ATMCI_CR, ATMCI_CR_MCIDIS);
|
||||
atmci_readl(host, ATMCI_SR);
|
||||
clk_disable(host->mck);
|
||||
clk_disable_unprepare(host->mck);
|
||||
|
||||
if (host->dma.chan)
|
||||
dma_release_channel(host->dma.chan);
|
||||
|
|
|
@ -39,6 +39,7 @@ enum dw_mci_exynos_type {
|
|||
DW_MCI_TYPE_EXYNOS4210,
|
||||
DW_MCI_TYPE_EXYNOS4412,
|
||||
DW_MCI_TYPE_EXYNOS5250,
|
||||
DW_MCI_TYPE_EXYNOS5420,
|
||||
};
|
||||
|
||||
/* Exynos implementation specific driver private data */
|
||||
|
@ -62,6 +63,9 @@ static struct dw_mci_exynos_compatible {
|
|||
}, {
|
||||
.compatible = "samsung,exynos5250-dw-mshc",
|
||||
.ctrl_type = DW_MCI_TYPE_EXYNOS5250,
|
||||
}, {
|
||||
.compatible = "samsung,exynos5420-dw-mshc",
|
||||
.ctrl_type = DW_MCI_TYPE_EXYNOS5420,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -90,7 +94,8 @@ static int dw_mci_exynos_setup_clock(struct dw_mci *host)
|
|||
{
|
||||
struct dw_mci_exynos_priv_data *priv = host->priv;
|
||||
|
||||
if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS5250)
|
||||
if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS5250 ||
|
||||
priv->ctrl_type == DW_MCI_TYPE_EXYNOS5420)
|
||||
host->bus_hz /= (priv->ciu_div + 1);
|
||||
else if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS4412)
|
||||
host->bus_hz /= EXYNOS4412_FIXED_CIU_CLK_DIV;
|
||||
|
@ -173,6 +178,8 @@ static const struct of_device_id dw_mci_exynos_match[] = {
|
|||
.data = &exynos_drv_data, },
|
||||
{ .compatible = "samsung,exynos5250-dw-mshc",
|
||||
.data = &exynos_drv_data, },
|
||||
{ .compatible = "samsung,exynos5420-dw-mshc",
|
||||
.data = &exynos_drv_data, },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, dw_mci_exynos_match);
|
||||
|
|
|
@ -59,7 +59,9 @@ static int dw_mci_pci_probe(struct pci_dev *pdev,
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
host->regs = pcim_iomap_table(pdev)[0];
|
||||
host->regs = pcim_iomap_table(pdev)[PCI_BAR_NO];
|
||||
|
||||
pci_set_master(pdev);
|
||||
|
||||
ret = dw_mci_probe(host);
|
||||
if (ret)
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include <linux/of.h>
|
||||
|
||||
#include "dw_mmc.h"
|
||||
#include "dw_mmc-pltfm.h"
|
||||
|
||||
static void dw_mci_rockchip_prepare_command(struct dw_mci *host, u32 *cmdr)
|
||||
{
|
||||
|
|
|
@ -1601,18 +1601,17 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id)
|
|||
|
||||
pending = mci_readl(host, MINTSTS); /* read-only mask reg */
|
||||
|
||||
/*
|
||||
* DTO fix - version 2.10a and below, and only if internal DMA
|
||||
* is configured.
|
||||
*/
|
||||
if (host->quirks & DW_MCI_QUIRK_IDMAC_DTO) {
|
||||
if (!pending &&
|
||||
((mci_readl(host, STATUS) >> 17) & 0x1fff))
|
||||
pending |= SDMMC_INT_DATA_OVER;
|
||||
}
|
||||
|
||||
if (pending) {
|
||||
|
||||
/*
|
||||
* DTO fix - version 2.10a and below, and only if internal DMA
|
||||
* is configured.
|
||||
*/
|
||||
if (host->quirks & DW_MCI_QUIRK_IDMAC_DTO) {
|
||||
if (!pending &&
|
||||
((mci_readl(host, STATUS) >> 17) & 0x1fff))
|
||||
pending |= SDMMC_INT_DATA_OVER;
|
||||
}
|
||||
|
||||
if (pending & DW_MCI_CMD_ERROR_FLAGS) {
|
||||
mci_writel(host, RINTSTS, DW_MCI_CMD_ERROR_FLAGS);
|
||||
host->cmd_status = pending;
|
||||
|
|
|
@ -713,7 +713,7 @@ static int jz4740_mmc_request_gpios(struct mmc_host *mmc,
|
|||
mmc->caps2 |= MMC_CAP2_RO_ACTIVE_HIGH;
|
||||
|
||||
if (gpio_is_valid(pdata->gpio_card_detect)) {
|
||||
ret = mmc_gpio_request_cd(mmc, pdata->gpio_card_detect);
|
||||
ret = mmc_gpio_request_cd(mmc, pdata->gpio_card_detect, 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
@ -783,9 +783,8 @@ static int jz4740_mmc_probe(struct platform_device* pdev)
|
|||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
host->base = devm_ioremap_resource(&pdev->dev, res);
|
||||
if (!host->base) {
|
||||
ret = -EBUSY;
|
||||
dev_err(&pdev->dev, "Failed to ioremap base memory\n");
|
||||
if (IS_ERR(host->base)) {
|
||||
ret = PTR_ERR(host->base);
|
||||
goto err_free_host;
|
||||
}
|
||||
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
|
||||
#include <linux/mmc/host.h>
|
||||
#include <linux/mmc/mmc.h> /* for R1_SPI_* bit values */
|
||||
#include <linux/mmc/slot-gpio.h>
|
||||
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/spi/mmc_spi.h>
|
||||
|
@ -1272,33 +1273,11 @@ static void mmc_spi_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
|
|||
}
|
||||
}
|
||||
|
||||
static int mmc_spi_get_ro(struct mmc_host *mmc)
|
||||
{
|
||||
struct mmc_spi_host *host = mmc_priv(mmc);
|
||||
|
||||
if (host->pdata && host->pdata->get_ro)
|
||||
return !!host->pdata->get_ro(mmc->parent);
|
||||
/*
|
||||
* Board doesn't support read only detection; let the mmc core
|
||||
* decide what to do.
|
||||
*/
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static int mmc_spi_get_cd(struct mmc_host *mmc)
|
||||
{
|
||||
struct mmc_spi_host *host = mmc_priv(mmc);
|
||||
|
||||
if (host->pdata && host->pdata->get_cd)
|
||||
return !!host->pdata->get_cd(mmc->parent);
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static const struct mmc_host_ops mmc_spi_ops = {
|
||||
.request = mmc_spi_request,
|
||||
.set_ios = mmc_spi_set_ios,
|
||||
.get_ro = mmc_spi_get_ro,
|
||||
.get_cd = mmc_spi_get_cd,
|
||||
.get_ro = mmc_gpio_get_ro,
|
||||
.get_cd = mmc_gpio_get_cd,
|
||||
};
|
||||
|
||||
|
||||
|
@ -1324,6 +1303,7 @@ static int mmc_spi_probe(struct spi_device *spi)
|
|||
struct mmc_host *mmc;
|
||||
struct mmc_spi_host *host;
|
||||
int status;
|
||||
bool has_ro = false;
|
||||
|
||||
/* We rely on full duplex transfers, mostly to reduce
|
||||
* per-transfer overheads (by making fewer transfers).
|
||||
|
@ -1448,18 +1428,33 @@ static int mmc_spi_probe(struct spi_device *spi)
|
|||
}
|
||||
|
||||
/* pass platform capabilities, if any */
|
||||
if (host->pdata)
|
||||
if (host->pdata) {
|
||||
mmc->caps |= host->pdata->caps;
|
||||
mmc->caps2 |= host->pdata->caps2;
|
||||
}
|
||||
|
||||
status = mmc_add_host(mmc);
|
||||
if (status != 0)
|
||||
goto fail_add_host;
|
||||
|
||||
if (host->pdata && host->pdata->flags & MMC_SPI_USE_CD_GPIO) {
|
||||
status = mmc_gpio_request_cd(mmc, host->pdata->cd_gpio,
|
||||
host->pdata->cd_debounce);
|
||||
if (status != 0)
|
||||
goto fail_add_host;
|
||||
}
|
||||
|
||||
if (host->pdata && host->pdata->flags & MMC_SPI_USE_RO_GPIO) {
|
||||
has_ro = true;
|
||||
status = mmc_gpio_request_ro(mmc, host->pdata->ro_gpio);
|
||||
if (status != 0)
|
||||
goto fail_add_host;
|
||||
}
|
||||
|
||||
dev_info(&spi->dev, "SD/MMC host %s%s%s%s%s\n",
|
||||
dev_name(&mmc->class_dev),
|
||||
host->dma_dev ? "" : ", no DMA",
|
||||
(host->pdata && host->pdata->get_ro)
|
||||
? "" : ", no WP",
|
||||
has_ro ? "" : ", no WP",
|
||||
(host->pdata && host->pdata->setpower)
|
||||
? "" : ", no poweroff",
|
||||
(mmc->caps & MMC_CAP_NEEDS_POLL)
|
||||
|
|
|
@ -757,7 +757,8 @@ static int __init mvsd_probe(struct platform_device *pdev)
|
|||
if (mvsd_data->gpio_card_detect &&
|
||||
gpio_is_valid(mvsd_data->gpio_card_detect)) {
|
||||
ret = mmc_gpio_request_cd(mmc,
|
||||
mvsd_data->gpio_card_detect);
|
||||
mvsd_data->gpio_card_detect,
|
||||
0);
|
||||
if (ret)
|
||||
goto out;
|
||||
} else {
|
||||
|
|
|
@ -102,12 +102,15 @@ static int mxs_mmc_get_cd(struct mmc_host *mmc)
|
|||
BM_SSP_STATUS_CARD_DETECT) ^ host->cd_inverted;
|
||||
}
|
||||
|
||||
static void mxs_mmc_reset(struct mxs_mmc_host *host)
|
||||
static int mxs_mmc_reset(struct mxs_mmc_host *host)
|
||||
{
|
||||
struct mxs_ssp *ssp = &host->ssp;
|
||||
u32 ctrl0, ctrl1;
|
||||
int ret;
|
||||
|
||||
stmp_reset_block(ssp->base);
|
||||
ret = stmp_reset_block(ssp->base);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ctrl0 = BM_SSP_CTRL0_IGNORE_CRC;
|
||||
ctrl1 = BF_SSP(0x3, CTRL1_SSP_MODE) |
|
||||
|
@ -132,6 +135,7 @@ static void mxs_mmc_reset(struct mxs_mmc_host *host)
|
|||
|
||||
writel(ctrl0, ssp->base + HW_SSP_CTRL0);
|
||||
writel(ctrl1, ssp->base + HW_SSP_CTRL1(ssp));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mxs_mmc_start_cmd(struct mxs_mmc_host *host,
|
||||
|
@ -618,21 +622,25 @@ static int mxs_mmc_probe(struct platform_device *pdev)
|
|||
}
|
||||
}
|
||||
|
||||
ssp->clk = clk_get(&pdev->dev, NULL);
|
||||
ssp->clk = devm_clk_get(&pdev->dev, NULL);
|
||||
if (IS_ERR(ssp->clk)) {
|
||||
ret = PTR_ERR(ssp->clk);
|
||||
goto out_mmc_free;
|
||||
}
|
||||
clk_prepare_enable(ssp->clk);
|
||||
|
||||
mxs_mmc_reset(host);
|
||||
ret = mxs_mmc_reset(host);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "Failed to reset mmc: %d\n", ret);
|
||||
goto out_clk_disable;
|
||||
}
|
||||
|
||||
ssp->dmach = dma_request_slave_channel(&pdev->dev, "rx-tx");
|
||||
if (!ssp->dmach) {
|
||||
dev_err(mmc_dev(host->mmc),
|
||||
"%s: failed to request dma\n", __func__);
|
||||
ret = -ENODEV;
|
||||
goto out_clk_put;
|
||||
goto out_clk_disable;
|
||||
}
|
||||
|
||||
/* set mmc core parameters */
|
||||
|
@ -685,9 +693,8 @@ static int mxs_mmc_probe(struct platform_device *pdev)
|
|||
out_free_dma:
|
||||
if (ssp->dmach)
|
||||
dma_release_channel(ssp->dmach);
|
||||
out_clk_put:
|
||||
out_clk_disable:
|
||||
clk_disable_unprepare(ssp->clk);
|
||||
clk_put(ssp->clk);
|
||||
out_mmc_free:
|
||||
mmc_free_host(mmc);
|
||||
return ret;
|
||||
|
@ -705,7 +712,6 @@ static int mxs_mmc_remove(struct platform_device *pdev)
|
|||
dma_release_channel(ssp->dmach);
|
||||
|
||||
clk_disable_unprepare(ssp->clk);
|
||||
clk_put(ssp->clk);
|
||||
|
||||
mmc_free_host(mmc);
|
||||
|
||||
|
|
|
@ -50,25 +50,6 @@ static struct of_mmc_spi *to_of_mmc_spi(struct device *dev)
|
|||
return container_of(dev->platform_data, struct of_mmc_spi, pdata);
|
||||
}
|
||||
|
||||
static int of_mmc_spi_read_gpio(struct device *dev, int gpio_num)
|
||||
{
|
||||
struct of_mmc_spi *oms = to_of_mmc_spi(dev);
|
||||
bool active_low = oms->alow_gpios[gpio_num];
|
||||
bool value = gpio_get_value(oms->gpios[gpio_num]);
|
||||
|
||||
return active_low ^ value;
|
||||
}
|
||||
|
||||
static int of_mmc_spi_get_cd(struct device *dev)
|
||||
{
|
||||
return of_mmc_spi_read_gpio(dev, CD_GPIO);
|
||||
}
|
||||
|
||||
static int of_mmc_spi_get_ro(struct device *dev)
|
||||
{
|
||||
return of_mmc_spi_read_gpio(dev, WP_GPIO);
|
||||
}
|
||||
|
||||
static int of_mmc_spi_init(struct device *dev,
|
||||
irqreturn_t (*irqhandler)(int, void *), void *mmc)
|
||||
{
|
||||
|
@ -130,20 +111,22 @@ struct mmc_spi_platform_data *mmc_spi_get_pdata(struct spi_device *spi)
|
|||
if (!gpio_is_valid(oms->gpios[i]))
|
||||
continue;
|
||||
|
||||
ret = gpio_request(oms->gpios[i], dev_name(dev));
|
||||
if (ret < 0) {
|
||||
oms->gpios[i] = -EINVAL;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (gpio_flags & OF_GPIO_ACTIVE_LOW)
|
||||
oms->alow_gpios[i] = true;
|
||||
}
|
||||
|
||||
if (gpio_is_valid(oms->gpios[CD_GPIO]))
|
||||
oms->pdata.get_cd = of_mmc_spi_get_cd;
|
||||
if (gpio_is_valid(oms->gpios[WP_GPIO]))
|
||||
oms->pdata.get_ro = of_mmc_spi_get_ro;
|
||||
if (gpio_is_valid(oms->gpios[CD_GPIO])) {
|
||||
oms->pdata.cd_gpio = oms->gpios[CD_GPIO];
|
||||
oms->pdata.flags |= MMC_SPI_USE_CD_GPIO;
|
||||
if (!oms->alow_gpios[CD_GPIO])
|
||||
oms->pdata.caps2 |= MMC_CAP2_CD_ACTIVE_HIGH;
|
||||
}
|
||||
if (gpio_is_valid(oms->gpios[WP_GPIO])) {
|
||||
oms->pdata.ro_gpio = oms->gpios[WP_GPIO];
|
||||
oms->pdata.flags |= MMC_SPI_USE_RO_GPIO;
|
||||
if (!oms->alow_gpios[WP_GPIO])
|
||||
oms->pdata.caps2 |= MMC_CAP2_RO_ACTIVE_HIGH;
|
||||
}
|
||||
|
||||
oms->detect_irq = irq_of_parse_and_map(np, 0);
|
||||
if (oms->detect_irq != 0) {
|
||||
|
@ -166,15 +149,10 @@ void mmc_spi_put_pdata(struct spi_device *spi)
|
|||
struct device *dev = &spi->dev;
|
||||
struct device_node *np = dev->of_node;
|
||||
struct of_mmc_spi *oms = to_of_mmc_spi(dev);
|
||||
int i;
|
||||
|
||||
if (!dev->platform_data || !np)
|
||||
return;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(oms->gpios); i++) {
|
||||
if (gpio_is_valid(oms->gpios[i]))
|
||||
gpio_free(oms->gpios[i]);
|
||||
}
|
||||
kfree(oms);
|
||||
dev->platform_data = NULL;
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include <linux/debugfs.h>
|
||||
#include <linux/dmaengine.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/sizes.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
|
@ -1041,6 +1042,7 @@ static void omap_hsmmc_do_irq(struct omap_hsmmc_host *host, int status)
|
|||
}
|
||||
}
|
||||
|
||||
OMAP_HSMMC_WRITE(host->base, STAT, status);
|
||||
if (end_cmd || ((status & CC_EN) && host->cmd))
|
||||
omap_hsmmc_cmd_done(host, host->cmd);
|
||||
if ((end_trans || (status & TC_EN)) && host->mrq)
|
||||
|
@ -1060,7 +1062,6 @@ static irqreturn_t omap_hsmmc_irq(int irq, void *dev_id)
|
|||
omap_hsmmc_do_irq(host, status);
|
||||
|
||||
/* Flush posted write */
|
||||
OMAP_HSMMC_WRITE(host->base, STAT, status);
|
||||
status = OMAP_HSMMC_READ(host->base, STAT);
|
||||
}
|
||||
|
||||
|
|
|
@ -119,7 +119,7 @@ static u8 bcm2835_sdhci_readb(struct sdhci_host *host, int reg)
|
|||
return byte;
|
||||
}
|
||||
|
||||
unsigned int bcm2835_sdhci_get_min_clock(struct sdhci_host *host)
|
||||
static unsigned int bcm2835_sdhci_get_min_clock(struct sdhci_host *host)
|
||||
{
|
||||
return MIN_FREQ;
|
||||
}
|
||||
|
|
|
@ -616,7 +616,7 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
|
|||
/* card_detect */
|
||||
switch (boarddata->cd_type) {
|
||||
case ESDHC_CD_GPIO:
|
||||
err = mmc_gpio_request_cd(host->mmc, boarddata->cd_gpio);
|
||||
err = mmc_gpio_request_cd(host->mmc, boarddata->cd_gpio, 0);
|
||||
if (err) {
|
||||
dev_err(mmc_dev(host->mmc),
|
||||
"failed to request card-detect gpio!\n");
|
||||
|
|
|
@ -316,6 +316,7 @@ static int sdhci_esdhc_probe(struct platform_device *pdev)
|
|||
|
||||
/* call to generic mmc_of_parse to support additional capabilities */
|
||||
mmc_of_parse(host->mmc);
|
||||
mmc_of_parse_voltage(np, &host->ocr_mask);
|
||||
|
||||
ret = sdhci_add_host(host);
|
||||
if (ret)
|
||||
|
|
|
@ -278,7 +278,8 @@ static int sdhci_pxav3_probe(struct platform_device *pdev)
|
|||
host->mmc->pm_caps |= pdata->pm_caps;
|
||||
|
||||
if (gpio_is_valid(pdata->ext_cd_gpio)) {
|
||||
ret = mmc_gpio_request_cd(host->mmc, pdata->ext_cd_gpio);
|
||||
ret = mmc_gpio_request_cd(host->mmc, pdata->ext_cd_gpio,
|
||||
0);
|
||||
if (ret) {
|
||||
dev_err(mmc_dev(host->mmc),
|
||||
"failed to allocate card detect gpio\n");
|
||||
|
|
|
@ -296,9 +296,12 @@ static void sdhci_cmu_set_clock(struct sdhci_host *host, unsigned int clock)
|
|||
unsigned long timeout;
|
||||
u16 clk = 0;
|
||||
|
||||
/* don't bother if the clock is going off */
|
||||
if (clock == 0)
|
||||
/* If the clock is going off, set to 0 at clock control register */
|
||||
if (clock == 0) {
|
||||
sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
|
||||
host->clock = clock;
|
||||
return;
|
||||
}
|
||||
|
||||
sdhci_s3c_set_clock(host, clock);
|
||||
|
||||
|
@ -608,6 +611,7 @@ static int sdhci_s3c_probe(struct platform_device *pdev)
|
|||
host->hw_name = "samsung-hsmmc";
|
||||
host->ops = &sdhci_s3c_ops;
|
||||
host->quirks = 0;
|
||||
host->quirks2 = 0;
|
||||
host->irq = irq;
|
||||
|
||||
/* Setup quirks for the controller */
|
||||
|
|
|
@ -84,7 +84,7 @@ static int sdhci_sirf_probe(struct platform_device *pdev)
|
|||
* gets setup in sdhci_add_host() and we oops.
|
||||
*/
|
||||
if (gpio_is_valid(priv->gpio_cd)) {
|
||||
ret = mmc_gpio_request_cd(host->mmc, priv->gpio_cd);
|
||||
ret = mmc_gpio_request_cd(host->mmc, priv->gpio_cd, 0);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "card detect irq request failed: %d\n",
|
||||
ret);
|
||||
|
|
|
@ -3119,6 +3119,9 @@ int sdhci_add_host(struct sdhci_host *host)
|
|||
SDHCI_MAX_CURRENT_MULTIPLIER;
|
||||
}
|
||||
|
||||
if (host->ocr_mask)
|
||||
ocr_avail = host->ocr_mask;
|
||||
|
||||
mmc->ocr_avail = ocr_avail;
|
||||
mmc->ocr_avail_sdio = ocr_avail;
|
||||
if (host->ocr_avail_sdio)
|
||||
|
@ -3213,6 +3216,8 @@ int sdhci_add_host(struct sdhci_host *host)
|
|||
host->tuning_timer.function = sdhci_tuning_timer;
|
||||
}
|
||||
|
||||
sdhci_init(host, 0);
|
||||
|
||||
ret = request_irq(host->irq, sdhci_irq, IRQF_SHARED,
|
||||
mmc_hostname(mmc), host);
|
||||
if (ret) {
|
||||
|
@ -3221,8 +3226,6 @@ int sdhci_add_host(struct sdhci_host *host)
|
|||
goto untasklet;
|
||||
}
|
||||
|
||||
sdhci_init(host, 0);
|
||||
|
||||
#ifdef CONFIG_MMC_DEBUG
|
||||
sdhci_dumpregs(host);
|
||||
#endif
|
||||
|
|
|
@ -61,6 +61,7 @@
|
|||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_qos.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/sh_dma.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
|
@ -133,6 +134,8 @@
|
|||
INT_BUFWEN | INT_CMD12DRE | INT_BUFRE | \
|
||||
INT_DTRANE | INT_CMD12RBE | INT_CMD12CRE)
|
||||
|
||||
#define INT_CCS (INT_CCSTO | INT_CCSRCV | INT_CCSDE)
|
||||
|
||||
/* CE_INT_MASK */
|
||||
#define MASK_ALL 0x00000000
|
||||
#define MASK_MCCSDE (1 << 29)
|
||||
|
@ -161,7 +164,7 @@
|
|||
|
||||
#define MASK_START_CMD (MASK_MCMDVIO | MASK_MBUFVIO | MASK_MWDATERR | \
|
||||
MASK_MRDATERR | MASK_MRIDXERR | MASK_MRSPERR | \
|
||||
MASK_MCCSTO | MASK_MCRCSTO | MASK_MWDATTO | \
|
||||
MASK_MCRCSTO | MASK_MWDATTO | \
|
||||
MASK_MRDATTO | MASK_MRBSYTO | MASK_MRSPTO)
|
||||
|
||||
#define MASK_CLEAN (INT_ERR_STS | MASK_MRBSYE | MASK_MCRSPE | \
|
||||
|
@ -243,6 +246,8 @@ struct sh_mmcif_host {
|
|||
int sg_blkidx;
|
||||
bool power;
|
||||
bool card_present;
|
||||
bool ccs_enable; /* Command Completion Signal support */
|
||||
bool clk_ctrl2_enable;
|
||||
struct mutex thread_lock;
|
||||
|
||||
/* DMA support */
|
||||
|
@ -386,25 +391,29 @@ static void sh_mmcif_request_dma(struct sh_mmcif_host *host,
|
|||
|
||||
host->dma_active = false;
|
||||
|
||||
if (!pdata)
|
||||
return;
|
||||
|
||||
if (pdata->slave_id_tx <= 0 || pdata->slave_id_rx <= 0)
|
||||
if (pdata) {
|
||||
if (pdata->slave_id_tx <= 0 || pdata->slave_id_rx <= 0)
|
||||
return;
|
||||
} else if (!host->pd->dev.of_node) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* We can only either use DMA for both Tx and Rx or not use it at all */
|
||||
dma_cap_zero(mask);
|
||||
dma_cap_set(DMA_SLAVE, mask);
|
||||
|
||||
host->chan_tx = dma_request_channel(mask, shdma_chan_filter,
|
||||
(void *)pdata->slave_id_tx);
|
||||
host->chan_tx = dma_request_slave_channel_compat(mask, shdma_chan_filter,
|
||||
pdata ? (void *)pdata->slave_id_tx : NULL,
|
||||
&host->pd->dev, "tx");
|
||||
dev_dbg(&host->pd->dev, "%s: TX: got channel %p\n", __func__,
|
||||
host->chan_tx);
|
||||
|
||||
if (!host->chan_tx)
|
||||
return;
|
||||
|
||||
cfg.slave_id = pdata->slave_id_tx;
|
||||
/* In the OF case the driver will get the slave ID from the DT */
|
||||
if (pdata)
|
||||
cfg.slave_id = pdata->slave_id_tx;
|
||||
cfg.direction = DMA_MEM_TO_DEV;
|
||||
cfg.dst_addr = res->start + MMCIF_CE_DATA;
|
||||
cfg.src_addr = 0;
|
||||
|
@ -412,15 +421,17 @@ static void sh_mmcif_request_dma(struct sh_mmcif_host *host,
|
|||
if (ret < 0)
|
||||
goto ecfgtx;
|
||||
|
||||
host->chan_rx = dma_request_channel(mask, shdma_chan_filter,
|
||||
(void *)pdata->slave_id_rx);
|
||||
host->chan_rx = dma_request_slave_channel_compat(mask, shdma_chan_filter,
|
||||
pdata ? (void *)pdata->slave_id_rx : NULL,
|
||||
&host->pd->dev, "rx");
|
||||
dev_dbg(&host->pd->dev, "%s: RX: got channel %p\n", __func__,
|
||||
host->chan_rx);
|
||||
|
||||
if (!host->chan_rx)
|
||||
goto erqrx;
|
||||
|
||||
cfg.slave_id = pdata->slave_id_rx;
|
||||
if (pdata)
|
||||
cfg.slave_id = pdata->slave_id_rx;
|
||||
cfg.direction = DMA_DEV_TO_MEM;
|
||||
cfg.dst_addr = 0;
|
||||
cfg.src_addr = res->start + MMCIF_CE_DATA;
|
||||
|
@ -485,8 +496,12 @@ static void sh_mmcif_sync_reset(struct sh_mmcif_host *host)
|
|||
|
||||
sh_mmcif_writel(host->addr, MMCIF_CE_VERSION, SOFT_RST_ON);
|
||||
sh_mmcif_writel(host->addr, MMCIF_CE_VERSION, SOFT_RST_OFF);
|
||||
if (host->ccs_enable)
|
||||
tmp |= SCCSTO_29;
|
||||
if (host->clk_ctrl2_enable)
|
||||
sh_mmcif_writel(host->addr, MMCIF_CE_CLK_CTRL2, 0x0F0F0000);
|
||||
sh_mmcif_bitset(host, MMCIF_CE_CLK_CTRL, tmp |
|
||||
SRSPTO_256 | SRBSYTO_29 | SRWDTO_29 | SCCSTO_29);
|
||||
SRSPTO_256 | SRBSYTO_29 | SRWDTO_29);
|
||||
/* byte swap on */
|
||||
sh_mmcif_bitset(host, MMCIF_CE_BUF_ACC, BUF_ACC_ATYP);
|
||||
}
|
||||
|
@ -866,6 +881,9 @@ static void sh_mmcif_start_cmd(struct sh_mmcif_host *host,
|
|||
break;
|
||||
}
|
||||
|
||||
if (host->ccs_enable)
|
||||
mask |= MASK_MCCSTO;
|
||||
|
||||
if (mrq->data) {
|
||||
sh_mmcif_writel(host->addr, MMCIF_CE_BLOCK_SET, 0);
|
||||
sh_mmcif_writel(host->addr, MMCIF_CE_BLOCK_SET,
|
||||
|
@ -873,7 +891,10 @@ static void sh_mmcif_start_cmd(struct sh_mmcif_host *host,
|
|||
}
|
||||
opc = sh_mmcif_set_cmd(host, mrq);
|
||||
|
||||
sh_mmcif_writel(host->addr, MMCIF_CE_INT, 0xD80430C0);
|
||||
if (host->ccs_enable)
|
||||
sh_mmcif_writel(host->addr, MMCIF_CE_INT, 0xD80430C0);
|
||||
else
|
||||
sh_mmcif_writel(host->addr, MMCIF_CE_INT, 0xD80430C0 | INT_CCS);
|
||||
sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, mask);
|
||||
/* set arg */
|
||||
sh_mmcif_writel(host->addr, MMCIF_CE_ARG, cmd->arg);
|
||||
|
@ -956,11 +977,8 @@ static int sh_mmcif_clk_update(struct sh_mmcif_host *host)
|
|||
|
||||
static void sh_mmcif_set_power(struct sh_mmcif_host *host, struct mmc_ios *ios)
|
||||
{
|
||||
struct sh_mmcif_plat_data *pd = host->pd->dev.platform_data;
|
||||
struct mmc_host *mmc = host->mmc;
|
||||
|
||||
if (pd && pd->set_pwr)
|
||||
pd->set_pwr(host->pd, ios->power_mode != MMC_POWER_OFF);
|
||||
if (!IS_ERR(mmc->supply.vmmc))
|
||||
/* Errors ignored... */
|
||||
mmc_regulator_set_ocr(mmc, mmc->supply.vmmc,
|
||||
|
@ -1241,11 +1259,14 @@ static irqreturn_t sh_mmcif_irqt(int irq, void *dev_id)
|
|||
static irqreturn_t sh_mmcif_intr(int irq, void *dev_id)
|
||||
{
|
||||
struct sh_mmcif_host *host = dev_id;
|
||||
u32 state;
|
||||
u32 state, mask;
|
||||
|
||||
state = sh_mmcif_readl(host->addr, MMCIF_CE_INT);
|
||||
sh_mmcif_writel(host->addr, MMCIF_CE_INT,
|
||||
~(state & sh_mmcif_readl(host->addr, MMCIF_CE_INT_MASK)));
|
||||
mask = sh_mmcif_readl(host->addr, MMCIF_CE_INT_MASK);
|
||||
if (host->ccs_enable)
|
||||
sh_mmcif_writel(host->addr, MMCIF_CE_INT, ~(state & mask));
|
||||
else
|
||||
sh_mmcif_writel(host->addr, MMCIF_CE_INT, INT_CCS | ~(state & mask));
|
||||
sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, state & MASK_CLEAN);
|
||||
|
||||
if (state & ~MASK_CLEAN)
|
||||
|
@ -1379,6 +1400,8 @@ static int sh_mmcif_probe(struct platform_device *pdev)
|
|||
host->mmc = mmc;
|
||||
host->addr = reg;
|
||||
host->timeout = msecs_to_jiffies(1000);
|
||||
host->ccs_enable = !pd || !pd->ccs_unsupported;
|
||||
host->clk_ctrl2_enable = pd && pd->clk_ctrl2_present;
|
||||
|
||||
host->pd = pdev;
|
||||
|
||||
|
@ -1436,7 +1459,7 @@ static int sh_mmcif_probe(struct platform_device *pdev)
|
|||
}
|
||||
|
||||
if (pd && pd->use_cd_gpio) {
|
||||
ret = mmc_gpio_request_cd(mmc, pd->cd_gpio);
|
||||
ret = mmc_gpio_request_cd(mmc, pd->cd_gpio, 0);
|
||||
if (ret < 0)
|
||||
goto erqcd;
|
||||
}
|
||||
|
|
|
@ -70,20 +70,6 @@ static void sh_mobile_sdhi_clk_disable(struct platform_device *pdev)
|
|||
clk_disable(priv->clk);
|
||||
}
|
||||
|
||||
static void sh_mobile_sdhi_set_pwr(struct platform_device *pdev, int state)
|
||||
{
|
||||
struct sh_mobile_sdhi_info *p = pdev->dev.platform_data;
|
||||
|
||||
p->set_pwr(pdev, state);
|
||||
}
|
||||
|
||||
static int sh_mobile_sdhi_get_cd(struct platform_device *pdev)
|
||||
{
|
||||
struct sh_mobile_sdhi_info *p = pdev->dev.platform_data;
|
||||
|
||||
return p->get_cd(pdev);
|
||||
}
|
||||
|
||||
static int sh_mobile_sdhi_wait_idle(struct tmio_mmc_host *host)
|
||||
{
|
||||
int timeout = 1000;
|
||||
|
@ -129,7 +115,12 @@ static const struct sh_mobile_sdhi_ops sdhi_ops = {
|
|||
static const struct of_device_id sh_mobile_sdhi_of_match[] = {
|
||||
{ .compatible = "renesas,shmobile-sdhi" },
|
||||
{ .compatible = "renesas,sh7372-sdhi" },
|
||||
{ .compatible = "renesas,sh73a0-sdhi", .data = &sh_mobile_sdhi_of_cfg[0], },
|
||||
{ .compatible = "renesas,r8a73a4-sdhi", .data = &sh_mobile_sdhi_of_cfg[0], },
|
||||
{ .compatible = "renesas,r8a7740-sdhi", .data = &sh_mobile_sdhi_of_cfg[0], },
|
||||
{ .compatible = "renesas,r8a7778-sdhi", .data = &sh_mobile_sdhi_of_cfg[0], },
|
||||
{ .compatible = "renesas,r8a7779-sdhi", .data = &sh_mobile_sdhi_of_cfg[0], },
|
||||
{ .compatible = "renesas,r8a7790-sdhi", .data = &sh_mobile_sdhi_of_cfg[0], },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, sh_mobile_sdhi_of_match);
|
||||
|
@ -180,10 +171,6 @@ static int sh_mobile_sdhi_probe(struct platform_device *pdev)
|
|||
mmc_data->capabilities |= p->tmio_caps;
|
||||
mmc_data->capabilities2 |= p->tmio_caps2;
|
||||
mmc_data->cd_gpio = p->cd_gpio;
|
||||
if (p->set_pwr)
|
||||
mmc_data->set_pwr = sh_mobile_sdhi_set_pwr;
|
||||
if (p->get_cd)
|
||||
mmc_data->get_cd = sh_mobile_sdhi_get_cd;
|
||||
|
||||
if (p->dma_slave_tx > 0 && p->dma_slave_rx > 0) {
|
||||
/*
|
||||
|
|
|
@ -104,6 +104,7 @@ static void tmio_mmc_start_dma_rx(struct tmio_mmc_host *host)
|
|||
pio:
|
||||
if (!desc) {
|
||||
/* DMA failed, fall back to PIO */
|
||||
tmio_mmc_enable_dma(host, false);
|
||||
if (ret >= 0)
|
||||
ret = -EIO;
|
||||
host->chan_rx = NULL;
|
||||
|
@ -116,7 +117,6 @@ pio:
|
|||
}
|
||||
dev_warn(&host->pdev->dev,
|
||||
"DMA failed: %d, falling back to PIO\n", ret);
|
||||
tmio_mmc_enable_dma(host, false);
|
||||
}
|
||||
|
||||
dev_dbg(&host->pdev->dev, "%s(): desc %p, cookie %d, sg[%d]\n", __func__,
|
||||
|
@ -185,6 +185,7 @@ static void tmio_mmc_start_dma_tx(struct tmio_mmc_host *host)
|
|||
pio:
|
||||
if (!desc) {
|
||||
/* DMA failed, fall back to PIO */
|
||||
tmio_mmc_enable_dma(host, false);
|
||||
if (ret >= 0)
|
||||
ret = -EIO;
|
||||
host->chan_tx = NULL;
|
||||
|
@ -197,7 +198,6 @@ pio:
|
|||
}
|
||||
dev_warn(&host->pdev->dev,
|
||||
"DMA failed: %d, falling back to PIO\n", ret);
|
||||
tmio_mmc_enable_dma(host, false);
|
||||
}
|
||||
|
||||
dev_dbg(&host->pdev->dev, "%s(): desc %p, cookie %d\n", __func__,
|
||||
|
|
|
@ -795,9 +795,13 @@ static void tmio_mmc_power_on(struct tmio_mmc_host *host, unsigned short vdd)
|
|||
* omap_hsmmc.c driver does.
|
||||
*/
|
||||
if (!IS_ERR(mmc->supply.vqmmc) && !ret) {
|
||||
regulator_enable(mmc->supply.vqmmc);
|
||||
ret = regulator_enable(mmc->supply.vqmmc);
|
||||
udelay(200);
|
||||
}
|
||||
|
||||
if (ret < 0)
|
||||
dev_dbg(&host->pdev->dev, "Regulators failed to power up: %d\n",
|
||||
ret);
|
||||
}
|
||||
|
||||
static void tmio_mmc_power_off(struct tmio_mmc_host *host)
|
||||
|
@ -932,25 +936,11 @@ static int tmio_mmc_get_ro(struct mmc_host *mmc)
|
|||
(sd_ctrl_read32(host, CTL_STATUS) & TMIO_STAT_WRPROTECT));
|
||||
}
|
||||
|
||||
static int tmio_mmc_get_cd(struct mmc_host *mmc)
|
||||
{
|
||||
struct tmio_mmc_host *host = mmc_priv(mmc);
|
||||
struct tmio_mmc_data *pdata = host->pdata;
|
||||
int ret = mmc_gpio_get_cd(mmc);
|
||||
if (ret >= 0)
|
||||
return ret;
|
||||
|
||||
if (!pdata->get_cd)
|
||||
return -ENOSYS;
|
||||
else
|
||||
return pdata->get_cd(host->pdev);
|
||||
}
|
||||
|
||||
static const struct mmc_host_ops tmio_mmc_ops = {
|
||||
.request = tmio_mmc_request,
|
||||
.set_ios = tmio_mmc_set_ios,
|
||||
.get_ro = tmio_mmc_get_ro,
|
||||
.get_cd = tmio_mmc_get_cd,
|
||||
.get_cd = mmc_gpio_get_cd,
|
||||
.enable_sdio_irq = tmio_mmc_enable_sdio_irq,
|
||||
};
|
||||
|
||||
|
@ -1106,7 +1096,7 @@ int tmio_mmc_host_probe(struct tmio_mmc_host **host,
|
|||
dev_pm_qos_expose_latency_limit(&pdev->dev, 100);
|
||||
|
||||
if (pdata->flags & TMIO_MMC_USE_GPIO_CD) {
|
||||
ret = mmc_gpio_request_cd(mmc, pdata->cd_gpio);
|
||||
ret = mmc_gpio_request_cd(mmc, pdata->cd_gpio, 0);
|
||||
if (ret < 0) {
|
||||
tmio_mmc_host_remove(_host);
|
||||
return ret;
|
||||
|
|
|
@ -2079,7 +2079,7 @@ static void vub300_enable_sdio_irq(struct mmc_host *mmc, int enable)
|
|||
kref_put(&vub300->kref, vub300_delete);
|
||||
}
|
||||
|
||||
void vub300_init_card(struct mmc_host *mmc, struct mmc_card *card)
|
||||
static void vub300_init_card(struct mmc_host *mmc, struct mmc_card *card)
|
||||
{ /* NOT irq */
|
||||
struct vub300_mmc_host *vub300 = mmc_priv(mmc);
|
||||
dev_info(&vub300->udev->dev, "NO host QUIRKS for this card\n");
|
||||
|
|
|
@ -108,7 +108,6 @@ struct tmio_mmc_data {
|
|||
unsigned int cd_gpio;
|
||||
void (*set_pwr)(struct platform_device *host, int state);
|
||||
void (*set_clk_div)(struct platform_device *host, int state);
|
||||
int (*get_cd)(struct platform_device *host);
|
||||
int (*write16_hook)(struct tmio_mmc_host *host, int addr);
|
||||
/* clock management callbacks */
|
||||
int (*clk_enable)(struct platform_device *pdev, unsigned int *f);
|
||||
|
|
|
@ -208,6 +208,8 @@ static inline void mmc_claim_host(struct mmc_host *host)
|
|||
__mmc_claim_host(host, NULL);
|
||||
}
|
||||
|
||||
struct device_node;
|
||||
extern u32 mmc_vddrange_to_ocrmask(int vdd_min, int vdd_max);
|
||||
extern int mmc_of_parse_voltage(struct device_node *np, u32 *mask);
|
||||
|
||||
#endif /* LINUX_MMC_CORE_H */
|
||||
|
|
|
@ -171,6 +171,7 @@ struct sdhci_host {
|
|||
unsigned int ocr_avail_sdio; /* OCR bit masks */
|
||||
unsigned int ocr_avail_sd;
|
||||
unsigned int ocr_avail_mmc;
|
||||
u32 ocr_mask; /* available voltages */
|
||||
|
||||
wait_queue_head_t buf_ready_int; /* Waitqueue for Buffer Read Ready interrupt */
|
||||
unsigned int tuning_done; /* Condition flag set when CMD19 succeeds */
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
|
||||
#include <linux/io.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/sh_dma.h>
|
||||
|
||||
/*
|
||||
* MMCIF : CE_CLK_CTRL [19:16]
|
||||
|
@ -33,12 +32,12 @@
|
|||
*/
|
||||
|
||||
struct sh_mmcif_plat_data {
|
||||
void (*set_pwr)(struct platform_device *pdev, int state);
|
||||
void (*down_pwr)(struct platform_device *pdev);
|
||||
int (*get_cd)(struct platform_device *pdef);
|
||||
unsigned int slave_id_tx; /* embedded slave_id_[tr]x */
|
||||
unsigned int slave_id_rx;
|
||||
bool use_cd_gpio : 1;
|
||||
bool ccs_unsupported : 1;
|
||||
bool clk_ctrl2_present : 1;
|
||||
unsigned int cd_gpio;
|
||||
u8 sup_pclk; /* 1 :SH7757, 0: SH7724/SH7372 */
|
||||
unsigned long caps;
|
||||
|
@ -62,6 +61,7 @@ struct sh_mmcif_plat_data {
|
|||
#define MMCIF_CE_INT_MASK 0x00000044
|
||||
#define MMCIF_CE_HOST_STS1 0x00000048
|
||||
#define MMCIF_CE_HOST_STS2 0x0000004C
|
||||
#define MMCIF_CE_CLK_CTRL2 0x00000070
|
||||
#define MMCIF_CE_VERSION 0x0000007C
|
||||
|
||||
/* CE_BUF_ACC */
|
||||
|
|
|
@ -25,8 +25,6 @@ struct sh_mobile_sdhi_info {
|
|||
unsigned long tmio_caps2;
|
||||
u32 tmio_ocr_mask; /* available MMC voltages */
|
||||
unsigned int cd_gpio;
|
||||
void (*set_pwr)(struct platform_device *pdev, int state);
|
||||
int (*get_cd)(struct platform_device *pdev);
|
||||
|
||||
/* callbacks for board specific setup code */
|
||||
int (*init)(struct platform_device *pdev,
|
||||
|
|
|
@ -18,7 +18,8 @@ int mmc_gpio_request_ro(struct mmc_host *host, unsigned int gpio);
|
|||
void mmc_gpio_free_ro(struct mmc_host *host);
|
||||
|
||||
int mmc_gpio_get_cd(struct mmc_host *host);
|
||||
int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio);
|
||||
int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio,
|
||||
unsigned int debounce);
|
||||
void mmc_gpio_free_cd(struct mmc_host *host);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -7,6 +7,11 @@
|
|||
struct device;
|
||||
struct mmc_host;
|
||||
|
||||
#define MMC_SPI_USE_CD_GPIO (1 << 0)
|
||||
#define MMC_SPI_USE_RO_GPIO (1 << 1)
|
||||
#define MMC_SPI_CD_GPIO_ACTIVE_LOW (1 << 2)
|
||||
#define MMC_SPI_RO_GPIO_ACTIVE_LOW (1 << 3)
|
||||
|
||||
/* Put this in platform_data of a device being used to manage an MMC/SD
|
||||
* card slot. (Modeled after PXA mmc glue; see that for usage examples.)
|
||||
*
|
||||
|
@ -21,17 +26,19 @@ struct mmc_spi_platform_data {
|
|||
void *);
|
||||
void (*exit)(struct device *, void *);
|
||||
|
||||
/* sense switch on sd cards */
|
||||
int (*get_ro)(struct device *);
|
||||
|
||||
/*
|
||||
* If board does not use CD interrupts, driver can optimize polling
|
||||
* using this function.
|
||||
* Card Detect and Read Only GPIOs. To enable debouncing on the card
|
||||
* detect GPIO, set the cd_debounce to the debounce time in
|
||||
* microseconds.
|
||||
*/
|
||||
int (*get_cd)(struct device *);
|
||||
unsigned int flags;
|
||||
unsigned int cd_gpio;
|
||||
unsigned int cd_debounce;
|
||||
unsigned int ro_gpio;
|
||||
|
||||
/* Capabilities to pass into mmc core (e.g. MMC_CAP_NEEDS_POLL). */
|
||||
unsigned long caps;
|
||||
unsigned long caps2;
|
||||
|
||||
/* how long to debounce card detect, in msecs */
|
||||
u16 detect_delay;
|
||||
|
|
Loading…
Reference in New Issue