Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ARM: OMAP: I2C: tps65010 driver converts to gpiolib

Make the tps65010 driver use gpiolib to expose its GPIOs.

Note: This patch will get merged via omap tree instead of I2C
as it will cause some board updates. This has been discussed
at on the I2C list:

http://lists.lm-sensors.org/pipermail/i2c/2008-March/003031.html

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Cc: i2c@lm-sensors.org
Signed-off-by: Tony Lindgren <tony@atomide.com>


authored by

David Brownell and committed by
Tony Lindgren
79966fd9 ac37a0b0

+131 -1
+1
drivers/i2c/chips/Kconfig
··· 93 93 94 94 config TPS65010 95 95 tristate "TPS6501x Power Management chips" 96 + depends on HAVE_GPIO_LIB 96 97 default y if MACH_OMAP_H2 || MACH_OMAP_H3 || MACH_OMAP_OSK 97 98 help 98 99 If you say yes here you get support for the TPS6501x series of
+100 -1
drivers/i2c/chips/tps65010.c
··· 30 30 #include <linux/debugfs.h> 31 31 #include <linux/seq_file.h> 32 32 #include <linux/mutex.h> 33 + #include <linux/platform_device.h> 33 34 34 35 #include <linux/i2c/tps65010.h> 36 + 37 + #include <asm/gpio.h> 38 + 35 39 36 40 /*-------------------------------------------------------------------------*/ 37 41 ··· 88 84 u8 chgstatus, regstatus, chgconf; 89 85 u8 nmask1, nmask2; 90 86 91 - /* not currently tracking GPIO state */ 87 + u8 outmask; 88 + struct gpio_chip chip; 89 + struct platform_device *leds; 92 90 }; 93 91 94 92 #define POWER_POLL_DELAY msecs_to_jiffies(5000) ··· 455 449 456 450 /*-------------------------------------------------------------------------*/ 457 451 452 + /* offsets 0..3 == GPIO1..GPIO4 453 + * offsets 4..5 == LED1/nPG, LED2 (we set one of the non-BLINK modes) 454 + */ 455 + static void 456 + tps65010_gpio_set(struct gpio_chip *chip, unsigned offset, int value) 457 + { 458 + if (offset < 4) 459 + tps65010_set_gpio_out_value(offset + 1, value); 460 + else 461 + tps65010_set_led(offset - 3, value ? ON : OFF); 462 + } 463 + 464 + static int 465 + tps65010_output(struct gpio_chip *chip, unsigned offset, int value) 466 + { 467 + /* GPIOs may be input-only */ 468 + if (offset < 4) { 469 + struct tps65010 *tps; 470 + 471 + tps = container_of(chip, struct tps65010, chip); 472 + if (!(tps->outmask & (1 << offset))) 473 + return -EINVAL; 474 + tps65010_set_gpio_out_value(offset + 1, value); 475 + } else 476 + tps65010_set_led(offset - 3, value ? ON : OFF); 477 + 478 + return 0; 479 + } 480 + 481 + static int tps65010_gpio_get(struct gpio_chip *chip, unsigned offset) 482 + { 483 + int value; 484 + struct tps65010 *tps; 485 + 486 + tps = container_of(chip, struct tps65010, chip); 487 + 488 + if (offset < 4) { 489 + value = i2c_smbus_read_byte_data(tps->client, TPS_DEFGPIO); 490 + if (value < 0) 491 + return 0; 492 + if (value & (1 << (offset + 4))) /* output */ 493 + return !(value & (1 << offset)); 494 + else /* input */ 495 + return (value & (1 << offset)); 496 + } 497 + 498 + /* REVISIT we *could* report LED1/nPG and LED2 state ... */ 499 + return 0; 500 + } 501 + 502 + 503 + /*-------------------------------------------------------------------------*/ 504 + 458 505 static struct tps65010 *the_tps; 459 506 460 507 static int __exit tps65010_remove(struct i2c_client *client) 461 508 { 462 509 struct tps65010 *tps = i2c_get_clientdata(client); 510 + struct tps65010_board *board = client->dev.platform_data; 463 511 512 + if (board && board->teardown) { 513 + int status = board->teardown(client, board->context); 514 + if (status < 0) 515 + dev_dbg(&client->dev, "board %s %s err %d\n", 516 + "teardown", client->name, status); 517 + } 464 518 if (client->irq > 0) 465 519 free_irq(client->irq, tps); 466 520 cancel_delayed_work(&tps->work); ··· 535 469 { 536 470 struct tps65010 *tps; 537 471 int status; 472 + struct tps65010_board *board = client->dev.platform_data; 538 473 539 474 if (the_tps) { 540 475 dev_dbg(&client->dev, "only one tps6501x chip allowed\n"); ··· 644 577 645 578 tps->file = debugfs_create_file(DRIVER_NAME, S_IRUGO, NULL, 646 579 tps, DEBUG_FOPS); 580 + 581 + /* optionally register GPIOs */ 582 + if (board && board->base > 0) { 583 + tps->outmask = board->outmask; 584 + 585 + tps->chip.label = client->name; 586 + 587 + tps->chip.set = tps65010_gpio_set; 588 + tps->chip.direction_output = tps65010_output; 589 + 590 + /* NOTE: only partial support for inputs; nyet IRQs */ 591 + tps->chip.get = tps65010_gpio_get; 592 + 593 + tps->chip.base = board->base; 594 + tps->chip.ngpio = 6; 595 + tps->chip.can_sleep = 1; 596 + 597 + status = gpiochip_add(&tps->chip); 598 + if (status < 0) 599 + dev_err(&client->dev, "can't add gpiochip, err %d\n", 600 + status); 601 + else if (board->setup) { 602 + status = board->setup(client, board->context); 603 + if (status < 0) { 604 + dev_dbg(&client->dev, 605 + "board %s %s err %d\n", 606 + "setup", client->name, status); 607 + status = 0; 608 + } 609 + } 610 + } 611 + 647 612 return 0; 648 613 fail1: 649 614 kfree(tps);
+30
include/linux/i2c/tps65010.h
··· 152 152 */ 153 153 extern int tps65013_set_low_pwr(unsigned mode); 154 154 155 + 156 + struct i2c_client; 157 + 158 + /** 159 + * struct tps65010_board - packages GPIO and LED lines 160 + * @base: the GPIO number to assign to GPIO-1 161 + * @outmask: bit (N-1) is set to allow GPIO-N to be used as an 162 + * (open drain) output 163 + * @setup: optional callback issued once the GPIOs are valid 164 + * @teardown: optional callback issued before the GPIOs are invalidated 165 + * @context: optional parameter passed to setup() and teardown() 166 + * 167 + * Board data may be used to package the GPIO (and LED) lines for use 168 + * in by the generic GPIO and LED frameworks. The first four GPIOs 169 + * starting at gpio_base are GPIO1..GPIO4. The next two are LED1/nPG 170 + * and LED2 (with hardware blinking capability, not currently exposed). 171 + * 172 + * The @setup callback may be used with the kind of board-specific glue 173 + * which hands the (now-valid) GPIOs to other drivers, or which puts 174 + * devices in their initial states using these GPIOs. 175 + */ 176 + struct tps65010_board { 177 + int base; 178 + unsigned outmask; 179 + 180 + int (*setup)(struct i2c_client *client, void *context); 181 + int (*teardown)(struct i2c_client *client, void *context); 182 + void *context; 183 + }; 184 + 155 185 #endif /* __LINUX_I2C_TPS65010_H */ 156 186