Commit 289b7bfd authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'gpio-v4.6-3' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio

Pull GPIO fixes from Linus Walleij:
 "Here is a set of four GPIO fixes.  The two fixes to the core are
  serious as they are regressing minor architectures.

  Core fixes:

   - Defer GPIO device setup until after gpiolib is initialized.

     It turns out that a few very tightly integrated GPIO platform
     drivers initialize so early (befor core_initcall()) so that the
     gpiolib isn't even initialized itself.  That limits what the
     library can do, and we cannot reference uninitialized fields until
     later.

     Defer some of the initialization until right after the gpiolib is
     initialized in these (rare) cases.

   - As a consequence: do not use devm_* resources when allocating the
     states in the initial set-up of the gpiochip.

  Driver fixes:

   - In ACPI retrieveal: ignore GpioInt when looking for output GPIOs.

   - Fix legacy builds on the PXA without a backing pin controller.

   - Use correct datatype on pca953x register writes"

* tag 'gpio-v4.6-3' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio:
  gpio: pca953x: Use correct u16 value for register word write
  gpiolib: Defer gpio device setup until after gpiolib initialization
  gpiolib: Do not use devm functions when registering gpio chip
  gpio: pxa: fix legacy non pinctrl aware builds
  gpio / ACPI: ignore GpioInt() GPIOs when requesting GPIO_OUT_*
parents 183c948a 9b8e3ec3
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/platform_data/pca953x.h> #include <linux/platform_data/pca953x.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <asm/unaligned.h>
#include <linux/of_platform.h> #include <linux/of_platform.h>
#include <linux/acpi.h> #include <linux/acpi.h>
...@@ -159,7 +160,7 @@ static int pca953x_write_regs(struct pca953x_chip *chip, int reg, u8 *val) ...@@ -159,7 +160,7 @@ static int pca953x_write_regs(struct pca953x_chip *chip, int reg, u8 *val)
switch (chip->chip_type) { switch (chip->chip_type) {
case PCA953X_TYPE: case PCA953X_TYPE:
ret = i2c_smbus_write_word_data(chip->client, ret = i2c_smbus_write_word_data(chip->client,
reg << 1, (u16) *val); reg << 1, cpu_to_le16(get_unaligned((u16 *)val)));
break; break;
case PCA957X_TYPE: case PCA957X_TYPE:
ret = i2c_smbus_write_byte_data(chip->client, reg << 1, ret = i2c_smbus_write_byte_data(chip->client, reg << 1,
......
...@@ -283,8 +283,8 @@ static int pxa_gpio_direction_output(struct gpio_chip *chip, ...@@ -283,8 +283,8 @@ static int pxa_gpio_direction_output(struct gpio_chip *chip,
writel_relaxed(mask, base + (value ? GPSR_OFFSET : GPCR_OFFSET)); writel_relaxed(mask, base + (value ? GPSR_OFFSET : GPCR_OFFSET));
ret = pinctrl_gpio_direction_output(chip->base + offset); ret = pinctrl_gpio_direction_output(chip->base + offset);
if (!ret) if (ret)
return 0; return ret;
spin_lock_irqsave(&gpio_lock, flags); spin_lock_irqsave(&gpio_lock, flags);
......
...@@ -68,6 +68,7 @@ LIST_HEAD(gpio_devices); ...@@ -68,6 +68,7 @@ LIST_HEAD(gpio_devices);
static void gpiochip_free_hogs(struct gpio_chip *chip); static void gpiochip_free_hogs(struct gpio_chip *chip);
static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip); static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip);
static bool gpiolib_initialized;
static inline void desc_set_label(struct gpio_desc *d, const char *label) static inline void desc_set_label(struct gpio_desc *d, const char *label)
{ {
...@@ -440,9 +441,63 @@ static void gpiodevice_release(struct device *dev) ...@@ -440,9 +441,63 @@ static void gpiodevice_release(struct device *dev)
cdev_del(&gdev->chrdev); cdev_del(&gdev->chrdev);
list_del(&gdev->list); list_del(&gdev->list);
ida_simple_remove(&gpio_ida, gdev->id); ida_simple_remove(&gpio_ida, gdev->id);
kfree(gdev->label);
kfree(gdev->descs);
kfree(gdev); kfree(gdev);
} }
static int gpiochip_setup_dev(struct gpio_device *gdev)
{
int status;
cdev_init(&gdev->chrdev, &gpio_fileops);
gdev->chrdev.owner = THIS_MODULE;
gdev->chrdev.kobj.parent = &gdev->dev.kobj;
gdev->dev.devt = MKDEV(MAJOR(gpio_devt), gdev->id);
status = cdev_add(&gdev->chrdev, gdev->dev.devt, 1);
if (status < 0)
chip_warn(gdev->chip, "failed to add char device %d:%d\n",
MAJOR(gpio_devt), gdev->id);
else
chip_dbg(gdev->chip, "added GPIO chardev (%d:%d)\n",
MAJOR(gpio_devt), gdev->id);
status = device_add(&gdev->dev);
if (status)
goto err_remove_chardev;
status = gpiochip_sysfs_register(gdev);
if (status)
goto err_remove_device;
/* From this point, the .release() function cleans up gpio_device */
gdev->dev.release = gpiodevice_release;
get_device(&gdev->dev);
pr_debug("%s: registered GPIOs %d to %d on device: %s (%s)\n",
__func__, gdev->base, gdev->base + gdev->ngpio - 1,
dev_name(&gdev->dev), gdev->chip->label ? : "generic");
return 0;
err_remove_device:
device_del(&gdev->dev);
err_remove_chardev:
cdev_del(&gdev->chrdev);
return status;
}
static void gpiochip_setup_devs(void)
{
struct gpio_device *gdev;
int err;
list_for_each_entry(gdev, &gpio_devices, list) {
err = gpiochip_setup_dev(gdev);
if (err)
pr_err("%s: Failed to initialize gpio device (%d)\n",
dev_name(&gdev->dev), err);
}
}
/** /**
* gpiochip_add_data() - register a gpio_chip * gpiochip_add_data() - register a gpio_chip
* @chip: the chip to register, with chip->base initialized * @chip: the chip to register, with chip->base initialized
...@@ -457,6 +512,9 @@ static void gpiodevice_release(struct device *dev) ...@@ -457,6 +512,9 @@ static void gpiodevice_release(struct device *dev)
* the gpio framework's arch_initcall(). Otherwise sysfs initialization * the gpio framework's arch_initcall(). Otherwise sysfs initialization
* for GPIOs will fail rudely. * for GPIOs will fail rudely.
* *
* gpiochip_add_data() must only be called after gpiolib initialization,
* ie after core_initcall().
*
* If chip->base is negative, this requests dynamic assignment of * If chip->base is negative, this requests dynamic assignment of
* a range of valid GPIOs. * a range of valid GPIOs.
*/ */
...@@ -504,8 +562,7 @@ int gpiochip_add_data(struct gpio_chip *chip, void *data) ...@@ -504,8 +562,7 @@ int gpiochip_add_data(struct gpio_chip *chip, void *data)
else else
gdev->owner = THIS_MODULE; gdev->owner = THIS_MODULE;
gdev->descs = devm_kcalloc(&gdev->dev, chip->ngpio, gdev->descs = kcalloc(chip->ngpio, sizeof(gdev->descs[0]), GFP_KERNEL);
sizeof(gdev->descs[0]), GFP_KERNEL);
if (!gdev->descs) { if (!gdev->descs) {
status = -ENOMEM; status = -ENOMEM;
goto err_free_gdev; goto err_free_gdev;
...@@ -514,16 +571,16 @@ int gpiochip_add_data(struct gpio_chip *chip, void *data) ...@@ -514,16 +571,16 @@ int gpiochip_add_data(struct gpio_chip *chip, void *data)
if (chip->ngpio == 0) { if (chip->ngpio == 0) {
chip_err(chip, "tried to insert a GPIO chip with zero lines\n"); chip_err(chip, "tried to insert a GPIO chip with zero lines\n");
status = -EINVAL; status = -EINVAL;
goto err_free_gdev; goto err_free_descs;
} }
if (chip->label) if (chip->label)
gdev->label = devm_kstrdup(&gdev->dev, chip->label, GFP_KERNEL); gdev->label = kstrdup(chip->label, GFP_KERNEL);
else else
gdev->label = devm_kstrdup(&gdev->dev, "unknown", GFP_KERNEL); gdev->label = kstrdup("unknown", GFP_KERNEL);
if (!gdev->label) { if (!gdev->label) {
status = -ENOMEM; status = -ENOMEM;
goto err_free_gdev; goto err_free_descs;
} }
gdev->ngpio = chip->ngpio; gdev->ngpio = chip->ngpio;
...@@ -543,7 +600,7 @@ int gpiochip_add_data(struct gpio_chip *chip, void *data) ...@@ -543,7 +600,7 @@ int gpiochip_add_data(struct gpio_chip *chip, void *data)
if (base < 0) { if (base < 0) {
status = base; status = base;
spin_unlock_irqrestore(&gpio_lock, flags); spin_unlock_irqrestore(&gpio_lock, flags);
goto err_free_gdev; goto err_free_label;
} }
/* /*
* TODO: it should not be necessary to reflect the assigned * TODO: it should not be necessary to reflect the assigned
...@@ -558,7 +615,7 @@ int gpiochip_add_data(struct gpio_chip *chip, void *data) ...@@ -558,7 +615,7 @@ int gpiochip_add_data(struct gpio_chip *chip, void *data)
status = gpiodev_add_to_list(gdev); status = gpiodev_add_to_list(gdev);
if (status) { if (status) {
spin_unlock_irqrestore(&gpio_lock, flags); spin_unlock_irqrestore(&gpio_lock, flags);
goto err_free_gdev; goto err_free_label;
} }
for (i = 0; i < chip->ngpio; i++) { for (i = 0; i < chip->ngpio; i++) {
...@@ -596,39 +653,16 @@ int gpiochip_add_data(struct gpio_chip *chip, void *data) ...@@ -596,39 +653,16 @@ int gpiochip_add_data(struct gpio_chip *chip, void *data)
* we get a device node entry in sysfs under * we get a device node entry in sysfs under
* /sys/bus/gpio/devices/gpiochipN/dev that can be used for * /sys/bus/gpio/devices/gpiochipN/dev that can be used for
* coldplug of device nodes and other udev business. * coldplug of device nodes and other udev business.
* We can do this only if gpiolib has been initialized.
* Otherwise, defer until later.
*/ */
cdev_init(&gdev->chrdev, &gpio_fileops); if (gpiolib_initialized) {
gdev->chrdev.owner = THIS_MODULE; status = gpiochip_setup_dev(gdev);
gdev->chrdev.kobj.parent = &gdev->dev.kobj;
gdev->dev.devt = MKDEV(MAJOR(gpio_devt), gdev->id);
status = cdev_add(&gdev->chrdev, gdev->dev.devt, 1);
if (status < 0)
chip_warn(chip, "failed to add char device %d:%d\n",
MAJOR(gpio_devt), gdev->id);
else
chip_dbg(chip, "added GPIO chardev (%d:%d)\n",
MAJOR(gpio_devt), gdev->id);
status = device_add(&gdev->dev);
if (status) if (status)
goto err_remove_chardev; goto err_remove_chip;
}
status = gpiochip_sysfs_register(gdev);
if (status)
goto err_remove_device;
/* From this point, the .release() function cleans up gpio_device */
gdev->dev.release = gpiodevice_release;
get_device(&gdev->dev);
pr_debug("%s: registered GPIOs %d to %d on device: %s (%s)\n",
__func__, gdev->base, gdev->base + gdev->ngpio - 1,
dev_name(&gdev->dev), chip->label ? : "generic");
return 0; return 0;
err_remove_device:
device_del(&gdev->dev);
err_remove_chardev:
cdev_del(&gdev->chrdev);
err_remove_chip: err_remove_chip:
acpi_gpiochip_remove(chip); acpi_gpiochip_remove(chip);
gpiochip_free_hogs(chip); gpiochip_free_hogs(chip);
...@@ -637,6 +671,10 @@ int gpiochip_add_data(struct gpio_chip *chip, void *data) ...@@ -637,6 +671,10 @@ int gpiochip_add_data(struct gpio_chip *chip, void *data)
spin_lock_irqsave(&gpio_lock, flags); spin_lock_irqsave(&gpio_lock, flags);
list_del(&gdev->list); list_del(&gdev->list);
spin_unlock_irqrestore(&gpio_lock, flags); spin_unlock_irqrestore(&gpio_lock, flags);
err_free_label:
kfree(gdev->label);
err_free_descs:
kfree(gdev->descs);
err_free_gdev: err_free_gdev:
ida_simple_remove(&gpio_ida, gdev->id); ida_simple_remove(&gpio_ida, gdev->id);
/* failures here can mean systems won't boot... */ /* failures here can mean systems won't boot... */
...@@ -2231,9 +2269,11 @@ static struct gpio_desc *of_find_gpio(struct device *dev, const char *con_id, ...@@ -2231,9 +2269,11 @@ static struct gpio_desc *of_find_gpio(struct device *dev, const char *con_id,
return desc; return desc;
} }
static struct gpio_desc *acpi_find_gpio(struct device *dev, const char *con_id, static struct gpio_desc *acpi_find_gpio(struct device *dev,
const char *con_id,
unsigned int idx, unsigned int idx,
enum gpio_lookup_flags *flags) enum gpiod_flags flags,
enum gpio_lookup_flags *lookupflags)
{ {
struct acpi_device *adev = ACPI_COMPANION(dev); struct acpi_device *adev = ACPI_COMPANION(dev);
struct acpi_gpio_info info; struct acpi_gpio_info info;
...@@ -2264,10 +2304,16 @@ static struct gpio_desc *acpi_find_gpio(struct device *dev, const char *con_id, ...@@ -2264,10 +2304,16 @@ static struct gpio_desc *acpi_find_gpio(struct device *dev, const char *con_id,
desc = acpi_get_gpiod_by_index(adev, NULL, idx, &info); desc = acpi_get_gpiod_by_index(adev, NULL, idx, &info);
if (IS_ERR(desc)) if (IS_ERR(desc))
return desc; return desc;
if ((flags == GPIOD_OUT_LOW || flags == GPIOD_OUT_HIGH) &&
info.gpioint) {
dev_dbg(dev, "refusing GpioInt() entry when doing GPIOD_OUT_* lookup\n");
return ERR_PTR(-ENOENT);
}
} }
if (info.polarity == GPIO_ACTIVE_LOW) if (info.polarity == GPIO_ACTIVE_LOW)
*flags |= GPIO_ACTIVE_LOW; *lookupflags |= GPIO_ACTIVE_LOW;
return desc; return desc;
} }
...@@ -2530,7 +2576,7 @@ struct gpio_desc *__must_check gpiod_get_index(struct device *dev, ...@@ -2530,7 +2576,7 @@ struct gpio_desc *__must_check gpiod_get_index(struct device *dev,
desc = of_find_gpio(dev, con_id, idx, &lookupflags); desc = of_find_gpio(dev, con_id, idx, &lookupflags);
} else if (ACPI_COMPANION(dev)) { } else if (ACPI_COMPANION(dev)) {
dev_dbg(dev, "using ACPI for GPIO lookup\n"); dev_dbg(dev, "using ACPI for GPIO lookup\n");
desc = acpi_find_gpio(dev, con_id, idx, &lookupflags); desc = acpi_find_gpio(dev, con_id, idx, flags, &lookupflags);
} }
} }
...@@ -2829,6 +2875,9 @@ static int __init gpiolib_dev_init(void) ...@@ -2829,6 +2875,9 @@ static int __init gpiolib_dev_init(void)
if (ret < 0) { if (ret < 0) {
pr_err("gpiolib: failed to allocate char dev region\n"); pr_err("gpiolib: failed to allocate char dev region\n");
bus_unregister(&gpio_bus_type); bus_unregister(&gpio_bus_type);
} else {
gpiolib_initialized = true;
gpiochip_setup_devs();
} }
return ret; return ret;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment