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
arch
arm
mach-netx
xc.c
Go to the documentation of this file.
1
/*
2
* arch/arm/mach-netx/xc.c
3
*
4
* Copyright (c) 2005 Sascha Hauer <
[email protected]
>, Pengutronix
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
8
* 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, write to the Free Software
17
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
*/
19
20
#include <
linux/init.h
>
21
#include <linux/device.h>
22
#include <
linux/firmware.h
>
23
#include <
linux/mutex.h
>
24
#include <linux/slab.h>
25
#include <
linux/io.h
>
26
#include <linux/export.h>
27
28
#include <mach/hardware.h>
29
#include <mach/irqs.h>
30
#include <
mach/netx-regs.h
>
31
32
#include <
mach/xc.h
>
33
34
static
DEFINE_MUTEX
(xc_lock);
35
36
static
int
xc_in_use = 0;
37
38
struct
fw_desc
{
39
unsigned
int
ofs
;
40
unsigned
int
size
;
41
unsigned
int
patch_ofs
;
42
unsigned
int
patch_entries
;
43
};
44
45
struct
fw_header
{
46
unsigned
int
magic
;
47
unsigned
int
type
;
48
unsigned
int
version
;
49
unsigned
int
reserved
[5];
50
struct
fw_desc
fw_desc
[3];
51
}
__attribute__
((packed));
52
53
int
xc_stop
(
struct
xc
*
x
)
54
{
55
writel
(
RPU_HOLD_PC
, x->
xmac_base
+
NETX_XMAC_RPU_HOLD_PC_OFS
);
56
writel
(
TPU_HOLD_PC
, x->
xmac_base
+
NETX_XMAC_TPU_HOLD_PC_OFS
);
57
writel
(
XPU_HOLD_PC
, x->
xpec_base
+
NETX_XPEC_XPU_HOLD_PC_OFS
);
58
return
0;
59
}
60
61
int
xc_start
(
struct
xc
*
x
)
62
{
63
writel
(0, x->
xmac_base
+
NETX_XMAC_RPU_HOLD_PC_OFS
);
64
writel
(0, x->
xmac_base
+
NETX_XMAC_TPU_HOLD_PC_OFS
);
65
writel
(0, x->
xpec_base
+
NETX_XPEC_XPU_HOLD_PC_OFS
);
66
return
0;
67
}
68
69
int
xc_running
(
struct
xc
*
x
)
70
{
71
return
(
readl
(x->
xmac_base
+
NETX_XMAC_RPU_HOLD_PC_OFS
) &
RPU_HOLD_PC
)
72
|| (
readl
(x->
xmac_base
+
NETX_XMAC_TPU_HOLD_PC_OFS
) &
TPU_HOLD_PC
)
73
|| (
readl
(x->
xpec_base
+
NETX_XPEC_XPU_HOLD_PC_OFS
) &
XPU_HOLD_PC
) ?
74
0 : 1;
75
}
76
77
int
xc_reset
(
struct
xc
*
x
)
78
{
79
writel
(0, x->
xpec_base
+
NETX_XPEC_PC_OFS
);
80
return
0;
81
}
82
83
static
int
xc_check_ptr(
struct
xc
*
x
,
unsigned
long
adr,
unsigned
int
size
)
84
{
85
if
(adr >=
NETX_PA_XMAC
(x->
no
) &&
86
adr + size <
NETX_PA_XMAC
(x->
no
) +
XMAC_MEM_SIZE
)
87
return
0;
88
89
if
(adr >=
NETX_PA_XPEC
(x->
no
) &&
90
adr + size <
NETX_PA_XPEC
(x->
no
) +
XPEC_MEM_SIZE
)
91
return
0;
92
93
dev_err
(x->
dev
,
"Illegal pointer in firmware found. aborting\n"
);
94
95
return
-1;
96
}
97
98
static
int
xc_patch(
struct
xc
*x,
const
void
*
patch
,
int
count
)
99
{
100
unsigned
int
val
, adr;
101
const
unsigned
int
*
data
= patch;
102
103
int
i
;
104
for
(i = 0; i <
count
; i++) {
105
adr = *data++;
106
val = *data++;
107
if
(xc_check_ptr(x, adr, 4) < 0)
108
return
-
EINVAL
;
109
110
writel
(val, (
void
__iomem
*)
io_p2v
(adr));
111
}
112
return
0;
113
}
114
115
int
xc_request_firmware
(
struct
xc
*x)
116
{
117
int
ret
;
118
char
name
[16];
119
const
struct
firmware
*
fw
;
120
struct
fw_header
*
head
;
121
unsigned
int
size
;
122
int
i
;
123
const
void
*
src
;
124
unsigned
long
dst
;
125
126
sprintf
(name,
"xc%d.bin"
, x->
no
);
127
128
ret =
request_firmware
(&fw, name, x->
dev
);
129
130
if
(ret < 0) {
131
dev_err
(x->
dev
,
"request_firmware failed\n"
);
132
return
ret
;
133
}
134
135
head = (
struct
fw_header
*)fw->
data
;
136
if
(head->
magic
!= 0x4e657458) {
137
if
(head->
magic
== 0x5874654e) {
138
dev_err
(x->
dev
,
139
"firmware magic is 'XteN'. Endianess problems?\n"
);
140
ret = -
ENODEV
;
141
goto
exit_release_firmware;
142
}
143
dev_err
(x->
dev
,
"unrecognized firmware magic 0x%08x\n"
,
144
head->
magic
);
145
ret = -
ENODEV
;
146
goto
exit_release_firmware;
147
}
148
149
x->
type
= head->
type
;
150
x->
version
= head->
version
;
151
152
ret = -
EINVAL
;
153
154
for
(i = 0; i < 3; i++) {
155
src = fw->
data
+ head->
fw_desc
[
i
].ofs;
156
dst = *(
unsigned
int
*)src;
157
src +=
sizeof
(
unsigned
int
);
158
size = head->
fw_desc
[
i
].size -
sizeof
(
unsigned
int
);
159
160
if
(xc_check_ptr(x, dst, size))
161
goto
exit_release_firmware;
162
163
memcpy
((
void
*)
io_p2v
(dst), src, size);
164
165
src = fw->
data
+ head->
fw_desc
[
i
].patch_ofs;
166
size = head->
fw_desc
[
i
].patch_entries;
167
ret = xc_patch(x, src, size);
168
if
(ret < 0)
169
goto
exit_release_firmware;
170
}
171
172
ret = 0;
173
174
exit_release_firmware:
175
release_firmware
(fw);
176
177
return
ret
;
178
}
179
180
struct
xc
*
request_xc
(
int
xcno,
struct
device
*
dev
)
181
{
182
struct
xc
*x =
NULL
;
183
184
mutex_lock
(&xc_lock);
185
186
if
(xcno > 3)
187
goto
exit
;
188
if
(xc_in_use & (1 << xcno))
189
goto
exit
;
190
191
x =
kmalloc
(
sizeof
(
struct
xc
),
GFP_KERNEL
);
192
if
(!x)
193
goto
exit
;
194
195
if
(!
request_mem_region
196
(
NETX_PA_XPEC
(xcno),
XPEC_MEM_SIZE
, kobject_name(&dev->
kobj
)))
197
goto
exit_free;
198
199
if
(!
request_mem_region
200
(
NETX_PA_XMAC
(xcno),
XMAC_MEM_SIZE
, kobject_name(&dev->
kobj
)))
201
goto
exit_release_1;
202
203
if
(!
request_mem_region
204
(
SRAM_INTERNAL_PHYS
(xcno),
SRAM_MEM_SIZE
, kobject_name(&dev->
kobj
)))
205
goto
exit_release_2;
206
207
x->
xpec_base
= (
void
*
__iomem
)
io_p2v
(
NETX_PA_XPEC
(xcno));
208
x->
xmac_base
= (
void
*
__iomem
)
io_p2v
(
NETX_PA_XMAC
(xcno));
209
x->
sram_base
=
ioremap
(
SRAM_INTERNAL_PHYS
(xcno),
SRAM_MEM_SIZE
);
210
if
(!x->
sram_base
)
211
goto
exit_release_3;
212
213
x->
irq
=
NETX_IRQ_XPEC
(xcno);
214
215
x->
no
= xcno;
216
x->
dev
=
dev
;
217
218
xc_in_use |= (1 << xcno);
219
220
goto
exit
;
221
222
exit_release_3:
223
release_mem_region
(
SRAM_INTERNAL_PHYS
(xcno),
SRAM_MEM_SIZE
);
224
exit_release_2:
225
release_mem_region
(
NETX_PA_XMAC
(xcno),
XMAC_MEM_SIZE
);
226
exit_release_1:
227
release_mem_region
(
NETX_PA_XPEC
(xcno),
XPEC_MEM_SIZE
);
228
exit_free:
229
kfree
(x);
230
x =
NULL
;
231
exit
:
232
mutex_unlock
(&xc_lock);
233
return
x
;
234
}
235
236
void
free_xc
(
struct
xc
*x)
237
{
238
int
xcno = x->
no
;
239
240
mutex_lock
(&xc_lock);
241
242
iounmap
(x->
sram_base
);
243
release_mem_region
(
SRAM_INTERNAL_PHYS
(xcno),
SRAM_MEM_SIZE
);
244
release_mem_region
(
NETX_PA_XMAC
(xcno),
XMAC_MEM_SIZE
);
245
release_mem_region
(
NETX_PA_XPEC
(xcno),
XPEC_MEM_SIZE
);
246
xc_in_use &= ~(1 << x->
no
);
247
kfree
(x);
248
249
mutex_unlock
(&xc_lock);
250
}
251
252
EXPORT_SYMBOL
(
free_xc
);
253
EXPORT_SYMBOL
(
request_xc
);
254
EXPORT_SYMBOL
(
xc_request_firmware
);
255
EXPORT_SYMBOL
(
xc_reset
);
256
EXPORT_SYMBOL
(
xc_running
);
257
EXPORT_SYMBOL
(
xc_start
);
258
EXPORT_SYMBOL
(
xc_stop
);
Generated on Thu Jan 10 2013 13:00:05 for Linux Kernel by
1.8.2