1*61e15267Ssyuu /* $OpenBSD: octeon_iobus.c,v 1.1 2011/05/08 13:24:55 syuu Exp $ */ 2*61e15267Ssyuu 3*61e15267Ssyuu /* 4*61e15267Ssyuu * Copyright (c) 2000-2004 Opsycon AB (www.opsycon.se) 5*61e15267Ssyuu * 6*61e15267Ssyuu * Redistribution and use in source and binary forms, with or without 7*61e15267Ssyuu * modification, are permitted provided that the following conditions 8*61e15267Ssyuu * are met: 9*61e15267Ssyuu * 1. Redistributions of source code must retain the above copyright 10*61e15267Ssyuu * notice, this list of conditions and the following disclaimer. 11*61e15267Ssyuu * 2. Redistributions in binary form must reproduce the above copyright 12*61e15267Ssyuu * notice, this list of conditions and the following disclaimer in the 13*61e15267Ssyuu * documentation and/or other materials provided with the distribution. 14*61e15267Ssyuu * 15*61e15267Ssyuu * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 16*61e15267Ssyuu * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17*61e15267Ssyuu * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18*61e15267Ssyuu * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 19*61e15267Ssyuu * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20*61e15267Ssyuu * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21*61e15267Ssyuu * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22*61e15267Ssyuu * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23*61e15267Ssyuu * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24*61e15267Ssyuu * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25*61e15267Ssyuu * SUCH DAMAGE. 26*61e15267Ssyuu * 27*61e15267Ssyuu */ 28*61e15267Ssyuu 29*61e15267Ssyuu /* 30*61e15267Ssyuu * This is a iobus driver. 31*61e15267Ssyuu * It handles configuration of all devices on the processor bus except UART. 32*61e15267Ssyuu */ 33*61e15267Ssyuu 34*61e15267Ssyuu #include <sys/param.h> 35*61e15267Ssyuu #include <sys/systm.h> 36*61e15267Ssyuu #include <sys/kernel.h> 37*61e15267Ssyuu #include <sys/conf.h> 38*61e15267Ssyuu #include <sys/malloc.h> 39*61e15267Ssyuu #include <sys/device.h> 40*61e15267Ssyuu #include <sys/proc.h> 41*61e15267Ssyuu 42*61e15267Ssyuu #include <mips64/archtype.h> 43*61e15267Ssyuu 44*61e15267Ssyuu #include <machine/autoconf.h> 45*61e15267Ssyuu #include <machine/atomic.h> 46*61e15267Ssyuu #include <machine/intr.h> 47*61e15267Ssyuu 48*61e15267Ssyuu #include <octeon/dev/octeonreg.h> 49*61e15267Ssyuu #include <octeon/dev/iobusvar.h> 50*61e15267Ssyuu 51*61e15267Ssyuu int iobusmatch(struct device *, void *, void *); 52*61e15267Ssyuu void iobusattach(struct device *, struct device *, void *); 53*61e15267Ssyuu int iobusprint(void *, const char *); 54*61e15267Ssyuu int iobussubmatch(struct device *, void *, void *); 55*61e15267Ssyuu 56*61e15267Ssyuu u_int8_t iobus_read_1(bus_space_tag_t, bus_space_handle_t, bus_size_t); 57*61e15267Ssyuu u_int16_t iobus_read_2(bus_space_tag_t, bus_space_handle_t, bus_size_t); 58*61e15267Ssyuu u_int32_t iobus_read_4(bus_space_tag_t, bus_space_handle_t, bus_size_t); 59*61e15267Ssyuu u_int64_t iobus_read_8(bus_space_tag_t, bus_space_handle_t, bus_size_t); 60*61e15267Ssyuu 61*61e15267Ssyuu void iobus_write_1(bus_space_tag_t, bus_space_handle_t, bus_size_t, 62*61e15267Ssyuu u_int8_t); 63*61e15267Ssyuu void iobus_write_2(bus_space_tag_t, bus_space_handle_t, bus_size_t, 64*61e15267Ssyuu u_int16_t); 65*61e15267Ssyuu void iobus_write_4(bus_space_tag_t, bus_space_handle_t, bus_size_t, 66*61e15267Ssyuu u_int32_t); 67*61e15267Ssyuu void iobus_write_8(bus_space_tag_t, bus_space_handle_t, bus_size_t, 68*61e15267Ssyuu u_int64_t); 69*61e15267Ssyuu 70*61e15267Ssyuu void iobus_read_raw_2(bus_space_tag_t, bus_space_handle_t, bus_addr_t, 71*61e15267Ssyuu u_int8_t *, bus_size_t); 72*61e15267Ssyuu void iobus_write_raw_2(bus_space_tag_t, bus_space_handle_t, bus_addr_t, 73*61e15267Ssyuu const u_int8_t *, bus_size_t); 74*61e15267Ssyuu void iobus_read_raw_4(bus_space_tag_t, bus_space_handle_t, bus_addr_t, 75*61e15267Ssyuu u_int8_t *, bus_size_t); 76*61e15267Ssyuu void iobus_write_raw_4(bus_space_tag_t, bus_space_handle_t, bus_addr_t, 77*61e15267Ssyuu const u_int8_t *, bus_size_t); 78*61e15267Ssyuu void iobus_read_raw_8(bus_space_tag_t, bus_space_handle_t, bus_addr_t, 79*61e15267Ssyuu u_int8_t *, bus_size_t); 80*61e15267Ssyuu void iobus_write_raw_8(bus_space_tag_t, bus_space_handle_t, bus_addr_t, 81*61e15267Ssyuu const u_int8_t *, bus_size_t); 82*61e15267Ssyuu 83*61e15267Ssyuu int iobus_space_map(bus_space_tag_t, bus_addr_t, bus_size_t, int, 84*61e15267Ssyuu bus_space_handle_t *); 85*61e15267Ssyuu void iobus_space_unmap(bus_space_tag_t, bus_space_handle_t, bus_size_t); 86*61e15267Ssyuu int iobus_space_region(bus_space_tag_t, bus_space_handle_t, bus_size_t, 87*61e15267Ssyuu bus_size_t, bus_space_handle_t *); 88*61e15267Ssyuu 89*61e15267Ssyuu void *iobus_space_vaddr(bus_space_tag_t, bus_space_handle_t); 90*61e15267Ssyuu 91*61e15267Ssyuu bus_addr_t iobus_pa_to_device(paddr_t); 92*61e15267Ssyuu paddr_t iobus_device_to_pa(bus_addr_t); 93*61e15267Ssyuu 94*61e15267Ssyuu struct cfattach iobus_ca = { 95*61e15267Ssyuu sizeof(struct device), iobusmatch, iobusattach 96*61e15267Ssyuu }; 97*61e15267Ssyuu 98*61e15267Ssyuu struct cfdriver iobus_cd = { 99*61e15267Ssyuu NULL, "iobus", DV_DULL 100*61e15267Ssyuu }; 101*61e15267Ssyuu 102*61e15267Ssyuu bus_space_t iobus_tag = { 103*61e15267Ssyuu .bus_base = PHYS_TO_XKPHYS(0, CCA_NC), 104*61e15267Ssyuu .bus_private = NULL, 105*61e15267Ssyuu ._space_read_1 = generic_space_read_1, 106*61e15267Ssyuu ._space_write_1 = generic_space_write_1, 107*61e15267Ssyuu ._space_read_2 = generic_space_read_2, 108*61e15267Ssyuu ._space_write_2 = generic_space_write_2, 109*61e15267Ssyuu ._space_read_4 = generic_space_read_4, 110*61e15267Ssyuu ._space_write_4 = generic_space_write_4, 111*61e15267Ssyuu ._space_read_8 = generic_space_read_8, 112*61e15267Ssyuu ._space_write_8 = generic_space_write_8, 113*61e15267Ssyuu ._space_read_raw_2 = generic_space_read_raw_2, 114*61e15267Ssyuu ._space_write_raw_2 = generic_space_write_raw_2, 115*61e15267Ssyuu ._space_read_raw_4 = generic_space_read_raw_4, 116*61e15267Ssyuu ._space_write_raw_4 = generic_space_write_raw_4, 117*61e15267Ssyuu ._space_read_raw_8 = generic_space_read_raw_8, 118*61e15267Ssyuu ._space_write_raw_8 = generic_space_write_raw_8, 119*61e15267Ssyuu ._space_map = iobus_space_map, 120*61e15267Ssyuu ._space_unmap = iobus_space_unmap, 121*61e15267Ssyuu ._space_subregion = generic_space_region, 122*61e15267Ssyuu ._space_vaddr = generic_space_vaddr 123*61e15267Ssyuu }; 124*61e15267Ssyuu 125*61e15267Ssyuu bus_space_handle_t iobus_h; 126*61e15267Ssyuu 127*61e15267Ssyuu struct machine_bus_dma_tag iobus_bus_dma_tag = { 128*61e15267Ssyuu NULL, /* _cookie */ 129*61e15267Ssyuu _dmamap_create, 130*61e15267Ssyuu _dmamap_destroy, 131*61e15267Ssyuu _dmamap_load, 132*61e15267Ssyuu _dmamap_load_mbuf, 133*61e15267Ssyuu _dmamap_load_uio, 134*61e15267Ssyuu _dmamap_load_raw, 135*61e15267Ssyuu _dmamap_load_buffer, 136*61e15267Ssyuu _dmamap_unload, 137*61e15267Ssyuu _dmamap_sync, 138*61e15267Ssyuu _dmamem_alloc, 139*61e15267Ssyuu _dmamem_free, 140*61e15267Ssyuu _dmamem_map, 141*61e15267Ssyuu _dmamem_unmap, 142*61e15267Ssyuu _dmamem_mmap, 143*61e15267Ssyuu iobus_pa_to_device, 144*61e15267Ssyuu iobus_device_to_pa, 145*61e15267Ssyuu 0 146*61e15267Ssyuu }; 147*61e15267Ssyuu 148*61e15267Ssyuu /* 149*61e15267Ssyuu * List of iobus child devices. 150*61e15267Ssyuu */ 151*61e15267Ssyuu 152*61e15267Ssyuu #define IOBUSDEV(name, unitno, unit) \ 153*61e15267Ssyuu { name, unitno, unit, &iobus_tag, &iobus_bus_dma_tag } 154*61e15267Ssyuu const struct iobus_unit iobus_units[] = { 155*61e15267Ssyuu { OCTEON_CF_BASE, 0 }, /* octcf */ 156*61e15267Ssyuu { 0, 0 }, /* pcibus */ 157*61e15267Ssyuu }; 158*61e15267Ssyuu struct iobus_attach_args iobus_children[] = { 159*61e15267Ssyuu IOBUSDEV("octcf", 0, &iobus_units[0]), 160*61e15267Ssyuu IOBUSDEV("pcibus", 0, &iobus_units[1]), 161*61e15267Ssyuu }; 162*61e15267Ssyuu #undef IOBUSDEV 163*61e15267Ssyuu 164*61e15267Ssyuu /* 165*61e15267Ssyuu * Match bus only to targets which have this bus. 166*61e15267Ssyuu */ 167*61e15267Ssyuu int 168*61e15267Ssyuu iobusmatch(struct device *parent, void *match, void *aux) 169*61e15267Ssyuu { 170*61e15267Ssyuu return (1); 171*61e15267Ssyuu } 172*61e15267Ssyuu 173*61e15267Ssyuu int 174*61e15267Ssyuu iobusprint(void *aux, const char *iobus) 175*61e15267Ssyuu { 176*61e15267Ssyuu struct iobus_attach_args *aa = aux; 177*61e15267Ssyuu 178*61e15267Ssyuu if (iobus != NULL) 179*61e15267Ssyuu printf("%s at %s", aa->aa_name, iobus); 180*61e15267Ssyuu 181*61e15267Ssyuu if (aa->aa_unit->addr != 0) 182*61e15267Ssyuu printf(" base 0x%llx", aa->aa_unit->addr); 183*61e15267Ssyuu if (aa->aa_unit->irq >= 0) 184*61e15267Ssyuu printf(" irq %d", aa->aa_unit->irq); 185*61e15267Ssyuu 186*61e15267Ssyuu return (UNCONF); 187*61e15267Ssyuu } 188*61e15267Ssyuu 189*61e15267Ssyuu int 190*61e15267Ssyuu iobussubmatch(struct device *parent, void *vcf, void *args) 191*61e15267Ssyuu { 192*61e15267Ssyuu struct cfdata *cf = vcf; 193*61e15267Ssyuu struct iobus_attach_args *aa = args; 194*61e15267Ssyuu 195*61e15267Ssyuu if (strcmp(cf->cf_driver->cd_name, aa->aa_name) != 0) 196*61e15267Ssyuu return 0; 197*61e15267Ssyuu 198*61e15267Ssyuu if (cf->cf_loc[0] != -1 && cf->cf_loc[0] != (int)aa->aa_unit->addr) 199*61e15267Ssyuu return 0; 200*61e15267Ssyuu 201*61e15267Ssyuu return (*cf->cf_attach->ca_match)(parent, cf, aa); 202*61e15267Ssyuu } 203*61e15267Ssyuu 204*61e15267Ssyuu void 205*61e15267Ssyuu iobusattach(struct device *parent, struct device *self, void *aux) 206*61e15267Ssyuu { 207*61e15267Ssyuu uint i; 208*61e15267Ssyuu 209*61e15267Ssyuu /* 210*61e15267Ssyuu * Map and setup CRIME control registers. 211*61e15267Ssyuu */ 212*61e15267Ssyuu if (bus_space_map(&iobus_tag, OCTEON_CIU_BASE, OCTEON_CIU_SIZE, 0, 213*61e15267Ssyuu &iobus_h)) { 214*61e15267Ssyuu printf(": can't map CIU control registers\n"); 215*61e15267Ssyuu return; 216*61e15267Ssyuu } 217*61e15267Ssyuu 218*61e15267Ssyuu printf("\n"); 219*61e15267Ssyuu 220*61e15267Ssyuu octeon_intr_init(); 221*61e15267Ssyuu 222*61e15267Ssyuu /* 223*61e15267Ssyuu * Attach subdevices. 224*61e15267Ssyuu */ 225*61e15267Ssyuu for (i = 0; i < nitems(iobus_children); i++) 226*61e15267Ssyuu config_found_sm(self, iobus_children + i, 227*61e15267Ssyuu iobusprint, iobussubmatch); 228*61e15267Ssyuu } 229*61e15267Ssyuu 230*61e15267Ssyuu int 231*61e15267Ssyuu iobus_space_map(bus_space_tag_t t, bus_addr_t offs, bus_size_t size, 232*61e15267Ssyuu int flags, bus_space_handle_t *bshp) 233*61e15267Ssyuu { 234*61e15267Ssyuu if (ISSET(flags, BUS_SPACE_MAP_KSEG0)) { 235*61e15267Ssyuu *bshp = PHYS_TO_CKSEG0(offs); 236*61e15267Ssyuu return 0; 237*61e15267Ssyuu } 238*61e15267Ssyuu if (ISSET(flags, BUS_SPACE_MAP_CACHEABLE)) 239*61e15267Ssyuu offs += 240*61e15267Ssyuu PHYS_TO_XKPHYS(0, CCA_CACHED) - PHYS_TO_XKPHYS(0, CCA_NC); 241*61e15267Ssyuu *bshp = t->bus_base + offs; 242*61e15267Ssyuu return 0; 243*61e15267Ssyuu } 244*61e15267Ssyuu 245*61e15267Ssyuu void 246*61e15267Ssyuu iobus_space_unmap(bus_space_tag_t t, bus_space_handle_t bsh, bus_size_t size) 247*61e15267Ssyuu { 248*61e15267Ssyuu } 249*61e15267Ssyuu 250*61e15267Ssyuu /* 251*61e15267Ssyuu * Iobus bus_dma helpers. 252*61e15267Ssyuu */ 253*61e15267Ssyuu 254*61e15267Ssyuu bus_addr_t 255*61e15267Ssyuu iobus_pa_to_device(paddr_t pa) 256*61e15267Ssyuu { 257*61e15267Ssyuu return (bus_addr_t)pa; 258*61e15267Ssyuu } 259*61e15267Ssyuu 260*61e15267Ssyuu paddr_t 261*61e15267Ssyuu iobus_device_to_pa(bus_addr_t addr) 262*61e15267Ssyuu { 263*61e15267Ssyuu return (paddr_t)addr; 264*61e15267Ssyuu } 265