[U-Boot] [PATCH 1/2] mmc: sunxi: Support cd-inverted DT property
Tuomas Tynkkynen
tuomas at tuxera.com
Wed Dec 20 13:34:47 UTC 2017
On Wed, 2017-12-20 at 13:26 +0100, Maxime Ripard wrote:
> On Mon, Dec 18, 2017 at 10:09:41PM +0200, Tuomas Tynkkynen wrote:
> > Commit 8620f384098b ("dm: sunxi: Linksprite_pcDuino3: Correct
> > polarity
> > of MMC card detect") claims that the Pcduino3 device tree has an
> > incorrect polarity for the card detect pin, but the actual problem
> > is
> > that unlike the Linux MMC driver, the U-Boot driver isn't
> > respecting the
> > cd-invert property (see
> > Documentation/devicetree/bindings/mmc/mmc.txt)
> > which tells that the card detect signal level should be inverted.
> >
> > Fix this properly by adding support for the cd-inverted property
> > while
> > reverting the original commit at the same time. While at it, I
> > noticed
> > the driver always enables pullups for the card detect line, which
> > is not
> > right if the card detect GPIO is active-high, so fix that as well.
> >
> > Signed-off-by: Tuomas Tynkkynen <tuomas at tuxera.com>
> > ---
> > arch/arm/dts/sun7i-a20-pcduino3.dts | 2 +-
> > drivers/mmc/sunxi_mmc.c | 12 ++++++++++--
> > 2 files changed, 11 insertions(+), 3 deletions(-)
> >
> > diff --git a/arch/arm/dts/sun7i-a20-pcduino3.dts
> > b/arch/arm/dts/sun7i-a20-pcduino3.dts
> > index 37b1e0ee9b..1a8b39be1d 100644
> > --- a/arch/arm/dts/sun7i-a20-pcduino3.dts
> > +++ b/arch/arm/dts/sun7i-a20-pcduino3.dts
> > @@ -164,7 +164,7 @@
> > pinctrl-0 = <&mmc0_pins_a>,
> > <&mmc0_cd_pin_reference_design>;
> > vmmc-supply = <®_vcc3v3>;
> > bus-width = <4>;
> > - cd-gpios = <&pio 7 1 GPIO_ACTIVE_LOW>; /* PH1 */
> > + cd-gpios = <&pio 7 1 GPIO_ACTIVE_HIGH>; /* PH1 */
> > cd-inverted;
> > status = "okay";
> > };
> > diff --git a/drivers/mmc/sunxi_mmc.c b/drivers/mmc/sunxi_mmc.c
> > index 4edb4be46c..7cc7303570 100644
> > --- a/drivers/mmc/sunxi_mmc.c
> > +++ b/drivers/mmc/sunxi_mmc.c
> > @@ -30,6 +30,7 @@ struct sunxi_mmc_priv {
> > uint32_t *mclkreg;
> > unsigned fatal_err;
> > struct gpio_desc cd_gpio; /* Change Detect GPIO */
> > + int cd_inverted;
> > struct sunxi_mmc *reg;
> > struct mmc_config cfg;
> > };
> > @@ -545,7 +546,7 @@ static int sunxi_mmc_getcd(struct udevice *dev)
> > struct sunxi_mmc_priv *priv = dev_get_priv(dev);
> >
> > if (dm_gpio_is_valid(&priv->cd_gpio))
> > - return dm_gpio_get_value(&priv->cd_gpio);
> > + return dm_gpio_get_value(&priv->cd_gpio) ^ priv-
> > >cd_inverted;
> >
> > return 1;
> > }
> > @@ -606,8 +607,15 @@ static int sunxi_mmc_probe(struct udevice
> > *dev)
> > if (!gpio_request_by_name(dev, "cd-gpios", 0, &priv-
> > >cd_gpio,
> > GPIOD_IS_IN)) {
> > int cd_pin = gpio_get_number(&priv->cd_gpio);
> > + int cd_state = priv->cd_gpio.flags &
> > GPIOD_ACTIVE_LOW ? 0 : 1;
>
> Isn't that change itself enough to get what you wanted?
>
> You really shouldn't be doing anything else.
Was that the correct part you meant to quote? The cd_state
was only for the somewhat pull-up change... Sorry about that,
here's the minimal (probably whitespace-damaged) change:
diff --git a/arch/arm/dts/sun7i-a20-pcduino3.dts b/arch/arm/dts/sun7i-a20-pcduino3.dts
index 37b1e0ee9b..1a8b39be1d 100644
--- a/arch/arm/dts/sun7i-a20-pcduino3.dts
+++ b/arch/arm/dts/sun7i-a20-pcduino3.dts
@@ -164,7 +164,7 @@
pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_reference_design>;
vmmc-supply = <®_vcc3v3>;
bus-width = <4>;
- cd-gpios = <&pio 7 1 GPIO_ACTIVE_LOW>; /* PH1 */
+ cd-gpios = <&pio 7 1 GPIO_ACTIVE_HIGH>; /* PH1 */
cd-inverted;
status = "okay";
};
diff --git a/drivers/mmc/sunxi_mmc.c b/drivers/mmc/sunxi_mmc.c
index 4edb4be46c..a974543148 100644
--- a/drivers/mmc/sunxi_mmc.c
+++ b/drivers/mmc/sunxi_mmc.c
@@ -30,6 +30,7 @@ struct sunxi_mmc_priv {
uint32_t *mclkreg;
unsigned fatal_err;
struct gpio_desc cd_gpio; /* Change Detect GPIO */
+ int cd_inverted;
struct sunxi_mmc *reg;
struct mmc_config cfg;
};
@@ -545,7 +546,7 @@ static int sunxi_mmc_getcd(struct udevice *dev)
struct sunxi_mmc_priv *priv = dev_get_priv(dev);
if (dm_gpio_is_valid(&priv->cd_gpio))
- return dm_gpio_get_value(&priv->cd_gpio);
+ return dm_gpio_get_value(&priv->cd_gpio) ^ priv->cd_inverted;
return 1;
}
@@ -607,6 +608,8 @@ static int sunxi_mmc_probe(struct udevice *dev)
GPIOD_IS_IN)) {
int cd_pin = gpio_get_number(&priv->cd_gpio);
+ priv->cd_inverted = dev_read_bool(dev, "cd-inverted");
+
sunxi_gpio_set_pull(cd_pin, SUNXI_GPIO_PULL_UP);
}
So: if the DT specifies GPIO_ACTIVE_LOW, dm_gpio_get_value()
does its own inversion of the GPIO level. Then, on top of that
we do another inversion if the "cd-inverted" property was specified.
This matches what the Linux MMC driver does.
Does that make sense?
Thanks.
More information about the U-Boot
mailing list