st_ll.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Shared Transport driver
  4. * HCI-LL module responsible for TI proprietary HCI_LL protocol
  5. * Copyright (C) 2009-2010 Texas Instruments
  6. * Author: Pavan Savoy <[email protected]>
  7. */
  8. #define pr_fmt(fmt) "(stll) :" fmt
  9. #include <linux/skbuff.h>
  10. #include <linux/module.h>
  11. #include <linux/platform_device.h>
  12. #include <linux/ti_wilink_st.h>
  13. /**********************************************************************/
  14. /* internal functions */
  15. static void send_ll_cmd(struct st_data_s *st_data,
  16. unsigned char cmd)
  17. {
  18. pr_debug("%s: writing %x", __func__, cmd);
  19. st_int_write(st_data, &cmd, 1);
  20. return;
  21. }
  22. static void ll_device_want_to_sleep(struct st_data_s *st_data)
  23. {
  24. struct kim_data_s *kim_data;
  25. struct ti_st_plat_data *pdata;
  26. pr_debug("%s", __func__);
  27. /* sanity check */
  28. if (st_data->ll_state != ST_LL_AWAKE)
  29. pr_err("ERR hcill: ST_LL_GO_TO_SLEEP_IND"
  30. "in state %ld", st_data->ll_state);
  31. send_ll_cmd(st_data, LL_SLEEP_ACK);
  32. /* update state */
  33. st_data->ll_state = ST_LL_ASLEEP;
  34. /* communicate to platform about chip asleep */
  35. kim_data = st_data->kim_data;
  36. pdata = kim_data->kim_pdev->dev.platform_data;
  37. if (pdata->chip_asleep)
  38. pdata->chip_asleep(NULL);
  39. }
  40. static void ll_device_want_to_wakeup(struct st_data_s *st_data)
  41. {
  42. struct kim_data_s *kim_data;
  43. struct ti_st_plat_data *pdata;
  44. /* diff actions in diff states */
  45. switch (st_data->ll_state) {
  46. case ST_LL_ASLEEP:
  47. send_ll_cmd(st_data, LL_WAKE_UP_ACK); /* send wake_ack */
  48. break;
  49. case ST_LL_ASLEEP_TO_AWAKE:
  50. /* duplicate wake_ind */
  51. pr_err("duplicate wake_ind while waiting for Wake ack");
  52. break;
  53. case ST_LL_AWAKE:
  54. /* duplicate wake_ind */
  55. pr_err("duplicate wake_ind already AWAKE");
  56. break;
  57. case ST_LL_AWAKE_TO_ASLEEP:
  58. /* duplicate wake_ind */
  59. pr_err("duplicate wake_ind");
  60. break;
  61. }
  62. /* update state */
  63. st_data->ll_state = ST_LL_AWAKE;
  64. /* communicate to platform about chip wakeup */
  65. kim_data = st_data->kim_data;
  66. pdata = kim_data->kim_pdev->dev.platform_data;
  67. if (pdata->chip_awake)
  68. pdata->chip_awake(NULL);
  69. }
  70. /**********************************************************************/
  71. /* functions invoked by ST Core */
  72. /* called when ST Core wants to
  73. * enable ST LL */
  74. void st_ll_enable(struct st_data_s *ll)
  75. {
  76. ll->ll_state = ST_LL_AWAKE;
  77. }
  78. /* called when ST Core /local module wants to
  79. * disable ST LL */
  80. void st_ll_disable(struct st_data_s *ll)
  81. {
  82. ll->ll_state = ST_LL_INVALID;
  83. }
  84. /* called when ST Core wants to update the state */
  85. void st_ll_wakeup(struct st_data_s *ll)
  86. {
  87. if (likely(ll->ll_state != ST_LL_AWAKE)) {
  88. send_ll_cmd(ll, LL_WAKE_UP_IND); /* WAKE_IND */
  89. ll->ll_state = ST_LL_ASLEEP_TO_AWAKE;
  90. } else {
  91. /* don't send the duplicate wake_indication */
  92. pr_err(" Chip already AWAKE ");
  93. }
  94. }
  95. /* called when ST Core wants the state */
  96. unsigned long st_ll_getstate(struct st_data_s *ll)
  97. {
  98. pr_debug(" returning state %ld", ll->ll_state);
  99. return ll->ll_state;
  100. }
  101. /* called from ST Core, when a PM related packet arrives */
  102. unsigned long st_ll_sleep_state(struct st_data_s *st_data,
  103. unsigned char cmd)
  104. {
  105. switch (cmd) {
  106. case LL_SLEEP_IND: /* sleep ind */
  107. pr_debug("sleep indication recvd");
  108. ll_device_want_to_sleep(st_data);
  109. break;
  110. case LL_SLEEP_ACK: /* sleep ack */
  111. pr_err("sleep ack rcvd: host shouldn't");
  112. break;
  113. case LL_WAKE_UP_IND: /* wake ind */
  114. pr_debug("wake indication recvd");
  115. ll_device_want_to_wakeup(st_data);
  116. break;
  117. case LL_WAKE_UP_ACK: /* wake ack */
  118. pr_debug("wake ack rcvd");
  119. st_data->ll_state = ST_LL_AWAKE;
  120. break;
  121. default:
  122. pr_err(" unknown input/state ");
  123. return -EINVAL;
  124. }
  125. return 0;
  126. }
  127. /* Called from ST CORE to initialize ST LL */
  128. long st_ll_init(struct st_data_s *ll)
  129. {
  130. /* set state to invalid */
  131. ll->ll_state = ST_LL_INVALID;
  132. return 0;
  133. }
  134. /* Called from ST CORE to de-initialize ST LL */
  135. long st_ll_deinit(struct st_data_s *ll)
  136. {
  137. return 0;
  138. }