diff options
author | Heiko Stübner <heiko@sntech.de> | 2011-12-19 13:42:19 -0500 |
---|---|---|
committer | Felipe Balbi <balbi@ti.com> | 2011-12-21 06:24:40 -0500 |
commit | bab7d037c84f74449a510841ad03707f7e6609a5 (patch) | |
tree | 321fdd951388e7192efc0d35cec18aa5de21db17 /drivers/usb/gadget/s3c-hsudc.c | |
parent | d93e2600d80fc41ccf339b4a2843a3007d479907 (diff) |
usb: gadget: s3c-hsudc: Add regulator handling
The udc has three supplies: vdda (3.3V), vddi (1.2V) and vddosc (1.8-3.3V).
Turn these on and off on start and stop calls.
Signed-off-by: Heiko Stuebner <heiko@sntech.de>
Reviewed-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Signed-off-by: Felipe Balbi <balbi@ti.com>
Diffstat (limited to 'drivers/usb/gadget/s3c-hsudc.c')
-rw-r--r-- | drivers/usb/gadget/s3c-hsudc.c | 41 |
1 files changed, 37 insertions, 4 deletions
diff --git a/drivers/usb/gadget/s3c-hsudc.c b/drivers/usb/gadget/s3c-hsudc.c index 1de955082abc..94f48f66f590 100644 --- a/drivers/usb/gadget/s3c-hsudc.c +++ b/drivers/usb/gadget/s3c-hsudc.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <linux/usb/otg.h> | 29 | #include <linux/usb/otg.h> |
30 | #include <linux/prefetch.h> | 30 | #include <linux/prefetch.h> |
31 | #include <linux/platform_data/s3c-hsudc.h> | 31 | #include <linux/platform_data/s3c-hsudc.h> |
32 | #include <linux/regulator/consumer.h> | ||
32 | 33 | ||
33 | #include <mach/regs-s3c2443-clock.h> | 34 | #include <mach/regs-s3c2443-clock.h> |
34 | 35 | ||
@@ -87,6 +88,12 @@ | |||
87 | #define DATA_STATE_XMIT (1) | 88 | #define DATA_STATE_XMIT (1) |
88 | #define DATA_STATE_RECV (2) | 89 | #define DATA_STATE_RECV (2) |
89 | 90 | ||
91 | static const char * const s3c_hsudc_supply_names[] = { | ||
92 | "vdda", /* analog phy supply, 3.3V */ | ||
93 | "vddi", /* digital phy supply, 1.2V */ | ||
94 | "vddosc", /* oscillator supply, 1.8V - 3.3V */ | ||
95 | }; | ||
96 | |||
90 | /** | 97 | /** |
91 | * struct s3c_hsudc_ep - Endpoint representation used by driver. | 98 | * struct s3c_hsudc_ep - Endpoint representation used by driver. |
92 | * @ep: USB gadget layer representation of device endpoint. | 99 | * @ep: USB gadget layer representation of device endpoint. |
@@ -139,6 +146,7 @@ struct s3c_hsudc { | |||
139 | struct device *dev; | 146 | struct device *dev; |
140 | struct s3c24xx_hsudc_platdata *pd; | 147 | struct s3c24xx_hsudc_platdata *pd; |
141 | struct otg_transceiver *transceiver; | 148 | struct otg_transceiver *transceiver; |
149 | struct regulator_bulk_data supplies[ARRAY_SIZE(s3c_hsudc_supply_names)]; | ||
142 | spinlock_t lock; | 150 | spinlock_t lock; |
143 | void __iomem *regs; | 151 | void __iomem *regs; |
144 | struct resource *mem_rsrc; | 152 | struct resource *mem_rsrc; |
@@ -1150,15 +1158,20 @@ static int s3c_hsudc_start(struct usb_gadget *gadget, | |||
1150 | hsudc->driver = driver; | 1158 | hsudc->driver = driver; |
1151 | hsudc->gadget.dev.driver = &driver->driver; | 1159 | hsudc->gadget.dev.driver = &driver->driver; |
1152 | 1160 | ||
1161 | ret = regulator_bulk_enable(ARRAY_SIZE(hsudc->supplies), | ||
1162 | hsudc->supplies); | ||
1163 | if (ret != 0) { | ||
1164 | dev_err(hsudc->dev, "failed to enable supplies: %d\n", ret); | ||
1165 | goto err_supplies; | ||
1166 | } | ||
1167 | |||
1153 | /* connect to bus through transceiver */ | 1168 | /* connect to bus through transceiver */ |
1154 | if (hsudc->transceiver) { | 1169 | if (hsudc->transceiver) { |
1155 | ret = otg_set_peripheral(hsudc->transceiver, &hsudc->gadget); | 1170 | ret = otg_set_peripheral(hsudc->transceiver, &hsudc->gadget); |
1156 | if (ret) { | 1171 | if (ret) { |
1157 | dev_err(hsudc->dev, "%s: can't bind to transceiver\n", | 1172 | dev_err(hsudc->dev, "%s: can't bind to transceiver\n", |
1158 | hsudc->gadget.name); | 1173 | hsudc->gadget.name); |
1159 | hsudc->driver = NULL; | 1174 | goto err_otg; |
1160 | hsudc->gadget.dev.driver = NULL; | ||
1161 | return ret; | ||
1162 | } | 1175 | } |
1163 | } | 1176 | } |
1164 | 1177 | ||
@@ -1171,6 +1184,12 @@ static int s3c_hsudc_start(struct usb_gadget *gadget, | |||
1171 | hsudc->pd->gpio_init(); | 1184 | hsudc->pd->gpio_init(); |
1172 | 1185 | ||
1173 | return 0; | 1186 | return 0; |
1187 | err_otg: | ||
1188 | regulator_bulk_disable(ARRAY_SIZE(hsudc->supplies), hsudc->supplies); | ||
1189 | err_supplies: | ||
1190 | hsudc->driver = NULL; | ||
1191 | hsudc->gadget.dev.driver = NULL; | ||
1192 | return ret; | ||
1174 | } | 1193 | } |
1175 | 1194 | ||
1176 | static int s3c_hsudc_stop(struct usb_gadget *gadget, | 1195 | static int s3c_hsudc_stop(struct usb_gadget *gadget, |
@@ -1200,6 +1219,8 @@ static int s3c_hsudc_stop(struct usb_gadget *gadget, | |||
1200 | 1219 | ||
1201 | disable_irq(hsudc->irq); | 1220 | disable_irq(hsudc->irq); |
1202 | 1221 | ||
1222 | regulator_bulk_disable(ARRAY_SIZE(hsudc->supplies), hsudc->supplies); | ||
1223 | |||
1203 | dev_info(hsudc->dev, "unregistered gadget driver '%s'\n", | 1224 | dev_info(hsudc->dev, "unregistered gadget driver '%s'\n", |
1204 | driver->driver.name); | 1225 | driver->driver.name); |
1205 | return 0; | 1226 | return 0; |
@@ -1241,7 +1262,7 @@ static int __devinit s3c_hsudc_probe(struct platform_device *pdev) | |||
1241 | struct resource *res; | 1262 | struct resource *res; |
1242 | struct s3c_hsudc *hsudc; | 1263 | struct s3c_hsudc *hsudc; |
1243 | struct s3c24xx_hsudc_platdata *pd = pdev->dev.platform_data; | 1264 | struct s3c24xx_hsudc_platdata *pd = pdev->dev.platform_data; |
1244 | int ret; | 1265 | int ret, i; |
1245 | 1266 | ||
1246 | hsudc = kzalloc(sizeof(struct s3c_hsudc) + | 1267 | hsudc = kzalloc(sizeof(struct s3c_hsudc) + |
1247 | sizeof(struct s3c_hsudc_ep) * pd->epnum, | 1268 | sizeof(struct s3c_hsudc_ep) * pd->epnum, |
@@ -1258,6 +1279,16 @@ static int __devinit s3c_hsudc_probe(struct platform_device *pdev) | |||
1258 | 1279 | ||
1259 | hsudc->transceiver = otg_get_transceiver(); | 1280 | hsudc->transceiver = otg_get_transceiver(); |
1260 | 1281 | ||
1282 | for (i = 0; i < ARRAY_SIZE(hsudc->supplies); i++) | ||
1283 | hsudc->supplies[i].supply = s3c_hsudc_supply_names[i]; | ||
1284 | |||
1285 | ret = regulator_bulk_get(dev, ARRAY_SIZE(hsudc->supplies), | ||
1286 | hsudc->supplies); | ||
1287 | if (ret != 0) { | ||
1288 | dev_err(dev, "failed to request supplies: %d\n", ret); | ||
1289 | goto err_supplies; | ||
1290 | } | ||
1291 | |||
1261 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 1292 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
1262 | if (!res) { | 1293 | if (!res) { |
1263 | dev_err(dev, "unable to obtain driver resource data\n"); | 1294 | dev_err(dev, "unable to obtain driver resource data\n"); |
@@ -1352,6 +1383,8 @@ err_res: | |||
1352 | if (hsudc->transceiver) | 1383 | if (hsudc->transceiver) |
1353 | otg_put_transceiver(hsudc->transceiver); | 1384 | otg_put_transceiver(hsudc->transceiver); |
1354 | 1385 | ||
1386 | regulator_bulk_free(ARRAY_SIZE(hsudc->supplies), hsudc->supplies); | ||
1387 | err_supplies: | ||
1355 | kfree(hsudc); | 1388 | kfree(hsudc); |
1356 | return ret; | 1389 | return ret; |
1357 | } | 1390 | } |