Home | History | Annotate | Line # | Download | only in loongson
gdium_machdep.c revision 1.4.6.3
      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.4.6.3  jdolecek #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.4.6.1       tls 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.4.6.1       tls 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.4.6.1       tls 	static device_t lastparent = NULL;
    243      1.1    bouyer 
    244  1.4.6.2       tls 	if (device_is_a(dev, "genfb") || device_is_a(dev, "voyagerfb")) {
    245  1.4.6.2       tls 		dict = device_properties(dev);
    246  1.4.6.2       tls 		/*
    247  1.4.6.2       tls 		 * this is a hack
    248  1.4.6.2       tls 		 * is_console needs to be checked against reality
    249  1.4.6.2       tls 		 */
    250  1.4.6.2       tls 		prop_dictionary_set_bool(dict, "is_console", 1);
    251  1.4.6.2       tls 		prop_dictionary_set_uint32(dict, "width", 1024);
    252  1.4.6.2       tls 		prop_dictionary_set_uint32(dict, "height", 600);
    253  1.4.6.2       tls 		prop_dictionary_set_uint32(dict, "depth", 16);
    254  1.4.6.2       tls 		prop_dictionary_set_uint32(dict, "linebytes", 2048);
    255  1.4.6.2       tls 		if (fb_addr != 0)
    256  1.4.6.2       tls 			prop_dictionary_set_uint32(dict, "address", fb_addr);
    257  1.4.6.2       tls 	}
    258  1.4.6.1       tls 	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.4.6.3  jdolecek 			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