static DEFINE_MUTEX(regulator_list_mutex);
static LIST_HEAD(regulator_list);
static LIST_HEAD(regulator_map_list);
+static LIST_HEAD(regulator_ena_gpio_list);
static bool has_full_constraints;
static bool board_wants_dummy_regulator;
struct regulator_dev *regulator;
};
+/*
+ * struct regulator_enable_gpio
+ *
+ * Management for shared enable GPIO pin
+ */
+struct regulator_enable_gpio {
+ struct list_head list;
+ int gpio;
+ u32 enable_count; /* a number of enabled shared GPIO */
+ u32 request_count; /* a number of requested shared GPIO */
+ unsigned int ena_gpio_invert:1;
+};
+
/*
* struct regulator
*
}
EXPORT_SYMBOL_GPL(devm_regulator_put);
+/* Manage enable GPIO list. Same GPIO pin can be shared among regulators */
+static int regulator_ena_gpio_request(struct regulator_dev *rdev,
+ const struct regulator_config *config)
+{
+ struct regulator_enable_gpio *pin;
+ int ret;
+
+ list_for_each_entry(pin, ®ulator_ena_gpio_list, list) {
+ if (pin->gpio == config->ena_gpio) {
+ rdev_dbg(rdev, "GPIO %d is already used\n",
+ config->ena_gpio);
+ goto update_ena_gpio_to_rdev;
+ }
+ }
+
+ ret = gpio_request_one(config->ena_gpio,
+ GPIOF_DIR_OUT | config->ena_gpio_flags,
+ rdev_get_name(rdev));
+ if (ret)
+ return ret;
+
+ pin = kzalloc(sizeof(struct regulator_enable_gpio), GFP_KERNEL);
+ if (pin == NULL) {
+ gpio_free(config->ena_gpio);
+ return -ENOMEM;
+ }
+
+ pin->gpio = config->ena_gpio;
+ pin->ena_gpio_invert = config->ena_gpio_invert;
+ list_add(&pin->list, ®ulator_ena_gpio_list);
+
+update_ena_gpio_to_rdev:
+ pin->request_count++;
+ rdev->ena_pin = pin;
+ return 0;
+}
+
+static void regulator_ena_gpio_free(struct regulator_dev *rdev)
+{
+ struct regulator_enable_gpio *pin, *n;
+
+ if (!rdev->ena_pin)
+ return;
+
+ /* Free the GPIO only in case of no use */
+ list_for_each_entry_safe(pin, n, ®ulator_ena_gpio_list, list) {
+ if (pin->gpio == rdev->ena_pin->gpio) {
+ if (pin->request_count <= 1) {
+ pin->request_count = 0;
+ gpio_free(pin->gpio);
+ list_del(&pin->list);
+ kfree(pin);
+ } else {
+ pin->request_count--;
+ }
+ }
+ }
+}
+
static int _regulator_do_enable(struct regulator_dev *rdev)
{
int ret, delay;
dev_set_drvdata(&rdev->dev, rdev);
if (config->ena_gpio && gpio_is_valid(config->ena_gpio)) {
- ret = gpio_request_one(config->ena_gpio,
- GPIOF_DIR_OUT | config->ena_gpio_flags,
- rdev_get_name(rdev));
+ ret = regulator_ena_gpio_request(rdev, config);
if (ret != 0) {
rdev_err(rdev, "Failed to request enable GPIO%d: %d\n",
config->ena_gpio, ret);
goto wash;
}
- rdev->ena_gpio = config->ena_gpio;
- rdev->ena_gpio_invert = config->ena_gpio_invert;
-
if (config->ena_gpio_flags & GPIOF_OUT_INIT_HIGH)
rdev->ena_gpio_state = 1;
scrub:
if (rdev->supply)
_regulator_put(rdev->supply);
- if (rdev->ena_gpio)
- gpio_free(rdev->ena_gpio);
+ regulator_ena_gpio_free(rdev);
kfree(rdev->constraints);
wash:
device_unregister(&rdev->dev);
unset_regulator_supplies(rdev);
list_del(&rdev->list);
kfree(rdev->constraints);
- if (rdev->ena_gpio)
- gpio_free(rdev->ena_gpio);
+ regulator_ena_gpio_free(rdev);
device_unregister(&rdev->dev);
mutex_unlock(®ulator_list_mutex);
}