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

ARM/mmc: Convert old mmci-omap to GPIO descriptors

A recent change to the OMAP driver making it use a dynamic GPIO
base created problems with some old OMAP1 board files, among
them Nokia 770, SX1 and also the OMAP2 Nokia n8x0.

Fix up all instances of GPIOs being used for the MMC driver
by pushing the handling of power, slot selection and MMC
"cover" into the driver as optional GPIOs.

This is maybe not the most perfect solution as the MMC
framework have some central handlers for some of the
stuff, but it at least makes the situtation better and
solves the immediate issue.

Fixes: 92bf78b33b0b ("gpio: omap: use dynamic allocation of base")
Acked-by: Ulf Hansson <ulf.hansson@linaro.org>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>

+83 -94
+13 -30
arch/arm/mach-omap1/board-nokia770.c
··· 184 184 185 185 #if IS_ENABLED(CONFIG_MMC_OMAP) 186 186 187 - #define NOKIA770_GPIO_MMC_POWER 41 188 - #define NOKIA770_GPIO_MMC_SWITCH 23 189 - 190 - static int nokia770_mmc_set_power(struct device *dev, int slot, int power_on, 191 - int vdd) 192 - { 193 - gpio_set_value(NOKIA770_GPIO_MMC_POWER, power_on); 194 - return 0; 195 - } 196 - 197 - static int nokia770_mmc_get_cover_state(struct device *dev, int slot) 198 - { 199 - return gpio_get_value(NOKIA770_GPIO_MMC_SWITCH); 200 - } 187 + static struct gpiod_lookup_table nokia770_mmc_gpio_table = { 188 + .dev_id = "mmci-omap.1", 189 + .table = { 190 + /* Slot index 0, VSD power, GPIO 41 */ 191 + GPIO_LOOKUP_IDX("gpio-32-47", 9, 192 + "vsd", 0, GPIO_ACTIVE_HIGH), 193 + /* Slot index 0, switch, GPIO 23 */ 194 + GPIO_LOOKUP_IDX("gpio-16-31", 7, 195 + "cover", 0, GPIO_ACTIVE_HIGH), 196 + { } 197 + }, 198 + }; 201 199 202 200 static struct omap_mmc_platform_data nokia770_mmc2_data = { 203 201 .nr_slots = 1, 204 202 .max_freq = 12000000, 205 203 .slots[0] = { 206 - .set_power = nokia770_mmc_set_power, 207 - .get_cover_state = nokia770_mmc_get_cover_state, 208 204 .ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34, 209 205 .name = "mmcblk", 210 206 }, ··· 210 214 211 215 static void __init nokia770_mmc_init(void) 212 216 { 213 - int ret; 214 - 215 - ret = gpio_request(NOKIA770_GPIO_MMC_POWER, "MMC power"); 216 - if (ret < 0) 217 - return; 218 - gpio_direction_output(NOKIA770_GPIO_MMC_POWER, 0); 219 - 220 - ret = gpio_request(NOKIA770_GPIO_MMC_SWITCH, "MMC cover"); 221 - if (ret < 0) { 222 - gpio_free(NOKIA770_GPIO_MMC_POWER); 223 - return; 224 - } 225 - gpio_direction_input(NOKIA770_GPIO_MMC_SWITCH); 226 - 217 + gpiod_add_lookup_table(&nokia770_mmc_gpio_table); 227 218 /* Only the second MMC controller is used */ 228 219 nokia770_mmc_data[1] = &nokia770_mmc2_data; 229 220 omap1_init_mmc(nokia770_mmc_data, OMAP16XX_NR_MMC);
-1
arch/arm/mach-omap1/board-sx1-mmc.c
··· 9 9 * Copyright (C) 2007 Instituto Nokia de Tecnologia - INdT 10 10 */ 11 11 12 - #include <linux/gpio.h> 13 12 #include <linux/platform_device.h> 14 13 15 14 #include "hardware.h"
+26 -59
arch/arm/mach-omap2/board-n8x0.c
··· 11 11 #include <linux/clk.h> 12 12 #include <linux/delay.h> 13 13 #include <linux/gpio.h> 14 + #include <linux/gpio/machine.h> 14 15 #include <linux/init.h> 15 16 #include <linux/io.h> 16 17 #include <linux/irq.h> ··· 171 170 * GPIO23 and GPIO9 slot 2 EMMC on N810 172 171 * 173 172 */ 174 - #define N8X0_SLOT_SWITCH_GPIO 96 175 - #define N810_EMMC_VSD_GPIO 23 176 - #define N810_EMMC_VIO_GPIO 9 177 - 178 173 static int slot1_cover_open; 179 174 static int slot2_cover_open; 180 175 static struct device *mmc_device; 181 176 182 - static int n8x0_mmc_switch_slot(struct device *dev, int slot) 183 - { 184 - #ifdef CONFIG_MMC_DEBUG 185 - dev_dbg(dev, "Choose slot %d\n", slot + 1); 186 - #endif 187 - gpio_set_value(N8X0_SLOT_SWITCH_GPIO, slot); 188 - return 0; 189 - } 177 + static struct gpiod_lookup_table nokia8xx_mmc_gpio_table = { 178 + .dev_id = "mmci-omap.0", 179 + .table = { 180 + /* Slot switch, GPIO 96 */ 181 + GPIO_LOOKUP("gpio-80-111", 16, 182 + "switch", GPIO_ACTIVE_HIGH), 183 + { } 184 + }, 185 + }; 186 + 187 + static struct gpiod_lookup_table nokia810_mmc_gpio_table = { 188 + .dev_id = "mmci-omap.0", 189 + .table = { 190 + /* Slot index 1, VSD power, GPIO 23 */ 191 + GPIO_LOOKUP_IDX("gpio-16-31", 7, 192 + "vsd", 1, GPIO_ACTIVE_HIGH), 193 + /* Slot index 1, VIO power, GPIO 9 */ 194 + GPIO_LOOKUP_IDX("gpio-0-15", 9, 195 + "vsd", 1, GPIO_ACTIVE_HIGH), 196 + { } 197 + }, 198 + }; 190 199 191 200 static int n8x0_mmc_set_power_menelaus(struct device *dev, int slot, 192 201 int power_on, int vdd) ··· 267 256 return 0; 268 257 } 269 258 270 - static void n810_set_power_emmc(struct device *dev, 271 - int power_on) 272 - { 273 - dev_dbg(dev, "Set EMMC power %s\n", power_on ? "on" : "off"); 274 - 275 - if (power_on) { 276 - gpio_set_value(N810_EMMC_VSD_GPIO, 1); 277 - msleep(1); 278 - gpio_set_value(N810_EMMC_VIO_GPIO, 1); 279 - msleep(1); 280 - } else { 281 - gpio_set_value(N810_EMMC_VIO_GPIO, 0); 282 - msleep(50); 283 - gpio_set_value(N810_EMMC_VSD_GPIO, 0); 284 - msleep(50); 285 - } 286 - } 287 - 288 259 static int n8x0_mmc_set_power(struct device *dev, int slot, int power_on, 289 260 int vdd) 290 261 { 291 262 if (board_is_n800() || slot == 0) 292 263 return n8x0_mmc_set_power_menelaus(dev, slot, power_on, vdd); 293 264 294 - n810_set_power_emmc(dev, power_on); 265 + /* The n810 power will be handled by GPIO code in the driver */ 295 266 296 267 return 0; 297 268 } ··· 411 418 static void n8x0_mmc_cleanup(struct device *dev) 412 419 { 413 420 menelaus_unregister_mmc_callback(); 414 - 415 - gpio_free(N8X0_SLOT_SWITCH_GPIO); 416 - 417 - if (board_is_n810()) { 418 - gpio_free(N810_EMMC_VSD_GPIO); 419 - gpio_free(N810_EMMC_VIO_GPIO); 420 - } 421 421 } 422 422 423 423 /* ··· 419 433 */ 420 434 static struct omap_mmc_platform_data mmc1_data = { 421 435 .nr_slots = 0, 422 - .switch_slot = n8x0_mmc_switch_slot, 423 436 .init = n8x0_mmc_late_init, 424 437 .cleanup = n8x0_mmc_cleanup, 425 438 .shutdown = n8x0_mmc_shutdown, ··· 448 463 449 464 static struct omap_mmc_platform_data *mmc_data[OMAP24XX_NR_MMC]; 450 465 451 - static struct gpio n810_emmc_gpios[] __initdata = { 452 - { N810_EMMC_VSD_GPIO, GPIOF_OUT_INIT_LOW, "MMC slot 2 Vddf" }, 453 - { N810_EMMC_VIO_GPIO, GPIOF_OUT_INIT_LOW, "MMC slot 2 Vdd" }, 454 - }; 455 - 456 466 static void __init n8x0_mmc_init(void) 457 467 { 458 - int err; 468 + gpiod_add_lookup_table(&nokia8xx_mmc_gpio_table); 459 469 460 470 if (board_is_n810()) { 461 471 mmc1_data.slots[0].name = "external"; ··· 463 483 */ 464 484 mmc1_data.slots[1].name = "internal"; 465 485 mmc1_data.slots[1].ban_openended = 1; 466 - } 467 - 468 - err = gpio_request_one(N8X0_SLOT_SWITCH_GPIO, GPIOF_OUT_INIT_LOW, 469 - "MMC slot switch"); 470 - if (err) 471 - return; 472 - 473 - if (board_is_n810()) { 474 - err = gpio_request_array(n810_emmc_gpios, 475 - ARRAY_SIZE(n810_emmc_gpios)); 476 - if (err) { 477 - gpio_free(N8X0_SLOT_SWITCH_GPIO); 478 - return; 479 - } 486 + gpiod_add_lookup_table(&nokia810_mmc_gpio_table); 480 487 } 481 488 482 489 mmc1_data.nr_slots = 2;
+44 -2
drivers/mmc/host/omap.c
··· 26 26 #include <linux/clk.h> 27 27 #include <linux/scatterlist.h> 28 28 #include <linux/slab.h> 29 + #include <linux/gpio/consumer.h> 29 30 #include <linux/platform_data/mmc-omap.h> 30 31 31 32 ··· 112 111 struct mmc_request *mrq; 113 112 struct mmc_omap_host *host; 114 113 struct mmc_host *mmc; 114 + struct gpio_desc *vsd; 115 + struct gpio_desc *vio; 116 + struct gpio_desc *cover; 115 117 struct omap_mmc_slot_data *pdata; 116 118 }; 117 119 ··· 137 133 int irq; 138 134 unsigned char bus_mode; 139 135 unsigned int reg_shift; 136 + struct gpio_desc *slot_switch; 140 137 141 138 struct work_struct cmd_abort_work; 142 139 unsigned abort:1; ··· 221 216 222 217 if (host->current_slot != slot) { 223 218 OMAP_MMC_WRITE(host, CON, slot->saved_con & 0xFC00); 224 - if (host->pdata->switch_slot != NULL) 225 - host->pdata->switch_slot(mmc_dev(slot->mmc), slot->id); 219 + if (host->slot_switch) 220 + /* 221 + * With two slots and a simple GPIO switch, setting 222 + * the GPIO to 0 selects slot ID 0, setting it to 1 223 + * selects slot ID 1. 224 + */ 225 + gpiod_set_value(host->slot_switch, slot->id); 226 226 host->current_slot = slot; 227 227 } 228 228 ··· 307 297 static inline 308 298 int mmc_omap_cover_is_open(struct mmc_omap_slot *slot) 309 299 { 300 + /* If we have a GPIO then use that */ 301 + if (slot->cover) 302 + return gpiod_get_value(slot->cover); 310 303 if (slot->pdata->get_cover_state) 311 304 return slot->pdata->get_cover_state(mmc_dev(slot->mmc), 312 305 slot->id); ··· 1119 1106 1120 1107 host = slot->host; 1121 1108 1109 + if (slot->vsd) 1110 + gpiod_set_value(slot->vsd, power_on); 1111 + if (slot->vio) 1112 + gpiod_set_value(slot->vio, power_on); 1113 + 1122 1114 if (slot->pdata->set_power != NULL) 1123 1115 slot->pdata->set_power(mmc_dev(slot->mmc), slot->id, power_on, 1124 1116 vdd); ··· 1258 1240 slot->power_mode = MMC_POWER_UNDEFINED; 1259 1241 slot->pdata = &host->pdata->slots[id]; 1260 1242 1243 + /* Check for some optional GPIO controls */ 1244 + slot->vsd = gpiod_get_index_optional(host->dev, "vsd", 1245 + id, GPIOD_OUT_LOW); 1246 + if (IS_ERR(slot->vsd)) 1247 + return dev_err_probe(host->dev, PTR_ERR(slot->vsd), 1248 + "error looking up VSD GPIO\n"); 1249 + slot->vio = gpiod_get_index_optional(host->dev, "vio", 1250 + id, GPIOD_OUT_LOW); 1251 + if (IS_ERR(slot->vio)) 1252 + return dev_err_probe(host->dev, PTR_ERR(slot->vio), 1253 + "error looking up VIO GPIO\n"); 1254 + slot->cover = gpiod_get_index_optional(host->dev, "cover", 1255 + id, GPIOD_IN); 1256 + if (IS_ERR(slot->cover)) 1257 + return dev_err_probe(host->dev, PTR_ERR(slot->cover), 1258 + "error looking up cover switch GPIO\n"); 1259 + 1261 1260 host->slots[id] = slot; 1262 1261 1263 1262 mmc->caps = 0; ··· 1383 1348 host->virt_base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); 1384 1349 if (IS_ERR(host->virt_base)) 1385 1350 return PTR_ERR(host->virt_base); 1351 + 1352 + host->slot_switch = gpiod_get_optional(host->dev, "switch", 1353 + GPIOD_OUT_LOW); 1354 + if (IS_ERR(host->slot_switch)) 1355 + return dev_err_probe(host->dev, PTR_ERR(host->slot_switch), 1356 + "error looking up slot switch GPIO\n"); 1357 + 1386 1358 1387 1359 INIT_WORK(&host->slot_release_work, mmc_omap_slot_release_work); 1388 1360 INIT_WORK(&host->send_stop_work, mmc_omap_send_stop_work);
-2
include/linux/platform_data/mmc-omap.h
··· 20 20 * maximum frequency on the MMC bus */ 21 21 unsigned int max_freq; 22 22 23 - /* switch the bus to a new slot */ 24 - int (*switch_slot)(struct device *dev, int slot); 25 23 /* initialize board-specific MMC functionality, can be NULL if 26 24 * not supported */ 27 25 int (*init)(struct device *dev);