1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (C) 2025 Linaro Ltd. 4 */ 5 6 #include <linux/auxiliary_bus.h> 7 #include <linux/cleanup.h> 8 #include <linux/device.h> 9 #include <linux/err.h> 10 #include <linux/gpio/consumer.h> 11 #include <linux/gpio/driver.h> 12 #include <linux/lockdep.h> 13 #include <linux/module.h> 14 #include <linux/mutex.h> 15 #include <linux/string_choices.h> 16 #include <linux/types.h> 17 18 #include "gpiolib-shared.h" 19 20 struct gpio_shared_proxy_data { 21 struct gpio_chip gc; 22 struct gpio_shared_desc *shared_desc; 23 struct device *dev; 24 bool voted_high; 25 }; 26 27 static int 28 gpio_shared_proxy_set_unlocked(struct gpio_shared_proxy_data *proxy, int value) 29 { 30 struct gpio_shared_desc *shared_desc = proxy->shared_desc; 31 struct gpio_desc *desc = shared_desc->desc; 32 int ret = 0; 33 34 lockdep_assert_held(&shared_desc->mutex); 35 36 if (value) { 37 /* User wants to set value to high. */ 38 if (proxy->voted_high) 39 /* Already voted for high, nothing to do. */ 40 goto out; 41 42 /* Haven't voted for high yet. */ 43 if (!shared_desc->highcnt) { 44 /* 45 * Current value is low, need to actually set value 46 * to high. 47 */ 48 ret = gpiod_set_value_cansleep(desc, 1); 49 if (ret) 50 goto out; 51 } 52 53 shared_desc->highcnt++; 54 proxy->voted_high = true; 55 56 goto out; 57 } 58 59 /* Desired value is low. */ 60 if (!proxy->voted_high) 61 /* We didn't vote for high, nothing to do. */ 62 goto out; 63 64 /* We previously voted for high. */ 65 if (shared_desc->highcnt == 1) { 66 /* This is the last remaining vote for high, set value to low. */ 67 ret = gpiod_set_value_cansleep(desc, 0); 68 if (ret) 69 goto out; 70 } 71 72 shared_desc->highcnt--; 73 proxy->voted_high = false; 74 75 out: 76 if (shared_desc->highcnt) 77 dev_dbg(proxy->dev, 78 "Voted for value '%s', effective value is 'high', number of votes for 'high': %u\n", 79 str_high_low(value), shared_desc->highcnt); 80 else 81 dev_dbg(proxy->dev, "Voted for value 'low', effective value is 'low'\n"); 82 83 return ret; 84 } 85 86 static int gpio_shared_proxy_request(struct gpio_chip *gc, unsigned int offset) 87 { 88 struct gpio_shared_proxy_data *proxy = gpiochip_get_data(gc); 89 struct gpio_shared_desc *shared_desc = proxy->shared_desc; 90 91 guard(mutex)(&shared_desc->mutex); 92 93 proxy->shared_desc->usecnt++; 94 95 dev_dbg(proxy->dev, "Shared GPIO requested, number of users: %u\n", 96 proxy->shared_desc->usecnt); 97 98 return 0; 99 } 100 101 static void gpio_shared_proxy_free(struct gpio_chip *gc, unsigned int offset) 102 { 103 struct gpio_shared_proxy_data *proxy = gpiochip_get_data(gc); 104 struct gpio_shared_desc *shared_desc = proxy->shared_desc; 105 int ret; 106 107 guard(mutex)(&shared_desc->mutex); 108 109 if (proxy->voted_high) { 110 ret = gpio_shared_proxy_set_unlocked(proxy, 0); 111 if (ret) 112 dev_err(proxy->dev, 113 "Failed to unset the shared GPIO value on release: %d\n", ret); 114 } 115 116 proxy->shared_desc->usecnt--; 117 118 dev_dbg(proxy->dev, "Shared GPIO freed, number of users: %u\n", 119 proxy->shared_desc->usecnt); 120 } 121 122 static int gpio_shared_proxy_set_config(struct gpio_chip *gc, 123 unsigned int offset, unsigned long cfg) 124 { 125 struct gpio_shared_proxy_data *proxy = gpiochip_get_data(gc); 126 struct gpio_shared_desc *shared_desc = proxy->shared_desc; 127 struct gpio_desc *desc = shared_desc->desc; 128 int ret; 129 130 guard(mutex)(&shared_desc->mutex); 131 132 if (shared_desc->usecnt > 1) { 133 if (shared_desc->cfg != cfg) { 134 dev_dbg(proxy->dev, 135 "Shared GPIO's configuration already set, accepting changes but users may conflict!!\n"); 136 } else { 137 dev_dbg(proxy->dev, "Equal config requested, nothing to do\n"); 138 return 0; 139 } 140 } 141 142 ret = gpiod_set_config(desc, cfg); 143 if (ret && ret != -ENOTSUPP) 144 return ret; 145 146 shared_desc->cfg = cfg; 147 return 0; 148 } 149 150 static int gpio_shared_proxy_direction_input(struct gpio_chip *gc, 151 unsigned int offset) 152 { 153 struct gpio_shared_proxy_data *proxy = gpiochip_get_data(gc); 154 struct gpio_shared_desc *shared_desc = proxy->shared_desc; 155 struct gpio_desc *desc = shared_desc->desc; 156 int dir; 157 158 guard(mutex)(&shared_desc->mutex); 159 160 if (shared_desc->usecnt == 1) { 161 dev_dbg(proxy->dev, 162 "Only one user of this shared GPIO, allowing to set direction to input\n"); 163 164 return gpiod_direction_input(desc); 165 } 166 167 dir = gpiod_get_direction(desc); 168 if (dir < 0) 169 return dir; 170 171 if (dir == GPIO_LINE_DIRECTION_OUT) { 172 dev_dbg(proxy->dev, 173 "Shared GPIO's direction already set to output, refusing to change\n"); 174 return -EPERM; 175 } 176 177 return 0; 178 } 179 180 static int gpio_shared_proxy_direction_output(struct gpio_chip *gc, 181 unsigned int offset, int value) 182 { 183 struct gpio_shared_proxy_data *proxy = gpiochip_get_data(gc); 184 struct gpio_shared_desc *shared_desc = proxy->shared_desc; 185 struct gpio_desc *desc = shared_desc->desc; 186 int ret, dir; 187 188 guard(mutex)(&shared_desc->mutex); 189 190 if (shared_desc->usecnt == 1) { 191 dev_dbg(proxy->dev, 192 "Only one user of this shared GPIO, allowing to set direction to output with value '%s'\n", 193 str_high_low(value)); 194 195 ret = gpiod_direction_output(desc, value); 196 if (ret) 197 return ret; 198 199 if (value) { 200 proxy->voted_high = true; 201 shared_desc->highcnt = 1; 202 } else { 203 proxy->voted_high = false; 204 shared_desc->highcnt = 0; 205 } 206 207 return 0; 208 } 209 210 dir = gpiod_get_direction(desc); 211 if (dir < 0) 212 return dir; 213 214 if (dir == GPIO_LINE_DIRECTION_IN) { 215 dev_dbg(proxy->dev, 216 "Shared GPIO's direction already set to input, refusing to change\n"); 217 return -EPERM; 218 } 219 220 return gpio_shared_proxy_set_unlocked(proxy, value); 221 } 222 223 static int gpio_shared_proxy_get_cansleep(struct gpio_chip *gc, 224 unsigned int offset) 225 { 226 struct gpio_shared_proxy_data *proxy = gpiochip_get_data(gc); 227 228 return gpiod_get_value_cansleep(proxy->shared_desc->desc); 229 } 230 231 static int gpio_shared_proxy_set_cansleep(struct gpio_chip *gc, 232 unsigned int offset, int value) 233 { 234 struct gpio_shared_proxy_data *proxy = gpiochip_get_data(gc); 235 236 guard(mutex)(&proxy->shared_desc->mutex); 237 238 return gpio_shared_proxy_set_unlocked(proxy, value); 239 } 240 241 static int gpio_shared_proxy_get_direction(struct gpio_chip *gc, 242 unsigned int offset) 243 { 244 struct gpio_shared_proxy_data *proxy = gpiochip_get_data(gc); 245 246 return gpiod_get_direction(proxy->shared_desc->desc); 247 } 248 249 static int gpio_shared_proxy_to_irq(struct gpio_chip *gc, unsigned int offset) 250 { 251 struct gpio_shared_proxy_data *proxy = gpiochip_get_data(gc); 252 253 return gpiod_to_irq(proxy->shared_desc->desc); 254 } 255 256 static int gpio_shared_proxy_probe(struct auxiliary_device *adev, 257 const struct auxiliary_device_id *id) 258 { 259 struct gpio_shared_proxy_data *proxy; 260 struct gpio_shared_desc *shared_desc; 261 struct device *dev = &adev->dev; 262 struct gpio_chip *gc; 263 264 shared_desc = devm_gpiod_shared_get(dev); 265 if (IS_ERR(shared_desc)) 266 return PTR_ERR(shared_desc); 267 268 proxy = devm_kzalloc(dev, sizeof(*proxy), GFP_KERNEL); 269 if (!proxy) 270 return -ENOMEM; 271 272 proxy->shared_desc = shared_desc; 273 proxy->dev = dev; 274 275 gc = &proxy->gc; 276 gc->base = -1; 277 gc->ngpio = 1; 278 gc->label = dev_name(dev); 279 gc->parent = dev; 280 gc->owner = THIS_MODULE; 281 /* 282 * Under the descriptor mutex the proxy may call 283 * gpiod_set_config()/gpiod_direction_*(), which can reach pinctrl 284 * paths that take a mutex (e.g. gpiod_set_config() -> 285 * gpiochip_generic_config() -> pinctrl_gpio_set_config()), independent 286 * of the underlying chip's can_sleep. So the descriptor lock must be a 287 * mutex and the proxy gpiochip is therefore always sleeping; drive the 288 * underlying GPIO through the cansleep value accessors, which are valid 289 * for both sleeping and non-sleeping chips. 290 */ 291 gc->can_sleep = true; 292 293 gc->request = gpio_shared_proxy_request; 294 gc->free = gpio_shared_proxy_free; 295 gc->set_config = gpio_shared_proxy_set_config; 296 gc->direction_input = gpio_shared_proxy_direction_input; 297 gc->direction_output = gpio_shared_proxy_direction_output; 298 gc->set = gpio_shared_proxy_set_cansleep; 299 gc->get = gpio_shared_proxy_get_cansleep; 300 gc->get_direction = gpio_shared_proxy_get_direction; 301 gc->to_irq = gpio_shared_proxy_to_irq; 302 303 return devm_gpiochip_add_data(dev, &proxy->gc, proxy); 304 } 305 306 static const struct auxiliary_device_id gpio_shared_proxy_id_table[] = { 307 { .name = "gpiolib_shared.proxy" }, 308 {}, 309 }; 310 MODULE_DEVICE_TABLE(auxiliary, gpio_shared_proxy_id_table); 311 312 static struct auxiliary_driver gpio_shared_proxy_driver = { 313 .driver = { 314 .name = "gpio-shared-proxy", 315 .suppress_bind_attrs = true, 316 }, 317 .probe = gpio_shared_proxy_probe, 318 .id_table = gpio_shared_proxy_id_table, 319 }; 320 module_auxiliary_driver(gpio_shared_proxy_driver); 321 322 MODULE_AUTHOR("Bartosz Golaszewski <bartosz.golaszewski@linaro.org>"); 323 MODULE_DESCRIPTION("Shared GPIO mux driver."); 324 MODULE_LICENSE("GPL"); 325