sunxi: remove linux 4.9 support
[openwrt/staging/blogic.git] / target / linux / sunxi / patches-4.9 / 090-sunxi-mmc-from-4-13.patch
diff --git a/target/linux/sunxi/patches-4.9/090-sunxi-mmc-from-4-13.patch b/target/linux/sunxi/patches-4.9/090-sunxi-mmc-from-4-13.patch
deleted file mode 100644 (file)
index e64581f..0000000
+++ /dev/null
@@ -1,288 +0,0 @@
---- a/Documentation/devicetree/bindings/mmc/sunxi-mmc.txt
-+++ b/Documentation/devicetree/bindings/mmc/sunxi-mmc.txt
-@@ -13,6 +13,7 @@ Required properties:
-    * "allwinner,sun5i-a13-mmc"
-    * "allwinner,sun7i-a20-mmc"
-    * "allwinner,sun9i-a80-mmc"
-+   * "allwinner,sun50i-a64-emmc"
-    * "allwinner,sun50i-a64-mmc"
-  - reg : mmc controller base registers
-  - clocks : a list with 4 phandle + clock specifier pairs
---- a/drivers/mmc/host/sunxi-mmc.c
-+++ b/drivers/mmc/host/sunxi-mmc.c
-@@ -5,6 +5,7 @@
-  * (C) Copyright 2013-2014 O2S GmbH <www.o2s.ch>
-  * (C) Copyright 2013-2014 David Lanzend�rfer <david.lanzendoerfer@o2s.ch>
-  * (C) Copyright 2013-2014 Hans de Goede <hdegoede@redhat.com>
-+ * (C) Copyright 2017 Sootech SA
-  *
-  * This program is free software; you can redistribute it and/or
-  * modify it under the terms of the GNU General Public License as
-@@ -101,6 +102,7 @@
-       (SDXC_SOFT_RESET | SDXC_FIFO_RESET | SDXC_DMA_RESET)
- /* clock control bits */
-+#define SDXC_MASK_DATA0                       BIT(31)
- #define SDXC_CARD_CLOCK_ON            BIT(16)
- #define SDXC_LOW_POWER_ON             BIT(17)
-@@ -253,6 +255,11 @@ struct sunxi_mmc_cfg {
-       /* does the IP block support autocalibration? */
-       bool can_calibrate;
-+
-+      /* Does DATA0 needs to be masked while the clock is updated */
-+      bool mask_data0;
-+
-+      bool needs_new_timings;
- };
- struct sunxi_mmc_host {
-@@ -482,7 +489,7 @@ static void sunxi_mmc_dump_errinfo(struc
-                                     cmd->opcode == SD_IO_RW_DIRECT))
-               return;
--      dev_err(mmc_dev(host->mmc),
-+      dev_dbg(mmc_dev(host->mmc),
-               "smc %d err, cmd %d,%s%s%s%s%s%s%s%s%s%s !!\n",
-               host->mmc->index, cmd->opcode,
-               data ? (data->flags & MMC_DATA_WRITE ? " WR" : " RD") : "",
-@@ -654,11 +661,16 @@ static int sunxi_mmc_oclk_onoff(struct s
-       unsigned long expire = jiffies + msecs_to_jiffies(750);
-       u32 rval;
-+      dev_dbg(mmc_dev(host->mmc), "%sabling the clock\n",
-+              oclk_en ? "en" : "dis");
-+
-       rval = mmc_readl(host, REG_CLKCR);
--      rval &= ~(SDXC_CARD_CLOCK_ON | SDXC_LOW_POWER_ON);
-+      rval &= ~(SDXC_CARD_CLOCK_ON | SDXC_LOW_POWER_ON | SDXC_MASK_DATA0);
-       if (oclk_en)
-               rval |= SDXC_CARD_CLOCK_ON;
-+      if (host->cfg->mask_data0)
-+              rval |= SDXC_MASK_DATA0;
-       mmc_writel(host, REG_CLKCR, rval);
-@@ -678,46 +690,29 @@ static int sunxi_mmc_oclk_onoff(struct s
-               return -EIO;
-       }
-+      if (host->cfg->mask_data0) {
-+              rval = mmc_readl(host, REG_CLKCR);
-+              mmc_writel(host, REG_CLKCR, rval & ~SDXC_MASK_DATA0);
-+      }
-+
-       return 0;
- }
- static int sunxi_mmc_calibrate(struct sunxi_mmc_host *host, int reg_off)
- {
--      u32 reg = readl(host->reg_base + reg_off);
--      u32 delay;
--      unsigned long timeout;
--
-       if (!host->cfg->can_calibrate)
-               return 0;
--      reg &= ~(SDXC_CAL_DL_MASK << SDXC_CAL_DL_SW_SHIFT);
--      reg &= ~SDXC_CAL_DL_SW_EN;
--
--      writel(reg | SDXC_CAL_START, host->reg_base + reg_off);
--
--      dev_dbg(mmc_dev(host->mmc), "calibration started\n");
--
--      timeout = jiffies + HZ * SDXC_CAL_TIMEOUT;
--
--      while (!((reg = readl(host->reg_base + reg_off)) & SDXC_CAL_DONE)) {
--              if (time_before(jiffies, timeout))
--                      cpu_relax();
--              else {
--                      reg &= ~SDXC_CAL_START;
--                      writel(reg, host->reg_base + reg_off);
--
--                      return -ETIMEDOUT;
--              }
--      }
--
--      delay = (reg >> SDXC_CAL_DL_SHIFT) & SDXC_CAL_DL_MASK;
--
--      reg &= ~SDXC_CAL_START;
--      reg |= (delay << SDXC_CAL_DL_SW_SHIFT) | SDXC_CAL_DL_SW_EN;
--
--      writel(reg, host->reg_base + reg_off);
--
--      dev_dbg(mmc_dev(host->mmc), "calibration ended, reg is 0x%x\n", reg);
-+      /*
-+       * FIXME:
-+       * This is not clear how the calibration is supposed to work
-+       * yet. The best rate have been obtained by simply setting the
-+       * delay to 0, as Allwinner does in its BSP.
-+       *
-+       * The only mode that doesn't have such a delay is HS400, that
-+       * is in itself a TODO.
-+       */
-+      writel(SDXC_CAL_DL_SW_EN, host->reg_base + reg_off);
-       return 0;
- }
-@@ -745,6 +740,7 @@ static int sunxi_mmc_clk_set_phase(struc
-                       index = SDXC_CLK_50M_DDR;
-               }
-       } else {
-+              dev_dbg(mmc_dev(host->mmc), "Invalid clock... returning\n");
-               return -EINVAL;
-       }
-@@ -757,10 +753,21 @@ static int sunxi_mmc_clk_set_phase(struc
- static int sunxi_mmc_clk_set_rate(struct sunxi_mmc_host *host,
-                                 struct mmc_ios *ios)
- {
-+      struct mmc_host *mmc = host->mmc;
-       long rate;
-       u32 rval, clock = ios->clock;
-       int ret;
-+      ret = sunxi_mmc_oclk_onoff(host, 0);
-+      if (ret)
-+              return ret;
-+
-+      /* Our clock is gated now */
-+      mmc->actual_clock = 0;
-+
-+      if (!ios->clock)
-+              return 0;
-+
-       /* 8 bit DDR requires a higher module clock */
-       if (ios->timing == MMC_TIMING_MMC_DDR52 &&
-           ios->bus_width == MMC_BUS_WIDTH_8)
-@@ -768,25 +775,21 @@ static int sunxi_mmc_clk_set_rate(struct
-       rate = clk_round_rate(host->clk_mmc, clock);
-       if (rate < 0) {
--              dev_err(mmc_dev(host->mmc), "error rounding clk to %d: %ld\n",
-+              dev_err(mmc_dev(mmc), "error rounding clk to %d: %ld\n",
-                       clock, rate);
-               return rate;
-       }
--      dev_dbg(mmc_dev(host->mmc), "setting clk to %d, rounded %ld\n",
-+      dev_dbg(mmc_dev(mmc), "setting clk to %d, rounded %ld\n",
-               clock, rate);
-       /* setting clock rate */
-       ret = clk_set_rate(host->clk_mmc, rate);
-       if (ret) {
--              dev_err(mmc_dev(host->mmc), "error setting clk to %ld: %d\n",
-+              dev_err(mmc_dev(mmc), "error setting clk to %ld: %d\n",
-                       rate, ret);
-               return ret;
-       }
--      ret = sunxi_mmc_oclk_onoff(host, 0);
--      if (ret)
--              return ret;
--
-       /* clear internal divider */
-       rval = mmc_readl(host, REG_CLKCR);
-       rval &= ~0xff;
-@@ -798,6 +801,13 @@ static int sunxi_mmc_clk_set_rate(struct
-       }
-       mmc_writel(host, REG_CLKCR, rval);
-+      if (host->cfg->needs_new_timings) {
-+              /* Don't touch the delay bits */
-+              rval = mmc_readl(host, REG_SD_NTSR);
-+              rval |= SDXC_2X_TIMING_MODE;
-+              mmc_writel(host, REG_SD_NTSR, rval);
-+      }
-+
-       ret = sunxi_mmc_clk_set_phase(host, ios, rate);
-       if (ret)
-               return ret;
-@@ -806,9 +816,22 @@ static int sunxi_mmc_clk_set_rate(struct
-       if (ret)
-               return ret;
--      /* TODO: enable calibrate on sdc2 SDXC_REG_DS_DL_REG of A64 */
-+      /*
-+       * FIXME:
-+       *
-+       * In HS400 we'll also need to calibrate the data strobe
-+       * signal. This should only happen on the MMC2 controller (at
-+       * least on the A64).
-+       */
-+
-+      ret = sunxi_mmc_oclk_onoff(host, 1);
-+      if (ret)
-+              return ret;
--      return sunxi_mmc_oclk_onoff(host, 1);
-+      /* And we just enabled our clock back */
-+      mmc->actual_clock = rate;
-+
-+      return 0;
- }
- static void sunxi_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
-@@ -822,10 +845,13 @@ static void sunxi_mmc_set_ios(struct mmc
-               break;
-       case MMC_POWER_UP:
--              host->ferror = mmc_regulator_set_ocr(mmc, mmc->supply.vmmc,
--                                                   ios->vdd);
--              if (host->ferror)
--                      return;
-+              if (!IS_ERR(mmc->supply.vmmc)) {
-+                      host->ferror = mmc_regulator_set_ocr(mmc,
-+                                                           mmc->supply.vmmc,
-+                                                           ios->vdd);
-+                      if (host->ferror)
-+                              return;
-+              }
-               if (!IS_ERR(mmc->supply.vqmmc)) {
-                       host->ferror = regulator_enable(mmc->supply.vqmmc);
-@@ -847,7 +873,9 @@ static void sunxi_mmc_set_ios(struct mmc
-       case MMC_POWER_OFF:
-               dev_dbg(mmc_dev(mmc), "power off!\n");
-               sunxi_mmc_reset_host(host);
--              mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, 0);
-+              if (!IS_ERR(mmc->supply.vmmc))
-+                      mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, 0);
-+
-               if (!IS_ERR(mmc->supply.vqmmc) && host->vqmmc_enabled)
-                       regulator_disable(mmc->supply.vqmmc);
-               host->vqmmc_enabled = false;
-@@ -877,7 +905,7 @@ static void sunxi_mmc_set_ios(struct mmc
-       mmc_writel(host, REG_GCTRL, rval);
-       /* set up clock */
--      if (ios->clock && ios->power_mode) {
-+      if (ios->power_mode) {
-               host->ferror = sunxi_mmc_clk_set_rate(host, ios);
-               /* Android code had a usleep_range(50000, 55000); here */
-       }
-@@ -1084,6 +1112,14 @@ static const struct sunxi_mmc_cfg sun50i
-       .idma_des_size_bits = 16,
-       .clk_delays = NULL,
-       .can_calibrate = true,
-+      .mask_data0 = true,
-+      .needs_new_timings = true,
-+};
-+
-+static const struct sunxi_mmc_cfg sun50i_a64_emmc_cfg = {
-+      .idma_des_size_bits = 13,
-+      .clk_delays = NULL,
-+      .can_calibrate = true,
- };
- static const struct of_device_id sunxi_mmc_of_match[] = {
-@@ -1092,6 +1128,7 @@ static const struct of_device_id sunxi_m
-       { .compatible = "allwinner,sun7i-a20-mmc", .data = &sun7i_a20_cfg },
-       { .compatible = "allwinner,sun9i-a80-mmc", .data = &sun9i_a80_cfg },
-       { .compatible = "allwinner,sun50i-a64-mmc", .data = &sun50i_a64_cfg },
-+      { .compatible = "allwinner,sun50i-a64-emmc", .data = &sun50i_a64_emmc_cfg },
-       { /* sentinel */ }
- };
- MODULE_DEVICE_TABLE(of, sunxi_mmc_of_match);