diff options
-rw-r--r-- | drivers/usb/serial/mos7840.c | 349 |
1 files changed, 166 insertions, 183 deletions
diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index bc3df86134fe..1cf3375ec1af 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c | |||
@@ -2340,208 +2340,191 @@ static int mos7840_port_probe(struct usb_serial_port *port) | |||
2340 | 2340 | ||
2341 | pnum = port->number - serial->minor; | 2341 | pnum = port->number - serial->minor; |
2342 | 2342 | ||
2343 | /* FIXME: remove do-while(0) loop used to keep stable patch minimal. | 2343 | dev_dbg(&port->dev, "mos7840_startup: configuring port %d\n", pnum); |
2344 | */ | 2344 | mos7840_port = kzalloc(sizeof(struct moschip_port), GFP_KERNEL); |
2345 | do { | 2345 | if (mos7840_port == NULL) { |
2346 | dev_dbg(&port->dev, "mos7840_startup: configuring port %d............\n", pnum); | 2346 | dev_err(&port->dev, "%s - Out of memory\n", __func__); |
2347 | mos7840_port = kzalloc(sizeof(struct moschip_port), GFP_KERNEL); | 2347 | return -ENOMEM; |
2348 | if (mos7840_port == NULL) { | 2348 | } |
2349 | dev_err(&port->dev, "%s - Out of memory\n", __func__); | ||
2350 | return -ENOMEM; | ||
2351 | } | ||
2352 | |||
2353 | /* Initialize all port interrupt end point to port 0 int | ||
2354 | * endpoint. Our device has only one interrupt end point | ||
2355 | * common to all port */ | ||
2356 | |||
2357 | mos7840_port->port = port; | ||
2358 | mos7840_set_port_private(port, mos7840_port); | ||
2359 | spin_lock_init(&mos7840_port->pool_lock); | ||
2360 | |||
2361 | /* minor is not initialised until later by | ||
2362 | * usb-serial.c:get_free_serial() and cannot therefore be used | ||
2363 | * to index device instances */ | ||
2364 | mos7840_port->port_num = pnum + 1; | ||
2365 | dev_dbg(&port->dev, "port->number = %d\n", port->number); | ||
2366 | dev_dbg(&port->dev, "port->serial->minor = %d\n", port->serial->minor); | ||
2367 | dev_dbg(&port->dev, "mos7840_port->port_num = %d\n", mos7840_port->port_num); | ||
2368 | dev_dbg(&port->dev, "serial->minor = %d\n", serial->minor); | ||
2369 | |||
2370 | if (mos7840_port->port_num == 1) { | ||
2371 | mos7840_port->SpRegOffset = 0x0; | ||
2372 | mos7840_port->ControlRegOffset = 0x1; | ||
2373 | mos7840_port->DcrRegOffset = 0x4; | ||
2374 | } else if ((mos7840_port->port_num == 2) | ||
2375 | && (serial->num_ports == 4)) { | ||
2376 | mos7840_port->SpRegOffset = 0x8; | ||
2377 | mos7840_port->ControlRegOffset = 0x9; | ||
2378 | mos7840_port->DcrRegOffset = 0x16; | ||
2379 | } else if ((mos7840_port->port_num == 2) | ||
2380 | && (serial->num_ports == 2)) { | ||
2381 | mos7840_port->SpRegOffset = 0xa; | ||
2382 | mos7840_port->ControlRegOffset = 0xb; | ||
2383 | mos7840_port->DcrRegOffset = 0x19; | ||
2384 | } else if ((mos7840_port->port_num == 3) | ||
2385 | && (serial->num_ports == 4)) { | ||
2386 | mos7840_port->SpRegOffset = 0xa; | ||
2387 | mos7840_port->ControlRegOffset = 0xb; | ||
2388 | mos7840_port->DcrRegOffset = 0x19; | ||
2389 | } else if ((mos7840_port->port_num == 4) | ||
2390 | && (serial->num_ports == 4)) { | ||
2391 | mos7840_port->SpRegOffset = 0xc; | ||
2392 | mos7840_port->ControlRegOffset = 0xd; | ||
2393 | mos7840_port->DcrRegOffset = 0x1c; | ||
2394 | } | ||
2395 | mos7840_dump_serial_port(port, mos7840_port); | ||
2396 | mos7840_set_port_private(port, mos7840_port); | ||
2397 | 2349 | ||
2398 | /* enable rx_disable bit in control register */ | 2350 | /* Initialize all port interrupt end point to port 0 int |
2399 | status = mos7840_get_reg_sync(port, | 2351 | * endpoint. Our device has only one interrupt end point |
2400 | mos7840_port->ControlRegOffset, &Data); | 2352 | * common to all port */ |
2401 | if (status < 0) { | 2353 | |
2402 | dev_dbg(&port->dev, "Reading ControlReg failed status-0x%x\n", status); | 2354 | mos7840_port->port = port; |
2403 | break; | 2355 | mos7840_set_port_private(port, mos7840_port); |
2404 | } else | 2356 | spin_lock_init(&mos7840_port->pool_lock); |
2405 | dev_dbg(&port->dev, "ControlReg Reading success val is %x, status%d\n", Data, status); | 2357 | |
2406 | Data |= 0x08; /* setting driver done bit */ | 2358 | /* minor is not initialised until later by |
2407 | Data |= 0x04; /* sp1_bit to have cts change reflect in | 2359 | * usb-serial.c:get_free_serial() and cannot therefore be used |
2408 | modem status reg */ | 2360 | * to index device instances */ |
2361 | mos7840_port->port_num = pnum + 1; | ||
2362 | dev_dbg(&port->dev, "port->number = %d\n", port->number); | ||
2363 | dev_dbg(&port->dev, "port->serial->minor = %d\n", port->serial->minor); | ||
2364 | dev_dbg(&port->dev, "mos7840_port->port_num = %d\n", mos7840_port->port_num); | ||
2365 | dev_dbg(&port->dev, "serial->minor = %d\n", serial->minor); | ||
2366 | |||
2367 | if (mos7840_port->port_num == 1) { | ||
2368 | mos7840_port->SpRegOffset = 0x0; | ||
2369 | mos7840_port->ControlRegOffset = 0x1; | ||
2370 | mos7840_port->DcrRegOffset = 0x4; | ||
2371 | } else if ((mos7840_port->port_num == 2) && (serial->num_ports == 4)) { | ||
2372 | mos7840_port->SpRegOffset = 0x8; | ||
2373 | mos7840_port->ControlRegOffset = 0x9; | ||
2374 | mos7840_port->DcrRegOffset = 0x16; | ||
2375 | } else if ((mos7840_port->port_num == 2) && (serial->num_ports == 2)) { | ||
2376 | mos7840_port->SpRegOffset = 0xa; | ||
2377 | mos7840_port->ControlRegOffset = 0xb; | ||
2378 | mos7840_port->DcrRegOffset = 0x19; | ||
2379 | } else if ((mos7840_port->port_num == 3) && (serial->num_ports == 4)) { | ||
2380 | mos7840_port->SpRegOffset = 0xa; | ||
2381 | mos7840_port->ControlRegOffset = 0xb; | ||
2382 | mos7840_port->DcrRegOffset = 0x19; | ||
2383 | } else if ((mos7840_port->port_num == 4) && (serial->num_ports == 4)) { | ||
2384 | mos7840_port->SpRegOffset = 0xc; | ||
2385 | mos7840_port->ControlRegOffset = 0xd; | ||
2386 | mos7840_port->DcrRegOffset = 0x1c; | ||
2387 | } | ||
2388 | mos7840_dump_serial_port(port, mos7840_port); | ||
2389 | mos7840_set_port_private(port, mos7840_port); | ||
2390 | |||
2391 | /* enable rx_disable bit in control register */ | ||
2392 | status = mos7840_get_reg_sync(port, | ||
2393 | mos7840_port->ControlRegOffset, &Data); | ||
2394 | if (status < 0) { | ||
2395 | dev_dbg(&port->dev, "Reading ControlReg failed status-0x%x\n", status); | ||
2396 | goto out; | ||
2397 | } else | ||
2398 | dev_dbg(&port->dev, "ControlReg Reading success val is %x, status%d\n", Data, status); | ||
2399 | Data |= 0x08; /* setting driver done bit */ | ||
2400 | Data |= 0x04; /* sp1_bit to have cts change reflect in | ||
2401 | modem status reg */ | ||
2402 | |||
2403 | /* Data |= 0x20; //rx_disable bit */ | ||
2404 | status = mos7840_set_reg_sync(port, | ||
2405 | mos7840_port->ControlRegOffset, Data); | ||
2406 | if (status < 0) { | ||
2407 | dev_dbg(&port->dev, "Writing ControlReg failed(rx_disable) status-0x%x\n", status); | ||
2408 | goto out; | ||
2409 | } else | ||
2410 | dev_dbg(&port->dev, "ControlReg Writing success(rx_disable) status%d\n", status); | ||
2411 | |||
2412 | /* Write default values in DCR (i.e 0x01 in DCR0, 0x05 in DCR2 | ||
2413 | and 0x24 in DCR3 */ | ||
2414 | Data = 0x01; | ||
2415 | status = mos7840_set_reg_sync(port, | ||
2416 | (__u16) (mos7840_port->DcrRegOffset + 0), Data); | ||
2417 | if (status < 0) { | ||
2418 | dev_dbg(&port->dev, "Writing DCR0 failed status-0x%x\n", status); | ||
2419 | goto out; | ||
2420 | } else | ||
2421 | dev_dbg(&port->dev, "DCR0 Writing success status%d\n", status); | ||
2409 | 2422 | ||
2410 | /* Data |= 0x20; //rx_disable bit */ | 2423 | Data = 0x05; |
2411 | status = mos7840_set_reg_sync(port, | 2424 | status = mos7840_set_reg_sync(port, |
2412 | mos7840_port->ControlRegOffset, Data); | 2425 | (__u16) (mos7840_port->DcrRegOffset + 1), Data); |
2413 | if (status < 0) { | 2426 | if (status < 0) { |
2414 | dev_dbg(&port->dev, "Writing ControlReg failed(rx_disable) status-0x%x\n", status); | 2427 | dev_dbg(&port->dev, "Writing DCR1 failed status-0x%x\n", status); |
2415 | break; | 2428 | goto out; |
2416 | } else | 2429 | } else |
2417 | dev_dbg(&port->dev, "ControlReg Writing success(rx_disable) status%d\n", status); | 2430 | dev_dbg(&port->dev, "DCR1 Writing success status%d\n", status); |
2418 | 2431 | ||
2419 | /* Write default values in DCR (i.e 0x01 in DCR0, 0x05 in DCR2 | 2432 | Data = 0x24; |
2420 | and 0x24 in DCR3 */ | 2433 | status = mos7840_set_reg_sync(port, |
2421 | Data = 0x01; | 2434 | (__u16) (mos7840_port->DcrRegOffset + 2), Data); |
2422 | status = mos7840_set_reg_sync(port, | 2435 | if (status < 0) { |
2423 | (__u16) (mos7840_port->DcrRegOffset + 0), Data); | 2436 | dev_dbg(&port->dev, "Writing DCR2 failed status-0x%x\n", status); |
2424 | if (status < 0) { | 2437 | goto out; |
2425 | dev_dbg(&port->dev, "Writing DCR0 failed status-0x%x\n", status); | 2438 | } else |
2426 | break; | 2439 | dev_dbg(&port->dev, "DCR2 Writing success status%d\n", status); |
2427 | } else | ||
2428 | dev_dbg(&port->dev, "DCR0 Writing success status%d\n", status); | ||
2429 | 2440 | ||
2430 | Data = 0x05; | 2441 | /* write values in clkstart0x0 and clkmulti 0x20 */ |
2431 | status = mos7840_set_reg_sync(port, | 2442 | Data = 0x0; |
2432 | (__u16) (mos7840_port->DcrRegOffset + 1), Data); | 2443 | status = mos7840_set_reg_sync(port, CLK_START_VALUE_REGISTER, Data); |
2433 | if (status < 0) { | 2444 | if (status < 0) { |
2434 | dev_dbg(&port->dev, "Writing DCR1 failed status-0x%x\n", status); | 2445 | dev_dbg(&port->dev, "Writing CLK_START_VALUE_REGISTER failed status-0x%x\n", status); |
2435 | break; | 2446 | goto out; |
2436 | } else | 2447 | } else |
2437 | dev_dbg(&port->dev, "DCR1 Writing success status%d\n", status); | 2448 | dev_dbg(&port->dev, "CLK_START_VALUE_REGISTER Writing success status%d\n", status); |
2438 | 2449 | ||
2439 | Data = 0x24; | 2450 | Data = 0x20; |
2440 | status = mos7840_set_reg_sync(port, | 2451 | status = mos7840_set_reg_sync(port, CLK_MULTI_REGISTER, Data); |
2441 | (__u16) (mos7840_port->DcrRegOffset + 2), Data); | 2452 | if (status < 0) { |
2442 | if (status < 0) { | 2453 | dev_dbg(&port->dev, "Writing CLK_MULTI_REGISTER failed status-0x%x\n", status); |
2443 | dev_dbg(&port->dev, "Writing DCR2 failed status-0x%x\n", status); | 2454 | goto error; |
2444 | break; | 2455 | } else |
2445 | } else | 2456 | dev_dbg(&port->dev, "CLK_MULTI_REGISTER Writing success status%d\n", status); |
2446 | dev_dbg(&port->dev, "DCR2 Writing success status%d\n", status); | ||
2447 | 2457 | ||
2448 | /* write values in clkstart0x0 and clkmulti 0x20 */ | 2458 | /* write value 0x0 to scratchpad register */ |
2449 | Data = 0x0; | 2459 | Data = 0x00; |
2460 | status = mos7840_set_uart_reg(port, SCRATCH_PAD_REGISTER, Data); | ||
2461 | if (status < 0) { | ||
2462 | dev_dbg(&port->dev, "Writing SCRATCH_PAD_REGISTER failed status-0x%x\n", status); | ||
2463 | goto out; | ||
2464 | } else | ||
2465 | dev_dbg(&port->dev, "SCRATCH_PAD_REGISTER Writing success status%d\n", status); | ||
2466 | |||
2467 | /* Zero Length flag register */ | ||
2468 | if ((mos7840_port->port_num != 1) && (serial->num_ports == 2)) { | ||
2469 | Data = 0xff; | ||
2450 | status = mos7840_set_reg_sync(port, | 2470 | status = mos7840_set_reg_sync(port, |
2451 | CLK_START_VALUE_REGISTER, Data); | 2471 | (__u16) (ZLP_REG1 + |
2472 | ((__u16)mos7840_port->port_num)), Data); | ||
2473 | dev_dbg(&port->dev, "ZLIP offset %x\n", | ||
2474 | (__u16)(ZLP_REG1 + ((__u16) mos7840_port->port_num))); | ||
2452 | if (status < 0) { | 2475 | if (status < 0) { |
2453 | dev_dbg(&port->dev, "Writing CLK_START_VALUE_REGISTER failed status-0x%x\n", status); | 2476 | dev_dbg(&port->dev, "Writing ZLP_REG%d failed status-0x%x\n", pnum + 2, status); |
2454 | break; | 2477 | goto out; |
2455 | } else | 2478 | } else |
2456 | dev_dbg(&port->dev, "CLK_START_VALUE_REGISTER Writing success status%d\n", status); | 2479 | dev_dbg(&port->dev, "ZLP_REG%d Writing success status%d\n", pnum + 2, status); |
2457 | 2480 | } else { | |
2458 | Data = 0x20; | 2481 | Data = 0xff; |
2459 | status = mos7840_set_reg_sync(port, | 2482 | status = mos7840_set_reg_sync(port, |
2460 | CLK_MULTI_REGISTER, Data); | 2483 | (__u16) (ZLP_REG1 + |
2461 | if (status < 0) { | 2484 | ((__u16)mos7840_port->port_num) - 0x1), Data); |
2462 | dev_dbg(&port->dev, "Writing CLK_MULTI_REGISTER failed status-0x%x\n", status); | 2485 | dev_dbg(&port->dev, "ZLIP offset %x\n", |
2463 | goto error; | 2486 | (__u16)(ZLP_REG1 + ((__u16) mos7840_port->port_num) - 0x1)); |
2464 | } else | ||
2465 | dev_dbg(&port->dev, "CLK_MULTI_REGISTER Writing success status%d\n", status); | ||
2466 | |||
2467 | /* write value 0x0 to scratchpad register */ | ||
2468 | Data = 0x00; | ||
2469 | status = mos7840_set_uart_reg(port, | ||
2470 | SCRATCH_PAD_REGISTER, Data); | ||
2471 | if (status < 0) { | 2487 | if (status < 0) { |
2472 | dev_dbg(&port->dev, "Writing SCRATCH_PAD_REGISTER failed status-0x%x\n", status); | 2488 | dev_dbg(&port->dev, "Writing ZLP_REG%d failed status-0x%x\n", pnum + 1, status); |
2473 | break; | 2489 | goto out; |
2474 | } else | 2490 | } else |
2475 | dev_dbg(&port->dev, "SCRATCH_PAD_REGISTER Writing success status%d\n", status); | 2491 | dev_dbg(&port->dev, "ZLP_REG%d Writing success status%d\n", pnum + 1, status); |
2476 | 2492 | ||
2477 | /* Zero Length flag register */ | 2493 | } |
2478 | if ((mos7840_port->port_num != 1) | 2494 | mos7840_port->control_urb = usb_alloc_urb(0, GFP_KERNEL); |
2479 | && (serial->num_ports == 2)) { | 2495 | mos7840_port->ctrl_buf = kmalloc(16, GFP_KERNEL); |
2480 | 2496 | mos7840_port->dr = kmalloc(sizeof(struct usb_ctrlrequest), | |
2481 | Data = 0xff; | 2497 | GFP_KERNEL); |
2482 | status = mos7840_set_reg_sync(port, | 2498 | if (!mos7840_port->control_urb || !mos7840_port->ctrl_buf || |
2483 | (__u16) (ZLP_REG1 + | 2499 | !mos7840_port->dr) { |
2484 | ((__u16)mos7840_port->port_num)), Data); | 2500 | status = -ENOMEM; |
2485 | dev_dbg(&port->dev, "ZLIP offset %x\n", | 2501 | goto error; |
2486 | (__u16)(ZLP_REG1 + ((__u16) mos7840_port->port_num))); | 2502 | } |
2487 | if (status < 0) { | ||
2488 | dev_dbg(&port->dev, "Writing ZLP_REG%d failed status-0x%x\n", pnum + 2, status); | ||
2489 | break; | ||
2490 | } else | ||
2491 | dev_dbg(&port->dev, "ZLP_REG%d Writing success status%d\n", pnum + 2, status); | ||
2492 | } else { | ||
2493 | Data = 0xff; | ||
2494 | status = mos7840_set_reg_sync(port, | ||
2495 | (__u16) (ZLP_REG1 + | ||
2496 | ((__u16)mos7840_port->port_num) - 0x1), Data); | ||
2497 | dev_dbg(&port->dev, "ZLIP offset %x\n", | ||
2498 | (__u16)(ZLP_REG1 + ((__u16) mos7840_port->port_num) - 0x1)); | ||
2499 | if (status < 0) { | ||
2500 | dev_dbg(&port->dev, "Writing ZLP_REG%d failed status-0x%x\n", pnum + 1, status); | ||
2501 | break; | ||
2502 | } else | ||
2503 | dev_dbg(&port->dev, "ZLP_REG%d Writing success status%d\n", pnum + 1, status); | ||
2504 | |||
2505 | } | ||
2506 | mos7840_port->control_urb = usb_alloc_urb(0, GFP_KERNEL); | ||
2507 | mos7840_port->ctrl_buf = kmalloc(16, GFP_KERNEL); | ||
2508 | mos7840_port->dr = kmalloc(sizeof(struct usb_ctrlrequest), | ||
2509 | GFP_KERNEL); | ||
2510 | if (!mos7840_port->control_urb || !mos7840_port->ctrl_buf || | ||
2511 | !mos7840_port->dr) { | ||
2512 | status = -ENOMEM; | ||
2513 | goto error; | ||
2514 | } | ||
2515 | |||
2516 | mos7840_port->has_led = false; | ||
2517 | 2503 | ||
2518 | /* Initialize LED timers */ | 2504 | mos7840_port->has_led = false; |
2519 | if (device_type == MOSCHIP_DEVICE_ID_7810) { | ||
2520 | mos7840_port->has_led = true; | ||
2521 | 2505 | ||
2522 | init_timer(&mos7840_port->led_timer1); | 2506 | /* Initialize LED timers */ |
2523 | mos7840_port->led_timer1.function = mos7840_led_off; | 2507 | if (device_type == MOSCHIP_DEVICE_ID_7810) { |
2524 | mos7840_port->led_timer1.expires = | 2508 | mos7840_port->has_led = true; |
2525 | jiffies + msecs_to_jiffies(LED_ON_MS); | ||
2526 | mos7840_port->led_timer1.data = | ||
2527 | (unsigned long)mos7840_port; | ||
2528 | 2509 | ||
2529 | init_timer(&mos7840_port->led_timer2); | 2510 | init_timer(&mos7840_port->led_timer1); |
2530 | mos7840_port->led_timer2.function = | 2511 | mos7840_port->led_timer1.function = mos7840_led_off; |
2531 | mos7840_led_flag_off; | 2512 | mos7840_port->led_timer1.expires = |
2532 | mos7840_port->led_timer2.expires = | 2513 | jiffies + msecs_to_jiffies(LED_ON_MS); |
2533 | jiffies + msecs_to_jiffies(LED_OFF_MS); | 2514 | mos7840_port->led_timer1.data = (unsigned long)mos7840_port; |
2534 | mos7840_port->led_timer2.data = | ||
2535 | (unsigned long)mos7840_port; | ||
2536 | 2515 | ||
2537 | mos7840_port->led_flag = false; | 2516 | init_timer(&mos7840_port->led_timer2); |
2517 | mos7840_port->led_timer2.function = mos7840_led_flag_off; | ||
2518 | mos7840_port->led_timer2.expires = | ||
2519 | jiffies + msecs_to_jiffies(LED_OFF_MS); | ||
2520 | mos7840_port->led_timer2.data = (unsigned long)mos7840_port; | ||
2538 | 2521 | ||
2539 | /* Turn off LED */ | 2522 | mos7840_port->led_flag = false; |
2540 | mos7840_set_led_sync(port, | ||
2541 | MODEM_CONTROL_REGISTER, 0x0300); | ||
2542 | } | ||
2543 | } while (0); | ||
2544 | 2523 | ||
2524 | /* Turn off LED */ | ||
2525 | mos7840_set_led_sync(port, MODEM_CONTROL_REGISTER, 0x0300); | ||
2526 | } | ||
2527 | out: | ||
2545 | if (pnum == serial->num_ports - 1) { | 2528 | if (pnum == serial->num_ports - 1) { |
2546 | /* Zero Length flag enable */ | 2529 | /* Zero Length flag enable */ |
2547 | Data = 0x0f; | 2530 | Data = 0x0f; |