summaryrefslogtreecommitdiffstats
path: root/drivers/gpio/gpiolib-acpi.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2018-01-31 21:25:27 +0100
committerLinus Torvalds <torvalds@linux-foundation.org>2018-01-31 21:25:27 +0100
commit9798f5178f5791f964562eccedcf4dabe02fd825 (patch)
treed0d76b4202eaa3d3be3aaa05206e57e02e16ac5b /drivers/gpio/gpiolib-acpi.c
parentMerge tag 'leds_for_4.16-rc1' of git://git.kernel.org/pub/scm/linux/kernel/gi... (diff)
parentgpio: Timestamp events in hardirq handler (diff)
downloadlinux-9798f5178f5791f964562eccedcf4dabe02fd825.tar.xz
linux-9798f5178f5791f964562eccedcf4dabe02fd825.zip
Merge tag 'gpio-v4.16-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio
Pull GPIO updates from Linus Walleij: "The is the bulk of GPIO changes for the v4.16 kernel cycle. It is pretty calm this time around I think. I even got time to get to things like starting to clean up header includes. Core changes: - Disallow open drain and open source flags to be set simultaneously. This doesn't make electrical sense, and would the hardware actually respond to this setting, the result would be short circuit. - ACPI GPIO has a new core infrastructure for handling quirks. The quirks are there to deal with broken ACPI tables centrally instead of pushing the work to individual drivers. In the world of BIOS writers, the ACPI tables are perfect. Until they find a mistake in it. When such a mistake is found, we can patch it with a quirk. It should never happen, the problem is that it happens. So we accomodate for it. - Several documentation updates. - Revert the patch setting up initial direction state from reading the device. This was causing bad things for drivers that can't read status on all its pins. It is only affecting debugfs information quality. - Label descriptors with the device name if no explicit label is passed in. - Pave the ground for transitioning SPI and regulators to use GPIO descriptors by implementing some quirks in the device tree GPIO parsing code. New drivers: - New driver for the Access PCIe IDIO 24 family. Other: - Major refactorings and improvements to the GPIO mockup driver used for test and verification. - Moved the AXP209 driver over to pin control since it gained a pin control back-end. These patches will appear (with the same hashes) in the pin control pull request as well. - Convert the onewire GPIO driver w1-gpio to use descriptors. This is merged here since the W1 maintainers send very few pull requests and he ACKed it. - Start to clean up driver headers using <linux/gpio.h> to just use <linux/gpio/driver.h> as appropriate" * tag 'gpio-v4.16-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio: (103 commits) gpio: Timestamp events in hardirq handler gpio: Fix kernel stack leak to userspace gpio: Fix a documentation spelling mistake gpio: Documentation update gpiolib: remove redundant initialization of pointer desc gpio: of: Fix NPE from OF flags gpio: stmpe: Delete an unnecessary variable initialisation in stmpe_gpio_probe() gpio: stmpe: Move an assignment in stmpe_gpio_probe() gpio: stmpe: Improve a size determination in stmpe_gpio_probe() gpio: stmpe: Use seq_putc() in stmpe_dbg_show() gpio: No NULL owner gpio: stmpe: i2c transfer are forbiden in atomic context gpio: davinci: Include proper header gpio: da905x: Include proper header gpio: cs5535: Include proper header gpio: crystalcove: Include proper header gpio: bt8xx: Include proper header gpio: bcm-kona: Include proper header gpio: arizona: Include proper header gpio: amd8111: Include proper header ...
Diffstat (limited to 'drivers/gpio/gpiolib-acpi.c')
-rw-r--r--drivers/gpio/gpiolib-acpi.c57
1 files changed, 38 insertions, 19 deletions
diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c
index d6f3d9ee1350..0ecffd172a80 100644
--- a/drivers/gpio/gpiolib-acpi.c
+++ b/drivers/gpio/gpiolib-acpi.c
@@ -414,7 +414,8 @@ EXPORT_SYMBOL_GPL(devm_acpi_dev_remove_driver_gpios);
static bool acpi_get_driver_gpio_data(struct acpi_device *adev,
const char *name, int index,
- struct acpi_reference_args *args)
+ struct acpi_reference_args *args,
+ unsigned int *quirks)
{
const struct acpi_gpio_mapping *gm;
@@ -430,6 +431,8 @@ static bool acpi_get_driver_gpio_data(struct acpi_device *adev,
args->args[1] = par->line_index;
args->args[2] = par->active_low;
args->nargs = 3;
+
+ *quirks = gm->quirks;
return true;
}
@@ -461,8 +464,8 @@ acpi_gpio_to_gpiod_flags(const struct acpi_resource_gpio *agpio)
}
}
-int
-acpi_gpio_update_gpiod_flags(enum gpiod_flags *flags, enum gpiod_flags update)
+static int
+__acpi_gpio_update_gpiod_flags(enum gpiod_flags *flags, enum gpiod_flags update)
{
int ret = 0;
@@ -489,12 +492,31 @@ acpi_gpio_update_gpiod_flags(enum gpiod_flags *flags, enum gpiod_flags update)
return ret;
}
+int
+acpi_gpio_update_gpiod_flags(enum gpiod_flags *flags, struct acpi_gpio_info *info)
+{
+ struct device *dev = &info->adev->dev;
+ enum gpiod_flags old = *flags;
+ int ret;
+
+ ret = __acpi_gpio_update_gpiod_flags(&old, info->flags);
+ if (info->quirks & ACPI_GPIO_QUIRK_NO_IO_RESTRICTION) {
+ if (ret)
+ dev_warn(dev, FW_BUG "GPIO not in correct mode, fixing\n");
+ } else {
+ if (ret)
+ dev_dbg(dev, "Override GPIO initialization flags\n");
+ *flags = old;
+ }
+
+ return ret;
+}
+
struct acpi_gpio_lookup {
struct acpi_gpio_info info;
int index;
int pin_index;
bool active_low;
- struct acpi_device *adev;
struct gpio_desc *desc;
int n;
};
@@ -531,8 +553,8 @@ static int acpi_populate_gpio_lookup(struct acpi_resource *ares, void *data)
lookup->info.triggering = agpio->triggering;
} else {
lookup->info.flags = acpi_gpio_to_gpiod_flags(agpio);
+ lookup->info.polarity = lookup->active_low;
}
-
}
return 1;
@@ -541,12 +563,13 @@ static int acpi_populate_gpio_lookup(struct acpi_resource *ares, void *data)
static int acpi_gpio_resource_lookup(struct acpi_gpio_lookup *lookup,
struct acpi_gpio_info *info)
{
+ struct acpi_device *adev = lookup->info.adev;
struct list_head res_list;
int ret;
INIT_LIST_HEAD(&res_list);
- ret = acpi_dev_get_resources(lookup->adev, &res_list,
+ ret = acpi_dev_get_resources(adev, &res_list,
acpi_populate_gpio_lookup,
lookup);
if (ret < 0)
@@ -557,11 +580,8 @@ static int acpi_gpio_resource_lookup(struct acpi_gpio_lookup *lookup,
if (!lookup->desc)
return -ENOENT;
- if (info) {
+ if (info)
*info = lookup->info;
- if (lookup->active_low)
- info->polarity = lookup->active_low;
- }
return 0;
}
@@ -570,6 +590,7 @@ static int acpi_gpio_property_lookup(struct fwnode_handle *fwnode,
struct acpi_gpio_lookup *lookup)
{
struct acpi_reference_args args;
+ unsigned int quirks = 0;
int ret;
memset(&args, 0, sizeof(args));
@@ -581,14 +602,14 @@ static int acpi_gpio_property_lookup(struct fwnode_handle *fwnode,
if (!adev)
return ret;
- if (!acpi_get_driver_gpio_data(adev, propname, index, &args))
+ if (!acpi_get_driver_gpio_data(adev, propname, index, &args,
+ &quirks))
return ret;
}
/*
* The property was found and resolved, so need to lookup the GPIO based
* on returned args.
*/
- lookup->adev = args.adev;
if (args.nargs != 3)
return -EPROTO;
@@ -596,6 +617,8 @@ static int acpi_gpio_property_lookup(struct fwnode_handle *fwnode,
lookup->pin_index = args.args[1];
lookup->active_low = !!args.args[2];
+ lookup->info.adev = args.adev;
+ lookup->info.quirks = quirks;
return 0;
}
@@ -643,11 +666,11 @@ static struct gpio_desc *acpi_get_gpiod_by_index(struct acpi_device *adev,
return ERR_PTR(ret);
dev_dbg(&adev->dev, "GPIO: _DSD returned %s %d %d %u\n",
- dev_name(&lookup.adev->dev), lookup.index,
+ dev_name(&lookup.info.adev->dev), lookup.index,
lookup.pin_index, lookup.active_low);
} else {
dev_dbg(&adev->dev, "GPIO: looking up %d in _CRS\n", index);
- lookup.adev = adev;
+ lookup.info.adev = adev;
}
ret = acpi_gpio_resource_lookup(&lookup, info);
@@ -664,7 +687,6 @@ struct gpio_desc *acpi_find_gpio(struct device *dev,
struct acpi_gpio_info info;
struct gpio_desc *desc;
char propname[32];
- int err;
int i;
/* Try first from _DSD */
@@ -703,10 +725,7 @@ struct gpio_desc *acpi_find_gpio(struct device *dev,
if (info.polarity == GPIO_ACTIVE_LOW)
*lookupflags |= GPIO_ACTIVE_LOW;
- err = acpi_gpio_update_gpiod_flags(dflags, info.flags);
- if (err)
- dev_dbg(dev, "Override GPIO initialization flags\n");
-
+ acpi_gpio_update_gpiod_flags(dflags, &info);
return desc;
}