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