aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/misc/ftdi-elan.c
diff options
context:
space:
mode:
authorTony Olech <tony.olech@elandigitalsystems.com>2006-12-06 08:16:22 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2006-12-20 13:14:27 -0500
commit4b87361d49c04894458f4d4e80f9669abc894ae1 (patch)
tree104f367f53487d77fa1ad5d07b31ae312bd673d7 /drivers/usb/misc/ftdi-elan.c
parent29ba4b533b677f3cd7f2fc901d51054555a8f243 (diff)
USB: u132-hcd/ftdi-elan: add support for Option GT 3G Quad card
ELAN's U132 is a USB to CardBus OHCI controller adapter, designed specifically for CardBus 3G data cards to function in machines without a CardBus slot. The "ftdi-elan" module is a USB client driver, that detects a supported CardBus OHCI controller plugged into the U132 adapter and thereafter provides the conduit for for access by the "u132-hcd" module. The "u132-hcd" module is a (cut-down OHCI) host controller that supports a single OHCI function of the CardBus card inserted into the U132 adapter. The problem with the initial implementation is that when the CardBus card inserted into the U132 adapter has multiple functions (and a CardBus card can support up to 4 functions), it was the first function that was arbitrarily choosen. The first batch of 3G cards tested, like the Merlin Qualcomm V620, have two functions each supporting a seperate USB OHCI host controller, of which it was that first function that is wired up to the 3G modem. Then along comes the Vodafone Mobile Connect 3G/GPRS data card, aka "Option GT 3G Quad" as printed on it's rear or "Option N.V. GlobeTrotter Fusion Quad Lite" as read with "lspci -v". And it has the meaningful functionality in the second CardBus function. That presents a problem because it was the "ftdi-elan" module alone that knows how to communicate to the embedded CardBus slot and the "u132-hcd" module alone that knows how to access the pcmcia configuration and CardBus accessible memory space. And of course, the information about attached (internally hardwired) devices is contained within USB configuration embedded somewhere within the CardBus card. If only the "u132-hcd" module probe() interface could return a result code that propagated back to the instigating function platform_device_register() then the "ftdi-elan" module could try an alternative CardBus function. However in spite of the recent changes to the drivers/base/ routines that moved device_attach() from bus_add_device() to bus_attach_device() both of those routines lose the "failed to attach" 0 result code and thus the calling routine, namely device_add() is incapable of propaging the "failed to attach" condition back to platform_device_add() and consequently back to the caller of platform_device_register() Experiments show that patching bus_attach_device() to return ENODEV fails with the kernel locking up very early during boot. But, however, if the patch is restricted to calls from platform_device_add() then it does seem to work. Unfortunately, until the kernel's drivers/base is properly modified to propagate -ENODEV back to the caller of platform_device_register(), it is necessary to "fix" the "ftdi-elan" module by importing knowledge from the "u132-hcd" module. This is the reason for the duplicated functionality introduced in this patch. Signed-off-by: Tony Olech <tony.olech@elandigitalsystems.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/misc/ftdi-elan.c')
-rw-r--r--drivers/usb/misc/ftdi-elan.c592
1 files changed, 393 insertions, 199 deletions
diff --git a/drivers/usb/misc/ftdi-elan.c b/drivers/usb/misc/ftdi-elan.c
index 18b1925032a8..41c0161abdb9 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");
51MODULE_DESCRIPTION("FTDI ELAN driver"); 52MODULE_DESCRIPTION("FTDI ELAN driver");
52MODULE_LICENSE("GPL"); 53MODULE_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)
55static int distrust_firmware = 1;
56module_param(distrust_firmware, bool, 0);
57MODULE_PARM_DESC(distrust_firmware, "true to distrust firmware power/overcurren"
58 "t setup");
54extern struct platform_driver u132_platform_driver; 59extern struct platform_driver u132_platform_driver;
55static struct workqueue_struct *status_queue; 60static struct workqueue_struct *status_queue;
56static struct workqueue_struct *command_queue; 61static 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
2291static 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)
2311static 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
2514static 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
2573static 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
2627static 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
2641static 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
2414static int ftdi_elan_setupOHCI(struct usb_ftdi *ftdi) 2692static 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);