aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/gadget/s3c-hsudc.c
diff options
context:
space:
mode:
authorHeiko Stübner <heiko@sntech.de>2011-12-19 13:42:19 -0500
committerFelipe Balbi <balbi@ti.com>2011-12-21 06:24:40 -0500
commitbab7d037c84f74449a510841ad03707f7e6609a5 (patch)
tree321fdd951388e7192efc0d35cec18aa5de21db17 /drivers/usb/gadget/s3c-hsudc.c
parentd93e2600d80fc41ccf339b4a2843a3007d479907 (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.c41
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
91static 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;
1187err_otg:
1188 regulator_bulk_disable(ARRAY_SIZE(hsudc->supplies), hsudc->supplies);
1189err_supplies:
1190 hsudc->driver = NULL;
1191 hsudc->gadget.dev.driver = NULL;
1192 return ret;
1174} 1193}
1175 1194
1176static int s3c_hsudc_stop(struct usb_gadget *gadget, 1195static 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);
1387err_supplies:
1355 kfree(hsudc); 1388 kfree(hsudc);
1356 return ret; 1389 return ret;
1357} 1390}