st_ll.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  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/platform_device.h>
  25. #include <linux/ti_wilink_st.h>
  26. /**********************************************************************/
  27. /* internal functions */
  28. static void send_ll_cmd(struct st_data_s *st_data,
  29. unsigned char cmd)
  30. {
  31. pr_debug("%s: writing %x", __func__, cmd);
  32. st_int_write(st_data, &cmd, 1);
  33. return;
  34. }
  35. static void ll_device_want_to_sleep(struct st_data_s *st_data)
  36. {
  37. struct kim_data_s *kim_data;
  38. struct ti_st_plat_data *pdata;
  39. pr_debug("%s", __func__);
  40. /* sanity check */
  41. if (st_data->ll_state != ST_LL_AWAKE)
  42. pr_err("ERR hcill: ST_LL_GO_TO_SLEEP_IND"
  43. "in state %ld", st_data->ll_state);
  44. send_ll_cmd(st_data, LL_SLEEP_ACK);
  45. /* update state */
  46. st_data->ll_state = ST_LL_ASLEEP;
  47. /* communicate to platform about chip asleep */
  48. kim_data = st_data->kim_data;
  49. if (kim_data->kim_pdev->dev.of_node) {
  50. pr_debug("use device tree data");
  51. pdata = dt_pdata;
  52. } else {
  53. pdata = kim_data->kim_pdev->dev.platform_data;
  54. }
  55. if (pdata->chip_asleep)
  56. pdata->chip_asleep(NULL);
  57. }
  58. static void ll_device_want_to_wakeup(struct st_data_s *st_data)
  59. {
  60. struct kim_data_s *kim_data;
  61. struct ti_st_plat_data *pdata;
  62. /* diff actions in diff states */
  63. switch (st_data->ll_state) {
  64. case ST_LL_ASLEEP:
  65. send_ll_cmd(st_data, LL_WAKE_UP_ACK); /* send wake_ack */
  66. break;
  67. case ST_LL_ASLEEP_TO_AWAKE:
  68. /* duplicate wake_ind */
  69. pr_err("duplicate wake_ind while waiting for Wake ack");
  70. break;
  71. case ST_LL_AWAKE:
  72. /* duplicate wake_ind */
  73. pr_err("duplicate wake_ind already AWAKE");
  74. break;
  75. case ST_LL_AWAKE_TO_ASLEEP:
  76. /* duplicate wake_ind */
  77. pr_err("duplicate wake_ind");
  78. break;
  79. }
  80. /* update state */
  81. st_data->ll_state = ST_LL_AWAKE;
  82. /* communicate to platform about chip wakeup */
  83. kim_data = st_data->kim_data;
  84. if (kim_data->kim_pdev->dev.of_node) {
  85. pr_debug("use device tree data");
  86. pdata = dt_pdata;
  87. } else {
  88. pdata = kim_data->kim_pdev->dev.platform_data;
  89. }
  90. if (pdata->chip_awake)
  91. pdata->chip_awake(NULL);
  92. }
  93. /**********************************************************************/
  94. /* functions invoked by ST Core */
  95. /* called when ST Core wants to
  96. * enable ST LL */
  97. void st_ll_enable(struct st_data_s *ll)
  98. {
  99. ll->ll_state = ST_LL_AWAKE;
  100. }
  101. /* called when ST Core /local module wants to
  102. * disable ST LL */
  103. void st_ll_disable(struct st_data_s *ll)
  104. {
  105. ll->ll_state = ST_LL_INVALID;
  106. }
  107. /* called when ST Core wants to update the state */
  108. void st_ll_wakeup(struct st_data_s *ll)
  109. {
  110. if (likely(ll->ll_state != ST_LL_AWAKE)) {
  111. send_ll_cmd(ll, LL_WAKE_UP_IND); /* WAKE_IND */
  112. ll->ll_state = ST_LL_ASLEEP_TO_AWAKE;
  113. } else {
  114. /* don't send the duplicate wake_indication */
  115. pr_err(" Chip already AWAKE ");
  116. }
  117. }
  118. /* called when ST Core wants the state */
  119. unsigned long st_ll_getstate(struct st_data_s *ll)
  120. {
  121. pr_debug(" returning state %ld", ll->ll_state);
  122. return ll->ll_state;
  123. }
  124. /* called from ST Core, when a PM related packet arrives */
  125. unsigned long st_ll_sleep_state(struct st_data_s *st_data,
  126. unsigned char cmd)
  127. {
  128. switch (cmd) {
  129. case LL_SLEEP_IND: /* sleep ind */
  130. pr_debug("sleep indication recvd");
  131. ll_device_want_to_sleep(st_data);
  132. break;
  133. case LL_SLEEP_ACK: /* sleep ack */
  134. pr_err("sleep ack rcvd: host shouldn't");
  135. break;
  136. case LL_WAKE_UP_IND: /* wake ind */
  137. pr_debug("wake indication recvd");
  138. ll_device_want_to_wakeup(st_data);
  139. break;
  140. case LL_WAKE_UP_ACK: /* wake ack */
  141. pr_debug("wake ack rcvd");
  142. st_data->ll_state = ST_LL_AWAKE;
  143. break;
  144. default:
  145. pr_err(" unknown input/state ");
  146. return -EINVAL;
  147. }
  148. return 0;
  149. }
  150. /* Called from ST CORE to initialize ST LL */
  151. long st_ll_init(struct st_data_s *ll)
  152. {
  153. /* set state to invalid */
  154. ll->ll_state = ST_LL_INVALID;
  155. return 0;
  156. }
  157. /* Called from ST CORE to de-initialize ST LL */
  158. long st_ll_deinit(struct st_data_s *ll)
  159. {
  160. return 0;
  161. }