1 /* $OpenBSD: octeon_iobus.c,v 1.16 2016/06/22 13:09:35 visa 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 #include <sys/atomic.h> 42 43 #include <machine/autoconf.h> 44 #include <machine/intr.h> 45 #include <machine/octeonvar.h> 46 #include <machine/octeonreg.h> 47 #include <machine/octeon_model.h> 48 49 #include <octeon/dev/iobusvar.h> 50 #include <octeon/dev/cn30xxgmxreg.h> 51 #include <octeon/dev/octhcireg.h> /* USBN_BASE */ 52 #include <octeon/dev/octuctlreg.h> 53 54 int iobusmatch(struct device *, void *, void *); 55 void iobusattach(struct device *, struct device *, void *); 56 int iobusprint(void *, const char *); 57 int iobussubmatch(struct device *, void *, void *); 58 int iobussearch(struct device *, void *, void *); 59 60 u_int8_t iobus_read_1(bus_space_tag_t, bus_space_handle_t, bus_size_t); 61 u_int16_t iobus_read_2(bus_space_tag_t, bus_space_handle_t, bus_size_t); 62 u_int32_t iobus_read_4(bus_space_tag_t, bus_space_handle_t, bus_size_t); 63 u_int64_t iobus_read_8(bus_space_tag_t, bus_space_handle_t, bus_size_t); 64 65 void iobus_write_1(bus_space_tag_t, bus_space_handle_t, bus_size_t, 66 u_int8_t); 67 void iobus_write_2(bus_space_tag_t, bus_space_handle_t, bus_size_t, 68 u_int16_t); 69 void iobus_write_4(bus_space_tag_t, bus_space_handle_t, bus_size_t, 70 u_int32_t); 71 void iobus_write_8(bus_space_tag_t, bus_space_handle_t, bus_size_t, 72 u_int64_t); 73 74 void iobus_read_raw_2(bus_space_tag_t, bus_space_handle_t, bus_addr_t, 75 u_int8_t *, bus_size_t); 76 void iobus_write_raw_2(bus_space_tag_t, bus_space_handle_t, bus_addr_t, 77 const u_int8_t *, bus_size_t); 78 void iobus_read_raw_4(bus_space_tag_t, bus_space_handle_t, bus_addr_t, 79 u_int8_t *, bus_size_t); 80 void iobus_write_raw_4(bus_space_tag_t, bus_space_handle_t, bus_addr_t, 81 const u_int8_t *, bus_size_t); 82 void iobus_read_raw_8(bus_space_tag_t, bus_space_handle_t, bus_addr_t, 83 u_int8_t *, bus_size_t); 84 void iobus_write_raw_8(bus_space_tag_t, bus_space_handle_t, bus_addr_t, 85 const u_int8_t *, bus_size_t); 86 87 bus_addr_t iobus_pa_to_device(paddr_t); 88 paddr_t iobus_device_to_pa(bus_addr_t); 89 90 struct cfattach iobus_ca = { 91 sizeof(struct device), iobusmatch, iobusattach 92 }; 93 94 struct cfdriver iobus_cd = { 95 NULL, "iobus", DV_DULL 96 }; 97 98 bus_space_t iobus_tag = { 99 .bus_base = PHYS_TO_XKPHYS(0, CCA_NC), 100 .bus_private = NULL, 101 ._space_read_1 = generic_space_read_1, 102 ._space_write_1 = generic_space_write_1, 103 ._space_read_2 = generic_space_read_2, 104 ._space_write_2 = generic_space_write_2, 105 ._space_read_4 = generic_space_read_4, 106 ._space_write_4 = generic_space_write_4, 107 ._space_read_8 = generic_space_read_8, 108 ._space_write_8 = generic_space_write_8, 109 ._space_read_raw_2 = generic_space_read_raw_2, 110 ._space_write_raw_2 = generic_space_write_raw_2, 111 ._space_read_raw_4 = generic_space_read_raw_4, 112 ._space_write_raw_4 = generic_space_write_raw_4, 113 ._space_read_raw_8 = generic_space_read_raw_8, 114 ._space_write_raw_8 = generic_space_write_raw_8, 115 ._space_map = iobus_space_map, 116 ._space_unmap = iobus_space_unmap, 117 ._space_subregion = generic_space_region, 118 ._space_vaddr = generic_space_vaddr 119 }; 120 121 bus_space_handle_t iobus_h; 122 123 struct machine_bus_dma_tag iobus_bus_dma_tag = { 124 NULL, /* _cookie */ 125 _dmamap_create, 126 _dmamap_destroy, 127 _dmamap_load, 128 _dmamap_load_mbuf, 129 _dmamap_load_uio, 130 _dmamap_load_raw, 131 _dmamap_load_buffer, 132 _dmamap_unload, 133 _dmamap_sync, 134 _dmamem_alloc, 135 _dmamem_free, 136 _dmamem_map, 137 _dmamem_unmap, 138 _dmamem_mmap, 139 iobus_pa_to_device, 140 iobus_device_to_pa, 141 0 142 }; 143 144 /* 145 * List of iobus child devices whose base addresses are too large to be 146 * recorded in the kernel configuration file. So look them up from here instead. 147 */ 148 149 static const struct octeon_iobus_addrs iobus_addrs[] = { 150 { "octcf", OCTEON_CF_BASE }, 151 { "octrng", OCTEON_RNG_BASE }, 152 { "dwctwo", USBN_BASE }, 153 { "amdcf", OCTEON_AMDCF_BASE}, 154 { "octuctl", UCTL_BASE }, 155 }; 156 157 /* There can only be one. */ 158 int iobus_found; 159 160 /* 161 * Match bus only to targets which have this bus. 162 */ 163 int 164 iobusmatch(struct device *parent, void *match, void *aux) 165 { 166 if (iobus_found) 167 return (0); 168 169 return (1); 170 } 171 172 int 173 iobusprint(void *aux, const char *iobus) 174 { 175 struct iobus_attach_args *aa = aux; 176 177 if (iobus != NULL) 178 printf("%s at %s", aa->aa_name, iobus); 179 180 if (aa->aa_addr != 0) 181 printf(" base 0x%lx", aa->aa_addr); 182 if (aa->aa_irq >= 0) 183 printf(" irq %d", aa->aa_irq); 184 185 return (UNCONF); 186 } 187 188 int 189 iobussubmatch(struct device *parent, void *vcf, void *args) 190 { 191 struct cfdata *cf = vcf; 192 struct iobus_attach_args *aa = args; 193 194 if (strcmp(cf->cf_driver->cd_name, aa->aa_name) != 0) 195 return 0; 196 197 if (cf->cf_loc[0] != -1 && cf->cf_loc[0] != (int)aa->aa_addr) 198 return 0; 199 200 return (*cf->cf_attach->ca_match)(parent, cf, aa); 201 } 202 203 void 204 iobusattach(struct device *parent, struct device *self, void *aux) 205 { 206 struct iobus_attach_args aa; 207 struct octeon_config oc; 208 struct device *sc = self; 209 int chipid, i, ngmx; 210 211 /* 212 * Map and setup CIU control registers. 213 */ 214 if (bus_space_map(&iobus_tag, OCTEON_CIU_BASE, OCTEON_CIU_SIZE, 0, 215 &iobus_h)) { 216 printf(": can't map CIU control registers\n"); 217 return; 218 } 219 220 iobus_found = 1; 221 222 printf("\n"); 223 224 octeon_intr_init(); 225 226 /* XXX */ 227 oc.mc_iobus_bust = &iobus_tag; 228 oc.mc_iobus_dmat = &iobus_bus_dma_tag; 229 void cn30xxfpa_bootstrap(struct octeon_config *); 230 cn30xxfpa_bootstrap(&oc); 231 void cn30xxpow_bootstrap(struct octeon_config *); 232 cn30xxpow_bootstrap(&oc); 233 234 /* 235 * Attach all subdevices as described in the config file. 236 */ 237 config_search(iobussearch, self, sc); 238 239 chipid = octeon_get_chipid(); 240 switch (octeon_model_family(chipid)) { 241 case OCTEON_MODEL_FAMILY_CN30XX: 242 case OCTEON_MODEL_FAMILY_CN50XX: 243 default: 244 ngmx = 1; 245 break; 246 case OCTEON_MODEL_FAMILY_CN61XX: 247 ngmx = 2; 248 break; 249 } 250 for (i = 0; i < ngmx; i++) { 251 aa.aa_name = "cn30xxgmx"; 252 aa.aa_bust = &iobus_tag; 253 aa.aa_dmat = &iobus_bus_dma_tag; 254 aa.aa_addr = GMX0_BASE_PORT0 + GMX_BLOCK_SIZE * i; 255 aa.aa_irq = -1; 256 aa.aa_unitno = i; 257 config_found_sm(self, &aa, iobusprint, iobussubmatch); 258 } 259 } 260 261 int 262 iobussearch(struct device *parent, void *v, void *aux) 263 { 264 struct iobus_attach_args aa; 265 struct cfdata *cf = v; 266 int i; 267 268 aa.aa_name = cf->cf_driver->cd_name; 269 aa.aa_bust = &iobus_tag; 270 aa.aa_dmat = &iobus_bus_dma_tag; 271 aa.aa_addr = cf->cf_loc[0]; 272 aa.aa_irq = cf->cf_loc[1]; 273 aa.aa_unitno = cf->cf_unit; 274 275 /* No address specified, try to look it up. */ 276 if (aa.aa_addr == -1) { 277 for (i = 0; i < nitems(iobus_addrs); i++) { 278 if (strcmp(iobus_addrs[i].name, cf->cf_driver->cd_name) == 0) 279 aa.aa_addr = iobus_addrs[i].address; 280 } 281 if (aa.aa_addr == -1) 282 return 0; 283 } 284 285 if (cf->cf_attach->ca_match(parent, cf, &aa) == 0) 286 return 0; 287 288 config_attach(parent, cf, &aa, iobusprint); 289 return 1; 290 } 291 292 int 293 iobus_space_map(bus_space_tag_t t, bus_addr_t offs, bus_size_t size, 294 int flags, bus_space_handle_t *bshp) 295 { 296 if (ISSET(flags, BUS_SPACE_MAP_KSEG0)) { 297 *bshp = PHYS_TO_CKSEG0(offs); 298 return 0; 299 } 300 if (ISSET(flags, BUS_SPACE_MAP_CACHEABLE)) 301 offs += 302 PHYS_TO_XKPHYS(0, CCA_CACHED) - PHYS_TO_XKPHYS(0, CCA_NC); 303 *bshp = t->bus_base + offs; 304 return 0; 305 } 306 307 void 308 iobus_space_unmap(bus_space_tag_t t, bus_space_handle_t bsh, bus_size_t size) 309 { 310 } 311 312 /* 313 * Iobus bus_dma helpers. 314 */ 315 316 bus_addr_t 317 iobus_pa_to_device(paddr_t pa) 318 { 319 return (bus_addr_t)pa; 320 } 321 322 paddr_t 323 iobus_device_to_pa(bus_addr_t addr) 324 { 325 return (paddr_t)addr; 326 } 327