diff options
| -rw-r--r-- | drivers/gpio/gpiolib.c | 39 | ||||
| -rw-r--r-- | include/asm-generic/gpio.h | 3 |
2 files changed, 26 insertions, 16 deletions
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 866431f674c3..5050693dcc35 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c | |||
| @@ -72,6 +72,8 @@ struct gpio_desc { | |||
| 72 | }; | 72 | }; |
| 73 | static struct gpio_desc gpio_desc[ARCH_NR_GPIOS]; | 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 | static LIST_HEAD(gpio_chips); | 77 | static LIST_HEAD(gpio_chips); |
| 76 | 78 | ||
| 77 | #ifdef CONFIG_GPIO_SYSFS | 79 | #ifdef CONFIG_GPIO_SYSFS |
| @@ -112,7 +114,7 @@ static inline void desc_set_label(struct gpio_desc *d, const char *label) | |||
| 112 | */ | 114 | */ |
| 113 | static int gpio_chip_hwgpio(const struct gpio_desc *desc) | 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 @@ static struct gpio_desc *gpio_to_desc(unsigned gpio) | |||
| 133 | */ | 135 | */ |
| 134 | static int desc_to_gpio(const struct gpio_desc *desc) | 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 @@ static int gpiochip_export(struct gpio_chip *chip) | |||
| 1007 | unsigned gpio; | 1009 | unsigned gpio; |
| 1008 | 1010 | ||
| 1009 | spin_lock_irqsave(&gpio_lock, flags); | 1011 | spin_lock_irqsave(&gpio_lock, flags); |
| 1010 | gpio = chip->base; | 1012 | gpio = 0; |
| 1011 | while (gpio_desc[gpio].chip == chip) | 1013 | while (gpio < chip->ngpio) |
| 1012 | gpio_desc[gpio++].chip = NULL; | 1014 | chip->desc[gpio++].chip = NULL; |
| 1013 | spin_unlock_irqrestore(&gpio_lock, flags); | 1015 | spin_unlock_irqrestore(&gpio_lock, flags); |
| 1014 | 1016 | ||
| 1015 | pr_debug("%s: chip %s status %d\n", __func__, | 1017 | pr_debug("%s: chip %s status %d\n", __func__, |
| @@ -1186,8 +1188,11 @@ int gpiochip_add(struct gpio_chip *chip) | |||
| 1186 | status = gpiochip_add_to_list(chip); | 1188 | status = gpiochip_add_to_list(chip); |
| 1187 | 1189 | ||
| 1188 | if (status == 0) { | 1190 | if (status == 0) { |
| 1189 | for (id = base; id < base + chip->ngpio; id++) { | 1191 | chip->desc = &gpio_desc[chip->base]; |
| 1190 | gpio_desc[id].chip = chip; | 1192 | |
| 1193 | for (id = 0; id < chip->ngpio; id++) { | ||
| 1194 | struct gpio_desc *desc = &chip->desc[id]; | ||
| 1195 | desc->chip = chip; | ||
| 1191 | 1196 | ||
| 1192 | /* REVISIT: most hardware initializes GPIOs as | 1197 | /* REVISIT: most hardware initializes GPIOs as |
| 1193 | * inputs (often with pullups enabled) so power | 1198 | * inputs (often with pullups enabled) so power |
| @@ -1196,7 +1201,7 @@ int gpiochip_add(struct gpio_chip *chip) | |||
| 1196 | * and in case chip->get_direction is not set, | 1201 | * and in case chip->get_direction is not set, |
| 1197 | * we may expose the wrong direction in sysfs. | 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 | ? (1 << FLAG_IS_OUT) | 1205 | ? (1 << FLAG_IS_OUT) |
| 1201 | : 0; | 1206 | : 0; |
| 1202 | } | 1207 | } |
| @@ -1249,15 +1254,15 @@ int gpiochip_remove(struct gpio_chip *chip) | |||
| 1249 | gpiochip_remove_pin_ranges(chip); | 1254 | gpiochip_remove_pin_ranges(chip); |
| 1250 | of_gpiochip_remove(chip); | 1255 | of_gpiochip_remove(chip); |
| 1251 | 1256 | ||
| 1252 | for (id = chip->base; id < chip->base + chip->ngpio; id++) { | 1257 | for (id = 0; id < chip->ngpio; id++) { |
| 1253 | if (test_bit(FLAG_REQUESTED, &gpio_desc[id].flags)) { | 1258 | if (test_bit(FLAG_REQUESTED, &chip->desc[id].flags)) { |
| 1254 | status = -EBUSY; | 1259 | status = -EBUSY; |
| 1255 | break; | 1260 | break; |
| 1256 | } | 1261 | } |
| 1257 | } | 1262 | } |
| 1258 | if (status == 0) { | 1263 | if (status == 0) { |
| 1259 | for (id = chip->base; id < chip->base + chip->ngpio; id++) | 1264 | for (id = 0; id < chip->ngpio; id++) |
| 1260 | gpio_desc[id].chip = NULL; | 1265 | chip->desc[id].chip = NULL; |
| 1261 | 1266 | ||
| 1262 | list_del(&chip->list); | 1267 | list_del(&chip->list); |
| 1263 | } | 1268 | } |
| @@ -1582,11 +1587,13 @@ EXPORT_SYMBOL_GPL(gpio_free_array); | |||
| 1582 | */ | 1587 | */ |
| 1583 | const char *gpiochip_is_requested(struct gpio_chip *chip, unsigned offset) | 1588 | const char *gpiochip_is_requested(struct gpio_chip *chip, unsigned offset) |
| 1584 | { | 1589 | { |
| 1585 | unsigned gpio = chip->base + offset; | 1590 | struct gpio_desc *desc; |
| 1586 | struct gpio_desc *desc = &gpio_desc[gpio]; | ||
| 1587 | 1591 | ||
| 1588 | if (!gpio_is_valid(gpio) || desc->chip != chip) | 1592 | if (!GPIO_OFFSET_VALID(chip, offset)) |
| 1589 | return NULL; | 1593 | return NULL; |
| 1594 | |||
| 1595 | desc = &chip->desc[offset]; | ||
| 1596 | |||
| 1590 | if (test_bit(FLAG_REQUESTED, &desc->flags) == 0) | 1597 | if (test_bit(FLAG_REQUESTED, &desc->flags) == 0) |
| 1591 | return NULL; | 1598 | return NULL; |
| 1592 | #ifdef CONFIG_DEBUG_FS | 1599 | #ifdef CONFIG_DEBUG_FS |
| @@ -2025,7 +2032,7 @@ static void gpiolib_dbg_show(struct seq_file *s, struct gpio_chip *chip) | |||
| 2025 | { | 2032 | { |
| 2026 | unsigned i; | 2033 | unsigned i; |
| 2027 | unsigned gpio = chip->base; | 2034 | unsigned gpio = chip->base; |
| 2028 | struct gpio_desc *gdesc = &gpio_desc[gpio]; | 2035 | struct gpio_desc *gdesc = &chip->desc[0]; |
| 2029 | int is_out; | 2036 | int is_out; |
| 2030 | 2037 | ||
| 2031 | for (i = 0; i < chip->ngpio; i++, gpio++, gdesc++) { | 2038 | for (i = 0; i < chip->ngpio; i++, gpio++, gdesc++) { |
diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h index b562f95cdc2f..bde646995d10 100644 --- a/include/asm-generic/gpio.h +++ b/include/asm-generic/gpio.h | |||
| @@ -47,6 +47,7 @@ struct gpio; | |||
| 47 | struct seq_file; | 47 | struct seq_file; |
| 48 | struct module; | 48 | struct module; |
| 49 | struct device_node; | 49 | struct device_node; |
| 50 | struct gpio_desc; | ||
| 50 | 51 | ||
| 51 | /** | 52 | /** |
| 52 | * struct gpio_chip - abstract a GPIO controller | 53 | * struct gpio_chip - abstract a GPIO controller |
| @@ -76,6 +77,7 @@ struct device_node; | |||
| 76 | * negative during registration, requests dynamic ID allocation. | 77 | * negative during registration, requests dynamic ID allocation. |
| 77 | * @ngpio: the number of GPIOs handled by this controller; the last GPIO | 78 | * @ngpio: the number of GPIOs handled by this controller; the last GPIO |
| 78 | * handled is (base + ngpio - 1). | 79 | * handled is (base + ngpio - 1). |
| 80 | * @desc: array of ngpio descriptors. Private. | ||
| 79 | * @can_sleep: flag must be set iff get()/set() methods sleep, as they | 81 | * @can_sleep: flag must be set iff get()/set() methods sleep, as they |
| 80 | * must while accessing GPIO expander chips over I2C or SPI | 82 | * must while accessing GPIO expander chips over I2C or SPI |
| 81 | * @names: if set, must be an array of strings to use as alternative | 83 | * @names: if set, must be an array of strings to use as alternative |
| @@ -126,6 +128,7 @@ struct gpio_chip { | |||
| 126 | struct gpio_chip *chip); | 128 | struct gpio_chip *chip); |
| 127 | int base; | 129 | int base; |
| 128 | u16 ngpio; | 130 | u16 ngpio; |
| 131 | struct gpio_desc *desc; | ||
| 129 | const char *const *names; | 132 | const char *const *names; |
| 130 | unsigned can_sleep:1; | 133 | unsigned can_sleep:1; |
| 131 | unsigned exported:1; | 134 | unsigned exported:1; |
