aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpio/gpiolib.c
diff options
context:
space:
mode:
authorAlexandre Courbot <acourbot@nvidia.com>2013-12-02 22:20:11 -0500
committerLinus Walleij <linus.walleij@linaro.org>2013-12-09 08:05:51 -0500
commitad824783fb23bbc8295cffb6214b3b82d25f7d4a (patch)
tree745d128c1d04dca7a6c7b10dd737f116f13ddcb1 /drivers/gpio/gpiolib.c
parentbdc54ef45d7670aeb52ce73f8b7ad5f3e5563661 (diff)
gpio: better lookup method for platform GPIOs
Change the format of the platform GPIO lookup tables to make them less confusing and improve lookup efficiency. The previous format was a single linked-list that required to compare the device name and function ID of every single GPIO defined for each lookup. Switch that to a list of per-device tables, so that the lookup can be done in two steps, omitting the GPIOs that are not relevant for a particular device. The matching rules are now defined as follows: - The device name must match *exactly*, and can be NULL for GPIOs not assigned to a particular device, - If the function ID in the lookup table is NULL, the con_id argument of gpiod_get() will not be used for lookup. However, if it is defined, it must match exactly. - The index must always match. Signed-off-by: Alexandre Courbot <acourbot@nvidia.com> Acked-by: Mika Westerberg <mika.westerberg@linux.intel.com> Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'drivers/gpio/gpiolib.c')
-rw-r--r--drivers/gpio/gpiolib.c108
1 files changed, 58 insertions, 50 deletions
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 44a232701179..4eb262a31777 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -2260,18 +2260,14 @@ void gpiod_set_value_cansleep(struct gpio_desc *desc, int value)
2260EXPORT_SYMBOL_GPL(gpiod_set_value_cansleep); 2260EXPORT_SYMBOL_GPL(gpiod_set_value_cansleep);
2261 2261
2262/** 2262/**
2263 * gpiod_add_table() - register GPIO device consumers 2263 * gpiod_add_lookup_table() - register GPIO device consumers
2264 * @table: array of consumers to register 2264 * @table: table of consumers to register
2265 * @num: number of consumers in table
2266 */ 2265 */
2267void gpiod_add_table(struct gpiod_lookup *table, size_t size) 2266void gpiod_add_lookup_table(struct gpiod_lookup_table *table)
2268{ 2267{
2269 mutex_lock(&gpio_lookup_lock); 2268 mutex_lock(&gpio_lookup_lock);
2270 2269
2271 while (size--) { 2270 list_add_tail(&table->list, &gpio_lookup_list);
2272 list_add_tail(&table->list, &gpio_lookup_list);
2273 table++;
2274 }
2275 2271
2276 mutex_unlock(&gpio_lookup_lock); 2272 mutex_unlock(&gpio_lookup_lock);
2277} 2273}
@@ -2327,72 +2323,84 @@ static struct gpio_desc *acpi_find_gpio(struct device *dev, const char *con_id,
2327 return desc; 2323 return desc;
2328} 2324}
2329 2325
2330static struct gpio_desc *gpiod_find(struct device *dev, const char *con_id, 2326static struct gpiod_lookup_table *gpiod_find_lookup_table(struct device *dev)
2331 unsigned int idx,
2332 enum gpio_lookup_flags *flags)
2333{ 2327{
2334 const char *dev_id = dev ? dev_name(dev) : NULL; 2328 const char *dev_id = dev ? dev_name(dev) : NULL;
2335 struct gpio_desc *desc = ERR_PTR(-ENODEV); 2329 struct gpiod_lookup_table *table;
2336 unsigned int match, best = 0;
2337 struct gpiod_lookup *p;
2338 2330
2339 mutex_lock(&gpio_lookup_lock); 2331 mutex_lock(&gpio_lookup_lock);
2340 2332
2341 list_for_each_entry(p, &gpio_lookup_list, list) { 2333 list_for_each_entry(table, &gpio_lookup_list, list) {
2342 match = 0; 2334 if (table->dev_id && dev_id) {
2335 /*
2336 * Valid strings on both ends, must be identical to have
2337 * a match
2338 */
2339 if (!strcmp(table->dev_id, dev_id))
2340 goto found;
2341 } else {
2342 /*
2343 * One of the pointers is NULL, so both must be to have
2344 * a match
2345 */
2346 if (dev_id == table->dev_id)
2347 goto found;
2348 }
2349 }
2350 table = NULL;
2343 2351
2344 if (p->dev_id) { 2352found:
2345 if (!dev_id || strcmp(p->dev_id, dev_id)) 2353 mutex_unlock(&gpio_lookup_lock);
2346 continue; 2354 return table;
2355}
2347 2356
2348 match += 2; 2357static struct gpio_desc *gpiod_find(struct device *dev, const char *con_id,
2349 } 2358 unsigned int idx,
2359 enum gpio_lookup_flags *flags)
2360{
2361 struct gpio_desc *desc = ERR_PTR(-ENODEV);
2362 struct gpiod_lookup_table *table;
2363 struct gpiod_lookup *p;
2350 2364
2351 if (p->con_id) { 2365 table = gpiod_find_lookup_table(dev);
2352 if (!con_id || strcmp(p->con_id, con_id)) 2366 if (!table)
2353 continue; 2367 return desc;
2354 2368
2355 match += 1; 2369 for (p = &table->table[0]; p->chip_label; p++) {
2356 } 2370 struct gpio_chip *chip;
2357 2371
2372 /* idx must always match exactly */
2358 if (p->idx != idx) 2373 if (p->idx != idx)
2359 continue; 2374 continue;
2360 2375
2361 if (match > best) { 2376 /* If the lookup entry has a con_id, require exact match */
2362 struct gpio_chip *chip; 2377 if (p->con_id && (!con_id || strcmp(p->con_id, con_id)))
2363 2378 continue;
2364 chip = find_chip_by_name(p->chip_label);
2365
2366 if (!chip) {
2367 dev_warn(dev, "cannot find GPIO chip %s\n",
2368 p->chip_label);
2369 continue;
2370 }
2371 2379
2372 if (chip->ngpio <= p->chip_hwnum) { 2380 chip = find_chip_by_name(p->chip_label);
2373 dev_warn(dev, "GPIO chip %s has %d GPIOs\n",
2374 chip->label, chip->ngpio);
2375 continue;
2376 }
2377 2381
2378 desc = gpio_to_desc(chip->base + p->chip_hwnum); 2382 if (!chip) {
2379 *flags = p->flags; 2383 dev_warn(dev, "cannot find GPIO chip %s\n",
2384 p->chip_label);
2385 continue;
2386 }
2380 2387
2381 if (match != 3) 2388 if (chip->ngpio <= p->chip_hwnum) {
2382 best = match; 2389 dev_warn(dev, "GPIO chip %s has %d GPIOs\n",
2383 else 2390 chip->label, chip->ngpio);
2384 break; 2391 continue;
2385 } 2392 }
2386 }
2387 2393
2388 mutex_unlock(&gpio_lookup_lock); 2394 desc = gpiochip_offset_to_desc(chip, p->chip_hwnum);
2395 *flags = p->flags;
2396 }
2389 2397
2390 return desc; 2398 return desc;
2391} 2399}
2392 2400
2393/** 2401/**
2394 * gpio_get - obtain a GPIO for a given GPIO function 2402 * gpio_get - obtain a GPIO for a given GPIO function
2395 * @dev: GPIO consumer 2403 * @dev: GPIO consumer, can be NULL for system-global GPIOs
2396 * @con_id: function within the GPIO consumer 2404 * @con_id: function within the GPIO consumer
2397 * 2405 *
2398 * Return the GPIO descriptor corresponding to the function con_id of device 2406 * Return the GPIO descriptor corresponding to the function con_id of device