diff options
-rw-r--r-- | drivers/usb/host/u132-hcd.c | 92 | ||||
-rw-r--r-- | drivers/usb/misc/ftdi-elan.c | 592 |
2 files changed, 425 insertions, 259 deletions
diff --git a/drivers/usb/host/u132-hcd.c b/drivers/usb/host/u132-hcd.c index a9d7119e317..a7fa0d75567 100644 --- a/drivers/usb/host/u132-hcd.c +++ b/drivers/usb/host/u132-hcd.c | |||
@@ -40,6 +40,7 @@ | |||
40 | #include <linux/moduleparam.h> | 40 | #include <linux/moduleparam.h> |
41 | #include <linux/delay.h> | 41 | #include <linux/delay.h> |
42 | #include <linux/ioport.h> | 42 | #include <linux/ioport.h> |
43 | #include <linux/pci_ids.h> | ||
43 | #include <linux/sched.h> | 44 | #include <linux/sched.h> |
44 | #include <linux/slab.h> | 45 | #include <linux/slab.h> |
45 | #include <linux/smp_lock.h> | 46 | #include <linux/smp_lock.h> |
@@ -210,15 +211,16 @@ struct u132 { | |||
210 | * these cannot be inlines because we need the structure offset!! | 211 | * these cannot be inlines because we need the structure offset!! |
211 | * Does anyone have a better way????? | 212 | * Does anyone have a better way????? |
212 | */ | 213 | */ |
214 | #define ftdi_read_pcimem(pdev, member, data) usb_ftdi_elan_read_pcimem(pdev, \ | ||
215 | offsetof(struct ohci_regs, member), 0, data); | ||
216 | #define ftdi_write_pcimem(pdev, member, data) usb_ftdi_elan_write_pcimem(pdev, \ | ||
217 | offsetof(struct ohci_regs, member), 0, data); | ||
213 | #define u132_read_pcimem(u132, member, data) \ | 218 | #define u132_read_pcimem(u132, member, data) \ |
214 | usb_ftdi_elan_read_pcimem(u132->platform_dev, offsetof(struct \ | 219 | usb_ftdi_elan_read_pcimem(u132->platform_dev, offsetof(struct \ |
215 | ohci_regs, member), 0, data); | 220 | ohci_regs, member), 0, data); |
216 | #define u132_write_pcimem(u132, member, data) \ | 221 | #define u132_write_pcimem(u132, member, data) \ |
217 | usb_ftdi_elan_write_pcimem(u132->platform_dev, offsetof(struct \ | 222 | usb_ftdi_elan_write_pcimem(u132->platform_dev, offsetof(struct \ |
218 | ohci_regs, member), 0, data); | 223 | ohci_regs, member), 0, data); |
219 | #define u132_write_pcimem_byte(u132, member, data) \ | ||
220 | usb_ftdi_elan_write_pcimem(u132->platform_dev, offsetof(struct \ | ||
221 | ohci_regs, member), 0x0e, data); | ||
222 | static inline struct u132 *udev_to_u132(struct u132_udev *udev) | 224 | static inline struct u132 *udev_to_u132(struct u132_udev *udev) |
223 | { | 225 | { |
224 | u8 udev_number = udev->udev_number; | 226 | u8 udev_number = udev->udev_number; |
@@ -1574,59 +1576,12 @@ static char *hcfs2string(int state) | |||
1574 | return "?"; | 1576 | return "?"; |
1575 | } | 1577 | } |
1576 | 1578 | ||
1577 | static int u132_usb_reset(struct u132 *u132) | ||
1578 | { | ||
1579 | int retval; | ||
1580 | retval = u132_read_pcimem(u132, control, &u132->hc_control); | ||
1581 | if (retval) | ||
1582 | return retval; | ||
1583 | u132->hc_control &= OHCI_CTRL_RWC; | ||
1584 | retval = u132_write_pcimem(u132, control, u132->hc_control); | ||
1585 | if (retval) | ||
1586 | return retval; | ||
1587 | return 0; | ||
1588 | } | ||
1589 | |||
1590 | static int u132_init(struct u132 *u132) | 1579 | static int u132_init(struct u132 *u132) |
1591 | { | 1580 | { |
1592 | int retval; | 1581 | int retval; |
1593 | u32 control; | 1582 | u32 control; |
1594 | u132_disable(u132); | 1583 | u132_disable(u132); |
1595 | u132->next_statechange = | 1584 | u132->next_statechange = jiffies; |
1596 | jiffies; /* SMM owns the HC? not for long! */ { | ||
1597 | u32 control; | ||
1598 | retval = u132_read_pcimem(u132, control, &control); | ||
1599 | if (retval) | ||
1600 | return retval; | ||
1601 | if (control & OHCI_CTRL_IR) { | ||
1602 | u32 temp = 50; | ||
1603 | retval = u132_write_pcimem(u132, intrenable, | ||
1604 | OHCI_INTR_OC); | ||
1605 | if (retval) | ||
1606 | return retval; | ||
1607 | retval = u132_write_pcimem_byte(u132, cmdstatus, | ||
1608 | OHCI_OCR); | ||
1609 | if (retval) | ||
1610 | return retval; | ||
1611 | check:{ | ||
1612 | retval = u132_read_pcimem(u132, control, | ||
1613 | &control); | ||
1614 | if (retval) | ||
1615 | return retval; | ||
1616 | } | ||
1617 | if (control & OHCI_CTRL_IR) { | ||
1618 | msleep(10); | ||
1619 | if (--temp == 0) { | ||
1620 | dev_err(&u132->platform_dev->dev, "USB " | ||
1621 | "HC takeover failed!(BIOS/SMM b" | ||
1622 | "ug) control=%08X\n", control); | ||
1623 | return -EBUSY; | ||
1624 | } | ||
1625 | goto check; | ||
1626 | } | ||
1627 | u132_usb_reset(u132); | ||
1628 | } | ||
1629 | } | ||
1630 | retval = u132_write_pcimem(u132, intrdisable, OHCI_INTR_MIE); | 1585 | retval = u132_write_pcimem(u132, intrdisable, OHCI_INTR_MIE); |
1631 | if (retval) | 1586 | if (retval) |
1632 | return retval; | 1587 | return retval; |
@@ -1725,7 +1680,7 @@ static int u132_run(struct u132 *u132) | |||
1725 | retry:retval = u132_read_pcimem(u132, cmdstatus, &status); | 1680 | retry:retval = u132_read_pcimem(u132, cmdstatus, &status); |
1726 | if (retval) | 1681 | if (retval) |
1727 | return retval; | 1682 | return retval; |
1728 | retval = u132_write_pcimem_byte(u132, cmdstatus, OHCI_HCR); | 1683 | retval = u132_write_pcimem(u132, cmdstatus, OHCI_HCR); |
1729 | if (retval) | 1684 | if (retval) |
1730 | return retval; | 1685 | return retval; |
1731 | extra:{ | 1686 | extra:{ |
@@ -1782,7 +1737,7 @@ static int u132_run(struct u132 *u132) | |||
1782 | retval = u132_write_pcimem(u132, control, u132->hc_control); | 1737 | retval = u132_write_pcimem(u132, control, u132->hc_control); |
1783 | if (retval) | 1738 | if (retval) |
1784 | return retval; | 1739 | return retval; |
1785 | retval = u132_write_pcimem_byte(u132, cmdstatus, OHCI_BLF); | 1740 | retval = u132_write_pcimem(u132, cmdstatus, OHCI_BLF); |
1786 | if (retval) | 1741 | if (retval) |
1787 | return retval; | 1742 | return retval; |
1788 | retval = u132_read_pcimem(u132, cmdstatus, &cmdstatus); | 1743 | retval = u132_read_pcimem(u132, cmdstatus, &cmdstatus); |
@@ -1839,8 +1794,8 @@ static void u132_hcd_stop(struct usb_hcd *hcd) | |||
1839 | { | 1794 | { |
1840 | struct u132 *u132 = hcd_to_u132(hcd); | 1795 | struct u132 *u132 = hcd_to_u132(hcd); |
1841 | if (u132->going > 1) { | 1796 | if (u132->going > 1) { |
1842 | dev_err(&u132->platform_dev->dev, "device has been removed %d\n" | 1797 | dev_err(&u132->platform_dev->dev, "u132 device %p(hcd=%p) has b" |
1843 | , u132->going); | 1798 | "een removed %d\n", u132, hcd, u132->going); |
1844 | } else if (u132->going > 0) { | 1799 | } else if (u132->going > 0) { |
1845 | dev_err(&u132->platform_dev->dev, "device hcd=%p is being remov" | 1800 | dev_err(&u132->platform_dev->dev, "device hcd=%p is being remov" |
1846 | "ed\n", hcd); | 1801 | "ed\n", hcd); |
@@ -2545,8 +2500,9 @@ static void u132_endpoint_disable(struct usb_hcd *hcd, | |||
2545 | { | 2500 | { |
2546 | struct u132 *u132 = hcd_to_u132(hcd); | 2501 | struct u132 *u132 = hcd_to_u132(hcd); |
2547 | if (u132->going > 2) { | 2502 | if (u132->going > 2) { |
2548 | dev_err(&u132->platform_dev->dev, "device has been removed %d\n" | 2503 | dev_err(&u132->platform_dev->dev, "u132 device %p(hcd=%p hep=%p" |
2549 | , u132->going); | 2504 | ") has been removed %d\n", u132, hcd, hep, |
2505 | u132->going); | ||
2550 | } else { | 2506 | } else { |
2551 | struct u132_endp *endp = hep->hcpriv; | 2507 | struct u132_endp *endp = hep->hcpriv; |
2552 | if (endp) | 2508 | if (endp) |
@@ -2790,7 +2746,6 @@ static int u132_hub_status_data(struct usb_hcd *hcd, char *buf) | |||
2790 | } else if (u132->going > 0) { | 2746 | } else if (u132->going > 0) { |
2791 | dev_err(&u132->platform_dev->dev, "device hcd=%p is being remov" | 2747 | dev_err(&u132->platform_dev->dev, "device hcd=%p is being remov" |
2792 | "ed\n", hcd); | 2748 | "ed\n", hcd); |
2793 | dump_stack(); | ||
2794 | return -ESHUTDOWN; | 2749 | return -ESHUTDOWN; |
2795 | } else { | 2750 | } else { |
2796 | int i, changed = 0, length = 1; | 2751 | int i, changed = 0, length = 1; |
@@ -3034,12 +2989,15 @@ static int __devexit u132_remove(struct platform_device *pdev) | |||
3034 | struct usb_hcd *hcd = platform_get_drvdata(pdev); | 2989 | struct usb_hcd *hcd = platform_get_drvdata(pdev); |
3035 | if (hcd) { | 2990 | if (hcd) { |
3036 | struct u132 *u132 = hcd_to_u132(hcd); | 2991 | struct u132 *u132 = hcd_to_u132(hcd); |
3037 | dump_stack(); | ||
3038 | if (u132->going++ > 1) { | 2992 | if (u132->going++ > 1) { |
2993 | dev_err(&u132->platform_dev->dev, "already being remove" | ||
2994 | "d\n"); | ||
3039 | return -ENODEV; | 2995 | return -ENODEV; |
3040 | } else { | 2996 | } else { |
3041 | int rings = MAX_U132_RINGS; | 2997 | int rings = MAX_U132_RINGS; |
3042 | int endps = MAX_U132_ENDPS; | 2998 | int endps = MAX_U132_ENDPS; |
2999 | dev_err(&u132->platform_dev->dev, "removing device u132" | ||
3000 | ".%d\n", u132->sequence_num); | ||
3043 | msleep(100); | 3001 | msleep(100); |
3044 | down(&u132->sw_lock); | 3002 | down(&u132->sw_lock); |
3045 | u132_monitor_cancel_work(u132); | 3003 | u132_monitor_cancel_work(u132); |
@@ -3121,10 +3079,24 @@ static void u132_initialise(struct u132 *u132, struct platform_device *pdev) | |||
3121 | static int __devinit u132_probe(struct platform_device *pdev) | 3079 | static int __devinit u132_probe(struct platform_device *pdev) |
3122 | { | 3080 | { |
3123 | struct usb_hcd *hcd; | 3081 | struct usb_hcd *hcd; |
3082 | int retval; | ||
3083 | u32 control; | ||
3084 | u32 rh_a = -1; | ||
3085 | u32 num_ports; | ||
3124 | msleep(100); | 3086 | msleep(100); |
3125 | if (u132_exiting > 0) { | 3087 | if (u132_exiting > 0) { |
3126 | return -ENODEV; | 3088 | return -ENODEV; |
3127 | } /* refuse to confuse usbcore */ | 3089 | } |
3090 | retval = ftdi_write_pcimem(pdev, intrdisable, OHCI_INTR_MIE); | ||
3091 | if (retval) | ||
3092 | return retval; | ||
3093 | retval = ftdi_read_pcimem(pdev, control, &control); | ||
3094 | if (retval) | ||
3095 | return retval; | ||
3096 | retval = ftdi_read_pcimem(pdev, roothub.a, &rh_a); | ||
3097 | if (retval) | ||
3098 | return retval; | ||
3099 | num_ports = rh_a & RH_A_NDP; /* refuse to confuse usbcore */ | ||
3128 | if (pdev->dev.dma_mask) { | 3100 | if (pdev->dev.dma_mask) { |
3129 | return -EINVAL; | 3101 | return -EINVAL; |
3130 | } | 3102 | } |
diff --git a/drivers/usb/misc/ftdi-elan.c b/drivers/usb/misc/ftdi-elan.c index 18b1925032a..41c0161abdb 100644 --- a/drivers/usb/misc/ftdi-elan.c +++ b/drivers/usb/misc/ftdi-elan.c | |||
@@ -40,6 +40,7 @@ | |||
40 | #include <linux/init.h> | 40 | #include <linux/init.h> |
41 | #include <linux/list.h> | 41 | #include <linux/list.h> |
42 | #include <linux/ioctl.h> | 42 | #include <linux/ioctl.h> |
43 | #include <linux/pci_ids.h> | ||
43 | #include <linux/slab.h> | 44 | #include <linux/slab.h> |
44 | #include <linux/module.h> | 45 | #include <linux/module.h> |
45 | #include <linux/kref.h> | 46 | #include <linux/kref.h> |
@@ -51,6 +52,10 @@ MODULE_AUTHOR("Tony Olech"); | |||
51 | MODULE_DESCRIPTION("FTDI ELAN driver"); | 52 | MODULE_DESCRIPTION("FTDI ELAN driver"); |
52 | MODULE_LICENSE("GPL"); | 53 | MODULE_LICENSE("GPL"); |
53 | #define INT_MODULE_PARM(n, v) static int n = v;module_param(n, int, 0444) | 54 | #define INT_MODULE_PARM(n, v) static int n = v;module_param(n, int, 0444) |
55 | static int distrust_firmware = 1; | ||
56 | module_param(distrust_firmware, bool, 0); | ||
57 | MODULE_PARM_DESC(distrust_firmware, "true to distrust firmware power/overcurren" | ||
58 | "t setup"); | ||
54 | extern struct platform_driver u132_platform_driver; | 59 | extern struct platform_driver u132_platform_driver; |
55 | static struct workqueue_struct *status_queue; | 60 | static struct workqueue_struct *status_queue; |
56 | static struct workqueue_struct *command_queue; | 61 | static struct workqueue_struct *command_queue; |
@@ -66,7 +71,9 @@ static struct list_head ftdi_static_list; | |||
66 | * end of the global variables protected by ftdi_module_lock | 71 | * end of the global variables protected by ftdi_module_lock |
67 | */ | 72 | */ |
68 | #include "usb_u132.h" | 73 | #include "usb_u132.h" |
69 | #define TD_DEVNOTRESP 5 | 74 | #include <asm/io.h> |
75 | #include "../core/hcd.h" | ||
76 | #include "../host/ohci.h" | ||
70 | /* Define these values to match your devices*/ | 77 | /* Define these values to match your devices*/ |
71 | #define USB_FTDI_ELAN_VENDOR_ID 0x0403 | 78 | #define USB_FTDI_ELAN_VENDOR_ID 0x0403 |
72 | #define USB_FTDI_ELAN_PRODUCT_ID 0xd6ea | 79 | #define USB_FTDI_ELAN_PRODUCT_ID 0xd6ea |
@@ -551,7 +558,7 @@ static void ftdi_elan_status_work(struct work_struct *work) | |||
551 | } else { | 558 | } else { |
552 | dev_err(&ftdi->udev->dev, "initialized failed - trying " | 559 | dev_err(&ftdi->udev->dev, "initialized failed - trying " |
553 | "again in 10 seconds\n"); | 560 | "again in 10 seconds\n"); |
554 | work_delay_in_msec = 10 *1000; | 561 | work_delay_in_msec = 1 *1000; |
555 | } | 562 | } |
556 | } else if (ftdi->registered == 0) { | 563 | } else if (ftdi->registered == 0) { |
557 | work_delay_in_msec = 10; | 564 | work_delay_in_msec = 10; |
@@ -2288,82 +2295,288 @@ static int ftdi_elan_checkingPCI(struct usb_ftdi *ftdi) | |||
2288 | } | 2295 | } |
2289 | } | 2296 | } |
2290 | 2297 | ||
2291 | static int ftdi_elan_enumeratePCI(struct usb_ftdi *ftdi) | 2298 | |
2299 | #define ftdi_read_pcimem(ftdi, member, data) ftdi_elan_read_pcimem(ftdi, \ | ||
2300 | offsetof(struct ohci_regs, member), 0, data); | ||
2301 | #define ftdi_write_pcimem(ftdi, member, data) ftdi_elan_write_pcimem(ftdi, \ | ||
2302 | offsetof(struct ohci_regs, member), 0, data); | ||
2303 | #define OHCI_QUIRK_AMD756 0x01 | ||
2304 | #define OHCI_QUIRK_SUPERIO 0x02 | ||
2305 | #define OHCI_QUIRK_INITRESET 0x04 | ||
2306 | #define OHCI_BIG_ENDIAN 0x08 | ||
2307 | #define OHCI_QUIRK_ZFMICRO 0x10 | ||
2308 | #define OHCI_CONTROL_INIT OHCI_CTRL_CBSR | ||
2309 | #define OHCI_INTR_INIT (OHCI_INTR_MIE | OHCI_INTR_UE | OHCI_INTR_RD | \ | ||
2310 | OHCI_INTR_WDH) | ||
2311 | static int ftdi_elan_check_controller(struct usb_ftdi *ftdi, int quirk) | ||
2312 | { | ||
2313 | int devices = 0; | ||
2314 | int retval; | ||
2315 | u32 hc_control; | ||
2316 | int num_ports; | ||
2317 | u32 control; | ||
2318 | u32 rh_a = -1; | ||
2319 | u32 status; | ||
2320 | u32 fminterval; | ||
2321 | u32 hc_fminterval; | ||
2322 | u32 periodicstart; | ||
2323 | u32 cmdstatus; | ||
2324 | u32 roothub_a; | ||
2325 | int mask = OHCI_INTR_INIT; | ||
2326 | int sleep_time = 0; | ||
2327 | int reset_timeout = 30; /* ... allow extra time */ | ||
2328 | int temp; | ||
2329 | retval = ftdi_write_pcimem(ftdi, intrdisable, OHCI_INTR_MIE); | ||
2330 | if (retval) | ||
2331 | return retval; | ||
2332 | retval = ftdi_read_pcimem(ftdi, control, &control); | ||
2333 | if (retval) | ||
2334 | return retval; | ||
2335 | retval = ftdi_read_pcimem(ftdi, roothub.a, &rh_a); | ||
2336 | if (retval) | ||
2337 | return retval; | ||
2338 | num_ports = rh_a & RH_A_NDP; | ||
2339 | retval = ftdi_read_pcimem(ftdi, fminterval, &hc_fminterval); | ||
2340 | if (retval) | ||
2341 | return retval; | ||
2342 | hc_fminterval &= 0x3fff; | ||
2343 | if (hc_fminterval != FI) { | ||
2344 | } | ||
2345 | hc_fminterval |= FSMP(hc_fminterval) << 16; | ||
2346 | retval = ftdi_read_pcimem(ftdi, control, &hc_control); | ||
2347 | if (retval) | ||
2348 | return retval; | ||
2349 | switch (hc_control & OHCI_CTRL_HCFS) { | ||
2350 | case OHCI_USB_OPER: | ||
2351 | sleep_time = 0; | ||
2352 | break; | ||
2353 | case OHCI_USB_SUSPEND: | ||
2354 | case OHCI_USB_RESUME: | ||
2355 | hc_control &= OHCI_CTRL_RWC; | ||
2356 | hc_control |= OHCI_USB_RESUME; | ||
2357 | sleep_time = 10; | ||
2358 | break; | ||
2359 | default: | ||
2360 | hc_control &= OHCI_CTRL_RWC; | ||
2361 | hc_control |= OHCI_USB_RESET; | ||
2362 | sleep_time = 50; | ||
2363 | break; | ||
2364 | } | ||
2365 | retval = ftdi_write_pcimem(ftdi, control, hc_control); | ||
2366 | if (retval) | ||
2367 | return retval; | ||
2368 | retval = ftdi_read_pcimem(ftdi, control, &control); | ||
2369 | if (retval) | ||
2370 | return retval; | ||
2371 | msleep(sleep_time); | ||
2372 | retval = ftdi_read_pcimem(ftdi, roothub.a, &roothub_a); | ||
2373 | if (retval) | ||
2374 | return retval; | ||
2375 | if (!(roothub_a & RH_A_NPS)) { /* power down each port */ | ||
2376 | for (temp = 0; temp < num_ports; temp++) { | ||
2377 | retval = ftdi_write_pcimem(ftdi, | ||
2378 | roothub.portstatus[temp], RH_PS_LSDA); | ||
2379 | if (retval) | ||
2380 | return retval; | ||
2381 | } | ||
2382 | } | ||
2383 | retval = ftdi_read_pcimem(ftdi, control, &control); | ||
2384 | if (retval) | ||
2385 | return retval; | ||
2386 | retry:retval = ftdi_read_pcimem(ftdi, cmdstatus, &status); | ||
2387 | if (retval) | ||
2388 | return retval; | ||
2389 | retval = ftdi_write_pcimem(ftdi, cmdstatus, OHCI_HCR); | ||
2390 | if (retval) | ||
2391 | return retval; | ||
2392 | extra:{ | ||
2393 | retval = ftdi_read_pcimem(ftdi, cmdstatus, &status); | ||
2394 | if (retval) | ||
2395 | return retval; | ||
2396 | if (0 != (status & OHCI_HCR)) { | ||
2397 | if (--reset_timeout == 0) { | ||
2398 | dev_err(&ftdi->udev->dev, "USB HC reset timed o" | ||
2399 | "ut!\n"); | ||
2400 | return -ENODEV; | ||
2401 | } else { | ||
2402 | msleep(5); | ||
2403 | goto extra; | ||
2404 | } | ||
2405 | } | ||
2406 | } | ||
2407 | if (quirk & OHCI_QUIRK_INITRESET) { | ||
2408 | retval = ftdi_write_pcimem(ftdi, control, hc_control); | ||
2409 | if (retval) | ||
2410 | return retval; | ||
2411 | retval = ftdi_read_pcimem(ftdi, control, &control); | ||
2412 | if (retval) | ||
2413 | return retval; | ||
2414 | } | ||
2415 | retval = ftdi_write_pcimem(ftdi, ed_controlhead, 0x00000000); | ||
2416 | if (retval) | ||
2417 | return retval; | ||
2418 | retval = ftdi_write_pcimem(ftdi, ed_bulkhead, 0x11000000); | ||
2419 | if (retval) | ||
2420 | return retval; | ||
2421 | retval = ftdi_write_pcimem(ftdi, hcca, 0x00000000); | ||
2422 | if (retval) | ||
2423 | return retval; | ||
2424 | retval = ftdi_read_pcimem(ftdi, fminterval, &fminterval); | ||
2425 | if (retval) | ||
2426 | return retval; | ||
2427 | retval = ftdi_write_pcimem(ftdi, fminterval, | ||
2428 | ((fminterval & FIT) ^ FIT) | hc_fminterval); | ||
2429 | if (retval) | ||
2430 | return retval; | ||
2431 | retval = ftdi_write_pcimem(ftdi, periodicstart, | ||
2432 | ((9 *hc_fminterval) / 10) & 0x3fff); | ||
2433 | if (retval) | ||
2434 | return retval; | ||
2435 | retval = ftdi_read_pcimem(ftdi, fminterval, &fminterval); | ||
2436 | if (retval) | ||
2437 | return retval; | ||
2438 | retval = ftdi_read_pcimem(ftdi, periodicstart, &periodicstart); | ||
2439 | if (retval) | ||
2440 | return retval; | ||
2441 | if (0 == (fminterval & 0x3fff0000) || 0 == periodicstart) { | ||
2442 | if (!(quirk & OHCI_QUIRK_INITRESET)) { | ||
2443 | quirk |= OHCI_QUIRK_INITRESET; | ||
2444 | goto retry; | ||
2445 | } else | ||
2446 | dev_err(&ftdi->udev->dev, "init err(%08x %04x)\n", | ||
2447 | fminterval, periodicstart); | ||
2448 | } /* start controller operations */ | ||
2449 | hc_control &= OHCI_CTRL_RWC; | ||
2450 | hc_control |= OHCI_CONTROL_INIT | OHCI_CTRL_BLE | OHCI_USB_OPER; | ||
2451 | retval = ftdi_write_pcimem(ftdi, control, hc_control); | ||
2452 | if (retval) | ||
2453 | return retval; | ||
2454 | retval = ftdi_write_pcimem(ftdi, cmdstatus, OHCI_BLF); | ||
2455 | if (retval) | ||
2456 | return retval; | ||
2457 | retval = ftdi_read_pcimem(ftdi, cmdstatus, &cmdstatus); | ||
2458 | if (retval) | ||
2459 | return retval; | ||
2460 | retval = ftdi_read_pcimem(ftdi, control, &control); | ||
2461 | if (retval) | ||
2462 | return retval; | ||
2463 | retval = ftdi_write_pcimem(ftdi, roothub.status, RH_HS_DRWE); | ||
2464 | if (retval) | ||
2465 | return retval; | ||
2466 | retval = ftdi_write_pcimem(ftdi, intrstatus, mask); | ||
2467 | if (retval) | ||
2468 | return retval; | ||
2469 | retval = ftdi_write_pcimem(ftdi, intrdisable, | ||
2470 | OHCI_INTR_MIE | OHCI_INTR_OC | OHCI_INTR_RHSC | OHCI_INTR_FNO | | ||
2471 | OHCI_INTR_UE | OHCI_INTR_RD | OHCI_INTR_SF | OHCI_INTR_WDH | | ||
2472 | OHCI_INTR_SO); | ||
2473 | if (retval) | ||
2474 | return retval; /* handle root hub init quirks ... */ | ||
2475 | retval = ftdi_read_pcimem(ftdi, roothub.a, &roothub_a); | ||
2476 | if (retval) | ||
2477 | return retval; | ||
2478 | roothub_a &= ~(RH_A_PSM | RH_A_OCPM); | ||
2479 | if (quirk & OHCI_QUIRK_SUPERIO) { | ||
2480 | roothub_a |= RH_A_NOCP; | ||
2481 | roothub_a &= ~(RH_A_POTPGT | RH_A_NPS); | ||
2482 | retval = ftdi_write_pcimem(ftdi, roothub.a, roothub_a); | ||
2483 | if (retval) | ||
2484 | return retval; | ||
2485 | } else if ((quirk & OHCI_QUIRK_AMD756) || distrust_firmware) { | ||
2486 | roothub_a |= RH_A_NPS; | ||
2487 | retval = ftdi_write_pcimem(ftdi, roothub.a, roothub_a); | ||
2488 | if (retval) | ||
2489 | return retval; | ||
2490 | } | ||
2491 | retval = ftdi_write_pcimem(ftdi, roothub.status, RH_HS_LPSC); | ||
2492 | if (retval) | ||
2493 | return retval; | ||
2494 | retval = ftdi_write_pcimem(ftdi, roothub.b, | ||
2495 | (roothub_a & RH_A_NPS) ? 0 : RH_B_PPCM); | ||
2496 | if (retval) | ||
2497 | return retval; | ||
2498 | retval = ftdi_read_pcimem(ftdi, control, &control); | ||
2499 | if (retval) | ||
2500 | return retval; | ||
2501 | mdelay((roothub_a >> 23) & 0x1fe); | ||
2502 | for (temp = 0; temp < num_ports; temp++) { | ||
2503 | u32 portstatus; | ||
2504 | retval = ftdi_read_pcimem(ftdi, roothub.portstatus[temp], | ||
2505 | &portstatus); | ||
2506 | if (retval) | ||
2507 | return retval; | ||
2508 | if (1 & portstatus) | ||
2509 | devices += 1; | ||
2510 | } | ||
2511 | return devices; | ||
2512 | } | ||
2513 | |||
2514 | static int ftdi_elan_setup_controller(struct usb_ftdi *ftdi, int fn) | ||
2292 | { | 2515 | { |
2293 | u32 latence_timer; | 2516 | u32 latence_timer; |
2294 | u32 controlreg; | ||
2295 | int UxxxStatus; | 2517 | int UxxxStatus; |
2296 | u32 pcidata; | 2518 | u32 pcidata; |
2297 | int reg = 0; | 2519 | int reg = 0; |
2298 | int foundOHCI = 0; | 2520 | int activePCIfn = fn << 8; |
2299 | u8 fn; | 2521 | UxxxStatus = ftdi_elan_write_reg(ftdi, 0x0000025FL | 0x2800); |
2300 | int activePCIfn = 0; | ||
2301 | u32 pciVID = 0; | ||
2302 | u32 pciPID = 0; | ||
2303 | UxxxStatus = ftdi_elan_read_reg(ftdi, &controlreg); | ||
2304 | if (UxxxStatus) | ||
2305 | return UxxxStatus; | ||
2306 | UxxxStatus = ftdi_elan_write_reg(ftdi, 0x00000000L); | ||
2307 | if (UxxxStatus) | ||
2308 | return UxxxStatus; | ||
2309 | msleep(750); | ||
2310 | UxxxStatus = ftdi_elan_write_reg(ftdi, 0x00000200L | 0x100); | ||
2311 | if (UxxxStatus) | 2522 | if (UxxxStatus) |
2312 | return UxxxStatus; | 2523 | return UxxxStatus; |
2313 | UxxxStatus = ftdi_elan_write_reg(ftdi, 0x00000200L | 0x500); | 2524 | reg = 16; |
2525 | UxxxStatus = ftdi_elan_write_config(ftdi, activePCIfn | reg, 0, | ||
2526 | 0xFFFFFFFF); | ||
2314 | if (UxxxStatus) | 2527 | if (UxxxStatus) |
2315 | return UxxxStatus; | 2528 | return UxxxStatus; |
2316 | UxxxStatus = ftdi_elan_read_reg(ftdi, &controlreg); | 2529 | UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0, |
2530 | &pcidata); | ||
2317 | if (UxxxStatus) | 2531 | if (UxxxStatus) |
2318 | return UxxxStatus; | 2532 | return UxxxStatus; |
2319 | UxxxStatus = ftdi_elan_write_reg(ftdi, 0x0000020CL | 0x000); | 2533 | UxxxStatus = ftdi_elan_write_config(ftdi, activePCIfn | reg, 0, |
2534 | 0xF0000000); | ||
2320 | if (UxxxStatus) | 2535 | if (UxxxStatus) |
2321 | return UxxxStatus; | 2536 | return UxxxStatus; |
2322 | UxxxStatus = ftdi_elan_write_reg(ftdi, 0x0000020DL | 0x000); | 2537 | UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0, |
2538 | &pcidata); | ||
2323 | if (UxxxStatus) | 2539 | if (UxxxStatus) |
2324 | return UxxxStatus; | 2540 | return UxxxStatus; |
2325 | msleep(250); | 2541 | reg = 12; |
2326 | UxxxStatus = ftdi_elan_write_reg(ftdi, 0x0000020FL | 0x000); | 2542 | UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0, |
2543 | &latence_timer); | ||
2327 | if (UxxxStatus) | 2544 | if (UxxxStatus) |
2328 | return UxxxStatus; | 2545 | return UxxxStatus; |
2329 | UxxxStatus = ftdi_elan_read_reg(ftdi, &controlreg); | 2546 | latence_timer &= 0xFFFF00FF; |
2547 | latence_timer |= 0x00001600; | ||
2548 | UxxxStatus = ftdi_elan_write_config(ftdi, activePCIfn | reg, 0x00, | ||
2549 | latence_timer); | ||
2330 | if (UxxxStatus) | 2550 | if (UxxxStatus) |
2331 | return UxxxStatus; | 2551 | return UxxxStatus; |
2332 | UxxxStatus = ftdi_elan_write_reg(ftdi, 0x0000025FL | 0x800); | 2552 | UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0, |
2553 | &pcidata); | ||
2333 | if (UxxxStatus) | 2554 | if (UxxxStatus) |
2334 | return UxxxStatus; | 2555 | return UxxxStatus; |
2335 | UxxxStatus = ftdi_elan_read_reg(ftdi, &controlreg); | 2556 | reg = 4; |
2557 | UxxxStatus = ftdi_elan_write_config(ftdi, activePCIfn | reg, 0x00, | ||
2558 | 0x06); | ||
2336 | if (UxxxStatus) | 2559 | if (UxxxStatus) |
2337 | return UxxxStatus; | 2560 | return UxxxStatus; |
2338 | UxxxStatus = ftdi_elan_read_reg(ftdi, &controlreg); | 2561 | UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0, |
2562 | &pcidata); | ||
2339 | if (UxxxStatus) | 2563 | if (UxxxStatus) |
2340 | return UxxxStatus; | 2564 | return UxxxStatus; |
2341 | msleep(1000); | 2565 | for (reg = 0; reg <= 0x54; reg += 4) { |
2342 | for (fn = 0; (fn < 4) && (!foundOHCI); fn++) { | 2566 | UxxxStatus = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata); |
2343 | activePCIfn = fn << 8; | ||
2344 | ftdi->function = fn + 1; | ||
2345 | UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0, | ||
2346 | &pcidata); | ||
2347 | if (UxxxStatus) | 2567 | if (UxxxStatus) |
2348 | return UxxxStatus; | 2568 | return UxxxStatus; |
2349 | pciVID = pcidata & 0xFFFF; | ||
2350 | pciPID = (pcidata >> 16) & 0xFFFF; | ||
2351 | if ((pciVID == 0x1045) && (pciPID == 0xc861)) { | ||
2352 | foundOHCI = 1; | ||
2353 | } else if ((pciVID == 0x1033) && (pciPID == 0x0035)) { | ||
2354 | foundOHCI = 1; | ||
2355 | } else if ((pciVID == 0x10b9) && (pciPID == 0x5237)) { | ||
2356 | foundOHCI = 1; | ||
2357 | } else if ((pciVID == 0x11c1) && (pciPID == 0x5802)) { | ||
2358 | foundOHCI = 1; | ||
2359 | } else if ((pciVID == 0x11AB) && (pciPID == 0x1FA6)) { | ||
2360 | } | ||
2361 | } | ||
2362 | if (foundOHCI == 0) { | ||
2363 | return -ENXIO; | ||
2364 | } | 2569 | } |
2365 | ftdi->platform_data.vendor = pciVID; | 2570 | return 0; |
2366 | ftdi->platform_data.device = pciPID; | 2571 | } |
2572 | |||
2573 | static int ftdi_elan_close_controller(struct usb_ftdi *ftdi, int fn) | ||
2574 | { | ||
2575 | u32 latence_timer; | ||
2576 | int UxxxStatus; | ||
2577 | u32 pcidata; | ||
2578 | int reg = 0; | ||
2579 | int activePCIfn = fn << 8; | ||
2367 | UxxxStatus = ftdi_elan_write_reg(ftdi, 0x0000025FL | 0x2800); | 2580 | UxxxStatus = ftdi_elan_write_reg(ftdi, 0x0000025FL | 0x2800); |
2368 | if (UxxxStatus) | 2581 | if (UxxxStatus) |
2369 | return UxxxStatus; | 2582 | return UxxxStatus; |
@@ -2377,7 +2590,7 @@ static int ftdi_elan_enumeratePCI(struct usb_ftdi *ftdi) | |||
2377 | if (UxxxStatus) | 2590 | if (UxxxStatus) |
2378 | return UxxxStatus; | 2591 | return UxxxStatus; |
2379 | UxxxStatus = ftdi_elan_write_config(ftdi, activePCIfn | reg, 0, | 2592 | UxxxStatus = ftdi_elan_write_config(ftdi, activePCIfn | reg, 0, |
2380 | 0xF0000000); | 2593 | 0x00000000); |
2381 | if (UxxxStatus) | 2594 | if (UxxxStatus) |
2382 | return UxxxStatus; | 2595 | return UxxxStatus; |
2383 | UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0, | 2596 | UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0, |
@@ -2401,7 +2614,7 @@ static int ftdi_elan_enumeratePCI(struct usb_ftdi *ftdi) | |||
2401 | return UxxxStatus; | 2614 | return UxxxStatus; |
2402 | reg = 4; | 2615 | reg = 4; |
2403 | UxxxStatus = ftdi_elan_write_config(ftdi, activePCIfn | reg, 0x00, | 2616 | UxxxStatus = ftdi_elan_write_config(ftdi, activePCIfn | reg, 0x00, |
2404 | 0x06); | 2617 | 0x00); |
2405 | if (UxxxStatus) | 2618 | if (UxxxStatus) |
2406 | return UxxxStatus; | 2619 | return UxxxStatus; |
2407 | UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0, | 2620 | UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0, |
@@ -2411,159 +2624,139 @@ static int ftdi_elan_enumeratePCI(struct usb_ftdi *ftdi) | |||
2411 | return 0; | 2624 | return 0; |
2412 | } | 2625 | } |
2413 | 2626 | ||
2627 | static int ftdi_elan_found_controller(struct usb_ftdi *ftdi, int fn, int quirk) | ||
2628 | { | ||
2629 | int result; | ||
2630 | int UxxxStatus; | ||
2631 | UxxxStatus = ftdi_elan_setup_controller(ftdi, fn); | ||
2632 | if (UxxxStatus) | ||
2633 | return UxxxStatus; | ||
2634 | result = ftdi_elan_check_controller(ftdi, quirk); | ||
2635 | UxxxStatus = ftdi_elan_close_controller(ftdi, fn); | ||
2636 | if (UxxxStatus) | ||
2637 | return UxxxStatus; | ||
2638 | return result; | ||
2639 | } | ||
2640 | |||
2641 | static int ftdi_elan_enumeratePCI(struct usb_ftdi *ftdi) | ||
2642 | { | ||
2643 | u32 controlreg; | ||
2644 | u8 sensebits; | ||
2645 | int UxxxStatus; | ||
2646 | UxxxStatus = ftdi_elan_read_reg(ftdi, &controlreg); | ||
2647 | if (UxxxStatus) | ||
2648 | return UxxxStatus; | ||
2649 | UxxxStatus = ftdi_elan_write_reg(ftdi, 0x00000000L); | ||
2650 | if (UxxxStatus) | ||
2651 | return UxxxStatus; | ||
2652 | msleep(750); | ||
2653 | UxxxStatus = ftdi_elan_write_reg(ftdi, 0x00000200L | 0x100); | ||
2654 | if (UxxxStatus) | ||
2655 | return UxxxStatus; | ||
2656 | UxxxStatus = ftdi_elan_write_reg(ftdi, 0x00000200L | 0x500); | ||
2657 | if (UxxxStatus) | ||
2658 | return UxxxStatus; | ||
2659 | UxxxStatus = ftdi_elan_read_reg(ftdi, &controlreg); | ||
2660 | if (UxxxStatus) | ||
2661 | return UxxxStatus; | ||
2662 | UxxxStatus = ftdi_elan_write_reg(ftdi, 0x0000020CL | 0x000); | ||
2663 | if (UxxxStatus) | ||
2664 | return UxxxStatus; | ||
2665 | UxxxStatus = ftdi_elan_write_reg(ftdi, 0x0000020DL | 0x000); | ||
2666 | if (UxxxStatus) | ||
2667 | return UxxxStatus; | ||
2668 | msleep(250); | ||
2669 | UxxxStatus = ftdi_elan_write_reg(ftdi, 0x0000020FL | 0x000); | ||
2670 | if (UxxxStatus) | ||
2671 | return UxxxStatus; | ||
2672 | UxxxStatus = ftdi_elan_read_reg(ftdi, &controlreg); | ||
2673 | if (UxxxStatus) | ||
2674 | return UxxxStatus; | ||
2675 | UxxxStatus = ftdi_elan_write_reg(ftdi, 0x0000025FL | 0x800); | ||
2676 | if (UxxxStatus) | ||
2677 | return UxxxStatus; | ||
2678 | UxxxStatus = ftdi_elan_read_reg(ftdi, &controlreg); | ||
2679 | if (UxxxStatus) | ||
2680 | return UxxxStatus; | ||
2681 | UxxxStatus = ftdi_elan_read_reg(ftdi, &controlreg); | ||
2682 | if (UxxxStatus) | ||
2683 | return UxxxStatus; | ||
2684 | msleep(1000); | ||
2685 | sensebits = (controlreg >> 16) & 0x000F; | ||
2686 | if (0x0D == sensebits) | ||
2687 | return 0; | ||
2688 | else | ||
2689 | return - ENXIO; | ||
2690 | } | ||
2691 | |||
2414 | static int ftdi_elan_setupOHCI(struct usb_ftdi *ftdi) | 2692 | static int ftdi_elan_setupOHCI(struct usb_ftdi *ftdi) |
2415 | { | 2693 | { |
2694 | int UxxxStatus; | ||
2416 | u32 pcidata; | 2695 | u32 pcidata; |
2417 | int U132Status; | 2696 | int reg = 0; |
2418 | int reg; | 2697 | u8 fn; |
2419 | int reset_repeat = 0; | 2698 | int activePCIfn = 0; |
2420 | do_reset:reg = 8; | 2699 | int max_devices = 0; |
2421 | U132Status = ftdi_elan_write_pcimem(ftdi, reg, 0x0e, 0x01); | 2700 | int controllers = 0; |
2422 | if (U132Status) | 2701 | int unrecognized = 0; |
2423 | return U132Status; | 2702 | ftdi->function = 0; |
2424 | reset_check:{ | 2703 | for (fn = 0; (fn < 4); fn++) { |
2425 | U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata); | 2704 | u32 pciVID = 0; |
2426 | if (U132Status) | 2705 | u32 pciPID = 0; |
2427 | return U132Status; | 2706 | int devices = 0; |
2428 | if (pcidata & 1) { | 2707 | activePCIfn = fn << 8; |
2429 | msleep(500); | 2708 | UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0, |
2430 | if (reset_repeat++ > 100) { | 2709 | &pcidata); |
2431 | reset_repeat = 0; | 2710 | if (UxxxStatus) |
2432 | goto do_reset; | 2711 | return UxxxStatus; |
2433 | } else | 2712 | pciVID = pcidata & 0xFFFF; |
2434 | goto reset_check; | 2713 | pciPID = (pcidata >> 16) & 0xFFFF; |
2714 | if ((pciVID == PCI_VENDOR_ID_OPTI) && (pciPID == 0xc861)) { | ||
2715 | devices = ftdi_elan_found_controller(ftdi, fn, 0); | ||
2716 | controllers += 1; | ||
2717 | } else if ((pciVID == PCI_VENDOR_ID_NEC) && (pciPID == 0x0035)) | ||
2718 | { | ||
2719 | devices = ftdi_elan_found_controller(ftdi, fn, 0); | ||
2720 | controllers += 1; | ||
2721 | } else if ((pciVID == PCI_VENDOR_ID_AL) && (pciPID == 0x5237)) { | ||
2722 | devices = ftdi_elan_found_controller(ftdi, fn, 0); | ||
2723 | controllers += 1; | ||
2724 | } else if ((pciVID == PCI_VENDOR_ID_ATT) && (pciPID == 0x5802)) | ||
2725 | { | ||
2726 | devices = ftdi_elan_found_controller(ftdi, fn, 0); | ||
2727 | controllers += 1; | ||
2728 | } else if (pciVID == PCI_VENDOR_ID_AMD && pciPID == 0x740c) { | ||
2729 | devices = ftdi_elan_found_controller(ftdi, fn, | ||
2730 | OHCI_QUIRK_AMD756); | ||
2731 | controllers += 1; | ||
2732 | } else if (pciVID == PCI_VENDOR_ID_COMPAQ && pciPID == 0xa0f8) { | ||
2733 | devices = ftdi_elan_found_controller(ftdi, fn, | ||
2734 | OHCI_QUIRK_ZFMICRO); | ||
2735 | controllers += 1; | ||
2736 | } else if (0 == pcidata) { | ||
2737 | } else | ||
2738 | unrecognized += 1; | ||
2739 | if (devices > max_devices) { | ||
2740 | max_devices = devices; | ||
2741 | ftdi->function = fn + 1; | ||
2742 | ftdi->platform_data.vendor = pciVID; | ||
2743 | ftdi->platform_data.device = pciPID; | ||
2435 | } | 2744 | } |
2436 | } | 2745 | } |
2437 | goto dump_regs; | 2746 | if (ftdi->function > 0) { |
2438 | msleep(500); | 2747 | UxxxStatus = ftdi_elan_setup_controller(ftdi, |
2439 | reg = 0x28; | 2748 | ftdi->function - 1); |
2440 | U132Status = ftdi_elan_write_pcimem(ftdi, reg, 0x00, 0x11000000); | 2749 | if (UxxxStatus) |
2441 | if (U132Status) | 2750 | return UxxxStatus; |
2442 | return U132Status; | 2751 | return 0; |
2443 | U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata); | 2752 | } else if (controllers > 0) { |
2444 | if (U132Status) | 2753 | return -ENXIO; |
2445 | return U132Status; | 2754 | } else if (unrecognized > 0) { |
2446 | reg = 0x40; | 2755 | return -ENXIO; |
2447 | U132Status = ftdi_elan_write_pcimem(ftdi, reg, 0x00, 0x2edf); | 2756 | } else { |
2448 | if (U132Status) | 2757 | ftdi->enumerated = 0; |
2449 | return U132Status; | 2758 | return -ENXIO; |
2450 | U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata); | ||
2451 | if (U132Status) | ||
2452 | return U132Status; | ||
2453 | reg = 0x34; | ||
2454 | U132Status = ftdi_elan_write_pcimem(ftdi, reg, 0x00, 0x2edf2edf); | ||
2455 | if (U132Status) | ||
2456 | return U132Status; | ||
2457 | U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata); | ||
2458 | if (U132Status) | ||
2459 | return U132Status; | ||
2460 | reg = 4; | ||
2461 | U132Status = ftdi_elan_write_pcimem(ftdi, reg, 0x00, 0xA0); | ||
2462 | if (U132Status) | ||
2463 | return U132Status; | ||
2464 | U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata); | ||
2465 | if (U132Status) | ||
2466 | return U132Status; | ||
2467 | msleep(250); | ||
2468 | reg = 8; | ||
2469 | U132Status = ftdi_elan_write_pcimem(ftdi, reg, 0x0e, 0x04); | ||
2470 | if (U132Status) | ||
2471 | return U132Status; | ||
2472 | U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata); | ||
2473 | if (U132Status) | ||
2474 | return U132Status; | ||
2475 | reg = 0x28; | ||
2476 | U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata); | ||
2477 | if (U132Status) | ||
2478 | return U132Status; | ||
2479 | reg = 8; | ||
2480 | U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata); | ||
2481 | if (U132Status) | ||
2482 | return U132Status; | ||
2483 | reg = 0x48; | ||
2484 | U132Status = ftdi_elan_write_pcimem(ftdi, reg, 0x00, 0x00001200); | ||
2485 | if (U132Status) | ||
2486 | return U132Status; | ||
2487 | U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata); | ||
2488 | if (U132Status) | ||
2489 | return U132Status; | ||
2490 | reg = 0x54; | ||
2491 | U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata); | ||
2492 | if (U132Status) | ||
2493 | return U132Status; | ||
2494 | reg = 0x58; | ||
2495 | U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata); | ||
2496 | if (U132Status) | ||
2497 | return U132Status; | ||
2498 | reg = 0x34; | ||
2499 | U132Status = ftdi_elan_write_pcimem(ftdi, reg, 0x00, 0x28002edf); | ||
2500 | if (U132Status) | ||
2501 | return U132Status; | ||
2502 | U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata); | ||
2503 | if (U132Status) | ||
2504 | return U132Status; | ||
2505 | msleep(100); | ||
2506 | reg = 0x50; | ||
2507 | U132Status = ftdi_elan_write_pcimem(ftdi, reg, 0x00, 0x10000); | ||
2508 | if (U132Status) | ||
2509 | return U132Status; | ||
2510 | reg = 0x54; | ||
2511 | power_check:U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata); | ||
2512 | if (U132Status) | ||
2513 | return U132Status; | ||
2514 | if (!(pcidata & 1)) { | ||
2515 | msleep(500); | ||
2516 | goto power_check; | ||
2517 | } | ||
2518 | msleep(3000); | ||
2519 | reg = 0x54; | ||
2520 | U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata); | ||
2521 | if (U132Status) | ||
2522 | return U132Status; | ||
2523 | reg = 0x58; | ||
2524 | U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata); | ||
2525 | if (U132Status) | ||
2526 | return U132Status; | ||
2527 | reg = 0x54; | ||
2528 | U132Status = ftdi_elan_write_pcimem(ftdi, reg, 0x00, 0x02); | ||
2529 | if (U132Status) | ||
2530 | return U132Status; | ||
2531 | U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata); | ||
2532 | if (U132Status) | ||
2533 | return U132Status; | ||
2534 | reg = 0x54; | ||
2535 | U132Status = ftdi_elan_write_pcimem(ftdi, reg, 0x00, 0x10); | ||
2536 | if (U132Status) | ||
2537 | return U132Status; | ||
2538 | U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata); | ||
2539 | if (U132Status) | ||
2540 | return U132Status; | ||
2541 | msleep(750); | ||
2542 | reg = 0x54; | ||
2543 | if (0) { | ||
2544 | U132Status = ftdi_elan_write_pcimem(ftdi, reg, 0x00, 0x02); | ||
2545 | if (U132Status) | ||
2546 | return U132Status; | ||
2547 | } | ||
2548 | if (0) { | ||
2549 | U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata); | ||
2550 | if (U132Status) | ||
2551 | return U132Status; | ||
2552 | } | ||
2553 | reg = 0x54; | ||
2554 | U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata); | ||
2555 | if (U132Status) | ||
2556 | return U132Status; | ||
2557 | reg = 0x58; | ||
2558 | U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata); | ||
2559 | if (U132Status) | ||
2560 | return U132Status; | ||
2561 | dump_regs:for (reg = 0; reg <= 0x54; reg += 4) { | ||
2562 | U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata); | ||
2563 | if (U132Status) | ||
2564 | return U132Status; | ||
2565 | } | 2759 | } |
2566 | return 0; | ||
2567 | } | 2760 | } |
2568 | 2761 | ||
2569 | 2762 | ||
@@ -2688,6 +2881,7 @@ static void ftdi_elan_disconnect(struct usb_interface *interface) | |||
2688 | platform_device_unregister(&ftdi->platform_dev); | 2881 | platform_device_unregister(&ftdi->platform_dev); |
2689 | ftdi->synchronized = 0; | 2882 | ftdi->synchronized = 0; |
2690 | ftdi->enumerated = 0; | 2883 | ftdi->enumerated = 0; |
2884 | ftdi->initialized = 0; | ||
2691 | ftdi->registered = 0; | 2885 | ftdi->registered = 0; |
2692 | } | 2886 | } |
2693 | flush_workqueue(status_queue); | 2887 | flush_workqueue(status_queue); |