aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--Documentation/gpio/board.txt28
-rw-r--r--drivers/gpio/gpiolib.c108
-rw-r--r--include/linux/gpio/driver.h21
3 files changed, 85 insertions, 72 deletions
diff --git a/Documentation/gpio/board.txt b/Documentation/gpio/board.txt
index 0d03506f2cc5..ba169faad5c6 100644
--- a/Documentation/gpio/board.txt
+++ b/Documentation/gpio/board.txt
@@ -72,10 +72,11 @@ where
72 72
73 - chip_label is the label of the gpiod_chip instance providing the GPIO 73 - chip_label is the label of the gpiod_chip instance providing the GPIO
74 - chip_hwnum is the hardware number of the GPIO within the chip 74 - chip_hwnum is the hardware number of the GPIO within the chip
75 - dev_id is the identifier of the device that will make use of this GPIO. If 75 - dev_id is the identifier of the device that will make use of this GPIO. It
76 NULL, the GPIO will be available to all devices. 76 can be NULL, in which case it will be matched for calls to gpiod_get()
77 with a NULL device.
77 - con_id is the name of the GPIO function from the device point of view. It 78 - con_id is the name of the GPIO function from the device point of view. It
78 can be NULL. 79 can be NULL, in which case it will match any function.
79 - idx is the index of the GPIO within the function. 80 - idx is the index of the GPIO within the function.
80 - flags is defined to specify the following properties: 81 - flags is defined to specify the following properties:
81 * GPIOF_ACTIVE_LOW - to configure the GPIO as active-low 82 * GPIOF_ACTIVE_LOW - to configure the GPIO as active-low
@@ -86,18 +87,23 @@ In the future, these flags might be extended to support more properties.
86 87
87Note that GPIO_LOOKUP() is just a shortcut to GPIO_LOOKUP_IDX() where idx = 0. 88Note that GPIO_LOOKUP() is just a shortcut to GPIO_LOOKUP_IDX() where idx = 0.
88 89
89A lookup table can then be defined as follows: 90A lookup table can then be defined as follows, with an empty entry defining its
91end:
90 92
91 struct gpiod_lookup gpios_table[] = { 93struct gpiod_lookup_table gpios_table = {
92 GPIO_LOOKUP_IDX("gpio.0", 15, "foo.0", "led", 0, GPIO_ACTIVE_HIGH), 94 .dev_id = "foo.0",
93 GPIO_LOOKUP_IDX("gpio.0", 16, "foo.0", "led", 1, GPIO_ACTIVE_HIGH), 95 .table = {
94 GPIO_LOOKUP_IDX("gpio.0", 17, "foo.0", "led", 2, GPIO_ACTIVE_HIGH), 96 GPIO_LOOKUP_IDX("gpio.0", 15, "led", 0, GPIO_ACTIVE_HIGH),
95 GPIO_LOOKUP("gpio.0", 1, "foo.0", "power", GPIO_ACTIVE_LOW), 97 GPIO_LOOKUP_IDX("gpio.0", 16, "led", 1, GPIO_ACTIVE_HIGH),
96 }; 98 GPIO_LOOKUP_IDX("gpio.0", 17, "led", 2, GPIO_ACTIVE_HIGH),
99 GPIO_LOOKUP("gpio.0", 1, "power", GPIO_ACTIVE_LOW),
100 { },
101 },
102};
97 103
98And the table can be added by the board code as follows: 104And the table can be added by the board code as follows:
99 105
100 gpiod_add_table(gpios_table, ARRAY_SIZE(gpios_table)); 106 gpiod_add_lookup_table(&gpios_table);
101 107
102The driver controlling "foo.0" will then be able to obtain its GPIOs as follows: 108The driver controlling "foo.0" will then be able to obtain its GPIOs as follows:
103 109
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
diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h
index c849676c6787..44c66b29a2d9 100644
--- a/include/linux/gpio/driver.h
+++ b/include/linux/gpio/driver.h
@@ -141,7 +141,6 @@ enum gpio_lookup_flags {
141 * platform data. 141 * platform data.
142 */ 142 */
143struct gpiod_lookup { 143struct gpiod_lookup {
144 struct list_head list;
145 /* 144 /*
146 * name of the chip the GPIO belongs to 145 * name of the chip the GPIO belongs to
147 */ 146 */
@@ -151,10 +150,6 @@ struct gpiod_lookup {
151 */ 150 */
152 u16 chip_hwnum; 151 u16 chip_hwnum;
153 /* 152 /*
154 * name of device that can claim this GPIO
155 */
156 const char *dev_id;
157 /*
158 * name of the GPIO from the device's point of view 153 * name of the GPIO from the device's point of view
159 */ 154 */
160 const char *con_id; 155 const char *con_id;
@@ -168,28 +163,32 @@ struct gpiod_lookup {
168 enum gpio_lookup_flags flags; 163 enum gpio_lookup_flags flags;
169}; 164};
170 165
166struct gpiod_lookup_table {
167 struct list_head list;
168 const char *dev_id;
169 struct gpiod_lookup table[];
170};
171
171/* 172/*
172 * Simple definition of a single GPIO under a con_id 173 * Simple definition of a single GPIO under a con_id
173 */ 174 */
174#define GPIO_LOOKUP(_chip_label, _chip_hwnum, _dev_id, _con_id, _flags) \ 175#define GPIO_LOOKUP(_chip_label, _chip_hwnum, _con_id, _flags) \
175 GPIO_LOOKUP_IDX(_chip_label, _chip_hwnum, _dev_id, _con_id, 0, _flags) 176 GPIO_LOOKUP_IDX(_chip_label, _chip_hwnum, _con_id, 0, _flags)
176 177
177/* 178/*
178 * Use this macro if you need to have several GPIOs under the same con_id. 179 * Use this macro if you need to have several GPIOs under the same con_id.
179 * Each GPIO needs to use a different index and can be accessed using 180 * Each GPIO needs to use a different index and can be accessed using
180 * gpiod_get_index() 181 * gpiod_get_index()
181 */ 182 */
182#define GPIO_LOOKUP_IDX(_chip_label, _chip_hwnum, _dev_id, _con_id, _idx, \ 183#define GPIO_LOOKUP_IDX(_chip_label, _chip_hwnum, _con_id, _idx, _flags) \
183 _flags) \
184{ \ 184{ \
185 .chip_label = _chip_label, \ 185 .chip_label = _chip_label, \
186 .chip_hwnum = _chip_hwnum, \ 186 .chip_hwnum = _chip_hwnum, \
187 .dev_id = _dev_id, \
188 .con_id = _con_id, \ 187 .con_id = _con_id, \
189 .idx = _idx, \ 188 .idx = _idx, \
190 .flags = _flags, \ 189 .flags = _flags, \
191} 190}
192 191
193void gpiod_add_table(struct gpiod_lookup *table, size_t size); 192void gpiod_add_lookup_table(struct gpiod_lookup_table *table);
194 193
195#endif 194#endif