Home | History | Annotate | Line # | Download | only in loongson
gdium_machdep.c revision 1.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.1  bouyer int	gdium_revision = 0;
     39  1.1  bouyer 
     40  1.1  bouyer void	gdium_attach_hook(device_t, device_t, struct pcibus_attach_args *);
     41  1.1  bouyer void	gdium_device_register(struct device *, void *);
     42  1.1  bouyer int	gdium_intr_map(int, int, int, pci_intr_handle_t *);
     43  1.1  bouyer void	gdium_powerdown(void);
     44  1.1  bouyer void	gdium_reset(void);
     45  1.1  bouyer 
     46  1.1  bouyer const struct bonito_config gdium_bonito = {
     47  1.1  bouyer 	.bc_adbase = 11,
     48  1.1  bouyer 
     49  1.1  bouyer 	.bc_gpioIE = LOONGSON_INTRMASK_GPIO,
     50  1.1  bouyer 	.bc_intEdge = LOONGSON_INTRMASK_PCI_SYSERR |
     51  1.1  bouyer 	    LOONGSON_INTRMASK_PCI_PARERR,
     52  1.1  bouyer 	.bc_intSteer = 0,
     53  1.1  bouyer 	.bc_intPol = LOONGSON_INTRMASK_DRAM_PARERR |
     54  1.1  bouyer 	    LOONGSON_INTRMASK_PCI_SYSERR | LOONGSON_INTRMASK_PCI_PARERR,
     55  1.1  bouyer 
     56  1.1  bouyer 	.bc_attach_hook = gdium_attach_hook,
     57  1.1  bouyer };
     58  1.1  bouyer 
     59  1.1  bouyer 
     60  1.1  bouyer const struct platform gdium_platform = {
     61  1.1  bouyer 	.system_type = LOONGSON_GDIUM,
     62  1.1  bouyer 	.vendor = "EMTEC",
     63  1.1  bouyer 	.product = "Gdium",
     64  1.1  bouyer 
     65  1.1  bouyer 	.bonito_config = &gdium_bonito,
     66  1.1  bouyer 	.isa_chipset = NULL,
     67  1.1  bouyer 	.legacy_io_ranges = NULL,
     68  1.1  bouyer 	.bonito_mips_intr = MIPS_INT_MASK_4,
     69  1.1  bouyer 	.isa_mips_intr = 0,
     70  1.1  bouyer 	.isa_intr = NULL,
     71  1.1  bouyer 	.p_pci_intr_map = gdium_intr_map,
     72  1.1  bouyer 	.irq_map = loongson2f_irqmap,
     73  1.1  bouyer 
     74  1.1  bouyer 	.setup = NULL,
     75  1.1  bouyer 	.device_register = gdium_device_register,
     76  1.1  bouyer 
     77  1.1  bouyer 	.powerdown = gdium_powerdown,
     78  1.1  bouyer 	.reset = gdium_reset
     79  1.1  bouyer };
     80  1.1  bouyer 
     81  1.1  bouyer void
     82  1.1  bouyer gdium_attach_hook(device_t parent, device_t self,
     83  1.1  bouyer     struct pcibus_attach_args *pba)
     84  1.1  bouyer {
     85  1.1  bouyer 	pci_chipset_tag_t pc = pba->pba_pc;
     86  1.1  bouyer 	pcireg_t id;
     87  1.1  bouyer 	pcitag_t tag;
     88  1.1  bouyer #ifdef notyet
     89  1.1  bouyer 	int bar;
     90  1.1  bouyer #endif
     91  1.1  bouyer #if 0
     92  1.1  bouyer 	pcireg_t reg;
     93  1.1  bouyer 	int dev, func;
     94  1.1  bouyer #endif
     95  1.1  bouyer 
     96  1.1  bouyer 	if (pba->pba_bus != 0)
     97  1.1  bouyer 		return;
     98  1.1  bouyer 
     99  1.1  bouyer #ifdef notyet
    100  1.1  bouyer 	/*
    101  1.1  bouyer 	 * Clear all BAR of the mini PCI slot; PMON did not initialize
    102  1.1  bouyer 	 * it, and we do not want it to conflict with anything.
    103  1.1  bouyer 	 */
    104  1.1  bouyer 	tag = pci_make_tag(pc, 0, 13, 0);
    105  1.1  bouyer 	for (bar = PCI_MAPREG_START; bar < PCI_MAPREG_END; bar += 4)
    106  1.1  bouyer 		pci_conf_write(pc, tag, bar, 0);
    107  1.1  bouyer #else
    108  1.1  bouyer 	/*
    109  1.1  bouyer 	 * Force a non conflicting BAR for the wireless controller,
    110  1.1  bouyer 	 * until proper resource configuration code is added to
    111  1.1  bouyer 	 * bonito (work in progress).
    112  1.1  bouyer 	 */
    113  1.1  bouyer 	tag = pci_make_tag(pc, 0, 13, 0);
    114  1.1  bouyer 	pci_conf_write(pc, tag, PCI_MAPREG_START, 0x06228000);
    115  1.1  bouyer #endif
    116  1.1  bouyer 
    117  1.1  bouyer 	/*
    118  1.1  bouyer 	 * Figure out which motherboard we are running on.
    119  1.1  bouyer 	 * Might not be good enough...
    120  1.1  bouyer 	 */
    121  1.1  bouyer 	tag = pci_make_tag(pc, 0, 17, 0);
    122  1.1  bouyer 	id = pci_conf_read(pc, tag, PCI_ID_REG);
    123  1.1  bouyer 	if (id == PCI_ID_CODE(PCI_VENDOR_NEC, PCI_PRODUCT_NEC_USB))
    124  1.1  bouyer 		gdium_revision = 1;
    125  1.1  bouyer 
    126  1.1  bouyer #if 0
    127  1.1  bouyer 	/*
    128  1.1  bouyer 	 * Tweak the usb controller capabilities.
    129  1.1  bouyer 	 */
    130  1.1  bouyer 	for (dev = pci_bus_maxdevs(pc, 0); dev >= 0; dev--) {
    131  1.1  bouyer 		tag = pci_make_tag(pc, 0, dev, 0);
    132  1.1  bouyer 		id = pci_conf_read(pc, tag, PCI_ID_REG);
    133  1.1  bouyer 		if (id != PCI_ID_CODE(PCI_VENDOR_NEC, PCI_PRODUCT_NEC_USB))
    134  1.1  bouyer 			continue;
    135  1.1  bouyer 		if (gdium_revision != 0) {
    136  1.1  bouyer 			reg = pci_conf_read(pc, tag, 0xe0);
    137  1.1  bouyer 			/* enable ports 1 and 2 */
    138  1.1  bouyer 			reg |= 0x00000003;
    139  1.1  bouyer 			pci_conf_write(pc, tag, 0xe0, reg);
    140  1.1  bouyer 		} else {
    141  1.1  bouyer 			for (func = 0; func < 2; func++) {
    142  1.1  bouyer 				tag = pci_make_tag(pc, 0, dev, func);
    143  1.1  bouyer 				id = pci_conf_read(pc, tag, PCI_ID_REG);
    144  1.1  bouyer 				if (PCI_VENDOR(id) != PCI_VENDOR_NEC)
    145  1.1  bouyer 					continue;
    146  1.1  bouyer 				if (PCI_PRODUCT(id) != PCI_PRODUCT_NEC_USB &&
    147  1.1  bouyer 				    PCI_PRODUCT(id) != PCI_PRODUCT_NEC_USB2)
    148  1.1  bouyer 					continue;
    149  1.1  bouyer 
    150  1.1  bouyer 				reg = pci_conf_read(pc, tag, 0xe0);
    151  1.1  bouyer 				/* enable ports 1 and 3, disable port 2 */
    152  1.1  bouyer 				reg &= ~0x00000007;
    153  1.1  bouyer 				reg |= 0x00000005;
    154  1.1  bouyer 				pci_conf_write(pc, tag, 0xe0, reg);
    155  1.1  bouyer 				pci_conf_write(pc, tag, 0xe4, 0x00000020);
    156  1.1  bouyer 			}
    157  1.1  bouyer 		}
    158  1.1  bouyer 	}
    159  1.1  bouyer #endif
    160  1.1  bouyer }
    161  1.1  bouyer 
    162  1.1  bouyer int
    163  1.1  bouyer gdium_intr_map(int dev, int fn, int pin, pci_intr_handle_t *ihp)
    164  1.1  bouyer {
    165  1.1  bouyer 	switch (dev) {
    166  1.1  bouyer 	/* mini-PCI slot */
    167  1.1  bouyer 	case 13:	/* C D A B */
    168  1.1  bouyer 		*ihp = BONITO_DIRECT_IRQ(LOONGSON_INTR_PCIA + (pin + 1) % 4);
    169  1.1  bouyer 		return 0;
    170  1.1  bouyer 	/* Frame buffer */
    171  1.1  bouyer 	case 14:
    172  1.1  bouyer 		*ihp = BONITO_DIRECT_IRQ(LOONGSON_INTR_PCIA);
    173  1.1  bouyer 		return 0;
    174  1.1  bouyer 	/* USB */
    175  1.1  bouyer 	case 15:
    176  1.1  bouyer 		if (gdium_revision == 0)
    177  1.1  bouyer 			*ihp = BONITO_DIRECT_IRQ(LOONGSON_INTR_PCIA +
    178  1.1  bouyer 			    (pin - 1));
    179  1.1  bouyer 		else
    180  1.1  bouyer 			*ihp = BONITO_DIRECT_IRQ(LOONGSON_INTR_PCIB);
    181  1.1  bouyer 		return 0;
    182  1.1  bouyer 	/* Ethernet */
    183  1.1  bouyer 	case 16:
    184  1.1  bouyer 		*ihp = BONITO_DIRECT_IRQ(LOONGSON_INTR_PCID);
    185  1.1  bouyer 		return 0;
    186  1.1  bouyer 	/* USB, not present in old motherboard revision */
    187  1.1  bouyer 	case 17:
    188  1.1  bouyer 		if (gdium_revision != 0) {
    189  1.1  bouyer 			*ihp = BONITO_DIRECT_IRQ(LOONGSON_INTR_PCIC);
    190  1.1  bouyer 			return 0;
    191  1.1  bouyer 		} else
    192  1.1  bouyer 			break;
    193  1.1  bouyer 	default:
    194  1.1  bouyer 		break;
    195  1.1  bouyer 	}
    196  1.1  bouyer 
    197  1.1  bouyer 	return 1;
    198  1.1  bouyer }
    199  1.1  bouyer 
    200  1.1  bouyer /*
    201  1.1  bouyer  * Due to PMON limitations on the Gdium Liberty, we do not get boot device
    202  1.1  bouyer  * information from PMON.
    203  1.1  bouyer  *
    204  1.1  bouyer  * Because of this, we always pretend the G-Key port is the boot device.
    205  1.1  bouyer  *
    206  1.1  bouyer  * Note that, unlike on the Lemote machines, other USB devices gets a fixed
    207  1.1  bouyer  * numbering (USB0 and USB1).
    208  1.1  bouyer  */
    209  1.1  bouyer 
    210  1.1  bouyer extern struct cfdriver bonito_cd;
    211  1.1  bouyer extern struct cfdriver pci_cd;
    212  1.1  bouyer extern struct cfdriver ehci_cd;
    213  1.1  bouyer extern struct cfdriver usb_cd;
    214  1.1  bouyer extern struct cfdriver uhub_cd;
    215  1.1  bouyer extern struct cfdriver umass_cd;
    216  1.1  bouyer extern struct cfdriver scsibus_cd;
    217  1.1  bouyer extern struct cfdriver sd_cd;
    218  1.1  bouyer 
    219  1.1  bouyer #include <dev/pci/pcivar.h>
    220  1.1  bouyer #include <dev/usb/usb.h>
    221  1.1  bouyer #include <dev/usb/usbdi.h>
    222  1.1  bouyer 
    223  1.1  bouyer void
    224  1.1  bouyer gdium_device_register(struct device *dev, void *aux)
    225  1.1  bouyer {
    226  1.1  bouyer 	static int gkey_chain_pos = 0;
    227  1.1  bouyer 	static struct device *lastparent = NULL;
    228  1.1  bouyer 
    229  1.1  bouyer 	if (dev->dv_parent != lastparent && gkey_chain_pos != 0)
    230  1.1  bouyer 		return;
    231  1.1  bouyer 
    232  1.1  bouyer 	switch (gkey_chain_pos) {
    233  1.1  bouyer 	case 0:	/* bonito at mainbus */
    234  1.1  bouyer 		if (device_is_a(dev, "bonito"))
    235  1.1  bouyer 			goto advance;
    236  1.1  bouyer 		break;
    237  1.1  bouyer 	case 1:	/* pci at bonito */
    238  1.1  bouyer 		if (device_is_a(dev, "pci"))
    239  1.1  bouyer 			goto advance;
    240  1.1  bouyer 		break;
    241  1.1  bouyer 	case 2:	/* ehci at pci dev 15 */
    242  1.1  bouyer 		if (device_is_a(dev, "ehci")) {
    243  1.1  bouyer 			struct pci_attach_args *paa = aux;
    244  1.1  bouyer 			if (paa->pa_device == 15)
    245  1.1  bouyer 				goto advance;
    246  1.1  bouyer 		}
    247  1.1  bouyer 		break;
    248  1.1  bouyer 	case 3:	/* usb at ehci */
    249  1.1  bouyer 		if (device_is_a(dev, "usb"))
    250  1.1  bouyer 			goto advance;
    251  1.1  bouyer 		break;
    252  1.1  bouyer 	case 4:	/* uhub at usb */
    253  1.1  bouyer 		if (device_is_a(dev, "uhub"))
    254  1.1  bouyer 			goto advance;
    255  1.1  bouyer 		break;
    256  1.1  bouyer 	case 5:	/* umass at uhub port 3 */
    257  1.1  bouyer 		if (device_is_a(dev, "umass")) {
    258  1.1  bouyer 			struct usb_attach_arg *uaa = aux;
    259  1.1  bouyer 			if (uaa->port == 3)
    260  1.1  bouyer 				goto advance;
    261  1.1  bouyer 		}
    262  1.1  bouyer 		break;
    263  1.1  bouyer 	case 6:	/* scsibus at umass */
    264  1.1  bouyer 		if (device_is_a(dev, "scsibus"))
    265  1.1  bouyer 			goto advance;
    266  1.1  bouyer 		break;
    267  1.1  bouyer 	case 7:	/* sd at scsibus */
    268  1.1  bouyer 		if (booted_device == NULL)
    269  1.1  bouyer 			booted_device = dev;
    270  1.1  bouyer 		break;
    271  1.1  bouyer 	}
    272  1.1  bouyer 
    273  1.1  bouyer 	return;
    274  1.1  bouyer 
    275  1.1  bouyer advance:
    276  1.1  bouyer 	gkey_chain_pos++;
    277  1.1  bouyer 	lastparent = dev;
    278  1.1  bouyer }
    279  1.1  bouyer 
    280  1.1  bouyer void
    281  1.1  bouyer gdium_powerdown()
    282  1.1  bouyer {
    283  1.1  bouyer 	REGVAL(BONITO_GPIODATA) |= 0x00000002;
    284  1.1  bouyer 	REGVAL(BONITO_GPIOIE) &= ~0x00000002;
    285  1.1  bouyer }
    286  1.1  bouyer 
    287  1.1  bouyer void
    288  1.1  bouyer gdium_reset()
    289  1.1  bouyer {
    290  1.1  bouyer 	REGVAL(BONITO_GPIODATA) &= ~0x00000002;
    291  1.1  bouyer 	REGVAL(BONITO_GPIOIE) &= ~0x00000002;
    292  1.1  bouyer }
    293