diff options
Diffstat (limited to 'drivers/regulator/fixed.c')
-rw-r--r-- | drivers/regulator/fixed.c | 88 |
1 files changed, 86 insertions, 2 deletions
diff --git a/drivers/regulator/fixed.c b/drivers/regulator/fixed.c index 9c7f956d57c4..f8b295700d7d 100644 --- a/drivers/regulator/fixed.c +++ b/drivers/regulator/fixed.c | |||
@@ -5,6 +5,9 @@ | |||
5 | * | 5 | * |
6 | * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> | 6 | * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> |
7 | * | 7 | * |
8 | * Copyright (c) 2009 Nokia Corporation | ||
9 | * Roger Quadros <ext-roger.quadros@nokia.com> | ||
10 | * | ||
8 | * This program is free software; you can redistribute it and/or | 11 | * This program is free software; you can redistribute it and/or |
9 | * modify it under the terms of the GNU General Public License as | 12 | * modify it under the terms of the GNU General Public License as |
10 | * published by the Free Software Foundation; either version 2 of the | 13 | * published by the Free Software Foundation; either version 2 of the |
@@ -20,20 +23,45 @@ | |||
20 | #include <linux/platform_device.h> | 23 | #include <linux/platform_device.h> |
21 | #include <linux/regulator/driver.h> | 24 | #include <linux/regulator/driver.h> |
22 | #include <linux/regulator/fixed.h> | 25 | #include <linux/regulator/fixed.h> |
26 | #include <linux/gpio.h> | ||
23 | 27 | ||
24 | struct fixed_voltage_data { | 28 | struct fixed_voltage_data { |
25 | struct regulator_desc desc; | 29 | struct regulator_desc desc; |
26 | struct regulator_dev *dev; | 30 | struct regulator_dev *dev; |
27 | int microvolts; | 31 | int microvolts; |
32 | int gpio; | ||
33 | unsigned enable_high:1; | ||
34 | unsigned is_enabled:1; | ||
28 | }; | 35 | }; |
29 | 36 | ||
30 | static int fixed_voltage_is_enabled(struct regulator_dev *dev) | 37 | static int fixed_voltage_is_enabled(struct regulator_dev *dev) |
31 | { | 38 | { |
32 | return 1; | 39 | struct fixed_voltage_data *data = rdev_get_drvdata(dev); |
40 | |||
41 | return data->is_enabled; | ||
33 | } | 42 | } |
34 | 43 | ||
35 | static int fixed_voltage_enable(struct regulator_dev *dev) | 44 | static int fixed_voltage_enable(struct regulator_dev *dev) |
36 | { | 45 | { |
46 | struct fixed_voltage_data *data = rdev_get_drvdata(dev); | ||
47 | |||
48 | if (gpio_is_valid(data->gpio)) { | ||
49 | gpio_set_value_cansleep(data->gpio, data->enable_high); | ||
50 | data->is_enabled = 1; | ||
51 | } | ||
52 | |||
53 | return 0; | ||
54 | } | ||
55 | |||
56 | static int fixed_voltage_disable(struct regulator_dev *dev) | ||
57 | { | ||
58 | struct fixed_voltage_data *data = rdev_get_drvdata(dev); | ||
59 | |||
60 | if (gpio_is_valid(data->gpio)) { | ||
61 | gpio_set_value_cansleep(data->gpio, !data->enable_high); | ||
62 | data->is_enabled = 0; | ||
63 | } | ||
64 | |||
37 | return 0; | 65 | return 0; |
38 | } | 66 | } |
39 | 67 | ||
@@ -58,6 +86,7 @@ static int fixed_voltage_list_voltage(struct regulator_dev *dev, | |||
58 | static struct regulator_ops fixed_voltage_ops = { | 86 | static struct regulator_ops fixed_voltage_ops = { |
59 | .is_enabled = fixed_voltage_is_enabled, | 87 | .is_enabled = fixed_voltage_is_enabled, |
60 | .enable = fixed_voltage_enable, | 88 | .enable = fixed_voltage_enable, |
89 | .disable = fixed_voltage_disable, | ||
61 | .get_voltage = fixed_voltage_get_voltage, | 90 | .get_voltage = fixed_voltage_get_voltage, |
62 | .list_voltage = fixed_voltage_list_voltage, | 91 | .list_voltage = fixed_voltage_list_voltage, |
63 | }; | 92 | }; |
@@ -87,13 +116,62 @@ static int regulator_fixed_voltage_probe(struct platform_device *pdev) | |||
87 | drvdata->desc.n_voltages = 1; | 116 | drvdata->desc.n_voltages = 1; |
88 | 117 | ||
89 | drvdata->microvolts = config->microvolts; | 118 | drvdata->microvolts = config->microvolts; |
119 | drvdata->gpio = config->gpio; | ||
120 | |||
121 | if (gpio_is_valid(config->gpio)) { | ||
122 | drvdata->enable_high = config->enable_high; | ||
123 | |||
124 | /* FIXME: Remove below print warning | ||
125 | * | ||
126 | * config->gpio must be set to -EINVAL by platform code if | ||
127 | * GPIO control is not required. However, early adopters | ||
128 | * not requiring GPIO control may forget to initialize | ||
129 | * config->gpio to -EINVAL. This will cause GPIO 0 to be used | ||
130 | * for GPIO control. | ||
131 | * | ||
132 | * This warning will be removed once there are a couple of users | ||
133 | * for this driver. | ||
134 | */ | ||
135 | if (!config->gpio) | ||
136 | dev_warn(&pdev->dev, | ||
137 | "using GPIO 0 for regulator enable control\n"); | ||
138 | |||
139 | ret = gpio_request(config->gpio, config->supply_name); | ||
140 | if (ret) { | ||
141 | dev_err(&pdev->dev, | ||
142 | "Could not obtain regulator enable GPIO %d: %d\n", | ||
143 | config->gpio, ret); | ||
144 | goto err_name; | ||
145 | } | ||
146 | |||
147 | /* set output direction without changing state | ||
148 | * to prevent glitch | ||
149 | */ | ||
150 | drvdata->is_enabled = config->enabled_at_boot; | ||
151 | ret = drvdata->is_enabled ? | ||
152 | config->enable_high : !config->enable_high; | ||
153 | |||
154 | ret = gpio_direction_output(config->gpio, ret); | ||
155 | if (ret) { | ||
156 | dev_err(&pdev->dev, | ||
157 | "Could not configure regulator enable GPIO %d direction: %d\n", | ||
158 | config->gpio, ret); | ||
159 | goto err_gpio; | ||
160 | } | ||
161 | |||
162 | } else { | ||
163 | /* Regulator without GPIO control is considered | ||
164 | * always enabled | ||
165 | */ | ||
166 | drvdata->is_enabled = 1; | ||
167 | } | ||
90 | 168 | ||
91 | drvdata->dev = regulator_register(&drvdata->desc, &pdev->dev, | 169 | drvdata->dev = regulator_register(&drvdata->desc, &pdev->dev, |
92 | config->init_data, drvdata); | 170 | config->init_data, drvdata); |
93 | if (IS_ERR(drvdata->dev)) { | 171 | if (IS_ERR(drvdata->dev)) { |
94 | ret = PTR_ERR(drvdata->dev); | 172 | ret = PTR_ERR(drvdata->dev); |
95 | dev_err(&pdev->dev, "Failed to register regulator: %d\n", ret); | 173 | dev_err(&pdev->dev, "Failed to register regulator: %d\n", ret); |
96 | goto err_name; | 174 | goto err_gpio; |
97 | } | 175 | } |
98 | 176 | ||
99 | platform_set_drvdata(pdev, drvdata); | 177 | platform_set_drvdata(pdev, drvdata); |
@@ -103,6 +181,9 @@ static int regulator_fixed_voltage_probe(struct platform_device *pdev) | |||
103 | 181 | ||
104 | return 0; | 182 | return 0; |
105 | 183 | ||
184 | err_gpio: | ||
185 | if (gpio_is_valid(config->gpio)) | ||
186 | gpio_free(config->gpio); | ||
106 | err_name: | 187 | err_name: |
107 | kfree(drvdata->desc.name); | 188 | kfree(drvdata->desc.name); |
108 | err: | 189 | err: |
@@ -118,6 +199,9 @@ static int regulator_fixed_voltage_remove(struct platform_device *pdev) | |||
118 | kfree(drvdata->desc.name); | 199 | kfree(drvdata->desc.name); |
119 | kfree(drvdata); | 200 | kfree(drvdata); |
120 | 201 | ||
202 | if (gpio_is_valid(drvdata->gpio)) | ||
203 | gpio_free(drvdata->gpio); | ||
204 | |||
121 | return 0; | 205 | return 0; |
122 | } | 206 | } |
123 | 207 | ||