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; |
