diff options
Diffstat (limited to 'drivers/usb/host/isp116x-hcd.c')
-rw-r--r-- | drivers/usb/host/isp116x-hcd.c | 422 |
1 files changed, 170 insertions, 252 deletions
diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c index 82f64986bc22..584b8dc65119 100644 --- a/drivers/usb/host/isp116x-hcd.c +++ b/drivers/usb/host/isp116x-hcd.c | |||
@@ -55,19 +55,13 @@ | |||
55 | /* enqueuing/finishing log of urbs */ | 55 | /* enqueuing/finishing log of urbs */ |
56 | //#define URB_TRACE | 56 | //#define URB_TRACE |
57 | 57 | ||
58 | #include <linux/config.h> | ||
59 | #include <linux/module.h> | 58 | #include <linux/module.h> |
60 | #include <linux/moduleparam.h> | ||
61 | #include <linux/kernel.h> | ||
62 | #include <linux/delay.h> | 59 | #include <linux/delay.h> |
63 | #include <linux/ioport.h> | 60 | #include <linux/debugfs.h> |
64 | #include <linux/sched.h> | 61 | #include <linux/seq_file.h> |
65 | #include <linux/slab.h> | ||
66 | #include <linux/smp_lock.h> | ||
67 | #include <linux/errno.h> | 62 | #include <linux/errno.h> |
68 | #include <linux/init.h> | 63 | #include <linux/init.h> |
69 | #include <linux/list.h> | 64 | #include <linux/list.h> |
70 | #include <linux/interrupt.h> | ||
71 | #include <linux/usb.h> | 65 | #include <linux/usb.h> |
72 | #include <linux/usb_isp116x.h> | 66 | #include <linux/usb_isp116x.h> |
73 | #include <linux/platform_device.h> | 67 | #include <linux/platform_device.h> |
@@ -77,14 +71,10 @@ | |||
77 | #include <asm/system.h> | 71 | #include <asm/system.h> |
78 | #include <asm/byteorder.h> | 72 | #include <asm/byteorder.h> |
79 | 73 | ||
80 | #ifndef DEBUG | ||
81 | # define STUB_DEBUG_FILE | ||
82 | #endif | ||
83 | |||
84 | #include "../core/hcd.h" | 74 | #include "../core/hcd.h" |
85 | #include "isp116x.h" | 75 | #include "isp116x.h" |
86 | 76 | ||
87 | #define DRIVER_VERSION "05 Aug 2005" | 77 | #define DRIVER_VERSION "03 Nov 2005" |
88 | #define DRIVER_DESC "ISP116x USB Host Controller Driver" | 78 | #define DRIVER_DESC "ISP116x USB Host Controller Driver" |
89 | 79 | ||
90 | MODULE_DESCRIPTION(DRIVER_DESC); | 80 | MODULE_DESCRIPTION(DRIVER_DESC); |
@@ -164,13 +154,11 @@ static void pack_fifo(struct isp116x *isp116x) | |||
164 | struct ptd *ptd; | 154 | struct ptd *ptd; |
165 | int buflen = isp116x->atl_last_dir == PTD_DIR_IN | 155 | int buflen = isp116x->atl_last_dir == PTD_DIR_IN |
166 | ? isp116x->atl_bufshrt : isp116x->atl_buflen; | 156 | ? isp116x->atl_bufshrt : isp116x->atl_buflen; |
167 | int ptd_count = 0; | ||
168 | 157 | ||
169 | isp116x_write_reg16(isp116x, HCuPINT, HCuPINT_AIIEOT); | 158 | isp116x_write_reg16(isp116x, HCuPINT, HCuPINT_AIIEOT); |
170 | isp116x_write_reg16(isp116x, HCXFERCTR, buflen); | 159 | isp116x_write_reg16(isp116x, HCXFERCTR, buflen); |
171 | isp116x_write_addr(isp116x, HCATLPORT | ISP116x_WRITE_OFFSET); | 160 | isp116x_write_addr(isp116x, HCATLPORT | ISP116x_WRITE_OFFSET); |
172 | for (ep = isp116x->atl_active; ep; ep = ep->active) { | 161 | for (ep = isp116x->atl_active; ep; ep = ep->active) { |
173 | ++ptd_count; | ||
174 | ptd = &ep->ptd; | 162 | ptd = &ep->ptd; |
175 | dump_ptd(ptd); | 163 | dump_ptd(ptd); |
176 | dump_ptd_out_data(ptd, ep->data); | 164 | dump_ptd_out_data(ptd, ep->data); |
@@ -305,9 +293,8 @@ static void postproc_atl_queue(struct isp116x *isp116x) | |||
305 | udev = urb->dev; | 293 | udev = urb->dev; |
306 | ptd = &ep->ptd; | 294 | ptd = &ep->ptd; |
307 | cc = PTD_GET_CC(ptd); | 295 | cc = PTD_GET_CC(ptd); |
308 | |||
309 | spin_lock(&urb->lock); | ||
310 | short_not_ok = 1; | 296 | short_not_ok = 1; |
297 | spin_lock(&urb->lock); | ||
311 | 298 | ||
312 | /* Data underrun is special. For allowed underrun | 299 | /* Data underrun is special. For allowed underrun |
313 | we clear the error and continue as normal. For | 300 | we clear the error and continue as normal. For |
@@ -420,7 +407,7 @@ static void postproc_atl_queue(struct isp116x *isp116x) | |||
420 | ep->nextpid = 0; | 407 | ep->nextpid = 0; |
421 | break; | 408 | break; |
422 | default: | 409 | default: |
423 | BUG_ON(1); | 410 | BUG(); |
424 | } | 411 | } |
425 | spin_unlock(&urb->lock); | 412 | spin_unlock(&urb->lock); |
426 | } | 413 | } |
@@ -628,8 +615,12 @@ static irqreturn_t isp116x_irq(struct usb_hcd *hcd, struct pt_regs *regs) | |||
628 | u32 intstat = isp116x_read_reg32(isp116x, HCINTSTAT); | 615 | u32 intstat = isp116x_read_reg32(isp116x, HCINTSTAT); |
629 | isp116x_write_reg32(isp116x, HCINTSTAT, intstat); | 616 | isp116x_write_reg32(isp116x, HCINTSTAT, intstat); |
630 | if (intstat & HCINT_UE) { | 617 | if (intstat & HCINT_UE) { |
631 | ERR("Unrecoverable error\n"); | 618 | ERR("Unrecoverable error, HC is dead!\n"); |
632 | /* What should we do here? Reset? */ | 619 | /* IRQ's are off, we do no DMA, |
620 | perfectly ready to die ... */ | ||
621 | hcd->state = HC_STATE_HALT; | ||
622 | ret = IRQ_HANDLED; | ||
623 | goto done; | ||
633 | } | 624 | } |
634 | if (intstat & HCINT_RHSC) | 625 | if (intstat & HCINT_RHSC) |
635 | /* When root hub or any of its ports is going | 626 | /* When root hub or any of its ports is going |
@@ -640,7 +631,6 @@ static irqreturn_t isp116x_irq(struct usb_hcd *hcd, struct pt_regs *regs) | |||
640 | if (intstat & HCINT_RD) { | 631 | if (intstat & HCINT_RD) { |
641 | DBG("---- remote wakeup\n"); | 632 | DBG("---- remote wakeup\n"); |
642 | usb_hcd_resume_root_hub(hcd); | 633 | usb_hcd_resume_root_hub(hcd); |
643 | ret = IRQ_HANDLED; | ||
644 | } | 634 | } |
645 | irqstat &= ~HCuPINT_OPR; | 635 | irqstat &= ~HCuPINT_OPR; |
646 | ret = IRQ_HANDLED; | 636 | ret = IRQ_HANDLED; |
@@ -651,6 +641,7 @@ static irqreturn_t isp116x_irq(struct usb_hcd *hcd, struct pt_regs *regs) | |||
651 | } | 641 | } |
652 | 642 | ||
653 | isp116x_write_reg16(isp116x, HCuPINTENB, isp116x->irqenb); | 643 | isp116x_write_reg16(isp116x, HCuPINTENB, isp116x->irqenb); |
644 | done: | ||
654 | spin_unlock(&isp116x->lock); | 645 | spin_unlock(&isp116x->lock); |
655 | return ret; | 646 | return ret; |
656 | } | 647 | } |
@@ -724,6 +715,7 @@ static int isp116x_urb_enqueue(struct usb_hcd *hcd, | |||
724 | 715 | ||
725 | spin_lock_irqsave(&isp116x->lock, flags); | 716 | spin_lock_irqsave(&isp116x->lock, flags); |
726 | if (!HC_IS_RUNNING(hcd->state)) { | 717 | if (!HC_IS_RUNNING(hcd->state)) { |
718 | kfree(ep); | ||
727 | ret = -ENODEV; | 719 | ret = -ENODEV; |
728 | goto fail; | 720 | goto fail; |
729 | } | 721 | } |
@@ -888,7 +880,7 @@ static void isp116x_endpoint_disable(struct usb_hcd *hcd, | |||
888 | struct usb_host_endpoint *hep) | 880 | struct usb_host_endpoint *hep) |
889 | { | 881 | { |
890 | int i; | 882 | int i; |
891 | struct isp116x_ep *ep = hep->hcpriv;; | 883 | struct isp116x_ep *ep = hep->hcpriv; |
892 | 884 | ||
893 | if (!ep) | 885 | if (!ep) |
894 | return; | 886 | return; |
@@ -916,8 +908,6 @@ static int isp116x_get_frame(struct usb_hcd *hcd) | |||
916 | return (int)fmnum; | 908 | return (int)fmnum; |
917 | } | 909 | } |
918 | 910 | ||
919 | /*----------------------------------------------------------------*/ | ||
920 | |||
921 | /* | 911 | /* |
922 | Adapted from ohci-hub.c. Currently we don't support autosuspend. | 912 | Adapted from ohci-hub.c. Currently we don't support autosuspend. |
923 | */ | 913 | */ |
@@ -968,11 +958,10 @@ static void isp116x_hub_descriptor(struct isp116x *isp116x, | |||
968 | desc->bHubContrCurrent = 0; | 958 | desc->bHubContrCurrent = 0; |
969 | desc->bNbrPorts = (u8) (reg & 0x3); | 959 | desc->bNbrPorts = (u8) (reg & 0x3); |
970 | /* Power switching, device type, overcurrent. */ | 960 | /* Power switching, device type, overcurrent. */ |
971 | desc->wHubCharacteristics = | 961 | desc->wHubCharacteristics = cpu_to_le16((u16) ((reg >> 8) & 0x1f)); |
972 | (__force __u16) cpu_to_le16((u16) ((reg >> 8) & 0x1f)); | ||
973 | desc->bPwrOn2PwrGood = (u8) ((reg >> 24) & 0xff); | 962 | desc->bPwrOn2PwrGood = (u8) ((reg >> 24) & 0xff); |
974 | /* two bitmaps: ports removable, and legacy PortPwrCtrlMask */ | 963 | /* two bitmaps: ports removable, and legacy PortPwrCtrlMask */ |
975 | desc->bitmap[0] = desc->bNbrPorts == 1 ? 1 << 1 : 3 << 1; | 964 | desc->bitmap[0] = 0; |
976 | desc->bitmap[1] = ~0; | 965 | desc->bitmap[1] = ~0; |
977 | } | 966 | } |
978 | 967 | ||
@@ -1159,135 +1148,9 @@ static int isp116x_hub_control(struct usb_hcd *hcd, | |||
1159 | return ret; | 1148 | return ret; |
1160 | } | 1149 | } |
1161 | 1150 | ||
1162 | #ifdef CONFIG_PM | ||
1163 | |||
1164 | static int isp116x_bus_suspend(struct usb_hcd *hcd) | ||
1165 | { | ||
1166 | struct isp116x *isp116x = hcd_to_isp116x(hcd); | ||
1167 | unsigned long flags; | ||
1168 | u32 val; | ||
1169 | int ret = 0; | ||
1170 | |||
1171 | spin_lock_irqsave(&isp116x->lock, flags); | ||
1172 | |||
1173 | val = isp116x_read_reg32(isp116x, HCCONTROL); | ||
1174 | switch (val & HCCONTROL_HCFS) { | ||
1175 | case HCCONTROL_USB_OPER: | ||
1176 | hcd->state = HC_STATE_QUIESCING; | ||
1177 | val &= (~HCCONTROL_HCFS & ~HCCONTROL_RWE); | ||
1178 | val |= HCCONTROL_USB_SUSPEND; | ||
1179 | if (hcd->remote_wakeup) | ||
1180 | val |= HCCONTROL_RWE; | ||
1181 | /* Wait for usb transfers to finish */ | ||
1182 | mdelay(2); | ||
1183 | isp116x_write_reg32(isp116x, HCCONTROL, val); | ||
1184 | hcd->state = HC_STATE_SUSPENDED; | ||
1185 | /* Wait for devices to suspend */ | ||
1186 | mdelay(5); | ||
1187 | case HCCONTROL_USB_SUSPEND: | ||
1188 | break; | ||
1189 | case HCCONTROL_USB_RESUME: | ||
1190 | isp116x_write_reg32(isp116x, HCCONTROL, | ||
1191 | (val & ~HCCONTROL_HCFS) | | ||
1192 | HCCONTROL_USB_RESET); | ||
1193 | case HCCONTROL_USB_RESET: | ||
1194 | ret = -EBUSY; | ||
1195 | break; | ||
1196 | default: | ||
1197 | ret = -EINVAL; | ||
1198 | } | ||
1199 | |||
1200 | spin_unlock_irqrestore(&isp116x->lock, flags); | ||
1201 | return ret; | ||
1202 | } | ||
1203 | |||
1204 | static int isp116x_bus_resume(struct usb_hcd *hcd) | ||
1205 | { | ||
1206 | struct isp116x *isp116x = hcd_to_isp116x(hcd); | ||
1207 | u32 val; | ||
1208 | int ret = -EINPROGRESS; | ||
1209 | |||
1210 | msleep(5); | ||
1211 | spin_lock_irq(&isp116x->lock); | ||
1212 | |||
1213 | val = isp116x_read_reg32(isp116x, HCCONTROL); | ||
1214 | switch (val & HCCONTROL_HCFS) { | ||
1215 | case HCCONTROL_USB_SUSPEND: | ||
1216 | val &= ~HCCONTROL_HCFS; | ||
1217 | val |= HCCONTROL_USB_RESUME; | ||
1218 | isp116x_write_reg32(isp116x, HCCONTROL, val); | ||
1219 | case HCCONTROL_USB_RESUME: | ||
1220 | break; | ||
1221 | case HCCONTROL_USB_OPER: | ||
1222 | /* Without setting power_state here the | ||
1223 | SUSPENDED state won't be removed from | ||
1224 | sysfs/usbN/power.state as a response to remote | ||
1225 | wakeup. Maybe in the future. */ | ||
1226 | hcd->self.root_hub->dev.power.power_state = PMSG_ON; | ||
1227 | ret = 0; | ||
1228 | break; | ||
1229 | default: | ||
1230 | ret = -EBUSY; | ||
1231 | } | ||
1232 | |||
1233 | if (ret != -EINPROGRESS) { | ||
1234 | spin_unlock_irq(&isp116x->lock); | ||
1235 | return ret; | ||
1236 | } | ||
1237 | |||
1238 | val = isp116x->rhdesca & RH_A_NDP; | ||
1239 | while (val--) { | ||
1240 | u32 stat = | ||
1241 | isp116x_read_reg32(isp116x, val ? HCRHPORT2 : HCRHPORT1); | ||
1242 | /* force global, not selective, resume */ | ||
1243 | if (!(stat & RH_PS_PSS)) | ||
1244 | continue; | ||
1245 | DBG("%s: Resuming port %d\n", __func__, val); | ||
1246 | isp116x_write_reg32(isp116x, RH_PS_POCI, val | ||
1247 | ? HCRHPORT2 : HCRHPORT1); | ||
1248 | } | ||
1249 | spin_unlock_irq(&isp116x->lock); | ||
1250 | |||
1251 | hcd->state = HC_STATE_RESUMING; | ||
1252 | mdelay(20); | ||
1253 | |||
1254 | /* Go operational */ | ||
1255 | spin_lock_irq(&isp116x->lock); | ||
1256 | val = isp116x_read_reg32(isp116x, HCCONTROL); | ||
1257 | isp116x_write_reg32(isp116x, HCCONTROL, | ||
1258 | (val & ~HCCONTROL_HCFS) | HCCONTROL_USB_OPER); | ||
1259 | spin_unlock_irq(&isp116x->lock); | ||
1260 | /* see analogous comment above */ | ||
1261 | hcd->self.root_hub->dev.power.power_state = PMSG_ON; | ||
1262 | hcd->state = HC_STATE_RUNNING; | ||
1263 | |||
1264 | return 0; | ||
1265 | } | ||
1266 | |||
1267 | |||
1268 | #else | ||
1269 | |||
1270 | #define isp116x_bus_suspend NULL | ||
1271 | #define isp116x_bus_resume NULL | ||
1272 | |||
1273 | #endif | ||
1274 | |||
1275 | /*-----------------------------------------------------------------*/ | 1151 | /*-----------------------------------------------------------------*/ |
1276 | 1152 | ||
1277 | #ifdef STUB_DEBUG_FILE | 1153 | #ifdef CONFIG_DEBUG_FS |
1278 | |||
1279 | static inline void create_debug_file(struct isp116x *isp116x) | ||
1280 | { | ||
1281 | } | ||
1282 | |||
1283 | static inline void remove_debug_file(struct isp116x *isp116x) | ||
1284 | { | ||
1285 | } | ||
1286 | |||
1287 | #else | ||
1288 | |||
1289 | #include <linux/proc_fs.h> | ||
1290 | #include <linux/seq_file.h> | ||
1291 | 1154 | ||
1292 | static void dump_irq(struct seq_file *s, char *label, u16 mask) | 1155 | static void dump_irq(struct seq_file *s, char *label, u16 mask) |
1293 | { | 1156 | { |
@@ -1311,13 +1174,9 @@ static void dump_int(struct seq_file *s, char *label, u32 mask) | |||
1311 | mask & HCINT_SF ? " sof" : "", mask & HCINT_SO ? " so" : ""); | 1174 | mask & HCINT_SF ? " sof" : "", mask & HCINT_SO ? " so" : ""); |
1312 | } | 1175 | } |
1313 | 1176 | ||
1314 | static int proc_isp116x_show(struct seq_file *s, void *unused) | 1177 | static int isp116x_show_dbg(struct seq_file *s, void *unused) |
1315 | { | 1178 | { |
1316 | struct isp116x *isp116x = s->private; | 1179 | struct isp116x *isp116x = s->private; |
1317 | struct isp116x_ep *ep; | ||
1318 | struct urb *urb; | ||
1319 | unsigned i; | ||
1320 | char *str; | ||
1321 | 1180 | ||
1322 | seq_printf(s, "%s\n%s version %s\n", | 1181 | seq_printf(s, "%s\n%s version %s\n", |
1323 | isp116x_to_hcd(isp116x)->product_desc, hcd_name, | 1182 | isp116x_to_hcd(isp116x)->product_desc, hcd_name, |
@@ -1333,105 +1192,50 @@ static int proc_isp116x_show(struct seq_file *s, void *unused) | |||
1333 | } | 1192 | } |
1334 | 1193 | ||
1335 | spin_lock_irq(&isp116x->lock); | 1194 | spin_lock_irq(&isp116x->lock); |
1336 | |||
1337 | dump_irq(s, "hc_irq_enable", isp116x_read_reg16(isp116x, HCuPINTENB)); | 1195 | dump_irq(s, "hc_irq_enable", isp116x_read_reg16(isp116x, HCuPINTENB)); |
1338 | dump_irq(s, "hc_irq_status", isp116x_read_reg16(isp116x, HCuPINT)); | 1196 | dump_irq(s, "hc_irq_status", isp116x_read_reg16(isp116x, HCuPINT)); |
1339 | dump_int(s, "hc_int_enable", isp116x_read_reg32(isp116x, HCINTENB)); | 1197 | dump_int(s, "hc_int_enable", isp116x_read_reg32(isp116x, HCINTENB)); |
1340 | dump_int(s, "hc_int_status", isp116x_read_reg32(isp116x, HCINTSTAT)); | 1198 | dump_int(s, "hc_int_status", isp116x_read_reg32(isp116x, HCINTSTAT)); |
1341 | 1199 | isp116x_show_regs_seq(isp116x, s); | |
1342 | list_for_each_entry(ep, &isp116x->async, schedule) { | ||
1343 | |||
1344 | switch (ep->nextpid) { | ||
1345 | case USB_PID_IN: | ||
1346 | str = "in"; | ||
1347 | break; | ||
1348 | case USB_PID_OUT: | ||
1349 | str = "out"; | ||
1350 | break; | ||
1351 | case USB_PID_SETUP: | ||
1352 | str = "setup"; | ||
1353 | break; | ||
1354 | case USB_PID_ACK: | ||
1355 | str = "status"; | ||
1356 | break; | ||
1357 | default: | ||
1358 | str = "?"; | ||
1359 | break; | ||
1360 | }; | ||
1361 | seq_printf(s, "%p, ep%d%s, maxpacket %d:\n", ep, | ||
1362 | ep->epnum, str, ep->maxpacket); | ||
1363 | list_for_each_entry(urb, &ep->hep->urb_list, urb_list) { | ||
1364 | seq_printf(s, " urb%p, %d/%d\n", urb, | ||
1365 | urb->actual_length, | ||
1366 | urb->transfer_buffer_length); | ||
1367 | } | ||
1368 | } | ||
1369 | if (!list_empty(&isp116x->async)) | ||
1370 | seq_printf(s, "\n"); | ||
1371 | |||
1372 | seq_printf(s, "periodic size= %d\n", PERIODIC_SIZE); | ||
1373 | |||
1374 | for (i = 0; i < PERIODIC_SIZE; i++) { | ||
1375 | ep = isp116x->periodic[i]; | ||
1376 | if (!ep) | ||
1377 | continue; | ||
1378 | seq_printf(s, "%2d [%3d]:\n", i, isp116x->load[i]); | ||
1379 | |||
1380 | /* DUMB: prints shared entries multiple times */ | ||
1381 | do { | ||
1382 | seq_printf(s, " %d/%p (%sdev%d ep%d%s max %d)\n", | ||
1383 | ep->period, ep, | ||
1384 | (ep->udev->speed == | ||
1385 | USB_SPEED_FULL) ? "" : "ls ", | ||
1386 | ep->udev->devnum, ep->epnum, | ||
1387 | (ep->epnum == | ||
1388 | 0) ? "" : ((ep->nextpid == | ||
1389 | USB_PID_IN) ? "in" : "out"), | ||
1390 | ep->maxpacket); | ||
1391 | ep = ep->next; | ||
1392 | } while (ep); | ||
1393 | } | ||
1394 | spin_unlock_irq(&isp116x->lock); | 1200 | spin_unlock_irq(&isp116x->lock); |
1395 | seq_printf(s, "\n"); | 1201 | seq_printf(s, "\n"); |
1396 | 1202 | ||
1397 | return 0; | 1203 | return 0; |
1398 | } | 1204 | } |
1399 | 1205 | ||
1400 | static int proc_isp116x_open(struct inode *inode, struct file *file) | 1206 | static int isp116x_open_seq(struct inode *inode, struct file *file) |
1401 | { | 1207 | { |
1402 | return single_open(file, proc_isp116x_show, PDE(inode)->data); | 1208 | return single_open(file, isp116x_show_dbg, inode->u.generic_ip); |
1403 | } | 1209 | } |
1404 | 1210 | ||
1405 | static struct file_operations proc_ops = { | 1211 | static struct file_operations isp116x_debug_fops = { |
1406 | .open = proc_isp116x_open, | 1212 | .open = isp116x_open_seq, |
1407 | .read = seq_read, | 1213 | .read = seq_read, |
1408 | .llseek = seq_lseek, | 1214 | .llseek = seq_lseek, |
1409 | .release = single_release, | 1215 | .release = single_release, |
1410 | }; | 1216 | }; |
1411 | 1217 | ||
1412 | /* expect just one isp116x per system */ | 1218 | static int create_debug_file(struct isp116x *isp116x) |
1413 | static const char proc_filename[] = "driver/isp116x"; | ||
1414 | |||
1415 | static void create_debug_file(struct isp116x *isp116x) | ||
1416 | { | 1219 | { |
1417 | struct proc_dir_entry *pde; | 1220 | isp116x->dentry = debugfs_create_file(hcd_name, |
1418 | 1221 | S_IRUGO, NULL, isp116x, | |
1419 | pde = create_proc_entry(proc_filename, 0, NULL); | 1222 | &isp116x_debug_fops); |
1420 | if (pde == NULL) | 1223 | if (!isp116x->dentry) |
1421 | return; | 1224 | return -ENOMEM; |
1422 | 1225 | return 0; | |
1423 | pde->proc_fops = &proc_ops; | ||
1424 | pde->data = isp116x; | ||
1425 | isp116x->pde = pde; | ||
1426 | } | 1226 | } |
1427 | 1227 | ||
1428 | static void remove_debug_file(struct isp116x *isp116x) | 1228 | static void remove_debug_file(struct isp116x *isp116x) |
1429 | { | 1229 | { |
1430 | if (isp116x->pde) | 1230 | debugfs_remove(isp116x->dentry); |
1431 | remove_proc_entry(proc_filename, NULL); | ||
1432 | } | 1231 | } |
1433 | 1232 | ||
1434 | #endif | 1233 | #else |
1234 | |||
1235 | #define create_debug_file(d) 0 | ||
1236 | #define remove_debug_file(d) do{}while(0) | ||
1237 | |||
1238 | #endif /* CONFIG_DEBUG_FS */ | ||
1435 | 1239 | ||
1436 | /*-----------------------------------------------------------------*/ | 1240 | /*-----------------------------------------------------------------*/ |
1437 | 1241 | ||
@@ -1466,7 +1270,7 @@ static int isp116x_reset(struct usb_hcd *hcd) | |||
1466 | struct isp116x *isp116x = hcd_to_isp116x(hcd); | 1270 | struct isp116x *isp116x = hcd_to_isp116x(hcd); |
1467 | unsigned long t; | 1271 | unsigned long t; |
1468 | u16 clkrdy = 0; | 1272 | u16 clkrdy = 0; |
1469 | int ret = 0, timeout = 15 /* ms */ ; | 1273 | int ret, timeout = 15 /* ms */ ; |
1470 | 1274 | ||
1471 | ret = isp116x_sw_reset(isp116x); | 1275 | ret = isp116x_sw_reset(isp116x); |
1472 | if (ret) | 1276 | if (ret) |
@@ -1482,7 +1286,7 @@ static int isp116x_reset(struct usb_hcd *hcd) | |||
1482 | break; | 1286 | break; |
1483 | } | 1287 | } |
1484 | if (!clkrdy) { | 1288 | if (!clkrdy) { |
1485 | ERR("Clock not ready after 20ms\n"); | 1289 | ERR("Clock not ready after %dms\n", timeout); |
1486 | /* After sw_reset the clock won't report to be ready, if | 1290 | /* After sw_reset the clock won't report to be ready, if |
1487 | H_WAKEUP pin is high. */ | 1291 | H_WAKEUP pin is high. */ |
1488 | ERR("Please make sure that the H_WAKEUP pin is pulled low!\n"); | 1292 | ERR("Please make sure that the H_WAKEUP pin is pulled low!\n"); |
@@ -1572,7 +1376,8 @@ static int isp116x_start(struct usb_hcd *hcd) | |||
1572 | 1376 | ||
1573 | val = 0; | 1377 | val = 0; |
1574 | if (board->remote_wakeup_enable) { | 1378 | if (board->remote_wakeup_enable) { |
1575 | hcd->can_wakeup = 1; | 1379 | if (!device_can_wakeup(hcd->self.controller)) |
1380 | device_init_wakeup(hcd->self.controller, 1); | ||
1576 | val |= RH_HS_DRWE; | 1381 | val |= RH_HS_DRWE; |
1577 | } | 1382 | } |
1578 | isp116x_write_reg32(isp116x, HCRHSTATUS, val); | 1383 | isp116x_write_reg32(isp116x, HCRHSTATUS, val); |
@@ -1600,12 +1405,126 @@ static int isp116x_start(struct usb_hcd *hcd) | |||
1600 | isp116x_write_reg32(isp116x, HCRHPORT1, RH_PS_CCS); | 1405 | isp116x_write_reg32(isp116x, HCRHPORT1, RH_PS_CCS); |
1601 | isp116x_write_reg32(isp116x, HCRHPORT2, RH_PS_CCS); | 1406 | isp116x_write_reg32(isp116x, HCRHPORT2, RH_PS_CCS); |
1602 | 1407 | ||
1603 | isp116x_show_regs(isp116x); | 1408 | isp116x_show_regs_log(isp116x); |
1604 | spin_unlock_irqrestore(&isp116x->lock, flags); | 1409 | spin_unlock_irqrestore(&isp116x->lock, flags); |
1605 | return 0; | 1410 | return 0; |
1606 | } | 1411 | } |
1607 | 1412 | ||
1608 | /*-----------------------------------------------------------------*/ | 1413 | #ifdef CONFIG_PM |
1414 | |||
1415 | static int isp116x_bus_suspend(struct usb_hcd *hcd) | ||
1416 | { | ||
1417 | struct isp116x *isp116x = hcd_to_isp116x(hcd); | ||
1418 | unsigned long flags; | ||
1419 | u32 val; | ||
1420 | int ret = 0; | ||
1421 | |||
1422 | spin_lock_irqsave(&isp116x->lock, flags); | ||
1423 | |||
1424 | val = isp116x_read_reg32(isp116x, HCCONTROL); | ||
1425 | switch (val & HCCONTROL_HCFS) { | ||
1426 | case HCCONTROL_USB_OPER: | ||
1427 | val &= (~HCCONTROL_HCFS & ~HCCONTROL_RWE); | ||
1428 | val |= HCCONTROL_USB_SUSPEND; | ||
1429 | if (device_may_wakeup(&hcd->self.root_hub->dev)) | ||
1430 | val |= HCCONTROL_RWE; | ||
1431 | /* Wait for usb transfers to finish */ | ||
1432 | mdelay(2); | ||
1433 | isp116x_write_reg32(isp116x, HCCONTROL, val); | ||
1434 | /* Wait for devices to suspend */ | ||
1435 | mdelay(5); | ||
1436 | case HCCONTROL_USB_SUSPEND: | ||
1437 | break; | ||
1438 | case HCCONTROL_USB_RESUME: | ||
1439 | isp116x_write_reg32(isp116x, HCCONTROL, | ||
1440 | (val & ~HCCONTROL_HCFS) | | ||
1441 | HCCONTROL_USB_RESET); | ||
1442 | case HCCONTROL_USB_RESET: | ||
1443 | ret = -EBUSY; | ||
1444 | break; | ||
1445 | default: | ||
1446 | ret = -EINVAL; | ||
1447 | } | ||
1448 | |||
1449 | spin_unlock_irqrestore(&isp116x->lock, flags); | ||
1450 | return ret; | ||
1451 | } | ||
1452 | |||
1453 | static int isp116x_bus_resume(struct usb_hcd *hcd) | ||
1454 | { | ||
1455 | struct isp116x *isp116x = hcd_to_isp116x(hcd); | ||
1456 | u32 val; | ||
1457 | |||
1458 | msleep(5); | ||
1459 | spin_lock_irq(&isp116x->lock); | ||
1460 | |||
1461 | val = isp116x_read_reg32(isp116x, HCCONTROL); | ||
1462 | switch (val & HCCONTROL_HCFS) { | ||
1463 | case HCCONTROL_USB_SUSPEND: | ||
1464 | val &= ~HCCONTROL_HCFS; | ||
1465 | val |= HCCONTROL_USB_RESUME; | ||
1466 | isp116x_write_reg32(isp116x, HCCONTROL, val); | ||
1467 | case HCCONTROL_USB_RESUME: | ||
1468 | break; | ||
1469 | case HCCONTROL_USB_OPER: | ||
1470 | spin_unlock_irq(&isp116x->lock); | ||
1471 | /* Without setting power_state here the | ||
1472 | SUSPENDED state won't be removed from | ||
1473 | sysfs/usbN/power.state as a response to remote | ||
1474 | wakeup. Maybe in the future. */ | ||
1475 | hcd->self.root_hub->dev.power.power_state = PMSG_ON; | ||
1476 | return 0; | ||
1477 | default: | ||
1478 | /* HCCONTROL_USB_RESET: this may happen, when during | ||
1479 | suspension the HC lost power. Reinitialize completely */ | ||
1480 | spin_unlock_irq(&isp116x->lock); | ||
1481 | DBG("Chip has been reset while suspended. Reinit from scratch.\n"); | ||
1482 | isp116x_reset(hcd); | ||
1483 | isp116x_start(hcd); | ||
1484 | isp116x_hub_control(hcd, SetPortFeature, | ||
1485 | USB_PORT_FEAT_POWER, 1, NULL, 0); | ||
1486 | if ((isp116x->rhdesca & RH_A_NDP) == 2) | ||
1487 | isp116x_hub_control(hcd, SetPortFeature, | ||
1488 | USB_PORT_FEAT_POWER, 2, NULL, 0); | ||
1489 | hcd->self.root_hub->dev.power.power_state = PMSG_ON; | ||
1490 | return 0; | ||
1491 | } | ||
1492 | |||
1493 | val = isp116x->rhdesca & RH_A_NDP; | ||
1494 | while (val--) { | ||
1495 | u32 stat = | ||
1496 | isp116x_read_reg32(isp116x, val ? HCRHPORT2 : HCRHPORT1); | ||
1497 | /* force global, not selective, resume */ | ||
1498 | if (!(stat & RH_PS_PSS)) | ||
1499 | continue; | ||
1500 | DBG("%s: Resuming port %d\n", __func__, val); | ||
1501 | isp116x_write_reg32(isp116x, RH_PS_POCI, val | ||
1502 | ? HCRHPORT2 : HCRHPORT1); | ||
1503 | } | ||
1504 | spin_unlock_irq(&isp116x->lock); | ||
1505 | |||
1506 | hcd->state = HC_STATE_RESUMING; | ||
1507 | msleep(20); | ||
1508 | |||
1509 | /* Go operational */ | ||
1510 | spin_lock_irq(&isp116x->lock); | ||
1511 | val = isp116x_read_reg32(isp116x, HCCONTROL); | ||
1512 | isp116x_write_reg32(isp116x, HCCONTROL, | ||
1513 | (val & ~HCCONTROL_HCFS) | HCCONTROL_USB_OPER); | ||
1514 | spin_unlock_irq(&isp116x->lock); | ||
1515 | /* see analogous comment above */ | ||
1516 | hcd->self.root_hub->dev.power.power_state = PMSG_ON; | ||
1517 | hcd->state = HC_STATE_RUNNING; | ||
1518 | |||
1519 | return 0; | ||
1520 | } | ||
1521 | |||
1522 | #else | ||
1523 | |||
1524 | #define isp116x_bus_suspend NULL | ||
1525 | #define isp116x_bus_resume NULL | ||
1526 | |||
1527 | #endif | ||
1609 | 1528 | ||
1610 | static struct hc_driver isp116x_hc_driver = { | 1529 | static struct hc_driver isp116x_hc_driver = { |
1611 | .description = hcd_name, | 1530 | .description = hcd_name, |
@@ -1735,12 +1654,19 @@ static int __init isp116x_probe(struct platform_device *pdev) | |||
1735 | } | 1654 | } |
1736 | 1655 | ||
1737 | ret = usb_add_hcd(hcd, irq, SA_INTERRUPT); | 1656 | ret = usb_add_hcd(hcd, irq, SA_INTERRUPT); |
1738 | if (ret != 0) | 1657 | if (ret) |
1739 | goto err6; | 1658 | goto err6; |
1740 | 1659 | ||
1741 | create_debug_file(isp116x); | 1660 | ret = create_debug_file(isp116x); |
1661 | if (ret) { | ||
1662 | ERR("Couldn't create debugfs entry\n"); | ||
1663 | goto err7; | ||
1664 | } | ||
1665 | |||
1742 | return 0; | 1666 | return 0; |
1743 | 1667 | ||
1668 | err7: | ||
1669 | usb_remove_hcd(hcd); | ||
1744 | err6: | 1670 | err6: |
1745 | usb_put_hcd(hcd); | 1671 | usb_put_hcd(hcd); |
1746 | err5: | 1672 | err5: |
@@ -1762,13 +1688,9 @@ static int __init isp116x_probe(struct platform_device *pdev) | |||
1762 | */ | 1688 | */ |
1763 | static int isp116x_suspend(struct platform_device *dev, pm_message_t state) | 1689 | static int isp116x_suspend(struct platform_device *dev, pm_message_t state) |
1764 | { | 1690 | { |
1765 | int ret = 0; | 1691 | VDBG("%s: state %x\n", __func__, state.event); |
1766 | |||
1767 | VDBG("%s: state %x\n", __func__, state); | ||
1768 | |||
1769 | dev->dev.power.power_state = state; | 1692 | dev->dev.power.power_state = state; |
1770 | 1693 | return 0; | |
1771 | return ret; | ||
1772 | } | 1694 | } |
1773 | 1695 | ||
1774 | /* | 1696 | /* |
@@ -1776,13 +1698,9 @@ static int isp116x_suspend(struct platform_device *dev, pm_message_t state) | |||
1776 | */ | 1698 | */ |
1777 | static int isp116x_resume(struct platform_device *dev) | 1699 | static int isp116x_resume(struct platform_device *dev) |
1778 | { | 1700 | { |
1779 | int ret = 0; | 1701 | VDBG("%s: state %x\n", __func__, dev->power.power_state.event); |
1780 | |||
1781 | VDBG("%s: state %x\n", __func__, dev->dev.power.power_state); | ||
1782 | |||
1783 | dev->dev.power.power_state = PMSG_ON; | 1702 | dev->dev.power.power_state = PMSG_ON; |
1784 | 1703 | return 0; | |
1785 | return ret; | ||
1786 | } | 1704 | } |
1787 | 1705 | ||
1788 | #else | 1706 | #else |