diff options
| -rw-r--r-- | drivers/i2c/muxes/i2c-arb-gpio-challenge.c | 79 |
1 files changed, 27 insertions, 52 deletions
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 @@ | |||
| 15 | */ | 15 | */ |
| 16 | 16 | ||
| 17 | #include <linux/delay.h> | 17 | #include <linux/delay.h> |
| 18 | #include <linux/gpio.h> | 18 | #include <linux/gpio/consumer.h> |
| 19 | #include <linux/kernel.h> | 19 | #include <linux/kernel.h> |
| 20 | #include <linux/i2c.h> | 20 | #include <linux/i2c.h> |
| 21 | #include <linux/i2c-mux.h> | 21 | #include <linux/i2c-mux.h> |
| 22 | #include <linux/module.h> | 22 | #include <linux/module.h> |
| 23 | #include <linux/of_gpio.h> | ||
| 24 | #include <linux/platform_device.h> | 23 | #include <linux/platform_device.h> |
| 25 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
| 26 | 25 | ||
| @@ -28,22 +27,16 @@ | |||
| 28 | /** | 27 | /** |
| 29 | * struct i2c_arbitrator_data - Driver data for I2C arbitrator | 28 | * struct i2c_arbitrator_data - Driver data for I2C arbitrator |
| 30 | * | 29 | * |
| 31 | * @our_gpio: GPIO we'll use to claim. | 30 | * @our_gpio: GPIO descriptor we'll use to claim. |
| 32 | * @our_gpio_release: 0 if active high; 1 if active low; AKA if the GPIO == | 31 | * @their_gpio: GPIO descriptor that the other side will use to claim. |
| 33 | * this then consider it released. | ||
| 34 | * @their_gpio: GPIO that the other side will use to claim. | ||
| 35 | * @their_gpio_release: 0 if active high; 1 if active low; AKA if the GPIO == | ||
| 36 | * this then consider it released. | ||
| 37 | * @slew_delay_us: microseconds to wait for a GPIO to go high. | 32 | * @slew_delay_us: microseconds to wait for a GPIO to go high. |
| 38 | * @wait_retry_us: we'll attempt another claim after this many microseconds. | 33 | * @wait_retry_us: we'll attempt another claim after this many microseconds. |
| 39 | * @wait_free_us: we'll give up after this many microseconds. | 34 | * @wait_free_us: we'll give up after this many microseconds. |
| 40 | */ | 35 | */ |
| 41 | 36 | ||
| 42 | struct i2c_arbitrator_data { | 37 | struct i2c_arbitrator_data { |
| 43 | int our_gpio; | 38 | struct gpio_desc *our_gpio; |
| 44 | int our_gpio_release; | 39 | struct gpio_desc *their_gpio; |
| 45 | int their_gpio; | ||
| 46 | int their_gpio_release; | ||
| 47 | unsigned int slew_delay_us; | 40 | unsigned int slew_delay_us; |
| 48 | unsigned int wait_retry_us; | 41 | unsigned int wait_retry_us; |
| 49 | unsigned int wait_free_us; | 42 | unsigned int wait_free_us; |
| @@ -64,15 +57,15 @@ static int i2c_arbitrator_select(struct i2c_mux_core *muxc, u32 chan) | |||
| 64 | stop_time = jiffies + usecs_to_jiffies(arb->wait_free_us) + 1; | 57 | stop_time = jiffies + usecs_to_jiffies(arb->wait_free_us) + 1; |
| 65 | do { | 58 | do { |
| 66 | /* Indicate that we want to claim the bus */ | 59 | /* Indicate that we want to claim the bus */ |
| 67 | gpio_set_value(arb->our_gpio, !arb->our_gpio_release); | 60 | gpiod_set_value(arb->our_gpio, 1); |
| 68 | udelay(arb->slew_delay_us); | 61 | udelay(arb->slew_delay_us); |
| 69 | 62 | ||
| 70 | /* Wait for the other master to release it */ | 63 | /* Wait for the other master to release it */ |
| 71 | stop_retry = jiffies + usecs_to_jiffies(arb->wait_retry_us) + 1; | 64 | stop_retry = jiffies + usecs_to_jiffies(arb->wait_retry_us) + 1; |
| 72 | while (time_before(jiffies, stop_retry)) { | 65 | while (time_before(jiffies, stop_retry)) { |
| 73 | int gpio_val = !!gpio_get_value(arb->their_gpio); | 66 | int gpio_val = gpiod_get_value(arb->their_gpio); |
| 74 | 67 | ||
| 75 | if (gpio_val == arb->their_gpio_release) { | 68 | if (!gpio_val) { |
| 76 | /* We got it, so return */ | 69 | /* We got it, so return */ |
| 77 | return 0; | 70 | return 0; |
| 78 | } | 71 | } |
| @@ -81,13 +74,13 @@ static int i2c_arbitrator_select(struct i2c_mux_core *muxc, u32 chan) | |||
| 81 | } | 74 | } |
| 82 | 75 | ||
| 83 | /* It didn't release, so give up, wait, and try again */ | 76 | /* It didn't release, so give up, wait, and try again */ |
| 84 | gpio_set_value(arb->our_gpio, arb->our_gpio_release); | 77 | gpiod_set_value(arb->our_gpio, 0); |
| 85 | 78 | ||
| 86 | usleep_range(arb->wait_retry_us, arb->wait_retry_us * 2); | 79 | usleep_range(arb->wait_retry_us, arb->wait_retry_us * 2); |
| 87 | } while (time_before(jiffies, stop_time)); | 80 | } while (time_before(jiffies, stop_time)); |
| 88 | 81 | ||
| 89 | /* Give up, release our claim */ | 82 | /* Give up, release our claim */ |
| 90 | gpio_set_value(arb->our_gpio, arb->our_gpio_release); | 83 | gpiod_set_value(arb->our_gpio, 0); |
| 91 | udelay(arb->slew_delay_us); | 84 | udelay(arb->slew_delay_us); |
| 92 | dev_err(muxc->dev, "Could not claim bus, timeout\n"); | 85 | dev_err(muxc->dev, "Could not claim bus, timeout\n"); |
| 93 | return -EBUSY; | 86 | return -EBUSY; |
| @@ -103,7 +96,7 @@ static int i2c_arbitrator_deselect(struct i2c_mux_core *muxc, u32 chan) | |||
| 103 | const struct i2c_arbitrator_data *arb = i2c_mux_priv(muxc); | 96 | const struct i2c_arbitrator_data *arb = i2c_mux_priv(muxc); |
| 104 | 97 | ||
| 105 | /* Release the bus and wait for the other master to notice */ | 98 | /* Release the bus and wait for the other master to notice */ |
| 106 | gpio_set_value(arb->our_gpio, arb->our_gpio_release); | 99 | gpiod_set_value(arb->our_gpio, 0); |
| 107 | udelay(arb->slew_delay_us); | 100 | udelay(arb->slew_delay_us); |
| 108 | 101 | ||
| 109 | return 0; | 102 | return 0; |
| @@ -116,8 +109,7 @@ static int i2c_arbitrator_probe(struct platform_device *pdev) | |||
| 116 | struct device_node *parent_np; | 109 | struct device_node *parent_np; |
| 117 | struct i2c_mux_core *muxc; | 110 | struct i2c_mux_core *muxc; |
| 118 | struct i2c_arbitrator_data *arb; | 111 | struct i2c_arbitrator_data *arb; |
| 119 | enum of_gpio_flags gpio_flags; | 112 | struct gpio_desc *dummy; |
| 120 | unsigned long out_init; | ||
| 121 | int ret; | 113 | int ret; |
| 122 | 114 | ||
| 123 | /* We only support probing from device tree; no platform_data */ | 115 | /* We only support probing from device tree; no platform_data */ |
| @@ -138,45 +130,28 @@ static int i2c_arbitrator_probe(struct platform_device *pdev) | |||
| 138 | 130 | ||
| 139 | platform_set_drvdata(pdev, muxc); | 131 | platform_set_drvdata(pdev, muxc); |
| 140 | 132 | ||
| 141 | /* Request GPIOs */ | 133 | /* Request GPIOs, our GPIO as unclaimed to begin with */ |
| 142 | ret = of_get_named_gpio_flags(np, "our-claim-gpio", 0, &gpio_flags); | 134 | arb->our_gpio = devm_gpiod_get(dev, "our-claim", GPIOD_OUT_LOW); |
| 143 | if (!gpio_is_valid(ret)) { | 135 | if (IS_ERR(arb->our_gpio)) { |
| 144 | if (ret != -EPROBE_DEFER) | 136 | dev_err(dev, "could not get \"our-claim\" GPIO (%ld)\n", |
| 145 | dev_err(dev, "Error getting our-claim-gpio\n"); | 137 | PTR_ERR(arb->our_gpio)); |
| 146 | return ret; | 138 | return PTR_ERR(arb->our_gpio); |
| 147 | } | ||
| 148 | arb->our_gpio = ret; | ||
| 149 | arb->our_gpio_release = !!(gpio_flags & OF_GPIO_ACTIVE_LOW); | ||
| 150 | out_init = (gpio_flags & OF_GPIO_ACTIVE_LOW) ? | ||
| 151 | GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW; | ||
| 152 | ret = devm_gpio_request_one(dev, arb->our_gpio, out_init, | ||
| 153 | "our-claim-gpio"); | ||
| 154 | if (ret) { | ||
| 155 | if (ret != -EPROBE_DEFER) | ||
| 156 | dev_err(dev, "Error requesting our-claim-gpio\n"); | ||
| 157 | return ret; | ||
| 158 | } | 139 | } |
| 159 | 140 | ||
| 160 | ret = of_get_named_gpio_flags(np, "their-claim-gpios", 0, &gpio_flags); | 141 | arb->their_gpio = devm_gpiod_get(dev, "their-claim", GPIOD_IN); |
| 161 | if (!gpio_is_valid(ret)) { | 142 | if (IS_ERR(arb->their_gpio)) { |
| 162 | if (ret != -EPROBE_DEFER) | 143 | dev_err(dev, "could not get \"their-claim\" GPIO (%ld)\n", |
| 163 | dev_err(dev, "Error getting their-claim-gpio\n"); | 144 | PTR_ERR(arb->their_gpio)); |
| 164 | return ret; | 145 | return PTR_ERR(arb->their_gpio); |
| 165 | } | ||
| 166 | arb->their_gpio = ret; | ||
| 167 | arb->their_gpio_release = !!(gpio_flags & OF_GPIO_ACTIVE_LOW); | ||
| 168 | ret = devm_gpio_request_one(dev, arb->their_gpio, GPIOF_IN, | ||
| 169 | "their-claim-gpio"); | ||
| 170 | if (ret) { | ||
| 171 | if (ret != -EPROBE_DEFER) | ||
| 172 | dev_err(dev, "Error requesting their-claim-gpio\n"); | ||
| 173 | return ret; | ||
| 174 | } | 146 | } |
| 175 | 147 | ||
| 176 | /* At the moment we only support a single two master (us + 1 other) */ | 148 | /* At the moment we only support a single two master (us + 1 other) */ |
| 177 | if (gpio_is_valid(of_get_named_gpio(np, "their-claim-gpios", 1))) { | 149 | dummy = devm_gpiod_get_index(dev, "their-claim", 1, GPIOD_IN); |
| 150 | if (!IS_ERR(dummy)) { | ||
| 178 | dev_err(dev, "Only one other master is supported\n"); | 151 | dev_err(dev, "Only one other master is supported\n"); |
| 179 | return -EINVAL; | 152 | return -EINVAL; |
| 153 | } else if (PTR_ERR(dummy) == -EPROBE_DEFER) { | ||
| 154 | return -EPROBE_DEFER; | ||
| 180 | } | 155 | } |
| 181 | 156 | ||
| 182 | /* Arbitration parameters */ | 157 | /* Arbitration parameters */ |
