Commit 6c0b4e6c85d085bd92966bc2b8da73e2d7f35929
Committed by
Grant Likely
1 parent
372e722ea4
Exists in
smarc-l5.0.0_1.0.0-ga
and in
5 other branches
gpiolib: let gpio_chip reference its descriptors
Add a pointer to the gpio_chip structure that references the array of GPIO descriptors belonging to the chip, and update gpiolib code to use this pointer instead of the global gpio_desc[] array. This is another step towards the removal of the gpio_desc[] global array. Signed-off-by: Alexandre Courbot <acourbot@nvidia.com> Reviewed-by: Linus Walleij <linus.walleij@linaro.orh> Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
Showing 2 changed files with 26 additions and 16 deletions Side-by-side Diff
drivers/gpio/gpiolib.c
... | ... | @@ -72,6 +72,8 @@ |
72 | 72 | }; |
73 | 73 | static struct gpio_desc gpio_desc[ARCH_NR_GPIOS]; |
74 | 74 | |
75 | +#define GPIO_OFFSET_VALID(chip, offset) (offset >= 0 && offset < chip->ngpio) | |
76 | + | |
75 | 77 | static LIST_HEAD(gpio_chips); |
76 | 78 | |
77 | 79 | #ifdef CONFIG_GPIO_SYSFS |
... | ... | @@ -112,7 +114,7 @@ |
112 | 114 | */ |
113 | 115 | static int gpio_chip_hwgpio(const struct gpio_desc *desc) |
114 | 116 | { |
115 | - return (desc - &gpio_desc[0]) - desc->chip->base; | |
117 | + return desc - &desc->chip->desc[0]; | |
116 | 118 | } |
117 | 119 | |
118 | 120 | /** |
... | ... | @@ -133,7 +135,7 @@ |
133 | 135 | */ |
134 | 136 | static int desc_to_gpio(const struct gpio_desc *desc) |
135 | 137 | { |
136 | - return desc - &gpio_desc[0]; | |
138 | + return desc->chip->base + gpio_chip_hwgpio(desc); | |
137 | 139 | } |
138 | 140 | |
139 | 141 | |
... | ... | @@ -1007,9 +1009,9 @@ |
1007 | 1009 | unsigned gpio; |
1008 | 1010 | |
1009 | 1011 | spin_lock_irqsave(&gpio_lock, flags); |
1010 | - gpio = chip->base; | |
1011 | - while (gpio_desc[gpio].chip == chip) | |
1012 | - gpio_desc[gpio++].chip = NULL; | |
1012 | + gpio = 0; | |
1013 | + while (gpio < chip->ngpio) | |
1014 | + chip->desc[gpio++].chip = NULL; | |
1013 | 1015 | spin_unlock_irqrestore(&gpio_lock, flags); |
1014 | 1016 | |
1015 | 1017 | pr_debug("%s: chip %s status %d\n", __func__, |
1016 | 1018 | |
... | ... | @@ -1186,9 +1188,12 @@ |
1186 | 1188 | status = gpiochip_add_to_list(chip); |
1187 | 1189 | |
1188 | 1190 | if (status == 0) { |
1189 | - for (id = base; id < base + chip->ngpio; id++) { | |
1190 | - gpio_desc[id].chip = chip; | |
1191 | + chip->desc = &gpio_desc[chip->base]; | |
1191 | 1192 | |
1193 | + for (id = 0; id < chip->ngpio; id++) { | |
1194 | + struct gpio_desc *desc = &chip->desc[id]; | |
1195 | + desc->chip = chip; | |
1196 | + | |
1192 | 1197 | /* REVISIT: most hardware initializes GPIOs as |
1193 | 1198 | * inputs (often with pullups enabled) so power |
1194 | 1199 | * usage is minimized. Linux code should set the |
... | ... | @@ -1196,7 +1201,7 @@ |
1196 | 1201 | * and in case chip->get_direction is not set, |
1197 | 1202 | * we may expose the wrong direction in sysfs. |
1198 | 1203 | */ |
1199 | - gpio_desc[id].flags = !chip->direction_input | |
1204 | + desc->flags = !chip->direction_input | |
1200 | 1205 | ? (1 << FLAG_IS_OUT) |
1201 | 1206 | : 0; |
1202 | 1207 | } |
1203 | 1208 | |
... | ... | @@ -1249,15 +1254,15 @@ |
1249 | 1254 | gpiochip_remove_pin_ranges(chip); |
1250 | 1255 | of_gpiochip_remove(chip); |
1251 | 1256 | |
1252 | - for (id = chip->base; id < chip->base + chip->ngpio; id++) { | |
1253 | - if (test_bit(FLAG_REQUESTED, &gpio_desc[id].flags)) { | |
1257 | + for (id = 0; id < chip->ngpio; id++) { | |
1258 | + if (test_bit(FLAG_REQUESTED, &chip->desc[id].flags)) { | |
1254 | 1259 | status = -EBUSY; |
1255 | 1260 | break; |
1256 | 1261 | } |
1257 | 1262 | } |
1258 | 1263 | if (status == 0) { |
1259 | - for (id = chip->base; id < chip->base + chip->ngpio; id++) | |
1260 | - gpio_desc[id].chip = NULL; | |
1264 | + for (id = 0; id < chip->ngpio; id++) | |
1265 | + chip->desc[id].chip = NULL; | |
1261 | 1266 | |
1262 | 1267 | list_del(&chip->list); |
1263 | 1268 | } |
1264 | 1269 | |
1265 | 1270 | |
... | ... | @@ -1582,11 +1587,13 @@ |
1582 | 1587 | */ |
1583 | 1588 | const char *gpiochip_is_requested(struct gpio_chip *chip, unsigned offset) |
1584 | 1589 | { |
1585 | - unsigned gpio = chip->base + offset; | |
1586 | - struct gpio_desc *desc = &gpio_desc[gpio]; | |
1590 | + struct gpio_desc *desc; | |
1587 | 1591 | |
1588 | - if (!gpio_is_valid(gpio) || desc->chip != chip) | |
1592 | + if (!GPIO_OFFSET_VALID(chip, offset)) | |
1589 | 1593 | return NULL; |
1594 | + | |
1595 | + desc = &chip->desc[offset]; | |
1596 | + | |
1590 | 1597 | if (test_bit(FLAG_REQUESTED, &desc->flags) == 0) |
1591 | 1598 | return NULL; |
1592 | 1599 | #ifdef CONFIG_DEBUG_FS |
... | ... | @@ -2025,7 +2032,7 @@ |
2025 | 2032 | { |
2026 | 2033 | unsigned i; |
2027 | 2034 | unsigned gpio = chip->base; |
2028 | - struct gpio_desc *gdesc = &gpio_desc[gpio]; | |
2035 | + struct gpio_desc *gdesc = &chip->desc[0]; | |
2029 | 2036 | int is_out; |
2030 | 2037 | |
2031 | 2038 | for (i = 0; i < chip->ngpio; i++, gpio++, gdesc++) { |
include/asm-generic/gpio.h
... | ... | @@ -47,6 +47,7 @@ |
47 | 47 | struct seq_file; |
48 | 48 | struct module; |
49 | 49 | struct device_node; |
50 | +struct gpio_desc; | |
50 | 51 | |
51 | 52 | /** |
52 | 53 | * struct gpio_chip - abstract a GPIO controller |
... | ... | @@ -76,6 +77,7 @@ |
76 | 77 | * negative during registration, requests dynamic ID allocation. |
77 | 78 | * @ngpio: the number of GPIOs handled by this controller; the last GPIO |
78 | 79 | * handled is (base + ngpio - 1). |
80 | + * @desc: array of ngpio descriptors. Private. | |
79 | 81 | * @can_sleep: flag must be set iff get()/set() methods sleep, as they |
80 | 82 | * must while accessing GPIO expander chips over I2C or SPI |
81 | 83 | * @names: if set, must be an array of strings to use as alternative |
... | ... | @@ -126,6 +128,7 @@ |
126 | 128 | struct gpio_chip *chip); |
127 | 129 | int base; |
128 | 130 | u16 ngpio; |
131 | + struct gpio_desc *desc; | |
129 | 132 | const char *const *names; |
130 | 133 | unsigned can_sleep:1; |
131 | 134 | unsigned exported:1; |