1 /* $NetBSD: ixp425_pci_space.c,v 1.6 2006/04/10 03:36:03 simonb Exp $ */
2
3 /*
4 * Copyright (c) 2003
5 * Ichiro FUKUHARA <ichiro@ichiro.org>.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by Ichiro FUKUHARA.
19 * 4. The name of the company nor the name of the author may be used to
20 * endorse or promote products derived from this software without specific
21 * prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY ICHIRO FUKUHARA ``AS IS'' AND ANY EXPRESS OR
24 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26 * IN NO EVENT SHALL ICHIRO FUKUHARA OR THE VOICES IN HIS HEAD BE LIABLE FOR
27 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 */
35
36 #include <sys/cdefs.h>
37 __FBSDID("$FreeBSD$");
38
39 /*
40 * bus_space PCI functions for ixp425
41 */
42
43 #include <sys/param.h>
44 #include <sys/systm.h>
45 #include <sys/bus.h>
46 #include <sys/endian.h>
47
48 #include <machine/pcb.h>
49
50 #include <vm/vm.h>
51 #include <vm/vm_kern.h>
52 #include <vm/pmap.h>
53 #include <vm/vm_page.h>
54 #include <vm/vm_extern.h>
55
56 #include <machine/bus.h>
57
58 #include <arm/xscale/ixp425/ixp425reg.h>
59 #include <arm/xscale/ixp425/ixp425var.h>
60
61 /*
62 * Macros to read/write registers
63 */
64 #define CSR_READ_4(x) *(volatile uint32_t *) \
65 (IXP425_PCI_CSR_BASE + (x))
66 #define CSR_WRITE_4(x, v) *(volatile uint32_t *) \
67 (IXP425_PCI_CSR_BASE + (x)) = (v)
68
69 /* Proto types for all the bus_space structure functions */
70 bs_protos(ixp425_pci);
71 bs_protos(ixp425_pci_io);
72 bs_protos(ixp425_pci_mem);
73
74 /* special I/O functions */
75 static u_int8_t _pci_io_bs_r_1(bus_space_tag_t tag, bus_space_handle_t, bus_size_t);
76 static u_int16_t _pci_io_bs_r_2(bus_space_tag_t tag, bus_space_handle_t, bus_size_t);
77 static u_int32_t _pci_io_bs_r_4(bus_space_tag_t tag, bus_space_handle_t, bus_size_t);
78
79 static void _pci_io_bs_w_1(bus_space_tag_t tag, bus_space_handle_t, bus_size_t, u_int8_t);
80 static void _pci_io_bs_w_2(bus_space_tag_t tag, bus_space_handle_t, bus_size_t, u_int16_t);
81 static void _pci_io_bs_w_4(bus_space_tag_t tag, bus_space_handle_t, bus_size_t, u_int32_t);
82
83 #ifdef __ARMEB__
84 static u_int8_t _pci_io_bs_r_1_s(bus_space_tag_t tag, bus_space_handle_t, bus_size_t);
85 static u_int16_t _pci_io_bs_r_2_s(bus_space_tag_t tag, bus_space_handle_t, bus_size_t);
86 static u_int32_t _pci_io_bs_r_4_s(bus_space_tag_t tag, bus_space_handle_t, bus_size_t);
87
88 static void _pci_io_bs_w_1_s(bus_space_tag_t tag, bus_space_handle_t, bus_size_t, u_int8_t);
89 static void _pci_io_bs_w_2_s(bus_space_tag_t tag, bus_space_handle_t, bus_size_t, u_int16_t);
90 static void _pci_io_bs_w_4_s(bus_space_tag_t tag, bus_space_handle_t, bus_size_t, u_int32_t);
91
92 static u_int8_t _pci_mem_bs_r_1(bus_space_tag_t tag, bus_space_handle_t, bus_size_t);
93 static u_int16_t _pci_mem_bs_r_2(bus_space_tag_t tag, bus_space_handle_t, bus_size_t);
94 static u_int32_t _pci_mem_bs_r_4(bus_space_tag_t tag, bus_space_handle_t, bus_size_t);
95
96 static void _pci_mem_bs_w_1(bus_space_tag_t tag, bus_space_handle_t, bus_size_t, u_int8_t);
97 static void _pci_mem_bs_w_2(bus_space_tag_t tag, bus_space_handle_t, bus_size_t, u_int16_t);
98 static void _pci_mem_bs_w_4(bus_space_tag_t tag, bus_space_handle_t, bus_size_t, u_int32_t);
99 #endif
100
101 struct bus_space ixp425_pci_io_bs_tag_template = {
102 /* mapping/unmapping */
103 .bs_map = ixp425_pci_io_bs_map,
104 .bs_unmap = ixp425_pci_io_bs_unmap,
105 .bs_subregion = ixp425_pci_bs_subregion,
106
107 .bs_alloc = ixp425_pci_io_bs_alloc,
108 .bs_free = ixp425_pci_io_bs_free,
109
110 /* barrier */
111 .bs_barrier = ixp425_pci_bs_barrier,
112
113 /*
114 * IXP425 processor does not have PCI I/O windows
115 */
116 /* read (single) */
117 .bs_r_1 = _pci_io_bs_r_1,
118 .bs_r_2 = _pci_io_bs_r_2,
119 .bs_r_4 = _pci_io_bs_r_4,
120
121 /* write (single) */
122 .bs_w_1 = _pci_io_bs_w_1,
123 .bs_w_2 = _pci_io_bs_w_2,
124 .bs_w_4 = _pci_io_bs_w_4,
125
126 #ifdef __ARMEB__
127 .bs_r_1_s = _pci_io_bs_r_1_s,
128 .bs_r_2_s = _pci_io_bs_r_2_s,
129 .bs_r_4_s = _pci_io_bs_r_4_s,
130
131 .bs_w_1_s = _pci_io_bs_w_1_s,
132 .bs_w_2_s = _pci_io_bs_w_2_s,
133 .bs_w_4_s = _pci_io_bs_w_4_s,
134 #else
135 .bs_r_1_s = _pci_io_bs_r_1,
136 .bs_r_2_s = _pci_io_bs_r_2,
137 .bs_r_4_s = _pci_io_bs_r_4,
138
139 .bs_w_1_s = _pci_io_bs_w_1,
140 .bs_w_2_s = _pci_io_bs_w_2,
141 .bs_w_4_s = _pci_io_bs_w_4,
142 #endif
143 };
144
145 void
146 ixp425_io_bs_init(bus_space_tag_t bs, void *cookie)
147 {
148 *bs = ixp425_pci_io_bs_tag_template;
149 bs->bs_privdata = cookie;
150 }
151
152 struct bus_space ixp425_pci_mem_bs_tag_template = {
153 /* mapping/unmapping */
154 .bs_map = ixp425_pci_mem_bs_map,
155 .bs_unmap = ixp425_pci_mem_bs_unmap,
156 .bs_subregion = ixp425_pci_bs_subregion,
157
158 .bs_alloc = ixp425_pci_mem_bs_alloc,
159 .bs_free = ixp425_pci_mem_bs_free,
160
161 /* barrier */
162 .bs_barrier = ixp425_pci_bs_barrier,
163
164 #ifdef __ARMEB__
165 /* read (single) */
166 .bs_r_1_s = _pci_mem_bs_r_1,
167 .bs_r_2_s = _pci_mem_bs_r_2,
168 .bs_r_4_s = _pci_mem_bs_r_4,
169
170 .bs_r_1 = ixp425_pci_mem_bs_r_1,
171 .bs_r_2 = ixp425_pci_mem_bs_r_2,
172 .bs_r_4 = ixp425_pci_mem_bs_r_4,
173
174 /* write (single) */
175 .bs_w_1_s = _pci_mem_bs_w_1,
176 .bs_w_2_s = _pci_mem_bs_w_2,
177 .bs_w_4_s = _pci_mem_bs_w_4,
178
179 .bs_w_1 = ixp425_pci_mem_bs_w_1,
180 .bs_w_2 = ixp425_pci_mem_bs_w_2,
181 .bs_w_4 = ixp425_pci_mem_bs_w_4,
182 #else
183 /* read (single) */
184 .bs_r_1 = ixp425_pci_mem_bs_r_1,
185 .bs_r_2 = ixp425_pci_mem_bs_r_2,
186 .bs_r_4 = ixp425_pci_mem_bs_r_4,
187 .bs_r_1_s = ixp425_pci_mem_bs_r_1,
188 .bs_r_2_s = ixp425_pci_mem_bs_r_2,
189 .bs_r_4_s = ixp425_pci_mem_bs_r_4,
190
191 /* write (single) */
192 .bs_w_1 = ixp425_pci_mem_bs_w_1,
193 .bs_w_2 = ixp425_pci_mem_bs_w_2,
194 .bs_w_4 = ixp425_pci_mem_bs_w_4,
195 .bs_w_1_s = ixp425_pci_mem_bs_w_1,
196 .bs_w_2_s = ixp425_pci_mem_bs_w_2,
197 .bs_w_4_s = ixp425_pci_mem_bs_w_4,
198 #endif
199 };
200
201 void
202 ixp425_mem_bs_init(bus_space_tag_t bs, void *cookie)
203 {
204 *bs = ixp425_pci_mem_bs_tag_template;
205 bs->bs_privdata = cookie;
206 }
207
208 /* common routine */
209 int
210 ixp425_pci_bs_subregion(bus_space_tag_t tag, bus_space_handle_t bsh, bus_size_t offset,
211 bus_size_t size, bus_space_handle_t *nbshp)
212 {
213 *nbshp = bsh + offset;
214 return (0);
215 }
216
217 void
218 ixp425_pci_bs_barrier(bus_space_tag_t tag, bus_space_handle_t bsh, bus_size_t offset,
219 bus_size_t len, int flags)
220 {
221 /* NULL */
222 }
223
224 /* io bs */
225 int
226 ixp425_pci_io_bs_map(bus_space_tag_t tag, bus_addr_t bpa, bus_size_t size,
227 int cacheable, bus_space_handle_t *bshp)
228 {
229 *bshp = bpa;
230 return (0);
231 }
232
233 void
234 ixp425_pci_io_bs_unmap(bus_space_tag_t tag, bus_space_handle_t h, bus_size_t size)
235 {
236 /* Nothing to do. */
237 }
238
239 int
240 ixp425_pci_io_bs_alloc(bus_space_tag_t tag, bus_addr_t rstart, bus_addr_t rend,
241 bus_size_t size, bus_size_t alignment, bus_size_t boundary, int cacheable,
242 bus_addr_t *bpap, bus_space_handle_t *bshp)
243 {
244 panic("ixp425_pci_io_bs_alloc(): not implemented\n");
245 }
246
247 void
248 ixp425_pci_io_bs_free(bus_space_tag_t tag, bus_space_handle_t bsh, bus_size_t size)
249 {
250 panic("ixp425_pci_io_bs_free(): not implemented\n");
251 }
252
253 /* special I/O functions */
254 static __inline u_int32_t
255 _bs_r(bus_space_tag_t tag, bus_space_handle_t ioh, bus_size_t off, u_int32_t be)
256 {
257 u_int32_t data;
258
259 CSR_WRITE_4(PCI_NP_AD, (ioh + off) & ~3);
260 CSR_WRITE_4(PCI_NP_CBE, be | COMMAND_NP_IO_READ);
261 data = CSR_READ_4(PCI_NP_RDATA);
262 if (CSR_READ_4(PCI_ISR) & ISR_PFE)
263 CSR_WRITE_4(PCI_ISR, ISR_PFE);
264
265 return data;
266 }
267
268 static u_int8_t
269 _pci_io_bs_r_1(bus_space_tag_t tag, bus_space_handle_t ioh, bus_size_t off)
270 {
271 u_int32_t data, n, be;
272
273 n = (ioh + off) % 4;
274 be = (0xf & ~(1U << n)) << NP_CBE_SHIFT;
275 data = _bs_r(tag, ioh, off, be);
276
277 return data >> (8 * n);
278 }
279
280 static u_int16_t
281 _pci_io_bs_r_2(bus_space_tag_t tag, bus_space_handle_t ioh, bus_size_t off)
282 {
283 u_int32_t data, n, be;
284
285 n = (ioh + off) % 4;
286 be = (0xf & ~((1U << n) | (1U << (n + 1)))) << NP_CBE_SHIFT;
287 data = _bs_r(tag, ioh, off, be);
288
289 return data >> (8 * n);
290 }
291
292 static u_int32_t
293 _pci_io_bs_r_4(bus_space_tag_t tag, bus_space_handle_t ioh, bus_size_t off)
294 {
295 u_int32_t data;
296
297 data = _bs_r(tag, ioh, off, 0);
298 return data;
299 }
300
301 #ifdef __ARMEB__
302 static u_int8_t
303 _pci_io_bs_r_1_s(bus_space_tag_t tag, bus_space_handle_t ioh, bus_size_t off)
304 {
305 u_int32_t data, n, be;
306
307 n = (ioh + off) % 4;
308 be = (0xf & ~(1U << n)) << NP_CBE_SHIFT;
309 data = _bs_r(tag, ioh, off, be);
310
311 return data >> (8 * n);
312 }
313
314 static u_int16_t
315 _pci_io_bs_r_2_s(bus_space_tag_t tag, bus_space_handle_t ioh, bus_size_t off)
316 {
317 u_int32_t data, n, be;
318
319 n = (ioh + off) % 4;
320 be = (0xf & ~((1U << n) | (1U << (n + 1)))) << NP_CBE_SHIFT;
321 data = _bs_r(tag, ioh, off, be);
322
323 return data >> (8 * n);
324 }
325
326 static u_int32_t
327 _pci_io_bs_r_4_s(bus_space_tag_t tag, bus_space_handle_t ioh, bus_size_t off)
328 {
329 u_int32_t data;
330
331 data = _bs_r(tag, ioh, off, 0);
332 return le32toh(data);
333 }
334 #endif /* __ARMEB__ */
335
336 static __inline void
337 _bs_w(bus_space_tag_t tag, bus_space_handle_t ioh, bus_size_t off,
338 u_int32_t be, u_int32_t data)
339 {
340 CSR_WRITE_4(PCI_NP_AD, (ioh + off) & ~3);
341 CSR_WRITE_4(PCI_NP_CBE, be | COMMAND_NP_IO_WRITE);
342 CSR_WRITE_4(PCI_NP_WDATA, data);
343 if (CSR_READ_4(PCI_ISR) & ISR_PFE)
344 CSR_WRITE_4(PCI_ISR, ISR_PFE);
345 }
346
347 static void
348 _pci_io_bs_w_1(bus_space_tag_t tag, bus_space_handle_t ioh, bus_size_t off,
349 u_int8_t val)
350 {
351 u_int32_t data, n, be;
352
353 n = (ioh + off) % 4;
354 be = (0xf & ~(1U << n)) << NP_CBE_SHIFT;
355 data = val << (8 * n);
356 _bs_w(tag, ioh, off, be, data);
357 }
358
359 static void
360 _pci_io_bs_w_2(bus_space_tag_t tag, bus_space_handle_t ioh, bus_size_t off,
361 u_int16_t val)
362 {
363 u_int32_t data, n, be;
364
365 n = (ioh + off) % 4;
366 be = (0xf & ~((1U << n) | (1U << (n + 1)))) << NP_CBE_SHIFT;
367 data = val << (8 * n);
368 _bs_w(tag, ioh, off, be, data);
369 }
370
371 static void
372 _pci_io_bs_w_4(bus_space_tag_t tag, bus_space_handle_t ioh, bus_size_t off,
373 u_int32_t val)
374 {
375 _bs_w(tag, ioh, off, 0, val);
376 }
377
378 #ifdef __ARMEB__
379 static void
380 _pci_io_bs_w_1_s(bus_space_tag_t tag, bus_space_handle_t ioh, bus_size_t off,
381 u_int8_t val)
382 {
383 u_int32_t data, n, be;
384
385 n = (ioh + off) % 4;
386 be = (0xf & ~(1U << n)) << NP_CBE_SHIFT;
387 data = val << (8 * n);
388 _bs_w(tag, ioh, off, be, data);
389 }
390
391 static void
392 _pci_io_bs_w_2_s(bus_space_tag_t tag, bus_space_handle_t ioh, bus_size_t off,
393 u_int16_t val)
394 {
395 u_int32_t data, n, be;
396
397 n = (ioh + off) % 4;
398 be = (0xf & ~((1U << n) | (1U << (n + 1)))) << NP_CBE_SHIFT;
399 data = val << (8 * n);
400 _bs_w(tag, ioh, off, be, data);
401 }
402
403 static void
404 _pci_io_bs_w_4_s(bus_space_tag_t tag, bus_space_handle_t ioh, bus_size_t off,
405 u_int32_t val)
406 {
407 _bs_w(tag, ioh, off, 0, htole32(val));
408 }
409 #endif /* __ARMEB__ */
410
411 /* mem bs */
412 int
413 ixp425_pci_mem_bs_map(bus_space_tag_t tag, bus_addr_t bpa, bus_size_t size,
414 int cacheable, bus_space_handle_t *bshp)
415 {
416 *bshp = (vm_offset_t)pmap_mapdev(bpa, size);
417 return (0);
418 }
419
420 void
421 ixp425_pci_mem_bs_unmap(bus_space_tag_t tag, bus_space_handle_t h, bus_size_t size)
422 {
423
424 pmap_unmapdev((vm_offset_t)h, size);
425 }
426
427 int
428 ixp425_pci_mem_bs_alloc(bus_space_tag_t tag, bus_addr_t rstart, bus_addr_t rend,
429 bus_size_t size, bus_size_t alignment, bus_size_t boundary, int cacheable,
430 bus_addr_t *bpap, bus_space_handle_t *bshp)
431 {
432 panic("ixp425_mem_bs_alloc(): not implemented\n");
433 }
434
435 void
436 ixp425_pci_mem_bs_free(bus_space_tag_t tag, bus_space_handle_t bsh, bus_size_t size)
437 {
438 panic("ixp425_mem_bs_free(): not implemented\n");
439 }
440
441 #ifdef __ARMEB__
442 static u_int8_t
443 _pci_mem_bs_r_1(bus_space_tag_t tag, bus_space_handle_t ioh, bus_size_t off)
444 {
445 return ixp425_pci_mem_bs_r_1(tag, ioh, off);
446 }
447
448 static u_int16_t
449 _pci_mem_bs_r_2(bus_space_tag_t tag, bus_space_handle_t ioh, bus_size_t off)
450 {
451 return (ixp425_pci_mem_bs_r_2(tag, ioh, off));
452 }
453
454 static u_int32_t
455 _pci_mem_bs_r_4(bus_space_tag_t tag, bus_space_handle_t ioh, bus_size_t off)
456 {
457 u_int32_t data;
458
459 data = ixp425_pci_mem_bs_r_4(tag, ioh, off);
460 return (le32toh(data));
461 }
462
463 static void
464 _pci_mem_bs_w_1(bus_space_tag_t tag, bus_space_handle_t ioh, bus_size_t off,
465 u_int8_t val)
466 {
467 ixp425_pci_mem_bs_w_1(tag, ioh, off, val);
468 }
469
470 static void
471 _pci_mem_bs_w_2(bus_space_tag_t tag, bus_space_handle_t ioh, bus_size_t off,
472 u_int16_t val)
473 {
474 ixp425_pci_mem_bs_w_2(tag, ioh, off, val);
475 }
476
477 static void
478 _pci_mem_bs_w_4(bus_space_tag_t tag, bus_space_handle_t ioh, bus_size_t off,
479 u_int32_t val)
480 {
481 ixp425_pci_mem_bs_w_4(tag, ioh, off, htole32(val));
482 }
483 #endif /* __ARMEB__ */
484
485 /* End of ixp425_pci_space.c */
Cache object: 8e017444b44dc5b5e309655e1df49453
|