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

Commit 45c9cc68 authored by Wolfram Sang's avatar Wolfram Sang
Browse files

Merge branch 'i2c-mux/for-next' of https://github.com/peda-r/i2c-mux into i2c/for-5.3

I realize that there are changes in drivers/i2c/busses/i2c-i801.c that strictly
speaking don't belong here, but I hope you don't mind. These changes are all
about the interaction with the i2c-mux-gpio code, and I did a test-merge a few
days ago w/o conflicts.

Anyway, the GPIO-work from Linus Walleij (with help from Serge Semin) in the
i2c-mux-gpio and i2c-arb-gpio-challenge drivers is the main feature.
parents 504ee6b3 05af0765
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
What:		/sys/devices/platform/<i2c-demux-name>/available_masters
Date:		January 2016
KernelVersion:	4.6
Contact:	Wolfram Sang <wsa@the-dreams.de>
Contact:	Wolfram Sang <wsa+renesas@sang-engineering.com>
Description:
		Reading the file will give you a list of masters which can be
		selected for a demultiplexed bus. The format is
@@ -12,7 +12,7 @@ Description:
What:		/sys/devices/platform/<i2c-demux-name>/current_master
Date:		January 2016
KernelVersion:	4.6
Contact:	Wolfram Sang <wsa@the-dreams.de>
Contact:	Wolfram Sang <wsa+renesas@sang-engineering.com>
Description:
		This file selects/shows the active I2C master for a demultiplexed
		bus. It uses the <index> value from the file 'available_masters'.
+30 −7
Original line number Diff line number Diff line
@@ -109,7 +109,7 @@
#include <linux/pm_runtime.h>

#if IS_ENABLED(CONFIG_I2C_MUX_GPIO) && defined CONFIG_DMI
#include <linux/gpio.h>
#include <linux/gpio/machine.h>
#include <linux/platform_data/i2c-mux-gpio.h>
#endif

@@ -278,6 +278,7 @@ struct i801_priv {
#if IS_ENABLED(CONFIG_I2C_MUX_GPIO) && defined CONFIG_DMI
	const struct i801_mux_config *mux_drvdata;
	struct platform_device *mux_pdev;
	struct gpiod_lookup_table *lookup;
#endif
	struct platform_device *tco_pdev;

@@ -1406,7 +1407,8 @@ static int i801_add_mux(struct i801_priv *priv)
	struct device *dev = &priv->adapter.dev;
	const struct i801_mux_config *mux_config;
	struct i2c_mux_gpio_platform_data gpio_data;
	int err;
	struct gpiod_lookup_table *lookup;
	int err, i;

	if (!priv->mux_drvdata)
		return 0;
@@ -1418,17 +1420,36 @@ static int i801_add_mux(struct i801_priv *priv)
	gpio_data.values = mux_config->values;
	gpio_data.n_values = mux_config->n_values;
	gpio_data.classes = mux_config->classes;
	gpio_data.gpio_chip = mux_config->gpio_chip;
	gpio_data.gpios = mux_config->gpios;
	gpio_data.n_gpios = mux_config->n_gpios;
	gpio_data.idle = I2C_MUX_GPIO_NO_IDLE;

	/* Register the mux device */
	/* Register GPIO descriptor lookup table */
	lookup = devm_kzalloc(dev,
			      struct_size(lookup, table, mux_config->n_gpios),
			      GFP_KERNEL);
	if (!lookup)
		return -ENOMEM;
	lookup->dev_id = "i2c-mux-gpio";
	for (i = 0; i < mux_config->n_gpios; i++) {
		lookup->table[i].chip_label = mux_config->gpio_chip;
		lookup->table[i].chip_hwnum = mux_config->gpios[i];
		lookup->table[i].con_id = "mux";
	}
	gpiod_add_lookup_table(lookup);
	priv->lookup = lookup;

	/*
	 * Register the mux device, we use PLATFORM_DEVID_NONE here
	 * because since we are referring to the GPIO chip by name we are
	 * anyways in deep trouble if there is more than one of these
	 * devices, and there should likely only be one platform controller
	 * hub.
	 */
	priv->mux_pdev = platform_device_register_data(dev, "i2c-mux-gpio",
				PLATFORM_DEVID_AUTO, &gpio_data,
				PLATFORM_DEVID_NONE, &gpio_data,
				sizeof(struct i2c_mux_gpio_platform_data));
	if (IS_ERR(priv->mux_pdev)) {
		err = PTR_ERR(priv->mux_pdev);
		gpiod_remove_lookup_table(lookup);
		priv->mux_pdev = NULL;
		dev_err(dev, "Failed to register i2c-mux-gpio device\n");
		return err;
@@ -1441,6 +1462,8 @@ static void i801_del_mux(struct i801_priv *priv)
{
	if (priv->mux_pdev)
		platform_device_unregister(priv->mux_pdev);
	if (priv->lookup)
		gpiod_remove_lookup_table(priv->lookup);
}

static unsigned int i801_get_adapter_class(struct i801_priv *priv)
+2 −2
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/slab.h>
#include <linux/sysfs.h>

/* multiplexer per channel data */
struct i2c_mux_priv {
@@ -243,8 +244,7 @@ struct i2c_mux_core *i2c_mux_alloc(struct i2c_adapter *parent,
{
	struct i2c_mux_core *muxc;

	muxc = devm_kzalloc(dev, sizeof(*muxc)
			    + max_adapters * sizeof(muxc->adapter[0])
	muxc = devm_kzalloc(dev, struct_size(muxc, adapter, max_adapters)
			    + sizeof_priv, GFP_KERNEL);
	if (!muxc)
		return NULL;
+27 −52
Original line number Diff line number Diff line
@@ -15,12 +15,11 @@
 */

#include <linux/delay.h>
#include <linux/gpio.h>
#include <linux/gpio/consumer.h>
#include <linux/kernel.h>
#include <linux/i2c.h>
#include <linux/i2c-mux.h>
#include <linux/module.h>
#include <linux/of_gpio.h>
#include <linux/platform_device.h>
#include <linux/slab.h>

@@ -28,22 +27,16 @@
/**
 * struct i2c_arbitrator_data - Driver data for I2C arbitrator
 *
 * @our_gpio: GPIO we'll use to claim.
 * @our_gpio_release: 0 if active high; 1 if active low; AKA if the GPIO ==
 *   this then consider it released.
 * @their_gpio: GPIO that the other side will use to claim.
 * @their_gpio_release: 0 if active high; 1 if active low; AKA if the GPIO ==
 *   this then consider it released.
 * @our_gpio: GPIO descriptor we'll use to claim.
 * @their_gpio: GPIO descriptor that the other side will use to claim.
 * @slew_delay_us: microseconds to wait for a GPIO to go high.
 * @wait_retry_us: we'll attempt another claim after this many microseconds.
 * @wait_free_us: we'll give up after this many microseconds.
 */

struct i2c_arbitrator_data {
	int our_gpio;
	int our_gpio_release;
	int their_gpio;
	int their_gpio_release;
	struct gpio_desc *our_gpio;
	struct gpio_desc *their_gpio;
	unsigned int slew_delay_us;
	unsigned int wait_retry_us;
	unsigned int wait_free_us;
@@ -64,15 +57,15 @@ static int i2c_arbitrator_select(struct i2c_mux_core *muxc, u32 chan)
	stop_time = jiffies + usecs_to_jiffies(arb->wait_free_us) + 1;
	do {
		/* Indicate that we want to claim the bus */
		gpio_set_value(arb->our_gpio, !arb->our_gpio_release);
		gpiod_set_value(arb->our_gpio, 1);
		udelay(arb->slew_delay_us);

		/* Wait for the other master to release it */
		stop_retry = jiffies + usecs_to_jiffies(arb->wait_retry_us) + 1;
		while (time_before(jiffies, stop_retry)) {
			int gpio_val = !!gpio_get_value(arb->their_gpio);
			int gpio_val = gpiod_get_value(arb->their_gpio);

			if (gpio_val == arb->their_gpio_release) {
			if (!gpio_val) {
				/* We got it, so return */
				return 0;
			}
@@ -81,13 +74,13 @@ static int i2c_arbitrator_select(struct i2c_mux_core *muxc, u32 chan)
		}

		/* It didn't release, so give up, wait, and try again */
		gpio_set_value(arb->our_gpio, arb->our_gpio_release);
		gpiod_set_value(arb->our_gpio, 0);

		usleep_range(arb->wait_retry_us, arb->wait_retry_us * 2);
	} while (time_before(jiffies, stop_time));

	/* Give up, release our claim */
	gpio_set_value(arb->our_gpio, arb->our_gpio_release);
	gpiod_set_value(arb->our_gpio, 0);
	udelay(arb->slew_delay_us);
	dev_err(muxc->dev, "Could not claim bus, timeout\n");
	return -EBUSY;
@@ -103,7 +96,7 @@ static int i2c_arbitrator_deselect(struct i2c_mux_core *muxc, u32 chan)
	const struct i2c_arbitrator_data *arb = i2c_mux_priv(muxc);

	/* Release the bus and wait for the other master to notice */
	gpio_set_value(arb->our_gpio, arb->our_gpio_release);
	gpiod_set_value(arb->our_gpio, 0);
	udelay(arb->slew_delay_us);

	return 0;
@@ -116,8 +109,7 @@ static int i2c_arbitrator_probe(struct platform_device *pdev)
	struct device_node *parent_np;
	struct i2c_mux_core *muxc;
	struct i2c_arbitrator_data *arb;
	enum of_gpio_flags gpio_flags;
	unsigned long out_init;
	struct gpio_desc *dummy;
	int ret;

	/* We only support probing from device tree; no platform_data */
@@ -138,45 +130,28 @@ static int i2c_arbitrator_probe(struct platform_device *pdev)

	platform_set_drvdata(pdev, muxc);

	/* Request GPIOs */
	ret = of_get_named_gpio_flags(np, "our-claim-gpio", 0, &gpio_flags);
	if (!gpio_is_valid(ret)) {
		if (ret != -EPROBE_DEFER)
			dev_err(dev, "Error getting our-claim-gpio\n");
		return ret;
	}
	arb->our_gpio = ret;
	arb->our_gpio_release = !!(gpio_flags & OF_GPIO_ACTIVE_LOW);
	out_init = (gpio_flags & OF_GPIO_ACTIVE_LOW) ?
		GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW;
	ret = devm_gpio_request_one(dev, arb->our_gpio, out_init,
				    "our-claim-gpio");
	if (ret) {
		if (ret != -EPROBE_DEFER)
			dev_err(dev, "Error requesting our-claim-gpio\n");
		return ret;
	/* Request GPIOs, our GPIO as unclaimed to begin with */
	arb->our_gpio = devm_gpiod_get(dev, "our-claim", GPIOD_OUT_LOW);
	if (IS_ERR(arb->our_gpio)) {
		dev_err(dev, "could not get \"our-claim\" GPIO (%ld)\n",
			PTR_ERR(arb->our_gpio));
		return PTR_ERR(arb->our_gpio);
	}

	ret = of_get_named_gpio_flags(np, "their-claim-gpios", 0, &gpio_flags);
	if (!gpio_is_valid(ret)) {
		if (ret != -EPROBE_DEFER)
			dev_err(dev, "Error getting their-claim-gpio\n");
		return ret;
	}
	arb->their_gpio = ret;
	arb->their_gpio_release = !!(gpio_flags & OF_GPIO_ACTIVE_LOW);
	ret = devm_gpio_request_one(dev, arb->their_gpio, GPIOF_IN,
				    "their-claim-gpio");
	if (ret) {
		if (ret != -EPROBE_DEFER)
			dev_err(dev, "Error requesting their-claim-gpio\n");
		return ret;
	arb->their_gpio = devm_gpiod_get(dev, "their-claim", GPIOD_IN);
	if (IS_ERR(arb->their_gpio)) {
		dev_err(dev, "could not get \"their-claim\" GPIO (%ld)\n",
			PTR_ERR(arb->their_gpio));
		return PTR_ERR(arb->their_gpio);
	}

	/* At the moment we only support a single two master (us + 1 other) */
	if (gpio_is_valid(of_get_named_gpio(np, "their-claim-gpios", 1))) {
	dummy = devm_gpiod_get_index(dev, "their-claim", 1, GPIOD_IN);
	if (!IS_ERR(dummy)) {
		dev_err(dev, "Only one other master is supported\n");
		return -EINVAL;
	} else if (PTR_ERR(dummy) == -EPROBE_DEFER) {
		return -EPROBE_DEFER;
	}

	/* Arbitration parameters */
+30 −86
Original line number Diff line number Diff line
@@ -14,13 +14,14 @@
#include <linux/platform_device.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/gpio.h>
#include <linux/bits.h>
#include <linux/gpio/consumer.h>
/* FIXME: stop poking around inside gpiolib */
#include "../../gpio/gpiolib.h"
#include <linux/of_gpio.h>

struct gpiomux {
	struct i2c_mux_gpio_platform_data data;
	unsigned gpio_base;
	int ngpios;
	struct gpio_desc **gpios;
};

@@ -30,8 +31,7 @@ static void i2c_mux_gpio_set(const struct gpiomux *mux, unsigned val)

	values[0] = val;

	gpiod_set_array_value_cansleep(mux->data.n_gpios, mux->gpios, NULL,
				       values);
	gpiod_set_array_value_cansleep(mux->ngpios, mux->gpios, NULL, values);
}

static int i2c_mux_gpio_select(struct i2c_mux_core *muxc, u32 chan)
@@ -52,12 +52,6 @@ static int i2c_mux_gpio_deselect(struct i2c_mux_core *muxc, u32 chan)
	return 0;
}

static int match_gpio_chip_by_label(struct gpio_chip *chip,
					      void *data)
{
	return !strcmp(chip->label, data);
}

#ifdef CONFIG_OF
static int i2c_mux_gpio_probe_dt(struct gpiomux *mux,
					struct platform_device *pdev)
@@ -65,8 +59,8 @@ static int i2c_mux_gpio_probe_dt(struct gpiomux *mux,
	struct device_node *np = pdev->dev.of_node;
	struct device_node *adapter_np, *child;
	struct i2c_adapter *adapter;
	unsigned *values, *gpios;
	int i = 0, ret;
	unsigned *values;
	int i = 0;

	if (!np)
		return -ENODEV;
@@ -103,29 +97,6 @@ static int i2c_mux_gpio_probe_dt(struct gpiomux *mux,
	if (of_property_read_u32(np, "idle-state", &mux->data.idle))
		mux->data.idle = I2C_MUX_GPIO_NO_IDLE;

	mux->data.n_gpios = of_gpio_named_count(np, "mux-gpios");
	if (mux->data.n_gpios < 0) {
		dev_err(&pdev->dev, "Missing mux-gpios property in the DT.\n");
		return -EINVAL;
	}

	gpios = devm_kcalloc(&pdev->dev,
			     mux->data.n_gpios, sizeof(*mux->data.gpios),
			     GFP_KERNEL);
	if (!gpios) {
		dev_err(&pdev->dev, "Cannot allocate gpios array");
		return -ENOMEM;
	}

	for (i = 0; i < mux->data.n_gpios; i++) {
		ret = of_get_named_gpio(np, "mux-gpios", i);
		if (ret < 0)
			return ret;
		gpios[i] = ret;
	}

	mux->data.gpios = gpios;

	return 0;
}
#else
@@ -142,8 +113,8 @@ static int i2c_mux_gpio_probe(struct platform_device *pdev)
	struct gpiomux *mux;
	struct i2c_adapter *parent;
	struct i2c_adapter *root;
	unsigned initial_state, gpio_base;
	int i, ret;
	unsigned initial_state;
	int i, ngpios, ret;

	mux = devm_kzalloc(&pdev->dev, sizeof(*mux), GFP_KERNEL);
	if (!mux)
@@ -158,29 +129,19 @@ static int i2c_mux_gpio_probe(struct platform_device *pdev)
			sizeof(mux->data));
	}

	/*
	 * If a GPIO chip name is provided, the GPIO pin numbers provided are
	 * relative to its base GPIO number. Otherwise they are absolute.
	 */
	if (mux->data.gpio_chip) {
		struct gpio_chip *gpio;

		gpio = gpiochip_find(mux->data.gpio_chip,
				     match_gpio_chip_by_label);
		if (!gpio)
			return -EPROBE_DEFER;

		gpio_base = gpio->base;
	} else {
		gpio_base = 0;
	ngpios = gpiod_count(&pdev->dev, "mux");
	if (ngpios <= 0) {
		dev_err(&pdev->dev, "no valid gpios provided\n");
		return ngpios ?: -EINVAL;
	}
	mux->ngpios = ngpios;

	parent = i2c_get_adapter(mux->data.parent);
	if (!parent)
		return -EPROBE_DEFER;

	muxc = i2c_mux_alloc(parent, &pdev->dev, mux->data.n_values,
			     mux->data.n_gpios * sizeof(*mux->gpios), 0,
			     ngpios * sizeof(*mux->gpios), 0,
			     i2c_mux_gpio_select, NULL);
	if (!muxc) {
		ret = -ENOMEM;
@@ -194,7 +155,6 @@ static int i2c_mux_gpio_probe(struct platform_device *pdev)
	root = i2c_root_adapter(&parent->dev);

	muxc->mux_locked = true;
	mux->gpio_base = gpio_base;

	if (mux->data.idle != I2C_MUX_GPIO_NO_IDLE) {
		initial_state = mux->data.idle;
@@ -203,34 +163,28 @@ static int i2c_mux_gpio_probe(struct platform_device *pdev)
		initial_state = mux->data.values[0];
	}

	for (i = 0; i < mux->data.n_gpios; i++) {
	for (i = 0; i < ngpios; i++) {
		struct device *gpio_dev;
		struct gpio_desc *gpio_desc;

		ret = gpio_request(gpio_base + mux->data.gpios[i], "i2c-mux-gpio");
		if (ret) {
			dev_err(&pdev->dev, "Failed to request GPIO %d\n",
				mux->data.gpios[i]);
			goto err_request_gpio;
		}

		ret = gpio_direction_output(gpio_base + mux->data.gpios[i],
					    initial_state & (1 << i));
		if (ret) {
			dev_err(&pdev->dev,
				"Failed to set direction of GPIO %d to output\n",
				mux->data.gpios[i]);
			i++;	/* gpio_request above succeeded, so must free */
			goto err_request_gpio;
		struct gpio_desc *gpiod;
		enum gpiod_flags flag;

		if (initial_state & BIT(i))
			flag = GPIOD_OUT_HIGH;
		else
			flag = GPIOD_OUT_LOW;
		gpiod = devm_gpiod_get_index(&pdev->dev, "mux", i, flag);
		if (IS_ERR(gpiod)) {
			ret = PTR_ERR(gpiod);
			goto alloc_failed;
		}

		gpio_desc = gpio_to_desc(gpio_base + mux->data.gpios[i]);
		mux->gpios[i] = gpio_desc;
		mux->gpios[i] = gpiod;

		if (!muxc->mux_locked)
			continue;

		gpio_dev = &gpio_desc->gdev->dev;
		/* FIXME: find a proper way to access the GPIO device */
		gpio_dev = &gpiod->gdev->dev;
		muxc->mux_locked = i2c_root_adapter(gpio_dev) == root;
	}

@@ -253,10 +207,6 @@ static int i2c_mux_gpio_probe(struct platform_device *pdev)

add_adapter_failed:
	i2c_mux_del_adapters(muxc);
	i = mux->data.n_gpios;
err_request_gpio:
	for (; i > 0; i--)
		gpio_free(gpio_base + mux->data.gpios[i - 1]);
alloc_failed:
	i2c_put_adapter(parent);

@@ -266,14 +216,8 @@ static int i2c_mux_gpio_probe(struct platform_device *pdev)
static int i2c_mux_gpio_remove(struct platform_device *pdev)
{
	struct i2c_mux_core *muxc = platform_get_drvdata(pdev);
	struct gpiomux *mux = i2c_mux_priv(muxc);
	int i;

	i2c_mux_del_adapters(muxc);

	for (i = 0; i < mux->data.n_gpios; i++)
		gpio_free(mux->gpio_base + mux->data.gpios[i]);

	i2c_put_adapter(muxc->parent);

	return 0;
Loading