Message ID | 20200831190130.47060-4-eajames@linux.ibm.com |
---|---|
State | New |
Headers | show |
Series | AST2600: Boot from eMMC | expand |
On Mon, 31 Aug 2020 at 19:01, Eddie James <eajames@linux.ibm.com> wrote: > > The Aspeed SDHC needs some additional parameters set to function > correctly. These should be encoded in the devicetree. > > Signed-off-by: Eddie James <eajames@linux.ibm.com> Does this use the same binding as the kernel patches that Andrew is going to send upstream? Can this one go straight to upstream u-boot? > --- > drivers/mmc/aspeed_sdhci.c | 2 ++ > drivers/mmc/aspeed_sdhci_ic.c | 16 ++++++++++++++++ > drivers/mmc/sdhci.c | 8 ++++++++ > include/mmc.h | 1 + > include/sdhci.h | 6 +++++- > 5 files changed, 32 insertions(+), 1 deletion(-) > mode change 100755 => 100644 drivers/mmc/aspeed_sdhci.c > > diff --git a/drivers/mmc/aspeed_sdhci.c b/drivers/mmc/aspeed_sdhci.c > old mode 100755 > new mode 100644 > index f4cdfe039f..36cbf29db5 > --- a/drivers/mmc/aspeed_sdhci.c > +++ b/drivers/mmc/aspeed_sdhci.c > @@ -93,6 +93,8 @@ static int aspeed_sdhci_probe(struct udevice *dev) > host->mmc = &plat->mmc; > if (ret) > return ret; > + > + host->mmc->drv_type = dev_read_u32_default(dev, "sdhci-drive-type", 0); > host->mmc->priv = host; > host->mmc->dev = dev; > upriv->mmc = host->mmc; > diff --git a/drivers/mmc/aspeed_sdhci_ic.c b/drivers/mmc/aspeed_sdhci_ic.c > index fd62ab3eae..b8dd5d52f9 100644 > --- a/drivers/mmc/aspeed_sdhci_ic.c > +++ b/drivers/mmc/aspeed_sdhci_ic.c > @@ -9,6 +9,10 @@ > #include <errno.h> > #include <fdtdec.h> > #include <asm/io.h> > +#include <linux/io.h> > +#include <linux/ioport.h> > + > +#define TIMING_PHASE_OFFSET 0xf4 > > struct aspeed_sdhci_general_reg { > u32 genreal_info; > @@ -32,6 +36,9 @@ static int aspeed_sdhci_irq_probe(struct udevice *dev) > { > struct aspeed_sdhci_general_data *priv = dev_get_priv(dev); > int ret = 0; > + struct resource regs; > + void __iomem *sdhci_ctrl_base; > + u32 timing_phase; > > debug("%s(dev=%p) \n", __func__, dev); > > @@ -41,6 +48,15 @@ static int aspeed_sdhci_irq_probe(struct udevice *dev) > return ret; > } > > + ret = dev_read_resource(dev, 0, ®s); > + if (ret < 0) > + return ret; > + > + sdhci_ctrl_base = (void __iomem *)regs.start; > + > + timing_phase = dev_read_u32_default(dev, "timing-phase", 0); > + writel(timing_phase, sdhci_ctrl_base + TIMING_PHASE_OFFSET); > + > return 0; > } > > diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c > index ff506cdf9d..2505d5b8be 100644 > --- a/drivers/mmc/sdhci.c > +++ b/drivers/mmc/sdhci.c > @@ -460,6 +460,7 @@ static int sdhci_set_ios(struct mmc *mmc) > #endif > u32 ctrl; > u32 gen_addr, gen_ctrl; > + u16 ctrl_2; > struct sdhci_host *host = mmc->priv; > > if (host->ops && host->ops->set_control_reg) > @@ -518,6 +519,13 @@ static int sdhci_set_ios(struct mmc *mmc) > > sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); > > + if ((SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300)) { > + ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL_2); > + ctrl_2 &= ~SDHCI_DRIVER_STRENGTH_MASK; > + ctrl_2 |= host->mmc->drv_type << SDHCI_DRIVER_STRENGTH_SHIFT; > + sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL_2); > + } > + > /* If available, call the driver specific "post" set_ios() function */ > if (host->ops && host->ops->set_ios_post) > host->ops->set_ios_post(host); > diff --git a/include/mmc.h b/include/mmc.h > index 1f30f71d25..4834dbaf81 100644 > --- a/include/mmc.h > +++ b/include/mmc.h > @@ -639,6 +639,7 @@ struct mmc { > * accessing the boot partitions > */ > u32 quirks; > + int drv_type; > }; > > struct mmc_hwpart_conf { > diff --git a/include/sdhci.h b/include/sdhci.h > index 14884e4dbb..6f85895480 100644 > --- a/include/sdhci.h > +++ b/include/sdhci.h > @@ -144,7 +144,11 @@ > > #define SDHCI_ACMD12_ERR 0x3C > > -/* 3E-3F reserved */ > +#define SDHCI_HOST_CONTROL_2 0x3E > +#define SDHCI_DRIVER_STRENGTH_MASK 0x30 > +#define SDHCI_DRIVER_STRENGTH_SHIFT 4 > + > +/* 3F reserved */ > > #define SDHCI_CAPABILITIES 0x40 > #define SDHCI_TIMEOUT_CLK_MASK 0x0000003F > -- > 2.26.2 >
diff --git a/drivers/mmc/aspeed_sdhci.c b/drivers/mmc/aspeed_sdhci.c old mode 100755 new mode 100644 index f4cdfe039f..36cbf29db5 --- a/drivers/mmc/aspeed_sdhci.c +++ b/drivers/mmc/aspeed_sdhci.c @@ -93,6 +93,8 @@ static int aspeed_sdhci_probe(struct udevice *dev) host->mmc = &plat->mmc; if (ret) return ret; + + host->mmc->drv_type = dev_read_u32_default(dev, "sdhci-drive-type", 0); host->mmc->priv = host; host->mmc->dev = dev; upriv->mmc = host->mmc; diff --git a/drivers/mmc/aspeed_sdhci_ic.c b/drivers/mmc/aspeed_sdhci_ic.c index fd62ab3eae..b8dd5d52f9 100644 --- a/drivers/mmc/aspeed_sdhci_ic.c +++ b/drivers/mmc/aspeed_sdhci_ic.c @@ -9,6 +9,10 @@ #include <errno.h> #include <fdtdec.h> #include <asm/io.h> +#include <linux/io.h> +#include <linux/ioport.h> + +#define TIMING_PHASE_OFFSET 0xf4 struct aspeed_sdhci_general_reg { u32 genreal_info; @@ -32,6 +36,9 @@ static int aspeed_sdhci_irq_probe(struct udevice *dev) { struct aspeed_sdhci_general_data *priv = dev_get_priv(dev); int ret = 0; + struct resource regs; + void __iomem *sdhci_ctrl_base; + u32 timing_phase; debug("%s(dev=%p) \n", __func__, dev); @@ -41,6 +48,15 @@ static int aspeed_sdhci_irq_probe(struct udevice *dev) return ret; } + ret = dev_read_resource(dev, 0, ®s); + if (ret < 0) + return ret; + + sdhci_ctrl_base = (void __iomem *)regs.start; + + timing_phase = dev_read_u32_default(dev, "timing-phase", 0); + writel(timing_phase, sdhci_ctrl_base + TIMING_PHASE_OFFSET); + return 0; } diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c index ff506cdf9d..2505d5b8be 100644 --- a/drivers/mmc/sdhci.c +++ b/drivers/mmc/sdhci.c @@ -460,6 +460,7 @@ static int sdhci_set_ios(struct mmc *mmc) #endif u32 ctrl; u32 gen_addr, gen_ctrl; + u16 ctrl_2; struct sdhci_host *host = mmc->priv; if (host->ops && host->ops->set_control_reg) @@ -518,6 +519,13 @@ static int sdhci_set_ios(struct mmc *mmc) sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); + if ((SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300)) { + ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL_2); + ctrl_2 &= ~SDHCI_DRIVER_STRENGTH_MASK; + ctrl_2 |= host->mmc->drv_type << SDHCI_DRIVER_STRENGTH_SHIFT; + sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL_2); + } + /* If available, call the driver specific "post" set_ios() function */ if (host->ops && host->ops->set_ios_post) host->ops->set_ios_post(host); diff --git a/include/mmc.h b/include/mmc.h index 1f30f71d25..4834dbaf81 100644 --- a/include/mmc.h +++ b/include/mmc.h @@ -639,6 +639,7 @@ struct mmc { * accessing the boot partitions */ u32 quirks; + int drv_type; }; struct mmc_hwpart_conf { diff --git a/include/sdhci.h b/include/sdhci.h index 14884e4dbb..6f85895480 100644 --- a/include/sdhci.h +++ b/include/sdhci.h @@ -144,7 +144,11 @@ #define SDHCI_ACMD12_ERR 0x3C -/* 3E-3F reserved */ +#define SDHCI_HOST_CONTROL_2 0x3E +#define SDHCI_DRIVER_STRENGTH_MASK 0x30 +#define SDHCI_DRIVER_STRENGTH_SHIFT 4 + +/* 3F reserved */ #define SDHCI_CAPABILITIES 0x40 #define SDHCI_TIMEOUT_CLK_MASK 0x0000003F
The Aspeed SDHC needs some additional parameters set to function correctly. These should be encoded in the devicetree. Signed-off-by: Eddie James <eajames@linux.ibm.com> --- drivers/mmc/aspeed_sdhci.c | 2 ++ drivers/mmc/aspeed_sdhci_ic.c | 16 ++++++++++++++++ drivers/mmc/sdhci.c | 8 ++++++++ include/mmc.h | 1 + include/sdhci.h | 6 +++++- 5 files changed, 32 insertions(+), 1 deletion(-) mode change 100755 => 100644 drivers/mmc/aspeed_sdhci.c