st_ll.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. /*
  2. * Shared Transport driver
  3. * HCI-LL module responsible for TI proprietary HCI_LL protocol
  4. * Copyright (C) 2009-2010 Texas Instruments
  5. * Author: Pavan Savoy <pavan_savoy@ti.com>
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License version 2 as
  9. * published by the Free Software Foundation.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program; if not, write to the Free Software
  18. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  19. *
  20. */
  21. #define pr_fmt(fmt) "(stll) :" fmt
  22. #include <linux/skbuff.h>
  23. #include <linux/module.h>
  24. #include <linux/ti_wilink_st.h>
  25. /**********************************************************************/
  26. /* internal functions */
  27. static void send_ll_cmd(struct st_data_s *st_data,
  28. unsigned char cmd)
  29. {
  30. pr_debug("%s: writing %x", __func__, cmd);
  31. st_int_write(st_data, &cmd, 1);
  32. return;
  33. }
  34. static void ll_device_want_to_sleep(struct st_data_s *st_data)
  35. {
  36. pr_debug("%s", __func__);
  37. /* sanity check */
  38. if (st_data->ll_state != ST_LL_AWAKE)
  39. pr_err("ERR hcill: ST_LL_GO_TO_SLEEP_IND"
  40. "in state %ld", st_data->ll_state);
  41. send_ll_cmd(st_data, LL_SLEEP_ACK);
  42. /* update state */
  43. st_data->ll_state = ST_LL_ASLEEP;
  44. }
  45. static void ll_device_want_to_wakeup(struct st_data_s *st_data)
  46. {
  47. /* diff actions in diff states */
  48. switch (st_data->ll_state) {
  49. case ST_LL_ASLEEP:
  50. send_ll_cmd(st_data, LL_WAKE_UP_ACK); /* send wake_ack */
  51. break;
  52. case ST_LL_ASLEEP_TO_AWAKE:
  53. /* duplicate wake_ind */
  54. pr_err("duplicate wake_ind while waiting for Wake ack");
  55. break;
  56. case ST_LL_AWAKE:
  57. /* duplicate wake_ind */
  58. pr_err("duplicate wake_ind already AWAKE");
  59. break;
  60. case ST_LL_AWAKE_TO_ASLEEP:
  61. /* duplicate wake_ind */
  62. pr_err("duplicate wake_ind");
  63. break;
  64. }
  65. /* update state */
  66. st_data->ll_state = ST_LL_AWAKE;
  67. }
  68. /**********************************************************************/
  69. /* functions invoked by ST Core */
  70. /* called when ST Core wants to
  71. * enable ST LL */
  72. void st_ll_enable(struct st_data_s *ll)
  73. {
  74. ll->ll_state = ST_LL_AWAKE;
  75. }
  76. /* called when ST Core /local module wants to
  77. * disable ST LL */
  78. void st_ll_disable(struct st_data_s *ll)
  79. {
  80. ll->ll_state = ST_LL_INVALID;
  81. }
  82. /* called when ST Core wants to update the state */
  83. void st_ll_wakeup(struct st_data_s *ll)
  84. {
  85. if (likely(ll->ll_state != ST_LL_AWAKE)) {
  86. send_ll_cmd(ll, LL_WAKE_UP_IND); /* WAKE_IND */
  87. ll->ll_state = ST_LL_ASLEEP_TO_AWAKE;
  88. } else {
  89. /* don't send the duplicate wake_indication */
  90. pr_err(" Chip already AWAKE ");
  91. }
  92. }
  93. /* called when ST Core wants the state */
  94. unsigned long st_ll_getstate(struct st_data_s *ll)
  95. {
  96. pr_debug(" returning state %ld", ll->ll_state);
  97. return ll->ll_state;
  98. }
  99. /* called from ST Core, when a PM related packet arrives */
  100. unsigned long st_ll_sleep_state(struct st_data_s *st_data,
  101. unsigned char cmd)
  102. {
  103. switch (cmd) {
  104. case LL_SLEEP_IND: /* sleep ind */
  105. pr_debug("sleep indication recvd");
  106. ll_device_want_to_sleep(st_data);
  107. break;
  108. case LL_SLEEP_ACK: /* sleep ack */
  109. pr_err("sleep ack rcvd: host shouldn't");
  110. break;
  111. case LL_WAKE_UP_IND: /* wake ind */
  112. pr_debug("wake indication recvd");
  113. ll_device_want_to_wakeup(st_data);
  114. break;
  115. case LL_WAKE_UP_ACK: /* wake ack */
  116. pr_debug("wake ack rcvd");
  117. st_data->ll_state = ST_LL_AWAKE;
  118. break;
  119. default:
  120. pr_err(" unknown input/state ");
  121. return -EINVAL;
  122. }
  123. return 0;
  124. }
  125. /* Called from ST CORE to initialize ST LL */
  126. long st_ll_init(struct st_data_s *ll)
  127. {
  128. /* set state to invalid */
  129. ll->ll_state = ST_LL_INVALID;
  130. return 0;
  131. }
  132. /* Called from ST CORE to de-initialize ST LL */
  133. long st_ll_deinit(struct st_data_s *ll)
  134. {
  135. return 0;
  136. }