You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
574 lines
18 KiB
574 lines
18 KiB
diff -u -N -r stblinux-3.14-1.8/drivers/clk/clk.c stblinux-3.14-1.10-git/drivers/clk/clk.c
|
|
--- stblinux-3.14-1.8/drivers/clk/clk.c 2015-07-28 23:57:38.000000000 +0000
|
|
+++ stblinux-3.14-1.10-git/drivers/clk/clk.c 2019-02-10 22:05:52.950336124 +0000
|
|
@@ -929,6 +929,9 @@
|
|
if (clk->prepare_count == 0) {
|
|
if (clk->flags & CLK_IS_SW)
|
|
for (i = 0; i < clk->num_parents; i++) {
|
|
+ if (!clk->parents[i])
|
|
+ clk->parents[i] =
|
|
+ __clk_lookup(clk->parent_names[i]);
|
|
ret = __clk_prepare(clk->parents[i]);
|
|
if (ret) {
|
|
for (j = i - 1; j >= 0; j--)
|
|
@@ -1042,6 +1045,9 @@
|
|
if (clk->enable_count == 0) {
|
|
if (clk->flags & CLK_IS_SW)
|
|
for (i = 0; i < clk->num_parents && !ret; i++) {
|
|
+ if (!clk->parents[i])
|
|
+ clk->parents[i] =
|
|
+ __clk_lookup(clk->parent_names[i]);
|
|
ret = __clk_enable(clk->parents[i]);
|
|
if (ret) {
|
|
for (j = i - 1; j >= 0; j--)
|
|
diff -u -N -r stblinux-3.14-1.8/drivers/mmc/core/mmc.c stblinux-3.14-1.10-git/drivers/mmc/core/mmc.c
|
|
--- stblinux-3.14-1.8/drivers/mmc/core/mmc.c 2015-07-28 23:57:39.000000000 +0000
|
|
+++ stblinux-3.14-1.10-git/drivers/mmc/core/mmc.c 2019-02-10 22:05:52.950336124 +0000
|
|
@@ -293,13 +293,12 @@
|
|
}
|
|
}
|
|
|
|
+ /*
|
|
+ * The EXT_CSD format is meant to be forward compatible. As long
|
|
+ * as CSD_STRUCTURE does not change, all values for EXT_CSD_REV
|
|
+ * are authorized, see JEDEC JESD84-B50 section B.8.
|
|
+ */
|
|
card->ext_csd.rev = ext_csd[EXT_CSD_REV];
|
|
- if (card->ext_csd.rev > 7) {
|
|
- pr_err("%s: unrecognised EXT_CSD revision %d\n",
|
|
- mmc_hostname(card->host), card->ext_csd.rev);
|
|
- err = -EINVAL;
|
|
- goto out;
|
|
- }
|
|
|
|
card->ext_csd.raw_sectors[0] = ext_csd[EXT_CSD_SEC_CNT + 0];
|
|
card->ext_csd.raw_sectors[1] = ext_csd[EXT_CSD_SEC_CNT + 1];
|
|
diff -u -N -r stblinux-3.14-1.8/drivers/mmc/core/sd.c stblinux-3.14-1.10-git/drivers/mmc/core/sd.c
|
|
--- stblinux-3.14-1.8/drivers/mmc/core/sd.c 2015-07-28 23:57:39.000000000 +0000
|
|
+++ stblinux-3.14-1.10-git/drivers/mmc/core/sd.c 2019-02-10 22:05:52.950336124 +0000
|
|
@@ -389,18 +389,9 @@
|
|
{
|
|
int host_drv_type = SD_DRIVER_TYPE_B;
|
|
int card_drv_type = SD_DRIVER_TYPE_B;
|
|
- int drive_strength;
|
|
+ int drive_strength, drv_type;
|
|
int err;
|
|
|
|
- /*
|
|
- * If the host doesn't support any of the Driver Types A,C or D,
|
|
- * or there is no board specific handler then default Driver
|
|
- * Type B is used.
|
|
- */
|
|
- if (!(card->host->caps & (MMC_CAP_DRIVER_TYPE_A | MMC_CAP_DRIVER_TYPE_C
|
|
- | MMC_CAP_DRIVER_TYPE_D)))
|
|
- return 0;
|
|
-
|
|
if (!card->host->ops->select_drive_strength)
|
|
return 0;
|
|
|
|
@@ -429,22 +420,24 @@
|
|
* return what is possible given the options
|
|
*/
|
|
mmc_host_clk_hold(card->host);
|
|
- drive_strength = card->host->ops->select_drive_strength(
|
|
+ drive_strength = card->host->ops->select_drive_strength(card,
|
|
card->sw_caps.uhs_max_dtr,
|
|
- host_drv_type, card_drv_type);
|
|
+ host_drv_type, card_drv_type, &drv_type);
|
|
mmc_host_clk_release(card->host);
|
|
|
|
- err = mmc_sd_switch(card, 1, 2, drive_strength, status);
|
|
- if (err)
|
|
- return err;
|
|
-
|
|
- if ((status[15] & 0xF) != drive_strength) {
|
|
- pr_warning("%s: Problem setting drive strength!\n",
|
|
- mmc_hostname(card->host));
|
|
- return 0;
|
|
+ if (drive_strength) {
|
|
+ err = mmc_sd_switch(card, 1, 2, drive_strength, status);
|
|
+ if (err)
|
|
+ return err;
|
|
+ if ((status[15] & 0xF) != drive_strength) {
|
|
+ pr_warn("%s: Problem setting drive strength!\n",
|
|
+ mmc_hostname(card->host));
|
|
+ return 0;
|
|
+ }
|
|
}
|
|
|
|
- mmc_set_driver_type(card->host, drive_strength);
|
|
+ if (drv_type)
|
|
+ mmc_set_driver_type(card->host, drv_type);
|
|
|
|
return 0;
|
|
}
|
|
diff -u -N -r stblinux-3.14-1.8/drivers/mmc/core/sdio.c stblinux-3.14-1.10-git/drivers/mmc/core/sdio.c
|
|
--- stblinux-3.14-1.8/drivers/mmc/core/sdio.c 2015-07-28 23:57:39.000000000 +0000
|
|
+++ stblinux-3.14-1.10-git/drivers/mmc/core/sdio.c 2019-02-10 22:05:52.950336124 +0000
|
|
@@ -401,21 +401,10 @@
|
|
{
|
|
int host_drv_type = SD_DRIVER_TYPE_B;
|
|
int card_drv_type = SD_DRIVER_TYPE_B;
|
|
- int drive_strength;
|
|
+ int drive_strength, drv_type;
|
|
unsigned char card_strength;
|
|
int err;
|
|
|
|
- /*
|
|
- * If the host doesn't support any of the Driver Types A,C or D,
|
|
- * or there is no board specific handler then default Driver
|
|
- * Type B is used.
|
|
- */
|
|
- if (!(card->host->caps &
|
|
- (MMC_CAP_DRIVER_TYPE_A |
|
|
- MMC_CAP_DRIVER_TYPE_C |
|
|
- MMC_CAP_DRIVER_TYPE_D)))
|
|
- return;
|
|
-
|
|
if (!card->host->ops->select_drive_strength)
|
|
return;
|
|
|
|
@@ -443,25 +432,29 @@
|
|
* information and let the hardware specific code
|
|
* return what is possible given the options
|
|
*/
|
|
- drive_strength = card->host->ops->select_drive_strength(
|
|
+ drive_strength = card->host->ops->select_drive_strength(card,
|
|
card->sw_caps.uhs_max_dtr,
|
|
- host_drv_type, card_drv_type);
|
|
-
|
|
- /* if error just use default for drive strength B */
|
|
- err = mmc_io_rw_direct(card, 0, 0, SDIO_CCCR_DRIVE_STRENGTH, 0,
|
|
- &card_strength);
|
|
- if (err)
|
|
- return;
|
|
-
|
|
- card_strength &= ~(SDIO_DRIVE_DTSx_MASK<<SDIO_DRIVE_DTSx_SHIFT);
|
|
- card_strength |= host_drive_to_sdio_drive(drive_strength);
|
|
+ host_drv_type, card_drv_type, &drv_type);
|
|
|
|
- err = mmc_io_rw_direct(card, 1, 0, SDIO_CCCR_DRIVE_STRENGTH,
|
|
- card_strength, NULL);
|
|
+ if (drive_strength) {
|
|
+ /* if error just use default for drive strength B */
|
|
+ err = mmc_io_rw_direct(card, 0, 0, SDIO_CCCR_DRIVE_STRENGTH, 0,
|
|
+ &card_strength);
|
|
+ if (err)
|
|
+ return;
|
|
+
|
|
+ card_strength &= ~(SDIO_DRIVE_DTSx_MASK<<SDIO_DRIVE_DTSx_SHIFT);
|
|
+ card_strength |= host_drive_to_sdio_drive(drive_strength);
|
|
+
|
|
+ /* if error default to drive strength B */
|
|
+ err = mmc_io_rw_direct(card, 1, 0, SDIO_CCCR_DRIVE_STRENGTH,
|
|
+ card_strength, NULL);
|
|
+ if (err)
|
|
+ return;
|
|
+ }
|
|
|
|
- /* if error default to drive strength B */
|
|
- if (!err)
|
|
- mmc_set_driver_type(card->host, drive_strength);
|
|
+ if (drv_type)
|
|
+ mmc_set_driver_type(card->host, drv_type);
|
|
}
|
|
|
|
|
|
diff -u -N -r stblinux-3.14-1.8/drivers/mmc/host/sdhci-brcmstb.c stblinux-3.14-1.10-git/drivers/mmc/host/sdhci-brcmstb.c
|
|
--- stblinux-3.14-1.8/drivers/mmc/host/sdhci-brcmstb.c 2015-07-28 23:57:39.000000000 +0000
|
|
+++ stblinux-3.14-1.10-git/drivers/mmc/host/sdhci-brcmstb.c 2019-02-10 22:06:28.132824631 +0000
|
|
@@ -31,6 +31,18 @@
|
|
#define SDIO_CFG_REG(x, y) (x + BCHP_SDIO_0_CFG_##y - \
|
|
BCHP_SDIO_0_CFG_REG_START)
|
|
|
|
+struct sdhci_brcmstb_priv {
|
|
+ void __iomem *cfg_regs;
|
|
+ int host_driver_type;
|
|
+ int host_hs_driver_type;
|
|
+ int card_driver_type;
|
|
+};
|
|
+
|
|
+#define MASK_OFF_DRV (SDHCI_PRESET_SDCLK_FREQ_MASK | \
|
|
+ SDHCI_PRESET_CLKGEN_SEL_MASK)
|
|
+
|
|
+static char *strength_type_to_string[] = {"B", "A", "C", "D"};
|
|
+
|
|
#if defined(CONFIG_BCM74371A0)
|
|
/*
|
|
* HW7445-1183
|
|
@@ -47,27 +59,128 @@
|
|
writeb(val, host->ioaddr + reg);
|
|
}
|
|
|
|
+/* We don't support drive strength override on chips that use the
|
|
+ * old version of the SDIO core.
|
|
+ */
|
|
+static void set_host_driver_strength_overrides(
|
|
+ struct sdhci_host *host,
|
|
+ struct sdhci_brcmstb_priv *priv)
|
|
+{
|
|
+}
|
|
+
|
|
+#else /* CONFIG_BCM74371A0 */
|
|
+
|
|
+static void set_host_driver_strength_overrides(
|
|
+ struct sdhci_host *host,
|
|
+ struct sdhci_brcmstb_priv *priv)
|
|
+{
|
|
+ u16 strength;
|
|
+ u16 sdr25;
|
|
+ u16 sdr50;
|
|
+ u16 ddr50;
|
|
+ u16 sdr104;
|
|
+ u32 val;
|
|
+ u32 cfg_base = (u32)priv->cfg_regs;
|
|
+
|
|
+ if (priv->host_driver_type) {
|
|
+ dev_info(mmc_dev(host->mmc),
|
|
+ "Changing UHS Host Driver TYPE Presets to TYPE %s\n",
|
|
+ strength_type_to_string[priv->host_driver_type]);
|
|
+ strength = (u16)priv->host_driver_type << 11;
|
|
+ sdr25 = sdhci_readw(host,
|
|
+ SDHCI_PRESET_FOR_SDR25) & MASK_OFF_DRV;
|
|
+ sdr50 = sdhci_readw(host,
|
|
+ SDHCI_PRESET_FOR_SDR50) & MASK_OFF_DRV;
|
|
+ ddr50 = sdhci_readw(host,
|
|
+ SDHCI_PRESET_FOR_DDR50) & MASK_OFF_DRV;
|
|
+ sdr104 = sdhci_readw(host,
|
|
+ SDHCI_PRESET_FOR_SDR104) & MASK_OFF_DRV;
|
|
+ val = (sdr25 | strength);
|
|
+ val |= ((u32)(sdr50 | strength)) << 16;
|
|
+ val |= 0x80000000;
|
|
+ DEV_WR(SDIO_CFG_REG(cfg_base, PRESET3), val);
|
|
+ val = (sdr104 | strength);
|
|
+ val |= ((u32)(ddr50 | strength)) << 16;
|
|
+ val |= 0x80000000;
|
|
+ DEV_WR(SDIO_CFG_REG(cfg_base, PRESET4), val);
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * The Host Controller Specification states that the driver
|
|
+ * strength setting is only valid for UHS modes, but our
|
|
+ * host controller allows this setting to be used for HS modes
|
|
+ * as well.
|
|
+ */
|
|
+ if (priv->host_hs_driver_type) {
|
|
+ u16 sdr12;
|
|
+ u16 hs;
|
|
+
|
|
+ dev_info(mmc_dev(host->mmc),
|
|
+ "Changing HS Host Driver TYPE Presets to TYPE %s\n",
|
|
+ strength_type_to_string[priv->host_hs_driver_type]);
|
|
+ strength = (u16)priv->host_hs_driver_type << 11;
|
|
+ sdr12 = sdhci_readw(host, SDHCI_PRESET_FOR_SDR12) &
|
|
+ MASK_OFF_DRV;
|
|
+ hs = sdhci_readw(host, SDHCI_PRESET_FOR_HS) & MASK_OFF_DRV;
|
|
+ val = (hs | strength);
|
|
+ val |= ((u32)(sdr12 | strength)) << 16;
|
|
+ val |= 0x80000000;
|
|
+ DEV_WR(SDIO_CFG_REG(cfg_base, PRESET2), val);
|
|
+ }
|
|
+}
|
|
+#endif /* CONFIG_BCM74371A0 */
|
|
+
|
|
+static int select_one_drive_strength(struct sdhci_host *host, int supported,
|
|
+ int requested, char *type)
|
|
+{
|
|
+ char strength_ok_msg[] = "Changing %s Driver to TYPE %s\n";
|
|
+ char strength_err_msg[] =
|
|
+ "Request to change %s Driver to TYPE %s not supported by %s\n";
|
|
+ if (supported & (1 << requested)) {
|
|
+ if (requested)
|
|
+ dev_info(mmc_dev(host->mmc), strength_ok_msg, type,
|
|
+ strength_type_to_string[requested], type);
|
|
+ return requested;
|
|
+ } else {
|
|
+ dev_warn(mmc_dev(host->mmc), strength_err_msg, type,
|
|
+ strength_type_to_string[requested], type);
|
|
+ return 0;
|
|
+ }
|
|
+}
|
|
+
|
|
+static int sdhci_brcmstb_select_drive_strength(struct sdhci_host *host,
|
|
+ struct mmc_card *card,
|
|
+ unsigned int max_dtr, int host_drv,
|
|
+ int card_drv, int *drv_type)
|
|
+{
|
|
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
|
|
+ struct sdhci_brcmstb_priv *priv = sdhci_pltfm_priv(pltfm_host);
|
|
+
|
|
+ *drv_type = select_one_drive_strength(host, host_drv,
|
|
+ priv->host_driver_type, "Host");
|
|
+ return select_one_drive_strength(host, card_drv,
|
|
+ priv->card_driver_type, "Card");
|
|
+}
|
|
+
|
|
static struct sdhci_ops sdhci_brcmstb_ops = {
|
|
- .write_b = sdhci_brcmstb_writeb,
|
|
+ .select_drive_strength = sdhci_brcmstb_select_drive_strength,
|
|
};
|
|
-#endif
|
|
|
|
static struct sdhci_pltfm_data sdhci_brcmstb_pdata = {
|
|
};
|
|
|
|
#if defined(CONFIG_BCM3390A0) || defined(CONFIG_BCM7145B0) || \
|
|
defined(CONFIG_BCM7250B0) || defined(CONFIG_BCM7364A0) || \
|
|
- defined(CONFIG_BCM7439B0) || defined(CONFIG_BCM7445D0)
|
|
-static int sdhci_override_caps(struct platform_device *pdev,
|
|
- uint32_t cap0_setbits,
|
|
- uint32_t cap0_clearbits,
|
|
- uint32_t cap1_setbits,
|
|
- uint32_t cap1_clearbits)
|
|
+ defined(CONFIG_BCM7445D0)
|
|
+static void sdhci_override_caps(struct sdhci_host *host,
|
|
+ struct sdhci_brcmstb_priv *priv,
|
|
+ uint32_t cap0_setbits,
|
|
+ uint32_t cap0_clearbits,
|
|
+ uint32_t cap1_setbits,
|
|
+ uint32_t cap1_clearbits)
|
|
{
|
|
uint32_t val;
|
|
- struct resource *iomem;
|
|
- uintptr_t cfg_base;
|
|
- struct sdhci_host *host = platform_get_drvdata(pdev);
|
|
+ void *cfg_base = priv->cfg_regs;
|
|
|
|
/*
|
|
* The CAP's override bits in the CFG registers default to all
|
|
@@ -75,32 +188,33 @@
|
|
* CAPS registers and then modify the requested bits and write
|
|
* them to the override CFG registers.
|
|
*/
|
|
- iomem = platform_get_resource(pdev, IORESOURCE_MEM, 1);
|
|
- if (!iomem)
|
|
- return -EINVAL;
|
|
- cfg_base = iomem->start;
|
|
val = sdhci_readl(host, SDHCI_CAPABILITIES);
|
|
val &= ~cap0_clearbits;
|
|
val |= cap0_setbits;
|
|
- BDEV_WR(SDIO_CFG_REG(cfg_base, CAP_REG0), val);
|
|
+ DEV_WR(SDIO_CFG_REG(cfg_base, CAP_REG0), val);
|
|
val = sdhci_readl(host, SDHCI_CAPABILITIES_1);
|
|
val &= ~cap1_clearbits;
|
|
val |= cap1_setbits;
|
|
- BDEV_WR(SDIO_CFG_REG(cfg_base, CAP_REG1), val);
|
|
- BDEV_WR(SDIO_CFG_REG(cfg_base, CAP_REG_OVERRIDE),
|
|
+ DEV_WR(SDIO_CFG_REG(cfg_base, CAP_REG1), val);
|
|
+ DEV_WR(SDIO_CFG_REG(cfg_base, CAP_REG_OVERRIDE),
|
|
BCHP_SDIO_0_CFG_CAP_REG_OVERRIDE_CAP_REG_OVERRIDE_MASK);
|
|
- return 0;
|
|
}
|
|
|
|
-static int sdhci_fix_caps(struct platform_device *pdev)
|
|
+static void sdhci_fix_caps(struct sdhci_host *host,
|
|
+ struct sdhci_brcmstb_priv *priv)
|
|
{
|
|
+#if defined(CONFIG_BCM7445D0)
|
|
+ /* Fixed for E0 and above */
|
|
+ if (BRCM_CHIP_REV() >= 0x40)
|
|
+ return 0;
|
|
+#endif
|
|
/* Disable SDR50 support because tuning is broken. */
|
|
- return sdhci_override_caps(pdev, 0, 0, 0, SDHCI_SUPPORT_SDR50);
|
|
+ sdhci_override_caps(host, priv, 0, 0, 0, SDHCI_SUPPORT_SDR50);
|
|
}
|
|
#else
|
|
-static int sdhci_fix_caps(struct platform_device *pdev)
|
|
+static void sdhci_fix_caps(struct sdhci_host *host,
|
|
+ struct sdhci_brcmstb_priv *priv)
|
|
{
|
|
- return 0;
|
|
}
|
|
#endif
|
|
|
|
@@ -123,11 +237,14 @@
|
|
{
|
|
struct sdhci_host *host = dev_get_drvdata(dev);
|
|
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
|
|
+ struct sdhci_brcmstb_priv *priv = sdhci_pltfm_priv(pltfm_host);
|
|
int err;
|
|
|
|
err = clk_enable(pltfm_host->clk);
|
|
if (err)
|
|
return err;
|
|
+ sdhci_fix_caps(host, priv);
|
|
+ set_host_driver_strength_overrides(host, priv);
|
|
return sdhci_resume_host(host);
|
|
}
|
|
|
|
@@ -136,12 +253,34 @@
|
|
static SIMPLE_DEV_PM_OPS(sdhci_brcmstb_pmops, sdhci_brcmstb_suspend,
|
|
sdhci_brcmstb_resume);
|
|
|
|
+static void sdhci_brcmstb_of_get_driver_type(struct device_node *dn,
|
|
+ char *name, int *dtype)
|
|
+{
|
|
+ const char *driver_type;
|
|
+ int res;
|
|
+
|
|
+ res = of_property_read_string(dn, name, &driver_type);
|
|
+ if (res == 0) {
|
|
+ if (strcmp(driver_type, "A") == 0)
|
|
+ *dtype = MMC_SET_DRIVER_TYPE_A;
|
|
+ else if (strcmp(driver_type, "B") == 0)
|
|
+ *dtype = MMC_SET_DRIVER_TYPE_B;
|
|
+ else if (strcmp(driver_type, "C") == 0)
|
|
+ *dtype = MMC_SET_DRIVER_TYPE_C;
|
|
+ else if (strcmp(driver_type, "D") == 0)
|
|
+ *dtype = MMC_SET_DRIVER_TYPE_D;
|
|
+ }
|
|
+}
|
|
+
|
|
+
|
|
static int sdhci_brcmstb_probe(struct platform_device *pdev)
|
|
{
|
|
struct device_node *dn = pdev->dev.of_node;
|
|
struct sdhci_host *host;
|
|
struct sdhci_pltfm_host *pltfm_host;
|
|
+ struct sdhci_brcmstb_priv *priv;
|
|
struct clk *clk;
|
|
+ struct resource *resource;
|
|
int res;
|
|
|
|
clk = of_clk_get_by_name(dn, "sw_sdio");
|
|
@@ -153,27 +292,46 @@
|
|
if (res)
|
|
goto undo_clk_get;
|
|
|
|
-/* Only enable reset workaround for 7439a0 and 74371a0 senior */
|
|
#if defined(CONFIG_BCM74371A0)
|
|
+ /* Only enable reset workaround for 74371a0 senior */
|
|
if (BRCM_CHIP_ID() == 0x7439)
|
|
- sdhci_brcmstb_pdata.ops = &sdhci_brcmstb_ops;
|
|
-#endif
|
|
- host = sdhci_pltfm_init(pdev, &sdhci_brcmstb_pdata, 0);
|
|
+ sdhci_brcmstb_ops.write_b = sdhci_brcmstb_writeb;
|
|
+#endif /* CONFIG_BCM74371A0 */
|
|
+ sdhci_brcmstb_pdata.ops = &sdhci_brcmstb_ops;
|
|
+ host = sdhci_pltfm_init(pdev, &sdhci_brcmstb_pdata,
|
|
+ sizeof(struct sdhci_brcmstb_priv));
|
|
if (IS_ERR(host)) {
|
|
res = PTR_ERR(host);
|
|
goto undo_clk_prep;
|
|
}
|
|
sdhci_get_of_property(pdev);
|
|
mmc_of_parse(host->mmc);
|
|
- res = sdhci_fix_caps(pdev);
|
|
- if (res)
|
|
- goto undo_pltfm_init;
|
|
+ pltfm_host = sdhci_priv(host);
|
|
+ priv = sdhci_pltfm_priv(pltfm_host);
|
|
+ resource = platform_get_resource(pdev, IORESOURCE_MEM, 1);
|
|
+ if (resource == NULL) {
|
|
+ dev_err(&pdev->dev, "can't get SDHCI CFG base address\n");
|
|
+ return -EINVAL;
|
|
+ }
|
|
+ priv->cfg_regs = devm_request_and_ioremap(&pdev->dev, resource);
|
|
+ if (!priv->cfg_regs) {
|
|
+ dev_err(&pdev->dev, "can't map register space\n");
|
|
+ return -EINVAL;
|
|
+ }
|
|
+ sdhci_fix_caps(host, priv);
|
|
+
|
|
+ sdhci_brcmstb_of_get_driver_type(dn, "host-driver-strength",
|
|
+ &priv->host_driver_type);
|
|
+ sdhci_brcmstb_of_get_driver_type(dn, "host-hs-driver-strength",
|
|
+ &priv->host_hs_driver_type);
|
|
+ sdhci_brcmstb_of_get_driver_type(dn, "card-driver-strength",
|
|
+ &priv->card_driver_type);
|
|
+ set_host_driver_strength_overrides(host, priv);
|
|
|
|
res = sdhci_add_host(host);
|
|
if (res)
|
|
goto undo_pltfm_init;
|
|
|
|
- pltfm_host = sdhci_priv(host);
|
|
pltfm_host->clk = clk;
|
|
return res;
|
|
|
|
diff -u -N -r stblinux-3.14-1.8/drivers/mmc/host/sdhci.c stblinux-3.14-1.10-git/drivers/mmc/host/sdhci.c
|
|
--- stblinux-3.14-1.8/drivers/mmc/host/sdhci.c 2015-07-28 23:57:39.000000000 +0000
|
|
+++ stblinux-3.14-1.10-git/drivers/mmc/host/sdhci.c 2019-02-10 22:05:52.954335952 +0000
|
|
@@ -1527,8 +1527,18 @@
|
|
ctrl_2 &= ~SDHCI_CTRL_DRV_TYPE_MASK;
|
|
if (ios->drv_type == MMC_SET_DRIVER_TYPE_A)
|
|
ctrl_2 |= SDHCI_CTRL_DRV_TYPE_A;
|
|
+ else if (ios->drv_type == MMC_SET_DRIVER_TYPE_B)
|
|
+ ctrl_2 |= SDHCI_CTRL_DRV_TYPE_B;
|
|
else if (ios->drv_type == MMC_SET_DRIVER_TYPE_C)
|
|
ctrl_2 |= SDHCI_CTRL_DRV_TYPE_C;
|
|
+ else if (ios->drv_type == MMC_SET_DRIVER_TYPE_D)
|
|
+ ctrl_2 |= SDHCI_CTRL_DRV_TYPE_D;
|
|
+ else {
|
|
+ pr_warn("%s: invalid driver type, default to "
|
|
+ "driver type B\n",
|
|
+ mmc_hostname(host->mmc));
|
|
+ ctrl_2 |= SDHCI_CTRL_DRV_TYPE_B;
|
|
+ }
|
|
|
|
sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2);
|
|
} else {
|
|
@@ -2047,6 +2057,18 @@
|
|
return err;
|
|
}
|
|
|
|
+static int sdhci_select_drive_strength(struct mmc_card *card,
|
|
+ unsigned int max_dtr, int host_drv,
|
|
+ int card_drv, int *drv_type)
|
|
+{
|
|
+ struct sdhci_host *host = mmc_priv(card->host);
|
|
+
|
|
+ if (!host->ops->select_drive_strength)
|
|
+ return 0;
|
|
+
|
|
+ return host->ops->select_drive_strength(host, card, max_dtr, host_drv,
|
|
+ card_drv, drv_type);
|
|
+}
|
|
|
|
static void sdhci_enable_preset_value(struct sdhci_host *host, bool enable)
|
|
{
|
|
@@ -2110,6 +2132,7 @@
|
|
.enable_sdio_irq = sdhci_enable_sdio_irq,
|
|
.start_signal_voltage_switch = sdhci_start_signal_voltage_switch,
|
|
.execute_tuning = sdhci_execute_tuning,
|
|
+ .select_drive_strength = sdhci_select_drive_strength,
|
|
.card_event = sdhci_card_event,
|
|
.card_busy = sdhci_card_busy,
|
|
};
|
|
diff -u -N -r stblinux-3.14-1.8/drivers/mmc/host/sdhci.h stblinux-3.14-1.10-git/drivers/mmc/host/sdhci.h
|
|
--- stblinux-3.14-1.8/drivers/mmc/host/sdhci.h 2015-07-28 23:57:39.000000000 +0000
|
|
+++ stblinux-3.14-1.10-git/drivers/mmc/host/sdhci.h 2019-02-10 22:05:52.954335952 +0000
|
|
@@ -229,6 +229,7 @@
|
|
|
|
/* 60-FB reserved */
|
|
|
|
+#define SDHCI_PRESET_FOR_HS 0x64
|
|
#define SDHCI_PRESET_FOR_SDR12 0x66
|
|
#define SDHCI_PRESET_FOR_SDR25 0x68
|
|
#define SDHCI_PRESET_FOR_SDR50 0x6A
|
|
@@ -296,6 +297,10 @@
|
|
void (*adma_workaround)(struct sdhci_host *host, u32 intmask);
|
|
void (*platform_init)(struct sdhci_host *host);
|
|
void (*card_event)(struct sdhci_host *host);
|
|
+ int (*select_drive_strength)(struct sdhci_host *host,
|
|
+ struct mmc_card *card,
|
|
+ unsigned int max_dtr, int host_drv,
|
|
+ int card_drv, int *drv_type);
|
|
};
|
|
|
|
#ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS
|
|
diff -u -N -r stblinux-3.14-1.8/include/linux/mmc/host.h stblinux-3.14-1.10-git/include/linux/mmc/host.h
|
|
--- stblinux-3.14-1.8/include/linux/mmc/host.h 2015-07-28 23:57:41.000000000 +0000
|
|
+++ stblinux-3.14-1.10-git/include/linux/mmc/host.h 2019-02-10 22:05:53.146327704 +0000
|
|
@@ -136,7 +136,9 @@
|
|
|
|
/* The tuning command opcode value is different for SD and eMMC cards */
|
|
int (*execute_tuning)(struct mmc_host *host, u32 opcode);
|
|
- int (*select_drive_strength)(unsigned int max_dtr, int host_drv, int card_drv);
|
|
+ int (*select_drive_strength)(struct mmc_card *card,
|
|
+ unsigned int max_dtr, int host_drv,
|
|
+ int card_drv, int *drv_type);
|
|
void (*hw_reset)(struct mmc_host *host);
|
|
void (*card_event)(struct mmc_host *host);
|
|
};
|
|
|