diff options
author | Wolfram Sang <wsa@the-dreams.de> | 2019-06-29 13:02:48 +0200 |
---|---|---|
committer | Wolfram Sang <wsa@the-dreams.de> | 2019-06-29 13:02:48 +0200 |
commit | 45c9cc681d8d9122fd64e1f2a4cc82e3dcc7f0a5 (patch) | |
tree | 18ab31531ac870d6fa1ba2022a1c6d6886277a09 /drivers/i2c | |
parent | 504ee6b306a70a106c2e8858fd916ed8c43c5776 (diff) | |
parent | 05af0765707fc136433ab380d5d627afe3b8dda9 (diff) | |
download | linux-45c9cc681d8d9122fd64e1f2a4cc82e3dcc7f0a5.tar.bz2 |
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.
Diffstat (limited to 'drivers/i2c')
-rw-r--r-- | drivers/i2c/busses/i2c-i801.c | 37 | ||||
-rw-r--r-- | drivers/i2c/i2c-mux.c | 4 | ||||
-rw-r--r-- | drivers/i2c/muxes/i2c-arb-gpio-challenge.c | 79 | ||||
-rw-r--r-- | drivers/i2c/muxes/i2c-mux-gpio.c | 116 | ||||
-rw-r--r-- | drivers/i2c/muxes/i2c-mux-pinctrl.c | 5 |
5 files changed, 91 insertions, 150 deletions
diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index 82005291bcf3..763a8d6cc336 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c @@ -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) diff --git a/drivers/i2c/i2c-mux.c b/drivers/i2c/i2c-mux.c index 603252fa1284..774507b54b57 100644 --- a/drivers/i2c/i2c-mux.c +++ b/drivers/i2c/i2c-mux.c @@ -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; diff --git a/drivers/i2c/muxes/i2c-arb-gpio-challenge.c b/drivers/i2c/muxes/i2c-arb-gpio-challenge.c index 812b8cff265f..a664f637bc3d 100644 --- a/drivers/i2c/muxes/i2c-arb-gpio-challenge.c +++ b/drivers/i2c/muxes/i2c-arb-gpio-challenge.c @@ -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 */ diff --git a/drivers/i2c/muxes/i2c-mux-gpio.c b/drivers/i2c/muxes/i2c-mux-gpio.c index 13882a2a4f60..fd482feafb19 100644 --- a/drivers/i2c/muxes/i2c-mux-gpio.c +++ b/drivers/i2c/muxes/i2c-mux-gpio.c @@ -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; + 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; } - 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; - } - - 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 @@ alloc_failed: 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; diff --git a/drivers/i2c/muxes/i2c-mux-pinctrl.c b/drivers/i2c/muxes/i2c-mux-pinctrl.c index cc6818aabab5..ff3e8c9d4dd8 100644 --- a/drivers/i2c/muxes/i2c-mux-pinctrl.c +++ b/drivers/i2c/muxes/i2c-mux-pinctrl.c @@ -27,7 +27,7 @@ struct i2c_mux_pinctrl { struct pinctrl *pinctrl; - struct pinctrl_state **states; + struct pinctrl_state *states[]; }; static int i2c_mux_pinctrl_select(struct i2c_mux_core *muxc, u32 chan) @@ -104,14 +104,13 @@ static int i2c_mux_pinctrl_probe(struct platform_device *pdev) return PTR_ERR(parent); muxc = i2c_mux_alloc(parent, dev, num_names, - sizeof(*mux) + num_names * sizeof(*mux->states), + struct_size(mux, states, num_names), 0, i2c_mux_pinctrl_select, NULL); if (!muxc) { ret = -ENOMEM; goto err_put_parent; } mux = i2c_mux_priv(muxc); - mux->states = (struct pinctrl_state **)(mux + 1); platform_set_drvdata(pdev, muxc); |