summaryrefslogtreecommitdiffstats
path: root/drivers/mci/mci-bcm2835.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mci/mci-bcm2835.c')
-rw-r--r--drivers/mci/mci-bcm2835.c35
1 files changed, 19 insertions, 16 deletions
diff --git a/drivers/mci/mci-bcm2835.c b/drivers/mci/mci-bcm2835.c
index 3380fa2afc..3546cc3a32 100644
--- a/drivers/mci/mci-bcm2835.c
+++ b/drivers/mci/mci-bcm2835.c
@@ -30,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;
@@ -118,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,
@@ -129,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);
@@ -148,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",
@@ -232,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,
@@ -301,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;
@@ -324,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,
@@ -353,7 +353,7 @@ static int bcm2835_mci_reset(struct mci_host *mci, struct device_d *mci_dev)
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;
@@ -424,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),