aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpio/gpiolib.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpio/gpiolib.c')
-rw-r--r--drivers/gpio/gpiolib.c1307
1 files changed, 743 insertions, 564 deletions
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 4d0106ceeba7..40f2d7f69be2 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -81,14 +81,14 @@ LIST_HEAD(gpio_devices);
static DEFINE_MUTEX(gpio_machine_hogs_mutex);
static LIST_HEAD(gpio_machine_hogs);
-static void gpiochip_free_hogs(struct gpio_chip *chip);
-static int gpiochip_add_irqchip(struct gpio_chip *gpiochip,
+static void gpiochip_free_hogs(struct gpio_chip *gc);
+static int gpiochip_add_irqchip(struct gpio_chip *gc,
struct lock_class_key *lock_key,
struct lock_class_key *request_key);
-static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip);
-static int gpiochip_irqchip_init_hw(struct gpio_chip *gpiochip);
-static int gpiochip_irqchip_init_valid_mask(struct gpio_chip *gpiochip);
-static void gpiochip_irqchip_free_valid_mask(struct gpio_chip *gpiochip);
+static void gpiochip_irqchip_remove(struct gpio_chip *gc);
+static int gpiochip_irqchip_init_hw(struct gpio_chip *gc);
+static int gpiochip_irqchip_init_valid_mask(struct gpio_chip *gc);
+static void gpiochip_irqchip_free_valid_mask(struct gpio_chip *gc);
static bool gpiolib_initialized;
@@ -132,23 +132,24 @@ EXPORT_SYMBOL_GPL(gpio_to_desc);
/**
* gpiochip_get_desc - get the GPIO descriptor corresponding to the given
* hardware number for this chip
- * @chip: GPIO chip
+ * @gc: GPIO chip
* @hwnum: hardware number of the GPIO for this chip
*
* Returns:
- * A pointer to the GPIO descriptor or %ERR_PTR(-EINVAL) if no GPIO exists
+ * A pointer to the GPIO descriptor or ``ERR_PTR(-EINVAL)`` if no GPIO exists
* in the given chip for the specified hardware number.
*/
-struct gpio_desc *gpiochip_get_desc(struct gpio_chip *chip,
+struct gpio_desc *gpiochip_get_desc(struct gpio_chip *gc,
unsigned int hwnum)
{
- struct gpio_device *gdev = chip->gpiodev;
+ struct gpio_device *gdev = gc->gpiodev;
if (hwnum >= gdev->ngpio)
return ERR_PTR(-EINVAL);
return &gdev->descs[hwnum];
}
+EXPORT_SYMBOL_GPL(gpiochip_get_desc);
/**
* desc_to_gpio - convert a GPIO descriptor to the integer namespace
@@ -213,11 +214,11 @@ static int gpiochip_find_base(int ngpio)
*/
int gpiod_get_direction(struct gpio_desc *desc)
{
- struct gpio_chip *chip;
+ struct gpio_chip *gc;
unsigned offset;
int ret;
- chip = gpiod_to_chip(desc);
+ gc = gpiod_to_chip(desc);
offset = gpio_chip_hwgpio(desc);
/*
@@ -228,10 +229,10 @@ int gpiod_get_direction(struct gpio_desc *desc)
test_bit(FLAG_IS_OUT, &desc->flags))
return 0;
- if (!chip->get_direction)
+ if (!gc->get_direction)
return -ENOTSUPP;
- ret = chip->get_direction(chip, offset);
+ ret = gc->get_direction(gc, offset);
if (ret < 0)
return ret;
@@ -301,6 +302,9 @@ static struct gpio_desc *gpio_name_to_desc(const char * const name)
struct gpio_device *gdev;
unsigned long flags;
+ if (!name)
+ return NULL;
+
spin_lock_irqsave(&gpio_lock, flags);
list_for_each_entry(gdev, &gpio_devices, list) {
@@ -309,7 +313,7 @@ static struct gpio_desc *gpio_name_to_desc(const char * const name)
for (i = 0; i != gdev->ngpio; ++i) {
struct gpio_desc *desc = &gdev->descs[i];
- if (!desc->name || !name)
+ if (!desc->name)
continue;
if (!strcmp(desc->name, name)) {
@@ -356,16 +360,16 @@ static int gpiochip_set_desc_names(struct gpio_chip *gc)
return 0;
}
-static unsigned long *gpiochip_allocate_mask(struct gpio_chip *chip)
+static unsigned long *gpiochip_allocate_mask(struct gpio_chip *gc)
{
unsigned long *p;
- p = bitmap_alloc(chip->ngpio, GFP_KERNEL);
+ p = bitmap_alloc(gc->ngpio, GFP_KERNEL);
if (!p)
return NULL;
/* Assume by default all GPIOs are valid */
- bitmap_fill(p, chip->ngpio);
+ bitmap_fill(p, gc->ngpio);
return p;
}
@@ -392,10 +396,10 @@ static int gpiochip_init_valid_mask(struct gpio_chip *gc)
return 0;
}
-static void gpiochip_free_valid_mask(struct gpio_chip *gpiochip)
+static void gpiochip_free_valid_mask(struct gpio_chip *gc)
{
- bitmap_free(gpiochip->valid_mask);
- gpiochip->valid_mask = NULL;
+ bitmap_free(gc->valid_mask);
+ gc->valid_mask = NULL;
}
static int gpiochip_add_pin_ranges(struct gpio_chip *gc)
@@ -406,13 +410,13 @@ static int gpiochip_add_pin_ranges(struct gpio_chip *gc)
return 0;
}
-bool gpiochip_line_is_valid(const struct gpio_chip *gpiochip,
+bool gpiochip_line_is_valid(const struct gpio_chip *gc,
unsigned int offset)
{
/* No mask means all valid */
- if (likely(!gpiochip->valid_mask))
+ if (likely(!gc->valid_mask))
return true;
- return test_bit(offset, gpiochip->valid_mask);
+ return test_bit(offset, gc->valid_mask);
}
EXPORT_SYMBOL_GPL(gpiochip_line_is_valid);
@@ -546,6 +550,9 @@ static long linehandle_set_config(struct linehandle_state *lh,
if (ret)
return ret;
}
+
+ atomic_notifier_call_chain(&desc->gdev->notifier,
+ GPIOLINE_CHANGED_CONFIG, desc);
}
return 0;
}
@@ -787,8 +794,6 @@ out_free_lh:
* @irq: the interrupt that trigger in response to events on this GPIO
* @wait: wait queue that handles blocking reads of events
* @events: KFIFO for the GPIO events
- * @read_lock: mutex lock to protect reads from colliding with adding
- * new events to the FIFO
* @timestamp: cache for the timestamp storing it between hardirq
* and IRQ thread, used to bring the timestamp close to the actual
* event
@@ -801,7 +806,6 @@ struct lineevent_state {
int irq;
wait_queue_head_t wait;
DECLARE_KFIFO(events, struct gpioevent_data, 16);
- struct mutex read_lock;
u64 timestamp;
};
@@ -817,7 +821,7 @@ static __poll_t lineevent_poll(struct file *filep,
poll_wait(filep, &le->wait, wait);
- if (!kfifo_is_empty(&le->events))
+ if (!kfifo_is_empty_spinlocked_noirqsave(&le->events, &le->wait.lock))
events = EPOLLIN | EPOLLRDNORM;
return events;
@@ -830,43 +834,52 @@ static ssize_t lineevent_read(struct file *filep,
loff_t *f_ps)
{
struct lineevent_state *le = filep->private_data;
- unsigned int copied;
+ struct gpioevent_data ge;
+ ssize_t bytes_read = 0;
int ret;
- if (count < sizeof(struct gpioevent_data))
+ if (count < sizeof(ge))
return -EINVAL;
do {
+ spin_lock(&le->wait.lock);
if (kfifo_is_empty(&le->events)) {
- if (filep->f_flags & O_NONBLOCK)
+ if (bytes_read) {
+ spin_unlock(&le->wait.lock);
+ return bytes_read;
+ }
+
+ if (filep->f_flags & O_NONBLOCK) {
+ spin_unlock(&le->wait.lock);
return -EAGAIN;
+ }
- ret = wait_event_interruptible(le->wait,
+ ret = wait_event_interruptible_locked(le->wait,
!kfifo_is_empty(&le->events));
- if (ret)
+ if (ret) {
+ spin_unlock(&le->wait.lock);
return ret;
+ }
}
- if (mutex_lock_interruptible(&le->read_lock))
- return -ERESTARTSYS;
- ret = kfifo_to_user(&le->events, buf, count, &copied);
- mutex_unlock(&le->read_lock);
-
- if (ret)
- return ret;
-
- /*
- * If we couldn't read anything from the fifo (a different
- * thread might have been faster) we either return -EAGAIN if
- * the file descriptor is non-blocking, otherwise we go back to
- * sleep and wait for more data to arrive.
- */
- if (copied == 0 && (filep->f_flags & O_NONBLOCK))
- return -EAGAIN;
+ ret = kfifo_out(&le->events, &ge, 1);
+ spin_unlock(&le->wait.lock);
+ if (ret != 1) {
+ /*
+ * This should never happen - we were holding the lock
+ * from the moment we learned the fifo is no longer
+ * empty until now.
+ */
+ ret = -EIO;
+ break;
+ }
- } while (copied == 0);
+ if (copy_to_user(buf + bytes_read, &ge, sizeof(ge)))
+ return -EFAULT;
+ bytes_read += sizeof(ge);
+ } while (count >= bytes_read + sizeof(ge));
- return copied;
+ return bytes_read;
}
static int lineevent_release(struct inode *inode, struct file *filep)
@@ -945,7 +958,7 @@ static irqreturn_t lineevent_irq_thread(int irq, void *p)
* we didn't get the timestamp from lineevent_irq_handler().
*/
if (!le->timestamp)
- ge.timestamp = ktime_get_real_ns();
+ ge.timestamp = ktime_get_ns();
else
ge.timestamp = le->timestamp;
@@ -968,9 +981,12 @@ static irqreturn_t lineevent_irq_thread(int irq, void *p)
return IRQ_NONE;
}
- ret = kfifo_put(&le->events, ge);
+ ret = kfifo_in_spinlocked_noirqsave(&le->events, &ge,
+ 1, &le->wait.lock);
if (ret)
wake_up_poll(&le->wait, EPOLLIN);
+ else
+ pr_debug_ratelimited("event FIFO is full - event dropped\n");
return IRQ_HANDLED;
}
@@ -983,7 +999,7 @@ static irqreturn_t lineevent_irq_handler(int irq, void *p)
* Just store the timestamp in hardirq context so we get it as
* close in time as possible to the actual event.
*/
- le->timestamp = ktime_get_real_ns();
+ le->timestamp = ktime_get_ns();
return IRQ_WAKE_THREAD;
}
@@ -1083,7 +1099,6 @@ static int lineevent_create(struct gpio_device *gdev, void __user *ip)
INIT_KFIFO(le->events);
init_waitqueue_head(&le->wait);
- mutex_init(&le->read_lock);
/* Request a thread to read the events */
ret = request_threaded_irq(le->irq,
@@ -1139,17 +1154,82 @@ out_free_le:
return ret;
}
+static void gpio_desc_to_lineinfo(struct gpio_desc *desc,
+ struct gpioline_info *info)
+{
+ struct gpio_chip *gc = desc->gdev->chip;
+ unsigned long flags;
+
+ spin_lock_irqsave(&gpio_lock, flags);
+
+ if (desc->name) {
+ strncpy(info->name, desc->name, sizeof(info->name));
+ info->name[sizeof(info->name) - 1] = '\0';
+ } else {
+ info->name[0] = '\0';
+ }
+
+ if (desc->label) {
+ strncpy(info->consumer, desc->label, sizeof(info->consumer));
+ info->consumer[sizeof(info->consumer) - 1] = '\0';
+ } else {
+ info->consumer[0] = '\0';
+ }
+
+ /*
+ * Userspace only need to know that the kernel is using this GPIO so
+ * it can't use it.
+ */
+ info->flags = 0;
+ if (test_bit(FLAG_REQUESTED, &desc->flags) ||
+ test_bit(FLAG_IS_HOGGED, &desc->flags) ||
+ test_bit(FLAG_USED_AS_IRQ, &desc->flags) ||
+ test_bit(FLAG_EXPORT, &desc->flags) ||
+ test_bit(FLAG_SYSFS, &desc->flags) ||
+ !pinctrl_gpio_can_use_line(gc->base + info->line_offset))
+ info->flags |= GPIOLINE_FLAG_KERNEL;
+ if (test_bit(FLAG_IS_OUT, &desc->flags))
+ info->flags |= GPIOLINE_FLAG_IS_OUT;
+ if (test_bit(FLAG_ACTIVE_LOW, &desc->flags))
+ info->flags |= GPIOLINE_FLAG_ACTIVE_LOW;
+ if (test_bit(FLAG_OPEN_DRAIN, &desc->flags))
+ info->flags |= (GPIOLINE_FLAG_OPEN_DRAIN |
+ GPIOLINE_FLAG_IS_OUT);
+ if (test_bit(FLAG_OPEN_SOURCE, &desc->flags))
+ info->flags |= (GPIOLINE_FLAG_OPEN_SOURCE |
+ GPIOLINE_FLAG_IS_OUT);
+ if (test_bit(FLAG_BIAS_DISABLE, &desc->flags))
+ info->flags |= GPIOLINE_FLAG_BIAS_DISABLE;
+ if (test_bit(FLAG_PULL_DOWN, &desc->flags))
+ info->flags |= GPIOLINE_FLAG_BIAS_PULL_DOWN;
+ if (test_bit(FLAG_PULL_UP, &desc->flags))
+ info->flags |= GPIOLINE_FLAG_BIAS_PULL_UP;
+
+ spin_unlock_irqrestore(&gpio_lock, flags);
+}
+
+struct gpio_chardev_data {
+ struct gpio_device *gdev;
+ wait_queue_head_t wait;
+ DECLARE_KFIFO(events, struct gpioline_info_changed, 32);
+ struct notifier_block lineinfo_changed_nb;
+ unsigned long *watched_lines;
+};
+
/*
* gpio_ioctl() - ioctl handler for the GPIO chardev
*/
static long gpio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
- struct gpio_device *gdev = filp->private_data;
- struct gpio_chip *chip = gdev->chip;
+ struct gpio_chardev_data *priv = filp->private_data;
+ struct gpio_device *gdev = priv->gdev;
+ struct gpio_chip *gc = gdev->chip;
void __user *ip = (void __user *)arg;
+ struct gpio_desc *desc;
+ __u32 offset;
/* We fail any subsequent ioctl():s when the chip is gone */
- if (!chip)
+ if (!gc)
return -ENODEV;
/* Fill in the struct and pass to userspace */
@@ -1168,68 +1248,40 @@ static long gpio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
if (copy_to_user(ip, &chipinfo, sizeof(chipinfo)))
return -EFAULT;
return 0;
- } else if (cmd == GPIO_GET_LINEINFO_IOCTL) {
+ } else if (cmd == GPIO_GET_LINEINFO_IOCTL ||
+ cmd == GPIO_GET_LINEINFO_WATCH_IOCTL) {
struct gpioline_info lineinfo;
- struct gpio_desc *desc;
if (copy_from_user(&lineinfo, ip, sizeof(lineinfo)))
return -EFAULT;
- desc = gpiochip_get_desc(chip, lineinfo.line_offset);
+ desc = gpiochip_get_desc(gc, lineinfo.line_offset);
if (IS_ERR(desc))
return PTR_ERR(desc);
- if (desc->name) {
- strncpy(lineinfo.name, desc->name,
- sizeof(lineinfo.name));
- lineinfo.name[sizeof(lineinfo.name)-1] = '\0';
- } else {
- lineinfo.name[0] = '\0';
- }
- if (desc->label) {
- strncpy(lineinfo.consumer, desc->label,
- sizeof(lineinfo.consumer));
- lineinfo.consumer[sizeof(lineinfo.consumer)-1] = '\0';
- } else {
- lineinfo.consumer[0] = '\0';
- }
-
- /*
- * Userspace only need to know that the kernel is using
- * this GPIO so it can't use it.
- */
- lineinfo.flags = 0;
- if (test_bit(FLAG_REQUESTED, &desc->flags) ||
- test_bit(FLAG_IS_HOGGED, &desc->flags) ||
- test_bit(FLAG_USED_AS_IRQ, &desc->flags) ||
- test_bit(FLAG_EXPORT, &desc->flags) ||
- test_bit(FLAG_SYSFS, &desc->flags) ||
- !pinctrl_gpio_can_use_line(chip->base + lineinfo.line_offset))
- lineinfo.flags |= GPIOLINE_FLAG_KERNEL;
- if (test_bit(FLAG_IS_OUT, &desc->flags))
- lineinfo.flags |= GPIOLINE_FLAG_IS_OUT;
- if (test_bit(FLAG_ACTIVE_LOW, &desc->flags))
- lineinfo.flags |= GPIOLINE_FLAG_ACTIVE_LOW;
- if (test_bit(FLAG_OPEN_DRAIN, &desc->flags))
- lineinfo.flags |= (GPIOLINE_FLAG_OPEN_DRAIN |
- GPIOLINE_FLAG_IS_OUT);
- if (test_bit(FLAG_OPEN_SOURCE, &desc->flags))
- lineinfo.flags |= (GPIOLINE_FLAG_OPEN_SOURCE |
- GPIOLINE_FLAG_IS_OUT);
- if (test_bit(FLAG_BIAS_DISABLE, &desc->flags))
- lineinfo.flags |= GPIOLINE_FLAG_BIAS_DISABLE;
- if (test_bit(FLAG_PULL_DOWN, &desc->flags))
- lineinfo.flags |= GPIOLINE_FLAG_BIAS_PULL_DOWN;
- if (test_bit(FLAG_PULL_UP, &desc->flags))
- lineinfo.flags |= GPIOLINE_FLAG_BIAS_PULL_UP;
+ gpio_desc_to_lineinfo(desc, &lineinfo);
if (copy_to_user(ip, &lineinfo, sizeof(lineinfo)))
return -EFAULT;
+
+ if (cmd == GPIO_GET_LINEINFO_WATCH_IOCTL)
+ set_bit(gpio_chip_hwgpio(desc), priv->watched_lines);
+
return 0;
} else if (cmd == GPIO_GET_LINEHANDLE_IOCTL) {
return linehandle_create(gdev, ip);
} else if (cmd == GPIO_GET_LINEEVENT_IOCTL) {
return lineevent_create(gdev, ip);
+ } else if (cmd == GPIO_GET_LINEINFO_UNWATCH_IOCTL) {
+ if (copy_from_user(&offset, ip, sizeof(offset)))
+ return -EFAULT;
+
+ desc = gpiochip_get_desc(gc, offset);
+ if (IS_ERR(desc))
+ return PTR_ERR(desc);
+
+ clear_bit(gpio_chip_hwgpio(desc), priv->watched_lines);
+ return 0;
}
return -EINVAL;
}
@@ -1242,6 +1294,101 @@ static long gpio_ioctl_compat(struct file *filp, unsigned int cmd,
}
#endif
+static struct gpio_chardev_data *
+to_gpio_chardev_data(struct notifier_block *nb)
+{
+ return container_of(nb, struct gpio_chardev_data, lineinfo_changed_nb);
+}
+
+static int lineinfo_changed_notify(struct notifier_block *nb,
+ unsigned long action, void *data)
+{
+ struct gpio_chardev_data *priv = to_gpio_chardev_data(nb);
+ struct gpioline_info_changed chg;
+ struct gpio_desc *desc = data;
+ int ret;
+
+ if (!test_bit(gpio_chip_hwgpio(desc), priv->watched_lines))
+ return NOTIFY_DONE;
+
+ memset(&chg, 0, sizeof(chg));
+ chg.info.line_offset = gpio_chip_hwgpio(desc);
+ chg.event_type = action;
+ chg.timestamp = ktime_get_ns();
+ gpio_desc_to_lineinfo(desc, &chg.info);
+
+ ret = kfifo_in_spinlocked(&priv->events, &chg, 1, &priv->wait.lock);
+ if (ret)
+ wake_up_poll(&priv->wait, EPOLLIN);
+ else
+ pr_debug_ratelimited("lineinfo event FIFO is full - event dropped\n");
+
+ return NOTIFY_OK;
+}
+
+static __poll_t lineinfo_watch_poll(struct file *filep,
+ struct poll_table_struct *pollt)
+{
+ struct gpio_chardev_data *priv = filep->private_data;
+ __poll_t events = 0;
+
+ poll_wait(filep, &priv->wait, pollt);
+
+ if (!kfifo_is_empty_spinlocked_noirqsave(&priv->events,
+ &priv->wait.lock))
+ events = EPOLLIN | EPOLLRDNORM;
+
+ return events;
+}
+
+static ssize_t lineinfo_watch_read(struct file *filep, char __user *buf,
+ size_t count, loff_t *off)
+{
+ struct gpio_chardev_data *priv = filep->private_data;
+ struct gpioline_info_changed event;
+ ssize_t bytes_read = 0;
+ int ret;
+
+ if (count < sizeof(event))
+ return -EINVAL;
+
+ do {
+ spin_lock(&priv->wait.lock);
+ if (kfifo_is_empty(&priv->events)) {
+ if (bytes_read) {
+ spin_unlock(&priv->wait.lock);
+ return bytes_read;
+ }
+
+ if (filep->f_flags & O_NONBLOCK) {
+ spin_unlock(&priv->wait.lock);
+ return -EAGAIN;
+ }
+
+ ret = wait_event_interruptible_locked(priv->wait,
+ !kfifo_is_empty(&priv->events));
+ if (ret) {
+ spin_unlock(&priv->wait.lock);
+ return ret;
+ }
+ }
+
+ ret = kfifo_out(&priv->events, &event, 1);
+ spin_unlock(&priv->wait.lock);
+ if (ret != 1) {
+ ret = -EIO;
+ break;
+ /* We should never get here. See lineevent_read(). */
+ }
+
+ if (copy_to_user(buf + bytes_read, &event, sizeof(event)))
+ return -EFAULT;
+ bytes_read += sizeof(event);
+ } while (count >= bytes_read + sizeof(event));
+
+ return bytes_read;
+}
+
/**
* gpio_chrdev_open() - open the chardev for ioctl operations
* @inode: inode for this chardev
@@ -1252,14 +1399,48 @@ static int gpio_chrdev_open(struct inode *inode, struct file *filp)
{
struct gpio_device *gdev = container_of(inode->i_cdev,
struct gpio_device, chrdev);
+ struct gpio_chardev_data *priv;
+ int ret = -ENOMEM;
/* Fail on open if the backing gpiochip is gone */
if (!gdev->chip)
return -ENODEV;
+
+ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->watched_lines = bitmap_zalloc(gdev->chip->ngpio, GFP_KERNEL);
+ if (!priv->watched_lines)
+ goto out_free_priv;
+
+ init_waitqueue_head(&priv->wait);
+ INIT_KFIFO(priv->events);
+ priv->gdev = gdev;
+
+ priv->lineinfo_changed_nb.notifier_call = lineinfo_changed_notify;
+ ret = atomic_notifier_chain_register(&gdev->notifier,
+ &priv->lineinfo_changed_nb);
+ if (ret)
+ goto out_free_bitmap;
+
get_device(&gdev->dev);
- filp->private_data = gdev;
+ filp->private_data = priv;
+
+ ret = nonseekable_open(inode, filp);
+ if (ret)
+ goto out_unregister_notifier;
- return nonseekable_open(inode, filp);
+ return ret;
+
+out_unregister_notifier:
+ atomic_notifier_chain_unregister(&gdev->notifier,
+ &priv->lineinfo_changed_nb);
+out_free_bitmap:
+ bitmap_free(priv->watched_lines);
+out_free_priv:
+ kfree(priv);
+ return ret;
}
/**
@@ -1270,17 +1451,23 @@ static int gpio_chrdev_open(struct inode *inode, struct file *filp)
*/
static int gpio_chrdev_release(struct inode *inode, struct file *filp)
{
- struct gpio_device *gdev = container_of(inode->i_cdev,
- struct gpio_device, chrdev);
+ struct gpio_chardev_data *priv = filp->private_data;
+ struct gpio_device *gdev = priv->gdev;
+ bitmap_free(priv->watched_lines);
+ atomic_notifier_chain_unregister(&gdev->notifier,
+ &priv->lineinfo_changed_nb);
put_device(&gdev->dev);
+ kfree(priv);
+
return 0;
}
-
static const struct file_operations gpio_fileops = {
.release = gpio_chrdev_release,
.open = gpio_chrdev_open,
+ .poll = lineinfo_watch_poll,
+ .read = lineinfo_watch_read,
.owner = THIS_MODULE,
.llseek = no_llseek,
.unlocked_ioctl = gpio_ioctl,
@@ -1332,12 +1519,12 @@ err_remove_device:
return ret;
}
-static void gpiochip_machine_hog(struct gpio_chip *chip, struct gpiod_hog *hog)
+static void gpiochip_machine_hog(struct gpio_chip *gc, struct gpiod_hog *hog)
{
struct gpio_desc *desc;
int rv;
- desc = gpiochip_get_desc(chip, hog->chip_hwnum);
+ desc = gpiochip_get_desc(gc, hog->chip_hwnum);
if (IS_ERR(desc)) {
pr_err("%s: unable to get GPIO desc: %ld\n",
__func__, PTR_ERR(desc));
@@ -1350,18 +1537,18 @@ static void gpiochip_machine_hog(struct gpio_chip *chip, struct gpiod_hog *hog)
rv = gpiod_hog(desc, hog->line_name, hog->lflags, hog->dflags);
if (rv)
pr_err("%s: unable to hog GPIO line (%s:%u): %d\n",
- __func__, chip->label, hog->chip_hwnum, rv);
+ __func__, gc->label, hog->chip_hwnum, rv);
}
-static void machine_gpiochip_add(struct gpio_chip *chip)
+static void machine_gpiochip_add(struct gpio_chip *gc)
{
struct gpiod_hog *hog;
mutex_lock(&gpio_machine_hogs_mutex);
list_for_each_entry(hog, &gpio_machine_hogs, list) {
- if (!strcmp(chip->label, hog->chip_label))
- gpiochip_machine_hog(chip, hog);
+ if (!strcmp(gc->label, hog->chip_label))
+ gpiochip_machine_hog(gc, hog);
}
mutex_unlock(&gpio_machine_hogs_mutex);
@@ -1380,14 +1567,14 @@ static void gpiochip_setup_devs(void)
}
}
-int gpiochip_add_data_with_key(struct gpio_chip *chip, void *data,
+int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data,
struct lock_class_key *lock_key,
struct lock_class_key *request_key)
{
unsigned long flags;
int ret = 0;
unsigned i;
- int base = chip->base;
+ int base = gc->base;
struct gpio_device *gdev;
/*
@@ -1398,19 +1585,19 @@ int gpiochip_add_data_with_key(struct gpio_chip *chip, void *data,
if (!gdev)
return -ENOMEM;
gdev->dev.bus = &gpio_bus_type;
- gdev->chip = chip;
- chip->gpiodev = gdev;
- if (chip->parent) {
- gdev->dev.parent = chip->parent;
- gdev->dev.of_node = chip->parent->of_node;
+ gdev->chip = gc;
+ gc->gpiodev = gdev;
+ if (gc->parent) {
+ gdev->dev.parent = gc->parent;
+ gdev->dev.of_node = gc->parent->of_node;
}
#ifdef CONFIG_OF_GPIO
/* If the gpiochip has an assigned OF node this takes precedence */
- if (chip->of_node)
- gdev->dev.of_node = chip->of_node;
+ if (gc->of_node)
+ gdev->dev.of_node = gc->of_node;
else
- chip->of_node = gdev->dev.of_node;
+ gc->of_node = gdev->dev.of_node;
#endif
gdev->id = ida_simple_get(&gpio_ida, 0, 0, GFP_KERNEL);
@@ -1421,37 +1608,37 @@ int gpiochip_add_data_with_key(struct gpio_chip *chip, void *data,
dev_set_name(&gdev->dev, GPIOCHIP_NAME "%d", gdev->id);
device_initialize(&gdev->dev);
dev_set_drvdata(&gdev->dev, gdev);
- if (chip->parent && chip->parent->driver)
- gdev->owner = chip->parent->driver->owner;
- else if (chip->owner)
+ if (gc->parent && gc->parent->driver)
+ gdev->owner = gc->parent->driver->owner;
+ else if (gc->owner)
/* TODO: remove chip->owner */
- gdev->owner = chip->owner;
+ gdev->owner = gc->owner;
else
gdev->owner = THIS_MODULE;
- gdev->descs = kcalloc(chip->ngpio, sizeof(gdev->descs[0]), GFP_KERNEL);
+ gdev->descs = kcalloc(gc->ngpio, sizeof(gdev->descs[0]), GFP_KERNEL);
if (!gdev->descs) {
ret = -ENOMEM;
goto err_free_ida;
}
- if (chip->ngpio == 0) {
- chip_err(chip, "tried to insert a GPIO chip with zero lines\n");
+ if (gc->ngpio == 0) {
+ chip_err(gc, "tried to insert a GPIO chip with zero lines\n");
ret = -EINVAL;
goto err_free_descs;
}
- if (chip->ngpio > FASTPATH_NGPIO)
- chip_warn(chip, "line cnt %u is greater than fast path cnt %u\n",
- chip->ngpio, FASTPATH_NGPIO);
+ if (gc->ngpio > FASTPATH_NGPIO)
+ chip_warn(gc, "line cnt %u is greater than fast path cnt %u\n",
+ gc->ngpio, FASTPATH_NGPIO);
- gdev->label = kstrdup_const(chip->label ?: "unknown", GFP_KERNEL);
+ gdev->label = kstrdup_const(gc->label ?: "unknown", GFP_KERNEL);
if (!gdev->label) {
ret = -ENOMEM;
goto err_free_descs;
}
- gdev->ngpio = chip->ngpio;
+ gdev->ngpio = gc->ngpio;
gdev->data = data;
spin_lock_irqsave(&gpio_lock, flags);
@@ -1464,7 +1651,7 @@ int gpiochip_add_data_with_key(struct gpio_chip *chip, void *data,
* of the sysfs interface anyways.
*/
if (base < 0) {
- base = gpiochip_find_base(chip->ngpio);
+ base = gpiochip_find_base(gc->ngpio);
if (base < 0) {
ret = base;
spin_unlock_irqrestore(&gpio_lock, flags);
@@ -1476,7 +1663,7 @@ int gpiochip_add_data_with_key(struct gpio_chip *chip, void *data,
* see if anyone makes use of this, else drop this and assign
* a poison instead.
*/
- chip->base = base;
+ gc->base = base;
}
gdev->base = base;
@@ -1486,60 +1673,62 @@ int gpiochip_add_data_with_key(struct gpio_chip *chip, void *data,
goto err_free_label;
}
- for (i = 0; i < chip->ngpio; i++)
+ for (i = 0; i < gc->ngpio; i++)
gdev->descs[i].gdev = gdev;
spin_unlock_irqrestore(&gpio_lock, flags);
+ ATOMIC_INIT_NOTIFIER_HEAD(&gdev->notifier);
+
#ifdef CONFIG_PINCTRL
INIT_LIST_HEAD(&gdev->pin_ranges);
#endif
- ret = gpiochip_set_desc_names(chip);
+ ret = gpiochip_set_desc_names(gc);
if (ret)
goto err_remove_from_list;
- ret = gpiochip_alloc_valid_mask(chip);
+ ret = gpiochip_alloc_valid_mask(gc);
if (ret)
goto err_remove_from_list;
- ret = of_gpiochip_add(chip);
+ ret = of_gpiochip_add(gc);
if (ret)
goto err_free_gpiochip_mask;
- ret = gpiochip_init_valid_mask(chip);
+ ret = gpiochip_init_valid_mask(gc);
if (ret)
goto err_remove_of_chip;
- for (i = 0; i < chip->ngpio; i++) {
+ for (i = 0; i < gc->ngpio; i++) {
struct gpio_desc *desc = &gdev->descs[i];
- if (chip->get_direction && gpiochip_line_is_valid(chip, i)) {
+ if (gc->get_direction && gpiochip_line_is_valid(gc, i)) {
assign_bit(FLAG_IS_OUT,
- &desc->flags, !chip->get_direction(chip, i));
+ &desc->flags, !gc->get_direction(gc, i));
} else {
assign_bit(FLAG_IS_OUT,
- &desc->flags, !chip->direction_input);
+ &desc->flags, !gc->direction_input);
}
}
- ret = gpiochip_add_pin_ranges(chip);
+ ret = gpiochip_add_pin_ranges(gc);
if (ret)
goto err_remove_of_chip;
- acpi_gpiochip_add(chip);
+ acpi_gpiochip_add(gc);
- machine_gpiochip_add(chip);
+ machine_gpiochip_add(gc);
- ret = gpiochip_irqchip_init_valid_mask(chip);
+ ret = gpiochip_irqchip_init_valid_mask(gc);
if (ret)
goto err_remove_acpi_chip;
- ret = gpiochip_irqchip_init_hw(chip);
+ ret = gpiochip_irqchip_init_hw(gc);
if (ret)
goto err_remove_acpi_chip;
- ret = gpiochip_add_irqchip(chip, lock_key, request_key);
+ ret = gpiochip_add_irqchip(gc, lock_key, request_key);
if (ret)
goto err_remove_irqchip_mask;
@@ -1559,17 +1748,17 @@ int gpiochip_add_data_with_key(struct gpio_chip *chip, void *data,
return 0;
err_remove_irqchip:
- gpiochip_irqchip_remove(chip);
+ gpiochip_irqchip_remove(gc);
err_remove_irqchip_mask:
- gpiochip_irqchip_free_valid_mask(chip);
+ gpiochip_irqchip_free_valid_mask(gc);
err_remove_acpi_chip:
- acpi_gpiochip_remove(chip);
+ acpi_gpiochip_remove(gc);
err_remove_of_chip:
- gpiochip_free_hogs(chip);
- of_gpiochip_remove(chip);
+ gpiochip_free_hogs(gc);
+ of_gpiochip_remove(gc);
err_free_gpiochip_mask:
- gpiochip_remove_pin_ranges(chip);
- gpiochip_free_valid_mask(chip);
+ gpiochip_remove_pin_ranges(gc);
+ gpiochip_free_valid_mask(gc);
err_remove_from_list:
spin_lock_irqsave(&gpio_lock, flags);
list_del(&gdev->list);
@@ -1584,7 +1773,7 @@ err_free_gdev:
/* failures here can mean systems won't boot... */
pr_err("%s: GPIOs %d..%d (%s) failed to register, %d\n", __func__,
gdev->base, gdev->base + gdev->ngpio - 1,
- chip->label ? : "generic", ret);
+ gc->label ? : "generic", ret);
kfree(gdev);
return ret;
}
@@ -1592,41 +1781,39 @@ EXPORT_SYMBOL_GPL(gpiochip_add_data_with_key);
/**
* gpiochip_get_data() - get per-subdriver data for the chip
- * @chip: GPIO chip
+ * @gc: GPIO chip
*
* Returns:
* The per-subdriver data for the chip.
*/
-void *gpiochip_get_data(struct gpio_chip *chip)
+void *gpiochip_get_data(struct gpio_chip *gc)
{
- return chip->gpiodev->data;
+ return gc->gpiodev->data;
}
EXPORT_SYMBOL_GPL(gpiochip_get_data);
/**
* gpiochip_remove() - unregister a gpio_chip
- * @chip: the chip to unregister
+ * @gc: the chip to unregister
*
* A gpio_chip with any GPIOs still requested may not be removed.
*/
-void gpiochip_remove(struct gpio_chip *chip)
+void gpiochip_remove(struct gpio_chip *gc)
{
- struct gpio_device *gdev = chip->gpiodev;
- struct gpio_desc *desc;
+ struct gpio_device *gdev = gc->gpiodev;
unsigned long flags;
- unsigned i;
- bool requested = false;
+ unsigned int i;
/* FIXME: should the legacy sysfs handling be moved to gpio_device? */
gpiochip_sysfs_unregister(gdev);
- gpiochip_free_hogs(chip);
+ gpiochip_free_hogs(gc);
/* Numb the device, cancelling all outstanding operations */
gdev->chip = NULL;
- gpiochip_irqchip_remove(chip);
- acpi_gpiochip_remove(chip);
- of_gpiochip_remove(chip);
- gpiochip_remove_pin_ranges(chip);
- gpiochip_free_valid_mask(chip);
+ gpiochip_irqchip_remove(gc);
+ acpi_gpiochip_remove(gc);
+ of_gpiochip_remove(gc);
+ gpiochip_remove_pin_ranges(gc);
+ gpiochip_free_valid_mask(gc);
/*
* We accept no more calls into the driver from this point, so
* NULL the driver data pointer
@@ -1635,13 +1822,12 @@ void gpiochip_remove(struct gpio_chip *chip)
spin_lock_irqsave(&gpio_lock, flags);
for (i = 0; i < gdev->ngpio; i++) {
- desc = &gdev->descs[i];
- if (test_bit(FLAG_REQUESTED, &desc->flags))
- requested = true;
+ if (gpiochip_is_requested(gc, i))
+ break;
}
spin_unlock_irqrestore(&gpio_lock, flags);
- if (requested)
+ if (i != gdev->ngpio)
dev_crit(&gdev->dev,
"REMOVING GPIOCHIP WITH GPIOS STILL REQUESTED\n");
@@ -1656,52 +1842,6 @@ void gpiochip_remove(struct gpio_chip *chip)
}
EXPORT_SYMBOL_GPL(gpiochip_remove);
-static void devm_gpio_chip_release(struct device *dev, void *res)
-{
- struct gpio_chip *chip = *(struct gpio_chip **)res;
-
- gpiochip_remove(chip);
-}
-
-/**
- * devm_gpiochip_add_data() - Resource managed gpiochip_add_data()
- * @dev: pointer to the device that gpio_chip belongs to.
- * @chip: the chip to register, with chip->base initialized
- * @data: driver-private data associated with this chip
- *
- * Context: potentially before irqs will work
- *
- * The gpio chip automatically be released when the device is unbound.
- *
- * Returns:
- * A negative errno if the chip can't be registered, such as because the
- * chip->base is invalid or already associated with a different chip.
- * Otherwise it returns zero as a success code.
- */
-int devm_gpiochip_add_data(struct device *dev, struct gpio_chip *chip,
- void *data)
-{
- struct gpio_chip **ptr;
- int ret;
-
- ptr = devres_alloc(devm_gpio_chip_release, sizeof(*ptr),
- GFP_KERNEL);
- if (!ptr)
- return -ENOMEM;
-
- ret = gpiochip_add_data(chip, data);
- if (ret < 0) {
- devres_free(ptr);
- return ret;
- }
-
- *ptr = chip;
- devres_add(dev, ptr);
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(devm_gpiochip_add_data);
-
/**
* gpiochip_find() - iterator for locating a specific gpio_chip
* @data: data to pass to match function
@@ -1714,31 +1854,31 @@ EXPORT_SYMBOL_GPL(devm_gpiochip_add_data);
* more gpio_chips.
*/
struct gpio_chip *gpiochip_find(void *data,
- int (*match)(struct gpio_chip *chip,
+ int (*match)(struct gpio_chip *gc,
void *data))
{
struct gpio_device *gdev;
- struct gpio_chip *chip = NULL;
+ struct gpio_chip *gc = NULL;
unsigned long flags;
spin_lock_irqsave(&gpio_lock, flags);
list_for_each_entry(gdev, &gpio_devices, list)
if (gdev->chip && match(gdev->chip, data)) {
- chip = gdev->chip;
+ gc = gdev->chip;
break;
}
spin_unlock_irqrestore(&gpio_lock, flags);
- return chip;
+ return gc;
}
EXPORT_SYMBOL_GPL(gpiochip_find);
-static int gpiochip_match_name(struct gpio_chip *chip, void *data)
+static int gpiochip_match_name(struct gpio_chip *gc, void *data)
{
const char *name = data;
- return !strcmp(chip->label, name);
+ return !strcmp(gc->label, name);
}
static struct gpio_chip *find_chip_by_name(const char *name)
@@ -1778,21 +1918,21 @@ static int gpiochip_irqchip_init_valid_mask(struct gpio_chip *gc)
return 0;
}
-static void gpiochip_irqchip_free_valid_mask(struct gpio_chip *gpiochip)
+static void gpiochip_irqchip_free_valid_mask(struct gpio_chip *gc)
{
- bitmap_free(gpiochip->irq.valid_mask);
- gpiochip->irq.valid_mask = NULL;
+ bitmap_free(gc->irq.valid_mask);
+ gc->irq.valid_mask = NULL;
}
-bool gpiochip_irqchip_irq_valid(const struct gpio_chip *gpiochip,
+bool gpiochip_irqchip_irq_valid(const struct gpio_chip *gc,
unsigned int offset)
{
- if (!gpiochip_line_is_valid(gpiochip, offset))
+ if (!gpiochip_line_is_valid(gc, offset))
return false;
/* No mask means all valid */
- if (likely(!gpiochip->irq.valid_mask))
+ if (likely(!gc->irq.valid_mask))
return true;
- return test_bit(offset, gpiochip->irq.valid_mask);
+ return test_bit(offset, gc->irq.valid_mask);
}
EXPORT_SYMBOL_GPL(gpiochip_irqchip_irq_valid);
@@ -1844,16 +1984,16 @@ static void gpiochip_set_cascaded_irqchip(struct gpio_chip *gc,
/**
* gpiochip_set_nested_irqchip() - connects a nested irqchip to a gpiochip
- * @gpiochip: the gpiochip to set the irqchip nested handler to
+ * @gc: the gpiochip to set the irqchip nested handler to
* @irqchip: the irqchip to nest to the gpiochip
* @parent_irq: the irq number corresponding to the parent IRQ for this
* nested irqchip
*/
-void gpiochip_set_nested_irqchip(struct gpio_chip *gpiochip,
+void gpiochip_set_nested_irqchip(struct gpio_chip *gc,
struct irq_chip *irqchip,
unsigned int parent_irq)
{
- gpiochip_set_cascaded_irqchip(gpiochip, parent_irq, NULL);
+ gpiochip_set_cascaded_irqchip(gc, parent_irq, NULL);
}
EXPORT_SYMBOL_GPL(gpiochip_set_nested_irqchip);
@@ -2030,7 +2170,7 @@ static int gpiochip_hierarchy_irq_domain_alloc(struct irq_domain *d,
return ret;
}
-static unsigned int gpiochip_child_offset_to_irq_noop(struct gpio_chip *chip,
+static unsigned int gpiochip_child_offset_to_irq_noop(struct gpio_chip *gc,
unsigned int offset)
{
return offset;
@@ -2090,7 +2230,7 @@ static bool gpiochip_hierarchy_is_hierarchical(struct gpio_chip *gc)
return !!gc->irq.parent_domain;
}
-void *gpiochip_populate_parent_fwspec_twocell(struct gpio_chip *chip,
+void *gpiochip_populate_parent_fwspec_twocell(struct gpio_chip *gc,
unsigned int parent_hwirq,
unsigned int parent_type)
{
@@ -2100,7 +2240,7 @@ void *gpiochip_populate_parent_fwspec_twocell(struct gpio_chip *chip,
if (!fwspec)
return NULL;
- fwspec->fwnode = chip->irq.parent_domain->fwnode;
+ fwspec->fwnode = gc->irq.parent_domain->fwnode;
fwspec->param_count = 2;
fwspec->param[0] = parent_hwirq;
fwspec->param[1] = parent_type;
@@ -2109,7 +2249,7 @@ void *gpiochip_populate_parent_fwspec_twocell(struct gpio_chip *chip,
}
EXPORT_SYMBOL_GPL(gpiochip_populate_parent_fwspec_twocell);
-void *gpiochip_populate_parent_fwspec_fourcell(struct gpio_chip *chip,
+void *gpiochip_populate_parent_fwspec_fourcell(struct gpio_chip *gc,
unsigned int parent_hwirq,
unsigned int parent_type)
{
@@ -2119,7 +2259,7 @@ void *gpiochip_populate_parent_fwspec_fourcell(struct gpio_chip *chip,
if (!fwspec)
return NULL;
- fwspec->fwnode = chip->irq.parent_domain->fwnode;
+ fwspec->fwnode = gc->irq.parent_domain->fwnode;
fwspec->param_count = 4;
fwspec->param[0] = 0;
fwspec->param[1] = parent_hwirq;
@@ -2157,28 +2297,28 @@ static bool gpiochip_hierarchy_is_hierarchical(struct gpio_chip *gc)
int gpiochip_irq_map(struct irq_domain *d, unsigned int irq,
irq_hw_number_t hwirq)
{
- struct gpio_chip *chip = d->host_data;
+ struct gpio_chip *gc = d->host_data;
int ret = 0;
- if (!gpiochip_irqchip_irq_valid(chip, hwirq))
+ if (!gpiochip_irqchip_irq_valid(gc, hwirq))
return -ENXIO;
- irq_set_chip_data(irq, chip);
+ irq_set_chip_data(irq, gc);
/*
* This lock class tells lockdep that GPIO irqs are in a different
* category than their parents, so it won't report false recursion.
*/
- irq_set_lockdep_class(irq, chip->irq.lock_key, chip->irq.request_key);
- irq_set_chip_and_handler(irq, chip->irq.chip, chip->irq.handler);
+ irq_set_lockdep_class(irq, gc->irq.lock_key, gc->irq.request_key);
+ irq_set_chip_and_handler(irq, gc->irq.chip, gc->irq.handler);
/* Chips that use nested thread handlers have them marked */
- if (chip->irq.threaded)
+ if (gc->irq.threaded)
irq_set_nested_thread(irq, 1);
irq_set_noprobe(irq);
- if (chip->irq.num_parents == 1)
- ret = irq_set_parent(irq, chip->irq.parents[0]);
- else if (chip->irq.map)
- ret = irq_set_parent(irq, chip->irq.map[hwirq]);
+ if (gc->irq.num_parents == 1)
+ ret = irq_set_parent(irq, gc->irq.parents[0]);
+ else if (gc->irq.map)
+ ret = irq_set_parent(irq, gc->irq.map[hwirq]);
if (ret < 0)
return ret;
@@ -2187,8 +2327,8 @@ int gpiochip_irq_map(struct irq_domain *d, unsigned int irq,
* No set-up of the hardware will happen if IRQ_TYPE_NONE
* is passed as default type.
*/
- if (chip->irq.default_type != IRQ_TYPE_NONE)
- irq_set_irq_type(irq, chip->irq.default_type);
+ if (gc->irq.default_type != IRQ_TYPE_NONE)
+ irq_set_irq_type(irq, gc->irq.default_type);
return 0;
}
@@ -2196,9 +2336,9 @@ EXPORT_SYMBOL_GPL(gpiochip_irq_map);
void gpiochip_irq_unmap(struct irq_domain *d, unsigned int irq)
{
- struct gpio_chip *chip = d->host_data;
+ struct gpio_chip *gc = d->host_data;
- if (chip->irq.threaded)
+ if (gc->irq.threaded)
irq_set_nested_thread(irq, 0);
irq_set_chip_and_handler(irq, NULL, NULL);
irq_set_chip_data(irq, NULL);
@@ -2230,9 +2370,9 @@ static const struct irq_domain_ops gpiochip_domain_ops = {
int gpiochip_irq_domain_activate(struct irq_domain *domain,
struct irq_data *data, bool reserve)
{
- struct gpio_chip *chip = domain->host_data;
+ struct gpio_chip *gc = domain->host_data;
- return gpiochip_lock_as_irq(chip, data->hwirq);
+ return gpiochip_lock_as_irq(gc, data->hwirq);
}
EXPORT_SYMBOL_GPL(gpiochip_irq_domain_activate);
@@ -2248,17 +2388,17 @@ EXPORT_SYMBOL_GPL(gpiochip_irq_domain_activate);
void gpiochip_irq_domain_deactivate(struct irq_domain *domain,
struct irq_data *data)
{
- struct gpio_chip *chip = domain->host_data;
+ struct gpio_chip *gc = domain->host_data;
- return gpiochip_unlock_as_irq(chip, data->hwirq);
+ return gpiochip_unlock_as_irq(gc, data->hwirq);
}
EXPORT_SYMBOL_GPL(gpiochip_irq_domain_deactivate);
-static int gpiochip_to_irq(struct gpio_chip *chip, unsigned offset)
+static int gpiochip_to_irq(struct gpio_chip *gc, unsigned offset)
{
- struct irq_domain *domain = chip->irq.domain;
+ struct irq_domain *domain = gc->irq.domain;
- if (!gpiochip_irqchip_irq_valid(chip, offset))
+ if (!gpiochip_irqchip_irq_valid(gc, offset))
return -ENXIO;
#ifdef CONFIG_IRQ_DOMAIN_HIERARCHY
@@ -2267,7 +2407,7 @@ static int gpiochip_to_irq(struct gpio_chip *chip, unsigned offset)
spec.fwnode = domain->fwnode;
spec.param_count = 2;
- spec.param[0] = chip->irq.child_offset_to_irq(chip, offset);
+ spec.param[0] = gc->irq.child_offset_to_irq(gc, offset);
spec.param[1] = IRQ_TYPE_NONE;
return irq_create_fwspec_mapping(&spec);
@@ -2279,50 +2419,57 @@ static int gpiochip_to_irq(struct gpio_chip *chip, unsigned offset)
static int gpiochip_irq_reqres(struct irq_data *d)
{
- struct gpio_chip *chip = irq_data_get_irq_chip_data(d);
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
- return gpiochip_reqres_irq(chip, d->hwirq);
+ return gpiochip_reqres_irq(gc, d->hwirq);
}
static void gpiochip_irq_relres(struct irq_data *d)
{
- struct gpio_chip *chip = irq_data_get_irq_chip_data(d);
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
- gpiochip_relres_irq(chip, d->hwirq);
+ gpiochip_relres_irq(gc, d->hwirq);
}
static void gpiochip_irq_enable(struct irq_data *d)
{
- struct gpio_chip *chip = irq_data_get_irq_chip_data(d);
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
- gpiochip_enable_irq(chip, d->hwirq);
- if (chip->irq.irq_enable)
- chip->irq.irq_enable(d);
+ gpiochip_enable_irq(gc, d->hwirq);
+ if (gc->irq.irq_enable)
+ gc->irq.irq_enable(d);
else
- chip->irq.chip->irq_unmask(d);
+ gc->irq.chip->irq_unmask(d);
}
static void gpiochip_irq_disable(struct irq_data *d)
{
- struct gpio_chip *chip = irq_data_get_irq_chip_data(d);
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
- if (chip->irq.irq_disable)
- chip->irq.irq_disable(d);
- else
- chip->irq.chip->irq_mask(d);
- gpiochip_disable_irq(chip, d->hwirq);
+ /*
+ * Since we override .irq_disable() we need to mimic the
+ * behaviour of __irq_disable() in irq/chip.c.
+ * First call .irq_disable() if it exists, else mimic the
+ * behaviour of mask_irq() which calls .irq_mask() if
+ * it exists.
+ */
+ if (gc->irq.irq_disable)
+ gc->irq.irq_disable(d);
+ else if (gc->irq.chip->irq_mask)
+ gc->irq.chip->irq_mask(d);
+ gpiochip_disable_irq(gc, d->hwirq);
}
-static void gpiochip_set_irq_hooks(struct gpio_chip *gpiochip)
+static void gpiochip_set_irq_hooks(struct gpio_chip *gc)
{
- struct irq_chip *irqchip = gpiochip->irq.chip;
+ struct irq_chip *irqchip = gc->irq.chip;
if (!irqchip->irq_request_resources &&
!irqchip->irq_release_resources) {
irqchip->irq_request_resources = gpiochip_irq_reqres;
irqchip->irq_release_resources = gpiochip_irq_relres;
}
- if (WARN_ON(gpiochip->irq.irq_enable))
+ if (WARN_ON(gc->irq.irq_enable))
return;
/* Check if the irqchip already has this hook... */
if (irqchip->irq_enable == gpiochip_irq_enable) {
@@ -2330,27 +2477,27 @@ static void gpiochip_set_irq_hooks(struct gpio_chip *gpiochip)
* ...and if so, give a gentle warning that this is bad
* practice.
*/
- chip_info(gpiochip,
+ chip_info(gc,
"detected irqchip that is shared with multiple gpiochips: please fix the driver.\n");
return;
}
- gpiochip->irq.irq_enable = irqchip->irq_enable;
- gpiochip->irq.irq_disable = irqchip->irq_disable;
+ gc->irq.irq_enable = irqchip->irq_enable;
+ gc->irq.irq_disable = irqchip->irq_disable;
irqchip->irq_enable = gpiochip_irq_enable;
irqchip->irq_disable = gpiochip_irq_disable;
}
/**
* gpiochip_add_irqchip() - adds an IRQ chip to a GPIO chip
- * @gpiochip: the GPIO chip to add the IRQ chip to
+ * @gc: the GPIO chip to add the IRQ chip to
* @lock_key: lockdep class for IRQ lock
* @request_key: lockdep class for IRQ request
*/
-static int gpiochip_add_irqchip(struct gpio_chip *gpiochip,
+static int gpiochip_add_irqchip(struct gpio_chip *gc,
struct lock_class_key *lock_key,
struct lock_class_key *request_key)
{
- struct irq_chip *irqchip = gpiochip->irq.chip;
+ struct irq_chip *irqchip = gc->irq.chip;
const struct irq_domain_ops *ops = NULL;
struct device_node *np;
unsigned int type;
@@ -2359,13 +2506,13 @@ static int gpiochip_add_irqchip(struct gpio_chip *gpiochip,
if (!irqchip)
return 0;
- if (gpiochip->irq.parent_handler && gpiochip->can_sleep) {
- chip_err(gpiochip, "you cannot have chained interrupts on a chip that may sleep\n");
+ if (gc->irq.parent_handler && gc->can_sleep) {
+ chip_err(gc, "you cannot have chained interrupts on a chip that may sleep\n");
return -EINVAL;
}
- np = gpiochip->gpiodev->dev.of_node;
- type = gpiochip->irq.default_type;
+ np = gc->gpiodev->dev.of_node;
+ type = gc->irq.default_type;
/*
* Specifying a default trigger is a terrible idea if DT or ACPI is
@@ -2376,74 +2523,74 @@ static int gpiochip_add_irqchip(struct gpio_chip *gpiochip,
"%s: Ignoring %u default trigger\n", np->full_name, type))
type = IRQ_TYPE_NONE;
- if (has_acpi_companion(gpiochip->parent) && type != IRQ_TYPE_NONE) {
- acpi_handle_warn(ACPI_HANDLE(gpiochip->parent),
+ if (has_acpi_companion(gc->parent) && type != IRQ_TYPE_NONE) {
+ acpi_handle_warn(ACPI_HANDLE(gc->parent),
"Ignoring %u default trigger\n", type);
type = IRQ_TYPE_NONE;
}
- gpiochip->to_irq = gpiochip_to_irq;
- gpiochip->irq.default_type = type;
- gpiochip->irq.lock_key = lock_key;
- gpiochip->irq.request_key = request_key;
+ gc->to_irq = gpiochip_to_irq;
+ gc->irq.default_type = type;
+ gc->irq.lock_key = lock_key;
+ gc->irq.request_key = request_key;
/* If a parent irqdomain is provided, let's build a hierarchy */
- if (gpiochip_hierarchy_is_hierarchical(gpiochip)) {
- int ret = gpiochip_hierarchy_add_domain(gpiochip);
+ if (gpiochip_hierarchy_is_hierarchical(gc)) {
+ int ret = gpiochip_hierarchy_add_domain(gc);
if (ret)
return ret;
} else {
/* Some drivers provide custom irqdomain ops */
- if (gpiochip->irq.domain_ops)
- ops = gpiochip->irq.domain_ops;
+ if (gc->irq.domain_ops)
+ ops = gc->irq.domain_ops;
if (!ops)
ops = &gpiochip_domain_ops;
- gpiochip->irq.domain = irq_domain_add_simple(np,
- gpiochip->ngpio,
- gpiochip->irq.first,
- ops, gpiochip);
- if (!gpiochip->irq.domain)
+ gc->irq.domain = irq_domain_add_simple(np,
+ gc->ngpio,
+ gc->irq.first,
+ ops, gc);
+ if (!gc->irq.domain)
return -EINVAL;
}
- if (gpiochip->irq.parent_handler) {
- void *data = gpiochip->irq.parent_handler_data ?: gpiochip;
+ if (gc->irq.parent_handler) {
+ void *data = gc->irq.parent_handler_data ?: gc;
- for (i = 0; i < gpiochip->irq.num_parents; i++) {
+ for (i = 0; i < gc->irq.num_parents; i++) {
/*
* The parent IRQ chip is already using the chip_data
* for this IRQ chip, so our callbacks simply use the
* handler_data.
*/
- irq_set_chained_handler_and_data(gpiochip->irq.parents[i],
- gpiochip->irq.parent_handler,
+ irq_set_chained_handler_and_data(gc->irq.parents[i],
+ gc->irq.parent_handler,
data);
}
}
- gpiochip_set_irq_hooks(gpiochip);
+ gpiochip_set_irq_hooks(gc);
- acpi_gpiochip_request_interrupts(gpiochip);
+ acpi_gpiochip_request_interrupts(gc);
return 0;
}
/**
* gpiochip_irqchip_remove() - removes an irqchip added to a gpiochip
- * @gpiochip: the gpiochip to remove the irqchip from
+ * @gc: the gpiochip to remove the irqchip from
*
* This is called only from gpiochip_remove()
*/
-static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip)
+static void gpiochip_irqchip_remove(struct gpio_chip *gc)
{
- struct irq_chip *irqchip = gpiochip->irq.chip;
+ struct irq_chip *irqchip = gc->irq.chip;
unsigned int offset;
- acpi_gpiochip_free_interrupts(gpiochip);
+ acpi_gpiochip_free_interrupts(gc);
- if (irqchip && gpiochip->irq.parent_handler) {
- struct gpio_irq_chip *irq = &gpiochip->irq;
+ if (irqchip && gc->irq.parent_handler) {
+ struct gpio_irq_chip *irq = &gc->irq;
unsigned int i;
for (i = 0; i < irq->num_parents; i++)
@@ -2452,18 +2599,18 @@ static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip)
}
/* Remove all IRQ mappings and delete the domain */
- if (gpiochip->irq.domain) {
+ if (gc->irq.domain) {
unsigned int irq;
- for (offset = 0; offset < gpiochip->ngpio; offset++) {
- if (!gpiochip_irqchip_irq_valid(gpiochip, offset))
+ for (offset = 0; offset < gc->ngpio; offset++) {
+ if (!gpiochip_irqchip_irq_valid(gc, offset))
continue;
- irq = irq_find_mapping(gpiochip->irq.domain, offset);
+ irq = irq_find_mapping(gc->irq.domain, offset);
irq_dispose_mapping(irq);
}
- irq_domain_remove(gpiochip->irq.domain);
+ irq_domain_remove(gc->irq.domain);
}
if (irqchip) {
@@ -2472,20 +2619,20 @@ static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip)
irqchip->irq_release_resources = NULL;
}
if (irqchip->irq_enable == gpiochip_irq_enable) {
- irqchip->irq_enable = gpiochip->irq.irq_enable;
- irqchip->irq_disable = gpiochip->irq.irq_disable;
+ irqchip->irq_enable = gc->irq.irq_enable;
+ irqchip->irq_disable = gc->irq.irq_disable;
}
}
- gpiochip->irq.irq_enable = NULL;
- gpiochip->irq.irq_disable = NULL;
- gpiochip->irq.chip = NULL;
+ gc->irq.irq_enable = NULL;
+ gc->irq.irq_disable = NULL;
+ gc->irq.chip = NULL;
- gpiochip_irqchip_free_valid_mask(gpiochip);
+ gpiochip_irqchip_free_valid_mask(gc);
}
/**
* gpiochip_irqchip_add_key() - adds an irqchip to a gpiochip
- * @gpiochip: the gpiochip to add the irqchip to
+ * @gc: the gpiochip to add the irqchip to
* @irqchip: the irqchip to add to the gpiochip
* @first_irq: if not dynamically assigned, the base (first) IRQ to
* allocate gpiochip irqs from
@@ -2510,7 +2657,7 @@ static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip)
* the pins on the gpiochip can generate a unique IRQ. Everything else
* need to be open coded.
*/
-int gpiochip_irqchip_add_key(struct gpio_chip *gpiochip,
+int gpiochip_irqchip_add_key(struct gpio_chip *gc,
struct irq_chip *irqchip,
unsigned int first_irq,
irq_flow_handler_t handler,
@@ -2521,23 +2668,23 @@ int gpiochip_irqchip_add_key(struct gpio_chip *gpiochip,
{
struct device_node *of_node;
- if (!gpiochip || !irqchip)
+ if (!gc || !irqchip)
return -EINVAL;
- if (!gpiochip->parent) {
+ if (!gc->parent) {
pr_err("missing gpiochip .dev parent pointer\n");
return -EINVAL;
}
- gpiochip->irq.threaded = threaded;
- of_node = gpiochip->parent->of_node;
+ gc->irq.threaded = threaded;
+ of_node = gc->parent->of_node;
#ifdef CONFIG_OF_GPIO
/*
* If the gpiochip has an assigned OF node this takes precedence
- * FIXME: get rid of this and use gpiochip->parent->of_node
+ * FIXME: get rid of this and use gc->parent->of_node
* everywhere
*/
- if (gpiochip->of_node)
- of_node = gpiochip->of_node;
+ if (gc->of_node)
+ of_node = gc->of_node;
#endif
/*
* Specifying a default trigger is a terrible idea if DT or ACPI is
@@ -2547,29 +2694,29 @@ int gpiochip_irqchip_add_key(struct gpio_chip *gpiochip,
if (WARN(of_node && type != IRQ_TYPE_NONE,
"%pOF: Ignoring %d default trigger\n", of_node, type))
type = IRQ_TYPE_NONE;
- if (has_acpi_companion(gpiochip->parent) && type != IRQ_TYPE_NONE) {
- acpi_handle_warn(ACPI_HANDLE(gpiochip->parent),
+ if (has_acpi_companion(gc->parent) && type != IRQ_TYPE_NONE) {
+ acpi_handle_warn(ACPI_HANDLE(gc->parent),
"Ignoring %d default trigger\n", type);
type = IRQ_TYPE_NONE;
}
- gpiochip->irq.chip = irqchip;
- gpiochip->irq.handler = handler;
- gpiochip->irq.default_type = type;
- gpiochip->to_irq = gpiochip_to_irq;
- gpiochip->irq.lock_key = lock_key;
- gpiochip->irq.request_key = request_key;
- gpiochip->irq.domain = irq_domain_add_simple(of_node,
- gpiochip->ngpio, first_irq,
- &gpiochip_domain_ops, gpiochip);
- if (!gpiochip->irq.domain) {
- gpiochip->irq.chip = NULL;
+ gc->irq.chip = irqchip;
+ gc->irq.handler = handler;
+ gc->irq.default_type = type;
+ gc->to_irq = gpiochip_to_irq;
+ gc->irq.lock_key = lock_key;
+ gc->irq.request_key = request_key;
+ gc->irq.domain = irq_domain_add_simple(of_node,
+ gc->ngpio, first_irq,
+ &gpiochip_domain_ops, gc);
+ if (!gc->irq.domain) {
+ gc->irq.chip = NULL;
return -EINVAL;
}
- gpiochip_set_irq_hooks(gpiochip);
+ gpiochip_set_irq_hooks(gc);
- acpi_gpiochip_request_interrupts(gpiochip);
+ acpi_gpiochip_request_interrupts(gc);
return 0;
}
@@ -2577,60 +2724,65 @@ EXPORT_SYMBOL_GPL(gpiochip_irqchip_add_key);
#else /* CONFIG_GPIOLIB_IRQCHIP */
-static inline int gpiochip_add_irqchip(struct gpio_chip *gpiochip,
+static inline int gpiochip_add_irqchip(struct gpio_chip *gc,
struct lock_class_key *lock_key,
struct lock_class_key *request_key)
{
return 0;
}
-static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip) {}
+static void gpiochip_irqchip_remove(struct gpio_chip *gc) {}
-static inline int gpiochip_irqchip_init_hw(struct gpio_chip *gpiochip)
+static inline int gpiochip_irqchip_init_hw(struct gpio_chip *gc)
{
return 0;
}
-static inline int gpiochip_irqchip_init_valid_mask(struct gpio_chip *gpiochip)
+static inline int gpiochip_irqchip_init_valid_mask(struct gpio_chip *gc)
{
return 0;
}
-static inline void gpiochip_irqchip_free_valid_mask(struct gpio_chip *gpiochip)
+static inline void gpiochip_irqchip_free_valid_mask(struct gpio_chip *gc)
{ }
#endif /* CONFIG_GPIOLIB_IRQCHIP */
/**
* gpiochip_generic_request() - request the gpio function for a pin
- * @chip: the gpiochip owning the GPIO
+ * @gc: the gpiochip owning the GPIO
* @offset: the offset of the GPIO to request for GPIO function
*/
-int gpiochip_generic_request(struct gpio_chip *chip, unsigned offset)
+int gpiochip_generic_request(struct gpio_chip *gc, unsigned offset)
{
- return pinctrl_gpio_request(chip->gpiodev->base + offset);
+#ifdef CONFIG_PINCTRL
+ if (list_empty(&gc->gpiodev->pin_ranges))
+ return 0;
+#endif
+
+ return pinctrl_gpio_request(gc->gpiodev->base + offset);
}
EXPORT_SYMBOL_GPL(gpiochip_generic_request);
/**
* gpiochip_generic_free() - free the gpio function from a pin
- * @chip: the gpiochip to request the gpio function for
+ * @gc: the gpiochip to request the gpio function for
* @offset: the offset of the GPIO to free from GPIO function
*/
-void gpiochip_generic_free(struct gpio_chip *chip, unsigned offset)
+void gpiochip_generic_free(struct gpio_chip *gc, unsigned offset)
{
- pinctrl_gpio_free(chip->gpiodev->base + offset);
+ pinctrl_gpio_free(gc->gpiodev->base + offset);
}
EXPORT_SYMBOL_GPL(gpiochip_generic_free);
/**
* gpiochip_generic_config() - apply configuration for a pin
- * @chip: the gpiochip owning the GPIO
+ * @gc: the gpiochip owning the GPIO
* @offset: the offset of the GPIO to apply the configuration
* @config: the configuration to be applied
*/
-int gpiochip_generic_config(struct gpio_chip *chip, unsigned offset,
+int gpiochip_generic_config(struct gpio_chip *gc, unsigned offset,
unsigned long config)
{
- return pinctrl_gpio_set_config(chip->gpiodev->base + offset, config);
+ return pinctrl_gpio_set_config(gc->gpiodev->base + offset, config);
}
EXPORT_SYMBOL_GPL(gpiochip_generic_config);
@@ -2638,7 +2790,7 @@ EXPORT_SYMBOL_GPL(gpiochip_generic_config);
/**
* gpiochip_add_pingroup_range() - add a range for GPIO <-> pin mapping
- * @chip: the gpiochip to add the range for
+ * @gc: the gpiochip to add the range for
* @pctldev: the pin controller to map to
* @gpio_offset: the start offset in the current gpio_chip number space
* @pin_group: name of the pin group inside the pin controller
@@ -2648,24 +2800,24 @@ EXPORT_SYMBOL_GPL(gpiochip_generic_config);
* Documentation/devicetree/bindings/gpio/gpio.txt on how to
* bind pinctrl and gpio drivers via the "gpio-ranges" property.
*/
-int gpiochip_add_pingroup_range(struct gpio_chip *chip,
+int gpiochip_add_pingroup_range(struct gpio_chip *gc,
struct pinctrl_dev *pctldev,
unsigned int gpio_offset, const char *pin_group)
{
struct gpio_pin_range *pin_range;
- struct gpio_device *gdev = chip->gpiodev;
+ struct gpio_device *gdev = gc->gpiodev;
int ret;
pin_range = kzalloc(sizeof(*pin_range), GFP_KERNEL);
if (!pin_range) {
- chip_err(chip, "failed to allocate pin ranges\n");
+ chip_err(gc, "failed to allocate pin ranges\n");
return -ENOMEM;
}
/* Use local offset as range ID */
pin_range->range.id = gpio_offset;
- pin_range->range.gc = chip;
- pin_range->range.name = chip->label;
+ pin_range->range.gc = gc;
+ pin_range->range.name = gc->label;
pin_range->range.base = gdev->base + gpio_offset;
pin_range->pctldev = pctldev;
@@ -2679,7 +2831,7 @@ int gpiochip_add_pingroup_range(struct gpio_chip *chip,
pinctrl_add_gpio_range(pctldev, &pin_range->range);
- chip_dbg(chip, "created GPIO range %d->%d ==> %s PINGRP %s\n",
+ chip_dbg(gc, "created GPIO range %d->%d ==> %s PINGRP %s\n",
gpio_offset, gpio_offset + pin_range->range.npins - 1,
pinctrl_dev_get_devname(pctldev), pin_group);
@@ -2691,7 +2843,7 @@ EXPORT_SYMBOL_GPL(gpiochip_add_pingroup_range);
/**
* gpiochip_add_pin_range() - add a range for GPIO <-> pin mapping
- * @chip: the gpiochip to add the range for
+ * @gc: the gpiochip to add the range for
* @pinctl_name: the dev_name() of the pin controller to map to
* @gpio_offset: the start offset in the current gpio_chip number space
* @pin_offset: the start offset in the pin controller number space
@@ -2706,24 +2858,24 @@ EXPORT_SYMBOL_GPL(gpiochip_add_pingroup_range);
* Documentation/devicetree/bindings/gpio/gpio.txt on how to
* bind pinctrl and gpio drivers via the "gpio-ranges" property.
*/
-int gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name,
+int gpiochip_add_pin_range(struct gpio_chip *gc, const char *pinctl_name,
unsigned int gpio_offset, unsigned int pin_offset,
unsigned int npins)
{
struct gpio_pin_range *pin_range;
- struct gpio_device *gdev = chip->gpiodev;
+ struct gpio_device *gdev = gc->gpiodev;
int ret;
pin_range = kzalloc(sizeof(*pin_range), GFP_KERNEL);
if (!pin_range) {
- chip_err(chip, "failed to allocate pin ranges\n");
+ chip_err(gc, "failed to allocate pin ranges\n");
return -ENOMEM;
}
/* Use local offset as range ID */
pin_range->range.id = gpio_offset;
- pin_range->range.gc = chip;
- pin_range->range.name = chip->label;
+ pin_range->range.gc = gc;
+ pin_range->range.name = gc->label;
pin_range->range.base = gdev->base + gpio_offset;
pin_range->range.pin_base = pin_offset;
pin_range->range.npins = npins;
@@ -2731,11 +2883,11 @@ int gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name,
&pin_range->range);
if (IS_ERR(pin_range->pctldev)) {
ret = PTR_ERR(pin_range->pctldev);
- chip_err(chip, "could not create pin range\n");
+ chip_err(gc, "could not create pin range\n");
kfree(pin_range);
return ret;
}
- chip_dbg(chip, "created GPIO range %d->%d ==> %s PIN %d->%d\n",
+ chip_dbg(gc, "created GPIO range %d->%d ==> %s PIN %d->%d\n",
gpio_offset, gpio_offset + npins - 1,
pinctl_name,
pin_offset, pin_offset + npins - 1);
@@ -2748,12 +2900,12 @@ EXPORT_SYMBOL_GPL(gpiochip_add_pin_range);
/**
* gpiochip_remove_pin_ranges() - remove all the GPIO <-> pin mappings
- * @chip: the chip to remove all the mappings for
+ * @gc: the chip to remove all the mappings for
*/
-void gpiochip_remove_pin_ranges(struct gpio_chip *chip)
+void gpiochip_remove_pin_ranges(struct gpio_chip *gc)
{
struct gpio_pin_range *pin_range, *tmp;
- struct gpio_device *gdev = chip->gpiodev;
+ struct gpio_device *gdev = gc->gpiodev;
list_for_each_entry_safe(pin_range, tmp, &gdev->pin_ranges, node) {
list_del(&pin_range->node);
@@ -2772,7 +2924,7 @@ EXPORT_SYMBOL_GPL(gpiochip_remove_pin_ranges);
*/
static int gpiod_request_commit(struct gpio_desc *desc, const char *label)
{
- struct gpio_chip *chip = desc->gdev->chip;
+ struct gpio_chip *gc = desc->gdev->chip;
int ret;
unsigned long flags;
unsigned offset;
@@ -2798,12 +2950,12 @@ static int gpiod_request_commit(struct gpio_desc *desc, const char *label)
goto done;
}
- if (chip->request) {
- /* chip->request may sleep */
+ if (gc->request) {
+ /* gc->request may sleep */
spin_unlock_irqrestore(&gpio_lock, flags);
offset = gpio_chip_hwgpio(desc);
- if (gpiochip_line_is_valid(chip, offset))
- ret = chip->request(chip, offset);
+ if (gpiochip_line_is_valid(gc, offset))
+ ret = gc->request(gc, offset);
else
ret = -EINVAL;
spin_lock_irqsave(&gpio_lock, flags);
@@ -2815,14 +2967,16 @@ static int gpiod_request_commit(struct gpio_desc *desc, const char *label)
goto done;
}
}
- if (chip->get_direction) {
- /* chip->get_direction may sleep */
+ if (gc->get_direction) {
+ /* gc->get_direction may sleep */
spin_unlock_irqrestore(&gpio_lock, flags);
gpiod_get_direction(desc);
spin_lock_irqsave(&gpio_lock, flags);
}
done:
spin_unlock_irqrestore(&gpio_lock, flags);
+ atomic_notifier_call_chain(&desc->gdev->notifier,
+ GPIOLINE_CHANGED_REQUESTED, desc);
return ret;
}
@@ -2890,7 +3044,7 @@ static bool gpiod_free_commit(struct gpio_desc *desc)
{
bool ret = false;
unsigned long flags;
- struct gpio_chip *chip;
+ struct gpio_chip *gc;
might_sleep();
@@ -2898,12 +3052,12 @@ static bool gpiod_free_commit(struct gpio_desc *desc)
spin_lock_irqsave(&gpio_lock, flags);
- chip = desc->gdev->chip;
- if (chip && test_bit(FLAG_REQUESTED, &desc->flags)) {
- if (chip->free) {
+ gc = desc->gdev->chip;
+ if (gc && test_bit(FLAG_REQUESTED, &desc->flags)) {
+ if (gc->free) {
spin_unlock_irqrestore(&gpio_lock, flags);
- might_sleep_if(chip->can_sleep);
- chip->free(chip, gpio_chip_hwgpio(desc));
+ might_sleep_if(gc->can_sleep);
+ gc->free(gc, gpio_chip_hwgpio(desc));
spin_lock_irqsave(&gpio_lock, flags);
}
kfree_const(desc->label);
@@ -2916,10 +3070,16 @@ static bool gpiod_free_commit(struct gpio_desc *desc)
clear_bit(FLAG_PULL_DOWN, &desc->flags);
clear_bit(FLAG_BIAS_DISABLE, &desc->flags);
clear_bit(FLAG_IS_HOGGED, &desc->flags);
+#ifdef CONFIG_OF_DYNAMIC
+ desc->hog = NULL;
+#endif
ret = true;
}
spin_unlock_irqrestore(&gpio_lock, flags);
+ atomic_notifier_call_chain(&desc->gdev->notifier,
+ GPIOLINE_CHANGED_RELEASED, desc);
+
return ret;
}
@@ -2935,7 +3095,7 @@ void gpiod_free(struct gpio_desc *desc)
/**
* gpiochip_is_requested - return string iff signal was requested
- * @chip: controller managing the signal
+ * @gc: controller managing the signal
* @offset: of signal within controller's 0..(ngpio - 1) range
*
* Returns NULL if the GPIO is not currently requested, else a string.
@@ -2946,14 +3106,16 @@ void gpiod_free(struct gpio_desc *desc)
* help with diagnostics, and knowing that the signal is used as a GPIO
* can help avoid accidentally multiplexing it to another controller.
*/
-const char *gpiochip_is_requested(struct gpio_chip *chip, unsigned offset)
+const char *gpiochip_is_requested(struct gpio_chip *gc, unsigned offset)
{
struct gpio_desc *desc;
- if (offset >= chip->ngpio)
+ if (offset >= gc->ngpio)
return NULL;
- desc = &chip->gpiodev->descs[offset];
+ desc = gpiochip_get_desc(gc, offset);
+ if (IS_ERR(desc))
+ return NULL;
if (test_bit(FLAG_REQUESTED, &desc->flags) == 0)
return NULL;
@@ -2963,7 +3125,7 @@ EXPORT_SYMBOL_GPL(gpiochip_is_requested);
/**
* gpiochip_request_own_desc - Allow GPIO chip to request its own descriptor
- * @chip: GPIO chip
+ * @gc: GPIO chip
* @hwnum: hardware number of the GPIO for which to request the descriptor
* @label: label for the GPIO
* @lflags: lookup flags for this GPIO or 0 if default, this can be used to
@@ -2982,17 +3144,17 @@ EXPORT_SYMBOL_GPL(gpiochip_is_requested);
* A pointer to the GPIO descriptor, or an ERR_PTR()-encoded negative error
* code on failure.
*/
-struct gpio_desc *gpiochip_request_own_desc(struct gpio_chip *chip,
+struct gpio_desc *gpiochip_request_own_desc(struct gpio_chip *gc,
unsigned int hwnum,
const char *label,
enum gpio_lookup_flags lflags,
enum gpiod_flags dflags)
{
- struct gpio_desc *desc = gpiochip_get_desc(chip, hwnum);
+ struct gpio_desc *desc = gpiochip_get_desc(gc, hwnum);
int ret;
if (IS_ERR(desc)) {
- chip_err(chip, "failed to get GPIO descriptor\n");
+ chip_err(gc, "failed to get GPIO descriptor\n");
return desc;
}
@@ -3002,7 +3164,7 @@ struct gpio_desc *gpiochip_request_own_desc(struct gpio_chip *chip,
ret = gpiod_configure_flags(desc, label, lflags, dflags);
if (ret) {
- chip_err(chip, "setup of own GPIO %s failed\n", label);
+ chip_err(gc, "setup of own GPIO %s failed\n", label);
gpiod_free_commit(desc);
return ERR_PTR(ret);
}
@@ -3044,9 +3206,9 @@ static int gpio_do_set_config(struct gpio_chip *gc, unsigned int offset,
return gc->set_config(gc, offset, config);
}
-static int gpio_set_config(struct gpio_chip *gc, unsigned int offset,
- enum pin_config_param mode)
+static int gpio_set_config(struct gpio_desc *desc, enum pin_config_param mode)
{
+ struct gpio_chip *gc = desc->gdev->chip;
unsigned long config;
unsigned arg;
@@ -3061,10 +3223,10 @@ static int gpio_set_config(struct gpio_chip *gc, unsigned int offset,
}
config = PIN_CONF_PACKED(mode, arg);
- return gpio_do_set_config(gc, offset, config);
+ return gpio_do_set_config(gc, gpio_chip_hwgpio(desc), config);
}
-static int gpio_set_bias(struct gpio_chip *chip, struct gpio_desc *desc)
+static int gpio_set_bias(struct gpio_desc *desc)
{
int bias = 0;
int ret = 0;
@@ -3077,7 +3239,7 @@ static int gpio_set_bias(struct gpio_chip *chip, struct gpio_desc *desc)
bias = PIN_CONFIG_BIAS_PULL_DOWN;
if (bias) {
- ret = gpio_set_config(chip, gpio_chip_hwgpio(desc), bias);
+ ret = gpio_set_config(desc, bias);
if (ret != -ENOTSUPP)
return ret;
}
@@ -3095,18 +3257,18 @@ static int gpio_set_bias(struct gpio_chip *chip, struct gpio_desc *desc)
*/
int gpiod_direction_input(struct gpio_desc *desc)
{
- struct gpio_chip *chip;
+ struct gpio_chip *gc;
int ret = 0;
VALIDATE_DESC(desc);
- chip = desc->gdev->chip;
+ gc = desc->gdev->chip;
/*
* It is legal to have no .get() and .direction_input() specified if
* the chip is output-only, but you can't specify .direction_input()
* and not support the .get() operation, that doesn't make sense.
*/
- if (!chip->get && chip->direction_input) {
+ if (!gc->get && gc->direction_input) {
gpiod_warn(desc,
"%s: missing get() but have direction_input()\n",
__func__);
@@ -3119,10 +3281,10 @@ int gpiod_direction_input(struct gpio_desc *desc)
* direction (if .get_direction() is supported) else we silently
* assume we are in input mode after this.
*/
- if (chip->direction_input) {
- ret = chip->direction_input(chip, gpio_chip_hwgpio(desc));
- } else if (chip->get_direction &&
- (chip->get_direction(chip, gpio_chip_hwgpio(desc)) != 1)) {
+ if (gc->direction_input) {
+ ret = gc->direction_input(gc, gpio_chip_hwgpio(desc));
+ } else if (gc->get_direction &&
+ (gc->get_direction(gc, gpio_chip_hwgpio(desc)) != 1)) {
gpiod_warn(desc,
"%s: missing direction_input() operation and line is output\n",
__func__);
@@ -3130,7 +3292,7 @@ int gpiod_direction_input(struct gpio_desc *desc)
}
if (ret == 0) {
clear_bit(FLAG_IS_OUT, &desc->flags);
- ret = gpio_set_bias(chip, desc);
+ ret = gpio_set_bias(desc);
}
trace_gpio_direction(desc_to_gpio(desc), 1, ret);
@@ -3214,7 +3376,6 @@ EXPORT_SYMBOL_GPL(gpiod_direction_output_raw);
*/
int gpiod_direction_output(struct gpio_desc *desc, int value)
{
- struct gpio_chip *gc;
int ret;
VALIDATE_DESC(desc);
@@ -3232,11 +3393,9 @@ int gpiod_direction_output(struct gpio_desc *desc, int value)
return -EIO;
}
- gc = desc->gdev->chip;
if (test_bit(FLAG_OPEN_DRAIN, &desc->flags)) {
/* First see if we can enable open drain in hardware */
- ret = gpio_set_config(gc, gpio_chip_hwgpio(desc),
- PIN_CONFIG_DRIVE_OPEN_DRAIN);
+ ret = gpio_set_config(desc, PIN_CONFIG_DRIVE_OPEN_DRAIN);
if (!ret)
goto set_output_value;
/* Emulate open drain by not actively driving the line high */
@@ -3246,8 +3405,7 @@ int gpiod_direction_output(struct gpio_desc *desc, int value)
}
}
else if (test_bit(FLAG_OPEN_SOURCE, &desc->flags)) {
- ret = gpio_set_config(gc, gpio_chip_hwgpio(desc),
- PIN_CONFIG_DRIVE_OPEN_SOURCE);
+ ret = gpio_set_config(desc, PIN_CONFIG_DRIVE_OPEN_SOURCE);
if (!ret)
goto set_output_value;
/* Emulate open source by not actively driving the line low */
@@ -3256,12 +3414,11 @@ int gpiod_direction_output(struct gpio_desc *desc, int value)
goto set_output_flag;
}
} else {
- gpio_set_config(gc, gpio_chip_hwgpio(desc),
- PIN_CONFIG_DRIVE_PUSH_PULL);
+ gpio_set_config(desc, PIN_CONFIG_DRIVE_PUSH_PULL);
}
set_output_value:
- ret = gpio_set_bias(gc, desc);
+ ret = gpio_set_bias(desc);
if (ret)
return ret;
return gpiod_direction_output_raw_commit(desc, value);
@@ -3280,6 +3437,26 @@ set_output_flag:
EXPORT_SYMBOL_GPL(gpiod_direction_output);
/**
+ * gpiod_set_config - sets @config for a GPIO
+ * @desc: descriptor of the GPIO for which to set the configuration
+ * @config: Same packed config format as generic pinconf
+ *
+ * Returns:
+ * 0 on success, %-ENOTSUPP if the controller doesn't support setting the
+ * configuration.
+ */
+int gpiod_set_config(struct gpio_desc *desc, unsigned long config)
+{
+ struct gpio_chip *gc;
+
+ VALIDATE_DESC(desc);
+ gc = desc->gdev->chip;
+
+ return gpio_do_set_config(gc, gpio_chip_hwgpio(desc), config);
+}
+EXPORT_SYMBOL_GPL(gpiod_set_config);
+
+/**
* gpiod_set_debounce - sets @debounce time for a GPIO
* @desc: descriptor of the GPIO for which to set debounce time
* @debounce: debounce time in microseconds
@@ -3290,14 +3467,10 @@ EXPORT_SYMBOL_GPL(gpiod_direction_output);
*/
int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce)
{
- struct gpio_chip *chip;
- unsigned long config;
-
- VALIDATE_DESC(desc);
- chip = desc->gdev->chip;
+ unsigned long config;
config = pinconf_to_config_packed(PIN_CONFIG_INPUT_DEBOUNCE, debounce);
- return gpio_do_set_config(chip, gpio_chip_hwgpio(desc), config);
+ return gpiod_set_config(desc, config);
}
EXPORT_SYMBOL_GPL(gpiod_set_debounce);
@@ -3311,7 +3484,7 @@ EXPORT_SYMBOL_GPL(gpiod_set_debounce);
*/
int gpiod_set_transitory(struct gpio_desc *desc, bool transitory)
{
- struct gpio_chip *chip;
+ struct gpio_chip *gc;
unsigned long packed;
int gpio;
int rc;
@@ -3324,14 +3497,14 @@ int gpiod_set_transitory(struct gpio_desc *desc, bool transitory)
assign_bit(FLAG_TRANSITORY, &desc->flags, transitory);
/* If the driver supports it, set the persistence state now */
- chip = desc->gdev->chip;
- if (!chip->set_config)
+ gc = desc->gdev->chip;
+ if (!gc->set_config)
return 0;
packed = pinconf_to_config_packed(PIN_CONFIG_PERSIST_STATE,
!transitory);
gpio = gpio_chip_hwgpio(desc);
- rc = gpio_do_set_config(chip, gpio, packed);
+ rc = gpio_do_set_config(gc, gpio, packed);
if (rc == -ENOTSUPP) {
dev_dbg(&desc->gdev->dev, "Persistence not supported for GPIO %d\n",
gpio);
@@ -3390,28 +3563,28 @@ EXPORT_SYMBOL_GPL(gpiod_toggle_active_low);
static int gpiod_get_raw_value_commit(const struct gpio_desc *desc)
{
- struct gpio_chip *chip;
+ struct gpio_chip *gc;
int offset;
int value;
- chip = desc->gdev->chip;
+ gc = desc->gdev->chip;
offset = gpio_chip_hwgpio(desc);
- value = chip->get ? chip->get(chip, offset) : -EIO;
+ value = gc->get ? gc->get(gc, offset) : -EIO;
value = value < 0 ? value : !!value;
trace_gpio_value(desc_to_gpio(desc), 1, value);
return value;
}
-static int gpio_chip_get_multiple(struct gpio_chip *chip,
+static int gpio_chip_get_multiple(struct gpio_chip *gc,
unsigned long *mask, unsigned long *bits)
{
- if (chip->get_multiple) {
- return chip->get_multiple(chip, mask, bits);
- } else if (chip->get) {
+ if (gc->get_multiple) {
+ return gc->get_multiple(gc, mask, bits);
+ } else if (gc->get) {
int i, value;
- for_each_set_bit(i, mask, chip->ngpio) {
- value = chip->get(chip, i);
+ for_each_set_bit(i, mask, gc->ngpio) {
+ value = gc->get(gc, i);
if (value < 0)
return value;
__assign_bit(i, bits, value);
@@ -3459,26 +3632,26 @@ int gpiod_get_array_value_complex(bool raw, bool can_sleep,
}
while (i < array_size) {
- struct gpio_chip *chip = desc_array[i]->gdev->chip;
+ struct gpio_chip *gc = desc_array[i]->gdev->chip;
unsigned long fastpath[2 * BITS_TO_LONGS(FASTPATH_NGPIO)];
unsigned long *mask, *bits;
int first, j, ret;
- if (likely(chip->ngpio <= FASTPATH_NGPIO)) {
+ if (likely(gc->ngpio <= FASTPATH_NGPIO)) {
mask = fastpath;
} else {
- mask = kmalloc_array(2 * BITS_TO_LONGS(chip->ngpio),
+ mask = kmalloc_array(2 * BITS_TO_LONGS(gc->ngpio),
sizeof(*mask),
can_sleep ? GFP_KERNEL : GFP_ATOMIC);
if (!mask)
return -ENOMEM;
}
- bits = mask + BITS_TO_LONGS(chip->ngpio);
- bitmap_zero(mask, chip->ngpio);
+ bits = mask + BITS_TO_LONGS(gc->ngpio);
+ bitmap_zero(mask, gc->ngpio);
if (!can_sleep)
- WARN_ON(chip->can_sleep);
+ WARN_ON(gc->can_sleep);
/* collect all inputs belonging to the same chip */
first = i;
@@ -3493,9 +3666,9 @@ int gpiod_get_array_value_complex(bool raw, bool can_sleep,
i = find_next_zero_bit(array_info->get_mask,
array_size, i);
} while ((i < array_size) &&
- (desc_array[i]->gdev->chip == chip));
+ (desc_array[i]->gdev->chip == gc));
- ret = gpio_chip_get_multiple(chip, mask, bits);
+ ret = gpio_chip_get_multiple(gc, mask, bits);
if (ret) {
if (mask != fastpath)
kfree(mask);
@@ -3633,13 +3806,13 @@ EXPORT_SYMBOL_GPL(gpiod_get_array_value);
static void gpio_set_open_drain_value_commit(struct gpio_desc *desc, bool value)
{
int ret = 0;
- struct gpio_chip *chip = desc->gdev->chip;
+ struct gpio_chip *gc = desc->gdev->chip;
int offset = gpio_chip_hwgpio(desc);
if (value) {
- ret = chip->direction_input(chip, offset);
+ ret = gc->direction_input(gc, offset);
} else {
- ret = chip->direction_output(chip, offset, 0);
+ ret = gc->direction_output(gc, offset, 0);
if (!ret)
set_bit(FLAG_IS_OUT, &desc->flags);
}
@@ -3658,15 +3831,15 @@ static void gpio_set_open_drain_value_commit(struct gpio_desc *desc, bool value)
static void gpio_set_open_source_value_commit(struct gpio_desc *desc, bool value)
{
int ret = 0;
- struct gpio_chip *chip = desc->gdev->chip;
+ struct gpio_chip *gc = desc->gdev->chip;
int offset = gpio_chip_hwgpio(desc);
if (value) {
- ret = chip->direction_output(chip, offset, 1);
+ ret = gc->direction_output(gc, offset, 1);
if (!ret)
set_bit(FLAG_IS_OUT, &desc->flags);
} else {
- ret = chip->direction_input(chip, offset);
+ ret = gc->direction_input(gc, offset);
}
trace_gpio_direction(desc_to_gpio(desc), !value, ret);
if (ret < 0)
@@ -3677,33 +3850,34 @@ static void gpio_set_open_source_value_commit(struct gpio_desc *desc, bool value
static void gpiod_set_raw_value_commit(struct gpio_desc *desc, bool value)
{
- struct gpio_chip *chip;
+ struct gpio_chip *gc;
- chip = desc->gdev->chip;
+ gc = desc->gdev->chip;
trace_gpio_value(desc_to_gpio(desc), 0, value);
- chip->set(chip, gpio_chip_hwgpio(desc), value);
+ gc->set(gc, gpio_chip_hwgpio(desc), value);
}
/*
* set multiple outputs on the same chip;
* use the chip's set_multiple function if available;
* otherwise set the outputs sequentially;
+ * @chip: the GPIO chip we operate on
* @mask: bit mask array; one bit per output; BITS_PER_LONG bits per word
* defines which outputs are to be changed
* @bits: bit value array; one bit per output; BITS_PER_LONG bits per word
* defines the values the outputs specified by mask are to be set to
*/
-static void gpio_chip_set_multiple(struct gpio_chip *chip,
+static void gpio_chip_set_multiple(struct gpio_chip *gc,
unsigned long *mask, unsigned long *bits)
{
- if (chip->set_multiple) {
- chip->set_multiple(chip, mask, bits);
+ if (gc->set_multiple) {
+ gc->set_multiple(gc, mask, bits);
} else {
unsigned int i;
/* set outputs if the corresponding mask bit is set */
- for_each_set_bit(i, mask, chip->ngpio)
- chip->set(chip, i, test_bit(i, bits));
+ for_each_set_bit(i, mask, gc->ngpio)
+ gc->set(gc, i, test_bit(i, bits));
}
}
@@ -3742,26 +3916,26 @@ int gpiod_set_array_value_complex(bool raw, bool can_sleep,
}
while (i < array_size) {
- struct gpio_chip *chip = desc_array[i]->gdev->chip;
+ struct gpio_chip *gc = desc_array[i]->gdev->chip;
unsigned long fastpath[2 * BITS_TO_LONGS(FASTPATH_NGPIO)];
unsigned long *mask, *bits;
int count = 0;
- if (likely(chip->ngpio <= FASTPATH_NGPIO)) {
+ if (likely(gc->ngpio <= FASTPATH_NGPIO)) {
mask = fastpath;
} else {
- mask = kmalloc_array(2 * BITS_TO_LONGS(chip->ngpio),
+ mask = kmalloc_array(2 * BITS_TO_LONGS(gc->ngpio),
sizeof(*mask),
can_sleep ? GFP_KERNEL : GFP_ATOMIC);
if (!mask)
return -ENOMEM;
}
- bits = mask + BITS_TO_LONGS(chip->ngpio);
- bitmap_zero(mask, chip->ngpio);
+ bits = mask + BITS_TO_LONGS(gc->ngpio);
+ bitmap_zero(mask, gc->ngpio);
if (!can_sleep)
- WARN_ON(chip->can_sleep);
+ WARN_ON(gc->can_sleep);
do {
struct gpio_desc *desc = desc_array[i];
@@ -3797,10 +3971,10 @@ int gpiod_set_array_value_complex(bool raw, bool can_sleep,
i = find_next_zero_bit(array_info->set_mask,
array_size, i);
} while ((i < array_size) &&
- (desc_array[i]->gdev->chip == chip));
+ (desc_array[i]->gdev->chip == gc));
/* push collected bits to outputs */
if (count != 0)
- gpio_chip_set_multiple(chip, mask, bits);
+ gpio_chip_set_multiple(gc, mask, bits);
if (mask != fastpath)
kfree(mask);
@@ -3962,7 +4136,7 @@ EXPORT_SYMBOL_GPL(gpiod_set_consumer_name);
*/
int gpiod_to_irq(const struct gpio_desc *desc)
{
- struct gpio_chip *chip;
+ struct gpio_chip *gc;
int offset;
/*
@@ -3973,10 +4147,10 @@ int gpiod_to_irq(const struct gpio_desc *desc)
if (!desc || IS_ERR(desc) || !desc->gdev || !desc->gdev->chip)
return -EINVAL;
- chip = desc->gdev->chip;
+ gc = desc->gdev->chip;
offset = gpio_chip_hwgpio(desc);
- if (chip->to_irq) {
- int retirq = chip->to_irq(chip, offset);
+ if (gc->to_irq) {
+ int retirq = gc->to_irq(gc, offset);
/* Zero means NO_IRQ */
if (!retirq)
@@ -3990,17 +4164,17 @@ EXPORT_SYMBOL_GPL(gpiod_to_irq);
/**
* gpiochip_lock_as_irq() - lock a GPIO to be used as IRQ
- * @chip: the chip the GPIO to lock belongs to
+ * @gc: the chip the GPIO to lock belongs to
* @offset: the offset of the GPIO to lock as IRQ
*
* This is used directly by GPIO drivers that want to lock down
* a certain GPIO line to be used for IRQs.
*/
-int gpiochip_lock_as_irq(struct gpio_chip *chip, unsigned int offset)
+int gpiochip_lock_as_irq(struct gpio_chip *gc, unsigned int offset)
{
struct gpio_desc *desc;
- desc = gpiochip_get_desc(chip, offset);
+ desc = gpiochip_get_desc(gc, offset);
if (IS_ERR(desc))
return PTR_ERR(desc);
@@ -4008,18 +4182,18 @@ int gpiochip_lock_as_irq(struct gpio_chip *chip, unsigned int offset)
* If it's fast: flush the direction setting if something changed
* behind our back
*/
- if (!chip->can_sleep && chip->get_direction) {
+ if (!gc->can_sleep && gc->get_direction) {
int dir = gpiod_get_direction(desc);
if (dir < 0) {
- chip_err(chip, "%s: cannot get GPIO direction\n",
+ chip_err(gc, "%s: cannot get GPIO direction\n",
__func__);
return dir;
}
}
if (test_bit(FLAG_IS_OUT, &desc->flags)) {
- chip_err(chip,
+ chip_err(gc,
"%s: tried to flag a GPIO set as output for IRQ\n",
__func__);
return -EIO;
@@ -4042,17 +4216,17 @@ EXPORT_SYMBOL_GPL(gpiochip_lock_as_irq);
/**
* gpiochip_unlock_as_irq() - unlock a GPIO used as IRQ
- * @chip: the chip the GPIO to lock belongs to
+ * @gc: the chip the GPIO to lock belongs to
* @offset: the offset of the GPIO to lock as IRQ
*
* This is used directly by GPIO drivers that want to indicate
* that a certain GPIO is no longer used exclusively for IRQ.
*/
-void gpiochip_unlock_as_irq(struct gpio_chip *chip, unsigned int offset)
+void gpiochip_unlock_as_irq(struct gpio_chip *gc, unsigned int offset)
{
struct gpio_desc *desc;
- desc = gpiochip_get_desc(chip, offset);
+ desc = gpiochip_get_desc(gc, offset);
if (IS_ERR(desc))
return;
@@ -4065,9 +4239,9 @@ void gpiochip_unlock_as_irq(struct gpio_chip *chip, unsigned int offset)
}
EXPORT_SYMBOL_GPL(gpiochip_unlock_as_irq);
-void gpiochip_disable_irq(struct gpio_chip *chip, unsigned int offset)
+void gpiochip_disable_irq(struct gpio_chip *gc, unsigned int offset)
{
- struct gpio_desc *desc = gpiochip_get_desc(chip, offset);
+ struct gpio_desc *desc = gpiochip_get_desc(gc, offset);
if (!IS_ERR(desc) &&
!WARN_ON(!test_bit(FLAG_USED_AS_IRQ, &desc->flags)))
@@ -4075,9 +4249,9 @@ void gpiochip_disable_irq(struct gpio_chip *chip, unsigned int offset)
}
EXPORT_SYMBOL_GPL(gpiochip_disable_irq);
-void gpiochip_enable_irq(struct gpio_chip *chip, unsigned int offset)
+void gpiochip_enable_irq(struct gpio_chip *gc, unsigned int offset)
{
- struct gpio_desc *desc = gpiochip_get_desc(chip, offset);
+ struct gpio_desc *desc = gpiochip_get_desc(gc, offset);
if (!IS_ERR(desc) &&
!WARN_ON(!test_bit(FLAG_USED_AS_IRQ, &desc->flags))) {
@@ -4087,63 +4261,63 @@ void gpiochip_enable_irq(struct gpio_chip *chip, unsigned int offset)
}
EXPORT_SYMBOL_GPL(gpiochip_enable_irq);
-bool gpiochip_line_is_irq(struct gpio_chip *chip, unsigned int offset)
+bool gpiochip_line_is_irq(struct gpio_chip *gc, unsigned int offset)
{
- if (offset >= chip->ngpio)
+ if (offset >= gc->ngpio)
return false;
- return test_bit(FLAG_USED_AS_IRQ, &chip->gpiodev->descs[offset].flags);
+ return test_bit(FLAG_USED_AS_IRQ, &gc->gpiodev->descs[offset].flags);
}
EXPORT_SYMBOL_GPL(gpiochip_line_is_irq);
-int gpiochip_reqres_irq(struct gpio_chip *chip, unsigned int offset)
+int gpiochip_reqres_irq(struct gpio_chip *gc, unsigned int offset)
{
int ret;
- if (!try_module_get(chip->gpiodev->owner))
+ if (!try_module_get(gc->gpiodev->owner))
return -ENODEV;
- ret = gpiochip_lock_as_irq(chip, offset);
+ ret = gpiochip_lock_as_irq(gc, offset);
if (ret) {
- chip_err(chip, "unable to lock HW IRQ %u for IRQ\n", offset);
- module_put(chip->gpiodev->owner);
+ chip_err(gc, "unable to lock HW IRQ %u for IRQ\n", offset);
+ module_put(gc->gpiodev->owner);
return ret;
}
return 0;
}
EXPORT_SYMBOL_GPL(gpiochip_reqres_irq);
-void gpiochip_relres_irq(struct gpio_chip *chip, unsigned int offset)
+void gpiochip_relres_irq(struct gpio_chip *gc, unsigned int offset)
{
- gpiochip_unlock_as_irq(chip, offset);
- module_put(chip->gpiodev->owner);
+ gpiochip_unlock_as_irq(gc, offset);
+ module_put(gc->gpiodev->owner);
}
EXPORT_SYMBOL_GPL(gpiochip_relres_irq);
-bool gpiochip_line_is_open_drain(struct gpio_chip *chip, unsigned int offset)
+bool gpiochip_line_is_open_drain(struct gpio_chip *gc, unsigned int offset)
{
- if (offset >= chip->ngpio)
+ if (offset >= gc->ngpio)
return false;
- return test_bit(FLAG_OPEN_DRAIN, &chip->gpiodev->descs[offset].flags);
+ return test_bit(FLAG_OPEN_DRAIN, &gc->gpiodev->descs[offset].flags);
}
EXPORT_SYMBOL_GPL(gpiochip_line_is_open_drain);
-bool gpiochip_line_is_open_source(struct gpio_chip *chip, unsigned int offset)
+bool gpiochip_line_is_open_source(struct gpio_chip *gc, unsigned int offset)
{
- if (offset >= chip->ngpio)
+ if (offset >= gc->ngpio)
return false;
- return test_bit(FLAG_OPEN_SOURCE, &chip->gpiodev->descs[offset].flags);
+ return test_bit(FLAG_OPEN_SOURCE, &gc->gpiodev->descs[offset].flags);
}
EXPORT_SYMBOL_GPL(gpiochip_line_is_open_source);
-bool gpiochip_line_is_persistent(struct gpio_chip *chip, unsigned int offset)
+bool gpiochip_line_is_persistent(struct gpio_chip *gc, unsigned int offset)
{
- if (offset >= chip->ngpio)
+ if (offset >= gc->ngpio)
return false;
- return !test_bit(FLAG_TRANSITORY, &chip->gpiodev->descs[offset].flags);
+ return !test_bit(FLAG_TRANSITORY, &gc->gpiodev->descs[offset].flags);
}
EXPORT_SYMBOL_GPL(gpiochip_line_is_persistent);
@@ -4381,7 +4555,7 @@ EXPORT_SYMBOL_GPL(gpiod_remove_lookup_table);
*/
void gpiod_add_hogs(struct gpiod_hog *hogs)
{
- struct gpio_chip *chip;
+ struct gpio_chip *gc;
struct gpiod_hog *hog;
mutex_lock(&gpio_machine_hogs_mutex);
@@ -4393,9 +4567,9 @@ void gpiod_add_hogs(struct gpiod_hog *hogs)
* The chip may have been registered earlier, so check if it
* exists and, if so, try to hog the line now.
*/
- chip = find_chip_by_name(hog->chip_label);
- if (chip)
- gpiochip_machine_hog(chip, hog);
+ gc = find_chip_by_name(hog->chip_label);
+ if (gc)
+ gpiochip_machine_hog(gc, hog);
}
mutex_unlock(&gpio_machine_hogs_mutex);
@@ -4445,7 +4619,7 @@ static struct gpio_desc *gpiod_find(struct device *dev, const char *con_id,
return desc;
for (p = &table->table[0]; p->chip_label; p++) {
- struct gpio_chip *chip;
+ struct gpio_chip *gc;
/* idx must always match exactly */
if (p->idx != idx)
@@ -4455,9 +4629,9 @@ static struct gpio_desc *gpiod_find(struct device *dev, const char *con_id,
if (p->con_id && (!con_id || strcmp(p->con_id, con_id)))
continue;
- chip = find_chip_by_name(p->chip_label);
+ gc = find_chip_by_name(p->chip_label);
- if (!chip) {
+ if (!gc) {
/*
* As the lookup table indicates a chip with
* p->chip_label should exist, assume it may
@@ -4470,15 +4644,15 @@ static struct gpio_desc *gpiod_find(struct device *dev, const char *con_id,
return ERR_PTR(-EPROBE_DEFER);
}
- if (chip->ngpio <= p->chip_hwnum) {
+ if (gc->ngpio <= p->chip_hwnum) {
dev_err(dev,
"requested GPIO %u (%u) is out of range [0..%u] for chip %s\n",
- idx, p->chip_hwnum, chip->ngpio - 1,
- chip->label);
+ idx, p->chip_hwnum, gc->ngpio - 1,
+ gc->label);
return ERR_PTR(-EINVAL);
}
- desc = gpiochip_get_desc(chip, p->chip_hwnum);
+ desc = gpiochip_get_desc(gc, p->chip_hwnum);
*flags = p->flags;
return desc;
@@ -4873,20 +5047,20 @@ EXPORT_SYMBOL_GPL(gpiod_get_index_optional);
int gpiod_hog(struct gpio_desc *desc, const char *name,
unsigned long lflags, enum gpiod_flags dflags)
{
- struct gpio_chip *chip;
+ struct gpio_chip *gc;
struct gpio_desc *local_desc;
int hwnum;
int ret;
- chip = gpiod_to_chip(desc);
+ gc = gpiod_to_chip(desc);
hwnum = gpio_chip_hwgpio(desc);
- local_desc = gpiochip_request_own_desc(chip, hwnum, name,
+ local_desc = gpiochip_request_own_desc(gc, hwnum, name,
lflags, dflags);
if (IS_ERR(local_desc)) {
ret = PTR_ERR(local_desc);
pr_err("requesting hog GPIO %s (chip %s, offset %d) failed, %d\n",
- name, chip->label, hwnum, ret);
+ name, gc->label, hwnum, ret);
return ret;
}
@@ -4904,15 +5078,15 @@ int gpiod_hog(struct gpio_desc *desc, const char *name,
/**
* gpiochip_free_hogs - Scan gpio-controller chip and release GPIO hog
- * @chip: gpio chip to act on
+ * @gc: gpio chip to act on
*/
-static void gpiochip_free_hogs(struct gpio_chip *chip)
+static void gpiochip_free_hogs(struct gpio_chip *gc)
{
int id;
- for (id = 0; id < chip->ngpio; id++) {
- if (test_bit(FLAG_IS_HOGGED, &chip->gpiodev->descs[id].flags))
- gpiochip_free_own_desc(&chip->gpiodev->descs[id]);
+ for (id = 0; id < gc->ngpio; id++) {
+ if (test_bit(FLAG_IS_HOGGED, &gc->gpiodev->descs[id].flags))
+ gpiochip_free_own_desc(&gc->gpiodev->descs[id]);
}
}
@@ -4935,7 +5109,7 @@ struct gpio_descs *__must_check gpiod_get_array(struct device *dev,
struct gpio_desc *desc;
struct gpio_descs *descs;
struct gpio_array *array_info = NULL;
- struct gpio_chip *chip;
+ struct gpio_chip *gc;
int count, bitmap_size;
count = gpiod_count(dev, con_id);
@@ -4955,7 +5129,7 @@ struct gpio_descs *__must_check gpiod_get_array(struct device *dev,
descs->desc[descs->ndescs] = desc;
- chip = gpiod_to_chip(desc);
+ gc = gpiod_to_chip(desc);
/*
* If pin hardware number of array member 0 is also 0, select
* its chip as a candidate for fast bitmap processing path.
@@ -4963,8 +5137,8 @@ struct gpio_descs *__must_check gpiod_get_array(struct device *dev,
if (descs->ndescs == 0 && gpio_chip_hwgpio(desc) == 0) {
struct gpio_descs *array;
- bitmap_size = BITS_TO_LONGS(chip->ngpio > count ?
- chip->ngpio : count);
+ bitmap_size = BITS_TO_LONGS(gc->ngpio > count ?
+ gc->ngpio : count);
array = kzalloc(struct_size(descs, desc, count) +
struct_size(array_info, invert_mask,
@@ -4987,7 +5161,7 @@ struct gpio_descs *__must_check gpiod_get_array(struct device *dev,
array_info->desc = descs->desc;
array_info->size = count;
- array_info->chip = chip;
+ array_info->chip = gc;
bitmap_set(array_info->get_mask, descs->ndescs,
count - descs->ndescs);
bitmap_set(array_info->set_mask, descs->ndescs,
@@ -4995,7 +5169,7 @@ struct gpio_descs *__must_check gpiod_get_array(struct device *dev,
descs->info = array_info;
}
/* Unmark array members which don't belong to the 'fast' chip */
- if (array_info && array_info->chip != chip) {
+ if (array_info && array_info->chip != gc) {
__clear_bit(descs->ndescs, array_info->get_mask);
__clear_bit(descs->ndescs, array_info->set_mask);
}
@@ -5020,8 +5194,8 @@ struct gpio_descs *__must_check gpiod_get_array(struct device *dev,
}
} else if (array_info) {
/* Exclude open drain or open source from fast output */
- if (gpiochip_line_is_open_drain(chip, descs->ndescs) ||
- gpiochip_line_is_open_source(chip, descs->ndescs))
+ if (gpiochip_line_is_open_drain(gc, descs->ndescs) ||
+ gpiochip_line_is_open_source(gc, descs->ndescs))
__clear_bit(descs->ndescs,
array_info->set_mask);
/* Identify 'fast' pins which require invertion */
@@ -5109,10 +5283,15 @@ 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;
}
+
+ gpiolib_initialized = true;
+ gpiochip_setup_devs();
+
+ if (IS_ENABLED(CONFIG_OF_DYNAMIC))
+ WARN_ON(of_reconfig_notifier_register(&gpio_of_notifier));
+
return ret;
}
core_initcall(gpiolib_dev_init);
@@ -5122,7 +5301,7 @@ core_initcall(gpiolib_dev_init);
static void gpiolib_dbg_show(struct seq_file *s, struct gpio_device *gdev)
{
unsigned i;
- struct gpio_chip *chip = gdev->chip;
+ struct gpio_chip *gc = gdev->chip;
unsigned gpio = gdev->base;
struct gpio_desc *gdesc = &gdev->descs[0];
bool is_out;
@@ -5145,7 +5324,7 @@ static void gpiolib_dbg_show(struct seq_file *s, struct gpio_device *gdev)
seq_printf(s, " gpio-%-3d (%-20.20s|%-20.20s) %s %s %s%s",
gpio, gdesc->name ? gdesc->name : "", gdesc->label,
is_out ? "out" : "in ",
- chip->get ? (chip->get(chip, i) ? "hi" : "lo") : "? ",
+ gc->get ? (gc->get(gc, i) ? "hi" : "lo") : "? ",
is_irq ? "IRQ " : "",
active_low ? "ACTIVE LOW" : "");
seq_printf(s, "\n");
@@ -5197,10 +5376,10 @@ static void gpiolib_seq_stop(struct seq_file *s, void *v)
static int gpiolib_seq_show(struct seq_file *s, void *v)
{
struct gpio_device *gdev = v;
- struct gpio_chip *chip = gdev->chip;
+ struct gpio_chip *gc = gdev->chip;
struct device *parent;
- if (!chip) {
+ if (!gc) {
seq_printf(s, "%s%s: (dangling chip)", (char *)s->private,
dev_name(&gdev->dev));
return 0;
@@ -5209,19 +5388,19 @@ static int gpiolib_seq_show(struct seq_file *s, void *v)
seq_printf(s, "%s%s: GPIOs %d-%d", (char *)s->private,
dev_name(&gdev->dev),
gdev->base, gdev->base + gdev->ngpio - 1);
- parent = chip->parent;
+ parent = gc->parent;
if (parent)
seq_printf(s, ", parent: %s/%s",
parent->bus ? parent->bus->name : "no-bus",
dev_name(parent));
- if (chip->label)
- seq_printf(s, ", %s", chip->label);
- if (chip->can_sleep)
+ if (gc->label)
+ seq_printf(s, ", %s", gc->label);
+ if (gc->can_sleep)
seq_printf(s, ", can sleep");
seq_printf(s, ":\n");
- if (chip->dbg_show)
- chip->dbg_show(s, chip);
+ if (gc->dbg_show)
+ gc->dbg_show(s, gc);
else
gpiolib_dbg_show(s, gdev);