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