diff options
Diffstat (limited to 'drivers/misc/ti-st/st_kim.c')
| -rw-r--r-- | drivers/misc/ti-st/st_kim.c | 144 |
1 files changed, 114 insertions, 30 deletions
diff --git a/drivers/misc/ti-st/st_kim.c b/drivers/misc/ti-st/st_kim.c index e4b7ee4f57b8..18e7a03985d4 100644 --- a/drivers/misc/ti-st/st_kim.c +++ b/drivers/misc/ti-st/st_kim.c | |||
| @@ -36,7 +36,8 @@ | |||
| 36 | #include <linux/skbuff.h> | 36 | #include <linux/skbuff.h> |
| 37 | #include <linux/ti_wilink_st.h> | 37 | #include <linux/ti_wilink_st.h> |
| 38 | #include <linux/module.h> | 38 | #include <linux/module.h> |
| 39 | 39 | #include <linux/of.h> | |
| 40 | #include <linux/of_device.h> | ||
| 40 | 41 | ||
| 41 | #define MAX_ST_DEVICES 3 /* Imagine 1 on each UART for now */ | 42 | #define MAX_ST_DEVICES 3 /* Imagine 1 on each UART for now */ |
| 42 | static struct platform_device *st_kim_devices[MAX_ST_DEVICES]; | 43 | static struct platform_device *st_kim_devices[MAX_ST_DEVICES]; |
| @@ -44,6 +45,9 @@ static struct platform_device *st_kim_devices[MAX_ST_DEVICES]; | |||
| 44 | /**********************************************************************/ | 45 | /**********************************************************************/ |
| 45 | /* internal functions */ | 46 | /* internal functions */ |
| 46 | 47 | ||
| 48 | struct ti_st_plat_data *dt_pdata; | ||
| 49 | static struct ti_st_plat_data *get_platform_data(struct device *dev); | ||
| 50 | |||
| 47 | /** | 51 | /** |
| 48 | * st_get_plat_device - | 52 | * st_get_plat_device - |
| 49 | * function which returns the reference to the platform device | 53 | * function which returns the reference to the platform device |
| @@ -215,6 +219,7 @@ static long read_local_version(struct kim_data_s *kim_gdata, char *bts_scr_name) | |||
| 215 | { | 219 | { |
| 216 | unsigned short version = 0, chip = 0, min_ver = 0, maj_ver = 0; | 220 | unsigned short version = 0, chip = 0, min_ver = 0, maj_ver = 0; |
| 217 | const char read_ver_cmd[] = { 0x01, 0x01, 0x10, 0x00 }; | 221 | const char read_ver_cmd[] = { 0x01, 0x01, 0x10, 0x00 }; |
| 222 | long timeout; | ||
| 218 | 223 | ||
| 219 | pr_debug("%s", __func__); | 224 | pr_debug("%s", __func__); |
| 220 | 225 | ||
| @@ -224,10 +229,11 @@ static long read_local_version(struct kim_data_s *kim_gdata, char *bts_scr_name) | |||
| 224 | return -EIO; | 229 | return -EIO; |
| 225 | } | 230 | } |
| 226 | 231 | ||
| 227 | if (!wait_for_completion_interruptible_timeout( | 232 | timeout = wait_for_completion_interruptible_timeout( |
| 228 | &kim_gdata->kim_rcvd, msecs_to_jiffies(CMD_RESP_TIME))) { | 233 | &kim_gdata->kim_rcvd, msecs_to_jiffies(CMD_RESP_TIME)); |
| 229 | pr_err(" waiting for ver info- timed out "); | 234 | if (timeout <= 0) { |
| 230 | return -ETIMEDOUT; | 235 | pr_err(" waiting for ver info- timed out or received signal"); |
| 236 | return timeout ? -ERESTARTSYS : -ETIMEDOUT; | ||
| 231 | } | 237 | } |
| 232 | reinit_completion(&kim_gdata->kim_rcvd); | 238 | reinit_completion(&kim_gdata->kim_rcvd); |
| 233 | /* the positions 12 & 13 in the response buffer provide with the | 239 | /* the positions 12 & 13 in the response buffer provide with the |
| @@ -391,13 +397,14 @@ static long download_firmware(struct kim_data_s *kim_gdata) | |||
| 391 | break; | 397 | break; |
| 392 | case ACTION_WAIT_EVENT: /* wait */ | 398 | case ACTION_WAIT_EVENT: /* wait */ |
| 393 | pr_debug("W"); | 399 | pr_debug("W"); |
| 394 | if (!wait_for_completion_interruptible_timeout( | 400 | err = wait_for_completion_interruptible_timeout( |
| 395 | &kim_gdata->kim_rcvd, | 401 | &kim_gdata->kim_rcvd, |
| 396 | msecs_to_jiffies(CMD_RESP_TIME))) { | 402 | msecs_to_jiffies(CMD_RESP_TIME)); |
| 397 | pr_err("response timeout during fw download "); | 403 | if (err <= 0) { |
| 404 | pr_err("response timeout/signaled during fw download "); | ||
| 398 | /* timed out */ | 405 | /* timed out */ |
| 399 | release_firmware(kim_gdata->fw_entry); | 406 | release_firmware(kim_gdata->fw_entry); |
| 400 | return -ETIMEDOUT; | 407 | return err ? -ERESTARTSYS : -ETIMEDOUT; |
| 401 | } | 408 | } |
| 402 | reinit_completion(&kim_gdata->kim_rcvd); | 409 | reinit_completion(&kim_gdata->kim_rcvd); |
| 403 | break; | 410 | break; |
| @@ -462,7 +469,12 @@ long st_kim_start(void *kim_data) | |||
| 462 | struct kim_data_s *kim_gdata = (struct kim_data_s *)kim_data; | 469 | struct kim_data_s *kim_gdata = (struct kim_data_s *)kim_data; |
| 463 | 470 | ||
| 464 | pr_info(" %s", __func__); | 471 | pr_info(" %s", __func__); |
| 465 | pdata = kim_gdata->kim_pdev->dev.platform_data; | 472 | if (kim_gdata->kim_pdev->dev.of_node) { |
| 473 | pr_debug("use device tree data"); | ||
| 474 | pdata = dt_pdata; | ||
| 475 | } else { | ||
| 476 | pdata = kim_gdata->kim_pdev->dev.platform_data; | ||
| 477 | } | ||
| 466 | 478 | ||
| 467 | do { | 479 | do { |
| 468 | /* platform specific enabling code here */ | 480 | /* platform specific enabling code here */ |
| @@ -522,12 +534,18 @@ long st_kim_stop(void *kim_data) | |||
| 522 | { | 534 | { |
| 523 | long err = 0; | 535 | long err = 0; |
| 524 | struct kim_data_s *kim_gdata = (struct kim_data_s *)kim_data; | 536 | struct kim_data_s *kim_gdata = (struct kim_data_s *)kim_data; |
| 525 | struct ti_st_plat_data *pdata = | 537 | struct ti_st_plat_data *pdata; |
| 526 | kim_gdata->kim_pdev->dev.platform_data; | ||
| 527 | struct tty_struct *tty = kim_gdata->core_data->tty; | 538 | struct tty_struct *tty = kim_gdata->core_data->tty; |
| 528 | 539 | ||
| 529 | reinit_completion(&kim_gdata->ldisc_installed); | 540 | reinit_completion(&kim_gdata->ldisc_installed); |
| 530 | 541 | ||
| 542 | if (kim_gdata->kim_pdev->dev.of_node) { | ||
| 543 | pr_debug("use device tree data"); | ||
| 544 | pdata = dt_pdata; | ||
| 545 | } else | ||
| 546 | pdata = kim_gdata->kim_pdev->dev.platform_data; | ||
| 547 | |||
| 548 | |||
| 531 | if (tty) { /* can be called before ldisc is installed */ | 549 | if (tty) { /* can be called before ldisc is installed */ |
| 532 | /* Flush any pending characters in the driver and discipline. */ | 550 | /* Flush any pending characters in the driver and discipline. */ |
| 533 | tty_ldisc_flush(tty); | 551 | tty_ldisc_flush(tty); |
| @@ -620,7 +638,7 @@ static ssize_t show_baud_rate(struct device *dev, | |||
| 620 | struct device_attribute *attr, char *buf) | 638 | struct device_attribute *attr, char *buf) |
| 621 | { | 639 | { |
| 622 | struct kim_data_s *kim_data = dev_get_drvdata(dev); | 640 | struct kim_data_s *kim_data = dev_get_drvdata(dev); |
| 623 | return sprintf(buf, "%ld\n", kim_data->baud_rate); | 641 | return sprintf(buf, "%d\n", kim_data->baud_rate); |
| 624 | } | 642 | } |
| 625 | 643 | ||
| 626 | static ssize_t show_flow_cntrl(struct device *dev, | 644 | static ssize_t show_flow_cntrl(struct device *dev, |
| @@ -676,12 +694,16 @@ void st_kim_ref(struct st_data_s **core_data, int id) | |||
| 676 | struct kim_data_s *kim_gdata; | 694 | struct kim_data_s *kim_gdata; |
| 677 | /* get kim_gdata reference from platform device */ | 695 | /* get kim_gdata reference from platform device */ |
| 678 | pdev = st_get_plat_device(id); | 696 | pdev = st_get_plat_device(id); |
| 679 | if (!pdev) { | 697 | if (!pdev) |
| 680 | *core_data = NULL; | 698 | goto err; |
| 681 | return; | ||
| 682 | } | ||
| 683 | kim_gdata = platform_get_drvdata(pdev); | 699 | kim_gdata = platform_get_drvdata(pdev); |
| 700 | if (!kim_gdata) | ||
| 701 | goto err; | ||
| 702 | |||
| 684 | *core_data = kim_gdata->core_data; | 703 | *core_data = kim_gdata->core_data; |
| 704 | return; | ||
| 705 | err: | ||
| 706 | *core_data = NULL; | ||
| 685 | } | 707 | } |
| 686 | 708 | ||
| 687 | static int kim_version_open(struct inode *i, struct file *f) | 709 | static int kim_version_open(struct inode *i, struct file *f) |
| @@ -715,13 +737,53 @@ static const struct file_operations list_debugfs_fops = { | |||
| 715 | * board-*.c file | 737 | * board-*.c file |
| 716 | */ | 738 | */ |
| 717 | 739 | ||
| 740 | static const struct of_device_id kim_of_match[] = { | ||
| 741 | { | ||
| 742 | .compatible = "kim", | ||
| 743 | }, | ||
| 744 | {} | ||
| 745 | }; | ||
| 746 | MODULE_DEVICE_TABLE(of, kim_of_match); | ||
| 747 | |||
| 748 | static struct ti_st_plat_data *get_platform_data(struct device *dev) | ||
| 749 | { | ||
| 750 | struct device_node *np = dev->of_node; | ||
| 751 | const u32 *dt_property; | ||
| 752 | int len; | ||
| 753 | |||
| 754 | dt_pdata = kzalloc(sizeof(*dt_pdata), GFP_KERNEL); | ||
| 755 | |||
| 756 | if (!dt_pdata) | ||
| 757 | pr_err("Can't allocate device_tree platform data\n"); | ||
| 758 | |||
| 759 | dt_property = of_get_property(np, "dev_name", &len); | ||
| 760 | if (dt_property) | ||
| 761 | memcpy(&dt_pdata->dev_name, dt_property, len); | ||
| 762 | of_property_read_u32(np, "nshutdown_gpio", | ||
| 763 | &dt_pdata->nshutdown_gpio); | ||
| 764 | of_property_read_u32(np, "flow_cntrl", &dt_pdata->flow_cntrl); | ||
| 765 | of_property_read_u32(np, "baud_rate", &dt_pdata->baud_rate); | ||
| 766 | |||
| 767 | return dt_pdata; | ||
| 768 | } | ||
| 769 | |||
| 718 | static struct dentry *kim_debugfs_dir; | 770 | static struct dentry *kim_debugfs_dir; |
| 719 | static int kim_probe(struct platform_device *pdev) | 771 | static int kim_probe(struct platform_device *pdev) |
| 720 | { | 772 | { |
| 721 | struct kim_data_s *kim_gdata; | 773 | struct kim_data_s *kim_gdata; |
| 722 | struct ti_st_plat_data *pdata = pdev->dev.platform_data; | 774 | struct ti_st_plat_data *pdata; |
| 723 | int err; | 775 | int err; |
| 724 | 776 | ||
| 777 | if (pdev->dev.of_node) | ||
| 778 | pdata = get_platform_data(&pdev->dev); | ||
| 779 | else | ||
| 780 | pdata = pdev->dev.platform_data; | ||
| 781 | |||
| 782 | if (pdata == NULL) { | ||
| 783 | dev_err(&pdev->dev, "Platform Data is missing\n"); | ||
| 784 | return -ENXIO; | ||
| 785 | } | ||
| 786 | |||
| 725 | if ((pdev->id != -1) && (pdev->id < MAX_ST_DEVICES)) { | 787 | if ((pdev->id != -1) && (pdev->id < MAX_ST_DEVICES)) { |
| 726 | /* multiple devices could exist */ | 788 | /* multiple devices could exist */ |
| 727 | st_kim_devices[pdev->id] = pdev; | 789 | st_kim_devices[pdev->id] = pdev; |
| @@ -750,14 +812,14 @@ static int kim_probe(struct platform_device *pdev) | |||
| 750 | kim_gdata->nshutdown = pdata->nshutdown_gpio; | 812 | kim_gdata->nshutdown = pdata->nshutdown_gpio; |
| 751 | err = gpio_request(kim_gdata->nshutdown, "kim"); | 813 | err = gpio_request(kim_gdata->nshutdown, "kim"); |
| 752 | if (unlikely(err)) { | 814 | if (unlikely(err)) { |
| 753 | pr_err(" gpio %ld request failed ", kim_gdata->nshutdown); | 815 | pr_err(" gpio %d request failed ", kim_gdata->nshutdown); |
| 754 | return err; | 816 | return err; |
| 755 | } | 817 | } |
| 756 | 818 | ||
| 757 | /* Configure nShutdown GPIO as output=0 */ | 819 | /* Configure nShutdown GPIO as output=0 */ |
| 758 | err = gpio_direction_output(kim_gdata->nshutdown, 0); | 820 | err = gpio_direction_output(kim_gdata->nshutdown, 0); |
| 759 | if (unlikely(err)) { | 821 | if (unlikely(err)) { |
| 760 | pr_err(" unable to configure gpio %ld", kim_gdata->nshutdown); | 822 | pr_err(" unable to configure gpio %d", kim_gdata->nshutdown); |
| 761 | return err; | 823 | return err; |
| 762 | } | 824 | } |
| 763 | /* get reference of pdev for request_firmware | 825 | /* get reference of pdev for request_firmware |
| @@ -781,8 +843,7 @@ static int kim_probe(struct platform_device *pdev) | |||
| 781 | kim_debugfs_dir = debugfs_create_dir("ti-st", NULL); | 843 | kim_debugfs_dir = debugfs_create_dir("ti-st", NULL); |
| 782 | if (!kim_debugfs_dir) { | 844 | if (!kim_debugfs_dir) { |
| 783 | pr_err(" debugfs entries creation failed "); | 845 | pr_err(" debugfs entries creation failed "); |
| 784 | err = -EIO; | 846 | return 0; |
| 785 | goto err_debugfs_dir; | ||
| 786 | } | 847 | } |
| 787 | 848 | ||
| 788 | debugfs_create_file("version", S_IRUGO, kim_debugfs_dir, | 849 | debugfs_create_file("version", S_IRUGO, kim_debugfs_dir, |
| @@ -791,9 +852,6 @@ static int kim_probe(struct platform_device *pdev) | |||
| 791 | kim_gdata, &list_debugfs_fops); | 852 | kim_gdata, &list_debugfs_fops); |
| 792 | return 0; | 853 | return 0; |
| 793 | 854 | ||
| 794 | err_debugfs_dir: | ||
| 795 | sysfs_remove_group(&pdev->dev.kobj, &uim_attr_grp); | ||
| 796 | |||
| 797 | err_sysfs_group: | 855 | err_sysfs_group: |
| 798 | st_core_exit(kim_gdata->core_data); | 856 | st_core_exit(kim_gdata->core_data); |
| 799 | 857 | ||
| @@ -806,9 +864,16 @@ err_core_init: | |||
| 806 | static int kim_remove(struct platform_device *pdev) | 864 | static int kim_remove(struct platform_device *pdev) |
| 807 | { | 865 | { |
| 808 | /* free the GPIOs requested */ | 866 | /* free the GPIOs requested */ |
| 809 | struct ti_st_plat_data *pdata = pdev->dev.platform_data; | 867 | struct ti_st_plat_data *pdata; |
| 810 | struct kim_data_s *kim_gdata; | 868 | struct kim_data_s *kim_gdata; |
| 811 | 869 | ||
| 870 | if (pdev->dev.of_node) { | ||
| 871 | pr_debug("use device tree data"); | ||
| 872 | pdata = dt_pdata; | ||
| 873 | } else { | ||
| 874 | pdata = pdev->dev.platform_data; | ||
| 875 | } | ||
| 876 | |||
| 812 | kim_gdata = platform_get_drvdata(pdev); | 877 | kim_gdata = platform_get_drvdata(pdev); |
| 813 | 878 | ||
| 814 | /* Free the Bluetooth/FM/GPIO | 879 | /* Free the Bluetooth/FM/GPIO |
| @@ -826,27 +891,44 @@ static int kim_remove(struct platform_device *pdev) | |||
| 826 | 891 | ||
| 827 | kfree(kim_gdata); | 892 | kfree(kim_gdata); |
| 828 | kim_gdata = NULL; | 893 | kim_gdata = NULL; |
| 894 | kfree(dt_pdata); | ||
| 895 | dt_pdata = NULL; | ||
| 896 | |||
| 829 | return 0; | 897 | return 0; |
| 830 | } | 898 | } |
| 831 | 899 | ||
| 832 | static int kim_suspend(struct platform_device *pdev, pm_message_t state) | 900 | static int kim_suspend(struct platform_device *pdev, pm_message_t state) |
| 833 | { | 901 | { |
| 834 | struct ti_st_plat_data *pdata = pdev->dev.platform_data; | 902 | struct ti_st_plat_data *pdata; |
| 903 | |||
| 904 | if (pdev->dev.of_node) { | ||
| 905 | pr_debug("use device tree data"); | ||
| 906 | pdata = dt_pdata; | ||
| 907 | } else { | ||
| 908 | pdata = pdev->dev.platform_data; | ||
| 909 | } | ||
| 835 | 910 | ||
| 836 | if (pdata->suspend) | 911 | if (pdata->suspend) |
| 837 | return pdata->suspend(pdev, state); | 912 | return pdata->suspend(pdev, state); |
| 838 | 913 | ||
| 839 | return -EOPNOTSUPP; | 914 | return 0; |
| 840 | } | 915 | } |
| 841 | 916 | ||
| 842 | static int kim_resume(struct platform_device *pdev) | 917 | static int kim_resume(struct platform_device *pdev) |
| 843 | { | 918 | { |
| 844 | struct ti_st_plat_data *pdata = pdev->dev.platform_data; | 919 | struct ti_st_plat_data *pdata; |
| 920 | |||
| 921 | if (pdev->dev.of_node) { | ||
| 922 | pr_debug("use device tree data"); | ||
| 923 | pdata = dt_pdata; | ||
| 924 | } else { | ||
| 925 | pdata = pdev->dev.platform_data; | ||
| 926 | } | ||
| 845 | 927 | ||
| 846 | if (pdata->resume) | 928 | if (pdata->resume) |
| 847 | return pdata->resume(pdev); | 929 | return pdata->resume(pdev); |
| 848 | 930 | ||
| 849 | return -EOPNOTSUPP; | 931 | return 0; |
| 850 | } | 932 | } |
| 851 | 933 | ||
| 852 | /**********************************************************************/ | 934 | /**********************************************************************/ |
| @@ -858,6 +940,8 @@ static struct platform_driver kim_platform_driver = { | |||
| 858 | .resume = kim_resume, | 940 | .resume = kim_resume, |
| 859 | .driver = { | 941 | .driver = { |
| 860 | .name = "kim", | 942 | .name = "kim", |
| 943 | .owner = THIS_MODULE, | ||
| 944 | .of_match_table = of_match_ptr(kim_of_match), | ||
| 861 | }, | 945 | }, |
| 862 | }; | 946 | }; |
| 863 | 947 | ||
