1 /* $NetBSD: ixp425_pci_space.c,v 1.4 2005/11/24 13:08:32 yamt 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 __KERNEL_RCSID(0, "$NetBSD: ixp425_pci_space.c,v 1.4 2005/11/24 13:08:32 yamt Exp $"); 38 39 /* 40 * bus_space PCI functions for ixp425 41 */ 42 43 #include <sys/param.h> 44 #include <sys/systm.h> 45 #include <sys/queue.h> 46 47 #include <uvm/uvm.h> 48 49 #include <machine/bus.h> 50 51 #include <arm/xscale/ixp425reg.h> 52 #include <arm/xscale/ixp425var.h> 53 54 /* 55 * Macros to read/write registers 56 */ 57 #define CSR_READ_4(x) *(__volatile uint32_t *) \ 58 (IXP425_PCI_CSR_BASE + (x)) 59 #define CSR_WRITE_4(x, v) *(__volatile uint32_t *) \ 60 (IXP425_PCI_CSR_BASE + (x)) = (v) 61 62 /* Proto types for all the bus_space structure functions */ 63 bs_protos(ixp425_pci); 64 bs_protos(ixp425_pci_io); 65 bs_protos(ixp425_pci_mem); 66 bs_protos(bs_notimpl); 67 68 /* special I/O functions */ 69 #if 1 /* XXX */ 70 inline u_int8_t _pci_io_bs_r_1(void *, bus_space_handle_t, bus_size_t); 71 inline u_int16_t _pci_io_bs_r_2(void *, bus_space_handle_t, bus_size_t); 72 inline u_int32_t _pci_io_bs_r_4(void *, bus_space_handle_t, bus_size_t); 73 74 inline void _pci_io_bs_w_1(void *, bus_space_handle_t, bus_size_t, u_int8_t); 75 inline void _pci_io_bs_w_2(void *, bus_space_handle_t, bus_size_t, u_int16_t); 76 inline void _pci_io_bs_w_4(void *, bus_space_handle_t, bus_size_t, u_int32_t); 77 #endif 78 79 struct bus_space ixp425_pci_bs_tag_template = { 80 /* cookie */ 81 (void *) 0, 82 83 /* mapping/unmapping */ 84 NULL, 85 NULL, 86 ixp425_pci_bs_subregion, 87 88 /* allocation/deallocation */ 89 NULL, 90 NULL, 91 92 /* get kernel virtual address */ 93 NULL, 94 95 /* mmap bus space for userland */ 96 ixp425_pci_bs_mmap, 97 98 /* barrier */ 99 ixp425_pci_bs_barrier, 100 101 /* read (single) */ 102 bs_notimpl_bs_r_1, 103 bs_notimpl_bs_r_2, 104 bs_notimpl_bs_r_4, 105 bs_notimpl_bs_r_8, 106 107 /* read multiple */ 108 bs_notimpl_bs_rm_1, 109 bs_notimpl_bs_rm_2, 110 bs_notimpl_bs_rm_4, 111 bs_notimpl_bs_rm_8, 112 113 /* read region */ 114 bs_notimpl_bs_rr_1, 115 bs_notimpl_bs_rr_2, 116 bs_notimpl_bs_rr_4, 117 bs_notimpl_bs_rr_8, 118 119 /* write (single) */ 120 bs_notimpl_bs_w_1, 121 bs_notimpl_bs_w_2, 122 bs_notimpl_bs_w_4, 123 bs_notimpl_bs_w_8, 124 125 /* write multiple */ 126 bs_notimpl_bs_wm_1, 127 bs_notimpl_bs_wm_2, 128 bs_notimpl_bs_wm_4, 129 bs_notimpl_bs_wm_8, 130 131 /* write region */ 132 bs_notimpl_bs_wr_1, 133 bs_notimpl_bs_wr_2, 134 bs_notimpl_bs_wr_4, 135 bs_notimpl_bs_wr_8, 136 137 /* set multiple */ 138 bs_notimpl_bs_sm_1, 139 bs_notimpl_bs_sm_2, 140 bs_notimpl_bs_sm_4, 141 bs_notimpl_bs_sm_8, 142 143 /* set region */ 144 bs_notimpl_bs_sr_1, 145 bs_notimpl_bs_sr_2, 146 bs_notimpl_bs_sr_4, 147 bs_notimpl_bs_sr_8, 148 149 /* copy */ 150 bs_notimpl_bs_c_1, 151 bs_notimpl_bs_c_2, 152 bs_notimpl_bs_c_4, 153 bs_notimpl_bs_c_8, 154 }; 155 156 void 157 ixp425_io_bs_init(bus_space_tag_t bs, void *cookie) 158 { 159 *bs = ixp425_pci_bs_tag_template; 160 bs->bs_cookie = cookie; 161 162 bs->bs_map = ixp425_pci_io_bs_map; 163 bs->bs_unmap = ixp425_pci_io_bs_unmap; 164 bs->bs_alloc = ixp425_pci_io_bs_alloc; 165 bs->bs_free = ixp425_pci_io_bs_free; 166 bs->bs_vaddr = ixp425_pci_io_bs_vaddr; 167 168 /* 169 * IXP425 processor does not have PCI I/O windows 170 */ 171 /* read (single) */ 172 bs->bs_r_1 = _pci_io_bs_r_1; 173 bs->bs_r_2 = _pci_io_bs_r_2; 174 bs->bs_r_4 = _pci_io_bs_r_4; 175 176 /* write (single) */ 177 bs->bs_w_1 = _pci_io_bs_w_1; 178 bs->bs_w_2 = _pci_io_bs_w_2; 179 bs->bs_w_4 = _pci_io_bs_w_4; 180 } 181 182 void 183 ixp425_mem_bs_init(bus_space_tag_t bs, void *cookie) 184 { 185 *bs = ixp425_pci_bs_tag_template; 186 bs->bs_cookie = cookie; 187 188 bs->bs_map = ixp425_pci_mem_bs_map; 189 bs->bs_unmap = ixp425_pci_mem_bs_unmap; 190 bs->bs_alloc = ixp425_pci_mem_bs_alloc; 191 bs->bs_free = ixp425_pci_mem_bs_free; 192 bs->bs_vaddr = ixp425_pci_mem_bs_vaddr; 193 194 /* read (single) */ 195 bs->bs_r_1 = ixp425_pci_mem_bs_r_1; 196 bs->bs_r_2 = ixp425_pci_mem_bs_r_2; 197 bs->bs_r_4 = ixp425_pci_mem_bs_r_4; 198 199 /* write (single) */ 200 bs->bs_w_1 = ixp425_pci_mem_bs_w_1; 201 bs->bs_w_2 = ixp425_pci_mem_bs_w_2; 202 bs->bs_w_4 = ixp425_pci_mem_bs_w_4; 203 } 204 205 /* common routine */ 206 int 207 ixp425_pci_bs_subregion(void *t, bus_space_handle_t bsh, bus_size_t offset, 208 bus_size_t size, bus_space_handle_t *nbshp) 209 { 210 *nbshp = bsh + offset; 211 return (0); 212 } 213 214 void 215 ixp425_pci_bs_barrier(void *t, bus_space_handle_t bsh, bus_size_t offset, 216 bus_size_t len, int flags) 217 { 218 /* NULL */ 219 } 220 221 paddr_t 222 ixp425_pci_bs_mmap(void *t, bus_addr_t addr, off_t off, int prot, int flags) 223 { 224 /* Not supported. */ 225 return (-1); 226 } 227 228 /* io bs */ 229 int 230 ixp425_pci_io_bs_map(void *t, bus_addr_t bpa, bus_size_t size, 231 int cacheable, bus_space_handle_t *bshp) 232 { 233 *bshp = bpa; 234 return (0); 235 } 236 237 void 238 ixp425_pci_io_bs_unmap(void *t, bus_space_handle_t bsh, bus_size_t size) 239 { 240 /* Nothing to do. */ 241 } 242 243 int 244 ixp425_pci_io_bs_alloc(void *t, bus_addr_t rstart, bus_addr_t rend, 245 bus_size_t size, bus_size_t alignment, bus_size_t boundary, int cacheable, 246 bus_addr_t *bpap, bus_space_handle_t *bshp) 247 { 248 panic("ixp425_pci_io_bs_alloc(): not implemented\n"); 249 } 250 251 void 252 ixp425_pci_io_bs_free(void *t, bus_space_handle_t bsh, bus_size_t size) 253 { 254 panic("ixp425_pci_io_bs_free(): not implemented\n"); 255 } 256 257 void * 258 ixp425_pci_io_bs_vaddr(void *t, bus_space_handle_t bsh) 259 { 260 /* Not supported. */ 261 return (NULL); 262 } 263 264 /* special I/O functions */ 265 #if 1 /* _pci_io_bs_{rw}_{124} */ 266 inline u_int8_t 267 _pci_io_bs_r_1(void *v, bus_space_handle_t ioh, bus_size_t off) 268 { 269 u_int32_t data, n, be; 270 int s; 271 272 n = (ioh + off) % 4; 273 be = (0xf & ~(1U << n)) << NP_CBE_SHIFT; 274 275 PCI_CONF_LOCK(s); 276 CSR_WRITE_4(PCI_NP_AD, (ioh + off) & ~3); 277 CSR_WRITE_4(PCI_NP_CBE, be | COMMAND_NP_IO_READ); 278 data = CSR_READ_4(PCI_NP_RDATA); 279 if (CSR_READ_4(PCI_ISR) & ISR_PFE) 280 CSR_WRITE_4(PCI_ISR, ISR_PFE); 281 PCI_CONF_UNLOCK(s); 282 283 return data >> (8 * n); 284 } 285 286 inline u_int16_t 287 _pci_io_bs_r_2(void *v, bus_space_handle_t ioh, bus_size_t off) 288 { 289 u_int32_t data, n, be; 290 int s; 291 292 n = (ioh + off) % 4; 293 be = (0xf & ~((1U << n) | (1U << (n + 1)))) << NP_CBE_SHIFT; 294 295 PCI_CONF_LOCK(s); 296 CSR_WRITE_4(PCI_NP_AD, (ioh + off) & ~3); 297 CSR_WRITE_4(PCI_NP_CBE, be | COMMAND_NP_IO_READ); 298 data = CSR_READ_4(PCI_NP_RDATA); 299 if (CSR_READ_4(PCI_ISR) & ISR_PFE) 300 CSR_WRITE_4(PCI_ISR, ISR_PFE); 301 PCI_CONF_UNLOCK(s); 302 303 return data >> (8 * n); 304 } 305 306 inline u_int32_t 307 _pci_io_bs_r_4(void *v, bus_space_handle_t ioh, bus_size_t off) 308 { 309 u_int32_t data; 310 int s; 311 312 PCI_CONF_LOCK(s); 313 CSR_WRITE_4(PCI_NP_AD, (ioh + off) & ~3); 314 CSR_WRITE_4(PCI_NP_CBE, COMMAND_NP_IO_READ); 315 data = CSR_READ_4(PCI_NP_RDATA); 316 if (CSR_READ_4(PCI_ISR) & ISR_PFE) 317 CSR_WRITE_4(PCI_ISR, ISR_PFE); 318 PCI_CONF_UNLOCK(s); 319 320 return data; 321 } 322 323 inline void 324 _pci_io_bs_w_1(void *v, bus_space_handle_t ioh, bus_size_t off, 325 u_int8_t val) 326 { 327 u_int32_t data, n, be; 328 int s; 329 330 n = (ioh + off) % 4; 331 be = (0xf & ~(1U << n)) << NP_CBE_SHIFT; 332 data = val << (8 * n); 333 334 PCI_CONF_LOCK(s); 335 CSR_WRITE_4(PCI_NP_AD, (ioh + off) & ~3); 336 CSR_WRITE_4(PCI_NP_CBE, be | COMMAND_NP_IO_WRITE); 337 CSR_WRITE_4(PCI_NP_WDATA, data); 338 if (CSR_READ_4(PCI_ISR) & ISR_PFE) 339 CSR_WRITE_4(PCI_ISR, ISR_PFE); 340 PCI_CONF_UNLOCK(s); 341 } 342 343 inline void 344 _pci_io_bs_w_2(void *v, bus_space_handle_t ioh, bus_size_t off, 345 u_int16_t val) 346 { 347 u_int32_t data, n, be; 348 int s; 349 350 n = (ioh + off) % 4; 351 be = (0xf & ~((1U << n) | (1U << (n + 1)))) << NP_CBE_SHIFT; 352 data = val << (8 * n); 353 354 PCI_CONF_LOCK(s); 355 CSR_WRITE_4(PCI_NP_AD, (ioh + off) & ~3); 356 CSR_WRITE_4(PCI_NP_CBE, be | COMMAND_NP_IO_WRITE); 357 CSR_WRITE_4(PCI_NP_WDATA, data); 358 if (CSR_READ_4(PCI_ISR) & ISR_PFE) 359 CSR_WRITE_4(PCI_ISR, ISR_PFE); 360 PCI_CONF_UNLOCK(s); 361 } 362 363 inline void 364 _pci_io_bs_w_4(void *v, bus_space_handle_t ioh, bus_size_t off, 365 u_int32_t val) 366 { 367 int s; 368 369 PCI_CONF_LOCK(s); 370 CSR_WRITE_4(PCI_NP_AD, (ioh + off) & ~3); 371 CSR_WRITE_4(PCI_NP_CBE, COMMAND_NP_IO_WRITE); 372 CSR_WRITE_4(PCI_NP_WDATA, val); 373 if (CSR_READ_4(PCI_ISR) & ISR_PFE) 374 CSR_WRITE_4(PCI_ISR, ISR_PFE); 375 PCI_CONF_UNLOCK(s); 376 } 377 #endif /* _pci_io_bs_{rw}_{124} */ 378 379 /* mem bs */ 380 int 381 ixp425_pci_mem_bs_map(void *t, bus_addr_t bpa, bus_size_t size, 382 int cacheable, bus_space_handle_t *bshp) 383 { 384 const struct pmap_devmap *pd; 385 386 paddr_t startpa; 387 paddr_t endpa; 388 paddr_t pa; 389 paddr_t offset; 390 vaddr_t va; 391 pt_entry_t *pte; 392 393 if ((pd = pmap_devmap_find_pa(bpa, size)) != NULL) { 394 /* Device was statically mapped. */ 395 *bshp = pd->pd_va + (bpa - pd->pd_pa); 396 return 0; 397 } 398 399 endpa = round_page(bpa + size); 400 offset = bpa & PAGE_MASK; 401 startpa = trunc_page(bpa); 402 403 /* Get some VM. */ 404 va = uvm_km_alloc(kernel_map, endpa - startpa, 0, 405 UVM_KMF_VAONLY | UVM_KMF_NOWAIT); 406 if (va == 0) 407 return ENOMEM; 408 409 /* Store the bus space handle */ 410 *bshp = va + offset; 411 412 /* Now map the pages */ 413 for (pa = startpa; pa < endpa; pa += PAGE_SIZE, va += PAGE_SIZE) { 414 pmap_kenter_pa(va, pa, VM_PROT_READ | VM_PROT_WRITE); 415 pte = vtopte(va); 416 *pte &= ~L2_S_CACHE_MASK; 417 PTE_SYNC(pte); 418 } 419 pmap_update(pmap_kernel()); 420 421 return(0); 422 } 423 424 void 425 ixp425_pci_mem_bs_unmap(void *t, bus_space_handle_t bsh, bus_size_t size) 426 { 427 vaddr_t va; 428 vaddr_t endva; 429 430 if (pmap_devmap_find_va(bsh, size) != NULL) { 431 /* Device was statically mapped; nothing to do. */ 432 return; 433 } 434 435 endva = round_page(bsh + size); 436 va = trunc_page(bsh); 437 438 pmap_kremove(va, endva - va); 439 uvm_km_free(kernel_map, va, endva - va, UVM_KMF_VAONLY); 440 } 441 442 int 443 ixp425_pci_mem_bs_alloc(void *t, bus_addr_t rstart, bus_addr_t rend, 444 bus_size_t size, bus_size_t alignment, bus_size_t boundary, int cacheable, 445 bus_addr_t *bpap, bus_space_handle_t *bshp) 446 { 447 panic("ixp425_mem_bs_alloc(): not implemented\n"); 448 } 449 450 void 451 ixp425_pci_mem_bs_free(void *t, bus_space_handle_t bsh, bus_size_t size) 452 { 453 panic("ixp425_mem_bs_free(): not implemented\n"); 454 } 455 456 void * 457 ixp425_pci_mem_bs_vaddr(void *t, bus_space_handle_t bsh) 458 { 459 return ((void *)bsh); 460 } 461 /* End of ixp425_pci_space.c */ 462