diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-05-23 21:24:10 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-05-23 21:24:10 -0400 |
| commit | 514e250f67d2b2a8ab08dc9c3650af19a411c926 (patch) | |
| tree | 5cb431c3a7c4792358ee82798281976db0412786 | |
| parent | b91fd4d5aad0c1124654341814067ca3f59490fc (diff) | |
| parent | cfb10898efe1bc1f3eb8d8f37f164d9e2ac8b43a (diff) | |
Merge tag 'gpio-fixes-v3.10-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio
Pull GPIO fixes from Linus Walleij:
- An OMAP fix that makes ethernet work again.
- Fix for build problem when building the MCP23S08 driver as module.
- IRQ conflicts in the Langwell driver.
- Fix IRQ coherency issues in the MXS driver.
- Return correct errorcode on errorpath when removing GPIO chips.
* tag 'gpio-fixes-v3.10-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio:
gpio: Don't override the error code in probe error handling
gpio: mxs: Use set and clear capabilities of the gpio controller
gpio-langwell: fix irq conflicts when DT is not used
gpio: mcp23s08: Fix build error when CONFIG_SPI_MASTER=y && CONFIG_I2C=m
gpio/omap: ensure gpio context is initialised
| -rw-r--r-- | drivers/gpio/Kconfig | 2 | ||||
| -rw-r--r-- | drivers/gpio/gpio-langwell.c | 17 | ||||
| -rw-r--r-- | drivers/gpio/gpio-ml-ioh.c | 3 | ||||
| -rw-r--r-- | drivers/gpio/gpio-mxs.c | 3 | ||||
| -rw-r--r-- | drivers/gpio/gpio-omap.c | 48 | ||||
| -rw-r--r-- | drivers/gpio/gpio-pch.c | 3 | ||||
| -rw-r--r-- | drivers/gpio/gpio-sch.c | 6 | ||||
| -rw-r--r-- | drivers/gpio/gpio-viperboard.c | 3 |
8 files changed, 64 insertions, 21 deletions
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 87d567089f13..573c449c49b9 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig | |||
| @@ -636,7 +636,7 @@ config GPIO_MAX7301 | |||
| 636 | 636 | ||
| 637 | config GPIO_MCP23S08 | 637 | config GPIO_MCP23S08 |
| 638 | tristate "Microchip MCP23xxx I/O expander" | 638 | tristate "Microchip MCP23xxx I/O expander" |
| 639 | depends on SPI_MASTER || I2C | 639 | depends on (SPI_MASTER && !I2C) || I2C |
| 640 | help | 640 | help |
| 641 | SPI/I2C driver for Microchip MCP23S08/MCP23S17/MCP23008/MCP23017 | 641 | SPI/I2C driver for Microchip MCP23S08/MCP23S17/MCP23008/MCP23017 |
| 642 | I/O expanders. | 642 | I/O expanders. |
diff --git a/drivers/gpio/gpio-langwell.c b/drivers/gpio/gpio-langwell.c index 634c3d37f7b5..62ef10a641c4 100644 --- a/drivers/gpio/gpio-langwell.c +++ b/drivers/gpio/gpio-langwell.c | |||
| @@ -324,6 +324,7 @@ static int lnw_gpio_probe(struct pci_dev *pdev, | |||
| 324 | resource_size_t start, len; | 324 | resource_size_t start, len; |
| 325 | struct lnw_gpio *lnw; | 325 | struct lnw_gpio *lnw; |
| 326 | u32 gpio_base; | 326 | u32 gpio_base; |
| 327 | u32 irq_base; | ||
| 327 | int retval; | 328 | int retval; |
| 328 | int ngpio = id->driver_data; | 329 | int ngpio = id->driver_data; |
| 329 | 330 | ||
| @@ -345,6 +346,7 @@ static int lnw_gpio_probe(struct pci_dev *pdev, | |||
| 345 | retval = -EFAULT; | 346 | retval = -EFAULT; |
| 346 | goto err_ioremap; | 347 | goto err_ioremap; |
| 347 | } | 348 | } |
| 349 | irq_base = *(u32 *)base; | ||
| 348 | gpio_base = *((u32 *)base + 1); | 350 | gpio_base = *((u32 *)base + 1); |
| 349 | /* release the IO mapping, since we already get the info from bar1 */ | 351 | /* release the IO mapping, since we already get the info from bar1 */ |
| 350 | iounmap(base); | 352 | iounmap(base); |
| @@ -365,13 +367,6 @@ static int lnw_gpio_probe(struct pci_dev *pdev, | |||
| 365 | goto err_ioremap; | 367 | goto err_ioremap; |
| 366 | } | 368 | } |
| 367 | 369 | ||
| 368 | lnw->domain = irq_domain_add_linear(pdev->dev.of_node, ngpio, | ||
| 369 | &lnw_gpio_irq_ops, lnw); | ||
| 370 | if (!lnw->domain) { | ||
| 371 | retval = -ENOMEM; | ||
| 372 | goto err_ioremap; | ||
| 373 | } | ||
| 374 | |||
| 375 | lnw->reg_base = base; | 370 | lnw->reg_base = base; |
| 376 | lnw->chip.label = dev_name(&pdev->dev); | 371 | lnw->chip.label = dev_name(&pdev->dev); |
| 377 | lnw->chip.request = lnw_gpio_request; | 372 | lnw->chip.request = lnw_gpio_request; |
| @@ -384,6 +379,14 @@ static int lnw_gpio_probe(struct pci_dev *pdev, | |||
| 384 | lnw->chip.ngpio = ngpio; | 379 | lnw->chip.ngpio = ngpio; |
| 385 | lnw->chip.can_sleep = 0; | 380 | lnw->chip.can_sleep = 0; |
| 386 | lnw->pdev = pdev; | 381 | lnw->pdev = pdev; |
| 382 | |||
| 383 | lnw->domain = irq_domain_add_simple(pdev->dev.of_node, ngpio, irq_base, | ||
| 384 | &lnw_gpio_irq_ops, lnw); | ||
| 385 | if (!lnw->domain) { | ||
| 386 | retval = -ENOMEM; | ||
| 387 | goto err_ioremap; | ||
| 388 | } | ||
| 389 | |||
| 387 | pci_set_drvdata(pdev, lnw); | 390 | pci_set_drvdata(pdev, lnw); |
| 388 | retval = gpiochip_add(&lnw->chip); | 391 | retval = gpiochip_add(&lnw->chip); |
| 389 | if (retval) { | 392 | if (retval) { |
diff --git a/drivers/gpio/gpio-ml-ioh.c b/drivers/gpio/gpio-ml-ioh.c index b73366523fae..0966f2637ad2 100644 --- a/drivers/gpio/gpio-ml-ioh.c +++ b/drivers/gpio/gpio-ml-ioh.c | |||
| @@ -496,8 +496,7 @@ err_irq_alloc_descs: | |||
| 496 | err_gpiochip_add: | 496 | err_gpiochip_add: |
| 497 | while (--i >= 0) { | 497 | while (--i >= 0) { |
| 498 | chip--; | 498 | chip--; |
| 499 | ret = gpiochip_remove(&chip->gpio); | 499 | if (gpiochip_remove(&chip->gpio)) |
| 500 | if (ret) | ||
| 501 | dev_err(&pdev->dev, "Failed gpiochip_remove(%d)\n", i); | 500 | dev_err(&pdev->dev, "Failed gpiochip_remove(%d)\n", i); |
| 502 | } | 501 | } |
| 503 | kfree(chip_save); | 502 | kfree(chip_save); |
diff --git a/drivers/gpio/gpio-mxs.c b/drivers/gpio/gpio-mxs.c index 25000b0f8453..f8e6af20dfbf 100644 --- a/drivers/gpio/gpio-mxs.c +++ b/drivers/gpio/gpio-mxs.c | |||
| @@ -326,7 +326,8 @@ static int mxs_gpio_probe(struct platform_device *pdev) | |||
| 326 | 326 | ||
| 327 | err = bgpio_init(&port->bgc, &pdev->dev, 4, | 327 | err = bgpio_init(&port->bgc, &pdev->dev, 4, |
| 328 | port->base + PINCTRL_DIN(port), | 328 | port->base + PINCTRL_DIN(port), |
| 329 | port->base + PINCTRL_DOUT(port), NULL, | 329 | port->base + PINCTRL_DOUT(port) + MXS_SET, |
| 330 | port->base + PINCTRL_DOUT(port) + MXS_CLR, | ||
| 330 | port->base + PINCTRL_DOE(port), NULL, 0); | 331 | port->base + PINCTRL_DOE(port), NULL, 0); |
| 331 | if (err) | 332 | if (err) |
| 332 | goto out_irqdesc_free; | 333 | goto out_irqdesc_free; |
diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index 2050891d9c65..d3f7d2db870f 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c | |||
| @@ -69,6 +69,7 @@ struct gpio_bank { | |||
| 69 | bool is_mpuio; | 69 | bool is_mpuio; |
| 70 | bool dbck_flag; | 70 | bool dbck_flag; |
| 71 | bool loses_context; | 71 | bool loses_context; |
| 72 | bool context_valid; | ||
| 72 | int stride; | 73 | int stride; |
| 73 | u32 width; | 74 | u32 width; |
| 74 | int context_loss_count; | 75 | int context_loss_count; |
| @@ -1128,6 +1129,10 @@ static int omap_gpio_probe(struct platform_device *pdev) | |||
| 1128 | bank->loses_context = true; | 1129 | bank->loses_context = true; |
| 1129 | } else { | 1130 | } else { |
| 1130 | bank->loses_context = pdata->loses_context; | 1131 | bank->loses_context = pdata->loses_context; |
| 1132 | |||
| 1133 | if (bank->loses_context) | ||
| 1134 | bank->get_context_loss_count = | ||
| 1135 | pdata->get_context_loss_count; | ||
| 1131 | } | 1136 | } |
| 1132 | 1137 | ||
| 1133 | 1138 | ||
| @@ -1178,9 +1183,6 @@ static int omap_gpio_probe(struct platform_device *pdev) | |||
| 1178 | omap_gpio_chip_init(bank); | 1183 | omap_gpio_chip_init(bank); |
| 1179 | omap_gpio_show_rev(bank); | 1184 | omap_gpio_show_rev(bank); |
| 1180 | 1185 | ||
| 1181 | if (bank->loses_context) | ||
| 1182 | bank->get_context_loss_count = pdata->get_context_loss_count; | ||
| 1183 | |||
| 1184 | pm_runtime_put(bank->dev); | 1186 | pm_runtime_put(bank->dev); |
| 1185 | 1187 | ||
| 1186 | list_add_tail(&bank->node, &omap_gpio_list); | 1188 | list_add_tail(&bank->node, &omap_gpio_list); |
| @@ -1259,6 +1261,8 @@ update_gpio_context_count: | |||
| 1259 | return 0; | 1261 | return 0; |
| 1260 | } | 1262 | } |
| 1261 | 1263 | ||
| 1264 | static void omap_gpio_init_context(struct gpio_bank *p); | ||
| 1265 | |||
| 1262 | static int omap_gpio_runtime_resume(struct device *dev) | 1266 | static int omap_gpio_runtime_resume(struct device *dev) |
| 1263 | { | 1267 | { |
| 1264 | struct platform_device *pdev = to_platform_device(dev); | 1268 | struct platform_device *pdev = to_platform_device(dev); |
| @@ -1268,6 +1272,20 @@ static int omap_gpio_runtime_resume(struct device *dev) | |||
| 1268 | int c; | 1272 | int c; |
| 1269 | 1273 | ||
| 1270 | spin_lock_irqsave(&bank->lock, flags); | 1274 | spin_lock_irqsave(&bank->lock, flags); |
| 1275 | |||
| 1276 | /* | ||
| 1277 | * On the first resume during the probe, the context has not | ||
| 1278 | * been initialised and so initialise it now. Also initialise | ||
| 1279 | * the context loss count. | ||
| 1280 | */ | ||
| 1281 | if (bank->loses_context && !bank->context_valid) { | ||
| 1282 | omap_gpio_init_context(bank); | ||
| 1283 | |||
| 1284 | if (bank->get_context_loss_count) | ||
| 1285 | bank->context_loss_count = | ||
| 1286 | bank->get_context_loss_count(bank->dev); | ||
| 1287 | } | ||
| 1288 | |||
| 1271 | _gpio_dbck_enable(bank); | 1289 | _gpio_dbck_enable(bank); |
| 1272 | 1290 | ||
| 1273 | /* | 1291 | /* |
| @@ -1384,6 +1402,29 @@ void omap2_gpio_resume_after_idle(void) | |||
| 1384 | } | 1402 | } |
| 1385 | 1403 | ||
| 1386 | #if defined(CONFIG_PM_RUNTIME) | 1404 | #if defined(CONFIG_PM_RUNTIME) |
| 1405 | static void omap_gpio_init_context(struct gpio_bank *p) | ||
| 1406 | { | ||
| 1407 | struct omap_gpio_reg_offs *regs = p->regs; | ||
| 1408 | void __iomem *base = p->base; | ||
| 1409 | |||
| 1410 | p->context.ctrl = __raw_readl(base + regs->ctrl); | ||
| 1411 | p->context.oe = __raw_readl(base + regs->direction); | ||
| 1412 | p->context.wake_en = __raw_readl(base + regs->wkup_en); | ||
| 1413 | p->context.leveldetect0 = __raw_readl(base + regs->leveldetect0); | ||
| 1414 | p->context.leveldetect1 = __raw_readl(base + regs->leveldetect1); | ||
| 1415 | p->context.risingdetect = __raw_readl(base + regs->risingdetect); | ||
| 1416 | p->context.fallingdetect = __raw_readl(base + regs->fallingdetect); | ||
| 1417 | p->context.irqenable1 = __raw_readl(base + regs->irqenable); | ||
| 1418 | p->context.irqenable2 = __raw_readl(base + regs->irqenable2); | ||
| 1419 | |||
| 1420 | if (regs->set_dataout && p->regs->clr_dataout) | ||
| 1421 | p->context.dataout = __raw_readl(base + regs->set_dataout); | ||
| 1422 | else | ||
| 1423 | p->context.dataout = __raw_readl(base + regs->dataout); | ||
| 1424 | |||
| 1425 | p->context_valid = true; | ||
| 1426 | } | ||
| 1427 | |||
| 1387 | static void omap_gpio_restore_context(struct gpio_bank *bank) | 1428 | static void omap_gpio_restore_context(struct gpio_bank *bank) |
| 1388 | { | 1429 | { |
| 1389 | __raw_writel(bank->context.wake_en, | 1430 | __raw_writel(bank->context.wake_en, |
| @@ -1421,6 +1462,7 @@ static void omap_gpio_restore_context(struct gpio_bank *bank) | |||
| 1421 | #else | 1462 | #else |
| 1422 | #define omap_gpio_runtime_suspend NULL | 1463 | #define omap_gpio_runtime_suspend NULL |
| 1423 | #define omap_gpio_runtime_resume NULL | 1464 | #define omap_gpio_runtime_resume NULL |
| 1465 | static void omap_gpio_init_context(struct gpio_bank *p) {} | ||
| 1424 | #endif | 1466 | #endif |
| 1425 | 1467 | ||
| 1426 | static const struct dev_pm_ops gpio_pm_ops = { | 1468 | static const struct dev_pm_ops gpio_pm_ops = { |
diff --git a/drivers/gpio/gpio-pch.c b/drivers/gpio/gpio-pch.c index cdf599687cf7..0fec097e838d 100644 --- a/drivers/gpio/gpio-pch.c +++ b/drivers/gpio/gpio-pch.c | |||
| @@ -424,8 +424,7 @@ end: | |||
| 424 | err_request_irq: | 424 | err_request_irq: |
| 425 | irq_free_descs(irq_base, gpio_pins[chip->ioh]); | 425 | irq_free_descs(irq_base, gpio_pins[chip->ioh]); |
| 426 | 426 | ||
| 427 | ret = gpiochip_remove(&chip->gpio); | 427 | if (gpiochip_remove(&chip->gpio)) |
| 428 | if (ret) | ||
| 429 | dev_err(&pdev->dev, "%s gpiochip_remove failed\n", __func__); | 428 | dev_err(&pdev->dev, "%s gpiochip_remove failed\n", __func__); |
| 430 | 429 | ||
| 431 | err_gpiochip_add: | 430 | err_gpiochip_add: |
diff --git a/drivers/gpio/gpio-sch.c b/drivers/gpio/gpio-sch.c index 1e4de16ceb41..5af65719b95d 100644 --- a/drivers/gpio/gpio-sch.c +++ b/drivers/gpio/gpio-sch.c | |||
| @@ -272,10 +272,8 @@ static int sch_gpio_probe(struct platform_device *pdev) | |||
| 272 | return 0; | 272 | return 0; |
| 273 | 273 | ||
| 274 | err_sch_gpio_resume: | 274 | err_sch_gpio_resume: |
| 275 | err = gpiochip_remove(&sch_gpio_core); | 275 | if (gpiochip_remove(&sch_gpio_core)) |
| 276 | if (err) | 276 | dev_err(&pdev->dev, "%s gpiochip_remove failed\n", __func__); |
| 277 | dev_err(&pdev->dev, "%s failed, %d\n", | ||
| 278 | "gpiochip_remove()", err); | ||
| 279 | 277 | ||
| 280 | err_sch_gpio_core: | 278 | err_sch_gpio_core: |
| 281 | release_region(res->start, resource_size(res)); | 279 | release_region(res->start, resource_size(res)); |
diff --git a/drivers/gpio/gpio-viperboard.c b/drivers/gpio/gpio-viperboard.c index 095ab14cea4d..5ac2919197fe 100644 --- a/drivers/gpio/gpio-viperboard.c +++ b/drivers/gpio/gpio-viperboard.c | |||
| @@ -446,7 +446,8 @@ static int vprbrd_gpio_probe(struct platform_device *pdev) | |||
| 446 | return ret; | 446 | return ret; |
| 447 | 447 | ||
| 448 | err_gpiob: | 448 | err_gpiob: |
| 449 | ret = gpiochip_remove(&vb_gpio->gpioa); | 449 | if (gpiochip_remove(&vb_gpio->gpioa)) |
| 450 | dev_err(&pdev->dev, "%s gpiochip_remove failed\n", __func__); | ||
| 450 | 451 | ||
| 451 | err_gpioa: | 452 | err_gpioa: |
| 452 | return ret; | 453 | return ret; |
