Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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: Michał Mirosław <mirq-linux@rere.qmqm.pl>
Link: https://lore.kernel.org/r/db189b715596d63caf8c6a088bddc71dd69a879b.1576031637.git.mirq-linux@rere.qmqm.pl
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>

authored by

Michał Mirosław and committed by
Ulf Hansson
0f7c815d 9073d10b

+12 -43
-17
drivers/gpio/gpiolib-of.c
··· 105 105 int index) 106 106 { 107 107 /* 108 - * Handle MMC "cd-inverted" and "wp-inverted" semantics. 109 - */ 110 - if (IS_ENABLED(CONFIG_MMC)) { 111 - /* 112 - * Active low is the default according to the 113 - * SDHCI specification and the device tree 114 - * bindings. However the code in the current 115 - * kernel was written such that the phandle 116 - * flags were always respected, and "cd-inverted" 117 - * would invert the flag from the device phandle. 118 - */ 119 - if (!strcmp(propname, "cd-gpios")) { 120 - if (of_property_read_bool(np, "cd-inverted")) 121 - *flags ^= OF_GPIO_ACTIVE_LOW; 122 - } 123 - } 124 - /* 125 108 * Some GPIO fixed regulator quirks. 126 109 * Note that active low is the default. 127 110 */
+4 -17
drivers/mmc/core/host.c
··· 175 175 struct device *dev = host->parent; 176 176 u32 bus_width, drv_type, cd_debounce_delay_ms; 177 177 int ret; 178 - bool cd_cap_invert, cd_gpio_invert = false; 179 178 180 179 if (!dev || !dev_fwnode(dev)) 181 180 return 0; ··· 217 218 */ 218 219 219 220 /* Parse Card Detection */ 221 + 220 222 if (device_property_read_bool(dev, "non-removable")) { 221 223 host->caps |= MMC_CAP_NONREMOVABLE; 222 224 } else { 223 - cd_cap_invert = device_property_read_bool(dev, "cd-inverted"); 225 + if (device_property_read_bool(dev, "cd-inverted")) 226 + host->caps2 |= MMC_CAP2_CD_ACTIVE_HIGH; 224 227 225 228 if (device_property_read_u32(dev, "cd-debounce-delay-ms", 226 229 &cd_debounce_delay_ms)) ··· 233 232 234 233 ret = mmc_gpiod_request_cd(host, "cd", 0, false, 235 234 cd_debounce_delay_ms * 1000, 236 - &cd_gpio_invert); 235 + NULL); 237 236 if (!ret) 238 237 dev_info(host->parent, "Got CD GPIO\n"); 239 238 else if (ret != -ENOENT && ret != -ENOSYS) 240 239 return ret; 241 - 242 - /* 243 - * There are two ways to flag that the CD line is inverted: 244 - * through the cd-inverted flag and by the GPIO line itself 245 - * being inverted from the GPIO subsystem. This is a leftover 246 - * from the times when the GPIO subsystem did not make it 247 - * possible to flag a line as inverted. 248 - * 249 - * If the capability on the host AND the GPIO line are 250 - * both inverted, the end result is that the CD line is 251 - * not inverted. 252 - */ 253 - if (cd_cap_invert ^ cd_gpio_invert) 254 - host->caps2 |= MMC_CAP2_CD_ACTIVE_HIGH; 255 240 } 256 241 257 242 /* Parse Write Protection */
+8 -9
drivers/mmc/core/slot-gpio.c
··· 19 19 struct mmc_gpio { 20 20 struct gpio_desc *ro_gpio; 21 21 struct gpio_desc *cd_gpio; 22 - bool override_cd_active_level; 23 22 irqreturn_t (*cd_gpio_isr)(int irq, void *dev_id); 24 23 char *ro_label; 25 24 char *cd_label; ··· 79 80 return -ENOSYS; 80 81 81 82 cansleep = gpiod_cansleep(ctx->cd_gpio); 82 - if (ctx->override_cd_active_level) { 83 - int value = cansleep ? 84 - gpiod_get_raw_value_cansleep(ctx->cd_gpio) : 85 - gpiod_get_raw_value(ctx->cd_gpio); 86 - return !value ^ !!(host->caps2 & MMC_CAP2_CD_ACTIVE_HIGH); 87 - } 88 - 89 83 return cansleep ? 90 84 gpiod_get_value_cansleep(ctx->cd_gpio) : 91 85 gpiod_get_value(ctx->cd_gpio); ··· 186 194 ctx->cd_debounce_delay_ms = debounce / 1000; 187 195 } 188 196 197 + /* override forces default (active-low) polarity ... */ 198 + if (override_active_level && !gpiod_is_active_low(desc)) 199 + gpiod_toggle_active_low(desc); 200 + 201 + /* ... or active-high */ 202 + if (host->caps2 & MMC_CAP2_CD_ACTIVE_HIGH) 203 + gpiod_toggle_active_low(desc); 204 + 189 205 if (gpio_invert) 190 206 *gpio_invert = !gpiod_is_active_low(desc); 191 207 192 - ctx->override_cd_active_level = override_active_level; 193 208 ctx->cd_gpio = desc; 194 209 195 210 return 0;