X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=drivers%2Fmmc%2Fsunxi_mmc.c;h=fd3fc2af40a05b1a418981b5c8e8d05017cde3d0;hb=0675f992dbf4a785a05a1baf149c2bce6aa5fe90;hp=623498187ef0255e6fd5a647819a7bdf4477f8e3;hpb=4608f37918e5d93d6b2b6909b325a5e6fb0a2346;p=u-boot diff --git a/drivers/mmc/sunxi_mmc.c b/drivers/mmc/sunxi_mmc.c index 623498187e..fd3fc2af40 100644 --- a/drivers/mmc/sunxi_mmc.c +++ b/drivers/mmc/sunxi_mmc.c @@ -9,6 +9,7 @@ */ #include +#include #include #include #include @@ -37,7 +38,7 @@ static int sunxi_mmc_getcd_gpio(int sdc_no) case 2: return sunxi_name_to_gpio(CONFIG_MMC2_CD_PIN); case 3: return sunxi_name_to_gpio(CONFIG_MMC3_CD_PIN); } - return -1; + return -EINVAL; } static int mmc_resource_init(int sdc_no) @@ -72,10 +73,12 @@ static int mmc_resource_init(int sdc_no) mmchost->mmc_no = sdc_no; cd_pin = sunxi_mmc_getcd_gpio(sdc_no); - if (cd_pin != -1) { + if (cd_pin >= 0) { ret = gpio_request(cd_pin, "mmc_cd"); - if (!ret) + if (!ret) { + sunxi_gpio_set_pull(cd_pin, SUNXI_GPIO_PULL_UP); ret = gpio_direction_input(cd_pin); + } } return ret; @@ -89,8 +92,13 @@ static int mmc_set_mod_clk(struct sunxi_mmc_host *mmchost, unsigned int hz) pll = CCM_MMC_CTRL_OSCM24; pll_hz = 24000000; } else { +#ifdef CONFIG_MACH_SUN9I + pll = CCM_MMC_CTRL_PLL_PERIPH0; + pll_hz = clock_get_pll4_periph0(); +#else pll = CCM_MMC_CTRL_PLL6; pll_hz = clock_get_pll6(); +#endif } div = pll_hz / hz; @@ -112,17 +120,27 @@ static int mmc_set_mod_clk(struct sunxi_mmc_host *mmchost, unsigned int hz) /* determine delays */ if (hz <= 400000) { oclk_dly = 0; - sclk_dly = 7; + sclk_dly = 0; } else if (hz <= 25000000) { oclk_dly = 0; sclk_dly = 5; +#ifdef CONFIG_MACH_SUN9I } else if (hz <= 50000000) { - oclk_dly = 3; - sclk_dly = 5; + oclk_dly = 5; + sclk_dly = 4; } else { /* hz > 50000000 */ oclk_dly = 2; sclk_dly = 4; +#else + } else if (hz <= 50000000) { + oclk_dly = 3; + sclk_dly = 4; + } else { + /* hz > 50000000 */ + oclk_dly = 1; + sclk_dly = 4; +#endif } writel(CCM_MMC_CTRL_ENABLE | pll | CCM_MMC_CTRL_SCLK_DLY(sclk_dly) | @@ -146,10 +164,15 @@ static int mmc_clk_io_on(int sdc_no) /* config ahb clock */ setbits_le32(&ccm->ahb_gate0, 1 << AHB_GATE_OFFSET_MMC(sdc_no)); -#if defined(CONFIG_MACH_SUN6I) || defined(CONFIG_MACH_SUN8I) +#ifdef CONFIG_SUNXI_GEN_SUN6I /* unassert reset */ setbits_le32(&ccm->ahb_reset0_cfg, 1 << AHB_RESET_OFFSET_MMC(sdc_no)); #endif +#if defined(CONFIG_MACH_SUN9I) + /* sun9i has a mmc-common module, also set the gate and reset there */ + writel(SUNXI_MMC_COMMON_CLK_GATE | SUNXI_MMC_COMMON_RESET, + SUNXI_MMC_COMMON_BASE + 4 * sdc_no); +#endif return mmc_set_mod_clk(mmchost, 24000000); } @@ -204,7 +227,7 @@ static int mmc_config_clock(struct mmc *mmc) return 0; } -static void mmc_set_ios(struct mmc *mmc) +static int sunxi_mmc_set_ios(struct mmc *mmc) { struct sunxi_mmc_host *mmchost = mmc->priv; @@ -214,7 +237,7 @@ static void mmc_set_ios(struct mmc *mmc) /* Change clock first */ if (mmc->clock && mmc_config_clock(mmc) != 0) { mmchost->fatal_err = 1; - return; + return -EINVAL; } /* Change bus width */ @@ -224,9 +247,11 @@ static void mmc_set_ios(struct mmc *mmc) writel(0x1, &mmchost->reg->width); else writel(0x0, &mmchost->reg->width); + + return 0; } -static int mmc_core_init(struct mmc *mmc) +static int sunxi_mmc_core_init(struct mmc *mmc) { struct sunxi_mmc_host *mmchost = mmc->priv; @@ -244,18 +269,20 @@ static int mmc_trans_data_by_cpu(struct mmc *mmc, struct mmc_data *data) const uint32_t status_bit = reading ? SUNXI_MMC_STATUS_FIFO_EMPTY : SUNXI_MMC_STATUS_FIFO_FULL; unsigned i; - unsigned byte_cnt = data->blocksize * data->blocks; - unsigned timeout_msecs = 2000; unsigned *buff = (unsigned int *)(reading ? data->dest : data->src); + unsigned byte_cnt = data->blocksize * data->blocks; + unsigned timeout_usecs = (byte_cnt >> 8) * 1000; + if (timeout_usecs < 2000000) + timeout_usecs = 2000000; /* Always read / write data through the CPU */ setbits_le32(&mmchost->reg->gctrl, SUNXI_MMC_GCTRL_ACCESS_BY_AHB); for (i = 0; i < (byte_cnt >> 2); i++) { while (readl(&mmchost->reg->status) & status_bit) { - if (!timeout_msecs--) + if (!timeout_usecs--) return -1; - udelay(1000); + udelay(1); } if (reading) @@ -279,7 +306,7 @@ static int mmc_rint_wait(struct mmc *mmc, unsigned int timeout_msecs, (status & SUNXI_MMC_RINT_INTERRUPT_ERROR_BIT)) { debug("%s timeout %x\n", what, status & SUNXI_MMC_RINT_INTERRUPT_ERROR_BIT); - return TIMEOUT; + return -ETIMEDOUT; } udelay(1000); } while (!(status & done_bit)); @@ -287,8 +314,8 @@ static int mmc_rint_wait(struct mmc *mmc, unsigned int timeout_msecs, return 0; } -static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, - struct mmc_data *data) +static int sunxi_mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, + struct mmc_data *data) { struct sunxi_mmc_host *mmchost = mmc->priv; unsigned int cmdval = SUNXI_MMC_CMD_START; @@ -314,7 +341,7 @@ static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, cmdval |= SUNXI_MMC_CMD_CHK_RESPONSE_CRC; if (data) { - if ((u32) data->dest & 0x3) { + if ((u32)(long)data->dest & 0x3) { error = -1; goto out; } @@ -350,12 +377,12 @@ static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, if (ret) { error = readl(&mmchost->reg->rint) & \ SUNXI_MMC_RINT_INTERRUPT_ERROR_BIT; - error = TIMEOUT; + error = -ETIMEDOUT; goto out; } } - error = mmc_rint_wait(mmc, 0xfffff, SUNXI_MMC_RINT_COMMAND_DONE, "cmd"); + error = mmc_rint_wait(mmc, 1000, SUNXI_MMC_RINT_COMMAND_DONE, "cmd"); if (error) goto out; @@ -377,7 +404,7 @@ static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, status = readl(&mmchost->reg->status); if (!timeout_msecs--) { debug("busy timeout\n"); - error = TIMEOUT; + error = -ETIMEDOUT; goto out; } udelay(1000); @@ -414,16 +441,16 @@ static int sunxi_mmc_getcd(struct mmc *mmc) int cd_pin; cd_pin = sunxi_mmc_getcd_gpio(mmchost->mmc_no); - if (cd_pin == -1) + if (cd_pin < 0) return 1; return !gpio_get_value(cd_pin); } static const struct mmc_ops sunxi_mmc_ops = { - .send_cmd = mmc_send_cmd, - .set_ios = mmc_set_ios, - .init = mmc_core_init, + .send_cmd = sunxi_mmc_send_cmd, + .set_ios = sunxi_mmc_set_ios, + .init = sunxi_mmc_core_init, .getcd = sunxi_mmc_getcd, }; @@ -438,10 +465,11 @@ struct mmc *sunxi_mmc_init(int sdc_no) cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34; cfg->host_caps = MMC_MODE_4BIT; - cfg->host_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS; -#if defined(CONFIG_MACH_SUN6I) || defined(CONFIG_MACH_SUN7I) || defined(CONFIG_MACH_SUN8I) - cfg->host_caps |= MMC_MODE_HC; +#if defined(CONFIG_MACH_SUN50I) || defined(CONFIG_MACH_SUN8I) + if (sdc_no == 2) + cfg->host_caps = MMC_MODE_8BIT; #endif + cfg->host_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS; cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT; cfg->f_min = 400000;