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