diff options
Diffstat (limited to 'drivers/mci/mci-bcm2835.c')
-rw-r--r-- | drivers/mci/mci-bcm2835.c | 57 |
1 files changed, 21 insertions, 36 deletions
diff --git a/drivers/mci/mci-bcm2835.c b/drivers/mci/mci-bcm2835.c index f2cb65231e..3546cc3a32 100644 --- a/drivers/mci/mci-bcm2835.c +++ b/drivers/mci/mci-bcm2835.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * Raspberry PI MCI driver * @@ -9,22 +10,6 @@ * timing workarounds) obviously extracted from the Linux kernel at: * https://github.com/raspberrypi/linux.git rpi-3.6.y * - * The Linux kernel code has the following (c) and license, which is hence - * propagated to here: - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * * Author: Wilhelm Lundgren <wilhelm.lundgren@cybercom.com> */ @@ -45,7 +30,7 @@ static int twoticks_delay; struct bcm2835_mci_host { struct mci_host mci; void __iomem *regs; - struct device_d *hw_dev; + struct device *hw_dev; int bus_width; u32 clock; u32 max_clock; @@ -133,7 +118,6 @@ static int bcm2835_mci_request(struct mci_host *mci, struct mci_cmd *cmd, struct mci_data *data) { u32 command, block_data = 0, transfer_mode = 0; int ret; - u32 wait_inhibit_mask = SDHCI_CMD_INHIBIT_CMD | SDHCI_CMD_INHIBIT_DATA; struct bcm2835_mci_host *host = to_bcm2835_host(mci); sdhci_set_cmd_xfer_mode(&host->sdhci, cmd, data, false, @@ -144,15 +128,9 @@ static int bcm2835_mci_request(struct mci_host *mci, struct mci_cmd *cmd, block_data |= data->blocksize; } - /* We shouldn't wait for data inihibit for stop commands, even - though they might use busy signaling */ - if (cmd->cmdidx == MMC_CMD_STOP_TRANSMISSION) - wait_inhibit_mask = SDHCI_CMD_INHIBIT_CMD; - - /*Wait for old command*/ - while (sdhci_read32(&host->sdhci, SDHCI_PRESENT_STATE) - & wait_inhibit_mask) - ; + ret = sdhci_wait_idle_data(&host->sdhci, cmd); + if (ret) + return ret; sdhci_write32(&host->sdhci, SDHCI_INT_ENABLE, 0xFFFFFFFF); sdhci_write32(&host->sdhci, SDHCI_INT_STATUS, 0xFFFFFFFF); @@ -163,7 +141,7 @@ static int bcm2835_mci_request(struct mci_host *mci, struct mci_cmd *cmd, command << 16 | transfer_mode); ret = bcm2835_mci_wait_command_done(host); - if (ret) { + if (ret && ret != -ETIMEDOUT) { dev_err(host->hw_dev, "Error while executing command %d\n", cmd->cmdidx); dev_err(host->hw_dev, "Status: 0x%X, Interrupt: 0x%X\n", @@ -247,6 +225,13 @@ static void bcm2835_mci_set_ios(struct mci_host *mci, struct mci_ios *ios) SDHCI_HOST_CONTROL__POWER_CONTROL__BLOCK_GAP_CONTROL); switch (ios->bus_width) { + case MMC_BUS_WIDTH_8: + sdhci_write32(&host->sdhci, + SDHCI_HOST_CONTROL__POWER_CONTROL__BLOCK_GAP_CONTROL, + (current_val & ~CONTROL0_4DATA) | CONTROL0_8DATA); + host->bus_width = 2; + dev_dbg(host->hw_dev, "Changing bus width to 8\n"); + break; case MMC_BUS_WIDTH_4: sdhci_write32(&host->sdhci, SDHCI_HOST_CONTROL__POWER_CONTROL__BLOCK_GAP_CONTROL, @@ -316,7 +301,7 @@ static void bcm2835_mci_set_ios(struct mci_host *mci, struct mci_ios *ios) host->bus_width, host->clock); } -static int bcm2835_mci_reset(struct mci_host *mci, struct device_d *mci_dev) +static int bcm2835_mci_reset(struct mci_host *mci, struct device *mci_dev) { struct bcm2835_mci_host *host; u32 ret = 0; @@ -339,7 +324,7 @@ static int bcm2835_mci_reset(struct mci_host *mci, struct device_d *mci_dev) sdhci_write32(&host->sdhci, SDHCI_HOST_CONTROL__POWER_CONTROL__BLOCK_GAP_CONTROL, - 0x00); + (SDHCI_BUS_VOLTAGE_330 | SDHCI_BUS_POWER_EN) << 8); sdhci_write32(&host->sdhci, SDHCI_ACMD12_ERR__HOST_CONTROL2, 0x00); sdhci_write32(&host->sdhci, @@ -365,13 +350,10 @@ static int bcm2835_mci_reset(struct mci_host *mci, struct device_d *mci_dev) sdhci_write32(&host->sdhci, SDHCI_INT_STATUS, 0xFFFFFFFF); - /*Now write command 0 and see if we get response*/ - sdhci_write32(&host->sdhci, SDHCI_ARGUMENT, 0x0); - sdhci_write32(&host->sdhci, SDHCI_TRANSFER_MODE__COMMAND, 0x0); - return bcm2835_mci_wait_command_done(host); + return 0; } -static int bcm2835_mci_probe(struct device_d *hw_dev) +static int bcm2835_mci_probe(struct device *hw_dev) { struct resource *iores; struct bcm2835_mci_host *host; @@ -442,11 +424,14 @@ static __maybe_unused struct of_device_id bcm2835_mci_compatible[] = { { .compatible = "brcm,bcm2835-sdhci", }, { + .compatible = "brcm,bcm2711-emmc2", + }, { /* sentinel */ } }; +MODULE_DEVICE_TABLE(of, bcm2835_mci_compatible); -static struct driver_d bcm2835_mci_driver = { +static struct driver bcm2835_mci_driver = { .name = "bcm2835_mci", .probe = bcm2835_mci_probe, .of_compatible = DRV_OF_COMPAT(bcm2835_mci_compatible), |