ixp425_pci_space.c revision 236987
10SN/A/* $NetBSD: ixp425_pci_space.c,v 1.6 2006/04/10 03:36:03 simonb Exp $ */ 22362SN/A 30SN/A/* 40SN/A * Copyright (c) 2003 50SN/A * Ichiro FUKUHARA <ichiro@ichiro.org>. 60SN/A * All rights reserved. 72362SN/A * 80SN/A * Redistribution and use in source and binary forms, with or without 92362SN/A * modification, are permitted provided that the following conditions 100SN/A * are met: 110SN/A * 1. Redistributions of source code must retain the above copyright 120SN/A * notice, this list of conditions and the following disclaimer. 130SN/A * 2. Redistributions in binary form must reproduce the above copyright 140SN/A * notice, this list of conditions and the following disclaimer in the 150SN/A * documentation and/or other materials provided with the distribution. 160SN/A * 3. All advertising materials mentioning features or use of this software 170SN/A * must display the following acknowledgement: 180SN/A * This product includes software developed by Ichiro FUKUHARA. 190SN/A * 4. The name of the company nor the name of the author may be used to 200SN/A * endorse or promote products derived from this software without specific 212362SN/A * prior written permission. 222362SN/A * 232362SN/A * THIS SOFTWARE IS PROVIDED BY ICHIRO FUKUHARA ``AS IS'' AND ANY EXPRESS OR 240SN/A * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 250SN/A * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 260SN/A * IN NO EVENT SHALL ICHIRO FUKUHARA OR THE VOICES IN HIS HEAD BE LIABLE FOR 270SN/A * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 280SN/A * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 290SN/A * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 300SN/A * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 310SN/A * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 320SN/A * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 330SN/A * SUCH DAMAGE. 340SN/A */ 350SN/A 360SN/A#include <sys/cdefs.h> 370SN/A__FBSDID("$FreeBSD: head/sys/arm/xscale/ixp425/ixp425_pci_space.c 236987 2012-06-13 04:38:09Z imp $"); 380SN/A 390SN/A/* 400SN/A * bus_space PCI functions for ixp425 410SN/A */ 420SN/A 430SN/A#include <sys/param.h> 440SN/A#include <sys/systm.h> 450SN/A#include <sys/bus.h> 460SN/A#include <sys/endian.h> 470SN/A 480SN/A#include <machine/pcb.h> 490SN/A 500SN/A#include <vm/vm.h> 510SN/A#include <vm/vm_kern.h> 520SN/A#include <vm/pmap.h> 530SN/A#include <vm/vm_page.h> 540SN/A#include <vm/vm_extern.h> 550SN/A 560SN/A#include <machine/bus.h> 570SN/A 58430SN/A#include <arm/xscale/ixp425/ixp425reg.h> 590SN/A#include <arm/xscale/ixp425/ixp425var.h> 600SN/A 610SN/A/* 620SN/A * Macros to read/write registers 630SN/A*/ 640SN/A#define CSR_READ_4(x) *(volatile uint32_t *) \ 650SN/A (IXP425_PCI_CSR_BASE + (x)) 660SN/A#define CSR_WRITE_4(x, v) *(volatile uint32_t *) \ 670SN/A (IXP425_PCI_CSR_BASE + (x)) = (v) 680SN/A 690SN/A/* Proto types for all the bus_space structure functions */ 700SN/Abs_protos(ixp425_pci); 710SN/Abs_protos(ixp425_pci_io); 720SN/Abs_protos(ixp425_pci_mem); 730SN/A 740SN/A/* special I/O functions */ 750SN/Astatic u_int8_t _pci_io_bs_r_1(void *, bus_space_handle_t, bus_size_t); 760SN/Astatic u_int16_t _pci_io_bs_r_2(void *, bus_space_handle_t, bus_size_t); 770SN/Astatic u_int32_t _pci_io_bs_r_4(void *, bus_space_handle_t, bus_size_t); 780SN/A 790SN/Astatic void _pci_io_bs_w_1(void *, bus_space_handle_t, bus_size_t, u_int8_t); 800SN/Astatic void _pci_io_bs_w_2(void *, bus_space_handle_t, bus_size_t, u_int16_t); 810SN/Astatic void _pci_io_bs_w_4(void *, bus_space_handle_t, bus_size_t, u_int32_t); 820SN/A 830SN/A#ifdef __ARMEB__ 840SN/Astatic u_int8_t _pci_io_bs_r_1_s(void *, bus_space_handle_t, bus_size_t); 850SN/Astatic u_int16_t _pci_io_bs_r_2_s(void *, bus_space_handle_t, bus_size_t); 860SN/Astatic u_int32_t _pci_io_bs_r_4_s(void *, bus_space_handle_t, bus_size_t); 870SN/A 880SN/Astatic void _pci_io_bs_w_1_s(void *, bus_space_handle_t, bus_size_t, u_int8_t); 890SN/Astatic void _pci_io_bs_w_2_s(void *, bus_space_handle_t, bus_size_t, u_int16_t); 900SN/Astatic void _pci_io_bs_w_4_s(void *, bus_space_handle_t, bus_size_t, u_int32_t); 910SN/A 920SN/Astatic u_int8_t _pci_mem_bs_r_1(void *, bus_space_handle_t, bus_size_t); 930SN/Astatic u_int16_t _pci_mem_bs_r_2(void *, bus_space_handle_t, bus_size_t); 940SN/Astatic u_int32_t _pci_mem_bs_r_4(void *, bus_space_handle_t, bus_size_t); 950SN/A 960SN/Astatic void _pci_mem_bs_w_1(void *, bus_space_handle_t, bus_size_t, u_int8_t); 9713629Savstepanstatic void _pci_mem_bs_w_2(void *, bus_space_handle_t, bus_size_t, u_int16_t); 980SN/Astatic void _pci_mem_bs_w_4(void *, bus_space_handle_t, bus_size_t, u_int32_t); 990SN/A#endif 1000SN/A 1010SN/Astruct bus_space ixp425_pci_io_bs_tag_template = { 1020SN/A /* mapping/unmapping */ 1030SN/A .bs_map = ixp425_pci_io_bs_map, 1040SN/A .bs_unmap = ixp425_pci_io_bs_unmap, 1050SN/A .bs_subregion = ixp425_pci_bs_subregion, 1060SN/A 1070SN/A .bs_alloc = ixp425_pci_io_bs_alloc, 1080SN/A .bs_free = ixp425_pci_io_bs_free, 10913220Salexsch 1100SN/A /* barrier */ 1110SN/A .bs_barrier = ixp425_pci_bs_barrier, 1120SN/A 1130SN/A /* 1140SN/A * IXP425 processor does not have PCI I/O windows 1150SN/A */ 1160SN/A /* read (single) */ 1170SN/A .bs_r_1 = _pci_io_bs_r_1, 1180SN/A .bs_r_2 = _pci_io_bs_r_2, 1190SN/A .bs_r_4 = _pci_io_bs_r_4, 1200SN/A 1210SN/A /* write (single) */ 1220SN/A .bs_w_1 = _pci_io_bs_w_1, 1230SN/A .bs_w_2 = _pci_io_bs_w_2, 1240SN/A .bs_w_4 = _pci_io_bs_w_4, 1250SN/A 1260SN/A#ifdef __ARMEB__ 1270SN/A .bs_r_1_s = _pci_io_bs_r_1_s, 1280SN/A .bs_r_2_s = _pci_io_bs_r_2_s, 1290SN/A .bs_r_4_s = _pci_io_bs_r_4_s, 1300SN/A 1310SN/A .bs_w_1_s = _pci_io_bs_w_1_s, 1320SN/A .bs_w_2_s = _pci_io_bs_w_2_s, 1330SN/A .bs_w_4_s = _pci_io_bs_w_4_s, 1340SN/A#else 1350SN/A .bs_r_1_s = _pci_io_bs_r_1, 1360SN/A .bs_r_2_s = _pci_io_bs_r_2, 1370SN/A .bs_r_4_s = _pci_io_bs_r_4, 1380SN/A 1390SN/A .bs_w_1_s = _pci_io_bs_w_1, 1400SN/A .bs_w_2_s = _pci_io_bs_w_2, 1410SN/A .bs_w_4_s = _pci_io_bs_w_4, 1420SN/A#endif 1430SN/A}; 1440SN/A 1450SN/Avoid 1460SN/Aixp425_io_bs_init(bus_space_tag_t bs, void *cookie) 1470SN/A{ 1480SN/A *bs = ixp425_pci_io_bs_tag_template; 1490SN/A bs->bs_cookie = cookie; 1500SN/A} 1510SN/A 1520SN/Astruct bus_space ixp425_pci_mem_bs_tag_template = { 1530SN/A /* mapping/unmapping */ 1540SN/A .bs_map = ixp425_pci_mem_bs_map, 1550SN/A .bs_unmap = ixp425_pci_mem_bs_unmap, 1560SN/A .bs_subregion = ixp425_pci_bs_subregion, 1570SN/A 1580SN/A .bs_alloc = ixp425_pci_mem_bs_alloc, 1590SN/A .bs_free = ixp425_pci_mem_bs_free, 1600SN/A 1610SN/A /* barrier */ 1620SN/A .bs_barrier = ixp425_pci_bs_barrier, 1630SN/A 1640SN/A#ifdef __ARMEB__ 1650SN/A /* read (single) */ 1660SN/A .bs_r_1_s = _pci_mem_bs_r_1, 1670SN/A .bs_r_2_s = _pci_mem_bs_r_2, 1680SN/A .bs_r_4_s = _pci_mem_bs_r_4, 169430SN/A 1700SN/A .bs_r_1 = ixp425_pci_mem_bs_r_1, 1710SN/A .bs_r_2 = ixp425_pci_mem_bs_r_2, 1720SN/A .bs_r_4 = ixp425_pci_mem_bs_r_4, 1730SN/A 1740SN/A /* write (single) */ 1750SN/A .bs_w_1_s = _pci_mem_bs_w_1, 1760SN/A .bs_w_2_s = _pci_mem_bs_w_2, 1770SN/A .bs_w_4_s = _pci_mem_bs_w_4, 1780SN/A 1790SN/A .bs_w_1 = ixp425_pci_mem_bs_w_1, 1800SN/A .bs_w_2 = ixp425_pci_mem_bs_w_2, 1810SN/A .bs_w_4 = ixp425_pci_mem_bs_w_4, 1820SN/A#else 1830SN/A /* read (single) */ 1840SN/A .bs_r_1 = ixp425_pci_mem_bs_r_1, 18513220Salexsch .bs_r_2 = ixp425_pci_mem_bs_r_2, 18613220Salexsch .bs_r_4 = ixp425_pci_mem_bs_r_4, 18713220Salexsch .bs_r_1_s = ixp425_pci_mem_bs_r_1, 1880SN/A .bs_r_2_s = ixp425_pci_mem_bs_r_2, 1890SN/A .bs_r_4_s = ixp425_pci_mem_bs_r_4, 1900SN/A 1910SN/A /* write (single) */ 1920SN/A .bs_w_1 = ixp425_pci_mem_bs_w_1, 1930SN/A .bs_w_2 = ixp425_pci_mem_bs_w_2, 1940SN/A .bs_w_4 = ixp425_pci_mem_bs_w_4, 1950SN/A .bs_w_1_s = ixp425_pci_mem_bs_w_1, 1960SN/A .bs_w_2_s = ixp425_pci_mem_bs_w_2, 1970SN/A .bs_w_4_s = ixp425_pci_mem_bs_w_4, 1980SN/A#endif 1990SN/A}; 2000SN/A 2010SN/Avoid 2020SN/Aixp425_mem_bs_init(bus_space_tag_t bs, void *cookie) 2030SN/A{ 2040SN/A *bs = ixp425_pci_mem_bs_tag_template; 2050SN/A bs->bs_cookie = cookie; 2060SN/A} 2070SN/A 2080SN/A/* common routine */ 2090SN/Aint 2100SN/Aixp425_pci_bs_subregion(void *t, bus_space_handle_t bsh, bus_size_t offset, 2110SN/A bus_size_t size, bus_space_handle_t *nbshp) 2120SN/A{ 2130SN/A *nbshp = bsh + offset; 2140SN/A return (0); 2150SN/A} 2160SN/A 2170SN/Avoid 2180SN/Aixp425_pci_bs_barrier(void *t, bus_space_handle_t bsh, bus_size_t offset, 2190SN/A bus_size_t len, int flags) 2200SN/A{ 2210SN/A /* NULL */ 2220SN/A} 2230SN/A 2240SN/A/* io bs */ 2250SN/Aint 2260SN/Aixp425_pci_io_bs_map(void *t, bus_addr_t bpa, bus_size_t size, 2270SN/A int cacheable, bus_space_handle_t *bshp) 2280SN/A{ 2290SN/A *bshp = bpa; 2300SN/A return (0); 2310SN/A} 2320SN/A 2330SN/Avoid 2340SN/Aixp425_pci_io_bs_unmap(void *t, bus_space_handle_t h, bus_size_t size) 2350SN/A{ 2360SN/A /* Nothing to do. */ 2370SN/A} 2380SN/A 2390SN/Aint 2400SN/Aixp425_pci_io_bs_alloc(void *t, bus_addr_t rstart, bus_addr_t rend, 2410SN/A bus_size_t size, bus_size_t alignment, bus_size_t boundary, int cacheable, 2420SN/A bus_addr_t *bpap, bus_space_handle_t *bshp) 2430SN/A{ 2440SN/A panic("ixp425_pci_io_bs_alloc(): not implemented\n"); 2450SN/A} 2460SN/A 2470SN/Avoid 248430SN/Aixp425_pci_io_bs_free(void *t, bus_space_handle_t bsh, bus_size_t size) 2490SN/A{ 2500SN/A panic("ixp425_pci_io_bs_free(): not implemented\n"); 2510SN/A} 252430SN/A 2530SN/A/* special I/O functions */ 2540SN/Astatic __inline u_int32_t 2550SN/A_bs_r(void *v, bus_space_handle_t ioh, bus_size_t off, u_int32_t be) 2560SN/A{ 2570SN/A u_int32_t data; 2580SN/A 2590SN/A CSR_WRITE_4(PCI_NP_AD, (ioh + off) & ~3); 2600SN/A CSR_WRITE_4(PCI_NP_CBE, be | COMMAND_NP_IO_READ); 2610SN/A data = CSR_READ_4(PCI_NP_RDATA); 2620SN/A if (CSR_READ_4(PCI_ISR) & ISR_PFE) 2630SN/A CSR_WRITE_4(PCI_ISR, ISR_PFE); 2640SN/A 2650SN/A return data; 2660SN/A} 2670SN/A 2680SN/Astatic u_int8_t 2690SN/A_pci_io_bs_r_1(void *v, bus_space_handle_t ioh, bus_size_t off) 2700SN/A{ 2710SN/A u_int32_t data, n, be; 2720SN/A 2730SN/A n = (ioh + off) % 4; 2740SN/A be = (0xf & ~(1U << n)) << NP_CBE_SHIFT; 2750SN/A data = _bs_r(v, ioh, off, be); 2760SN/A 2770SN/A return data >> (8 * n); 2780SN/A} 279430SN/A 280430SN/Astatic u_int16_t 281430SN/A_pci_io_bs_r_2(void *v, bus_space_handle_t ioh, bus_size_t off) 2820SN/A{ 2830SN/A u_int32_t data, n, be; 2840SN/A 285430SN/A n = (ioh + off) % 4; 286430SN/A be = (0xf & ~((1U << n) | (1U << (n + 1)))) << NP_CBE_SHIFT; 287430SN/A data = _bs_r(v, ioh, off, be); 288430SN/A 289430SN/A return data >> (8 * n); 2900SN/A} 2910SN/A 292430SN/Astatic u_int32_t 293430SN/A_pci_io_bs_r_4(void *v, bus_space_handle_t ioh, bus_size_t off) 294430SN/A{ 295430SN/A u_int32_t data; 2960SN/A 2970SN/A data = _bs_r(v, ioh, off, 0); 2980SN/A return data; 2990SN/A} 300430SN/A 301430SN/A#ifdef __ARMEB__ 302430SN/Astatic u_int8_t 303430SN/A_pci_io_bs_r_1_s(void *v, bus_space_handle_t ioh, bus_size_t off) 304430SN/A{ 305430SN/A u_int32_t data, n, be; 3060SN/A 3070SN/A n = (ioh + off) % 4; 3080SN/A be = (0xf & ~(1U << n)) << NP_CBE_SHIFT; 309430SN/A data = _bs_r(v, ioh, off, be); 3100SN/A 3110SN/A return data >> (8 * n); 312430SN/A} 313430SN/A 314430SN/Astatic u_int16_t 315430SN/A_pci_io_bs_r_2_s(void *v, bus_space_handle_t ioh, bus_size_t off) 316430SN/A{ 317430SN/A u_int32_t data, n, be; 318430SN/A 319430SN/A n = (ioh + off) % 4; 320430SN/A be = (0xf & ~((1U << n) | (1U << (n + 1)))) << NP_CBE_SHIFT; 321430SN/A data = _bs_r(v, ioh, off, be); 322430SN/A 323430SN/A return data >> (8 * n); 324430SN/A} 325430SN/A 326430SN/Astatic u_int32_t 327430SN/A_pci_io_bs_r_4_s(void *v, bus_space_handle_t ioh, bus_size_t off) 328430SN/A{ 329430SN/A u_int32_t data; 330430SN/A 331430SN/A data = _bs_r(v, ioh, off, 0); 332430SN/A return le32toh(data); 3330SN/A} 334430SN/A#endif /* __ARMEB__ */ 3350SN/A 3361045SN/Astatic __inline void 3371045SN/A_bs_w(void *v, bus_space_handle_t ioh, bus_size_t off, 3381045SN/A u_int32_t be, u_int32_t data) 3391045SN/A{ 3401045SN/A CSR_WRITE_4(PCI_NP_AD, (ioh + off) & ~3); 3411045SN/A CSR_WRITE_4(PCI_NP_CBE, be | COMMAND_NP_IO_WRITE); 3420SN/A 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 347static void 348_pci_io_bs_w_1(void *v, 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(v, ioh, off, be, data); 357} 358 359static void 360_pci_io_bs_w_2(void *v, 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(v, ioh, off, be, data); 369} 370 371static void 372_pci_io_bs_w_4(void *v, bus_space_handle_t ioh, bus_size_t off, 373 u_int32_t val) 374{ 375 _bs_w(v, ioh, off, 0, val); 376} 377 378#ifdef __ARMEB__ 379static void 380_pci_io_bs_w_1_s(void *v, 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(v, ioh, off, be, data); 389} 390 391static void 392_pci_io_bs_w_2_s(void *v, 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(v, ioh, off, be, data); 401} 402 403static void 404_pci_io_bs_w_4_s(void *v, bus_space_handle_t ioh, bus_size_t off, 405 u_int32_t val) 406{ 407 _bs_w(v, ioh, off, 0, htole32(val)); 408} 409#endif /* __ARMEB__ */ 410 411/* mem bs */ 412int 413ixp425_pci_mem_bs_map(void *t, bus_addr_t bpa, bus_size_t size, 414 int cacheable, bus_space_handle_t *bshp) 415{ 416 vm_paddr_t pa, endpa; 417 418 pa = trunc_page(bpa); 419 endpa = round_page(bpa + size); 420 421 *bshp = (vm_offset_t)pmap_mapdev(pa, endpa - pa); 422 423 return (0); 424} 425 426void 427ixp425_pci_mem_bs_unmap(void *t, bus_space_handle_t h, bus_size_t size) 428{ 429 vm_offset_t va, endva; 430 431 va = trunc_page((vm_offset_t)t); 432 endva = va + round_page(size); 433 434 /* Free the kernel virtual mapping. */ 435 kmem_free(kernel_map, va, endva - va); 436} 437 438int 439ixp425_pci_mem_bs_alloc(void *t, bus_addr_t rstart, bus_addr_t rend, 440 bus_size_t size, bus_size_t alignment, bus_size_t boundary, int cacheable, 441 bus_addr_t *bpap, bus_space_handle_t *bshp) 442{ 443 panic("ixp425_mem_bs_alloc(): not implemented\n"); 444} 445 446void 447ixp425_pci_mem_bs_free(void *t, bus_space_handle_t bsh, bus_size_t size) 448{ 449 panic("ixp425_mem_bs_free(): not implemented\n"); 450} 451 452#ifdef __ARMEB__ 453static u_int8_t 454_pci_mem_bs_r_1(void *v, bus_space_handle_t ioh, bus_size_t off) 455{ 456 return ixp425_pci_mem_bs_r_1(v, ioh, off); 457} 458 459static u_int16_t 460_pci_mem_bs_r_2(void *v, bus_space_handle_t ioh, bus_size_t off) 461{ 462 return (ixp425_pci_mem_bs_r_2(v, ioh, off)); 463} 464 465static u_int32_t 466_pci_mem_bs_r_4(void *v, bus_space_handle_t ioh, bus_size_t off) 467{ 468 u_int32_t data; 469 470 data = ixp425_pci_mem_bs_r_4(v, ioh, off); 471 return (le32toh(data)); 472} 473 474static void 475_pci_mem_bs_w_1(void *v, bus_space_handle_t ioh, bus_size_t off, 476 u_int8_t val) 477{ 478 ixp425_pci_mem_bs_w_1(v, ioh, off, val); 479} 480 481static void 482_pci_mem_bs_w_2(void *v, bus_space_handle_t ioh, bus_size_t off, 483 u_int16_t val) 484{ 485 ixp425_pci_mem_bs_w_2(v, ioh, off, val); 486} 487 488static void 489_pci_mem_bs_w_4(void *v, bus_space_handle_t ioh, bus_size_t off, 490 u_int32_t val) 491{ 492 ixp425_pci_mem_bs_w_4(v, ioh, off, htole32(val)); 493} 494#endif /* __ARMEB__ */ 495 496/* End of ixp425_pci_space.c */ 497