aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKim, Milo <Milo.Kim@ti.com>2013-02-18 01:50:39 -0500
committerMark Brown <broonie@opensource.wolfsonmicro.com>2013-03-03 21:37:56 -0500
commitf19b00da8ed37db4e3891fe534fcf3a605a0e562 (patch)
tree9aae58c0afa589458a90345784b1c99d014e0fb0
parent6dbe51c251a327e012439c4772097a13df43c5b8 (diff)
regulator: core: support shared enable GPIO concept
A Regulator can be enabled by external GPIO pin. This is configurable in the regulator_config. At this moment, the GPIO can be owned by only one regulator device. In some devices, multiple regulators are enabled by shared one GPIO pin. This patch extends this limitation, enabling shared enable GPIO of regulators. New list for enable GPIO: 'regulator_ena_gpio_list' This manages enable GPIO list. New structure for supporting shared enable GPIO: 'regulator_enable_gpio' The enable count is used for balancing GPIO control count. This count is incremented when GPIO is enabled. On the other hand, it's decremented when GPIO is disabled. Reference count: 'request_count' The reference count, 'request_count' is incremented/decremented on requesting/freeing the GPIO. This count makes sure only free the GPIO when it has no users. How it works If the GPIO is already used, skip requesting new GPIO usage. The GPIO is new one, request GPIO function and add it to the list of enable GPIO. This list is used for balancing enable GPIO count and pin control. Updating a GPIO and invert code moved 'ena_gpio' and 'ena_gpio_invert' of the regulator_config were moved to new function, regulator_ena_gpio_request(). Use regulator_enable_pin structure rather than regulator_dev. Signed-off-by: Milo(Woogyom) Kim <milo.kim@ti.com> Reviewed-by: Axel Lin <axel.lin@ingics.com> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
-rw-r--r--drivers/regulator/core.c86
-rw-r--r--include/linux/regulator/driver.h2
2 files changed, 78 insertions, 10 deletions
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index da9782bd27d0..71d6adc4eeab 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -51,6 +51,7 @@
51static DEFINE_MUTEX(regulator_list_mutex); 51static DEFINE_MUTEX(regulator_list_mutex);
52static LIST_HEAD(regulator_list); 52static LIST_HEAD(regulator_list);
53static LIST_HEAD(regulator_map_list); 53static LIST_HEAD(regulator_map_list);
54static LIST_HEAD(regulator_ena_gpio_list);
54static bool has_full_constraints; 55static bool has_full_constraints;
55static bool board_wants_dummy_regulator; 56static bool board_wants_dummy_regulator;
56 57
@@ -69,6 +70,19 @@ struct regulator_map {
69}; 70};
70 71
71/* 72/*
73 * struct regulator_enable_gpio
74 *
75 * Management for shared enable GPIO pin
76 */
77struct regulator_enable_gpio {
78 struct list_head list;
79 int gpio;
80 u32 enable_count; /* a number of enabled shared GPIO */
81 u32 request_count; /* a number of requested shared GPIO */
82 unsigned int ena_gpio_invert:1;
83};
84
85/*
72 * struct regulator 86 * struct regulator
73 * 87 *
74 * One for each consumer device. 88 * One for each consumer device.
@@ -1456,6 +1470,65 @@ void devm_regulator_put(struct regulator *regulator)
1456} 1470}
1457EXPORT_SYMBOL_GPL(devm_regulator_put); 1471EXPORT_SYMBOL_GPL(devm_regulator_put);
1458 1472
1473/* Manage enable GPIO list. Same GPIO pin can be shared among regulators */
1474static int regulator_ena_gpio_request(struct regulator_dev *rdev,
1475 const struct regulator_config *config)
1476{
1477 struct regulator_enable_gpio *pin;
1478 int ret;
1479
1480 list_for_each_entry(pin, &regulator_ena_gpio_list, list) {
1481 if (pin->gpio == config->ena_gpio) {
1482 rdev_dbg(rdev, "GPIO %d is already used\n",
1483 config->ena_gpio);
1484 goto update_ena_gpio_to_rdev;
1485 }
1486 }
1487
1488 ret = gpio_request_one(config->ena_gpio,
1489 GPIOF_DIR_OUT | config->ena_gpio_flags,
1490 rdev_get_name(rdev));
1491 if (ret)
1492 return ret;
1493
1494 pin = kzalloc(sizeof(struct regulator_enable_gpio), GFP_KERNEL);
1495 if (pin == NULL) {
1496 gpio_free(config->ena_gpio);
1497 return -ENOMEM;
1498 }
1499
1500 pin->gpio = config->ena_gpio;
1501 pin->ena_gpio_invert = config->ena_gpio_invert;
1502 list_add(&pin->list, &regulator_ena_gpio_list);
1503
1504update_ena_gpio_to_rdev:
1505 pin->request_count++;
1506 rdev->ena_pin = pin;
1507 return 0;
1508}
1509
1510static void regulator_ena_gpio_free(struct regulator_dev *rdev)
1511{
1512 struct regulator_enable_gpio *pin, *n;
1513
1514 if (!rdev->ena_pin)
1515 return;
1516
1517 /* Free the GPIO only in case of no use */
1518 list_for_each_entry_safe(pin, n, &regulator_ena_gpio_list, list) {
1519 if (pin->gpio == rdev->ena_pin->gpio) {
1520 if (pin->request_count <= 1) {
1521 pin->request_count = 0;
1522 gpio_free(pin->gpio);
1523 list_del(&pin->list);
1524 kfree(pin);
1525 } else {
1526 pin->request_count--;
1527 }
1528 }
1529 }
1530}
1531
1459static int _regulator_do_enable(struct regulator_dev *rdev) 1532static int _regulator_do_enable(struct regulator_dev *rdev)
1460{ 1533{
1461 int ret, delay; 1534 int ret, delay;
@@ -3435,18 +3508,13 @@ regulator_register(const struct regulator_desc *regulator_desc,
3435 dev_set_drvdata(&rdev->dev, rdev); 3508 dev_set_drvdata(&rdev->dev, rdev);
3436 3509
3437 if (config->ena_gpio && gpio_is_valid(config->ena_gpio)) { 3510 if (config->ena_gpio && gpio_is_valid(config->ena_gpio)) {
3438 ret = gpio_request_one(config->ena_gpio, 3511 ret = regulator_ena_gpio_request(rdev, config);
3439 GPIOF_DIR_OUT | config->ena_gpio_flags,
3440 rdev_get_name(rdev));
3441 if (ret != 0) { 3512 if (ret != 0) {
3442 rdev_err(rdev, "Failed to request enable GPIO%d: %d\n", 3513 rdev_err(rdev, "Failed to request enable GPIO%d: %d\n",
3443 config->ena_gpio, ret); 3514 config->ena_gpio, ret);
3444 goto wash; 3515 goto wash;
3445 } 3516 }
3446 3517
3447 rdev->ena_gpio = config->ena_gpio;
3448 rdev->ena_gpio_invert = config->ena_gpio_invert;
3449
3450 if (config->ena_gpio_flags & GPIOF_OUT_INIT_HIGH) 3518 if (config->ena_gpio_flags & GPIOF_OUT_INIT_HIGH)
3451 rdev->ena_gpio_state = 1; 3519 rdev->ena_gpio_state = 1;
3452 3520
@@ -3522,8 +3590,7 @@ unset_supplies:
3522scrub: 3590scrub:
3523 if (rdev->supply) 3591 if (rdev->supply)
3524 _regulator_put(rdev->supply); 3592 _regulator_put(rdev->supply);
3525 if (rdev->ena_gpio) 3593 regulator_ena_gpio_free(rdev);
3526 gpio_free(rdev->ena_gpio);
3527 kfree(rdev->constraints); 3594 kfree(rdev->constraints);
3528wash: 3595wash:
3529 device_unregister(&rdev->dev); 3596 device_unregister(&rdev->dev);
@@ -3558,8 +3625,7 @@ void regulator_unregister(struct regulator_dev *rdev)
3558 unset_regulator_supplies(rdev); 3625 unset_regulator_supplies(rdev);
3559 list_del(&rdev->list); 3626 list_del(&rdev->list);
3560 kfree(rdev->constraints); 3627 kfree(rdev->constraints);
3561 if (rdev->ena_gpio) 3628 regulator_ena_gpio_free(rdev);
3562 gpio_free(rdev->ena_gpio);
3563 device_unregister(&rdev->dev); 3629 device_unregister(&rdev->dev);
3564 mutex_unlock(&regulator_list_mutex); 3630 mutex_unlock(&regulator_list_mutex);
3565} 3631}
diff --git a/include/linux/regulator/driver.h b/include/linux/regulator/driver.h
index 23070fd83872..a467d11dd67d 100644
--- a/include/linux/regulator/driver.h
+++ b/include/linux/regulator/driver.h
@@ -22,6 +22,7 @@
22struct regmap; 22struct regmap;
23struct regulator_dev; 23struct regulator_dev;
24struct regulator_init_data; 24struct regulator_init_data;
25struct regulator_enable_gpio;
25 26
26enum regulator_status { 27enum regulator_status {
27 REGULATOR_STATUS_OFF, 28 REGULATOR_STATUS_OFF,
@@ -300,6 +301,7 @@ struct regulator_dev {
300 301
301 struct dentry *debugfs; 302 struct dentry *debugfs;
302 303
304 struct regulator_enable_gpio *ena_pin;
303 int ena_gpio; 305 int ena_gpio;
304 unsigned int ena_gpio_invert:1; 306 unsigned int ena_gpio_invert:1;
305 unsigned int ena_gpio_state:1; 307 unsigned int ena_gpio_state:1;