Linux Kernel
3.7.1
Main Page
Related Pages
Modules
Namespaces
Data Structures
Files
File List
Globals
All
Data Structures
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
drivers
usb
host
whci
init.c
Go to the documentation of this file.
1
/*
2
* Wireless Host Controller (WHC) initialization.
3
*
4
* Copyright (C) 2007 Cambridge Silicon Radio Ltd.
5
*
6
* This program is free software; you can redistribute it and/or
7
* modify it under the terms of the GNU General Public License version
8
* 2 as 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, see <http://www.gnu.org/licenses/>.
17
*/
18
#include <linux/kernel.h>
19
#include <
linux/gfp.h
>
20
#include <
linux/dma-mapping.h
>
21
#include <
linux/uwb/umc.h
>
22
23
#include "../../wusbcore/wusbhc.h"
24
25
#include "
whcd.h
"
26
27
/*
28
* Reset the host controller.
29
*/
30
static
void
whc_hw_reset(
struct
whc
*
whc
)
31
{
32
le_writel(
WUSBCMD_WHCRESET
, whc->
base
+
WUSBCMD
);
33
whci_wait_for
(&whc->
umc
->dev, whc->
base
+
WUSBCMD
,
WUSBCMD_WHCRESET
, 0,
34
100,
"reset"
);
35
}
36
37
static
void
whc_hw_init_di_buf(
struct
whc
*
whc
)
38
{
39
int
d
;
40
41
/* Disable all entries in the Device Information buffer. */
42
for
(d = 0; d < whc->
n_devices
; d++)
43
whc->
di_buf
[d].addr_sec_info =
WHC_DI_DISABLE
;
44
45
le_writeq(whc->
di_buf_dma
, whc->
base
+
WUSBDEVICEINFOADDR
);
46
}
47
48
static
void
whc_hw_init_dn_buf(
struct
whc *whc)
49
{
50
/* Clear the Device Notification buffer to ensure the V (valid)
51
* bits are clear. */
52
memset
(whc->
dn_buf
, 0, 4096);
53
54
le_writeq(whc->
dn_buf_dma
, whc->
base
+
WUSBDNTSBUFADDR
);
55
}
56
57
int
whc_init
(
struct
whc *whc)
58
{
59
u32
whcsparams;
60
int
ret
,
i
;
61
resource_size_t
start
,
len
;
62
63
spin_lock_init
(&whc->
lock
);
64
mutex_init
(&whc->
mutex
);
65
init_waitqueue_head
(&whc->
cmd_wq
);
66
init_waitqueue_head
(&whc->
async_list_wq
);
67
init_waitqueue_head
(&whc->
periodic_list_wq
);
68
whc->
workqueue
=
create_singlethread_workqueue
(dev_name(&whc->
umc
->dev));
69
if
(whc->
workqueue
==
NULL
) {
70
ret = -
ENOMEM
;
71
goto
error
;
72
}
73
INIT_WORK
(&whc->
dn_work
,
whc_dn_work
);
74
75
INIT_WORK
(&whc->
async_work
,
scan_async_work
);
76
INIT_LIST_HEAD(&whc->
async_list
);
77
INIT_LIST_HEAD(&whc->
async_removed_list
);
78
79
INIT_WORK
(&whc->
periodic_work
,
scan_periodic_work
);
80
for
(i = 0; i < 5; i++)
81
INIT_LIST_HEAD(&whc->
periodic_list
[i]);
82
INIT_LIST_HEAD(&whc->
periodic_removed_list
);
83
84
/* Map HC registers. */
85
start = whc->
umc
->resource.start;
86
len = whc->
umc
->resource.end - start + 1;
87
if
(!
request_mem_region
(start, len,
"whci-hc"
)) {
88
dev_err
(&whc->
umc
->dev,
"can't request HC region\n"
);
89
ret = -
EBUSY
;
90
goto
error
;
91
}
92
whc->
base_phys
=
start
;
93
whc->
base
=
ioremap
(start, len);
94
if
(!whc->
base
) {
95
dev_err
(&whc->
umc
->dev,
"ioremap\n"
);
96
ret = -
ENOMEM
;
97
goto
error
;
98
}
99
100
whc_hw_reset(whc);
101
102
/* Read maximum number of devices, keys and MMC IEs. */
103
whcsparams = le_readl(whc->
base
+
WHCSPARAMS
);
104
whc->
n_devices
=
WHCSPARAMS_TO_N_DEVICES
(whcsparams);
105
whc->
n_keys
=
WHCSPARAMS_TO_N_KEYS
(whcsparams);
106
whc->
n_mmc_ies
=
WHCSPARAMS_TO_N_MMC_IES
(whcsparams);
107
108
dev_dbg
(&whc->
umc
->dev,
"N_DEVICES = %d, N_KEYS = %d, N_MMC_IES = %d\n"
,
109
whc->
n_devices
, whc->
n_keys
, whc->
n_mmc_ies
);
110
111
whc->
qset_pool
=
dma_pool_create
(
"qset"
, &whc->
umc
->dev,
112
sizeof
(
struct
whc_qset
), 64, 0);
113
if
(whc->
qset_pool
==
NULL
) {
114
ret = -
ENOMEM
;
115
goto
error
;
116
}
117
118
ret =
asl_init
(whc);
119
if
(ret < 0)
120
goto
error
;
121
ret =
pzl_init
(whc);
122
if
(ret < 0)
123
goto
error
;
124
125
/* Allocate and initialize a buffer for generic commands, the
126
Device Information buffer, and the Device Notification
127
buffer. */
128
129
whc->
gen_cmd_buf
=
dma_alloc_coherent
(&whc->
umc
->dev,
WHC_GEN_CMD_DATA_LEN
,
130
&whc->
gen_cmd_buf_dma
,
GFP_KERNEL
);
131
if
(whc->
gen_cmd_buf
==
NULL
) {
132
ret = -
ENOMEM
;
133
goto
error
;
134
}
135
136
whc->
dn_buf
=
dma_alloc_coherent
(&whc->
umc
->dev,
137
sizeof
(
struct
dn_buf_entry
) *
WHC_N_DN_ENTRIES
,
138
&whc->
dn_buf_dma
,
GFP_KERNEL
);
139
if
(!whc->
dn_buf
) {
140
ret = -
ENOMEM
;
141
goto
error
;
142
}
143
whc_hw_init_dn_buf(whc);
144
145
whc->
di_buf
=
dma_alloc_coherent
(&whc->
umc
->dev,
146
sizeof
(
struct
di_buf_entry
) * whc->
n_devices
,
147
&whc->
di_buf_dma
,
GFP_KERNEL
);
148
if
(!whc->
di_buf
) {
149
ret = -
ENOMEM
;
150
goto
error
;
151
}
152
whc_hw_init_di_buf(whc);
153
154
return
0;
155
156
error
:
157
whc_clean_up
(whc);
158
return
ret
;
159
}
160
161
void
whc_clean_up
(
struct
whc *whc)
162
{
163
resource_size_t
len
;
164
165
if
(whc->
di_buf
)
166
dma_free_coherent
(&whc->
umc
->dev,
sizeof
(
struct
di_buf_entry
) * whc->
n_devices
,
167
whc->
di_buf
, whc->
di_buf_dma
);
168
if
(whc->
dn_buf
)
169
dma_free_coherent
(&whc->
umc
->dev,
sizeof
(
struct
dn_buf_entry
) *
WHC_N_DN_ENTRIES
,
170
whc->
dn_buf
, whc->
dn_buf_dma
);
171
if
(whc->
gen_cmd_buf
)
172
dma_free_coherent
(&whc->
umc
->dev,
WHC_GEN_CMD_DATA_LEN
,
173
whc->
gen_cmd_buf
, whc->
gen_cmd_buf_dma
);
174
175
pzl_clean_up
(whc);
176
asl_clean_up
(whc);
177
178
if
(whc->
qset_pool
)
179
dma_pool_destroy
(whc->
qset_pool
);
180
181
len = resource_size(&whc->
umc
->resource);
182
if
(whc->
base
)
183
iounmap
(whc->
base
);
184
if
(whc->
base_phys
)
185
release_mem_region
(whc->
base_phys
, len);
186
187
if
(whc->
workqueue
)
188
destroy_workqueue
(whc->
workqueue
);
189
}
Generated on Thu Jan 10 2013 12:54:18 for Linux Kernel by
1.8.2