aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc
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 /drivers/misc
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>
Diffstat (limited to 'drivers/misc')
-rw-r--r--drivers/misc/ti-st/st_kim.c244
1 files changed, 121 insertions, 123 deletions
diff --git a/drivers/misc/ti-st/st_kim.c b/drivers/misc/ti-st/st_kim.c
index 707c8582641..a7fda814175 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