mirror of
https://github.com/torvalds/linux.git
synced 2024-11-27 22:51:35 +00:00
GPIO fixes for the V4.6 series:
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. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJXCVYaAAoJEEEQszewGV1z/MEQALfOdb+7WO/45qEtZCMpU2ih LOm60aiIdvVggsibeiGlHRbIF97P9z9GVD5nI3NJ7QPVDgKmqhL9ma+jAxxdUnpt AOs3Yd/sdThocfb9UsqHkPxVC/vge7TEU9EUDnLSx5UMaHO6tsBrUB06y3mDM01f X1nLtQweuEMYOutIVF9VaOx6DeFbVV4RqpxEHPbzPf4oAJrqreWqduPzxdYbdphs +hsm4sCodsjANiNtWjZpdEUFnw+MFRjOS234jKxMiC3xIdp4pO1NlqLxWTcK3N9Y WdxiAdrKEPq/5IUlt4R0shOL7e0o60nIJIlczxrAp4Z6jCKw+WYGIB/iIfh0rLq+ /M4Awgrn3rUAs5jcJ4n7dm9QdCMd0XXw8+maLpYkYXa7rKHrUDyIC55L/DTSuoIY XwfdKd0Eyapa+iNhFmxQ6EWqH3JZCOv1IHQ65BbVXGzef2Voy6exCAKScF9vM7bV V2ydyrYOt++6stdS2KCbTgipLAeInXqXk0Xag5uPw0zGeJgYfhdYW5+2xfYp2PWD v9Z6VNkrF8u9AxGS3tq8Z/RMBR2dCyL2nFUi+TKx0cu3zbjGOEPOHfV45Tid59Jd YroHLBpRIB77srsKHcC3ZBtKbtt4idyzbYJHTni7XBT3F7pM/xUV37R1ZpWPrYAS JA/fhOSAuy7YnaV1CQFL =X4YD -----END PGP SIGNATURE----- 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_*
This commit is contained in:
commit
289b7bfd48
@ -18,6 +18,7 @@
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/platform_data/pca953x.h>
|
||||
#include <linux/slab.h>
|
||||
#include <asm/unaligned.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/acpi.h>
|
||||
|
||||
@ -159,7 +160,7 @@ static int pca953x_write_regs(struct pca953x_chip *chip, int reg, u8 *val)
|
||||
switch (chip->chip_type) {
|
||||
case PCA953X_TYPE:
|
||||
ret = i2c_smbus_write_word_data(chip->client,
|
||||
reg << 1, (u16) *val);
|
||||
reg << 1, cpu_to_le16(get_unaligned((u16 *)val)));
|
||||
break;
|
||||
case PCA957X_TYPE:
|
||||
ret = i2c_smbus_write_byte_data(chip->client, reg << 1,
|
||||
|
@ -283,8 +283,8 @@ static int pxa_gpio_direction_output(struct gpio_chip *chip,
|
||||
writel_relaxed(mask, base + (value ? GPSR_OFFSET : GPCR_OFFSET));
|
||||
|
||||
ret = pinctrl_gpio_direction_output(chip->base + offset);
|
||||
if (!ret)
|
||||
return 0;
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
spin_lock_irqsave(&gpio_lock, flags);
|
||||
|
||||
|
@ -68,6 +68,7 @@ LIST_HEAD(gpio_devices);
|
||||
static void gpiochip_free_hogs(struct gpio_chip *chip);
|
||||
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)
|
||||
{
|
||||
@ -440,9 +441,63 @@ static void gpiodevice_release(struct device *dev)
|
||||
cdev_del(&gdev->chrdev);
|
||||
list_del(&gdev->list);
|
||||
ida_simple_remove(&gpio_ida, gdev->id);
|
||||
kfree(gdev->label);
|
||||
kfree(gdev->descs);
|
||||
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
|
||||
* @chip: the chip to register, with chip->base initialized
|
||||
@ -457,6 +512,9 @@ static void gpiodevice_release(struct device *dev)
|
||||
* the gpio framework's arch_initcall(). Otherwise sysfs initialization
|
||||
* 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
|
||||
* a range of valid GPIOs.
|
||||
*/
|
||||
@ -504,8 +562,7 @@ int gpiochip_add_data(struct gpio_chip *chip, void *data)
|
||||
else
|
||||
gdev->owner = THIS_MODULE;
|
||||
|
||||
gdev->descs = devm_kcalloc(&gdev->dev, chip->ngpio,
|
||||
sizeof(gdev->descs[0]), GFP_KERNEL);
|
||||
gdev->descs = kcalloc(chip->ngpio, sizeof(gdev->descs[0]), GFP_KERNEL);
|
||||
if (!gdev->descs) {
|
||||
status = -ENOMEM;
|
||||
goto err_free_gdev;
|
||||
@ -514,16 +571,16 @@ int gpiochip_add_data(struct gpio_chip *chip, void *data)
|
||||
if (chip->ngpio == 0) {
|
||||
chip_err(chip, "tried to insert a GPIO chip with zero lines\n");
|
||||
status = -EINVAL;
|
||||
goto err_free_gdev;
|
||||
goto err_free_descs;
|
||||
}
|
||||
|
||||
if (chip->label)
|
||||
gdev->label = devm_kstrdup(&gdev->dev, chip->label, GFP_KERNEL);
|
||||
gdev->label = kstrdup(chip->label, GFP_KERNEL);
|
||||
else
|
||||
gdev->label = devm_kstrdup(&gdev->dev, "unknown", GFP_KERNEL);
|
||||
gdev->label = kstrdup("unknown", GFP_KERNEL);
|
||||
if (!gdev->label) {
|
||||
status = -ENOMEM;
|
||||
goto err_free_gdev;
|
||||
goto err_free_descs;
|
||||
}
|
||||
|
||||
gdev->ngpio = chip->ngpio;
|
||||
@ -543,7 +600,7 @@ int gpiochip_add_data(struct gpio_chip *chip, void *data)
|
||||
if (base < 0) {
|
||||
status = base;
|
||||
spin_unlock_irqrestore(&gpio_lock, flags);
|
||||
goto err_free_gdev;
|
||||
goto err_free_label;
|
||||
}
|
||||
/*
|
||||
* TODO: it should not be necessary to reflect the assigned
|
||||
@ -558,7 +615,7 @@ int gpiochip_add_data(struct gpio_chip *chip, void *data)
|
||||
status = gpiodev_add_to_list(gdev);
|
||||
if (status) {
|
||||
spin_unlock_irqrestore(&gpio_lock, flags);
|
||||
goto err_free_gdev;
|
||||
goto err_free_label;
|
||||
}
|
||||
|
||||
for (i = 0; i < chip->ngpio; i++) {
|
||||
@ -596,39 +653,16 @@ int gpiochip_add_data(struct gpio_chip *chip, void *data)
|
||||
* we get a device node entry in sysfs under
|
||||
* /sys/bus/gpio/devices/gpiochipN/dev that can be used for
|
||||
* 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);
|
||||
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(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)
|
||||
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), chip->label ? : "generic");
|
||||
|
||||
if (gpiolib_initialized) {
|
||||
status = gpiochip_setup_dev(gdev);
|
||||
if (status)
|
||||
goto err_remove_chip;
|
||||
}
|
||||
return 0;
|
||||
|
||||
err_remove_device:
|
||||
device_del(&gdev->dev);
|
||||
err_remove_chardev:
|
||||
cdev_del(&gdev->chrdev);
|
||||
err_remove_chip:
|
||||
acpi_gpiochip_remove(chip);
|
||||
gpiochip_free_hogs(chip);
|
||||
@ -637,6 +671,10 @@ err_remove_from_list:
|
||||
spin_lock_irqsave(&gpio_lock, flags);
|
||||
list_del(&gdev->list);
|
||||
spin_unlock_irqrestore(&gpio_lock, flags);
|
||||
err_free_label:
|
||||
kfree(gdev->label);
|
||||
err_free_descs:
|
||||
kfree(gdev->descs);
|
||||
err_free_gdev:
|
||||
ida_simple_remove(&gpio_ida, gdev->id);
|
||||
/* 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,
|
||||
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,
|
||||
enum gpio_lookup_flags *flags)
|
||||
enum gpiod_flags flags,
|
||||
enum gpio_lookup_flags *lookupflags)
|
||||
{
|
||||
struct acpi_device *adev = ACPI_COMPANION(dev);
|
||||
struct acpi_gpio_info info;
|
||||
@ -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);
|
||||
if (IS_ERR(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)
|
||||
*flags |= GPIO_ACTIVE_LOW;
|
||||
*lookupflags |= GPIO_ACTIVE_LOW;
|
||||
|
||||
return desc;
|
||||
}
|
||||
@ -2530,7 +2576,7 @@ struct gpio_desc *__must_check gpiod_get_index(struct device *dev,
|
||||
desc = of_find_gpio(dev, con_id, idx, &lookupflags);
|
||||
} else if (ACPI_COMPANION(dev)) {
|
||||
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)
|
||||
if (ret < 0) {
|
||||
pr_err("gpiolib: failed to allocate char dev region\n");
|
||||
bus_unregister(&gpio_bus_type);
|
||||
} else {
|
||||
gpiolib_initialized = true;
|
||||
gpiochip_setup_devs();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user