diff options
Diffstat (limited to 'drivers/mci/atmel-sdhci-common.c')
-rw-r--r-- | drivers/mci/atmel-sdhci-common.c | 168 |
1 files changed, 53 insertions, 115 deletions
diff --git a/drivers/mci/atmel-sdhci-common.c b/drivers/mci/atmel-sdhci-common.c index 680b1980c0..082ce842f7 100644 --- a/drivers/mci/atmel-sdhci-common.c +++ b/drivers/mci/atmel-sdhci-common.c @@ -11,10 +11,19 @@ #include <common.h> #include <mci.h> +#include <linux/bitfield.h> -#include "atmel-sdhci.h" +#include <mach/at91/early_udelay.h> + +#ifdef __PBL__ +#define udelay early_udelay +#undef dev_err +#define dev_err(d, ...) pr_err(__VA_ARGS__) +#undef dev_warn +#define dev_warn(d, ...) pr_warn(__VA_ARGS__) +#endif -#define AT91_SDHCI_CA1R 0x44 /* Capabilities 1 Register */ +#include "atmel-sdhci.h" #define AT91_SDHCI_MC1R 0x204 #define AT91_SDHCI_MC1_FCD BIT(7) @@ -30,15 +39,15 @@ static inline struct at91_sdhci *to_priv(struct sdhci *sdhci) void at91_sdhci_host_capability(struct at91_sdhci *host, unsigned *voltages) { - u16 caps; + u32 caps; - caps = sdhci_read16(&host->sdhci, SDHCI_CAPABILITIES_1); + caps = sdhci_read32(&host->sdhci, SDHCI_CAPABILITIES); - if (caps & SDHCI_HOSTCAP_VOLTAGE_330) + if (caps & SDHCI_CAN_VDD_330) *voltages |= MMC_VDD_32_33 | MMC_VDD_33_34; - if (caps & SDHCI_HOSTCAP_VOLTAGE_300) + if (caps & SDHCI_CAN_VDD_300) *voltages |= MMC_VDD_29_30 | MMC_VDD_30_31; - if (caps & SDHCI_HOSTCAP_VOLTAGE_180) + if (caps & SDHCI_CAN_VDD_180) *voltages |= MMC_VDD_165_195; } @@ -80,49 +89,18 @@ exit: return is_inserted; } -static int at91_sdhci_wait_for_done(struct at91_sdhci *host, u32 mask) -{ - struct sdhci *sdhci = &host->sdhci; - u16 status; - int ret; - - ret = sdhci_read16_poll_timeout(sdhci, SDHCI_INT_NORMAL_STATUS, status, - (status & mask) == mask || (status & SDHCI_INT_ERROR), - USEC_PER_SEC); - - if (ret < 0) { - pr_err("SDHCI timeout while waiting for done\n"); - return ret; - } - - if (status & SDHCI_INT_ERROR) { - pr_err("SDHCI_INT_ERROR: 0x%08x\n", - sdhci_read16(sdhci, SDHCI_INT_ERROR_STATUS)); - return -EPERM; - } - - return status; -} - int at91_sdhci_send_command(struct at91_sdhci *host, struct mci_cmd *cmd, struct mci_data *data) { unsigned command, xfer; struct sdhci *sdhci = &host->sdhci; - u32 mask, status, state; + u32 mask; + int status; int ret; - /* Wait for idle before next command */ - mask = SDHCI_CMD_INHIBIT_CMD; - if (cmd->cmdidx != MMC_CMD_STOP_TRANSMISSION) - mask |= SDHCI_CMD_INHIBIT_DATA; - - ret = sdhci_read32_poll_timeout(sdhci, SDHCI_PRESENT_STATE, state, - !(state & mask), 100 * USEC_PER_MSEC); - if (ret) { - pr_err("timeout while waiting for idle\n"); + ret = sdhci_wait_idle_data(&host->sdhci, cmd); + if (ret) return ret; - } sdhci_write32(sdhci, SDHCI_INT_STATUS, ~0U); @@ -146,29 +124,30 @@ int at91_sdhci_send_command(struct at91_sdhci *host, struct mci_cmd *cmd, sdhci_write32(sdhci, SDHCI_ARGUMENT, cmd->cmdarg); sdhci_write16(sdhci, SDHCI_COMMAND, command); - status = at91_sdhci_wait_for_done(host, mask); - if (status >= 0 && (status & (SDHCI_INT_ERROR | mask)) == mask) { - sdhci_read_response(sdhci, cmd); - sdhci_write32(sdhci, SDHCI_INT_STATUS, mask); - - if (data) - sdhci_transfer_data(sdhci, data); + status = sdhci_wait_for_done(&host->sdhci, mask); + if (status < 0) + goto error; - udelay(1000); + sdhci_read_response(sdhci, cmd); + sdhci_write32(sdhci, SDHCI_INT_STATUS, mask); - status = sdhci_read32(sdhci, SDHCI_INT_STATUS); - sdhci_write32(sdhci, SDHCI_INT_STATUS, ~0U); + if (data) + sdhci_transfer_data_pio(sdhci, data); - return 0; - } + udelay(1000); status = sdhci_read32(sdhci, SDHCI_INT_STATUS); sdhci_write32(sdhci, SDHCI_INT_STATUS, ~0U); + return 0; + +error: + sdhci_write32(sdhci, SDHCI_INT_STATUS, ~0U); + sdhci_reset(sdhci, SDHCI_RESET_CMD); sdhci_reset(sdhci, SDHCI_RESET_DATA); - return status & SDHCI_INT_TIMEOUT ? -ETIMEDOUT : -ECOMM; + return status; } static void at91_sdhci_set_power(struct at91_sdhci *host, unsigned vdd) @@ -206,26 +185,21 @@ static int at91_sdhci_set_clock(struct at91_sdhci *host, unsigned clock) struct sdhci *sdhci = &host->sdhci; unsigned clk = 0, clk_div; unsigned reg; - u32 present_mask, caps, caps_clk_mult; + u32 caps, caps_clk_mult; int ret; - present_mask = SDHCI_CMD_INHIBIT_CMD | SDHCI_CMD_INHIBIT_DATA; - ret = sdhci_read32_poll_timeout(sdhci, SDHCI_PRESENT_STATE, reg, - !(reg & present_mask), - 100 * USEC_PER_MSEC); - if (ret) { - pr_warn("Timeout waiting for CMD and DAT Inhibit bits\n"); + ret = sdhci_wait_idle_data(&host->sdhci, NULL); + if (ret) return ret; - } sdhci_write16(sdhci, SDHCI_CLOCK_CONTROL, 0); if (clock == 0) return 0; - caps = sdhci_read32(sdhci, AT91_SDHCI_CA1R); + caps = sdhci_read32(sdhci, SDHCI_CAPABILITIES_1); - caps_clk_mult = (caps & SDHCI_CLOCK_MUL_MASK) >> SDHCI_CLOCK_MUL_SHIFT; + caps_clk_mult = FIELD_GET(SDHCI_CLOCK_MUL_MASK, caps); if (caps_clk_mult) { for (clk_div = 1; clk_div <= 1024; clk_div++) { @@ -250,26 +224,26 @@ static int at91_sdhci_set_clock(struct at91_sdhci *host, unsigned clock) clk |= SDHCI_FREQ_SEL(clk_div); clk |= ((clk_div & SDHCI_DIV_HI_MASK) >> SDHCI_DIV_MASK_LEN) << SDHCI_DIVIDER_HI_SHIFT; - clk |= SDHCI_INTCLOCK_EN; + clk |= SDHCI_CLOCK_INT_EN; sdhci_write16(sdhci, SDHCI_CLOCK_CONTROL, clk); ret = sdhci_read32_poll_timeout(sdhci, SDHCI_CLOCK_CONTROL, clk, - clk & SDHCI_INTCLOCK_STABLE, + clk & SDHCI_CLOCK_INT_STABLE, 20 * USEC_PER_MSEC); if (ret) { - pr_warn("Timeout waiting for clock stable\n"); + dev_warn(host->dev, "Timeout waiting for clock stable\n"); return ret; } - clk |= SDHCI_SDCLOCK_EN; + clk |= SDHCI_CLOCK_CARD_EN; sdhci_write16(sdhci, SDHCI_CLOCK_CONTROL, clk); reg = sdhci_read8(sdhci, SDHCI_HOST_CONTROL); if (clock > 26000000) - reg |= SDHCI_HIGHSPEED_EN; + reg |= SDHCI_CTRL_HISPD; else - reg &= ~SDHCI_HIGHSPEED_EN; + reg &= ~SDHCI_CTRL_HISPD; sdhci_write8(sdhci, SDHCI_HOST_CONTROL, reg); @@ -285,15 +259,15 @@ static int at91_sdhci_set_bus_width(struct at91_sdhci *host, unsigned bus_width) switch(bus_width) { case MMC_BUS_WIDTH_8: - reg |= SDHCI_DATA_WIDTH_8BIT; + reg |= SDHCI_CTRL_8BITBUS; break; case MMC_BUS_WIDTH_4: - reg &= ~SDHCI_DATA_WIDTH_8BIT; - reg |= SDHCI_DATA_WIDTH_4BIT; + reg &= ~SDHCI_CTRL_8BITBUS; + reg |= SDHCI_CTRL_4BITBUS; break; default: - reg &= ~SDHCI_DATA_WIDTH_8BIT; - reg &= ~SDHCI_DATA_WIDTH_4BIT; + reg &= ~SDHCI_CTRL_8BITBUS; + reg &= ~SDHCI_CTRL_4BITBUS; } sdhci_write8(sdhci, SDHCI_HOST_CONTROL, reg); @@ -358,50 +332,14 @@ int at91_sdhci_init(struct at91_sdhci *host, u32 maxclk, } if (cal_always_on) { - sdhci_write32(sdhci, AT91_SDHCI_CALCR_ALWYSON | AT91_SDHCI_CALCR_EN, - AT91_SDHCI_CALCR); + sdhci_write32(sdhci, AT91_SDHCI_CALCR, + AT91_SDHCI_CALCR_ALWYSON | AT91_SDHCI_CALCR_EN); } return 0; } -static u32 at91_sdhci_read32(struct sdhci *sdhci, int reg) -{ - return readl(to_priv(sdhci)->base + reg); -} - -static void at91_sdhci_write32(struct sdhci *sdhci, int reg, u32 value) -{ - writel(value, to_priv(sdhci)->base + reg); -} - -static u16 at91_sdhci_read16(struct sdhci *sdhci, int reg) -{ - return readw(to_priv(sdhci)->base + reg); -} - -static void at91_sdhci_write16(struct sdhci *sdhci, int reg, u16 value) -{ - writew(value, to_priv(sdhci)->base + reg); -} - -static u8 at91_sdhci_read8(struct sdhci *sdhci, int reg) -{ - return readb(to_priv(sdhci)->base + reg); -} - -static void at91_sdhci_write8(struct sdhci *sdhci, int reg, u8 value) -{ - writeb(value, to_priv(sdhci)->base + reg); -} - void at91_sdhci_mmio_init(struct at91_sdhci *host, void __iomem *base) { - host->base = base; - host->sdhci.read8 = at91_sdhci_read8; - host->sdhci.read16 = at91_sdhci_read16; - host->sdhci.read32 = at91_sdhci_read32; - host->sdhci.write8 = at91_sdhci_write8; - host->sdhci.write16 = at91_sdhci_write16; - host->sdhci.write32 = at91_sdhci_write32; + host->sdhci.base = base; } |