diff options
Diffstat (limited to 'drivers/usb/gadget/pch_udc.c')
-rw-r--r-- | drivers/usb/gadget/pch_udc.c | 323 |
1 files changed, 312 insertions, 11 deletions
diff --git a/drivers/usb/gadget/pch_udc.c b/drivers/usb/gadget/pch_udc.c index a3fcaae4bc2a..65307064a6fd 100644 --- a/drivers/usb/gadget/pch_udc.c +++ b/drivers/usb/gadget/pch_udc.c | |||
@@ -15,6 +15,14 @@ | |||
15 | #include <linux/interrupt.h> | 15 | #include <linux/interrupt.h> |
16 | #include <linux/usb/ch9.h> | 16 | #include <linux/usb/ch9.h> |
17 | #include <linux/usb/gadget.h> | 17 | #include <linux/usb/gadget.h> |
18 | #include <linux/gpio.h> | ||
19 | #include <linux/irq.h> | ||
20 | |||
21 | /* GPIO port for VBUS detecting */ | ||
22 | static int vbus_gpio_port = -1; /* GPIO port number (-1:Not used) */ | ||
23 | |||
24 | #define PCH_VBUS_PERIOD 3000 /* VBUS polling period (msec) */ | ||
25 | #define PCH_VBUS_INTERVAL 10 /* VBUS polling interval (msec) */ | ||
18 | 26 | ||
19 | /* Address offset of Registers */ | 27 | /* Address offset of Registers */ |
20 | #define UDC_EP_REG_SHIFT 0x20 /* Offset to next EP */ | 28 | #define UDC_EP_REG_SHIFT 0x20 /* Offset to next EP */ |
@@ -296,6 +304,21 @@ struct pch_udc_ep { | |||
296 | }; | 304 | }; |
297 | 305 | ||
298 | /** | 306 | /** |
307 | * struct pch_vbus_gpio_data - Structure holding GPIO informaton | ||
308 | * for detecting VBUS | ||
309 | * @port: gpio port number | ||
310 | * @intr: gpio interrupt number | ||
311 | * @irq_work_fall Structure for WorkQueue | ||
312 | * @irq_work_rise Structure for WorkQueue | ||
313 | */ | ||
314 | struct pch_vbus_gpio_data { | ||
315 | int port; | ||
316 | int intr; | ||
317 | struct work_struct irq_work_fall; | ||
318 | struct work_struct irq_work_rise; | ||
319 | }; | ||
320 | |||
321 | /** | ||
299 | * struct pch_udc_dev - Structure holding complete information | 322 | * struct pch_udc_dev - Structure holding complete information |
300 | * of the PCH USB device | 323 | * of the PCH USB device |
301 | * @gadget: gadget driver data | 324 | * @gadget: gadget driver data |
@@ -311,6 +334,7 @@ struct pch_udc_ep { | |||
311 | * @registered: driver regsitered with system | 334 | * @registered: driver regsitered with system |
312 | * @suspended: driver in suspended state | 335 | * @suspended: driver in suspended state |
313 | * @connected: gadget driver associated | 336 | * @connected: gadget driver associated |
337 | * @vbus_session: required vbus_session state | ||
314 | * @set_cfg_not_acked: pending acknowledgement 4 setup | 338 | * @set_cfg_not_acked: pending acknowledgement 4 setup |
315 | * @waiting_zlp_ack: pending acknowledgement 4 ZLP | 339 | * @waiting_zlp_ack: pending acknowledgement 4 ZLP |
316 | * @data_requests: DMA pool for data requests | 340 | * @data_requests: DMA pool for data requests |
@@ -322,6 +346,7 @@ struct pch_udc_ep { | |||
322 | * @base_addr: for mapped device memory | 346 | * @base_addr: for mapped device memory |
323 | * @irq: IRQ line for the device | 347 | * @irq: IRQ line for the device |
324 | * @cfg_data: current cfg, intf, and alt in use | 348 | * @cfg_data: current cfg, intf, and alt in use |
349 | * @vbus_gpio: GPIO informaton for detecting VBUS | ||
325 | */ | 350 | */ |
326 | struct pch_udc_dev { | 351 | struct pch_udc_dev { |
327 | struct usb_gadget gadget; | 352 | struct usb_gadget gadget; |
@@ -337,6 +362,7 @@ struct pch_udc_dev { | |||
337 | registered:1, | 362 | registered:1, |
338 | suspended:1, | 363 | suspended:1, |
339 | connected:1, | 364 | connected:1, |
365 | vbus_session:1, | ||
340 | set_cfg_not_acked:1, | 366 | set_cfg_not_acked:1, |
341 | waiting_zlp_ack:1; | 367 | waiting_zlp_ack:1; |
342 | struct pci_pool *data_requests; | 368 | struct pci_pool *data_requests; |
@@ -347,7 +373,8 @@ struct pch_udc_dev { | |||
347 | unsigned long phys_addr; | 373 | unsigned long phys_addr; |
348 | void __iomem *base_addr; | 374 | void __iomem *base_addr; |
349 | unsigned irq; | 375 | unsigned irq; |
350 | struct pch_udc_cfg_data cfg_data; | 376 | struct pch_udc_cfg_data cfg_data; |
377 | struct pch_vbus_gpio_data vbus_gpio; | ||
351 | }; | 378 | }; |
352 | 379 | ||
353 | #define PCH_UDC_PCI_BAR 1 | 380 | #define PCH_UDC_PCI_BAR 1 |
@@ -554,6 +581,29 @@ static void pch_udc_clear_disconnect(struct pch_udc_dev *dev) | |||
554 | } | 581 | } |
555 | 582 | ||
556 | /** | 583 | /** |
584 | * pch_udc_reconnect() - This API initializes usb device controller, | ||
585 | * and clear the disconnect status. | ||
586 | * @dev: Reference to pch_udc_regs structure | ||
587 | */ | ||
588 | static void pch_udc_init(struct pch_udc_dev *dev); | ||
589 | static void pch_udc_reconnect(struct pch_udc_dev *dev) | ||
590 | { | ||
591 | pch_udc_init(dev); | ||
592 | |||
593 | /* enable device interrupts */ | ||
594 | /* pch_udc_enable_interrupts() */ | ||
595 | pch_udc_bit_clr(dev, UDC_DEVIRQMSK_ADDR, | ||
596 | UDC_DEVINT_UR | UDC_DEVINT_ENUM); | ||
597 | |||
598 | /* Clear the disconnect */ | ||
599 | pch_udc_bit_set(dev, UDC_DEVCTL_ADDR, UDC_DEVCTL_RES); | ||
600 | pch_udc_bit_clr(dev, UDC_DEVCTL_ADDR, UDC_DEVCTL_SD); | ||
601 | mdelay(1); | ||
602 | /* Resume USB signalling */ | ||
603 | pch_udc_bit_clr(dev, UDC_DEVCTL_ADDR, UDC_DEVCTL_RES); | ||
604 | } | ||
605 | |||
606 | /** | ||
557 | * pch_udc_vbus_session() - set or clearr the disconnect status. | 607 | * pch_udc_vbus_session() - set or clearr the disconnect status. |
558 | * @dev: Reference to pch_udc_regs structure | 608 | * @dev: Reference to pch_udc_regs structure |
559 | * @is_active: Parameter specifying the action | 609 | * @is_active: Parameter specifying the action |
@@ -563,10 +613,18 @@ static void pch_udc_clear_disconnect(struct pch_udc_dev *dev) | |||
563 | static inline void pch_udc_vbus_session(struct pch_udc_dev *dev, | 613 | static inline void pch_udc_vbus_session(struct pch_udc_dev *dev, |
564 | int is_active) | 614 | int is_active) |
565 | { | 615 | { |
566 | if (is_active) | 616 | if (is_active) { |
567 | pch_udc_clear_disconnect(dev); | 617 | pch_udc_reconnect(dev); |
568 | else | 618 | dev->vbus_session = 1; |
619 | } else { | ||
620 | if (dev->driver && dev->driver->disconnect) { | ||
621 | spin_unlock(&dev->lock); | ||
622 | dev->driver->disconnect(&dev->gadget); | ||
623 | spin_lock(&dev->lock); | ||
624 | } | ||
569 | pch_udc_set_disconnect(dev); | 625 | pch_udc_set_disconnect(dev); |
626 | dev->vbus_session = 0; | ||
627 | } | ||
570 | } | 628 | } |
571 | 629 | ||
572 | /** | 630 | /** |
@@ -1126,7 +1184,17 @@ static int pch_udc_pcd_pullup(struct usb_gadget *gadget, int is_on) | |||
1126 | if (!gadget) | 1184 | if (!gadget) |
1127 | return -EINVAL; | 1185 | return -EINVAL; |
1128 | dev = container_of(gadget, struct pch_udc_dev, gadget); | 1186 | dev = container_of(gadget, struct pch_udc_dev, gadget); |
1129 | pch_udc_vbus_session(dev, is_on); | 1187 | if (is_on) { |
1188 | pch_udc_reconnect(dev); | ||
1189 | } else { | ||
1190 | if (dev->driver && dev->driver->disconnect) { | ||
1191 | spin_unlock(&dev->lock); | ||
1192 | dev->driver->disconnect(&dev->gadget); | ||
1193 | spin_lock(&dev->lock); | ||
1194 | } | ||
1195 | pch_udc_set_disconnect(dev); | ||
1196 | } | ||
1197 | |||
1130 | return 0; | 1198 | return 0; |
1131 | } | 1199 | } |
1132 | 1200 | ||
@@ -1183,6 +1251,188 @@ static const struct usb_gadget_ops pch_udc_ops = { | |||
1183 | }; | 1251 | }; |
1184 | 1252 | ||
1185 | /** | 1253 | /** |
1254 | * pch_vbus_gpio_get_value() - This API gets value of GPIO port as VBUS status. | ||
1255 | * @dev: Reference to the driver structure | ||
1256 | * | ||
1257 | * Return value: | ||
1258 | * 1: VBUS is high | ||
1259 | * 0: VBUS is low | ||
1260 | * -1: It is not enable to detect VBUS using GPIO | ||
1261 | */ | ||
1262 | static int pch_vbus_gpio_get_value(struct pch_udc_dev *dev) | ||
1263 | { | ||
1264 | int vbus = 0; | ||
1265 | |||
1266 | if (dev->vbus_gpio.port) | ||
1267 | vbus = gpio_get_value(dev->vbus_gpio.port) ? 1 : 0; | ||
1268 | else | ||
1269 | vbus = -1; | ||
1270 | |||
1271 | return vbus; | ||
1272 | } | ||
1273 | |||
1274 | /** | ||
1275 | * pch_vbus_gpio_work_fall() - This API keeps watch on VBUS becoming Low. | ||
1276 | * If VBUS is Low, disconnect is processed | ||
1277 | * @irq_work: Structure for WorkQueue | ||
1278 | * | ||
1279 | */ | ||
1280 | static void pch_vbus_gpio_work_fall(struct work_struct *irq_work) | ||
1281 | { | ||
1282 | struct pch_vbus_gpio_data *vbus_gpio = container_of(irq_work, | ||
1283 | struct pch_vbus_gpio_data, irq_work_fall); | ||
1284 | struct pch_udc_dev *dev = | ||
1285 | container_of(vbus_gpio, struct pch_udc_dev, vbus_gpio); | ||
1286 | int vbus_saved = -1; | ||
1287 | int vbus; | ||
1288 | int count; | ||
1289 | |||
1290 | if (!dev->vbus_gpio.port) | ||
1291 | return; | ||
1292 | |||
1293 | for (count = 0; count < (PCH_VBUS_PERIOD / PCH_VBUS_INTERVAL); | ||
1294 | count++) { | ||
1295 | vbus = pch_vbus_gpio_get_value(dev); | ||
1296 | |||
1297 | if ((vbus_saved == vbus) && (vbus == 0)) { | ||
1298 | dev_dbg(&dev->pdev->dev, "VBUS fell"); | ||
1299 | if (dev->driver | ||
1300 | && dev->driver->disconnect) { | ||
1301 | dev->driver->disconnect( | ||
1302 | &dev->gadget); | ||
1303 | } | ||
1304 | if (dev->vbus_gpio.intr) | ||
1305 | pch_udc_init(dev); | ||
1306 | else | ||
1307 | pch_udc_reconnect(dev); | ||
1308 | return; | ||
1309 | } | ||
1310 | vbus_saved = vbus; | ||
1311 | mdelay(PCH_VBUS_INTERVAL); | ||
1312 | } | ||
1313 | } | ||
1314 | |||
1315 | /** | ||
1316 | * pch_vbus_gpio_work_rise() - This API checks VBUS is High. | ||
1317 | * If VBUS is High, connect is processed | ||
1318 | * @irq_work: Structure for WorkQueue | ||
1319 | * | ||
1320 | */ | ||
1321 | static void pch_vbus_gpio_work_rise(struct work_struct *irq_work) | ||
1322 | { | ||
1323 | struct pch_vbus_gpio_data *vbus_gpio = container_of(irq_work, | ||
1324 | struct pch_vbus_gpio_data, irq_work_rise); | ||
1325 | struct pch_udc_dev *dev = | ||
1326 | container_of(vbus_gpio, struct pch_udc_dev, vbus_gpio); | ||
1327 | int vbus; | ||
1328 | |||
1329 | if (!dev->vbus_gpio.port) | ||
1330 | return; | ||
1331 | |||
1332 | mdelay(PCH_VBUS_INTERVAL); | ||
1333 | vbus = pch_vbus_gpio_get_value(dev); | ||
1334 | |||
1335 | if (vbus == 1) { | ||
1336 | dev_dbg(&dev->pdev->dev, "VBUS rose"); | ||
1337 | pch_udc_reconnect(dev); | ||
1338 | return; | ||
1339 | } | ||
1340 | } | ||
1341 | |||
1342 | /** | ||
1343 | * pch_vbus_gpio_irq() - IRQ handler for GPIO intrerrupt for changing VBUS | ||
1344 | * @irq: Interrupt request number | ||
1345 | * @dev: Reference to the device structure | ||
1346 | * | ||
1347 | * Return codes: | ||
1348 | * 0: Success | ||
1349 | * -EINVAL: GPIO port is invalid or can't be initialized. | ||
1350 | */ | ||
1351 | static irqreturn_t pch_vbus_gpio_irq(int irq, void *data) | ||
1352 | { | ||
1353 | struct pch_udc_dev *dev = (struct pch_udc_dev *)data; | ||
1354 | |||
1355 | if (!dev->vbus_gpio.port || !dev->vbus_gpio.intr) | ||
1356 | return IRQ_NONE; | ||
1357 | |||
1358 | if (pch_vbus_gpio_get_value(dev)) | ||
1359 | schedule_work(&dev->vbus_gpio.irq_work_rise); | ||
1360 | else | ||
1361 | schedule_work(&dev->vbus_gpio.irq_work_fall); | ||
1362 | |||
1363 | return IRQ_HANDLED; | ||
1364 | } | ||
1365 | |||
1366 | /** | ||
1367 | * pch_vbus_gpio_init() - This API initializes GPIO port detecting VBUS. | ||
1368 | * @dev: Reference to the driver structure | ||
1369 | * @vbus_gpio Number of GPIO port to detect gpio | ||
1370 | * | ||
1371 | * Return codes: | ||
1372 | * 0: Success | ||
1373 | * -EINVAL: GPIO port is invalid or can't be initialized. | ||
1374 | */ | ||
1375 | static int pch_vbus_gpio_init(struct pch_udc_dev *dev, int vbus_gpio_port) | ||
1376 | { | ||
1377 | int err; | ||
1378 | int irq_num = 0; | ||
1379 | |||
1380 | dev->vbus_gpio.port = 0; | ||
1381 | dev->vbus_gpio.intr = 0; | ||
1382 | |||
1383 | if (vbus_gpio_port <= -1) | ||
1384 | return -EINVAL; | ||
1385 | |||
1386 | err = gpio_is_valid(vbus_gpio_port); | ||
1387 | if (!err) { | ||
1388 | pr_err("%s: gpio port %d is invalid\n", | ||
1389 | __func__, vbus_gpio_port); | ||
1390 | return -EINVAL; | ||
1391 | } | ||
1392 | |||
1393 | err = gpio_request(vbus_gpio_port, "pch_vbus"); | ||
1394 | if (err) { | ||
1395 | pr_err("%s: can't request gpio port %d, err: %d\n", | ||
1396 | __func__, vbus_gpio_port, err); | ||
1397 | return -EINVAL; | ||
1398 | } | ||
1399 | |||
1400 | dev->vbus_gpio.port = vbus_gpio_port; | ||
1401 | gpio_direction_input(vbus_gpio_port); | ||
1402 | INIT_WORK(&dev->vbus_gpio.irq_work_fall, pch_vbus_gpio_work_fall); | ||
1403 | |||
1404 | irq_num = gpio_to_irq(vbus_gpio_port); | ||
1405 | if (irq_num > 0) { | ||
1406 | irq_set_irq_type(irq_num, IRQ_TYPE_EDGE_BOTH); | ||
1407 | err = request_irq(irq_num, pch_vbus_gpio_irq, 0, | ||
1408 | "vbus_detect", dev); | ||
1409 | if (!err) { | ||
1410 | dev->vbus_gpio.intr = irq_num; | ||
1411 | INIT_WORK(&dev->vbus_gpio.irq_work_rise, | ||
1412 | pch_vbus_gpio_work_rise); | ||
1413 | } else { | ||
1414 | pr_err("%s: can't request irq %d, err: %d\n", | ||
1415 | __func__, irq_num, err); | ||
1416 | } | ||
1417 | } | ||
1418 | |||
1419 | return 0; | ||
1420 | } | ||
1421 | |||
1422 | /** | ||
1423 | * pch_vbus_gpio_free() - This API frees resources of GPIO port | ||
1424 | * @dev: Reference to the driver structure | ||
1425 | */ | ||
1426 | static void pch_vbus_gpio_free(struct pch_udc_dev *dev) | ||
1427 | { | ||
1428 | if (dev->vbus_gpio.intr) | ||
1429 | free_irq(dev->vbus_gpio.intr, dev); | ||
1430 | |||
1431 | if (dev->vbus_gpio.port) | ||
1432 | gpio_free(dev->vbus_gpio.port); | ||
1433 | } | ||
1434 | |||
1435 | /** | ||
1186 | * complete_req() - This API is invoked from the driver when processing | 1436 | * complete_req() - This API is invoked from the driver when processing |
1187 | * of a request is complete | 1437 | * of a request is complete |
1188 | * @ep: Reference to the endpoint structure | 1438 | * @ep: Reference to the endpoint structure |
@@ -1493,6 +1743,7 @@ static int pch_udc_pcd_ep_disable(struct usb_ep *usbep) | |||
1493 | pch_udc_ep_disable(ep); | 1743 | pch_udc_ep_disable(ep); |
1494 | pch_udc_disable_ep_interrupts(ep->dev, PCH_UDC_EPINT(ep->in, ep->num)); | 1744 | pch_udc_disable_ep_interrupts(ep->dev, PCH_UDC_EPINT(ep->in, ep->num)); |
1495 | ep->desc = NULL; | 1745 | ep->desc = NULL; |
1746 | ep->ep.desc = NULL; | ||
1496 | INIT_LIST_HEAD(&ep->queue); | 1747 | INIT_LIST_HEAD(&ep->queue); |
1497 | spin_unlock_irqrestore(&ep->dev->lock, iflags); | 1748 | spin_unlock_irqrestore(&ep->dev->lock, iflags); |
1498 | return 0; | 1749 | return 0; |
@@ -2335,8 +2586,11 @@ static void pch_udc_svc_ur_interrupt(struct pch_udc_dev *dev) | |||
2335 | /* Complete request queue */ | 2586 | /* Complete request queue */ |
2336 | empty_req_queue(ep); | 2587 | empty_req_queue(ep); |
2337 | } | 2588 | } |
2338 | if (dev->driver && dev->driver->disconnect) | 2589 | if (dev->driver && dev->driver->disconnect) { |
2590 | spin_unlock(&dev->lock); | ||
2339 | dev->driver->disconnect(&dev->gadget); | 2591 | dev->driver->disconnect(&dev->gadget); |
2592 | spin_lock(&dev->lock); | ||
2593 | } | ||
2340 | } | 2594 | } |
2341 | 2595 | ||
2342 | /** | 2596 | /** |
@@ -2371,6 +2625,11 @@ static void pch_udc_svc_enum_interrupt(struct pch_udc_dev *dev) | |||
2371 | pch_udc_set_dma(dev, DMA_DIR_TX); | 2625 | pch_udc_set_dma(dev, DMA_DIR_TX); |
2372 | pch_udc_set_dma(dev, DMA_DIR_RX); | 2626 | pch_udc_set_dma(dev, DMA_DIR_RX); |
2373 | pch_udc_ep_set_rrdy(&(dev->ep[UDC_EP0OUT_IDX])); | 2627 | pch_udc_ep_set_rrdy(&(dev->ep[UDC_EP0OUT_IDX])); |
2628 | |||
2629 | /* enable device interrupts */ | ||
2630 | pch_udc_enable_interrupts(dev, UDC_DEVINT_UR | UDC_DEVINT_US | | ||
2631 | UDC_DEVINT_ES | UDC_DEVINT_ENUM | | ||
2632 | UDC_DEVINT_SI | UDC_DEVINT_SC); | ||
2374 | } | 2633 | } |
2375 | 2634 | ||
2376 | /** | 2635 | /** |
@@ -2459,12 +2718,18 @@ static void pch_udc_svc_cfg_interrupt(struct pch_udc_dev *dev) | |||
2459 | */ | 2718 | */ |
2460 | static void pch_udc_dev_isr(struct pch_udc_dev *dev, u32 dev_intr) | 2719 | static void pch_udc_dev_isr(struct pch_udc_dev *dev, u32 dev_intr) |
2461 | { | 2720 | { |
2721 | int vbus; | ||
2722 | |||
2462 | /* USB Reset Interrupt */ | 2723 | /* USB Reset Interrupt */ |
2463 | if (dev_intr & UDC_DEVINT_UR) | 2724 | if (dev_intr & UDC_DEVINT_UR) { |
2464 | pch_udc_svc_ur_interrupt(dev); | 2725 | pch_udc_svc_ur_interrupt(dev); |
2726 | dev_dbg(&dev->pdev->dev, "USB_RESET\n"); | ||
2727 | } | ||
2465 | /* Enumeration Done Interrupt */ | 2728 | /* Enumeration Done Interrupt */ |
2466 | if (dev_intr & UDC_DEVINT_ENUM) | 2729 | if (dev_intr & UDC_DEVINT_ENUM) { |
2467 | pch_udc_svc_enum_interrupt(dev); | 2730 | pch_udc_svc_enum_interrupt(dev); |
2731 | dev_dbg(&dev->pdev->dev, "USB_ENUM\n"); | ||
2732 | } | ||
2468 | /* Set Interface Interrupt */ | 2733 | /* Set Interface Interrupt */ |
2469 | if (dev_intr & UDC_DEVINT_SI) | 2734 | if (dev_intr & UDC_DEVINT_SI) |
2470 | pch_udc_svc_intf_interrupt(dev); | 2735 | pch_udc_svc_intf_interrupt(dev); |
@@ -2472,8 +2737,30 @@ static void pch_udc_dev_isr(struct pch_udc_dev *dev, u32 dev_intr) | |||
2472 | if (dev_intr & UDC_DEVINT_SC) | 2737 | if (dev_intr & UDC_DEVINT_SC) |
2473 | pch_udc_svc_cfg_interrupt(dev); | 2738 | pch_udc_svc_cfg_interrupt(dev); |
2474 | /* USB Suspend interrupt */ | 2739 | /* USB Suspend interrupt */ |
2475 | if (dev_intr & UDC_DEVINT_US) | 2740 | if (dev_intr & UDC_DEVINT_US) { |
2741 | if (dev->driver | ||
2742 | && dev->driver->suspend) { | ||
2743 | spin_unlock(&dev->lock); | ||
2744 | dev->driver->suspend(&dev->gadget); | ||
2745 | spin_lock(&dev->lock); | ||
2746 | } | ||
2747 | |||
2748 | vbus = pch_vbus_gpio_get_value(dev); | ||
2749 | if ((dev->vbus_session == 0) | ||
2750 | && (vbus != 1)) { | ||
2751 | if (dev->driver && dev->driver->disconnect) { | ||
2752 | spin_unlock(&dev->lock); | ||
2753 | dev->driver->disconnect(&dev->gadget); | ||
2754 | spin_lock(&dev->lock); | ||
2755 | } | ||
2756 | pch_udc_reconnect(dev); | ||
2757 | } else if ((dev->vbus_session == 0) | ||
2758 | && (vbus == 1) | ||
2759 | && !dev->vbus_gpio.intr) | ||
2760 | schedule_work(&dev->vbus_gpio.irq_work_fall); | ||
2761 | |||
2476 | dev_dbg(&dev->pdev->dev, "USB_SUSPEND\n"); | 2762 | dev_dbg(&dev->pdev->dev, "USB_SUSPEND\n"); |
2763 | } | ||
2477 | /* Clear the SOF interrupt, if enabled */ | 2764 | /* Clear the SOF interrupt, if enabled */ |
2478 | if (dev_intr & UDC_DEVINT_SOF) | 2765 | if (dev_intr & UDC_DEVINT_SOF) |
2479 | dev_dbg(&dev->pdev->dev, "SOF\n"); | 2766 | dev_dbg(&dev->pdev->dev, "SOF\n"); |
@@ -2499,6 +2786,14 @@ static irqreturn_t pch_udc_isr(int irq, void *pdev) | |||
2499 | dev_intr = pch_udc_read_device_interrupts(dev); | 2786 | dev_intr = pch_udc_read_device_interrupts(dev); |
2500 | ep_intr = pch_udc_read_ep_interrupts(dev); | 2787 | ep_intr = pch_udc_read_ep_interrupts(dev); |
2501 | 2788 | ||
2789 | /* For a hot plug, this find that the controller is hung up. */ | ||
2790 | if (dev_intr == ep_intr) | ||
2791 | if (dev_intr == pch_udc_readl(dev, UDC_DEVCFG_ADDR)) { | ||
2792 | dev_dbg(&dev->pdev->dev, "UDC: Hung up\n"); | ||
2793 | /* The controller is reset */ | ||
2794 | pch_udc_writel(dev, UDC_SRST, UDC_SRST_ADDR); | ||
2795 | return IRQ_HANDLED; | ||
2796 | } | ||
2502 | if (dev_intr) | 2797 | if (dev_intr) |
2503 | /* Clear device interrupts */ | 2798 | /* Clear device interrupts */ |
2504 | pch_udc_write_device_interrupts(dev, dev_intr); | 2799 | pch_udc_write_device_interrupts(dev, dev_intr); |
@@ -2625,6 +2920,7 @@ static int pch_udc_pcd_init(struct pch_udc_dev *dev) | |||
2625 | { | 2920 | { |
2626 | pch_udc_init(dev); | 2921 | pch_udc_init(dev); |
2627 | pch_udc_pcd_reinit(dev); | 2922 | pch_udc_pcd_reinit(dev); |
2923 | pch_vbus_gpio_init(dev, vbus_gpio_port); | ||
2628 | return 0; | 2924 | return 0; |
2629 | } | 2925 | } |
2630 | 2926 | ||
@@ -2725,7 +3021,8 @@ static int pch_udc_start(struct usb_gadget_driver *driver, | |||
2725 | pch_udc_setup_ep0(dev); | 3021 | pch_udc_setup_ep0(dev); |
2726 | 3022 | ||
2727 | /* clear SD */ | 3023 | /* clear SD */ |
2728 | pch_udc_clear_disconnect(dev); | 3024 | if ((pch_vbus_gpio_get_value(dev) != 0) || !dev->vbus_gpio.intr) |
3025 | pch_udc_clear_disconnect(dev); | ||
2729 | 3026 | ||
2730 | dev->connected = 1; | 3027 | dev->connected = 1; |
2731 | return 0; | 3028 | return 0; |
@@ -2803,6 +3100,8 @@ static void pch_udc_remove(struct pci_dev *pdev) | |||
2803 | UDC_EP0OUT_BUFF_SIZE * 4, DMA_FROM_DEVICE); | 3100 | UDC_EP0OUT_BUFF_SIZE * 4, DMA_FROM_DEVICE); |
2804 | kfree(dev->ep0out_buf); | 3101 | kfree(dev->ep0out_buf); |
2805 | 3102 | ||
3103 | pch_vbus_gpio_free(dev); | ||
3104 | |||
2806 | pch_udc_exit(dev); | 3105 | pch_udc_exit(dev); |
2807 | 3106 | ||
2808 | if (dev->irq_registered) | 3107 | if (dev->irq_registered) |
@@ -2912,8 +3211,10 @@ static int pch_udc_probe(struct pci_dev *pdev, | |||
2912 | } | 3211 | } |
2913 | pch_udc = dev; | 3212 | pch_udc = dev; |
2914 | /* initialize the hardware */ | 3213 | /* initialize the hardware */ |
2915 | if (pch_udc_pcd_init(dev)) | 3214 | if (pch_udc_pcd_init(dev)) { |
3215 | retval = -ENODEV; | ||
2916 | goto finished; | 3216 | goto finished; |
3217 | } | ||
2917 | if (request_irq(pdev->irq, pch_udc_isr, IRQF_SHARED, KBUILD_MODNAME, | 3218 | if (request_irq(pdev->irq, pch_udc_isr, IRQF_SHARED, KBUILD_MODNAME, |
2918 | dev)) { | 3219 | dev)) { |
2919 | dev_err(&pdev->dev, "%s: request_irq(%d) fail\n", __func__, | 3220 | dev_err(&pdev->dev, "%s: request_irq(%d) fail\n", __func__, |