2 * Shared Transport driver
3 * HCI-LL module responsible for TI proprietary HCI_LL protocol
4 * Copyright (C) 2009 Texas Instruments
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #define pr_fmt(fmt) "(stll) :" fmt
22 #include <linux/skbuff.h>
23 #include <linux/module.h>
24 #include <linux/ti_wilink_st.h>
26 /**********************************************************************/
27 /* internal functions */
28 static void send_ll_cmd(struct st_data_s *st_data,
32 pr_info("%s: writing %x", __func__, cmd);
33 st_int_write(st_data, &cmd, 1);
37 static void ll_device_want_to_sleep(struct st_data_s *st_data)
39 pr_debug("%s", __func__);
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);
45 send_ll_cmd(st_data, LL_SLEEP_ACK);
47 st_data->ll_state = ST_LL_ASLEEP;
50 static void ll_device_want_to_wakeup(struct st_data_s *st_data)
52 /* diff actions in diff states */
53 switch (st_data->ll_state) {
55 send_ll_cmd(st_data, LL_WAKE_UP_ACK); /* send wake_ack */
57 case ST_LL_ASLEEP_TO_AWAKE:
58 /* duplicate wake_ind */
59 pr_err("duplicate wake_ind while waiting for Wake ack");
62 /* duplicate wake_ind */
63 pr_err("duplicate wake_ind already AWAKE");
65 case ST_LL_AWAKE_TO_ASLEEP:
66 /* duplicate wake_ind */
67 pr_err("duplicate wake_ind");
71 st_data->ll_state = ST_LL_AWAKE;
74 /**********************************************************************/
75 /* functions invoked by ST Core */
77 /* called when ST Core wants to
79 void st_ll_enable(struct st_data_s *ll)
81 ll->ll_state = ST_LL_AWAKE;
84 /* called when ST Core /local module wants to
86 void st_ll_disable(struct st_data_s *ll)
88 ll->ll_state = ST_LL_INVALID;
91 /* called when ST Core wants to update the state */
92 void st_ll_wakeup(struct st_data_s *ll)
94 if (likely(ll->ll_state != ST_LL_AWAKE)) {
95 send_ll_cmd(ll, LL_WAKE_UP_IND); /* WAKE_IND */
96 ll->ll_state = ST_LL_ASLEEP_TO_AWAKE;
98 /* don't send the duplicate wake_indication */
99 pr_err(" Chip already AWAKE ");
103 /* called when ST Core wants the state */
104 unsigned long st_ll_getstate(struct st_data_s *ll)
106 pr_debug(" returning state %ld", ll->ll_state);
110 /* called from ST Core, when a PM related packet arrives */
111 unsigned long st_ll_sleep_state(struct st_data_s *st_data,
115 case LL_SLEEP_IND: /* sleep ind */
116 pr_info("sleep indication recvd");
117 ll_device_want_to_sleep(st_data);
119 case LL_SLEEP_ACK: /* sleep ack */
120 pr_err("sleep ack rcvd: host shouldn't");
122 case LL_WAKE_UP_IND: /* wake ind */
123 pr_info("wake indication recvd");
124 ll_device_want_to_wakeup(st_data);
126 case LL_WAKE_UP_ACK: /* wake ack */
127 pr_info("wake ack rcvd");
128 st_data->ll_state = ST_LL_AWAKE;
131 pr_err(" unknown input/state ");
137 /* Called from ST CORE to initialize ST LL */
138 long st_ll_init(struct st_data_s *ll)
140 /* set state to invalid */
141 ll->ll_state = ST_LL_INVALID;
145 /* Called from ST CORE to de-initialize ST LL */
146 long st_ll_deinit(struct st_data_s *ll)