Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 594fa265 authored by Grant Likely's avatar Grant Likely
Browse files

of/gpio: stop using device_node data pointer to find gpio_chip



Currently the kernel uses the struct device_node.data pointer to resolve
a struct gpio_chip pointer from a device tree node.  However, the .data
member doesn't provide any type checking and there aren't any rules
enforced on what it should be used for.  There's no guarantee that the
data stored in it actually points to an gpio_chip pointer.

Instead of relying on the .data pointer, this patch modifies the code
to add a lookup function which scans through the registered gpio_chips
and returns the gpio_chip that has a pointer to the specified
device_node.

Signed-off-by: default avatarGrant Likely <grant.likely@secretlab.ca>
CC: Andrew Morton <akpm@linux-foundation.org>
CC: Anton Vorontsov <avorontsov@ru.mvista.com>
CC: Grant Likely <grant.likely@secretlab.ca>
CC: David Brownell <dbrownell@users.sourceforge.net>
CC: Bill Gatliff <bgat@billgatliff.com>
CC: Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
CC: Benjamin Herrenschmidt <benh@kernel.crashing.org>
CC: Jean Delvare <khali@linux-fr.org>
CC: linux-kernel@vger.kernel.org
CC: devicetree-discuss@lists.ozlabs.org
parent a19e3da5
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -39,7 +39,7 @@ static int of_reset_gpio_handle(void)
		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);
+1 −0
Original line number Diff line number Diff line
@@ -350,6 +350,7 @@ mpc52xx_gpt_gpio_setup(struct mpc52xx_gpt_priv *gpt, struct device_node *node)
	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 */
+3 −20
Original line number Diff line number Diff line
@@ -35,7 +35,6 @@

struct mcu {
	struct mutex lock;
	struct device_node *np;
	struct i2c_client *client;
	struct gpio_chip gc;
	u8 reg_ctrl;
@@ -79,7 +78,6 @@ static int mcu_gpiochip_add(struct mcu *mcu)
{
	struct device_node *np;
	struct gpio_chip *gc = &mcu->gc;
	int ret;

	np = of_find_compatible_node(NULL, NULL, "fsl,mcu-mpc8349emitx");
	if (!np)
@@ -94,29 +92,14 @@ static int mcu_gpiochip_add(struct mcu *mcu)
	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,
+1 −1
Original line number Diff line number Diff line
@@ -167,7 +167,7 @@ struct qe_pin *qe_pin_request(struct device_node *np, int index)
		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);
+32 −0
Original line number Diff line number Diff line
@@ -1153,6 +1153,38 @@ int gpiochip_remove(struct gpio_chip *chip)
}
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.
Loading