diff options
| -rw-r--r-- | Documentation/gpio.txt | 64 | ||||
| -rw-r--r-- | drivers/gpio/gpiolib.c | 58 | ||||
| -rw-r--r-- | include/asm-generic/gpio.h | 26 |
3 files changed, 148 insertions, 0 deletions
diff --git a/Documentation/gpio.txt b/Documentation/gpio.txt index 1866c27eec69..c2c6e9b39bbe 100644 --- a/Documentation/gpio.txt +++ b/Documentation/gpio.txt | |||
| @@ -253,6 +253,70 @@ pin setup (e.g. controlling which pin the GPIO uses, pullup/pulldown). | |||
| 253 | Also note that it's your responsibility to have stopped using a GPIO | 253 | Also note that it's your responsibility to have stopped using a GPIO |
| 254 | before you free it. | 254 | before you free it. |
| 255 | 255 | ||
| 256 | Considering in most cases GPIOs are actually configured right after they | ||
| 257 | are claimed, three additional calls are defined: | ||
| 258 | |||
| 259 | /* request a single GPIO, with initial configuration specified by | ||
| 260 | * 'flags', identical to gpio_request() wrt other arguments and | ||
| 261 | * return value | ||
| 262 | */ | ||
| 263 | int gpio_request_one(unsigned gpio, unsigned long flags, const char *label); | ||
| 264 | |||
| 265 | /* request multiple GPIOs in a single call | ||
| 266 | */ | ||
| 267 | int gpio_request_array(struct gpio *array, size_t num); | ||
| 268 | |||
| 269 | /* release multiple GPIOs in a single call | ||
| 270 | */ | ||
| 271 | void gpio_free_array(struct gpio *array, size_t num); | ||
| 272 | |||
| 273 | where 'flags' is currently defined to specify the following properties: | ||
| 274 | |||
| 275 | * GPIOF_DIR_IN - to configure direction as input | ||
| 276 | * GPIOF_DIR_OUT - to configure direction as output | ||
| 277 | |||
| 278 | * GPIOF_INIT_LOW - as output, set initial level to LOW | ||
| 279 | * GPIOF_INIT_HIGH - as output, set initial level to HIGH | ||
| 280 | |||
| 281 | since GPIOF_INIT_* are only valid when configured as output, so group valid | ||
| 282 | combinations as: | ||
| 283 | |||
| 284 | * GPIOF_IN - configure as input | ||
| 285 | * GPIOF_OUT_INIT_LOW - configured as output, initial level LOW | ||
| 286 | * GPIOF_OUT_INIT_HIGH - configured as output, initial level HIGH | ||
| 287 | |||
| 288 | In the future, these flags can be extended to support more properties such | ||
| 289 | as open-drain status. | ||
| 290 | |||
| 291 | Further more, to ease the claim/release of multiple GPIOs, 'struct gpio' is | ||
| 292 | introduced to encapsulate all three fields as: | ||
| 293 | |||
| 294 | struct gpio { | ||
| 295 | unsigned gpio; | ||
| 296 | unsigned long flags; | ||
| 297 | const char *label; | ||
| 298 | }; | ||
| 299 | |||
| 300 | A typical example of usage: | ||
| 301 | |||
| 302 | static struct gpio leds_gpios[] = { | ||
| 303 | { 32, GPIOF_OUT_INIT_HIGH, "Power LED" }, /* default to ON */ | ||
| 304 | { 33, GPIOF_OUT_INIT_LOW, "Green LED" }, /* default to OFF */ | ||
| 305 | { 34, GPIOF_OUT_INIT_LOW, "Red LED" }, /* default to OFF */ | ||
| 306 | { 35, GPIOF_OUT_INIT_LOW, "Blue LED" }, /* default to OFF */ | ||
| 307 | { ... }, | ||
| 308 | }; | ||
| 309 | |||
| 310 | err = gpio_request_one(31, GPIOF_IN, "Reset Button"); | ||
| 311 | if (err) | ||
| 312 | ... | ||
| 313 | |||
| 314 | err = gpio_request_array(leds_gpios, ARRAY_SIZE(leds_gpios)); | ||
| 315 | if (err) | ||
| 316 | ... | ||
| 317 | |||
| 318 | gpio_free_array(leds_gpios, ARRAY_SIZE(leds_gpios)); | ||
| 319 | |||
| 256 | 320 | ||
| 257 | GPIOs mapped to IRQs | 321 | GPIOs mapped to IRQs |
| 258 | -------------------- | 322 | -------------------- |
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 350842ad3632..9006fdb26fea 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c | |||
| @@ -1237,6 +1237,64 @@ void gpio_free(unsigned gpio) | |||
| 1237 | } | 1237 | } |
| 1238 | EXPORT_SYMBOL_GPL(gpio_free); | 1238 | EXPORT_SYMBOL_GPL(gpio_free); |
| 1239 | 1239 | ||
| 1240 | /** | ||
| 1241 | * gpio_request_one - request a single GPIO with initial configuration | ||
| 1242 | * @gpio: the GPIO number | ||
| 1243 | * @flags: GPIO configuration as specified by GPIOF_* | ||
| 1244 | * @label: a literal description string of this GPIO | ||
| 1245 | */ | ||
| 1246 | int gpio_request_one(unsigned gpio, unsigned long flags, const char *label) | ||
| 1247 | { | ||
| 1248 | int err; | ||
| 1249 | |||
| 1250 | err = gpio_request(gpio, label); | ||
| 1251 | if (err) | ||
| 1252 | return err; | ||
| 1253 | |||
| 1254 | if (flags & GPIOF_DIR_IN) | ||
| 1255 | err = gpio_direction_input(gpio); | ||
| 1256 | else | ||
| 1257 | err = gpio_direction_output(gpio, | ||
| 1258 | (flags & GPIOF_INIT_HIGH) ? 1 : 0); | ||
| 1259 | |||
| 1260 | return err; | ||
| 1261 | } | ||
| 1262 | EXPORT_SYMBOL_GPL(gpio_request_one); | ||
| 1263 | |||
| 1264 | /** | ||
| 1265 | * gpio_request_array - request multiple GPIOs in a single call | ||
| 1266 | * @array: array of the 'struct gpio' | ||
| 1267 | * @num: how many GPIOs in the array | ||
| 1268 | */ | ||
| 1269 | int gpio_request_array(struct gpio *array, size_t num) | ||
| 1270 | { | ||
| 1271 | int i, err; | ||
| 1272 | |||
| 1273 | for (i = 0; i < num; i++, array++) { | ||
| 1274 | err = gpio_request_one(array->gpio, array->flags, array->label); | ||
| 1275 | if (err) | ||
| 1276 | goto err_free; | ||
| 1277 | } | ||
| 1278 | return 0; | ||
| 1279 | |||
| 1280 | err_free: | ||
| 1281 | while (i--) | ||
| 1282 | gpio_free((--array)->gpio); | ||
| 1283 | return err; | ||
| 1284 | } | ||
| 1285 | EXPORT_SYMBOL_GPL(gpio_request_array); | ||
| 1286 | |||
| 1287 | /** | ||
| 1288 | * gpio_free_array - release multiple GPIOs in a single call | ||
| 1289 | * @array: array of the 'struct gpio' | ||
| 1290 | * @num: how many GPIOs in the array | ||
| 1291 | */ | ||
| 1292 | void gpio_free_array(struct gpio *array, size_t num) | ||
| 1293 | { | ||
| 1294 | while (num--) | ||
| 1295 | gpio_free((array++)->gpio); | ||
| 1296 | } | ||
| 1297 | EXPORT_SYMBOL_GPL(gpio_free_array); | ||
| 1240 | 1298 | ||
| 1241 | /** | 1299 | /** |
| 1242 | * gpiochip_is_requested - return string iff signal was requested | 1300 | * gpiochip_is_requested - return string iff signal was requested |
diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h index 485eeb6c4ef3..979c6a57f2f1 100644 --- a/include/asm-generic/gpio.h +++ b/include/asm-generic/gpio.h | |||
| @@ -136,6 +136,32 @@ extern int __gpio_cansleep(unsigned gpio); | |||
| 136 | 136 | ||
| 137 | extern int __gpio_to_irq(unsigned gpio); | 137 | extern int __gpio_to_irq(unsigned gpio); |
| 138 | 138 | ||
| 139 | #define GPIOF_DIR_OUT (0 << 0) | ||
| 140 | #define GPIOF_DIR_IN (1 << 0) | ||
| 141 | |||
| 142 | #define GPIOF_INIT_LOW (0 << 1) | ||
| 143 | #define GPIOF_INIT_HIGH (1 << 1) | ||
| 144 | |||
| 145 | #define GPIOF_IN (GPIOF_DIR_IN) | ||
| 146 | #define GPIOF_OUT_INIT_LOW (GPIOF_DIR_OUT | GPIOF_INIT_LOW) | ||
| 147 | #define GPIOF_OUT_INIT_HIGH (GPIOF_DIR_OUT | GPIOF_INIT_HIGH) | ||
| 148 | |||
| 149 | /** | ||
| 150 | * struct gpio - a structure describing a GPIO with configuration | ||
| 151 | * @gpio: the GPIO number | ||
| 152 | * @flags: GPIO configuration as specified by GPIOF_* | ||
| 153 | * @label: a literal description string of this GPIO | ||
| 154 | */ | ||
| 155 | struct gpio { | ||
| 156 | unsigned gpio; | ||
| 157 | unsigned long flags; | ||
| 158 | const char *label; | ||
| 159 | }; | ||
| 160 | |||
| 161 | extern int gpio_request_one(unsigned gpio, unsigned long flags, const char *label); | ||
| 162 | extern int gpio_request_array(struct gpio *array, size_t num); | ||
| 163 | extern void gpio_free_array(struct gpio *array, size_t num); | ||
| 164 | |||
| 139 | #ifdef CONFIG_GPIO_SYSFS | 165 | #ifdef CONFIG_GPIO_SYSFS |
| 140 | 166 | ||
| 141 | /* | 167 | /* |
