diff options
Diffstat (limited to 'drivers/misc/ti-st/st_kim.c')
-rw-r--r-- | drivers/misc/ti-st/st_kim.c | 109 |
1 files changed, 44 insertions, 65 deletions
diff --git a/drivers/misc/ti-st/st_kim.c b/drivers/misc/ti-st/st_kim.c index 7c14f8fd98d..04a819944f6 100644 --- a/drivers/misc/ti-st/st_kim.c +++ b/drivers/misc/ti-st/st_kim.c | |||
@@ -63,10 +63,27 @@ static struct platform_device *st_get_plat_device(int id) | |||
63 | * in case of error don't complete so that waiting for proper | 63 | * in case of error don't complete so that waiting for proper |
64 | * response times out | 64 | * response times out |
65 | */ | 65 | */ |
66 | void validate_firmware_response(struct kim_data_s *kim_gdata) | 66 | static void validate_firmware_response(struct kim_data_s *kim_gdata) |
67 | { | 67 | { |
68 | struct sk_buff *skb = kim_gdata->rx_skb; | 68 | struct sk_buff *skb = kim_gdata->rx_skb; |
69 | if (unlikely(skb->data[5] != 0)) { | 69 | if (!skb) |
70 | return; | ||
71 | |||
72 | /* these magic numbers are the position in the response buffer which | ||
73 | * allows us to distinguish whether the response is for the read | ||
74 | * version info. command | ||
75 | */ | ||
76 | if (skb->data[2] == 0x01 && skb->data[3] == 0x01 && | ||
77 | skb->data[4] == 0x10 && skb->data[5] == 0x00) { | ||
78 | /* fw version response */ | ||
79 | memcpy(kim_gdata->resp_buffer, | ||
80 | kim_gdata->rx_skb->data, | ||
81 | kim_gdata->rx_skb->len); | ||
82 | complete_all(&kim_gdata->kim_rcvd); | ||
83 | kim_gdata->rx_state = ST_W4_PACKET_TYPE; | ||
84 | kim_gdata->rx_skb = NULL; | ||
85 | kim_gdata->rx_count = 0; | ||
86 | } else if (unlikely(skb->data[5] != 0)) { | ||
70 | pr_err("no proper response during fw download"); | 87 | pr_err("no proper response during fw download"); |
71 | pr_err("data6 %x", skb->data[5]); | 88 | pr_err("data6 %x", skb->data[5]); |
72 | kfree_skb(skb); | 89 | kfree_skb(skb); |
@@ -119,7 +136,7 @@ static inline int kim_check_data_len(struct kim_data_s *kim_gdata, int len) | |||
119 | * have been observed to come in bursts of different | 136 | * have been observed to come in bursts of different |
120 | * tty_receive and hence the logic | 137 | * tty_receive and hence the logic |
121 | */ | 138 | */ |
122 | void kim_int_recv(struct kim_data_s *kim_gdata, | 139 | static void kim_int_recv(struct kim_data_s *kim_gdata, |
123 | const unsigned char *data, long count) | 140 | const unsigned char *data, long count) |
124 | { | 141 | { |
125 | const unsigned char *ptr; | 142 | const unsigned char *ptr; |
@@ -207,16 +224,19 @@ static long read_local_version(struct kim_data_s *kim_gdata, char *bts_scr_name) | |||
207 | return -EIO; | 224 | return -EIO; |
208 | } | 225 | } |
209 | 226 | ||
210 | if (!wait_for_completion_timeout | 227 | if (!wait_for_completion_interruptible_timeout( |
211 | (&kim_gdata->kim_rcvd, msecs_to_jiffies(CMD_RESP_TIME))) { | 228 | &kim_gdata->kim_rcvd, msecs_to_jiffies(CMD_RESP_TIME))) { |
212 | pr_err(" waiting for ver info- timed out "); | 229 | pr_err(" waiting for ver info- timed out "); |
213 | return -ETIMEDOUT; | 230 | return -ETIMEDOUT; |
214 | } | 231 | } |
215 | INIT_COMPLETION(kim_gdata->kim_rcvd); | 232 | INIT_COMPLETION(kim_gdata->kim_rcvd); |
233 | /* the positions 12 & 13 in the response buffer provide with the | ||
234 | * chip, major & minor numbers | ||
235 | */ | ||
216 | 236 | ||
217 | version = | 237 | version = |
218 | MAKEWORD(kim_gdata->resp_buffer[13], | 238 | MAKEWORD(kim_gdata->resp_buffer[12], |
219 | kim_gdata->resp_buffer[14]); | 239 | kim_gdata->resp_buffer[13]); |
220 | chip = (version & 0x7C00) >> 10; | 240 | chip = (version & 0x7C00) >> 10; |
221 | min_ver = (version & 0x007F); | 241 | min_ver = (version & 0x007F); |
222 | maj_ver = (version & 0x0380) >> 7; | 242 | maj_ver = (version & 0x0380) >> 7; |
@@ -236,7 +256,7 @@ static long read_local_version(struct kim_data_s *kim_gdata, char *bts_scr_name) | |||
236 | return 0; | 256 | return 0; |
237 | } | 257 | } |
238 | 258 | ||
239 | void skip_change_remote_baud(unsigned char **ptr, long *len) | 259 | static void skip_change_remote_baud(unsigned char **ptr, long *len) |
240 | { | 260 | { |
241 | unsigned char *nxt_action, *cur_action; | 261 | unsigned char *nxt_action, *cur_action; |
242 | cur_action = *ptr; | 262 | cur_action = *ptr; |
@@ -370,9 +390,9 @@ static long download_firmware(struct kim_data_s *kim_gdata) | |||
370 | break; | 390 | break; |
371 | case ACTION_WAIT_EVENT: /* wait */ | 391 | case ACTION_WAIT_EVENT: /* wait */ |
372 | pr_debug("W"); | 392 | pr_debug("W"); |
373 | if (!wait_for_completion_timeout | 393 | if (!wait_for_completion_interruptible_timeout( |
374 | (&kim_gdata->kim_rcvd, | 394 | &kim_gdata->kim_rcvd, |
375 | msecs_to_jiffies(CMD_RESP_TIME))) { | 395 | msecs_to_jiffies(CMD_RESP_TIME))) { |
376 | pr_err("response timeout during fw download "); | 396 | pr_err("response timeout during fw download "); |
377 | /* timed out */ | 397 | /* timed out */ |
378 | release_firmware(kim_gdata->fw_entry); | 398 | release_firmware(kim_gdata->fw_entry); |
@@ -410,16 +430,10 @@ void st_kim_recv(void *disc_data, const unsigned char *data, long count) | |||
410 | struct st_data_s *st_gdata = (struct st_data_s *)disc_data; | 430 | struct st_data_s *st_gdata = (struct st_data_s *)disc_data; |
411 | struct kim_data_s *kim_gdata = st_gdata->kim_data; | 431 | struct kim_data_s *kim_gdata = st_gdata->kim_data; |
412 | 432 | ||
413 | /* copy to local buffer */ | 433 | /* proceed to gather all data and distinguish read fw version response |
414 | if (unlikely(data[4] == 0x01 && data[5] == 0x10 && data[0] == 0x04)) { | 434 | * from other fw responses when data gathering is complete |
415 | /* must be the read_ver_cmd */ | 435 | */ |
416 | memcpy(kim_gdata->resp_buffer, data, count); | 436 | kim_int_recv(kim_gdata, data, count); |
417 | complete_all(&kim_gdata->kim_rcvd); | ||
418 | return; | ||
419 | } else { | ||
420 | kim_int_recv(kim_gdata, data, count); | ||
421 | /* either completes or times out */ | ||
422 | } | ||
423 | return; | 437 | return; |
424 | } | 438 | } |
425 | 439 | ||
@@ -454,11 +468,6 @@ long st_kim_start(void *kim_data) | |||
454 | if (pdata->chip_enable) | 468 | if (pdata->chip_enable) |
455 | pdata->chip_enable(kim_gdata); | 469 | pdata->chip_enable(kim_gdata); |
456 | 470 | ||
457 | /* Configure BT nShutdown to HIGH state */ | ||
458 | gpio_set_value(kim_gdata->nshutdown, GPIO_LOW); | ||
459 | mdelay(5); /* FIXME: a proper toggle */ | ||
460 | gpio_set_value(kim_gdata->nshutdown, GPIO_HIGH); | ||
461 | mdelay(100); | ||
462 | /* re-initialize the completion */ | 471 | /* re-initialize the completion */ |
463 | INIT_COMPLETION(kim_gdata->ldisc_installed); | 472 | INIT_COMPLETION(kim_gdata->ldisc_installed); |
464 | /* send notification to UIM */ | 473 | /* send notification to UIM */ |
@@ -467,8 +476,8 @@ long st_kim_start(void *kim_data) | |||
467 | sysfs_notify(&kim_gdata->kim_pdev->dev.kobj, | 476 | sysfs_notify(&kim_gdata->kim_pdev->dev.kobj, |
468 | NULL, "install"); | 477 | NULL, "install"); |
469 | /* wait for ldisc to be installed */ | 478 | /* wait for ldisc to be installed */ |
470 | err = wait_for_completion_timeout(&kim_gdata->ldisc_installed, | 479 | err = wait_for_completion_interruptible_timeout( |
471 | msecs_to_jiffies(LDISC_TIME)); | 480 | &kim_gdata->ldisc_installed, msecs_to_jiffies(LDISC_TIME)); |
472 | if (!err) { | 481 | if (!err) { |
473 | /* ldisc installation timeout, | 482 | /* ldisc installation timeout, |
474 | * flush uart, power cycle BT_EN */ | 483 | * flush uart, power cycle BT_EN */ |
@@ -500,8 +509,7 @@ long st_kim_start(void *kim_data) | |||
500 | * (b) upon failure to either install ldisc or download firmware. | 509 | * (b) upon failure to either install ldisc or download firmware. |
501 | * The function is responsible to (a) notify UIM about un-installation, | 510 | * The function is responsible to (a) notify UIM about un-installation, |
502 | * (b) flush UART if the ldisc was installed. | 511 | * (b) flush UART if the ldisc was installed. |
503 | * (c) reset BT_EN - pull down nshutdown at the end. | 512 | * (c) invoke platform's chip disabling routine. |
504 | * (d) invoke platform's chip disabling routine. | ||
505 | */ | 513 | */ |
506 | long st_kim_stop(void *kim_data) | 514 | long st_kim_stop(void *kim_data) |
507 | { | 515 | { |
@@ -526,20 +534,13 @@ long st_kim_stop(void *kim_data) | |||
526 | sysfs_notify(&kim_gdata->kim_pdev->dev.kobj, NULL, "install"); | 534 | sysfs_notify(&kim_gdata->kim_pdev->dev.kobj, NULL, "install"); |
527 | 535 | ||
528 | /* wait for ldisc to be un-installed */ | 536 | /* wait for ldisc to be un-installed */ |
529 | err = wait_for_completion_timeout(&kim_gdata->ldisc_installed, | 537 | err = wait_for_completion_interruptible_timeout( |
530 | msecs_to_jiffies(LDISC_TIME)); | 538 | &kim_gdata->ldisc_installed, msecs_to_jiffies(LDISC_TIME)); |
531 | if (!err) { /* timeout */ | 539 | if (!err) { /* timeout */ |
532 | pr_err(" timed out waiting for ldisc to be un-installed"); | 540 | pr_err(" timed out waiting for ldisc to be un-installed"); |
533 | return -ETIMEDOUT; | 541 | err = -ETIMEDOUT; |
534 | } | 542 | } |
535 | 543 | ||
536 | /* By default configure BT nShutdown to LOW state */ | ||
537 | gpio_set_value(kim_gdata->nshutdown, GPIO_LOW); | ||
538 | mdelay(1); | ||
539 | gpio_set_value(kim_gdata->nshutdown, GPIO_HIGH); | ||
540 | mdelay(1); | ||
541 | gpio_set_value(kim_gdata->nshutdown, GPIO_LOW); | ||
542 | |||
543 | /* platform specific disable */ | 544 | /* platform specific disable */ |
544 | if (pdata->chip_disable) | 545 | if (pdata->chip_disable) |
545 | pdata->chip_disable(kim_gdata); | 546 | pdata->chip_disable(kim_gdata); |
@@ -701,7 +702,7 @@ static const struct file_operations list_debugfs_fops = { | |||
701 | * board-*.c file | 702 | * board-*.c file |
702 | */ | 703 | */ |
703 | 704 | ||
704 | struct dentry *kim_debugfs_dir; | 705 | static struct dentry *kim_debugfs_dir; |
705 | static int kim_probe(struct platform_device *pdev) | 706 | static int kim_probe(struct platform_device *pdev) |
706 | { | 707 | { |
707 | long status; | 708 | long status; |
@@ -731,20 +732,6 @@ static int kim_probe(struct platform_device *pdev) | |||
731 | /* refer to itself */ | 732 | /* refer to itself */ |
732 | kim_gdata->core_data->kim_data = kim_gdata; | 733 | kim_gdata->core_data->kim_data = kim_gdata; |
733 | 734 | ||
734 | /* Claim the chip enable nShutdown gpio from the system */ | ||
735 | kim_gdata->nshutdown = pdata->nshutdown_gpio; | ||
736 | status = gpio_request(kim_gdata->nshutdown, "kim"); | ||
737 | if (unlikely(status)) { | ||
738 | pr_err(" gpio %ld request failed ", kim_gdata->nshutdown); | ||
739 | return status; | ||
740 | } | ||
741 | |||
742 | /* Configure nShutdown GPIO as output=0 */ | ||
743 | status = gpio_direction_output(kim_gdata->nshutdown, 0); | ||
744 | if (unlikely(status)) { | ||
745 | pr_err(" unable to configure gpio %ld", kim_gdata->nshutdown); | ||
746 | return status; | ||
747 | } | ||
748 | /* get reference of pdev for request_firmware | 735 | /* get reference of pdev for request_firmware |
749 | */ | 736 | */ |
750 | kim_gdata->kim_pdev = pdev; | 737 | kim_gdata->kim_pdev = pdev; |
@@ -780,18 +767,10 @@ static int kim_probe(struct platform_device *pdev) | |||
780 | 767 | ||
781 | static int kim_remove(struct platform_device *pdev) | 768 | static int kim_remove(struct platform_device *pdev) |
782 | { | 769 | { |
783 | /* free the GPIOs requested */ | ||
784 | struct ti_st_plat_data *pdata = pdev->dev.platform_data; | ||
785 | struct kim_data_s *kim_gdata; | 770 | struct kim_data_s *kim_gdata; |
786 | 771 | ||
787 | kim_gdata = dev_get_drvdata(&pdev->dev); | 772 | kim_gdata = dev_get_drvdata(&pdev->dev); |
788 | 773 | ||
789 | /* Free the Bluetooth/FM/GPIO | ||
790 | * nShutdown gpio from the system | ||
791 | */ | ||
792 | gpio_free(pdata->nshutdown_gpio); | ||
793 | pr_info("nshutdown GPIO Freed"); | ||
794 | |||
795 | debugfs_remove_recursive(kim_debugfs_dir); | 774 | debugfs_remove_recursive(kim_debugfs_dir); |
796 | sysfs_remove_group(&pdev->dev.kobj, &uim_attr_grp); | 775 | sysfs_remove_group(&pdev->dev.kobj, &uim_attr_grp); |
797 | pr_info("sysfs entries removed"); | 776 | pr_info("sysfs entries removed"); |
@@ -804,7 +783,7 @@ static int kim_remove(struct platform_device *pdev) | |||
804 | return 0; | 783 | return 0; |
805 | } | 784 | } |
806 | 785 | ||
807 | int kim_suspend(struct platform_device *pdev, pm_message_t state) | 786 | static int kim_suspend(struct platform_device *pdev, pm_message_t state) |
808 | { | 787 | { |
809 | struct ti_st_plat_data *pdata = pdev->dev.platform_data; | 788 | struct ti_st_plat_data *pdata = pdev->dev.platform_data; |
810 | 789 | ||
@@ -814,7 +793,7 @@ int kim_suspend(struct platform_device *pdev, pm_message_t state) | |||
814 | return -EOPNOTSUPP; | 793 | return -EOPNOTSUPP; |
815 | } | 794 | } |
816 | 795 | ||
817 | int kim_resume(struct platform_device *pdev) | 796 | static int kim_resume(struct platform_device *pdev) |
818 | { | 797 | { |
819 | struct ti_st_plat_data *pdata = pdev->dev.platform_data; | 798 | struct ti_st_plat_data *pdata = pdev->dev.platform_data; |
820 | 799 | ||