summaryrefslogtreecommitdiff
path: root/drivers/gpio/gpio-exar.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2017-07-07 12:40:27 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2017-07-07 12:40:27 -0700
commitc7d28eca1d58d335ff8de6f33559b221bdd029f9 (patch)
tree3522cae5809d6912ccc307a4b0a7dea3ffeb8225 /drivers/gpio/gpio-exar.c
parentdddd564dbb5934c9a0c401491cafb98ab1c82fc6 (diff)
parent413058df4331ce29f9934a5870d582c7e71fe15f (diff)
Merge tag 'gpio-v4.13-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio
Pull GPIO updates from Linus Walleij: "This is the bulk of GPIO changes for the v4.13 series. Some administrativa: I have a slew of 8250 serial patches and the new IOT2040 serial+GPIO driver coming in through this tree, along with a whole bunch of Exar 8250 fixes. These are ACKed by Greg and also hit drivers/platform/* where they are ACKed by Andy Shevchenko. Speaking about drivers/platform/* there is also a bunch of ACPI stuff coming through that route, again ACKed by Andy. The MCP23S08 changes are coming in here as well. You already have the commits in your tree, so this is just a result of sharing an immutable branch between pin control and GPIO. Core: - Export add/remove for lookup tables so that modules can export GPIO descriptor tables. - Handle GPIO sleep states: it is now possible to flag that a GPIO line may loose its state during suspend/resume of the system to save power. This is used in the Wolfson Micro Arizona driver. - ACPI-based GPIO was tightened up a lot around the edges. - Use bitmap_fill() to speed up a loop. New drivers: - Exar XRA1403 SPI-based GPIO. - MVEBU driver now supports Armada 7K and 8K. - LP87565 PMIC GPIO. - Renesas R-CAR R8A7743 (RZ/G1M). - The new IOT2040 8250 serial/GPIO also comes in through this changeset. Substantial driver changes: - Seriously fix the Exar 8250 GPIO portions to work. - The MCP23S08 was moved out to a pin control driver. - Convert MEVEBU to use regmap for register access. - Drop Vulcan support from the Broadcom driver. - Serious cleanup and improvement of the mockup driver, giving us a better test coverage. Misc: - Lots of janitorial clean up. - A bunch of documentation fixes" * tag 'gpio-v4.13-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio: (70 commits) serial: exar: Add support for IOT2040 device gpio-exar/8250-exar: Make set of exported GPIOs configurable platform: Accept const properties serial: exar: Factor out platform hooks gpio-exar/8250-exar: Rearrange gpiochip parenthood gpio: exar: Fix iomap request gpio-exar/8250-exar: Do not even instantiate a GPIO device for Commtech cards serial: uapi: Add support for bus termination gpio: rcar: Add R8A7743 (RZ/G1M) support gpio: gpio-wcove: Fix GPIO control register offset calculation gpio: lp87565: Add support for GPIO gpio: dwapb: fix missing first irq for edgeboth irq type MAINTAINERS: Take maintainership for GPIO ACPI support gpio: exar: Fix reading of directions and values gpio: exar: Allocate resources on behalf of the platform device gpio-exar/8250-exar: Fix passing in of parent PCI device gpio: mockup: use devm_kcalloc() where applicable gpio: mockup: add myself as author gpio: mockup: improve the error message gpio: mockup: don't return magic numbers from probe() ...
Diffstat (limited to 'drivers/gpio/gpio-exar.c')
-rw-r--r--drivers/gpio/gpio-exar.c79
1 files changed, 41 insertions, 38 deletions
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;
+ exar_gpio->first_pin = first_pin;
- ret = devm_gpiochip_add_data(&pcidev->dev,
+ ret = devm_gpiochip_add_data(&pdev->dev,
&exar_gpio->gpio_chip, exar_gpio);
if (ret)
goto err_destroy;