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