diff options
49 files changed, 1507 insertions, 459 deletions
diff --git a/Documentation/acpi/gpio-properties.txt b/Documentation/acpi/gpio-properties.txt index 2aff0349facd..88c65cb5bf0a 100644 --- a/Documentation/acpi/gpio-properties.txt +++ b/Documentation/acpi/gpio-properties.txt @@ -156,3 +156,68 @@ pointed to by its first argument. That should be done in the driver's .probe() routine. On removal, the driver should unregister its GPIO mapping table by calling acpi_dev_remove_driver_gpios() on the ACPI device object where that table was previously registered. + +Using the _CRS fallback +----------------------- + +If a device does not have _DSD or the driver does not create ACPI GPIO +mapping, the Linux GPIO framework refuses to return any GPIOs. This is +because the driver does not know what it actually gets. For example if we +have a device like below: + + Device (BTH) + { + Name (_HID, ...) + + Name (_CRS, ResourceTemplate () { + GpioIo (Exclusive, PullNone, 0, 0, IoRestrictionNone, + "\\_SB.GPO0", 0, ResourceConsumer) {15} + GpioIo (Exclusive, PullNone, 0, 0, IoRestrictionNone, + "\\_SB.GPO0", 0, ResourceConsumer) {27} + }) + } + +The driver might expect to get the right GPIO when it does: + + desc = gpiod_get(dev, "reset", GPIOD_OUT_LOW); + +but since there is no way to know the mapping between "reset" and +the GpioIo() in _CRS desc will hold ERR_PTR(-ENOENT). + +The driver author can solve this by passing the mapping explictly +(the recommended way and documented in the above chapter). + +The ACPI GPIO mapping tables should not contaminate drivers that are not +knowing about which exact device they are servicing on. It implies that +the ACPI GPIO mapping tables are hardly linked to ACPI ID and certain +objects, as listed in the above chapter, of the device in question. + +Getting GPIO descriptor +----------------------- + +There are two main approaches to get GPIO resource from ACPI: + desc = gpiod_get(dev, connection_id, flags); + desc = gpiod_get_index(dev, connection_id, index, flags); + +We may consider two different cases here, i.e. when connection ID is +provided and otherwise. + +Case 1: + desc = gpiod_get(dev, "non-null-connection-id", flags); + desc = gpiod_get_index(dev, "non-null-connection-id", index, flags); + +Case 2: + desc = gpiod_get(dev, NULL, flags); + desc = gpiod_get_index(dev, NULL, index, flags); + +Case 1 assumes that corresponding ACPI device description must have +defined device properties and will prevent to getting any GPIO resources +otherwise. + +Case 2 explicitly tells GPIO core to look for resources in _CRS. + +Be aware that gpiod_get_index() in cases 1 and 2, assuming that there +are two versions of ACPI device description provided and no mapping is +present in the driver, will return different resources. That's why a +certain driver has to handle them carefully as explained in previous +chapter. diff --git a/Documentation/devicetree/bindings/gpio/gpio.txt b/Documentation/devicetree/bindings/gpio/gpio.txt index 84ede036f73d..802402f6cc5d 100644 --- a/Documentation/devicetree/bindings/gpio/gpio.txt +++ b/Documentation/devicetree/bindings/gpio/gpio.txt @@ -74,11 +74,14 @@ GPIO pin number, and GPIO flags as accepted by the "qe_pio_e" gpio-controller. Optional standard bitfield specifiers for the last cell: - Bit 0: 0 means active high, 1 means active low -- Bit 1: 1 means single-ended wiring, see: +- Bit 1: 0 mean push-pull wiring, see: + https://en.wikipedia.org/wiki/Push-pull_output + 1 means single-ended wiring, see: https://en.wikipedia.org/wiki/Single-ended_triode - When used with active-low, this means open drain/collector, see: +- Bit 2: 0 means open-source, 1 means open drain, see: https://en.wikipedia.org/wiki/Open_collector - When used with active-high, this means open source/emitter +- Bit 3: 0 means the output should be maintained during sleep/low-power mode + 1 means the output state can be lost during sleep/low-power mode 1.1) GPIO specifier best practices ---------------------------------- @@ -282,8 +285,8 @@ Example 1: }; Here, a single GPIO controller has GPIOs 0..9 routed to pin controller -pinctrl1's pins 20..29, and GPIOs 10..19 routed to pin controller pinctrl2's -pins 50..59. +pinctrl1's pins 20..29, and GPIOs 10..29 routed to pin controller pinctrl2's +pins 50..69. Example 2: diff --git a/Documentation/devicetree/bindings/gpio/renesas,gpio-rcar.txt b/Documentation/devicetree/bindings/gpio/renesas,gpio-rcar.txt index 7c1ab3b3254f..6826a371fb69 100644 --- a/Documentation/devicetree/bindings/gpio/renesas,gpio-rcar.txt +++ b/Documentation/devicetree/bindings/gpio/renesas,gpio-rcar.txt @@ -3,6 +3,7 @@ Required Properties: - compatible: should contain one of the following. + - "renesas,gpio-r8a7743": for R8A7743 (RZ/G1M) compatible GPIO controller. - "renesas,gpio-r8a7778": for R8A7778 (R-Mobile M1) compatible GPIO controller. - "renesas,gpio-r8a7779": for R8A7779 (R-Car H1) compatible GPIO controller. - "renesas,gpio-r8a7790": for R8A7790 (R-Car H2) compatible GPIO controller. diff --git a/MAINTAINERS b/MAINTAINERS index 101af8787cac..cb79977dd049 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5747,6 +5747,15 @@ F: include/asm-generic/gpio.h F: include/uapi/linux/gpio.h F: tools/gpio/ +GPIO ACPI SUPPORT +M: Mika Westerberg <mika.westerberg@linux.intel.com> +M: Andy Shevchenko <andriy.shevchenko@linux.intel.com> +L: linux-gpio@vger.kernel.org +L: linux-acpi@vger.kernel.org +S: Maintained +F: Documentation/acpi/gpio-properties.txt +F: drivers/gpio/gpiolib-acpi.c + GRE DEMULTIPLEXER DRIVER M: Dmitry Kozlov <xeb@mail.ru> L: netdev@vger.kernel.org @@ -12026,6 +12035,13 @@ S: Maintained F: drivers/media/platform/davinci/ F: include/media/davinci/ +TI DAVINCI SERIES GPIO DRIVER +M: Keerthy <j-keerthy@ti.com> +L: linux-gpio@vger.kernel.org +S: Maintained +F: Documentation/devicetree/bindings/gpio/gpio-davinci.txt +F: drivers/gpio/gpio-davinci.c + TI AM437X VPFE DRIVER M: "Lad, Prabhakar" <prabhakar.csengg@gmail.com> L: linux-media@vger.kernel.org @@ -14338,6 +14354,14 @@ L: linux-kernel@vger.kernel.org S: Supported F: drivers/char/xillybus/ +XRA1403 GPIO EXPANDER +M: Nandor Han <nandor.han@ge.com> +M: Semi Malinen <semi.malinen@ge.com> +L: linux-gpio@vger.kernel.org +S: Maintained +F: drivers/gpio/gpio-xra1403.c +F: Documentation/devicetree/bindings/gpio/gpio-xra1403.txt + XTENSA XTFPGA PLATFORM SUPPORT M: Max Filippov <jcmvbkbc@gmail.com> L: linux-xtensa@linux-xtensa.org diff --git a/arch/arm/mach-davinci/board-da830-evm.c b/arch/arm/mach-davinci/board-da830-evm.c index 58075627c6df..f673cd7a6766 100644 --- a/arch/arm/mach-davinci/board-da830-evm.c +++ b/arch/arm/mach-davinci/board-da830-evm.c @@ -17,7 +17,7 @@ #include <linux/gpio/machine.h> #include <linux/platform_device.h> #include <linux/i2c.h> -#include <linux/i2c/pcf857x.h> +#include <linux/platform_data/pcf857x.h> #include <linux/platform_data/at24.h> #include <linux/mtd/mtd.h> #include <linux/mtd/partitions.h> diff --git a/arch/arm/mach-davinci/board-dm644x-evm.c b/arch/arm/mach-davinci/board-dm644x-evm.c index 20f1874a5657..70e00dbeec96 100644 --- a/arch/arm/mach-davinci/board-dm644x-evm.c +++ b/arch/arm/mach-davinci/board-dm644x-evm.c @@ -14,7 +14,7 @@ #include <linux/platform_device.h> #include <linux/gpio.h> #include <linux/i2c.h> -#include <linux/i2c/pcf857x.h> +#include <linux/platform_data/pcf857x.h> #include <linux/platform_data/at24.h> #include <linux/mtd/mtd.h> #include <linux/mtd/nand.h> diff --git a/arch/arm/mach-davinci/board-dm646x-evm.c b/arch/arm/mach-davinci/board-dm646x-evm.c index 055e947a6a39..1d76e7480a42 100644 --- a/arch/arm/mach-davinci/board-dm646x-evm.c +++ b/arch/arm/mach-davinci/board-dm646x-evm.c @@ -23,7 +23,7 @@ #include <linux/platform_device.h> #include <linux/i2c.h> #include <linux/platform_data/at24.h> -#include <linux/i2c/pcf857x.h> +#include <linux/platform_data/pcf857x.h> #include <media/i2c/tvp514x.h> #include <media/i2c/adv7343.h> diff --git a/arch/arm/mach-pxa/balloon3.c b/arch/arm/mach-pxa/balloon3.c index d452a49c0396..1467c1d1e541 100644 --- a/arch/arm/mach-pxa/balloon3.c +++ b/arch/arm/mach-pxa/balloon3.c @@ -27,7 +27,7 @@ #include <linux/mtd/mtd.h> #include <linux/mtd/partitions.h> #include <linux/types.h> -#include <linux/i2c/pcf857x.h> +#include <linux/platform_data/pcf857x.h> #include <linux/i2c/pxa-i2c.h> #include <linux/mtd/nand.h> #include <linux/mtd/physmap.h> diff --git a/arch/arm/mach-pxa/littleton.c b/arch/arm/mach-pxa/littleton.c index 051c554776a6..fae38fdc8d8e 100644 --- a/arch/arm/mach-pxa/littleton.c +++ b/arch/arm/mach-pxa/littleton.c @@ -27,7 +27,7 @@ #include <linux/i2c.h> #include <linux/leds.h> #include <linux/mfd/da903x.h> -#include <linux/i2c/max732x.h> +#include <linux/platform_data/max732x.h> #include <linux/i2c/pxa-i2c.h> #include <asm/types.h> diff --git a/arch/arm/mach-pxa/stargate2.c b/arch/arm/mach-pxa/stargate2.c index 7b6610e9dae4..2d45d18b1a5e 100644 --- a/arch/arm/mach-pxa/stargate2.c +++ b/arch/arm/mach-pxa/stargate2.c @@ -26,7 +26,7 @@ #include <linux/mtd/partitions.h> #include <linux/i2c/pxa-i2c.h> -#include <linux/i2c/pcf857x.h> +#include <linux/platform_data/pcf857x.h> #include <linux/platform_data/at24.h> #include <linux/smc91x.h> #include <linux/gpio.h> diff --git a/arch/blackfin/mach-bf537/boards/stamp.c b/arch/blackfin/mach-bf537/boards/stamp.c index eaec7b4832a2..24985e658c19 100644 --- a/arch/blackfin/mach-bf537/boards/stamp.c +++ b/arch/blackfin/mach-bf537/boards/stamp.c @@ -22,7 +22,7 @@ #include <linux/usb/isp1362.h> #endif #include <linux/i2c.h> -#include <linux/i2c/adp5588.h> +#include <linux/platform_data/adp5588.h> #include <linux/etherdevice.h> #include <linux/ata_platform.h> #include <linux/irq.h> diff --git a/arch/mips/ath79/mach-pb44.c b/arch/mips/ath79/mach-pb44.c index 67b980d94fb7..be78298dffb4 100644 --- a/arch/mips/ath79/mach-pb44.c +++ b/arch/mips/ath79/mach-pb44.c @@ -12,7 +12,7 @@ #include <linux/platform_device.h> #include <linux/i2c.h> #include <linux/i2c-gpio.h> -#include <linux/i2c/pcf857x.h> +#include <linux/platform_data/pcf857x.h> #include "machtypes.h" #include "dev-gpio-buttons.h" diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 97332d094fe2..d1bd99271066 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -344,7 +344,7 @@ EXPORT_SYMBOL_GPL(platform_device_add_data); * platform device is released. */ int platform_device_add_properties(struct platform_device *pdev, - struct property_entry *properties) + const struct property_entry *properties) { return device_add_properties(&pdev->dev, properties); } diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 395c85df48fd..f235eae04c16 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -337,9 +337,10 @@ config GPIO_MPC8XXX config GPIO_MVEBU def_bool y - depends on PLAT_ORION + depends on PLAT_ORION || ARCH_MVEBU depends on OF_GPIO select GENERIC_IRQ_CHIP + select REGMAP_MMIO config GPIO_MXC def_bool y @@ -515,12 +516,13 @@ config GPIO_XILINX config GPIO_XLP tristate "Netlogic XLP GPIO support" - depends on OF_GPIO && (CPU_XLP || ARCH_VULCAN || ARCH_THUNDER2 || COMPILE_TEST) + depends on OF_GPIO && (CPU_XLP || ARCH_THUNDER2 || COMPILE_TEST) select GPIOLIB_IRQCHIP help This driver provides support for GPIO interface on Netlogic XLP MIPS64 SoCs. Currently supported XLP variants are XLP8XX, XLP3XX, XLP2XX, - XLP9XX and XLP5XX. + XLP9XX and XLP5XX. The same GPIO controller block is also present in + Cavium's ThunderX2 CN99XX SoCs. If unsure, say N. @@ -963,6 +965,16 @@ config GPIO_LP873X This driver can also be built as a module. If so, the module will be called gpio-lp873x. +config GPIO_LP87565 + tristate "TI LP87565 GPIO" + depends on MFD_TI_LP87565 + help + This driver supports the GPIO on TI Lp873565 PMICs. 3 GPIOs are present + on LP87565 PMICs. + + This driver can also be built as a module. If so, the module will be + called gpio-lp87565. + config GPIO_MAX77620 tristate "GPIO support for PMIC MAX77620 and MAX20024" depends on MFD_MAX77620 @@ -1236,6 +1248,12 @@ config GPIO_PISOSR GPIO driver for SPI compatible parallel-in/serial-out shift registers. These are input only devices. +config GPIO_XRA1403 + tristate "EXAR XRA1403 16-bit GPIO expander" + select REGMAP_SPI + help + GPIO driver for EXAR XRA1403 16-bit SPI-based GPIO expander. + endmenu menu "USB GPIO expanders" diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 845f990fc987..a9fda6c55113 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -67,6 +67,7 @@ obj-$(CONFIG_GPIO_LP3943) += gpio-lp3943.o obj-$(CONFIG_GPIO_LPC18XX) += gpio-lpc18xx.o obj-$(CONFIG_ARCH_LPC32XX) += gpio-lpc32xx.o obj-$(CONFIG_GPIO_LP873X) += gpio-lp873x.o +obj-$(CONFIG_GPIO_LP87565) += gpio-lp87565.o obj-$(CONFIG_GPIO_LYNXPOINT) += gpio-lynxpoint.o obj-$(CONFIG_GPIO_MAX730X) += gpio-max730x.o obj-$(CONFIG_GPIO_MAX7300) += gpio-max7300.o @@ -141,6 +142,7 @@ obj-$(CONFIG_GPIO_XGENE) += gpio-xgene.o obj-$(CONFIG_GPIO_XGENE_SB) += gpio-xgene-sb.o obj-$(CONFIG_GPIO_XILINX) += gpio-xilinx.o obj-$(CONFIG_GPIO_XLP) += gpio-xlp.o +obj-$(CONFIG_GPIO_XRA1403) += gpio-xra1403.o obj-$(CONFIG_GPIO_XTENSA) += gpio-xtensa.o obj-$(CONFIG_GPIO_ZEVIO) += gpio-zevio.o obj-$(CONFIG_GPIO_ZYNQ) += gpio-zynq.o diff --git a/drivers/gpio/gpio-adp5588.c b/drivers/gpio/gpio-adp5588.c index c0f718b12317..e717f8dc3966 100644 --- a/drivers/gpio/gpio-adp5588.c +++ b/drivers/gpio/gpio-adp5588.c @@ -16,7 +16,7 @@ #include <linux/interrupt.h> #include <linux/irq.h> -#include <linux/i2c/adp5588.h> +#include <linux/platform_data/adp5588.h> #define DRV_NAME "adp5588-gpio" diff --git a/drivers/gpio/gpio-arizona.c b/drivers/gpio/gpio-arizona.c index cd23fd727f95..d4e6ba0301bc 100644 --- a/drivers/gpio/gpio-arizona.c +++ b/drivers/gpio/gpio-arizona.c @@ -33,9 +33,23 @@ static int arizona_gpio_direction_in(struct gpio_chip *chip, unsigned offset) { struct arizona_gpio *arizona_gpio = gpiochip_get_data(chip); struct arizona *arizona = arizona_gpio->arizona; + bool persistent = gpiochip_line_is_persistent(chip, offset); + bool change; + int ret; - return regmap_update_bits(arizona->regmap, ARIZONA_GPIO1_CTRL + offset, - ARIZONA_GPN_DIR, ARIZONA_GPN_DIR); + ret = regmap_update_bits_check(arizona->regmap, + ARIZONA_GPIO1_CTRL + offset, + ARIZONA_GPN_DIR, ARIZONA_GPN_DIR, + &change); + if (ret < 0) + return ret; + + if (change && persistent) { + pm_runtime_mark_last_busy(chip->parent); + pm_runtime_put_autosuspend(chip->parent); + } + + return 0; } static int arizona_gpio_get(struct gpio_chip *chip, unsigned offset) @@ -85,6 +99,21 @@ static int arizona_gpio_direction_out(struct gpio_chip *chip, { struct arizona_gpio *arizona_gpio = gpiochip_get_data(chip); struct arizona *arizona = arizona_gpio->arizona; + bool persistent = gpiochip_line_is_persistent(chip, offset); + unsigned int val; + int ret; + + ret = regmap_read(arizona->regmap, ARIZONA_GPIO1_CTRL + offset, &val); + if (ret < 0) + return ret; + + if ((val & ARIZONA_GPN_DIR) && persistent) { + ret = pm_runtime_get_sync(chip->parent); + if (ret < 0) { + dev_err(chip->parent, "Failed to resume: %d\n", ret); + return ret; + } + } if (value) value = ARIZONA_GPN_LVL; @@ -158,6 +187,8 @@ static int arizona_gpio_probe(struct platform_device *pdev) else arizona_gpio->gpio_chip.base = -1; + pm_runtime_enable(&pdev->dev); + ret = devm_gpiochip_add_data(&pdev->dev, &arizona_gpio->gpio_chip, arizona_gpio); if (ret < 0) { diff --git a/drivers/gpio/gpio-davinci.c b/drivers/gpio/gpio-davinci.c index ac173575d3f6..65cb359308e3 100644 --- a/drivers/gpio/gpio-davinci.c +++ b/drivers/gpio/gpio-davinci.c @@ -437,6 +437,7 @@ static int davinci_gpio_irq_setup(struct platform_device *pdev) { unsigned gpio, bank; int irq; + int ret; struct clk *clk; u32 binten = 0; unsigned ngpio, bank_irq; @@ -480,12 +481,15 @@ static int davinci_gpio_irq_setup(struct platform_device *pdev) PTR_ERR(clk)); return PTR_ERR(clk); } - clk_prepare_enable(clk); + ret = clk_prepare_enable(clk); + if (ret) + return ret; if (!pdata->gpio_unbanked) { irq = devm_irq_alloc_descs(dev, -1, 0, ngpio, 0); if (irq < 0) { dev_err(dev, "Couldn't allocate IRQ numbers\n"); + clk_disable_unprepare(clk); return irq; } @@ -494,6 +498,7 @@ static int davinci_gpio_irq_setup(struct platform_device *pdev) chips); if (!irq_domain) { dev_err(dev, "Couldn't register an IRQ domain\n"); + clk_disable_unprepare(clk); return -ENODEV; } } @@ -562,8 +567,10 @@ static int davinci_gpio_irq_setup(struct platform_device *pdev) sizeof(struct davinci_gpio_irq_data), GFP_KERNEL); - if (!irqdata) + if (!irqdata) { + clk_disable_unprepare(clk); return -ENOMEM; + } irqdata->regs = g; irqdata->bank_num = bank; diff --git a/drivers/gpio/gpio-dwapb.c b/drivers/gpio/gpio-dwapb.c index f051c4552af5..c07ada9c7af6 100644 --- a/drivers/gpio/gpio-dwapb.c +++ b/drivers/gpio/gpio-dwapb.c @@ -288,7 +288,8 @@ static int dwapb_irq_set_type(struct irq_data *d, u32 type) irq_setup_alt_chip(d, type); dwapb_write(gpio, GPIO_INTTYPE_LEVEL, level); - dwapb_write(gpio, GPIO_INT_POLARITY, polarity); + if (type != IRQ_TYPE_EDGE_BOTH) + dwapb_write(gpio, GPIO_INT_POLARITY, polarity); spin_unlock_irqrestore(&gc->bgpio_lock, flags); return 0; diff --git a/drivers/gpio/gpio-exar.c b/drivers/gpio/gpio-exar.c index 081076771217..fb8d304cfa17 100644 --- a/drivers/gpio/gpio-exar.c +++ b/drivers/gpio/gpio-exar.c @@ -31,6 +31,7 @@ struct exar_gpio_chip { int index; void __iomem *regs; char name[20]; + unsigned int first_pin; }; static void exar_update(struct gpio_chip *chip, unsigned int reg, int val, @@ -51,11 +52,12 @@ static void exar_update(struct gpio_chip *chip, unsigned int reg, int val, static int exar_set_direction(struct gpio_chip *chip, int direction, unsigned int offset) { - unsigned int bank = offset / 8; - unsigned int addr; + struct exar_gpio_chip *exar_gpio = gpiochip_get_data(chip); + unsigned int addr = (offset + exar_gpio->first_pin) / 8 ? + EXAR_OFFSET_MPIOSEL_HI : EXAR_OFFSET_MPIOSEL_LO; + unsigned int bit = (offset + exar_gpio->first_pin) % 8; - addr = bank ? EXAR_OFFSET_MPIOSEL_HI : EXAR_OFFSET_MPIOSEL_LO; - exar_update(chip, addr, direction, offset % 8); + exar_update(chip, addr, direction, bit); return 0; } @@ -68,41 +70,38 @@ static int exar_get(struct gpio_chip *chip, unsigned int reg) value = readb(exar_gpio->regs + reg); mutex_unlock(&exar_gpio->lock); - return !!value; + return value; } static int exar_get_direction(struct gpio_chip *chip, unsigned int offset) { - unsigned int bank = offset / 8; - unsigned int addr; - int val; - - addr = bank ? EXAR_OFFSET_MPIOSEL_HI : EXAR_OFFSET_MPIOSEL_LO; - val = exar_get(chip, addr) >> (offset % 8); + struct exar_gpio_chip *exar_gpio = gpiochip_get_data(chip); + unsigned int addr = (offset + exar_gpio->first_pin) / 8 ? + EXAR_OFFSET_MPIOSEL_HI : EXAR_OFFSET_MPIOSEL_LO; + unsigned int bit = (offset + exar_gpio->first_pin) % 8; - return !!val; + return !!(exar_get(chip, addr) & BIT(bit)); } static int exar_get_value(struct gpio_chip *chip, unsigned int offset) { - unsigned int bank = offset / 8; - unsigned int addr; - int val; - - addr = bank ? EXAR_OFFSET_MPIOLVL_LO : EXAR_OFFSET_MPIOLVL_HI; - val = exar_get(chip, addr) >> (offset % 8); + struct exar_gpio_chip *exar_gpio = gpiochip_get_data(chip); + unsigned int addr = (offset + exar_gpio->first_pin) / 8 ? + EXAR_OFFSET_MPIOLVL_HI : EXAR_OFFSET_MPIOLVL_LO; + unsigned int bit = (offset + exar_gpio->first_pin) % 8; - return !!val; + return !!(exar_get(chip, addr) & BIT(bit)); } static void exar_set_value(struct gpio_chip *chip, unsigned int offset, int value) { - unsigned int bank = offset / 8; - unsigned int addr; + struct exar_gpio_chip *exar_gpio = gpiochip_get_data(chip); + unsigned int addr = (offset + exar_gpio->first_pin) / 8 ? + EXAR_OFFSET_MPIOLVL_HI : EXAR_OFFSET_MPIOLVL_LO; + unsigned int bit = (offset + exar_gpio->first_pin) % 8; - addr = bank ? EXAR_OFFSET_MPIOLVL_HI : EXAR_OFFSET_MPIOLVL_LO; - exar_update(chip, addr, value, offset % 8); + exar_update(chip, addr, value, bit); } static int exar_direction_output(struct gpio_chip *chip, unsigned int offset, @@ -119,27 +118,30 @@ static int exar_direction_input(struct gpio_chip *chip, unsigned int offset) static int gpio_exar_probe(struct platform_device *pdev) { - struct pci_dev *pcidev = platform_get_drvdata(pdev); + struct pci_dev *pcidev = to_pci_dev(pdev->dev.parent); struct exar_gpio_chip *exar_gpio; + u32 first_pin, ngpios; void __iomem *p; int index, ret; - if (pcidev->vendor != PCI_VENDOR_ID_EXAR) - return -ENODEV; - /* - * Map the pci device to get the register addresses. - * We will need to read and write those registers to control - * the GPIO pins. - * Using managed functions will save us from unmaping on exit. - * As the device is enabled using managed functions by the - * UART driver we can also use managed functions here. + * The UART driver must have mapped region 0 prior to registering this + * device - use it. */ - p = pcim_iomap(pcidev, 0, 0); + p = pcim_iomap_table(pcidev)[0]; if (!p) return -ENOMEM; - exar_gpio = devm_kzalloc(&pcidev->dev, sizeof(*exar_gpio), GFP_KERNEL); + ret = device_property_read_u32(&pdev->dev, "linux,first-pin", + &first_pin); + if (ret) + return ret; + + ret = device_property_read_u32(&pdev->dev, "ngpios", &ngpios); + if (ret) + return ret; + + exar_gpio = devm_kzalloc(&pdev->dev, sizeof(*exar_gpio), GFP_KERNEL); if (!exar_gpio) return -ENOMEM; @@ -149,18 +151,19 @@ static int gpio_exar_probe(struct platform_device *pdev) sprintf(exar_gpio->name, "exar_gpio%d", index); exar_gpio->gpio_chip.label = exar_gpio->name; - exar_gpio->gpio_chip.parent = &pcidev->dev; + exar_gpio->gpio_chip.parent = &pdev->dev; exar_gpio->gpio_chip.direction_output = exar_direction_output; exar_gpio->gpio_chip.direction_input = exar_direction_input; exar_gpio->gpio_chip.get_direction = exar_get_direction; exar_gpio->gpio_chip.get = exar_get_value; exar_gpio->gpio_chip.set = exar_set_value; exar_gpio->gpio_chip.base = -1; - exar_gpio->gpio_chip.ngpio = 16; + exar_gpio->gpio_chip.ngpio = ngpios; exar_gpio->regs = p; exar_gpio->index = index; |