.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0 |
---|
1 | 2 | /* |
---|
2 | 3 | * Intel Merrifield SoC GPIO driver |
---|
3 | 4 | * |
---|
4 | 5 | * Copyright (c) 2016 Intel Corporation. |
---|
5 | 6 | * Author: Andy Shevchenko <andriy.shevchenko@linux.intel.com> |
---|
6 | | - * |
---|
7 | | - * This program is free software; you can redistribute it and/or modify |
---|
8 | | - * it under the terms of the GNU General Public License version 2 as |
---|
9 | | - * published by the Free Software Foundation. |
---|
10 | 7 | */ |
---|
11 | 8 | |
---|
12 | 9 | #include <linux/acpi.h> |
---|
13 | 10 | #include <linux/bitops.h> |
---|
14 | 11 | #include <linux/gpio/driver.h> |
---|
15 | | -#include <linux/init.h> |
---|
16 | 12 | #include <linux/interrupt.h> |
---|
17 | 13 | #include <linux/io.h> |
---|
18 | 14 | #include <linux/module.h> |
---|
.. | .. |
---|
166 | 162 | { |
---|
167 | 163 | void __iomem *gpdr = gpio_reg(chip, offset, GPDR); |
---|
168 | 164 | |
---|
169 | | - return !(readl(gpdr) & BIT(offset % 32)); |
---|
| 165 | + if (readl(gpdr) & BIT(offset % 32)) |
---|
| 166 | + return GPIO_LINE_DIRECTION_OUT; |
---|
| 167 | + |
---|
| 168 | + return GPIO_LINE_DIRECTION_IN; |
---|
170 | 169 | } |
---|
171 | 170 | |
---|
172 | 171 | static int mrfld_gpio_set_debounce(struct gpio_chip *chip, unsigned int offset, |
---|
.. | .. |
---|
366 | 365 | chained_irq_exit(irqchip, desc); |
---|
367 | 366 | } |
---|
368 | 367 | |
---|
369 | | -static void mrfld_irq_init_hw(struct mrfld_gpio *priv) |
---|
| 368 | +static int mrfld_irq_init_hw(struct gpio_chip *chip) |
---|
370 | 369 | { |
---|
| 370 | + struct mrfld_gpio *priv = gpiochip_get_data(chip); |
---|
371 | 371 | void __iomem *reg; |
---|
372 | 372 | unsigned int base; |
---|
373 | 373 | |
---|
.. | .. |
---|
379 | 379 | reg = gpio_reg(&priv->chip, base, GFER); |
---|
380 | 380 | writel(0, reg); |
---|
381 | 381 | } |
---|
| 382 | + |
---|
| 383 | + return 0; |
---|
382 | 384 | } |
---|
383 | 385 | |
---|
384 | | -static const char *mrfld_gpio_get_pinctrl_dev_name(void) |
---|
| 386 | +static const char *mrfld_gpio_get_pinctrl_dev_name(struct mrfld_gpio *priv) |
---|
385 | 387 | { |
---|
386 | | - const char *dev_name = acpi_dev_get_first_match_name("INTC1002", NULL, -1); |
---|
387 | | - return dev_name ? dev_name : "pinctrl-merrifield"; |
---|
| 388 | + struct acpi_device *adev; |
---|
| 389 | + const char *name; |
---|
| 390 | + |
---|
| 391 | + adev = acpi_dev_get_first_match_dev("INTC1002", NULL, -1); |
---|
| 392 | + if (adev) { |
---|
| 393 | + name = devm_kstrdup(priv->dev, acpi_dev_name(adev), GFP_KERNEL); |
---|
| 394 | + acpi_dev_put(adev); |
---|
| 395 | + } else { |
---|
| 396 | + name = "pinctrl-merrifield"; |
---|
| 397 | + } |
---|
| 398 | + |
---|
| 399 | + return name; |
---|
| 400 | +} |
---|
| 401 | + |
---|
| 402 | +static int mrfld_gpio_add_pin_ranges(struct gpio_chip *chip) |
---|
| 403 | +{ |
---|
| 404 | + struct mrfld_gpio *priv = gpiochip_get_data(chip); |
---|
| 405 | + const struct mrfld_gpio_pinrange *range; |
---|
| 406 | + const char *pinctrl_dev_name; |
---|
| 407 | + unsigned int i; |
---|
| 408 | + int retval; |
---|
| 409 | + |
---|
| 410 | + pinctrl_dev_name = mrfld_gpio_get_pinctrl_dev_name(priv); |
---|
| 411 | + for (i = 0; i < ARRAY_SIZE(mrfld_gpio_ranges); i++) { |
---|
| 412 | + range = &mrfld_gpio_ranges[i]; |
---|
| 413 | + retval = gpiochip_add_pin_range(&priv->chip, pinctrl_dev_name, |
---|
| 414 | + range->gpio_base, |
---|
| 415 | + range->pin_base, |
---|
| 416 | + range->npins); |
---|
| 417 | + if (retval) { |
---|
| 418 | + dev_err(priv->dev, "failed to add GPIO pin range\n"); |
---|
| 419 | + return retval; |
---|
| 420 | + } |
---|
| 421 | + } |
---|
| 422 | + |
---|
| 423 | + return 0; |
---|
388 | 424 | } |
---|
389 | 425 | |
---|
390 | 426 | static int mrfld_gpio_probe(struct pci_dev *pdev, const struct pci_device_id *id) |
---|
391 | 427 | { |
---|
392 | | - const struct mrfld_gpio_pinrange *range; |
---|
393 | | - const char *pinctrl_dev_name; |
---|
| 428 | + struct gpio_irq_chip *girq; |
---|
394 | 429 | struct mrfld_gpio *priv; |
---|
395 | 430 | u32 gpio_base, irq_base; |
---|
396 | 431 | void __iomem *base; |
---|
397 | | - unsigned int i; |
---|
398 | 432 | int retval; |
---|
399 | 433 | |
---|
400 | 434 | retval = pcim_enable_device(pdev); |
---|
.. | .. |
---|
409 | 443 | |
---|
410 | 444 | base = pcim_iomap_table(pdev)[1]; |
---|
411 | 445 | |
---|
412 | | - irq_base = readl(base); |
---|
413 | | - gpio_base = readl(sizeof(u32) + base); |
---|
| 446 | + irq_base = readl(base + 0 * sizeof(u32)); |
---|
| 447 | + gpio_base = readl(base + 1 * sizeof(u32)); |
---|
414 | 448 | |
---|
415 | 449 | /* Release the IO mapping, since we already get the info from BAR1 */ |
---|
416 | 450 | pcim_iounmap_regions(pdev, BIT(1)); |
---|
.. | .. |
---|
435 | 469 | priv->chip.base = gpio_base; |
---|
436 | 470 | priv->chip.ngpio = MRFLD_NGPIO; |
---|
437 | 471 | priv->chip.can_sleep = false; |
---|
| 472 | + priv->chip.add_pin_ranges = mrfld_gpio_add_pin_ranges; |
---|
438 | 473 | |
---|
439 | 474 | raw_spin_lock_init(&priv->lock); |
---|
440 | 475 | |
---|
441 | | - pci_set_drvdata(pdev, priv); |
---|
| 476 | + retval = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES); |
---|
| 477 | + if (retval < 0) |
---|
| 478 | + return retval; |
---|
| 479 | + |
---|
| 480 | + girq = &priv->chip.irq; |
---|
| 481 | + girq->chip = &mrfld_irqchip; |
---|
| 482 | + girq->init_hw = mrfld_irq_init_hw; |
---|
| 483 | + girq->parent_handler = mrfld_irq_handler; |
---|
| 484 | + girq->num_parents = 1; |
---|
| 485 | + girq->parents = devm_kcalloc(&pdev->dev, girq->num_parents, |
---|
| 486 | + sizeof(*girq->parents), GFP_KERNEL); |
---|
| 487 | + if (!girq->parents) |
---|
| 488 | + return -ENOMEM; |
---|
| 489 | + girq->parents[0] = pci_irq_vector(pdev, 0); |
---|
| 490 | + girq->first = irq_base; |
---|
| 491 | + girq->default_type = IRQ_TYPE_NONE; |
---|
| 492 | + girq->handler = handle_bad_irq; |
---|
| 493 | + |
---|
442 | 494 | retval = devm_gpiochip_add_data(&pdev->dev, &priv->chip, priv); |
---|
443 | 495 | if (retval) { |
---|
444 | 496 | dev_err(&pdev->dev, "gpiochip_add error %d\n", retval); |
---|
445 | 497 | return retval; |
---|
446 | 498 | } |
---|
447 | 499 | |
---|
448 | | - pinctrl_dev_name = mrfld_gpio_get_pinctrl_dev_name(); |
---|
449 | | - for (i = 0; i < ARRAY_SIZE(mrfld_gpio_ranges); i++) { |
---|
450 | | - range = &mrfld_gpio_ranges[i]; |
---|
451 | | - retval = gpiochip_add_pin_range(&priv->chip, |
---|
452 | | - pinctrl_dev_name, |
---|
453 | | - range->gpio_base, |
---|
454 | | - range->pin_base, |
---|
455 | | - range->npins); |
---|
456 | | - if (retval) { |
---|
457 | | - dev_err(&pdev->dev, "failed to add GPIO pin range\n"); |
---|
458 | | - return retval; |
---|
459 | | - } |
---|
460 | | - } |
---|
461 | | - |
---|
462 | | - retval = gpiochip_irqchip_add(&priv->chip, &mrfld_irqchip, irq_base, |
---|
463 | | - handle_bad_irq, IRQ_TYPE_NONE); |
---|
464 | | - if (retval) { |
---|
465 | | - dev_err(&pdev->dev, "could not connect irqchip to gpiochip\n"); |
---|
466 | | - return retval; |
---|
467 | | - } |
---|
468 | | - |
---|
469 | | - mrfld_irq_init_hw(priv); |
---|
470 | | - |
---|
471 | | - gpiochip_set_chained_irqchip(&priv->chip, &mrfld_irqchip, pdev->irq, |
---|
472 | | - mrfld_irq_handler); |
---|
473 | | - |
---|
| 500 | + pci_set_drvdata(pdev, priv); |
---|
474 | 501 | return 0; |
---|
475 | 502 | } |
---|
476 | 503 | |
---|