Commit 0f7c815d authored by Michał Mirosław's avatar Michał Mirosław Committed by Ulf Hansson
Browse files

mmc: core: Rework cd-gpio handling



There are a few places around the code that invert inverted and possibly
inverted CD line. That's really confusing. Squash them all into one place
in mmc_gpiod_request_cd(). MMC_CAP2_CD_ACTIVE_HIGH is used analogously to
WP line: in GPIO mode it is used only at probe time to switch polarity, for
native mode it is left as is.

Signed-off-by: default avatarMichał Mirosław <mirq-linux@rere.qmqm.pl>
Link: https://lore.kernel.org/r/db189b715596d63caf8c6a088bddc71dd69a879b.1576031637.git.mirq-linux@rere.qmqm.pl


Signed-off-by: default avatarUlf Hansson <ulf.hansson@linaro.org>
parent 9073d10b
Loading
Loading
Loading
Loading
+0 −17
Original line number Diff line number Diff line
@@ -104,23 +104,6 @@ static void of_gpio_flags_quirks(struct device_node *np,
				 enum of_gpio_flags *flags,
				 int index)
{
	/*
	 * Handle MMC "cd-inverted" and "wp-inverted" semantics.
	 */
	if (IS_ENABLED(CONFIG_MMC)) {
		/*
		 * Active low is the default according to the
		 * SDHCI specification and the device tree
		 * bindings. However the code in the current
		 * kernel was written such that the phandle
		 * flags were always respected, and "cd-inverted"
		 * would invert the flag from the device phandle.
		 */
		if (!strcmp(propname, "cd-gpios")) {
			if (of_property_read_bool(np, "cd-inverted"))
				*flags ^= OF_GPIO_ACTIVE_LOW;
		}
	}
	/*
	 * Some GPIO fixed regulator quirks.
	 * Note that active low is the default.
+4 −17
Original line number Diff line number Diff line
@@ -175,7 +175,6 @@ int mmc_of_parse(struct mmc_host *host)
	struct device *dev = host->parent;
	u32 bus_width, drv_type, cd_debounce_delay_ms;
	int ret;
	bool cd_cap_invert, cd_gpio_invert = false;

	if (!dev || !dev_fwnode(dev))
		return 0;
@@ -218,10 +217,12 @@ int mmc_of_parse(struct mmc_host *host)
	 */

	/* Parse Card Detection */

	if (device_property_read_bool(dev, "non-removable")) {
		host->caps |= MMC_CAP_NONREMOVABLE;
	} else {
		cd_cap_invert = device_property_read_bool(dev, "cd-inverted");
		if (device_property_read_bool(dev, "cd-inverted"))
			host->caps2 |= MMC_CAP2_CD_ACTIVE_HIGH;

		if (device_property_read_u32(dev, "cd-debounce-delay-ms",
					     &cd_debounce_delay_ms))
@@ -232,25 +233,11 @@ int mmc_of_parse(struct mmc_host *host)

		ret = mmc_gpiod_request_cd(host, "cd", 0, false,
					   cd_debounce_delay_ms * 1000,
					   &cd_gpio_invert);
					   NULL);
		if (!ret)
			dev_info(host->parent, "Got CD GPIO\n");
		else if (ret != -ENOENT && ret != -ENOSYS)
			return ret;

		/*
		 * There are two ways to flag that the CD line is inverted:
		 * through the cd-inverted flag and by the GPIO line itself
		 * being inverted from the GPIO subsystem. This is a leftover
		 * from the times when the GPIO subsystem did not make it
		 * possible to flag a line as inverted.
		 *
		 * If the capability on the host AND the GPIO line are
		 * both inverted, the end result is that the CD line is
		 * not inverted.
		 */
		if (cd_cap_invert ^ cd_gpio_invert)
			host->caps2 |= MMC_CAP2_CD_ACTIVE_HIGH;
	}

	/* Parse Write Protection */
+8 −9
Original line number Diff line number Diff line
@@ -19,7 +19,6 @@
struct mmc_gpio {
	struct gpio_desc *ro_gpio;
	struct gpio_desc *cd_gpio;
	bool override_cd_active_level;
	irqreturn_t (*cd_gpio_isr)(int irq, void *dev_id);
	char *ro_label;
	char *cd_label;
@@ -80,13 +79,6 @@ int mmc_gpio_get_cd(struct mmc_host *host)
		return -ENOSYS;

	cansleep = gpiod_cansleep(ctx->cd_gpio);
	if (ctx->override_cd_active_level) {
		int value = cansleep ?
				gpiod_get_raw_value_cansleep(ctx->cd_gpio) :
				gpiod_get_raw_value(ctx->cd_gpio);
		return !value ^ !!(host->caps2 & MMC_CAP2_CD_ACTIVE_HIGH);
	}

	return cansleep ?
		gpiod_get_value_cansleep(ctx->cd_gpio) :
		gpiod_get_value(ctx->cd_gpio);
@@ -194,10 +186,17 @@ int mmc_gpiod_request_cd(struct mmc_host *host, const char *con_id,
			ctx->cd_debounce_delay_ms = debounce / 1000;
	}

	/* override forces default (active-low) polarity ... */
	if (override_active_level && !gpiod_is_active_low(desc))
		gpiod_toggle_active_low(desc);

	/* ... or active-high */
	if (host->caps2 & MMC_CAP2_CD_ACTIVE_HIGH)
		gpiod_toggle_active_low(desc);

	if (gpio_invert)
		*gpio_invert = !gpiod_is_active_low(desc);

	ctx->override_cd_active_level = override_active_level;
	ctx->cd_gpio = desc;

	return 0;