summaryrefslogtreecommitdiff
path: root/drivers/regulator/gpio-switch-regulator.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/regulator/gpio-switch-regulator.c')
-rw-r--r--drivers/regulator/gpio-switch-regulator.c412
1 files changed, 0 insertions, 412 deletions
diff --git a/drivers/regulator/gpio-switch-regulator.c b/drivers/regulator/gpio-switch-regulator.c
deleted file mode 100644
index 55dd63675a06..000000000000
--- a/drivers/regulator/gpio-switch-regulator.c
+++ /dev/null
@@ -1,412 +0,0 @@
-/*
- * driver/regulator/gpio-switch-regulator.c
- * GPIO based switch regulator to enable/disable power rails.
- *
- * Copyright (c) 2011, NVIDIA Corporation.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-/*#define DEBUG 1*/
-/*#define VERBOSE_DEBUG 1*/
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/err.h>
-#include <linux/slab.h>
-#include <linux/platform_device.h>
-#include <linux/regulator/driver.h>
-#include <linux/regulator/machine.h>
-#include <linux/gpio.h>
-#include <linux/regulator/gpio-switch-regulator.h>
-
-struct gpio_switch_regulator {
- struct regulator_desc reg_desc;
- struct regulator_init_data reg_init_data;
- struct regulator *input_regulator;
- struct regulator_dev *rdev;
- struct device *dev;
- int gpio_nr;
- int pin_group;
- bool is_gpio_init;
- bool is_enable;
- bool active_low;
- bool is_init_success;
- int *voltages;
- unsigned curr_vol_sel;
- struct gpio_switch_regulator_subdev_data *psubdev_data;
- int (*enable_rail)(struct gpio_switch_regulator_subdev_data *sdata);
- int (*disable_rail)(struct gpio_switch_regulator_subdev_data *sdata);
-};
-
-static int _gpio_regulator_enable(struct device *dev,
- struct gpio_switch_regulator *ri)
-{
- int init_val;
- int ret;
-
- if (ri->enable_rail) {
- ret = ri->enable_rail(ri->psubdev_data);
- if (ret < 0)
- dev_err(dev, "Unable to enable rail through board api"
- " error %d\n", ret);
- } else {
- init_val = (ri->active_low) ? 0 : 1;
- ret = gpio_direction_output(ri->gpio_nr, init_val);
- if (ret < 0)
- dev_err(dev, "Unable to set direction %d\n",
- ri->gpio_nr);
- }
- return ret;
-}
-
-static int _gpio_regulator_disable(struct device *dev,
- struct gpio_switch_regulator *ri)
-{
- int init_val;
- int ret;
-
- if (ri->disable_rail) {
- ret = ri->disable_rail(ri->psubdev_data);
- if (ret < 0)
- dev_err(dev, "Unable to disable rail through "
- "board api %d\n", ret);
- } else {
- init_val = (ri->active_low) ? 1 : 0;
- ret = gpio_direction_output(ri->gpio_nr, init_val);
- if (ret < 0)
- dev_err(dev, "Unable to set direction %d\n",
- ri->gpio_nr);
- }
- return ret;
-}
-
-static int gpio_switch_list_voltage(struct regulator_dev *rdev,
- unsigned selector)
-{
- struct gpio_switch_regulator *ri = rdev_get_drvdata(rdev);
-
- if (selector < ri->reg_desc.n_voltages)
- return ri->voltages[selector] * 1000;
- else
- return 0;
-}
-
-static int gpio_switch_set_voltage(struct regulator_dev *rdev,
- int min_uV, int max_uV, unsigned *selector)
-{
- struct gpio_switch_regulator *ri = rdev_get_drvdata(rdev);
- int uV;
- bool found = false;
- unsigned val;
-
- for (val = 0; val < ri->reg_desc.n_voltages; val++) {
- uV = ri->voltages[val] * 1000;
- if (min_uV <= uV && uV <= max_uV) {
- found = true;
- *selector = ri->curr_vol_sel = val;
- break;
- }
- }
- if (found && ri->input_regulator)
- return regulator_set_voltage(ri->input_regulator, min_uV,
- max_uV);
- ri->curr_vol_sel = 0;
- return -EINVAL;
-}
-
-static int gpio_switch_get_voltage(struct regulator_dev *rdev)
-{
- struct gpio_switch_regulator *ri = rdev_get_drvdata(rdev);
- if (ri->input_regulator)
- return regulator_get_voltage(ri->input_regulator);
-
- if (ri->curr_vol_sel < ri->reg_desc.n_voltages)
- return ri->voltages[ri->curr_vol_sel] * 1000;
- return 0;
-}
-
-static int gpio_switch_regulator_enable(struct regulator_dev *rdev)
-{
- struct gpio_switch_regulator *ri = rdev_get_drvdata(rdev);
- int ret = 0;
- if (ri->is_enable)
- return 0;
-
- if (ri->input_regulator) {
- ret = regulator_enable(ri->input_regulator);
- if (ret < 0) {
- dev_err(&rdev->dev, "%s:Failed to enable regulator"
- " Error %d\n", __func__, ret);
- return ret;
- }
- }
-
- ret = _gpio_regulator_enable(&rdev->dev, ri);
- if (ret < 0)
- return ret;
- ri->is_enable = true;
- return 0;
-}
-
-static int gpio_switch_regulator_disable(struct regulator_dev *rdev)
-{
- struct gpio_switch_regulator *ri = rdev_get_drvdata(rdev);
- int ret = 0;
-
- if (!ri->is_enable)
- return 0;
-
- ret = _gpio_regulator_disable(&rdev->dev, ri);
- if (ret < 0)
- return ret;
-
- if (ri->input_regulator) {
- ret = regulator_disable(ri->input_regulator);
- if (ret < 0) {
- dev_err(&rdev->dev, "%s:Failed to disable regulator"
- " Error %d\n", __func__, ret);
- return ret;
- }
- }
-
- ri->is_enable = false;
- return 0;
-}
-
-static int gpio_switch_regulator_is_enabled(struct regulator_dev *rdev)
-{
- struct gpio_switch_regulator *ri = rdev_get_drvdata(rdev);
- int ret = 0;
- if (ri->input_regulator) {
- ret = regulator_is_enabled(ri->input_regulator);
- if (!ret)
- return ret;
- }
- return (ri->is_enable) ? 1 : 0;
-}
-
-static struct regulator_ops gpio_switch_regulator_ops = {
- .list_voltage = gpio_switch_list_voltage,
- .get_voltage = gpio_switch_get_voltage,
- .set_voltage = gpio_switch_set_voltage,
- .is_enabled = gpio_switch_regulator_is_enabled,
- .enable = gpio_switch_regulator_enable,
- .disable = gpio_switch_regulator_disable,
-};
-
-static int __devinit gpio_switch_regulator_probe(struct platform_device *pdev)
-{
- struct gpio_switch_regulator *ri = NULL;
- struct gpio_switch_regulator *gswitch_reg = NULL;
- struct gpio_switch_regulator_platform_data *pdata;
- struct gpio_switch_regulator_subdev_data *sdata = NULL;
- int id = pdev->id;
- int ret = 0;
- int rcount;
-
- dev_dbg(&pdev->dev, "Probing regulator %d\n", id);
-
- pdata = pdev->dev.platform_data;
- if (!pdata) {
- dev_err(&pdev->dev, "%s:No platform data Exiting\n", __func__);
- return -ENODEV;
- }
-
- BUG_ON(!pdata->num_subdevs);
-
- gswitch_reg = kzalloc(sizeof(struct gpio_switch_regulator) *
- pdata->num_subdevs, GFP_KERNEL);
- if (!gswitch_reg) {
- dev_err(&pdev->dev, "%s:Failed to allocate memory\n", __func__);
- return -ENOMEM;
- }
-
- for (rcount = 0; rcount < pdata->num_subdevs; ++rcount) {
- ri = &gswitch_reg[rcount];
- sdata = pdata->subdevs[rcount];
-
- /* Initialize the regulator parameter */
- ri->reg_desc.name = sdata->regulator_name;
- ri->reg_desc.ops = &gpio_switch_regulator_ops;
- ri->reg_desc.type = REGULATOR_VOLTAGE;
- ri->reg_desc.id = sdata->id;
- ri->reg_desc.n_voltages = sdata->n_voltages;
- ri->reg_desc.owner = THIS_MODULE;
- ri->is_init_success = false;
-
- memcpy(&ri->reg_init_data.constraints, &sdata->constraints,
- sizeof(struct regulation_constraints));
-
- /* Initialize min and maximum contraint voltage if it is not
- * define in platform device */
- if (!sdata->constraints.min_uV)
- ri->reg_init_data.constraints.min_uV = 1000 *
- sdata->voltages[0];
-
- if (!sdata->constraints.max_uV)
- ri->reg_init_data.constraints.max_uV = 1000 *
- sdata->voltages[sdata->n_voltages - 1];
-
- ri->reg_init_data.num_consumer_supplies =
- sdata->num_consumer_supplies;
- ri->reg_init_data.consumer_supplies = sdata->consumer_supplies;
-
- ri->input_regulator = NULL;
- ri->is_gpio_init = false;
- ri->is_enable = (sdata->init_state) ? true : false;
- ri->voltages = sdata->voltages;
- ri->psubdev_data = sdata;
- ri->gpio_nr = sdata->gpio_nr;
- ri->active_low = sdata->active_low;
- ri->dev = &pdev->dev;
- ri->enable_rail = sdata->enable_rail;
- ri->disable_rail = sdata->disable_rail;
- ri->pin_group = sdata->pin_group;
-
- /* Checking for board APIs enable/disable rail */
- if (ri->enable_rail || ri->disable_rail)
- BUG_ON(!(ri->enable_rail && ri->disable_rail));
-
- /* Get the regulator structure if input supply is available */
- if (sdata->input_supply) {
- ri->input_regulator = regulator_get(NULL,
- sdata->input_supply);
- if (IS_ERR_OR_NULL(ri->input_regulator)) {
- dev_err(&pdev->dev, "Unable to get regu"
- "lator %s\n", sdata->input_supply);
- ret = -ENODEV;
- goto reg_get_fail;
- }
- if (ri->is_enable) {
- ret = regulator_enable(ri->input_regulator);
- if (ret < 0) {
- dev_err(&pdev->dev, "Unable to enable "
- "regulator %s\n",
- sdata->input_supply);
- goto reg_en_fail;
- }
- }
- }
-
- /* Initialize gpios */
- ret = gpio_request(ri->gpio_nr, sdata->regulator_name);
- if (ret < 0) {
- dev_err(&pdev->dev, "Unable to request gpio %d\n",
- ri->gpio_nr);
- goto gpio_req_fail;
- }
-
- if (ri->is_enable)
- ret = _gpio_regulator_enable(&pdev->dev, ri);
- else
- ret = _gpio_regulator_disable(&pdev->dev, ri);
- if (ret < 0)
- goto reg_cont_fail;
-
- ri->is_gpio_init = true;
-
- ri->rdev = regulator_register(&ri->reg_desc, &pdev->dev,
- &ri->reg_init_data, ri);
- if (IS_ERR_OR_NULL(ri->rdev)) {
- dev_err(&pdev->dev, "Failed to register regulator %s\n",
- ri->reg_desc.name);
- ret = PTR_ERR(ri->rdev);
- goto reg_reg_fail;
- }
-
- /* If everything success then continue for next registration */
- ri->is_init_success = true;
- continue;
-
- /* Cleanup the current registration and continue for next
- * registration*/
-reg_reg_fail:
- if (ri->is_enable)
- _gpio_regulator_disable(&pdev->dev, ri);
-reg_cont_fail:
- gpio_free(ri->gpio_nr);
-gpio_req_fail:
- if (ri->is_enable && ri->input_regulator)
- regulator_disable(ri->input_regulator);
-reg_en_fail:
- if (ri->input_regulator) {
- regulator_put(ri->input_regulator);
- ri->input_regulator = NULL;
- }
-reg_get_fail:
- dev_err(&pdev->dev, "Unable to register regulator %s\n",
- sdata->regulator_name);
- }
-
- platform_set_drvdata(pdev, gswitch_reg);
- return 0;
-}
-
-static int __devexit gpio_switch_regulator_remove(struct platform_device *pdev)
-{
- struct gpio_switch_regulator *ri = NULL;
- struct gpio_switch_regulator *gswitch_reg = platform_get_drvdata(pdev);
- int i;
- struct gpio_switch_regulator_platform_data *pdata;
-
- pdata = pdev->dev.platform_data;
-
- /* Unregister devices in reverse order */
- for (i = pdata->num_subdevs; i; --i) {
- ri = &gswitch_reg[i - 1];
- /* If registration was not success, then do not release */
- if (!ri->is_init_success)
- continue;
-
- if (ri->is_enable)
- _gpio_regulator_disable(&pdev->dev, ri);
-
- if (ri->input_regulator) {
- if (ri->is_enable)
- regulator_disable(ri->input_regulator);
- regulator_put(ri->input_regulator);
- }
-
- regulator_unregister(ri->rdev);
- gpio_free(ri->gpio_nr);
- }
-
- kfree(gswitch_reg);
- platform_set_drvdata(pdev, NULL);
- return 0;
-}
-
-static struct platform_driver gpio_switch_regulator_driver = {
- .driver = {
- .name = "gpio-switch-regulator",
- .owner = THIS_MODULE,
- },
- .probe = gpio_switch_regulator_probe,
- .remove = __devexit_p(gpio_switch_regulator_remove),
-};
-
-static int __init gpio_switch_regulator_init(void)
-{
- return platform_driver_register(&gpio_switch_regulator_driver);
-}
-
-static void __exit gpio_switch_regulator_exit(void)
-{
- platform_driver_unregister(&gpio_switch_regulator_driver);
-}
-
-subsys_initcall_sync(gpio_switch_regulator_init);
-module_exit(gpio_switch_regulator_exit);