提交 514e250f 编写于 作者: L Linus Torvalds

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
...@@ -636,7 +636,7 @@ config GPIO_MAX7301 ...@@ -636,7 +636,7 @@ config GPIO_MAX7301
config GPIO_MCP23S08 config GPIO_MCP23S08
tristate "Microchip MCP23xxx I/O expander" tristate "Microchip MCP23xxx I/O expander"
depends on SPI_MASTER || I2C depends on (SPI_MASTER && !I2C) || I2C
help help
SPI/I2C driver for Microchip MCP23S08/MCP23S17/MCP23008/MCP23017 SPI/I2C driver for Microchip MCP23S08/MCP23S17/MCP23008/MCP23017
I/O expanders. I/O expanders.
......
...@@ -324,6 +324,7 @@ static int lnw_gpio_probe(struct pci_dev *pdev, ...@@ -324,6 +324,7 @@ static int lnw_gpio_probe(struct pci_dev *pdev,
resource_size_t start, len; resource_size_t start, len;
struct lnw_gpio *lnw; struct lnw_gpio *lnw;
u32 gpio_base; u32 gpio_base;
u32 irq_base;
int retval; int retval;
int ngpio = id->driver_data; int ngpio = id->driver_data;
...@@ -345,6 +346,7 @@ static int lnw_gpio_probe(struct pci_dev *pdev, ...@@ -345,6 +346,7 @@ static int lnw_gpio_probe(struct pci_dev *pdev,
retval = -EFAULT; retval = -EFAULT;
goto err_ioremap; goto err_ioremap;
} }
irq_base = *(u32 *)base;
gpio_base = *((u32 *)base + 1); gpio_base = *((u32 *)base + 1);
/* release the IO mapping, since we already get the info from bar1 */ /* release the IO mapping, since we already get the info from bar1 */
iounmap(base); iounmap(base);
...@@ -365,13 +367,6 @@ static int lnw_gpio_probe(struct pci_dev *pdev, ...@@ -365,13 +367,6 @@ static int lnw_gpio_probe(struct pci_dev *pdev,
goto err_ioremap; goto err_ioremap;
} }
lnw->domain = irq_domain_add_linear(pdev->dev.of_node, ngpio,
&lnw_gpio_irq_ops, lnw);
if (!lnw->domain) {
retval = -ENOMEM;
goto err_ioremap;
}
lnw->reg_base = base; lnw->reg_base = base;
lnw->chip.label = dev_name(&pdev->dev); lnw->chip.label = dev_name(&pdev->dev);
lnw->chip.request = lnw_gpio_request; lnw->chip.request = lnw_gpio_request;
...@@ -384,6 +379,14 @@ static int lnw_gpio_probe(struct pci_dev *pdev, ...@@ -384,6 +379,14 @@ static int lnw_gpio_probe(struct pci_dev *pdev,
lnw->chip.ngpio = ngpio; lnw->chip.ngpio = ngpio;
lnw->chip.can_sleep = 0; lnw->chip.can_sleep = 0;
lnw->pdev = pdev; lnw->pdev = pdev;
lnw->domain = irq_domain_add_simple(pdev->dev.of_node, ngpio, irq_base,
&lnw_gpio_irq_ops, lnw);
if (!lnw->domain) {
retval = -ENOMEM;
goto err_ioremap;
}
pci_set_drvdata(pdev, lnw); pci_set_drvdata(pdev, lnw);
retval = gpiochip_add(&lnw->chip); retval = gpiochip_add(&lnw->chip);
if (retval) { if (retval) {
......
...@@ -496,8 +496,7 @@ static int ioh_gpio_probe(struct pci_dev *pdev, ...@@ -496,8 +496,7 @@ static int ioh_gpio_probe(struct pci_dev *pdev,
err_gpiochip_add: err_gpiochip_add:
while (--i >= 0) { while (--i >= 0) {
chip--; chip--;
ret = gpiochip_remove(&chip->gpio); if (gpiochip_remove(&chip->gpio))
if (ret)
dev_err(&pdev->dev, "Failed gpiochip_remove(%d)\n", i); dev_err(&pdev->dev, "Failed gpiochip_remove(%d)\n", i);
} }
kfree(chip_save); kfree(chip_save);
......
...@@ -326,7 +326,8 @@ static int mxs_gpio_probe(struct platform_device *pdev) ...@@ -326,7 +326,8 @@ static int mxs_gpio_probe(struct platform_device *pdev)
err = bgpio_init(&port->bgc, &pdev->dev, 4, err = bgpio_init(&port->bgc, &pdev->dev, 4,
port->base + PINCTRL_DIN(port), port->base + PINCTRL_DIN(port),
port->base + PINCTRL_DOUT(port), NULL, port->base + PINCTRL_DOUT(port) + MXS_SET,
port->base + PINCTRL_DOUT(port) + MXS_CLR,
port->base + PINCTRL_DOE(port), NULL, 0); port->base + PINCTRL_DOE(port), NULL, 0);
if (err) if (err)
goto out_irqdesc_free; goto out_irqdesc_free;
......
...@@ -69,6 +69,7 @@ struct gpio_bank { ...@@ -69,6 +69,7 @@ struct gpio_bank {
bool is_mpuio; bool is_mpuio;
bool dbck_flag; bool dbck_flag;
bool loses_context; bool loses_context;
bool context_valid;
int stride; int stride;
u32 width; u32 width;
int context_loss_count; int context_loss_count;
...@@ -1128,6 +1129,10 @@ static int omap_gpio_probe(struct platform_device *pdev) ...@@ -1128,6 +1129,10 @@ static int omap_gpio_probe(struct platform_device *pdev)
bank->loses_context = true; bank->loses_context = true;
} else { } else {
bank->loses_context = pdata->loses_context; bank->loses_context = pdata->loses_context;
if (bank->loses_context)
bank->get_context_loss_count =
pdata->get_context_loss_count;
} }
...@@ -1178,9 +1183,6 @@ static int omap_gpio_probe(struct platform_device *pdev) ...@@ -1178,9 +1183,6 @@ static int omap_gpio_probe(struct platform_device *pdev)
omap_gpio_chip_init(bank); omap_gpio_chip_init(bank);
omap_gpio_show_rev(bank); omap_gpio_show_rev(bank);
if (bank->loses_context)
bank->get_context_loss_count = pdata->get_context_loss_count;
pm_runtime_put(bank->dev); pm_runtime_put(bank->dev);
list_add_tail(&bank->node, &omap_gpio_list); list_add_tail(&bank->node, &omap_gpio_list);
...@@ -1259,6 +1261,8 @@ static int omap_gpio_runtime_suspend(struct device *dev) ...@@ -1259,6 +1261,8 @@ static int omap_gpio_runtime_suspend(struct device *dev)
return 0; return 0;
} }
static void omap_gpio_init_context(struct gpio_bank *p);
static int omap_gpio_runtime_resume(struct device *dev) static int omap_gpio_runtime_resume(struct device *dev)
{ {
struct platform_device *pdev = to_platform_device(dev); struct platform_device *pdev = to_platform_device(dev);
...@@ -1268,6 +1272,20 @@ static int omap_gpio_runtime_resume(struct device *dev) ...@@ -1268,6 +1272,20 @@ static int omap_gpio_runtime_resume(struct device *dev)
int c; int c;
spin_lock_irqsave(&bank->lock, flags); spin_lock_irqsave(&bank->lock, flags);
/*
* On the first resume during the probe, the context has not
* been initialised and so initialise it now. Also initialise
* the context loss count.
*/
if (bank->loses_context && !bank->context_valid) {
omap_gpio_init_context(bank);
if (bank->get_context_loss_count)
bank->context_loss_count =
bank->get_context_loss_count(bank->dev);
}
_gpio_dbck_enable(bank); _gpio_dbck_enable(bank);
/* /*
...@@ -1384,6 +1402,29 @@ void omap2_gpio_resume_after_idle(void) ...@@ -1384,6 +1402,29 @@ void omap2_gpio_resume_after_idle(void)
} }
#if defined(CONFIG_PM_RUNTIME) #if defined(CONFIG_PM_RUNTIME)
static void omap_gpio_init_context(struct gpio_bank *p)
{
struct omap_gpio_reg_offs *regs = p->regs;
void __iomem *base = p->base;
p->context.ctrl = __raw_readl(base + regs->ctrl);
p->context.oe = __raw_readl(base + regs->direction);
p->context.wake_en = __raw_readl(base + regs->wkup_en);
p->context.leveldetect0 = __raw_readl(base + regs->leveldetect0);
p->context.leveldetect1 = __raw_readl(base + regs->leveldetect1);
p->context.risingdetect = __raw_readl(base + regs->risingdetect);
p->context.fallingdetect = __raw_readl(base + regs->fallingdetect);
p->context.irqenable1 = __raw_readl(base + regs->irqenable);
p->context.irqenable2 = __raw_readl(base + regs->irqenable2);
if (regs->set_dataout && p->regs->clr_dataout)
p->context.dataout = __raw_readl(base + regs->set_dataout);
else
p->context.dataout = __raw_readl(base + regs->dataout);
p->context_valid = true;
}
static void omap_gpio_restore_context(struct gpio_bank *bank) static void omap_gpio_restore_context(struct gpio_bank *bank)
{ {
__raw_writel(bank->context.wake_en, __raw_writel(bank->context.wake_en,
...@@ -1421,6 +1462,7 @@ static void omap_gpio_restore_context(struct gpio_bank *bank) ...@@ -1421,6 +1462,7 @@ static void omap_gpio_restore_context(struct gpio_bank *bank)
#else #else
#define omap_gpio_runtime_suspend NULL #define omap_gpio_runtime_suspend NULL
#define omap_gpio_runtime_resume NULL #define omap_gpio_runtime_resume NULL
static void omap_gpio_init_context(struct gpio_bank *p) {}
#endif #endif
static const struct dev_pm_ops gpio_pm_ops = { static const struct dev_pm_ops gpio_pm_ops = {
......
...@@ -424,8 +424,7 @@ static int pch_gpio_probe(struct pci_dev *pdev, ...@@ -424,8 +424,7 @@ static int pch_gpio_probe(struct pci_dev *pdev,
err_request_irq: err_request_irq:
irq_free_descs(irq_base, gpio_pins[chip->ioh]); irq_free_descs(irq_base, gpio_pins[chip->ioh]);
ret = gpiochip_remove(&chip->gpio); if (gpiochip_remove(&chip->gpio))
if (ret)
dev_err(&pdev->dev, "%s gpiochip_remove failed\n", __func__); dev_err(&pdev->dev, "%s gpiochip_remove failed\n", __func__);
err_gpiochip_add: err_gpiochip_add:
......
...@@ -272,10 +272,8 @@ static int sch_gpio_probe(struct platform_device *pdev) ...@@ -272,10 +272,8 @@ static int sch_gpio_probe(struct platform_device *pdev)
return 0; return 0;
err_sch_gpio_resume: err_sch_gpio_resume:
err = gpiochip_remove(&sch_gpio_core); if (gpiochip_remove(&sch_gpio_core))
if (err) dev_err(&pdev->dev, "%s gpiochip_remove failed\n", __func__);
dev_err(&pdev->dev, "%s failed, %d\n",
"gpiochip_remove()", err);
err_sch_gpio_core: err_sch_gpio_core:
release_region(res->start, resource_size(res)); release_region(res->start, resource_size(res));
......
...@@ -446,7 +446,8 @@ static int vprbrd_gpio_probe(struct platform_device *pdev) ...@@ -446,7 +446,8 @@ static int vprbrd_gpio_probe(struct platform_device *pdev)
return ret; return ret;
err_gpiob: err_gpiob:
ret = gpiochip_remove(&vb_gpio->gpioa); if (gpiochip_remove(&vb_gpio->gpioa))
dev_err(&pdev->dev, "%s gpiochip_remove failed\n", __func__);
err_gpioa: err_gpioa:
return ret; return ret;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册