1 1.1 bouyer /* $OpenBSD: gdium_machdep.c,v 1.6 2010/05/08 21:59:56 miod Exp $ */ 2 1.1 bouyer 3 1.1 bouyer /* 4 1.1 bouyer * Copyright (c) 2010 Miodrag Vallat. 5 1.1 bouyer * 6 1.1 bouyer * Permission to use, copy, modify, and distribute this software for any 7 1.1 bouyer * purpose with or without fee is hereby granted, provided that the above 8 1.1 bouyer * copyright notice and this permission notice appear in all copies. 9 1.1 bouyer * 10 1.1 bouyer * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 1.1 bouyer * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 1.1 bouyer * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 1.1 bouyer * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 1.1 bouyer * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 1.1 bouyer * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 1.1 bouyer * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 1.1 bouyer */ 18 1.1 bouyer 19 1.1 bouyer /* 20 1.1 bouyer * Gdium Liberty specific code and configuration data. 21 1.1 bouyer */ 22 1.1 bouyer 23 1.1 bouyer #include <sys/param.h> 24 1.1 bouyer #include <sys/systm.h> 25 1.1 bouyer #include <sys/device.h> 26 1.1 bouyer #include <sys/types.h> 27 1.1 bouyer 28 1.7 macallan #include <mips/cpuregs.h> 29 1.1 bouyer #include <evbmips/loongson/autoconf.h> 30 1.1 bouyer #include <evbmips/loongson/loongson_intr.h> 31 1.1 bouyer 32 1.1 bouyer #include <dev/pci/pcireg.h> 33 1.1 bouyer #include <dev/pci/pcivar.h> 34 1.1 bouyer #include <dev/pci/pcidevs.h> 35 1.1 bouyer 36 1.1 bouyer #include <mips/bonito/bonitoreg.h> 37 1.1 bouyer #include <mips/bonito/bonitovar.h> 38 1.1 bouyer 39 1.2 macallan #include <dev/wscons/wsconsio.h> 40 1.2 macallan #include <dev/wscons/wsdisplayvar.h> 41 1.2 macallan #include <dev/rasops/rasops.h> 42 1.2 macallan #include <dev/wsfont/wsfont.h> 43 1.2 macallan #include <dev/wscons/wsdisplay_vconsvar.h> 44 1.2 macallan 45 1.1 bouyer int gdium_revision = 0; 46 1.2 macallan static pcireg_t fb_addr = 0; 47 1.1 bouyer 48 1.1 bouyer void gdium_attach_hook(device_t, device_t, struct pcibus_attach_args *); 49 1.5 chs void gdium_device_register(device_t, void *); 50 1.1 bouyer int gdium_intr_map(int, int, int, pci_intr_handle_t *); 51 1.1 bouyer void gdium_powerdown(void); 52 1.1 bouyer void gdium_reset(void); 53 1.1 bouyer 54 1.1 bouyer const struct bonito_config gdium_bonito = { 55 1.1 bouyer .bc_adbase = 11, 56 1.1 bouyer 57 1.1 bouyer .bc_gpioIE = LOONGSON_INTRMASK_GPIO, 58 1.1 bouyer .bc_intEdge = LOONGSON_INTRMASK_PCI_SYSERR | 59 1.1 bouyer LOONGSON_INTRMASK_PCI_PARERR, 60 1.1 bouyer .bc_intSteer = 0, 61 1.1 bouyer .bc_intPol = LOONGSON_INTRMASK_DRAM_PARERR | 62 1.1 bouyer LOONGSON_INTRMASK_PCI_SYSERR | LOONGSON_INTRMASK_PCI_PARERR, 63 1.1 bouyer 64 1.1 bouyer .bc_attach_hook = gdium_attach_hook, 65 1.1 bouyer }; 66 1.1 bouyer 67 1.1 bouyer 68 1.1 bouyer const struct platform gdium_platform = { 69 1.1 bouyer .system_type = LOONGSON_GDIUM, 70 1.1 bouyer .vendor = "EMTEC", 71 1.1 bouyer .product = "Gdium", 72 1.1 bouyer 73 1.1 bouyer .bonito_config = &gdium_bonito, 74 1.1 bouyer .isa_chipset = NULL, 75 1.1 bouyer .legacy_io_ranges = NULL, 76 1.1 bouyer .bonito_mips_intr = MIPS_INT_MASK_4, 77 1.1 bouyer .isa_mips_intr = 0, 78 1.1 bouyer .isa_intr = NULL, 79 1.1 bouyer .p_pci_intr_map = gdium_intr_map, 80 1.1 bouyer .irq_map = loongson2f_irqmap, 81 1.1 bouyer 82 1.1 bouyer .setup = NULL, 83 1.1 bouyer .device_register = gdium_device_register, 84 1.1 bouyer 85 1.1 bouyer .powerdown = gdium_powerdown, 86 1.1 bouyer .reset = gdium_reset 87 1.1 bouyer }; 88 1.1 bouyer 89 1.2 macallan static struct vcons_screen gdium_console_screen; 90 1.2 macallan 91 1.2 macallan static struct wsscreen_descr gdium_stdscreen = { 92 1.2 macallan .name = "std", 93 1.2 macallan }; 94 1.2 macallan 95 1.1 bouyer void 96 1.1 bouyer gdium_attach_hook(device_t parent, device_t self, 97 1.1 bouyer struct pcibus_attach_args *pba) 98 1.1 bouyer { 99 1.1 bouyer pci_chipset_tag_t pc = pba->pba_pc; 100 1.1 bouyer pcireg_t id; 101 1.1 bouyer pcitag_t tag; 102 1.1 bouyer #ifdef notyet 103 1.1 bouyer int bar; 104 1.1 bouyer #endif 105 1.1 bouyer #if 0 106 1.1 bouyer pcireg_t reg; 107 1.1 bouyer int dev, func; 108 1.1 bouyer #endif 109 1.1 bouyer 110 1.1 bouyer if (pba->pba_bus != 0) 111 1.1 bouyer return; 112 1.1 bouyer 113 1.1 bouyer #ifdef notyet 114 1.1 bouyer /* 115 1.1 bouyer * Clear all BAR of the mini PCI slot; PMON did not initialize 116 1.1 bouyer * it, and we do not want it to conflict with anything. 117 1.1 bouyer */ 118 1.1 bouyer tag = pci_make_tag(pc, 0, 13, 0); 119 1.1 bouyer for (bar = PCI_MAPREG_START; bar < PCI_MAPREG_END; bar += 4) 120 1.1 bouyer pci_conf_write(pc, tag, bar, 0); 121 1.1 bouyer #else 122 1.1 bouyer /* 123 1.1 bouyer * Force a non conflicting BAR for the wireless controller, 124 1.1 bouyer * until proper resource configuration code is added to 125 1.1 bouyer * bonito (work in progress). 126 1.1 bouyer */ 127 1.1 bouyer tag = pci_make_tag(pc, 0, 13, 0); 128 1.1 bouyer pci_conf_write(pc, tag, PCI_MAPREG_START, 0x06228000); 129 1.1 bouyer #endif 130 1.1 bouyer 131 1.1 bouyer /* 132 1.1 bouyer * Figure out which motherboard we are running on. 133 1.1 bouyer * Might not be good enough... 134 1.1 bouyer */ 135 1.1 bouyer tag = pci_make_tag(pc, 0, 17, 0); 136 1.1 bouyer id = pci_conf_read(pc, tag, PCI_ID_REG); 137 1.1 bouyer if (id == PCI_ID_CODE(PCI_VENDOR_NEC, PCI_PRODUCT_NEC_USB)) 138 1.1 bouyer gdium_revision = 1; 139 1.1 bouyer 140 1.1 bouyer #if 0 141 1.1 bouyer /* 142 1.1 bouyer * Tweak the usb controller capabilities. 143 1.1 bouyer */ 144 1.1 bouyer for (dev = pci_bus_maxdevs(pc, 0); dev >= 0; dev--) { 145 1.1 bouyer tag = pci_make_tag(pc, 0, dev, 0); 146 1.1 bouyer id = pci_conf_read(pc, tag, PCI_ID_REG); 147 1.1 bouyer if (id != PCI_ID_CODE(PCI_VENDOR_NEC, PCI_PRODUCT_NEC_USB)) 148 1.1 bouyer continue; 149 1.1 bouyer if (gdium_revision != 0) { 150 1.1 bouyer reg = pci_conf_read(pc, tag, 0xe0); 151 1.1 bouyer /* enable ports 1 and 2 */ 152 1.1 bouyer reg |= 0x00000003; 153 1.1 bouyer pci_conf_write(pc, tag, 0xe0, reg); 154 1.1 bouyer } else { 155 1.1 bouyer for (func = 0; func < 2; func++) { 156 1.1 bouyer tag = pci_make_tag(pc, 0, dev, func); 157 1.1 bouyer id = pci_conf_read(pc, tag, PCI_ID_REG); 158 1.1 bouyer if (PCI_VENDOR(id) != PCI_VENDOR_NEC) 159 1.1 bouyer continue; 160 1.1 bouyer if (PCI_PRODUCT(id) != PCI_PRODUCT_NEC_USB && 161 1.1 bouyer PCI_PRODUCT(id) != PCI_PRODUCT_NEC_USB2) 162 1.1 bouyer continue; 163 1.1 bouyer 164 1.1 bouyer reg = pci_conf_read(pc, tag, 0xe0); 165 1.1 bouyer /* enable ports 1 and 3, disable port 2 */ 166 1.1 bouyer reg &= ~0x00000007; 167 1.1 bouyer reg |= 0x00000005; 168 1.1 bouyer pci_conf_write(pc, tag, 0xe0, reg); 169 1.1 bouyer pci_conf_write(pc, tag, 0xe4, 0x00000020); 170 1.1 bouyer } 171 1.1 bouyer } 172 1.1 bouyer } 173 1.1 bouyer #endif 174 1.1 bouyer } 175 1.1 bouyer 176 1.1 bouyer int 177 1.1 bouyer gdium_intr_map(int dev, int fn, int pin, pci_intr_handle_t *ihp) 178 1.1 bouyer { 179 1.1 bouyer switch (dev) { 180 1.1 bouyer /* mini-PCI slot */ 181 1.1 bouyer case 13: /* C D A B */ 182 1.1 bouyer *ihp = BONITO_DIRECT_IRQ(LOONGSON_INTR_PCIA + (pin + 1) % 4); 183 1.1 bouyer return 0; 184 1.1 bouyer /* Frame buffer */ 185 1.1 bouyer case 14: 186 1.1 bouyer *ihp = BONITO_DIRECT_IRQ(LOONGSON_INTR_PCIA); 187 1.1 bouyer return 0; 188 1.1 bouyer /* USB */ 189 1.1 bouyer case 15: 190 1.1 bouyer if (gdium_revision == 0) 191 1.1 bouyer *ihp = BONITO_DIRECT_IRQ(LOONGSON_INTR_PCIA + 192 1.1 bouyer (pin - 1)); 193 1.1 bouyer else 194 1.1 bouyer *ihp = BONITO_DIRECT_IRQ(LOONGSON_INTR_PCIB); 195 1.1 bouyer return 0; 196 1.1 bouyer /* Ethernet */ 197 1.1 bouyer case 16: 198 1.1 bouyer *ihp = BONITO_DIRECT_IRQ(LOONGSON_INTR_PCID); 199 1.1 bouyer return 0; 200 1.1 bouyer /* USB, not present in old motherboard revision */ 201 1.1 bouyer case 17: 202 1.1 bouyer if (gdium_revision != 0) { 203 1.1 bouyer *ihp = BONITO_DIRECT_IRQ(LOONGSON_INTR_PCIC); 204 1.1 bouyer return 0; 205 1.1 bouyer } else 206 1.1 bouyer break; 207 1.1 bouyer default: 208 1.1 bouyer break; 209 1.1 bouyer } 210 1.1 bouyer 211 1.1 bouyer return 1; 212 1.1 bouyer } 213 1.1 bouyer 214 1.1 bouyer /* 215 1.1 bouyer * Due to PMON limitations on the Gdium Liberty, we do not get boot device 216 1.1 bouyer * information from PMON. 217 1.1 bouyer * 218 1.1 bouyer * Because of this, we always pretend the G-Key port is the boot device. 219 1.1 bouyer * 220 1.1 bouyer * Note that, unlike on the Lemote machines, other USB devices gets a fixed 221 1.1 bouyer * numbering (USB0 and USB1). 222 1.1 bouyer */ 223 1.1 bouyer 224 1.1 bouyer extern struct cfdriver bonito_cd; 225 1.1 bouyer extern struct cfdriver pci_cd; 226 1.1 bouyer extern struct cfdriver ehci_cd; 227 1.1 bouyer extern struct cfdriver usb_cd; 228 1.1 bouyer extern struct cfdriver uhub_cd; 229 1.1 bouyer extern struct cfdriver umass_cd; 230 1.1 bouyer extern struct cfdriver scsibus_cd; 231 1.1 bouyer extern struct cfdriver sd_cd; 232 1.1 bouyer 233 1.1 bouyer #include <dev/pci/pcivar.h> 234 1.1 bouyer #include <dev/usb/usb.h> 235 1.1 bouyer #include <dev/usb/usbdi.h> 236 1.1 bouyer 237 1.1 bouyer void 238 1.5 chs gdium_device_register(device_t dev, void *aux) 239 1.1 bouyer { 240 1.2 macallan prop_dictionary_t dict; 241 1.1 bouyer static int gkey_chain_pos = 0; 242 1.5 chs static device_t lastparent = NULL; 243 1.1 bouyer 244 1.6 macallan if (device_is_a(dev, "genfb") || device_is_a(dev, "voyagerfb")) { 245 1.6 macallan dict = device_properties(dev); 246 1.6 macallan /* 247 1.6 macallan * this is a hack 248 1.6 macallan * is_console needs to be checked against reality 249 1.6 macallan */ 250 1.6 macallan prop_dictionary_set_bool(dict, "is_console", 1); 251 1.6 macallan prop_dictionary_set_uint32(dict, "width", 1024); 252 1.6 macallan prop_dictionary_set_uint32(dict, "height", 600); 253 1.6 macallan prop_dictionary_set_uint32(dict, "depth", 16); 254 1.6 macallan prop_dictionary_set_uint32(dict, "linebytes", 2048); 255 1.6 macallan if (fb_addr != 0) 256 1.6 macallan prop_dictionary_set_uint32(dict, "address", fb_addr); 257 1.6 macallan } 258 1.5 chs if (device_parent(dev) != lastparent && gkey_chain_pos != 0) 259 1.1 bouyer return; 260 1.1 bouyer 261 1.1 bouyer switch (gkey_chain_pos) { 262 1.1 bouyer case 0: /* bonito at mainbus */ 263 1.1 bouyer if (device_is_a(dev, "bonito")) 264 1.1 bouyer goto advance; 265 1.1 bouyer break; 266 1.1 bouyer case 1: /* pci at bonito */ 267 1.1 bouyer if (device_is_a(dev, "pci")) 268 1.1 bouyer goto advance; 269 1.1 bouyer break; 270 1.1 bouyer case 2: /* ehci at pci dev 15 */ 271 1.1 bouyer if (device_is_a(dev, "ehci")) { 272 1.1 bouyer struct pci_attach_args *paa = aux; 273 1.1 bouyer if (paa->pa_device == 15) 274 1.1 bouyer goto advance; 275 1.1 bouyer } 276 1.1 bouyer break; 277 1.1 bouyer case 3: /* usb at ehci */ 278 1.1 bouyer if (device_is_a(dev, "usb")) 279 1.1 bouyer goto advance; 280 1.1 bouyer break; 281 1.1 bouyer case 4: /* uhub at usb */ 282 1.1 bouyer if (device_is_a(dev, "uhub")) 283 1.1 bouyer goto advance; 284 1.1 bouyer break; 285 1.1 bouyer case 5: /* umass at uhub port 3 */ 286 1.1 bouyer if (device_is_a(dev, "umass")) { 287 1.1 bouyer struct usb_attach_arg *uaa = aux; 288 1.8 skrll if (uaa->uaa_port == 3) 289 1.1 bouyer goto advance; 290 1.1 bouyer } 291 1.1 bouyer break; 292 1.1 bouyer case 6: /* scsibus at umass */ 293 1.1 bouyer if (device_is_a(dev, "scsibus")) 294 1.1 bouyer goto advance; 295 1.1 bouyer break; 296 1.1 bouyer case 7: /* sd at scsibus */ 297 1.1 bouyer if (booted_device == NULL) 298 1.1 bouyer booted_device = dev; 299 1.1 bouyer break; 300 1.1 bouyer } 301 1.1 bouyer 302 1.1 bouyer return; 303 1.1 bouyer 304 1.1 bouyer advance: 305 1.1 bouyer gkey_chain_pos++; 306 1.1 bouyer lastparent = dev; 307 1.1 bouyer } 308 1.1 bouyer 309 1.1 bouyer void 310 1.4 christos gdium_powerdown(void) 311 1.1 bouyer { 312 1.1 bouyer REGVAL(BONITO_GPIODATA) |= 0x00000002; 313 1.1 bouyer REGVAL(BONITO_GPIOIE) &= ~0x00000002; 314 1.3 macallan printf("Powering down...\n"); 315 1.3 macallan while(1) delay(1000); 316 1.1 bouyer } 317 1.1 bouyer 318 1.1 bouyer void 319 1.4 christos gdium_reset(void) 320 1.1 bouyer { 321 1.1 bouyer REGVAL(BONITO_GPIODATA) &= ~0x00000002; 322 1.1 bouyer REGVAL(BONITO_GPIOIE) &= ~0x00000002; 323 1.1 bouyer } 324 1.2 macallan 325 1.2 macallan /* 326 1.2 macallan * Early console code 327 1.2 macallan */ 328 1.2 macallan 329 1.2 macallan int 330 1.2 macallan gdium_cnattach(bus_space_tag_t memt, bus_space_tag_t iot, 331 1.2 macallan pci_chipset_tag_t pc, pcitag_t tag, pcireg_t id) 332 1.2 macallan { 333 1.2 macallan struct rasops_info * const ri = &gdium_console_screen.scr_ri; 334 1.2 macallan long defattr; 335 1.2 macallan pcireg_t reg; 336 1.2 macallan 337 1.2 macallan 338 1.2 macallan /* filter out unrecognized devices */ 339 1.2 macallan switch (id) { 340 1.2 macallan default: 341 1.2 macallan return ENODEV; 342 1.2 macallan case PCI_ID_CODE(PCI_VENDOR_SILMOTION, PCI_PRODUCT_SILMOTION_SM502): 343 1.2 macallan break; 344 1.2 macallan } 345 1.2 macallan 346 1.2 macallan wsfont_init(); 347 1.2 macallan 348 1.2 macallan /* set up rasops */ 349 1.2 macallan ri->ri_width = 1024; 350 1.2 macallan ri->ri_height = 600; 351 1.2 macallan ri->ri_depth = 16; 352 1.2 macallan ri->ri_stride = 0x800; 353 1.2 macallan 354 1.2 macallan /* read the mapping register for the frame buffer */ 355 1.2 macallan reg = pci_conf_read(pc, tag, PCI_MAPREG_START); 356 1.2 macallan fb_addr = reg; 357 1.2 macallan 358 1.2 macallan ri->ri_bits = (char *)MIPS_PHYS_TO_KSEG1(BONITO_PCILO_BASE + reg); 359 1.2 macallan ri->ri_flg = RI_CENTER | RI_NO_AUTO; 360 1.2 macallan 361 1.2 macallan memset(ri->ri_bits, 0, 0x200000); 362 1.2 macallan 363 1.2 macallan /* use as much of the screen as the font permits */ 364 1.2 macallan rasops_init(ri, 30, 80); 365 1.2 macallan 366 1.2 macallan rasops_reconfig(ri, ri->ri_height / ri->ri_font->fontheight, 367 1.2 macallan ri->ri_width / ri->ri_font->fontwidth); 368 1.2 macallan 369 1.2 macallan gdium_stdscreen.nrows = ri->ri_rows; 370 1.2 macallan gdium_stdscreen.ncols = ri->ri_cols; 371 1.2 macallan gdium_stdscreen.textops = &ri->ri_ops; 372 1.2 macallan gdium_stdscreen.capabilities = ri->ri_caps; 373 1.2 macallan 374 1.2 macallan ri->ri_ops.allocattr(ri, 0, ri->ri_rows - 1, 0, &defattr); 375 1.2 macallan 376 1.2 macallan wsdisplay_preattach(&gdium_stdscreen, ri, 0, 0, defattr); 377 1.2 macallan 378 1.2 macallan return 0; 379 1.2 macallan 380 1.2 macallan } 381