aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPavan Savoy <pavan_savoy@ti.com>2011-02-04 03:23:10 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2011-02-04 15:41:20 -0500
commitec60d0ad20ff8796dc41b30a9dce485478ccd263 (patch)
tree9a0a96e59fb0f193ad25177a54fe16612e2f8545
parent5c88b02196a99332dacf305c8757674dd7a303ff (diff)
drivers:misc: ti-st: move from rfkill to sysfs
The communication between ST KIM and UIM was interfaced over the /dev/rfkill device node. Move the interface to a simpler less abusive sysfs entry mechanism and document it in Documentation/ABI/testing/ under sysfs-platform-kim. Shared transport driver would now read the UART details originally received by bootloader or firmware as platform data. The data read will be shared over sysfs entries for the user-space UIM or other n/w manager/plugins to be read, and assist the driver by opening up the UART, setting the baud-rate and installing the line discipline. Signed-off-by: Pavan Savoy <pavan_savoy@ti.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--Documentation/ABI/testing/sysfs-platform-kim48
-rw-r--r--drivers/misc/ti-st/st_kim.c244
-rw-r--r--include/linux/ti_wilink_st.h19
3 files changed, 186 insertions, 125 deletions
diff --git a/Documentation/ABI/testing/sysfs-platform-kim b/Documentation/ABI/testing/sysfs-platform-kim
new file mode 100644
index 000000000000..c1653271872a
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-platform-kim
@@ -0,0 +1,48 @@
1What: /sys/devices/platform/kim/dev_name
2Date: January 2010
3KernelVersion: 2.6.38
4Contact: "Pavan Savoy" <pavan_savoy@ti.com>
5Description:
6 Name of the UART device at which the WL128x chip
7 is connected. example: "/dev/ttyS0".
8 The device name flows down to architecture specific board
9 initialization file from the SFI/ATAGS bootloader
10 firmware. The name exposed is read from the user-space
11 dameon and opens the device when install is requested.
12
13What: /sys/devices/platform/kim/baud_rate
14Date: January 2010
15KernelVersion: 2.6.38
16Contact: "Pavan Savoy" <pavan_savoy@ti.com>
17Description:
18 The maximum reliable baud-rate the host can support.
19 Different platforms tend to have different high-speed
20 UART configurations, so the baud-rate needs to be set
21 locally and also sent across to the WL128x via a HCI-VS
22 command. The entry is read and made use by the user-space
23 daemon when the ldisc install is requested.
24
25What: /sys/devices/platform/kim/flow_cntrl
26Date: January 2010
27KernelVersion: 2.6.38
28Contact: "Pavan Savoy" <pavan_savoy@ti.com>
29Description:
30 The WL128x makes use of flow control mechanism, and this
31 entry most often should be 1, the host's UART is required
32 to have the capability of flow-control, or else this
33 entry can be made use of for exceptions.
34
35What: /sys/devices/platform/kim/install
36Date: January 2010
37KernelVersion: 2.6.38
38Contact: "Pavan Savoy" <pavan_savoy@ti.com>
39Description:
40 When one of the protocols Bluetooth, FM or GPS wants to make
41 use of the shared UART transport, it registers to the shared
42 transport driver, which will signal the user-space for opening,
43 configuring baud and install line discipline via this sysfs
44 entry. This entry would be polled upon by the user-space
45 daemon managing the UART, and is notified about the change
46 by the sysfs_notify. The value would be '1' when UART needs
47 to be opened/ldisc installed, and would be '0' when UART
48 is no more required and needs to be closed.
diff --git a/drivers/misc/ti-st/st_kim.c b/drivers/misc/ti-st/st_kim.c
index 707c85826417..a7fda8141758 100644
--- a/drivers/misc/ti-st/st_kim.c
+++ b/drivers/misc/ti-st/st_kim.c
@@ -30,46 +30,12 @@
30#include <linux/debugfs.h> 30#include <linux/debugfs.h>
31#include <linux/seq_file.h> 31#include <linux/seq_file.h>
32#include <linux/sched.h> 32#include <linux/sched.h>
33#include <linux/rfkill.h> 33#include <linux/tty.h>
34 34
35#include <linux/skbuff.h> 35#include <linux/skbuff.h>
36#include <linux/ti_wilink_st.h> 36#include <linux/ti_wilink_st.h>
37 37
38 38
39static int kim_probe(struct platform_device *pdev);
40static int kim_remove(struct platform_device *pdev);
41
42/* KIM platform device driver structure */
43static struct platform_driver kim_platform_driver = {
44 .probe = kim_probe,
45 .remove = kim_remove,
46 /* TODO: ST driver power management during suspend/resume ?
47 */
48#if 0
49 .suspend = kim_suspend,
50 .resume = kim_resume,
51#endif
52 .driver = {
53 .name = "kim",
54 .owner = THIS_MODULE,
55 },
56};
57
58static int kim_toggle_radio(void*, bool);
59static const struct rfkill_ops kim_rfkill_ops = {
60 .set_block = kim_toggle_radio,
61};
62
63/* strings to be used for rfkill entries and by
64 * ST Core to be used for sysfs debug entry
65 */
66#define PROTO_ENTRY(type, name) name
67const unsigned char *protocol_names[] = {
68 PROTO_ENTRY(ST_BT, "Bluetooth"),
69 PROTO_ENTRY(ST_FM, "FM"),
70 PROTO_ENTRY(ST_GPS, "GPS"),
71};
72
73#define MAX_ST_DEVICES 3 /* Imagine 1 on each UART for now */ 39#define MAX_ST_DEVICES 3 /* Imagine 1 on each UART for now */
74static struct platform_device *st_kim_devices[MAX_ST_DEVICES]; 40static struct platform_device *st_kim_devices[MAX_ST_DEVICES];
75 41
@@ -371,8 +337,7 @@ void st_kim_chip_toggle(enum proto_type type, enum kim_gpio_state state)
371 kim_gdata = dev_get_drvdata(&kim_pdev->dev); 337 kim_gdata = dev_get_drvdata(&kim_pdev->dev);
372 338
373 if (kim_gdata->gpios[type] == -1) { 339 if (kim_gdata->gpios[type] == -1) {
374 pr_info(" gpio not requested for protocol %s", 340 pr_info("gpio not requested for protocol %d", type);
375 protocol_names[type]);
376 return; 341 return;
377 } 342 }
378 switch (type) { 343 switch (type) {
@@ -450,11 +415,6 @@ long st_kim_start(void *kim_data)
450 pr_info(" %s", __func__); 415 pr_info(" %s", __func__);
451 416
452 do { 417 do {
453 /* TODO: this is only because rfkill sub-system
454 * doesn't send events to user-space if the state
455 * isn't changed
456 */
457 rfkill_set_hw_state(kim_gdata->rfkill[ST_BT], 1);
458 /* Configure BT nShutdown to HIGH state */ 418 /* Configure BT nShutdown to HIGH state */
459 gpio_set_value(kim_gdata->gpios[ST_BT], GPIO_LOW); 419 gpio_set_value(kim_gdata->gpios[ST_BT], GPIO_LOW);
460 mdelay(5); /* FIXME: a proper toggle */ 420 mdelay(5); /* FIXME: a proper toggle */
@@ -462,22 +422,20 @@ long st_kim_start(void *kim_data)
462 mdelay(100); 422 mdelay(100);
463 /* re-initialize the completion */ 423 /* re-initialize the completion */
464 INIT_COMPLETION(kim_gdata->ldisc_installed); 424 INIT_COMPLETION(kim_gdata->ldisc_installed);
465#if 0 /* older way of signalling user-space UIM */ 425 /* send notification to UIM */
466 /* send signal to UIM */ 426 kim_gdata->ldisc_install = 1;
467 err = kill_pid(find_get_pid(kim_gdata->uim_pid), SIGUSR2, 0); 427 pr_info("ldisc_install = 1");
468 if (err != 0) { 428 sysfs_notify(&kim_gdata->kim_pdev->dev.kobj,
469 pr_info(" sending SIGUSR2 to uim failed %ld", err); 429 NULL, "install");
470 err = -1;
471 continue;
472 }
473#endif
474 /* unblock and send event to UIM via /dev/rfkill */
475 rfkill_set_hw_state(kim_gdata->rfkill[ST_BT], 0);
476 /* wait for ldisc to be installed */ 430 /* wait for ldisc to be installed */
477 err = wait_for_completion_timeout(&kim_gdata->ldisc_installed, 431 err = wait_for_completion_timeout(&kim_gdata->ldisc_installed,
478 msecs_to_jiffies(LDISC_TIME)); 432 msecs_to_jiffies(LDISC_TIME));
479 if (!err) { /* timeout */ 433 if (!err) { /* timeout */
480 pr_err("line disc installation timed out "); 434 pr_err("line disc installation timed out ");
435 kim_gdata->ldisc_install = 0;
436 pr_info("ldisc_install = 0");
437 sysfs_notify(&kim_gdata->kim_pdev->dev.kobj,
438 NULL, "install");
481 err = -1; 439 err = -1;
482 continue; 440 continue;
483 } else { 441 } else {
@@ -486,6 +444,10 @@ long st_kim_start(void *kim_data)
486 err = download_firmware(kim_gdata); 444 err = download_firmware(kim_gdata);
487 if (err != 0) { 445 if (err != 0) {
488 pr_err("download firmware failed"); 446 pr_err("download firmware failed");
447 kim_gdata->ldisc_install = 0;
448 pr_info("ldisc_install = 0");
449 sysfs_notify(&kim_gdata->kim_pdev->dev.kobj,
450 NULL, "install");
489 continue; 451 continue;
490 } else { /* on success don't retry */ 452 } else { /* on success don't retry */
491 break; 453 break;
@@ -505,16 +467,15 @@ long st_kim_stop(void *kim_data)
505 struct kim_data_s *kim_gdata = (struct kim_data_s *)kim_data; 467 struct kim_data_s *kim_gdata = (struct kim_data_s *)kim_data;
506 468
507 INIT_COMPLETION(kim_gdata->ldisc_installed); 469 INIT_COMPLETION(kim_gdata->ldisc_installed);
508#if 0 /* older way of signalling user-space UIM */ 470
509 /* send signal to UIM */ 471 /* Flush any pending characters in the driver and discipline. */
510 err = kill_pid(find_get_pid(kim_gdata->uim_pid), SIGUSR2, 1); 472 tty_ldisc_flush(kim_gdata->core_data->tty);
511 if (err != 0) { 473 tty_driver_flush_buffer(kim_gdata->core_data->tty);
512 pr_err("sending SIGUSR2 to uim failed %ld", err); 474
513 return -1; 475 /* send uninstall notification to UIM */
514 } 476 pr_info("ldisc_install = 0");
515#endif 477 kim_gdata->ldisc_install = 0;
516 /* set BT rfkill to be blocked */ 478 sysfs_notify(&kim_gdata->kim_pdev->dev.kobj, NULL, "install");
517 err = rfkill_set_hw_state(kim_gdata->rfkill[ST_BT], 1);
518 479
519 /* wait for ldisc to be un-installed */ 480 /* wait for ldisc to be un-installed */
520 err = wait_for_completion_timeout(&kim_gdata->ldisc_installed, 481 err = wait_for_completion_timeout(&kim_gdata->ldisc_installed,
@@ -553,33 +514,59 @@ static int show_list(struct seq_file *s, void *unused)
553 return 0; 514 return 0;
554} 515}
555 516
556/* function called from rfkill subsystem, when someone from 517static ssize_t show_install(struct device *dev,
557 * user space would write 0/1 on the sysfs entry 518 struct device_attribute *attr, char *buf)
558 * /sys/class/rfkill/rfkill0,1,3/state
559 */
560static int kim_toggle_radio(void *data, bool blocked)
561{ 519{
562 enum proto_type type = *((enum proto_type *)data); 520 struct kim_data_s *kim_data = dev_get_drvdata(dev);
563 pr_debug(" %s: %d ", __func__, type); 521 return sprintf(buf, "%d\n", kim_data->ldisc_install);
522}
564 523
565 switch (type) { 524static ssize_t show_dev_name(struct device *dev,
566 case ST_BT: 525 struct device_attribute *attr, char *buf)
567 /* do nothing */ 526{
568 break; 527 struct kim_data_s *kim_data = dev_get_drvdata(dev);
569 case ST_FM: 528 return sprintf(buf, "%s\n", kim_data->dev_name);
570 case ST_GPS: 529}
571 if (blocked) 530
572 st_kim_chip_toggle(type, KIM_GPIO_INACTIVE); 531static ssize_t show_baud_rate(struct device *dev,
573 else 532 struct device_attribute *attr, char *buf)
574 st_kim_chip_toggle(type, KIM_GPIO_ACTIVE); 533{
575 break; 534 struct kim_data_s *kim_data = dev_get_drvdata(dev);
576 case ST_MAX_CHANNELS: 535 return sprintf(buf, "%ld\n", kim_data->baud_rate);
577 pr_err(" wrong proto type "); 536}
578 break; 537
579 } 538static ssize_t show_flow_cntrl(struct device *dev,
580 return 0; 539 struct device_attribute *attr, char *buf)
540{
541 struct kim_data_s *kim_data = dev_get_drvdata(dev);
542 return sprintf(buf, "%d\n", kim_data->flow_cntrl);
581} 543}
582 544
545/* structures specific for sysfs entries */
546static struct kobj_attribute ldisc_install =
547__ATTR(install, 0444, (void *)show_install, NULL);
548
549static struct kobj_attribute uart_dev_name =
550__ATTR(dev_name, 0444, (void *)show_dev_name, NULL);
551
552static struct kobj_attribute uart_baud_rate =
553__ATTR(baud_rate, 0444, (void *)show_baud_rate, NULL);
554
555static struct kobj_attribute uart_flow_cntrl =
556__ATTR(flow_cntrl, 0444, (void *)show_flow_cntrl, NULL);
557
558static struct attribute *uim_attrs[] = {
559 &ldisc_install.attr,
560 &uart_dev_name.attr,
561 &uart_baud_rate.attr,
562 &uart_flow_cntrl.attr,
563 NULL,
564};
565
566static struct attribute_group uim_attr_grp = {
567 .attrs = uim_attrs,
568};
569
583/** 570/**
584 * st_kim_ref - reference the core's data 571 * st_kim_ref - reference the core's data
585 * This references the per-ST platform device in the arch/xx/ 572 * This references the per-ST platform device in the arch/xx/
@@ -633,8 +620,9 @@ static int kim_probe(struct platform_device *pdev)
633{ 620{
634 long status; 621 long status;
635 long proto; 622 long proto;
636 long *gpios = pdev->dev.platform_data;
637 struct kim_data_s *kim_gdata; 623 struct kim_data_s *kim_gdata;
624 struct ti_st_plat_data *pdata = pdev->dev.platform_data;
625 long *gpios = pdata->gpios;
638 626
639 if ((pdev->id != -1) && (pdev->id < MAX_ST_DEVICES)) { 627 if ((pdev->id != -1) && (pdev->id < MAX_ST_DEVICES)) {
640 /* multiple devices could exist */ 628 /* multiple devices could exist */
@@ -700,30 +688,18 @@ static int kim_probe(struct platform_device *pdev)
700 init_completion(&kim_gdata->kim_rcvd); 688 init_completion(&kim_gdata->kim_rcvd);
701 init_completion(&kim_gdata->ldisc_installed); 689 init_completion(&kim_gdata->ldisc_installed);
702 690
703 for (proto = 0; (proto < ST_MAX_CHANNELS) 691 status = sysfs_create_group(&pdev->dev.kobj, &uim_attr_grp);
704 && (gpios[proto] != -1); proto++) { 692 if (status) {
705 /* TODO: should all types be rfkill_type_bt ? */ 693 pr_err("failed to create sysfs entries");
706 kim_gdata->rf_protos[proto] = proto; 694 return status;
707 kim_gdata->rfkill[proto] = rfkill_alloc(protocol_names[proto],
708 &pdev->dev, RFKILL_TYPE_BLUETOOTH,
709 &kim_rfkill_ops, &kim_gdata->rf_protos[proto]);
710 if (kim_gdata->rfkill[proto] == NULL) {
711 pr_err("cannot create rfkill entry for gpio %ld",
712 gpios[proto]);
713 continue;
714 }
715 /* block upon creation */
716 rfkill_init_sw_state(kim_gdata->rfkill[proto], 1);
717 status = rfkill_register(kim_gdata->rfkill[proto]);
718 if (unlikely(status)) {
719 pr_err("rfkill registration failed for gpio %ld",
720 gpios[proto]);
721 rfkill_unregister(kim_gdata->rfkill[proto]);
722 continue;
723 }
724 pr_info("rfkill entry created for %ld", gpios[proto]);
725 } 695 }
726 696
697 /* copying platform data */
698 strncpy(kim_gdata->dev_name, pdata->dev_name, UART_DEV_NAME_LEN);
699 kim_gdata->flow_cntrl = pdata->flow_cntrl;
700 kim_gdata->baud_rate = pdata->baud_rate;
701 pr_info("sysfs entries created\n");
702
727 kim_debugfs_dir = debugfs_create_dir("ti-st", NULL); 703 kim_debugfs_dir = debugfs_create_dir("ti-st", NULL);
728 if (IS_ERR(kim_debugfs_dir)) { 704 if (IS_ERR(kim_debugfs_dir)) {
729 pr_err(" debugfs entries creation failed "); 705 pr_err(" debugfs entries creation failed ");
@@ -741,9 +717,9 @@ static int kim_probe(struct platform_device *pdev)
741 717
742static int kim_remove(struct platform_device *pdev) 718static int kim_remove(struct platform_device *pdev)
743{ 719{
744 /* free the GPIOs requested 720 /* free the GPIOs requested */
745 */ 721 struct ti_st_plat_data *pdata = pdev->dev.platform_data;
746 long *gpios = pdev->dev.platform_data; 722 long *gpios = pdata->gpios;
747 long proto; 723 long proto;
748 struct kim_data_s *kim_gdata; 724 struct kim_data_s *kim_gdata;
749 725
@@ -755,12 +731,11 @@ static int kim_remove(struct platform_device *pdev)
755 * nShutdown gpio from the system 731 * nShutdown gpio from the system
756 */ 732 */
757 gpio_free(gpios[proto]); 733 gpio_free(gpios[proto]);
758 rfkill_unregister(kim_gdata->rfkill[proto]);
759 rfkill_destroy(kim_gdata->rfkill[proto]);
760 kim_gdata->rfkill[proto] = NULL;
761 } 734 }
762 pr_info("kim: GPIO Freed"); 735 pr_info("kim: GPIO Freed");
763 debugfs_remove_recursive(kim_debugfs_dir); 736 debugfs_remove_recursive(kim_debugfs_dir);
737
738 sysfs_remove_group(&pdev->dev.kobj, &uim_attr_grp);
764 kim_gdata->kim_pdev = NULL; 739 kim_gdata->kim_pdev = NULL;
765 st_core_exit(kim_gdata->core_data); 740 st_core_exit(kim_gdata->core_data);
766 741
@@ -769,23 +744,46 @@ static int kim_remove(struct platform_device *pdev)
769 return 0; 744 return 0;
770} 745}
771 746
747int kim_suspend(struct platform_device *pdev, pm_message_t state)
748{
749 struct ti_st_plat_data *pdata = pdev->dev.platform_data;
750
751 if (pdata->suspend)
752 return pdata->suspend(pdev, state);
753
754 return -EOPNOTSUPP;
755}
756
757int kim_resume(struct platform_device *pdev)
758{
759 struct ti_st_plat_data *pdata = pdev->dev.platform_data;
760
761 if (pdata->resume)
762 return pdata->resume(pdev);
763
764 return -EOPNOTSUPP;
765}
766
772/**********************************************************************/ 767/**********************************************************************/
773/* entry point for ST KIM module, called in from ST Core */ 768/* entry point for ST KIM module, called in from ST Core */
769static struct platform_driver kim_platform_driver = {
770 .probe = kim_probe,
771 .remove = kim_remove,
772 .suspend = kim_suspend,
773 .resume = kim_resume,
774 .driver = {
775 .name = "kim",
776 .owner = THIS_MODULE,
777 },
778};
774 779
775static int __init st_kim_init(void) 780static int __init st_kim_init(void)
776{ 781{
777 long ret = 0; 782 return platform_driver_register(&kim_platform_driver);
778 ret = platform_driver_register(&kim_platform_driver);
779 if (ret != 0) {
780 pr_err("platform drv registration failed");
781 return -1;
782 }
783 return 0;
784} 783}
785 784
786static void __exit st_kim_deinit(void) 785static void __exit st_kim_deinit(void)
787{ 786{
788 /* the following returns void */
789 platform_driver_unregister(&kim_platform_driver); 787 platform_driver_unregister(&kim_platform_driver);
790} 788}
791 789
diff --git a/include/linux/ti_wilink_st.h b/include/linux/ti_wilink_st.h
index 1674ca7ab86d..010cda7287a0 100644
--- a/include/linux/ti_wilink_st.h
+++ b/include/linux/ti_wilink_st.h
@@ -206,8 +206,8 @@ void gps_chrdrv_stub_init(void);
206/* time in msec to wait for 206/* time in msec to wait for
207 * line discipline to be installed 207 * line discipline to be installed
208 */ 208 */
209#define LDISC_TIME 500 209#define LDISC_TIME 1000
210#define CMD_RESP_TIME 500 210#define CMD_RESP_TIME 800
211#define MAKEWORD(a, b) ((unsigned short)(((unsigned char)(a)) \ 211#define MAKEWORD(a, b) ((unsigned short)(((unsigned char)(a)) \
212 | ((unsigned short)((unsigned char)(b))) << 8)) 212 | ((unsigned short)((unsigned char)(b))) << 8))
213 213
@@ -230,6 +230,7 @@ struct chip_version {
230 unsigned short maj_ver; 230 unsigned short maj_ver;
231}; 231};
232 232
233#define UART_DEV_NAME_LEN 32
233/** 234/**
234 * struct kim_data_s - the KIM internal data, embedded as the 235 * struct kim_data_s - the KIM internal data, embedded as the
235 * platform's drv data. One for each ST device in the system. 236 * platform's drv data. One for each ST device in the system.
@@ -271,6 +272,10 @@ struct kim_data_s {
271 enum proto_type rf_protos[ST_MAX_CHANNELS]; 272 enum proto_type rf_protos[ST_MAX_CHANNELS];
272 struct st_data_s *core_data; 273 struct st_data_s *core_data;
273 struct chip_version version; 274 struct chip_version version;
275 unsigned char ldisc_install;
276 unsigned char dev_name[UART_DEV_NAME_LEN];
277 unsigned char flow_cntrl;
278 unsigned long baud_rate;
274}; 279};
275 280
276/** 281/**
@@ -413,4 +418,14 @@ struct gps_event_hdr {
413 u16 plen; 418 u16 plen;
414} __attribute__ ((packed)); 419} __attribute__ ((packed));
415 420
421/* platform data */
422struct ti_st_plat_data {
423 long gpios[ST_MAX_CHANNELS]; /* BT, FM and GPS */
424 unsigned char dev_name[UART_DEV_NAME_LEN]; /* uart name */
425 unsigned char flow_cntrl; /* flow control flag */
426 unsigned long baud_rate;
427 int (*suspend)(struct platform_device *, pm_message_t);
428 int (*resume)(struct platform_device *);
429};
430
416#endif /* TI_WILINK_ST_H */ 431#endif /* TI_WILINK_ST_H */