goto err0;
}
- gc = gpio->data;
+ gc = of_node_to_gpiochip(gpio);
if (!gc) {
pr_debug("%s: gpio controller %s isn't registered\n",
root->full_name, gpio->full_name);
gpt->gc.base = -1;
gpt->gc.of_gpio_n_cells = 2;
gpt->gc.of_xlate = of_gpio_simple_xlate;
+ gpt->gc.of_node = node;
of_node_get(node);
/* Setup external pin in GPIO mode */
struct mcu {
struct mutex lock;
- struct device_node *np;
struct i2c_client *client;
struct gpio_chip gc;
u8 reg_ctrl;
{
struct device_node *np;
struct gpio_chip *gc = &mcu->gc;
- int ret;
np = of_find_compatible_node(NULL, NULL, "fsl,mcu-mpc8349emitx");
if (!np)
gc->direction_output = mcu_gpio_dir_out;
gc->of_gpio_n_cells = 2;
gc->of_xlate = of_gpio_simple_xlate;
+ gc->of_node = np;
- mcu->np = np;
-
- /*
- * We don't want to lose the node, its ->data and ->full_name...
- * So, if succeeded, we don't put the node here.
- */
- ret = gpiochip_add(gc);
- if (ret)
- of_node_put(np);
- return ret;
+ return gpiochip_add(gc);
}
static int mcu_gpiochip_remove(struct mcu *mcu)
{
- int ret;
-
- ret = gpiochip_remove(&mcu->gc);
- if (ret)
- return ret;
- of_node_put(mcu->np);
-
- return 0;
+ return gpiochip_remove(&mcu->gc);
}
static int __devinit mcu_probe(struct i2c_client *client,
goto err1;
}
- gc = gpio_np->data;
+ gc = of_node_to_gpiochip(gpio_np);
if (!gc) {
pr_debug("%s: gpio controller %s isn't registered\n",
np->full_name, gpio_np->full_name);
}
EXPORT_SYMBOL_GPL(gpiochip_remove);
+/**
+ * gpiochip_find() - iterator for locating a specific gpio_chip
+ * @data: data to pass to match function
+ * @callback: Callback function to check gpio_chip
+ *
+ * Similar to bus_find_device. It returns a reference to a gpio_chip as
+ * determined by a user supplied @match callback. The callback should return
+ * 0 if the device doesn't match and non-zero if it does. If the callback is
+ * non-zero, this function will return to the caller and not iterate over any
+ * more gpio_chips.
+ */
+struct gpio_chip *gpiochip_find(void *data,
+ int (*match)(struct gpio_chip *chip, void *data))
+{
+ struct gpio_chip *chip = NULL;
+ unsigned long flags;
+ int i;
+
+ spin_lock_irqsave(&gpio_lock, flags);
+ for (i = 0; i < ARCH_NR_GPIOS; i++) {
+ if (!gpio_desc[i].chip)
+ continue;
+
+ if (match(gpio_desc[i].chip, data)) {
+ chip = gpio_desc[i].chip;
+ break;
+ }
+ }
+ spin_unlock_irqrestore(&gpio_lock, flags);
+
+ return chip;
+}
/* These "optional" allocation calls help prevent drivers from stomping
* on each other, and help provide better diagnostics in debugfs.
goto err0;
}
- gc = gpio_np->data;
+ gc = of_node_to_gpiochip(gpio_np);
if (!gc) {
pr_debug("%s: gpio controller %s isn't registered\n",
np->full_name, gpio_np->full_name);
if (mm_gc->save_regs)
mm_gc->save_regs(mm_gc);
- np->data = &mm_gc->gc;
mm_gc->gc.of_node = np;
ret = gpiochip_add(gc);
np->full_name, gc->base);
return 0;
err2:
- np->data = NULL;
iounmap(mm_gc->regs);
err1:
kfree(gc->label);
return ret;
}
EXPORT_SYMBOL(of_mm_gpiochip_add);
+
+/* Private function for resolving node pointer to gpio_chip */
+static int of_gpiochip_is_match(struct gpio_chip *chip, void *data)
+{
+ return chip->of_node == data;
+}
+
+struct gpio_chip *of_node_to_gpiochip(struct device_node *np)
+{
+ return gpiochip_find(np, of_gpiochip_is_match);
+}
/* add/remove chips */
extern int gpiochip_add(struct gpio_chip *chip);
extern int __must_check gpiochip_remove(struct gpio_chip *chip);
+extern struct gpio_chip *gpiochip_find(void *data,
+ int (*match)(struct gpio_chip *chip,
+ void *data));
/* Always use the library code for GPIO management calls,
struct of_mm_gpio_chip *mm_gc);
extern int of_gpio_simple_xlate(struct gpio_chip *gc, struct device_node *np,
const void *gpio_spec, u32 *flags);
+
+extern struct gpio_chip *of_node_to_gpiochip(struct device_node *np);
+
#else /* CONFIG_OF_GPIO */
/* Drivers may not strictly depend on the GPIO support, so let them link. */