ed1e4bc180d3e1327939d2e86deb3b40068fe27f
[deliverable/linux.git] / drivers / staging / ti-st / st_ll.c
1 /*
2 * Shared Transport driver
3 * HCI-LL module responsible for TI proprietary HCI_LL protocol
4 * Copyright (C) 2009 Texas Instruments
5 *
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.
9 *
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.
14 *
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
18 *
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 /**********************************************************************/
27 /* internal functions */
28 static void send_ll_cmd(struct st_data_s *st_data,
29 unsigned char cmd)
30 {
31
32 pr_info("%s: writing %x", __func__, cmd);
33 st_int_write(st_data, &cmd, 1);
34 return;
35 }
36
37 static void ll_device_want_to_sleep(struct st_data_s *st_data)
38 {
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
45 send_ll_cmd(st_data, LL_SLEEP_ACK);
46 /* update state */
47 st_data->ll_state = ST_LL_ASLEEP;
48 }
49
50 static void ll_device_want_to_wakeup(struct st_data_s *st_data)
51 {
52 /* diff actions in diff states */
53 switch (st_data->ll_state) {
54 case ST_LL_ASLEEP:
55 send_ll_cmd(st_data, LL_WAKE_UP_ACK); /* send wake_ack */
56 break;
57 case ST_LL_ASLEEP_TO_AWAKE:
58 /* duplicate wake_ind */
59 pr_err("duplicate wake_ind while waiting for Wake ack");
60 break;
61 case ST_LL_AWAKE:
62 /* duplicate wake_ind */
63 pr_err("duplicate wake_ind already AWAKE");
64 break;
65 case ST_LL_AWAKE_TO_ASLEEP:
66 /* duplicate wake_ind */
67 pr_err("duplicate wake_ind");
68 break;
69 }
70 /* update state */
71 st_data->ll_state = ST_LL_AWAKE;
72 }
73
74 /**********************************************************************/
75 /* functions invoked by ST Core */
76
77 /* called when ST Core wants to
78 * enable ST LL */
79 void st_ll_enable(struct st_data_s *ll)
80 {
81 ll->ll_state = ST_LL_AWAKE;
82 }
83
84 /* called when ST Core /local module wants to
85 * disable ST LL */
86 void st_ll_disable(struct st_data_s *ll)
87 {
88 ll->ll_state = ST_LL_INVALID;
89 }
90
91 /* called when ST Core wants to update the state */
92 void st_ll_wakeup(struct st_data_s *ll)
93 {
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;
97 } else {
98 /* don't send the duplicate wake_indication */
99 pr_err(" Chip already AWAKE ");
100 }
101 }
102
103 /* called when ST Core wants the state */
104 unsigned long st_ll_getstate(struct st_data_s *ll)
105 {
106 pr_debug(" returning state %ld", ll->ll_state);
107 return ll->ll_state;
108 }
109
110 /* called from ST Core, when a PM related packet arrives */
111 unsigned long st_ll_sleep_state(struct st_data_s *st_data,
112 unsigned char cmd)
113 {
114 switch (cmd) {
115 case LL_SLEEP_IND: /* sleep ind */
116 pr_info("sleep indication recvd");
117 ll_device_want_to_sleep(st_data);
118 break;
119 case LL_SLEEP_ACK: /* sleep ack */
120 pr_err("sleep ack rcvd: host shouldn't");
121 break;
122 case LL_WAKE_UP_IND: /* wake ind */
123 pr_info("wake indication recvd");
124 ll_device_want_to_wakeup(st_data);
125 break;
126 case LL_WAKE_UP_ACK: /* wake ack */
127 pr_info("wake ack rcvd");
128 st_data->ll_state = ST_LL_AWAKE;
129 break;
130 default:
131 pr_err(" unknown input/state ");
132 return -1;
133 }
134 return 0;
135 }
136
137 /* Called from ST CORE to initialize ST LL */
138 long st_ll_init(struct st_data_s *ll)
139 {
140 /* set state to invalid */
141 ll->ll_state = ST_LL_INVALID;
142 return 0;
143 }
144
145 /* Called from ST CORE to de-initialize ST LL */
146 long st_ll_deinit(struct st_data_s *ll)
147 {
148 return 0;
149 }
This page took 0.034095 seconds and 4 git commands to generate.