Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/drivers/misc/ti-st/st_ll.c
15111 views
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/ti_wilink_st.h>
26
27
/**********************************************************************/
28
/* internal functions */
29
static void send_ll_cmd(struct st_data_s *st_data,
30
unsigned char cmd)
31
{
32
33
pr_debug("%s: writing %x", __func__, cmd);
34
st_int_write(st_data, &cmd, 1);
35
return;
36
}
37
38
static void ll_device_want_to_sleep(struct st_data_s *st_data)
39
{
40
pr_debug("%s", __func__);
41
/* sanity check */
42
if (st_data->ll_state != ST_LL_AWAKE)
43
pr_err("ERR hcill: ST_LL_GO_TO_SLEEP_IND"
44
"in state %ld", st_data->ll_state);
45
46
send_ll_cmd(st_data, LL_SLEEP_ACK);
47
/* update state */
48
st_data->ll_state = ST_LL_ASLEEP;
49
}
50
51
static void ll_device_want_to_wakeup(struct st_data_s *st_data)
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
75
/**********************************************************************/
76
/* functions invoked by ST Core */
77
78
/* called when ST Core wants to
79
* enable ST LL */
80
void st_ll_enable(struct st_data_s *ll)
81
{
82
ll->ll_state = ST_LL_AWAKE;
83
}
84
85
/* called when ST Core /local module wants to
86
* disable ST LL */
87
void st_ll_disable(struct st_data_s *ll)
88
{
89
ll->ll_state = ST_LL_INVALID;
90
}
91
92
/* called when ST Core wants to update the state */
93
void st_ll_wakeup(struct st_data_s *ll)
94
{
95
if (likely(ll->ll_state != ST_LL_AWAKE)) {
96
send_ll_cmd(ll, LL_WAKE_UP_IND); /* WAKE_IND */
97
ll->ll_state = ST_LL_ASLEEP_TO_AWAKE;
98
} else {
99
/* don't send the duplicate wake_indication */
100
pr_err(" Chip already AWAKE ");
101
}
102
}
103
104
/* called when ST Core wants the state */
105
unsigned long st_ll_getstate(struct st_data_s *ll)
106
{
107
pr_debug(" returning state %ld", ll->ll_state);
108
return ll->ll_state;
109
}
110
111
/* called from ST Core, when a PM related packet arrives */
112
unsigned long st_ll_sleep_state(struct st_data_s *st_data,
113
unsigned char cmd)
114
{
115
switch (cmd) {
116
case LL_SLEEP_IND: /* sleep ind */
117
pr_debug("sleep indication recvd");
118
ll_device_want_to_sleep(st_data);
119
break;
120
case LL_SLEEP_ACK: /* sleep ack */
121
pr_err("sleep ack rcvd: host shouldn't");
122
break;
123
case LL_WAKE_UP_IND: /* wake ind */
124
pr_debug("wake indication recvd");
125
ll_device_want_to_wakeup(st_data);
126
break;
127
case LL_WAKE_UP_ACK: /* wake ack */
128
pr_debug("wake ack rcvd");
129
st_data->ll_state = ST_LL_AWAKE;
130
break;
131
default:
132
pr_err(" unknown input/state ");
133
return -EINVAL;
134
}
135
return 0;
136
}
137
138
/* Called from ST CORE to initialize ST LL */
139
long st_ll_init(struct st_data_s *ll)
140
{
141
/* set state to invalid */
142
ll->ll_state = ST_LL_INVALID;
143
return 0;
144
}
145
146
/* Called from ST CORE to de-initialize ST LL */
147
long st_ll_deinit(struct st_data_s *ll)
148
{
149
return 0;
150
}
151
152