aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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;