|
@@ -71,6 +71,9 @@ static DEFINE_MUTEX(gpio_lookup_lock);
|
|
|
static LIST_HEAD(gpio_lookup_list);
|
|
|
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,
|
|
|
struct lock_class_key *lock_key,
|
|
@@ -1171,6 +1174,41 @@ err_remove_device:
|
|
|
return status;
|
|
|
}
|
|
|
|
|
|
+static void gpiochip_machine_hog(struct gpio_chip *chip, struct gpiod_hog *hog)
|
|
|
+{
|
|
|
+ struct gpio_desc *desc;
|
|
|
+ int rv;
|
|
|
+
|
|
|
+ desc = gpiochip_get_desc(chip, hog->chip_hwnum);
|
|
|
+ if (IS_ERR(desc)) {
|
|
|
+ pr_err("%s: unable to get GPIO desc: %ld\n",
|
|
|
+ __func__, PTR_ERR(desc));
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (desc->flags & FLAG_IS_HOGGED)
|
|
|
+ return;
|
|
|
+
|
|
|
+ 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);
|
|
|
+}
|
|
|
+
|
|
|
+static void machine_gpiochip_add(struct gpio_chip *chip)
|
|
|
+{
|
|
|
+ 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);
|
|
|
+ }
|
|
|
+
|
|
|
+ mutex_unlock(&gpio_machine_hogs_mutex);
|
|
|
+}
|
|
|
+
|
|
|
static void gpiochip_setup_devs(void)
|
|
|
{
|
|
|
struct gpio_device *gdev;
|
|
@@ -1326,6 +1364,8 @@ int gpiochip_add_data_with_key(struct gpio_chip *chip, void *data,
|
|
|
|
|
|
acpi_gpiochip_add(chip);
|
|
|
|
|
|
+ machine_gpiochip_add(chip);
|
|
|
+
|
|
|
/*
|
|
|
* By first adding the chardev, and then adding the device,
|
|
|
* we get a device node entry in sysfs under
|
|
@@ -3462,6 +3502,33 @@ void gpiod_remove_lookup_table(struct gpiod_lookup_table *table)
|
|
|
}
|
|
|
EXPORT_SYMBOL_GPL(gpiod_remove_lookup_table);
|
|
|
|
|
|
+/**
|
|
|
+ * gpiod_add_hogs() - register a set of GPIO hogs from machine code
|
|
|
+ * @hogs: table of gpio hog entries with a zeroed sentinel at the end
|
|
|
+ */
|
|
|
+void gpiod_add_hogs(struct gpiod_hog *hogs)
|
|
|
+{
|
|
|
+ struct gpio_chip *chip;
|
|
|
+ struct gpiod_hog *hog;
|
|
|
+
|
|
|
+ mutex_lock(&gpio_machine_hogs_mutex);
|
|
|
+
|
|
|
+ for (hog = &hogs[0]; hog->chip_label; hog++) {
|
|
|
+ list_add_tail(&hog->list, &gpio_machine_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);
|
|
|
+ }
|
|
|
+
|
|
|
+ mutex_unlock(&gpio_machine_hogs_mutex);
|
|
|
+}
|
|
|
+EXPORT_SYMBOL_GPL(gpiod_add_hogs);
|
|
|
+
|
|
|
static struct gpiod_lookup_table *gpiod_find_lookup_table(struct device *dev)
|
|
|
{
|
|
|
const char *dev_id = dev ? dev_name(dev) : NULL;
|