diff options
Diffstat (limited to 'drivers/mci/dove-sdhci.c')
-rw-r--r-- | drivers/mci/dove-sdhci.c | 160 |
1 files changed, 42 insertions, 118 deletions
diff --git a/drivers/mci/dove-sdhci.c b/drivers/mci/dove-sdhci.c index bccda53994..d37046ad31 100644 --- a/drivers/mci/dove-sdhci.c +++ b/drivers/mci/dove-sdhci.c @@ -1,22 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + /* * Marvell Dove SDHCI MCI driver * * Pengutronix, Michael Grzeschik <mgr@pengutronix.de> * Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com> - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * */ #include <clock.h> @@ -32,55 +20,12 @@ struct dove_sdhci { struct mci_host mci; - void __iomem *base; struct sdhci sdhci; }; #define priv_from_mci_host(h) \ container_of(h, struct dove_sdhci, mci); -static void dove_sdhci_writel(struct sdhci *sdhci, int reg, u32 val) -{ - struct dove_sdhci *p = container_of(sdhci, struct dove_sdhci, sdhci); - - writel(val, p->base + reg); -} - -static void dove_sdhci_writew(struct sdhci *sdhci, int reg, u16 val) -{ - struct dove_sdhci *p = container_of(sdhci, struct dove_sdhci, sdhci); - - writew(val, p->base + reg); -} - -static void dove_sdhci_writeb(struct sdhci *sdhci, int reg, u8 val) -{ - struct dove_sdhci *p = container_of(sdhci, struct dove_sdhci, sdhci); - - writeb(val, p->base + reg); -} - -static u32 dove_sdhci_readl(struct sdhci *sdhci, int reg) -{ - struct dove_sdhci *p = container_of(sdhci, struct dove_sdhci, sdhci); - - return readl(p->base + reg); -} - -static u16 dove_sdhci_readw(struct sdhci *sdhci, int reg) -{ - struct dove_sdhci *p = container_of(sdhci, struct dove_sdhci, sdhci); - - return readw(p->base + reg); -} - -static u8 dove_sdhci_readb(struct sdhci *sdhci, int reg) -{ - struct dove_sdhci *p = container_of(sdhci, struct dove_sdhci, sdhci); - - return readb(p->base + reg); -} - static int dove_sdhci_wait_for_done(struct dove_sdhci *host, u16 mask) { u16 status; @@ -112,39 +57,26 @@ static int dove_sdhci_wait_for_done(struct dove_sdhci *host, u16 mask) static int dove_sdhci_mci_send_cmd(struct mci_host *mci, struct mci_cmd *cmd, struct mci_data *data) { - u16 val; u32 command, xfer; - u64 start; int ret; unsigned int num_bytes = 0; struct dove_sdhci *host = priv_from_mci_host(mci); - sdhci_write32(&host->sdhci, SDHCI_INT_STATUS, ~0); - - /* Do not wait for CMD_INHIBIT_DAT on stop commands */ - if (cmd->cmdidx == MMC_CMD_STOP_TRANSMISSION) - val = SDHCI_CMD_INHIBIT_CMD; - else - val = SDHCI_CMD_INHIBIT_CMD | SDHCI_CMD_INHIBIT_DATA; + ret = sdhci_wait_idle_data(&host->sdhci, cmd); + if (ret) + return ret; - /* Wait for bus idle */ - start = get_time_ns(); - while (1) { - if (!(sdhci_read16(&host->sdhci, SDHCI_PRESENT_STATE) & val)) - break; - if (is_timeout(start, 10 * MSECOND)) { - dev_err(host->mci.hw_dev, "SDHCI timeout while waiting for idle\n"); - return -ETIMEDOUT; - } - } + sdhci_write32(&host->sdhci, SDHCI_INT_STATUS, ~0); /* setup transfer data */ if (data) { num_bytes = data->blocks * data->blocksize; if (data->flags & MMC_DATA_READ) - sdhci_write32(&host->sdhci, SDHCI_DMA_ADDRESS, (u32)data->dest); + sdhci_write32(&host->sdhci, SDHCI_DMA_ADDRESS, + lower_32_bits(virt_to_phys(data->dest))); else - sdhci_write32(&host->sdhci, SDHCI_DMA_ADDRESS, (u32)data->src); + sdhci_write32(&host->sdhci, SDHCI_DMA_ADDRESS, + lower_32_bits(virt_to_phys(data->src))); sdhci_write16(&host->sdhci, SDHCI_BLOCK_SIZE, SDHCI_DMA_BOUNDARY_512K | SDHCI_TRANSFER_BLOCK_SIZE(data->blocksize)); sdhci_write16(&host->sdhci, SDHCI_BLOCK_COUNT, data->blocks); @@ -152,10 +84,12 @@ static int dove_sdhci_mci_send_cmd(struct mci_host *mci, struct mci_cmd *cmd, if (data->flags & MMC_DATA_WRITE) - dma_sync_single_for_device((unsigned long)data->src, + dma_sync_single_for_device(host->mci.hw_dev, + lower_32_bits(virt_to_phys(data->src)), num_bytes, DMA_TO_DEVICE); else - dma_sync_single_for_device((unsigned long)data->dest, + dma_sync_single_for_device(host->mci.hw_dev, + lower_32_bits(virt_to_phys(data->dest)), num_bytes, DMA_FROM_DEVICE); } @@ -181,11 +115,13 @@ static int dove_sdhci_mci_send_cmd(struct mci_host *mci, struct mci_cmd *cmd, if (data) { if (data->flags & MMC_DATA_WRITE) - dma_sync_single_for_cpu((unsigned long)data->src, + dma_sync_single_for_cpu(host->mci.hw_dev, + lower_32_bits(virt_to_phys(data->src)), num_bytes, DMA_TO_DEVICE); else - dma_sync_single_for_cpu((unsigned long)data->dest, - num_bytes, DMA_FROM_DEVICE); + dma_sync_single_for_cpu(host->mci.hw_dev, + lower_32_bits(virt_to_phys(data->dest)), + num_bytes, DMA_FROM_DEVICE); ret = dove_sdhci_wait_for_done(host, SDHCI_INT_XFER_COMPLETE); if (ret) { @@ -209,7 +145,7 @@ static u16 dove_sdhci_get_clock_divider(struct dove_sdhci *host, u32 reqclk) { u16 div; - for (div = 1; div < SDHCI_SPEC_200_MAX_CLK_DIVIDER; div *= 2) + for (div = 1; div < SDHCI_MAX_DIV_SPEC_200; div *= 2) if ((host->mci.f_max / div) <= reqclk) break; div /= 2; @@ -236,33 +172,35 @@ static void dove_sdhci_mci_set_ios(struct mci_host *mci, struct mci_ios *ios) /* set bus width */ val = sdhci_read8(&host->sdhci, SDHCI_HOST_CONTROL) & - ~(SDHCI_DATA_WIDTH_4BIT | SDHCI_DATA_WIDTH_8BIT); + ~(SDHCI_CTRL_4BITBUS | SDHCI_CTRL_8BITBUS); switch (ios->bus_width) { case MMC_BUS_WIDTH_8: - val |= SDHCI_DATA_WIDTH_8BIT; + val |= SDHCI_CTRL_8BITBUS; break; case MMC_BUS_WIDTH_4: - val |= SDHCI_DATA_WIDTH_4BIT; + val |= SDHCI_CTRL_4BITBUS; + break; + case MMC_BUS_WIDTH_1: break; } if (ios->clock > 26000000) - val |= SDHCI_HIGHSPEED_EN; + val |= SDHCI_CTRL_HISPD; else - val &= ~SDHCI_HIGHSPEED_EN; + val &= ~SDHCI_CTRL_HISPD; sdhci_write8(&host->sdhci, SDHCI_HOST_CONTROL, val); /* set bus clock */ sdhci_write16(&host->sdhci, SDHCI_CLOCK_CONTROL, 0); val = dove_sdhci_get_clock_divider(host, ios->clock); - val = SDHCI_INTCLOCK_EN | SDHCI_FREQ_SEL(val); + val = SDHCI_CLOCK_INT_EN | SDHCI_FREQ_SEL(val); sdhci_write16(&host->sdhci, SDHCI_CLOCK_CONTROL, val); /* wait for internal clock stable */ start = get_time_ns(); while (!(sdhci_read16(&host->sdhci, SDHCI_CLOCK_CONTROL) & - SDHCI_INTCLOCK_STABLE)) { + SDHCI_CLOCK_INT_STABLE)) { if (is_timeout(start, 20 * MSECOND)) { dev_err(host->mci.hw_dev, "SDHCI clock stable timeout\n"); return; @@ -270,10 +208,10 @@ static void dove_sdhci_mci_set_ios(struct mci_host *mci, struct mci_ios *ios) } /* enable bus clock */ - sdhci_write16(&host->sdhci, SDHCI_CLOCK_CONTROL, val | SDHCI_SDCLOCK_EN); + sdhci_write16(&host->sdhci, SDHCI_CLOCK_CONTROL, val | SDHCI_CLOCK_CARD_EN); } -static int dove_sdhci_mci_init(struct mci_host *mci, struct device_d *dev) +static int dove_sdhci_mci_init(struct mci_host *mci, struct device *dev) { u64 start; struct dove_sdhci *host = priv_from_mci_host(mci); @@ -302,19 +240,18 @@ static int dove_sdhci_mci_init(struct mci_host *mci, struct device_d *dev) static void dove_sdhci_set_mci_caps(struct dove_sdhci *host) { - u16 caps[2]; + u32 caps; - caps[0] = sdhci_read16(&host->sdhci, SDHCI_CAPABILITIES); - caps[1] = sdhci_read16(&host->sdhci, SDHCI_CAPABILITIES_1); + caps = sdhci_read32(&host->sdhci, SDHCI_CAPABILITIES); - if (caps[1] & SDHCI_HOSTCAP_VOLTAGE_180) + if (caps & SDHCI_CAN_VDD_180) host->mci.voltages |= MMC_VDD_165_195; - if (caps[1] & SDHCI_HOSTCAP_VOLTAGE_300) + if (caps & SDHCI_CAN_VDD_300) host->mci.voltages |= MMC_VDD_29_30 | MMC_VDD_30_31; - if (caps[1] & SDHCI_HOSTCAP_VOLTAGE_330) + if (caps & SDHCI_CAN_VDD_330) host->mci.voltages |= MMC_VDD_32_33 | MMC_VDD_33_34; - if (caps[1] & SDHCI_HOSTCAP_HIGHSPEED) + if (caps & SDHCI_CAN_DO_HISPD) host->mci.host_caps |= (MMC_CAP_MMC_HIGHSPEED_52MHZ | MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED); @@ -323,23 +260,17 @@ static void dove_sdhci_set_mci_caps(struct dove_sdhci *host) mci_of_parse(&host->mci); /* limit bus widths to controller capabilities */ - if ((caps[1] & SDHCI_HOSTCAP_8BIT) == 0) + if ((caps & SDHCI_CAN_DO_8BIT) == 0) host->mci.host_caps &= ~MMC_CAP_8_BIT_DATA; } -static int dove_sdhci_detect(struct device_d *dev) -{ - struct dove_sdhci *host = dev->priv; - return mci_detect_card(&host->mci); -} - -static int dove_sdhci_probe(struct device_d *dev) +static int dove_sdhci_probe(struct device *dev) { struct dove_sdhci *host; int ret; host = xzalloc(sizeof(*host)); - host->base = dev_request_mem_region(dev, 0); + host->sdhci.base = dev_request_mem_region(dev, 0); host->mci.max_req_size = 0x8000; host->mci.hw_dev = dev; host->mci.send_cmd = dove_sdhci_mci_send_cmd; @@ -347,14 +278,6 @@ static int dove_sdhci_probe(struct device_d *dev) host->mci.init = dove_sdhci_mci_init; host->mci.f_max = 50000000; host->mci.f_min = host->mci.f_max / 256; - host->sdhci.read32 = dove_sdhci_readl; - host->sdhci.read16 = dove_sdhci_readw; - host->sdhci.read8 = dove_sdhci_readb; - host->sdhci.write32 = dove_sdhci_writel; - host->sdhci.write16 = dove_sdhci_writew; - host->sdhci.write8 = dove_sdhci_writeb; - dev->priv = host; - dev->detect = dove_sdhci_detect; dove_sdhci_set_mci_caps(host); @@ -368,8 +291,9 @@ static struct of_device_id dove_sdhci_dt_ids[] = { { .compatible = "marvell,dove-sdhci", }, { } }; +MODULE_DEVICE_TABLE(of, dove_sdhci_dt_ids); -static struct driver_d dove_sdhci_driver = { +static struct driver dove_sdhci_driver = { .name = "dove-sdhci", .probe = dove_sdhci_probe, .of_compatible = DRV_OF_COMPAT(dove_sdhci_dt_ids), |