diff options
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/gpio/Kconfig | 2 | ||||
| -rw-r--r-- | drivers/gpio/gpio-lynxpoint.c | 93 |
2 files changed, 26 insertions, 69 deletions
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 345da63fb0ad..255e8f00910f 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig | |||
| @@ -430,7 +430,7 @@ config GPIO_GE_FPGA | |||
| 430 | config GPIO_LYNXPOINT | 430 | config GPIO_LYNXPOINT |
| 431 | tristate "Intel Lynxpoint GPIO support" | 431 | tristate "Intel Lynxpoint GPIO support" |
| 432 | depends on ACPI && X86 | 432 | depends on ACPI && X86 |
| 433 | select IRQ_DOMAIN | 433 | select GPIOLIB_IRQCHIP |
| 434 | help | 434 | help |
| 435 | driver for GPIO functionality on Intel Lynxpoint PCH chipset | 435 | driver for GPIO functionality on Intel Lynxpoint PCH chipset |
| 436 | Requires ACPI device enumeration code to set up a platform device. | 436 | Requires ACPI device enumeration code to set up a platform device. |
diff --git a/drivers/gpio/gpio-lynxpoint.c b/drivers/gpio/gpio-lynxpoint.c index 7c141dd850a1..ff9eb911b5e4 100644 --- a/drivers/gpio/gpio-lynxpoint.c +++ b/drivers/gpio/gpio-lynxpoint.c | |||
| @@ -25,9 +25,7 @@ | |||
| 25 | #include <linux/types.h> | 25 | #include <linux/types.h> |
| 26 | #include <linux/bitops.h> | 26 | #include <linux/bitops.h> |
| 27 | #include <linux/interrupt.h> | 27 | #include <linux/interrupt.h> |
| 28 | #include <linux/irq.h> | ||
| 29 | #include <linux/gpio.h> | 28 | #include <linux/gpio.h> |
| 30 | #include <linux/irqdomain.h> | ||
| 31 | #include <linux/slab.h> | 29 | #include <linux/slab.h> |
| 32 | #include <linux/acpi.h> | 30 | #include <linux/acpi.h> |
| 33 | #include <linux/platform_device.h> | 31 | #include <linux/platform_device.h> |
| @@ -62,7 +60,6 @@ | |||
| 62 | 60 | ||
| 63 | struct lp_gpio { | 61 | struct lp_gpio { |
| 64 | struct gpio_chip chip; | 62 | struct gpio_chip chip; |
| 65 | struct irq_domain *domain; | ||
| 66 | struct platform_device *pdev; | 63 | struct platform_device *pdev; |
| 67 | spinlock_t lock; | 64 | spinlock_t lock; |
| 68 | unsigned long reg_base; | 65 | unsigned long reg_base; |
| @@ -151,7 +148,8 @@ static void lp_gpio_free(struct gpio_chip *chip, unsigned offset) | |||
| 151 | 148 | ||
| 152 | static int lp_irq_type(struct irq_data *d, unsigned type) | 149 | static int lp_irq_type(struct irq_data *d, unsigned type) |
| 153 | { | 150 | { |
| 154 | struct lp_gpio *lg = irq_data_get_irq_chip_data(d); | 151 | struct gpio_chip *gc = irq_data_get_irq_chip_data(d); |
| 152 | struct lp_gpio *lg = container_of(gc, struct lp_gpio, chip); | ||
| 155 | u32 hwirq = irqd_to_hwirq(d); | 153 | u32 hwirq = irqd_to_hwirq(d); |
| 156 | unsigned long flags; | 154 | unsigned long flags; |
| 157 | u32 value; | 155 | u32 value; |
| @@ -236,16 +234,11 @@ static int lp_gpio_direction_output(struct gpio_chip *chip, | |||
| 236 | return 0; | 234 | return 0; |
| 237 | } | 235 | } |
| 238 | 236 | ||
| 239 | static int lp_gpio_to_irq(struct gpio_chip *chip, unsigned offset) | ||
| 240 | { | ||
| 241 | struct lp_gpio *lg = container_of(chip, struct lp_gpio, chip); | ||
| 242 | return irq_create_mapping(lg->domain, offset); | ||
| 243 | } | ||
| 244 | |||
| 245 | static void lp_gpio_irq_handler(unsigned hwirq, struct irq_desc *desc) | 237 | static void lp_gpio_irq_handler(unsigned hwirq, struct irq_desc *desc) |
| 246 | { | 238 | { |
| 247 | struct irq_data *data = irq_desc_get_irq_data(desc); | 239 | struct irq_data *data = irq_desc_get_irq_data(desc); |
| 248 | struct lp_gpio *lg = irq_data_get_irq_handler_data(data); | 240 | struct gpio_chip *gc = irq_desc_get_handler_data(desc); |
| 241 | struct lp_gpio *lg = container_of(gc, struct lp_gpio, chip); | ||
| 249 | struct irq_chip *chip = irq_data_get_irq_chip(data); | 242 | struct irq_chip *chip = irq_data_get_irq_chip(data); |
| 250 | u32 base, pin, mask; | 243 | u32 base, pin, mask; |
| 251 | unsigned long reg, ena, pending; | 244 | unsigned long reg, ena, pending; |
| @@ -262,7 +255,7 @@ static void lp_gpio_irq_handler(unsigned hwirq, struct irq_desc *desc) | |||
| 262 | mask = BIT(pin); | 255 | mask = BIT(pin); |
| 263 | /* Clear before handling so we don't lose an edge */ | 256 | /* Clear before handling so we don't lose an edge */ |
| 264 | outl(mask, reg); | 257 | outl(mask, reg); |
| 265 | irq = irq_find_mapping(lg->domain, base + pin); | 258 | irq = irq_find_mapping(lg->chip.irqdomain, base + pin); |
| 266 | generic_handle_irq(irq); | 259 | generic_handle_irq(irq); |
| 267 | } | 260 | } |
| 268 | } | 261 | } |
| @@ -279,7 +272,8 @@ static void lp_irq_mask(struct irq_data *d) | |||
| 279 | 272 | ||
| 280 | static void lp_irq_enable(struct irq_data *d) | 273 | static void lp_irq_enable(struct irq_data *d) |
| 281 | { | 274 | { |
| 282 | struct lp_gpio *lg = irq_data_get_irq_chip_data(d); | 275 | struct gpio_chip *gc = irq_data_get_irq_chip_data(d); |
| 276 | struct lp_gpio *lg = container_of(gc, struct lp_gpio, chip); | ||
| 283 | u32 hwirq = irqd_to_hwirq(d); | 277 | u32 hwirq = irqd_to_hwirq(d); |
| 284 | unsigned long reg = lp_gpio_reg(&lg->chip, hwirq, LP_INT_ENABLE); | 278 | unsigned long reg = lp_gpio_reg(&lg->chip, hwirq, LP_INT_ENABLE); |
| 285 | unsigned long flags; | 279 | unsigned long flags; |
| @@ -291,7 +285,8 @@ static void lp_irq_enable(struct irq_data *d) | |||
| 291 | 285 | ||
| 292 | static void lp_irq_disable(struct irq_data *d) | 286 | static void lp_irq_disable(struct irq_data *d) |
| 293 | { | 287 | { |
| 294 | struct lp_gpio *lg = irq_data_get_irq_chip_data(d); | 288 | struct gpio_chip *gc = irq_data_get_irq_chip_data(d); |
| 289 | struct lp_gpio *lg = container_of(gc, struct lp_gpio, chip); | ||
| 295 | u32 hwirq = irqd_to_hwirq(d); | 290 | u32 hwirq = irqd_to_hwirq(d); |
| 296 | unsigned long reg = lp_gpio_reg(&lg->chip, hwirq, LP_INT_ENABLE); | 291 | unsigned long reg = lp_gpio_reg(&lg->chip, hwirq, LP_INT_ENABLE); |
| 297 | unsigned long flags; | 292 | unsigned long flags; |
| @@ -301,26 +296,6 @@ static void lp_irq_disable(struct irq_data *d) | |||
| 301 | spin_unlock_irqrestore(&lg->lock, flags); | 296 | spin_unlock_irqrestore(&lg->lock, flags); |
| 302 | } | 297 | } |
| 303 | 298 | ||
| 304 | static int lp_irq_reqres(struct irq_data *d) | ||
| 305 | { | ||
| 306 | struct lp_gpio *lg = irq_data_get_irq_chip_data(d); | ||
| 307 | |||
| 308 | if (gpio_lock_as_irq(&lg->chip, irqd_to_hwirq(d))) { | ||
| 309 | dev_err(lg->chip.dev, | ||
| 310 | "unable to lock HW IRQ %lu for IRQ\n", | ||
| 311 | irqd_to_hwirq(d)); | ||
| 312 | return -EINVAL; | ||
| 313 | } | ||
| 314 | return 0; | ||
| 315 | } | ||
| 316 | |||
| 317 | static void lp_irq_relres(struct irq_data *d) | ||
| 318 | { | ||
| 319 | struct lp_gpio *lg = irq_data_get_irq_chip_data(d); | ||
| 320 | |||
| 321 | gpio_unlock_as_irq(&lg->chip, irqd_to_hwirq(d)); | ||
| 322 | } | ||
| 323 | |||
| 324 | static struct irq_chip lp_irqchip = { | 299 | static struct irq_chip lp_irqchip = { |
| 325 | .name = "LP-GPIO", | 300 | .name = "LP-GPIO", |
| 326 | .irq_mask = lp_irq_mask, | 301 | .irq_mask = lp_irq_mask, |
| @@ -328,8 +303,6 @@ static struct irq_chip lp_irqchip = { | |||
| 328 | .irq_enable = lp_irq_enable, | 303 | .irq_enable = lp_irq_enable, |
| 329 | .irq_disable = lp_irq_disable, | 304 | .irq_disable = lp_irq_disable, |
| 330 | .irq_set_type = lp_irq_type, | 305 | .irq_set_type = lp_irq_type, |
| 331 | .irq_request_resources = lp_irq_reqres, | ||
| 332 | .irq_release_resources = lp_irq_relres, | ||
| 333 | .flags = IRQCHIP_SKIP_SET_WAKE, | 306 | .flags = IRQCHIP_SKIP_SET_WAKE, |
| 334 | }; | 307 | }; |
| 335 | 308 | ||
| @@ -348,22 +321,6 @@ static void lp_gpio_irq_init_hw(struct lp_gpio *lg) | |||
| 348 | } | 321 | } |
| 349 | } | 322 | } |
| 350 | 323 | ||
| 351 | static int lp_gpio_irq_map(struct irq_domain *d, unsigned int irq, | ||
| 352 | irq_hw_number_t hwirq) | ||
| 353 | { | ||
| 354 | struct lp_gpio *lg = d->host_data; | ||
| 355 | |||
| 356 | irq_set_chip_and_handler(irq, &lp_irqchip, handle_simple_irq); | ||
| 357 | irq_set_chip_data(irq, lg); | ||
| 358 | irq_set_irq_type(irq, IRQ_TYPE_NONE); | ||
| 359 | |||
| 360 | return 0; | ||
| 361 | } | ||
| 362 | |||
| 363 | static const struct irq_domain_ops lp_gpio_irq_ops = { | ||
| 364 | .map = lp_gpio_irq_map, | ||
| 365 | }; | ||
| 366 | |||
| 367 | static int lp_gpio_probe(struct platform_device *pdev) | 324 | static int lp_gpio_probe(struct platform_device *pdev) |
| 368 | { | 325 | { |
| 369 | struct lp_gpio *lg; | 326 | struct lp_gpio *lg; |
| @@ -371,7 +328,6 @@ static int lp_gpio_probe(struct platform_device *pdev) | |||
| 371 | struct resource *io_rc, *irq_rc; | 328 | struct resource *io_rc, *irq_rc; |
| 372 | struct device *dev = &pdev->dev; | 329 | struct device *dev = &pdev->dev; |
| 373 | unsigned long reg_len; | 330 | unsigned long reg_len; |
| 374 | unsigned hwirq; | ||
| 375 | int ret = -ENODEV; | 331 | int ret = -ENODEV; |
| 376 | 332 | ||
| 377 | lg = devm_kzalloc(dev, sizeof(struct lp_gpio), GFP_KERNEL); | 333 | lg = devm_kzalloc(dev, sizeof(struct lp_gpio), GFP_KERNEL); |
| @@ -414,27 +370,28 @@ static int lp_gpio_probe(struct platform_device *pdev) | |||
| 414 | gc->can_sleep = false; | 370 | gc->can_sleep = false; |
| 415 | gc->dev = dev; | 371 | gc->dev = dev; |
| 416 | 372 | ||
| 373 | ret = gpiochip_add(gc); | ||
| 374 | if (ret) { | ||
| 375 | dev_err(dev, "failed adding lp-gpio chip\n"); | ||
| 376 | return ret; | ||
| 377 | } | ||
| 378 | |||
| 417 | /* set up interrupts */ | 379 | /* set up interrupts */ |
| 418 | if (irq_rc && irq_rc->start) { | 380 | if (irq_rc && irq_rc->start) { |
| 419 | hwirq = irq_rc->start; | ||
| 420 | gc->to_irq = lp_gpio_to_irq; | ||
| 421 | |||
| 422 | lg->domain = irq_domain_add_linear(NULL, LP_NUM_GPIO, | ||
| 423 | &lp_gpio_irq_ops, lg); | ||
| 424 | if (!lg->domain) | ||
| 425 | return -ENXIO; | ||
| 426 | |||
| 427 | lp_gpio_irq_init_hw(lg); | 381 | lp_gpio_irq_init_hw(lg); |
| 382 | ret = gpiochip_irqchip_add(gc, &lp_irqchip, 0, | ||
| 383 | handle_simple_irq, IRQ_TYPE_NONE); | ||
| 384 | if (ret) { | ||
| 385 | dev_err(dev, "failed to add irqchip\n"); | ||
| 386 | gpiochip_remove(gc); | ||
| 387 | return ret; | ||
| 388 | } | ||
| 428 | 389 | ||
| 429 | irq_set_handler_data(hwirq, lg); | 390 | gpiochip_set_chained_irqchip(gc, &lp_irqchip, |
| 430 | irq_set_chained_handler(hwirq, lp_gpio_irq_handler); | 391 | (unsigned)irq_rc->start, |
| 392 | lp_gpio_irq_handler); | ||
| 431 | } | 393 | } |
| 432 | 394 | ||
| 433 | ret = gpiochip_add(gc); | ||
| 434 | if (ret) { | ||
| 435 | dev_err(dev, "failed adding lp-gpio chip\n"); | ||
| 436 | return ret; | ||
| 437 | } | ||
| 438 | pm_runtime_enable(dev); | 395 | pm_runtime_enable(dev); |
| 439 | 396 | ||
| 440 | return 0; | 397 | return 0; |
