diff options
author | Alexandre Courbot <acourbot@nvidia.com> | 2013-12-02 22:20:11 -0500 |
---|---|---|
committer | Linus Walleij <linus.walleij@linaro.org> | 2013-12-09 08:05:51 -0500 |
commit | ad824783fb23bbc8295cffb6214b3b82d25f7d4a (patch) | |
tree | 745d128c1d04dca7a6c7b10dd737f116f13ddcb1 | |
parent | bdc54ef45d7670aeb52ce73f8b7ad5f3e5563661 (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.txt | 28 | ||||
-rw-r--r-- | drivers/gpio/gpiolib.c | 108 | ||||
-rw-r--r-- | include/linux/gpio/driver.h | 21 |
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 | ||
87 | Note that GPIO_LOOKUP() is just a shortcut to GPIO_LOOKUP_IDX() where idx = 0. | 88 | Note that GPIO_LOOKUP() is just a shortcut to GPIO_LOOKUP_IDX() where idx = 0. |
88 | 89 | ||
89 | A lookup table can then be defined as follows: | 90 | A lookup table can then be defined as follows, with an empty entry defining its |
91 | end: | ||
90 | 92 | ||
91 | struct gpiod_lookup gpios_table[] = { | 93 | struct 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 | ||
98 | And the table can be added by the board code as follows: | 104 | And 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 | ||
102 | The driver controlling "foo.0" will then be able to obtain its GPIOs as follows: | 108 | The 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) | |||
2260 | EXPORT_SYMBOL_GPL(gpiod_set_value_cansleep); | 2260 | EXPORT_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 | */ |
2267 | void gpiod_add_table(struct gpiod_lookup *table, size_t size) | 2266 | void 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 | ||
2330 | static struct gpio_desc *gpiod_find(struct device *dev, const char *con_id, | 2326 | static 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) { | 2352 | found: |
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; | 2357 | static 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 | */ |
143 | struct gpiod_lookup { | 143 | struct 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 | ||
166 | struct 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 | ||
193 | void gpiod_add_table(struct gpiod_lookup *table, size_t size); | 192 | void gpiod_add_lookup_table(struct gpiod_lookup_table *table); |
194 | 193 | ||
195 | #endif | 194 | #endif |