diff options
| -rw-r--r-- | drivers/regulator/core.c | 86 | ||||
| -rw-r--r-- | include/linux/regulator/driver.h | 2 |
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 @@ | |||
| 51 | static DEFINE_MUTEX(regulator_list_mutex); | 51 | static DEFINE_MUTEX(regulator_list_mutex); |
| 52 | static LIST_HEAD(regulator_list); | 52 | static LIST_HEAD(regulator_list); |
| 53 | static LIST_HEAD(regulator_map_list); | 53 | static LIST_HEAD(regulator_map_list); |
| 54 | static LIST_HEAD(regulator_ena_gpio_list); | ||
| 54 | static bool has_full_constraints; | 55 | static bool has_full_constraints; |
| 55 | static bool board_wants_dummy_regulator; | 56 | static 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 | */ | ||
| 77 | struct 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 | } |
| 1457 | EXPORT_SYMBOL_GPL(devm_regulator_put); | 1471 | EXPORT_SYMBOL_GPL(devm_regulator_put); |
| 1458 | 1472 | ||
| 1473 | /* Manage enable GPIO list. Same GPIO pin can be shared among regulators */ | ||
| 1474 | static 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, ®ulator_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, ®ulator_ena_gpio_list); | ||
| 1503 | |||
| 1504 | update_ena_gpio_to_rdev: | ||
| 1505 | pin->request_count++; | ||
| 1506 | rdev->ena_pin = pin; | ||
| 1507 | return 0; | ||
| 1508 | } | ||
| 1509 | |||
| 1510 | static 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, ®ulator_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 | |||
| 1459 | static int _regulator_do_enable(struct regulator_dev *rdev) | 1532 | static 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: | |||
| 3522 | scrub: | 3590 | scrub: |
| 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); |
| 3528 | wash: | 3595 | wash: |
| 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(®ulator_list_mutex); | 3630 | mutex_unlock(®ulator_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 @@ | |||
| 22 | struct regmap; | 22 | struct regmap; |
| 23 | struct regulator_dev; | 23 | struct regulator_dev; |
| 24 | struct regulator_init_data; | 24 | struct regulator_init_data; |
| 25 | struct regulator_enable_gpio; | ||
| 25 | 26 | ||
| 26 | enum regulator_status { | 27 | enum 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; |
