diff options
Diffstat (limited to 'drivers/gpio')
-rw-r--r-- | drivers/gpio/Kconfig | 1 | ||||
-rw-r--r-- | drivers/gpio/gpio-langwell.c | 50 |
2 files changed, 30 insertions, 21 deletions
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 7875c3f93662..8ee6d29c3714 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig | |||
@@ -404,6 +404,7 @@ config GPIO_BT8XX | |||
404 | config GPIO_LANGWELL | 404 | config GPIO_LANGWELL |
405 | bool "Intel Langwell/Penwell GPIO support" | 405 | bool "Intel Langwell/Penwell GPIO support" |
406 | depends on PCI && X86 | 406 | depends on PCI && X86 |
407 | select IRQ_DOMAIN | ||
407 | help | 408 | help |
408 | Say Y here to support Intel Langwell/Penwell GPIO. | 409 | Say Y here to support Intel Langwell/Penwell GPIO. |
409 | 410 | ||
diff --git a/drivers/gpio/gpio-langwell.c b/drivers/gpio/gpio-langwell.c index 52f00d3cf667..b0673574dc70 100644 --- a/drivers/gpio/gpio-langwell.c +++ b/drivers/gpio/gpio-langwell.c | |||
@@ -36,6 +36,7 @@ | |||
36 | #include <linux/gpio.h> | 36 | #include <linux/gpio.h> |
37 | #include <linux/slab.h> | 37 | #include <linux/slab.h> |
38 | #include <linux/pm_runtime.h> | 38 | #include <linux/pm_runtime.h> |
39 | #include <linux/irqdomain.h> | ||
39 | 40 | ||
40 | /* | 41 | /* |
41 | * Langwell chip has 64 pins and thus there are 2 32bit registers to control | 42 | * Langwell chip has 64 pins and thus there are 2 32bit registers to control |
@@ -66,8 +67,8 @@ struct lnw_gpio { | |||
66 | struct gpio_chip chip; | 67 | struct gpio_chip chip; |
67 | void *reg_base; | 68 | void *reg_base; |
68 | spinlock_t lock; | 69 | spinlock_t lock; |
69 | unsigned irq_base; | ||
70 | struct pci_dev *pdev; | 70 | struct pci_dev *pdev; |
71 | struct irq_domain *domain; | ||
71 | }; | 72 | }; |
72 | 73 | ||
73 | static void __iomem *gpio_reg(struct gpio_chip *chip, unsigned offset, | 74 | static void __iomem *gpio_reg(struct gpio_chip *chip, unsigned offset, |
@@ -176,13 +177,13 @@ static int lnw_gpio_direction_output(struct gpio_chip *chip, | |||
176 | static int lnw_gpio_to_irq(struct gpio_chip *chip, unsigned offset) | 177 | static int lnw_gpio_to_irq(struct gpio_chip *chip, unsigned offset) |
177 | { | 178 | { |
178 | struct lnw_gpio *lnw = container_of(chip, struct lnw_gpio, chip); | 179 | struct lnw_gpio *lnw = container_of(chip, struct lnw_gpio, chip); |
179 | return lnw->irq_base + offset; | 180 | return irq_create_mapping(lnw->domain, offset); |
180 | } | 181 | } |
181 | 182 | ||
182 | static int lnw_irq_type(struct irq_data *d, unsigned type) | 183 | static int lnw_irq_type(struct irq_data *d, unsigned type) |
183 | { | 184 | { |
184 | struct lnw_gpio *lnw = irq_data_get_irq_chip_data(d); | 185 | struct lnw_gpio *lnw = irq_data_get_irq_chip_data(d); |
185 | u32 gpio = d->irq - lnw->irq_base; | 186 | u32 gpio = irqd_to_hwirq(d); |
186 | unsigned long flags; | 187 | unsigned long flags; |
187 | u32 value; | 188 | u32 value; |
188 | void __iomem *grer = gpio_reg(&lnw->chip, gpio, GRER); | 189 | void __iomem *grer = gpio_reg(&lnw->chip, gpio, GRER); |
@@ -256,7 +257,8 @@ static void lnw_irq_handler(unsigned irq, struct irq_desc *desc) | |||
256 | pending &= ~mask; | 257 | pending &= ~mask; |
257 | /* Clear before handling so we can't lose an edge */ | 258 | /* Clear before handling so we can't lose an edge */ |
258 | writel(mask, gedr); | 259 | writel(mask, gedr); |
259 | generic_handle_irq(lnw->irq_base + base + gpio); | 260 | generic_handle_irq(irq_find_mapping(lnw->domain, |
261 | base + gpio)); | ||
260 | } | 262 | } |
261 | } | 263 | } |
262 | 264 | ||
@@ -281,6 +283,24 @@ static void lnw_irq_init_hw(struct lnw_gpio *lnw) | |||
281 | } | 283 | } |
282 | } | 284 | } |
283 | 285 | ||
286 | static int lnw_gpio_irq_map(struct irq_domain *d, unsigned int virq, | ||
287 | irq_hw_number_t hw) | ||
288 | { | ||
289 | struct lnw_gpio *lnw = d->host_data; | ||
290 | |||
291 | irq_set_chip_and_handler_name(virq, &lnw_irqchip, handle_simple_irq, | ||
292 | "demux"); | ||
293 | irq_set_chip_data(virq, lnw); | ||
294 | irq_set_irq_type(virq, IRQ_TYPE_NONE); | ||
295 | |||
296 | return 0; | ||
297 | } | ||
298 | |||
299 | static const struct irq_domain_ops lnw_gpio_irq_ops = { | ||
300 | .map = lnw_gpio_irq_map, | ||
301 | .xlate = irq_domain_xlate_twocell, | ||
302 | }; | ||
303 | |||
284 | #ifdef CONFIG_PM | 304 | #ifdef CONFIG_PM |
285 | static int lnw_gpio_runtime_resume(struct device *dev) | 305 | static int lnw_gpio_runtime_resume(struct device *dev) |
286 | { | 306 | { |
@@ -318,10 +338,8 @@ static int __devinit lnw_gpio_probe(struct pci_dev *pdev, | |||
318 | const struct pci_device_id *id) | 338 | const struct pci_device_id *id) |
319 | { | 339 | { |
320 | void *base; | 340 | void *base; |
321 | int i; | ||
322 | resource_size_t start, len; | 341 | resource_size_t start, len; |
323 | struct lnw_gpio *lnw; | 342 | struct lnw_gpio *lnw; |
324 | u32 irq_base; | ||
325 | u32 gpio_base; | 343 | u32 gpio_base; |
326 | int retval = 0; | 344 | int retval = 0; |
327 | int ngpio = id->driver_data; | 345 | int ngpio = id->driver_data; |
@@ -335,7 +353,7 @@ static int __devinit lnw_gpio_probe(struct pci_dev *pdev, | |||
335 | dev_err(&pdev->dev, "error requesting resources\n"); | 353 | dev_err(&pdev->dev, "error requesting resources\n"); |
336 | goto err2; | 354 | goto err2; |
337 | } | 355 | } |
338 | /* get the irq_base from bar1 */ | 356 | /* get the gpio_base from bar1 */ |
339 | start = pci_resource_start(pdev, 1); | 357 | start = pci_resource_start(pdev, 1); |
340 | len = pci_resource_len(pdev, 1); | 358 | len = pci_resource_len(pdev, 1); |
341 | base = ioremap_nocache(start, len); | 359 | base = ioremap_nocache(start, len); |
@@ -343,7 +361,6 @@ static int __devinit lnw_gpio_probe(struct pci_dev *pdev, | |||
343 | dev_err(&pdev->dev, "error mapping bar1\n"); | 361 | dev_err(&pdev->dev, "error mapping bar1\n"); |
344 | goto err3; | 362 | goto err3; |
345 | } | 363 | } |
346 | irq_base = *(u32 *)base; | ||
347 | gpio_base = *((u32 *)base + 1); | 364 | gpio_base = *((u32 *)base + 1); |
348 | /* release the IO mapping, since we already get the info from bar1 */ | 365 | /* release the IO mapping, since we already get the info from bar1 */ |
349 | iounmap(base); | 366 | iounmap(base); |
@@ -364,12 +381,10 @@ static int __devinit lnw_gpio_probe(struct pci_dev *pdev, | |||
364 | goto err3; | 381 | goto err3; |
365 | } | 382 | } |
366 | 383 | ||
367 | retval = irq_alloc_descs(-1, irq_base, ngpio, 0); | 384 | lnw->domain = irq_domain_add_linear(pdev->dev.of_node, ngpio, |
368 | if (retval < 0) { | 385 | &lnw_gpio_irq_ops, lnw); |
369 | dev_err(&pdev->dev, "can't allocate IRQ descs\n"); | 386 | if (!lnw->domain) |
370 | goto err3; | 387 | goto err3; |
371 | } | ||
372 | lnw->irq_base = retval; | ||
373 | 388 | ||
374 | lnw->reg_base = base; | 389 | lnw->reg_base = base; |
375 | lnw->chip.label = dev_name(&pdev->dev); | 390 | lnw->chip.label = dev_name(&pdev->dev); |
@@ -387,18 +402,13 @@ static int __devinit lnw_gpio_probe(struct pci_dev *pdev, | |||
387 | retval = gpiochip_add(&lnw->chip); | 402 | retval = gpiochip_add(&lnw->chip); |
388 | if (retval) { | 403 | if (retval) { |
389 | dev_err(&pdev->dev, "langwell gpiochip_add error %d\n", retval); | 404 | dev_err(&pdev->dev, "langwell gpiochip_add error %d\n", retval); |
390 | goto err4; | 405 | goto err3; |
391 | } | 406 | } |
392 | 407 | ||
393 | lnw_irq_init_hw(lnw); | 408 | lnw_irq_init_hw(lnw); |
394 | 409 | ||
395 | irq_set_handler_data(pdev->irq, lnw); | 410 | irq_set_handler_data(pdev->irq, lnw); |
396 | irq_set_chained_handler(pdev->irq, lnw_irq_handler); | 411 | irq_set_chained_handler(pdev->irq, lnw_irq_handler); |
397 | for (i = 0; i < lnw->chip.ngpio; i++) { | ||
398 | irq_set_chip_and_handler_name(i + lnw->irq_base, &lnw_irqchip, | ||
399 | handle_simple_irq, "demux"); | ||
400 | irq_set_chip_data(i + lnw->irq_base, lnw); | ||
401 | } | ||
402 | 412 | ||
403 | spin_lock_init(&lnw->lock); | 413 | spin_lock_init(&lnw->lock); |
404 | 414 | ||
@@ -407,8 +417,6 @@ static int __devinit lnw_gpio_probe(struct pci_dev *pdev, | |||
407 | 417 | ||
408 | return 0; | 418 | return 0; |
409 | 419 | ||
410 | err4: | ||
411 | irq_free_descs(lnw->irq_base, ngpio); | ||
412 | err3: | 420 | err3: |
413 | pci_release_regions(pdev); | 421 | pci_release_regions(pdev); |
414 | err2: | 422 | err2: |