aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/gadget/s3c-hsudc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/gadget/s3c-hsudc.c')
-rw-r--r--drivers/usb/gadget/s3c-hsudc.c136
1 files changed, 70 insertions, 66 deletions
diff --git a/drivers/usb/gadget/s3c-hsudc.c b/drivers/usb/gadget/s3c-hsudc.c
index 20a553b46aed..df8661d266cb 100644
--- a/drivers/usb/gadget/s3c-hsudc.c
+++ b/drivers/usb/gadget/s3c-hsudc.c
@@ -28,9 +28,10 @@
28#include <linux/usb/gadget.h> 28#include <linux/usb/gadget.h>
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>
32#include <linux/regulator/consumer.h>
31 33
32#include <mach/regs-s3c2443-clock.h> 34#include <mach/regs-s3c2443-clock.h>
33#include <plat/udc.h>
34 35
35#define S3C_HSUDC_REG(x) (x) 36#define S3C_HSUDC_REG(x) (x)
36 37
@@ -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;
@@ -153,7 +161,6 @@ struct s3c_hsudc {
153#define ep_index(_ep) ((_ep)->bEndpointAddress & \ 161#define ep_index(_ep) ((_ep)->bEndpointAddress & \
154 USB_ENDPOINT_NUMBER_MASK) 162 USB_ENDPOINT_NUMBER_MASK)
155 163
156static struct s3c_hsudc *the_controller;
157static const char driver_name[] = "s3c-udc"; 164static const char driver_name[] = "s3c-udc";
158static const char ep0name[] = "ep0-control"; 165static const char ep0name[] = "ep0-control";
159 166
@@ -282,8 +289,7 @@ static void s3c_hsudc_nuke_ep(struct s3c_hsudc_ep *hsep, int status)
282 * All the endpoints are stopped and any pending transfer requests if any on 289 * All the endpoints are stopped and any pending transfer requests if any on
283 * the endpoint are terminated. 290 * the endpoint are terminated.
284 */ 291 */
285static void s3c_hsudc_stop_activity(struct s3c_hsudc *hsudc, 292static void s3c_hsudc_stop_activity(struct s3c_hsudc *hsudc)
286 struct usb_gadget_driver *driver)
287{ 293{
288 struct s3c_hsudc_ep *hsep; 294 struct s3c_hsudc_ep *hsep;
289 int epnum; 295 int epnum;
@@ -295,10 +301,6 @@ static void s3c_hsudc_stop_activity(struct s3c_hsudc *hsudc,
295 hsep->stopped = 1; 301 hsep->stopped = 1;
296 s3c_hsudc_nuke_ep(hsep, -ESHUTDOWN); 302 s3c_hsudc_nuke_ep(hsep, -ESHUTDOWN);
297 } 303 }
298
299 spin_unlock(&hsudc->lock);
300 driver->disconnect(&hsudc->gadget);
301 spin_lock(&hsudc->lock);
302} 304}
303 305
304/** 306/**
@@ -1135,16 +1137,15 @@ static irqreturn_t s3c_hsudc_irq(int irq, void *_dev)
1135 return IRQ_HANDLED; 1137 return IRQ_HANDLED;
1136} 1138}
1137 1139
1138static int s3c_hsudc_start(struct usb_gadget_driver *driver, 1140static int s3c_hsudc_start(struct usb_gadget *gadget,
1139 int (*bind)(struct usb_gadget *)) 1141 struct usb_gadget_driver *driver)
1140{ 1142{
1141 struct s3c_hsudc *hsudc = the_controller; 1143 struct s3c_hsudc *hsudc = to_hsudc(gadget);
1142 int ret; 1144 int ret;
1143 1145
1144 if (!driver 1146 if (!driver
1145 || driver->speed < USB_SPEED_FULL 1147 || driver->max_speed < USB_SPEED_FULL
1146 || !bind 1148 || !driver->setup)
1147 || !driver->unbind || !driver->disconnect || !driver->setup)
1148 return -EINVAL; 1149 return -EINVAL;
1149 1150
1150 if (!hsudc) 1151 if (!hsudc)
@@ -1155,21 +1156,12 @@ static int s3c_hsudc_start(struct usb_gadget_driver *driver,
1155 1156
1156 hsudc->driver = driver; 1157 hsudc->driver = driver;
1157 hsudc->gadget.dev.driver = &driver->driver; 1158 hsudc->gadget.dev.driver = &driver->driver;
1158 hsudc->gadget.speed = USB_SPEED_UNKNOWN;
1159 ret = device_add(&hsudc->gadget.dev);
1160 if (ret) {
1161 dev_err(hsudc->dev, "failed to probe gadget device");
1162 return ret;
1163 }
1164 1159
1165 ret = bind(&hsudc->gadget); 1160 ret = regulator_bulk_enable(ARRAY_SIZE(hsudc->supplies),
1166 if (ret) { 1161 hsudc->supplies);
1167 dev_err(hsudc->dev, "%s: bind failed\n", hsudc->gadget.name); 1162 if (ret != 0) {
1168 device_del(&hsudc->gadget.dev); 1163 dev_err(hsudc->dev, "failed to enable supplies: %d\n", ret);
1169 1164 goto err_supplies;
1170 hsudc->driver = NULL;
1171 hsudc->gadget.dev.driver = NULL;
1172 return ret;
1173 } 1165 }
1174 1166
1175 /* connect to bus through transceiver */ 1167 /* connect to bus through transceiver */
@@ -1178,13 +1170,7 @@ static int s3c_hsudc_start(struct usb_gadget_driver *driver,
1178 if (ret) { 1170 if (ret) {
1179 dev_err(hsudc->dev, "%s: can't bind to transceiver\n", 1171 dev_err(hsudc->dev, "%s: can't bind to transceiver\n",
1180 hsudc->gadget.name); 1172 hsudc->gadget.name);
1181 driver->unbind(&hsudc->gadget); 1173 goto err_otg;
1182
1183 device_del(&hsudc->gadget.dev);
1184
1185 hsudc->driver = NULL;
1186 hsudc->gadget.dev.driver = NULL;
1187 return ret;
1188 } 1174 }
1189 } 1175 }
1190 1176
@@ -1197,34 +1183,43 @@ static int s3c_hsudc_start(struct usb_gadget_driver *driver,
1197 hsudc->pd->gpio_init(); 1183 hsudc->pd->gpio_init();
1198 1184
1199 return 0; 1185 return 0;
1186err_otg:
1187 regulator_bulk_disable(ARRAY_SIZE(hsudc->supplies), hsudc->supplies);
1188err_supplies:
1189 hsudc->driver = NULL;
1190 hsudc->gadget.dev.driver = NULL;
1191 return ret;
1200} 1192}
1201 1193
1202static int s3c_hsudc_stop(struct usb_gadget_driver *driver) 1194static int s3c_hsudc_stop(struct usb_gadget *gadget,
1195 struct usb_gadget_driver *driver)
1203{ 1196{
1204 struct s3c_hsudc *hsudc = the_controller; 1197 struct s3c_hsudc *hsudc = to_hsudc(gadget);
1205 unsigned long flags; 1198 unsigned long flags;
1206 1199
1207 if (!hsudc) 1200 if (!hsudc)
1208 return -ENODEV; 1201 return -ENODEV;
1209 1202
1210 if (!driver || driver != hsudc->driver || !driver->unbind) 1203 if (!driver || driver != hsudc->driver)
1211 return -EINVAL; 1204 return -EINVAL;
1212 1205
1213 spin_lock_irqsave(&hsudc->lock, flags); 1206 spin_lock_irqsave(&hsudc->lock, flags);
1214 hsudc->driver = 0; 1207 hsudc->driver = NULL;
1208 hsudc->gadget.dev.driver = NULL;
1209 hsudc->gadget.speed = USB_SPEED_UNKNOWN;
1215 s3c_hsudc_uninit_phy(); 1210 s3c_hsudc_uninit_phy();
1216 if (hsudc->pd->gpio_uninit) 1211 if (hsudc->pd->gpio_uninit)
1217 hsudc->pd->gpio_uninit(); 1212 hsudc->pd->gpio_uninit();
1218 s3c_hsudc_stop_activity(hsudc, driver); 1213 s3c_hsudc_stop_activity(hsudc);
1219 spin_unlock_irqrestore(&hsudc->lock, flags); 1214 spin_unlock_irqrestore(&hsudc->lock, flags);
1220 1215
1221 if (hsudc->transceiver) 1216 if (hsudc->transceiver)
1222 (void) otg_set_peripheral(hsudc->transceiver, NULL); 1217 (void) otg_set_peripheral(hsudc->transceiver, NULL);
1223 1218
1224 driver->unbind(&hsudc->gadget);
1225 device_del(&hsudc->gadget.dev);
1226 disable_irq(hsudc->irq); 1219 disable_irq(hsudc->irq);
1227 1220
1221 regulator_bulk_disable(ARRAY_SIZE(hsudc->supplies), hsudc->supplies);
1222
1228 dev_info(hsudc->dev, "unregistered gadget driver '%s'\n", 1223 dev_info(hsudc->dev, "unregistered gadget driver '%s'\n",
1229 driver->driver.name); 1224 driver->driver.name);
1230 return 0; 1225 return 0;
@@ -1242,7 +1237,7 @@ static int s3c_hsudc_gadget_getframe(struct usb_gadget *gadget)
1242 1237
1243static int s3c_hsudc_vbus_draw(struct usb_gadget *gadget, unsigned mA) 1238static int s3c_hsudc_vbus_draw(struct usb_gadget *gadget, unsigned mA)
1244{ 1239{
1245 struct s3c_hsudc *hsudc = the_controller; 1240 struct s3c_hsudc *hsudc = to_hsudc(gadget);
1246 1241
1247 if (!hsudc) 1242 if (!hsudc)
1248 return -ENODEV; 1243 return -ENODEV;
@@ -1255,18 +1250,18 @@ static int s3c_hsudc_vbus_draw(struct usb_gadget *gadget, unsigned mA)
1255 1250
1256static struct usb_gadget_ops s3c_hsudc_gadget_ops = { 1251static struct usb_gadget_ops s3c_hsudc_gadget_ops = {
1257 .get_frame = s3c_hsudc_gadget_getframe, 1252 .get_frame = s3c_hsudc_gadget_getframe,
1258 .start = s3c_hsudc_start, 1253 .udc_start = s3c_hsudc_start,
1259 .stop = s3c_hsudc_stop, 1254 .udc_stop = s3c_hsudc_stop,
1260 .vbus_draw = s3c_hsudc_vbus_draw, 1255 .vbus_draw = s3c_hsudc_vbus_draw,
1261}; 1256};
1262 1257
1263static int s3c_hsudc_probe(struct platform_device *pdev) 1258static int __devinit s3c_hsudc_probe(struct platform_device *pdev)
1264{ 1259{
1265 struct device *dev = &pdev->dev; 1260 struct device *dev = &pdev->dev;
1266 struct resource *res; 1261 struct resource *res;
1267 struct s3c_hsudc *hsudc; 1262 struct s3c_hsudc *hsudc;
1268 struct s3c24xx_hsudc_platdata *pd = pdev->dev.platform_data; 1263 struct s3c24xx_hsudc_platdata *pd = pdev->dev.platform_data;
1269 int ret; 1264 int ret, i;
1270 1265
1271 hsudc = kzalloc(sizeof(struct s3c_hsudc) + 1266 hsudc = kzalloc(sizeof(struct s3c_hsudc) +
1272 sizeof(struct s3c_hsudc_ep) * pd->epnum, 1267 sizeof(struct s3c_hsudc_ep) * pd->epnum,
@@ -1276,13 +1271,22 @@ static int s3c_hsudc_probe(struct platform_device *pdev)
1276 return -ENOMEM; 1271 return -ENOMEM;
1277 } 1272 }
1278 1273
1279 the_controller = hsudc;
1280 platform_set_drvdata(pdev, dev); 1274 platform_set_drvdata(pdev, dev);
1281 hsudc->dev = dev; 1275 hsudc->dev = dev;
1282 hsudc->pd = pdev->dev.platform_data; 1276 hsudc->pd = pdev->dev.platform_data;
1283 1277
1284 hsudc->transceiver = otg_get_transceiver(); 1278 hsudc->transceiver = otg_get_transceiver();
1285 1279
1280 for (i = 0; i < ARRAY_SIZE(hsudc->supplies); i++)
1281 hsudc->supplies[i].supply = s3c_hsudc_supply_names[i];
1282
1283 ret = regulator_bulk_get(dev, ARRAY_SIZE(hsudc->supplies),
1284 hsudc->supplies);
1285 if (ret != 0) {
1286 dev_err(dev, "failed to request supplies: %d\n", ret);
1287 goto err_supplies;
1288 }
1289
1286 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1290 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1287 if (!res) { 1291 if (!res) {
1288 dev_err(dev, "unable to obtain driver resource data\n"); 1292 dev_err(dev, "unable to obtain driver resource data\n");
@@ -1307,10 +1311,9 @@ static int s3c_hsudc_probe(struct platform_device *pdev)
1307 1311
1308 spin_lock_init(&hsudc->lock); 1312 spin_lock_init(&hsudc->lock);
1309 1313
1310 device_initialize(&hsudc->gadget.dev);
1311 dev_set_name(&hsudc->gadget.dev, "gadget"); 1314 dev_set_name(&hsudc->gadget.dev, "gadget");
1312 1315
1313 hsudc->gadget.is_dualspeed = 1; 1316 hsudc->gadget.max_speed = USB_SPEED_HIGH;
1314 hsudc->gadget.ops = &s3c_hsudc_gadget_ops; 1317 hsudc->gadget.ops = &s3c_hsudc_gadget_ops;
1315 hsudc->gadget.name = dev_name(dev); 1318 hsudc->gadget.name = dev_name(dev);
1316 hsudc->gadget.dev.parent = dev; 1319 hsudc->gadget.dev.parent = dev;
@@ -1319,6 +1322,7 @@ static int s3c_hsudc_probe(struct platform_device *pdev)
1319 1322
1320 hsudc->gadget.is_otg = 0; 1323 hsudc->gadget.is_otg = 0;
1321 hsudc->gadget.is_a_peripheral = 0; 1324 hsudc->gadget.is_a_peripheral = 0;
1325 hsudc->gadget.speed = USB_SPEED_UNKNOWN;
1322 1326
1323 s3c_hsudc_setup_ep(hsudc); 1327 s3c_hsudc_setup_ep(hsudc);
1324 1328
@@ -1348,12 +1352,20 @@ static int s3c_hsudc_probe(struct platform_device *pdev)
1348 disable_irq(hsudc->irq); 1352 disable_irq(hsudc->irq);
1349 local_irq_enable(); 1353 local_irq_enable();
1350 1354
1355 ret = device_register(&hsudc->gadget.dev);
1356 if (ret) {
1357 put_device(&hsudc->gadget.dev);
1358 goto err_add_device;
1359 }
1360
1351 ret = usb_add_gadget_udc(&pdev->dev, &hsudc->gadget); 1361 ret = usb_add_gadget_udc(&pdev->dev, &hsudc->gadget);
1352 if (ret) 1362 if (ret)
1353 goto err_add_udc; 1363 goto err_add_udc;
1354 1364
1355 return 0; 1365 return 0;
1356err_add_udc: 1366err_add_udc:
1367 device_unregister(&hsudc->gadget.dev);
1368err_add_device:
1357 clk_disable(hsudc->uclk); 1369 clk_disable(hsudc->uclk);
1358 clk_put(hsudc->uclk); 1370 clk_put(hsudc->uclk);
1359err_clk: 1371err_clk:
@@ -1362,10 +1374,13 @@ err_irq:
1362 iounmap(hsudc->regs); 1374 iounmap(hsudc->regs);
1363 1375
1364err_remap: 1376err_remap:
1365 release_resource(hsudc->mem_rsrc); 1377 release_mem_region(res->start, resource_size(res));
1366 kfree(hsudc->mem_rsrc);
1367
1368err_res: 1378err_res:
1379 if (hsudc->transceiver)
1380 otg_put_transceiver(hsudc->transceiver);
1381
1382 regulator_bulk_free(ARRAY_SIZE(hsudc->supplies), hsudc->supplies);
1383err_supplies:
1369 kfree(hsudc); 1384 kfree(hsudc);
1370 return ret; 1385 return ret;
1371} 1386}
@@ -1377,21 +1392,10 @@ static struct platform_driver s3c_hsudc_driver = {
1377 }, 1392 },
1378 .probe = s3c_hsudc_probe, 1393 .probe = s3c_hsudc_probe,
1379}; 1394};
1380MODULE_ALIAS("platform:s3c-hsudc");
1381
1382static int __init s3c_hsudc_modinit(void)
1383{
1384 return platform_driver_register(&s3c_hsudc_driver);
1385}
1386 1395
1387static void __exit s3c_hsudc_modexit(void) 1396module_platform_driver(s3c_hsudc_driver);
1388{
1389 platform_driver_unregister(&s3c_hsudc_driver);
1390}
1391
1392module_init(s3c_hsudc_modinit);
1393module_exit(s3c_hsudc_modexit);
1394 1397
1395MODULE_DESCRIPTION("Samsung S3C24XX USB high-speed controller driver"); 1398MODULE_DESCRIPTION("Samsung S3C24XX USB high-speed controller driver");
1396MODULE_AUTHOR("Thomas Abraham <thomas.ab@samsung.com>"); 1399MODULE_AUTHOR("Thomas Abraham <thomas.ab@samsung.com>");
1397MODULE_LICENSE("GPL"); 1400MODULE_LICENSE("GPL");
1401MODULE_ALIAS("platform:s3c-hsudc");