int
iq80321_pci_intr_map(const struct pci_attach_args *pa, pci_intr_handle_t *ihp)
{
	struct i80321_softc *sc = pa->pa_pc->pc_intr_v;
	int b, d, f;
	uint32_t busno;

	/*
	 * The IQ80321's interrupts are routed like so:
	 *
	 *	XINT0	i82544 Gig-E
	 *
	 *	XINT1	UART
	 *
	 *	XINT2	INTA# from S-PCI-X slot
	 *
	 *	XINT3	INTB# from S-PCI-X slot
	 */

	busno = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_PCIXSR);
	busno = PCIXSR_BUSNO(busno);
	if (busno == 0xff)
		busno = 0;

	pci_decompose_tag(pa->pa_pc, pa->pa_intrtag, &b, &d, &f);

	/* No mappings for devices not on our bus. */
	if (b != busno)
		goto no_mapping;

	switch (d) {
	case 4:			/* i82544 Gig-E */
		if (pa->pa_intrpin == 1) {
			*ihp = ICU_INT_XINT(0);
			return (0);
		}
		goto no_mapping;

	case 6:			/* S-PCI-X slot */
		if (pa->pa_intrpin == 1) {
			*ihp = ICU_INT_XINT(2);
			return (0);
		}
		if (pa->pa_intrpin == 2) {
			*ihp = ICU_INT_XINT(3);
			return (0);
		}
		goto no_mapping;

	default:
 no_mapping:
		printf("iq80321_pci_intr_map: no mapping for %d/%d/%d\n",
		    pa->pa_bus, pa->pa_device, pa->pa_function);
		return (1);
	}

	return (0);
}
Beispiel #2
0
extern int
machdep_pci_route_interrupt(device_t pcib, device_t dev, int pin)
{
	int bus;
	int device;
	int func;
	uint32_t busno;
	struct i80321_pci_softc *sc = device_get_softc(pcib);
	bus = pci_get_bus(dev);
	device = pci_get_slot(dev);
	func = pci_get_function(dev);
	busno = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_PCIXSR);
	busno = PCIXSR_BUSNO(busno);
	if (busno == 0xff)
		busno = 0;
	if (bus != busno)
		goto no_mapping;
	switch (device) {
		/* IQ31244 PCI */
	case 1: /* PCIX-PCIX bridge */
		/*
		 * The S-ATA chips are behind the bridge, and all of
		 * the S-ATA interrupts are wired together.
		 */
		return (ICU_INT_XINT(2));
	case 2: /* PCI slot */
		/* All pins are wired together. */
		return (ICU_INT_XINT(3));
	case 3: /* i82546 dual Gig-E */
		if (pin == 1 || pin == 2)
			return (ICU_INT_XINT(0));
		goto no_mapping;
		/* IQ80321 PCI */
	case 4: /* i82544 Gig-E */
	case 8: /*
		 * Apparently you can set the device for the ethernet adapter
		 * to 8 with a jumper, so handle that as well
		 */
		if (pin == 1)
			return (ICU_INT_XINT(0));
		goto no_mapping;
	case 6: /* S-PCI-X slot */
		if (pin == 1)
			return (ICU_INT_XINT(2));
		if (pin == 2)
			return (ICU_INT_XINT(3));
		goto no_mapping;
	default:
no_mapping:
		printf("No mapping for %d/%d/%d/%c\n", bus, device, func, pin);
		
	}
	return (0);

}
Beispiel #3
0
void
i80321_pci_init(pci_chipset_tag_t pc, void *cookie)
{
#if NPCI > 0 && defined(PCI_NETBSD_CONFIGURE)
	struct i80321_softc *sc = cookie;
	struct extent *ioext, *memext;
	uint32_t busno;
#endif

	pc->pc_conf_v = cookie;
	pc->pc_attach_hook = i80321_pci_attach_hook;
	pc->pc_bus_maxdevs = i80321_pci_bus_maxdevs;
	pc->pc_make_tag = i80321_pci_make_tag;
	pc->pc_decompose_tag = i80321_pci_decompose_tag;
	pc->pc_conf_read = i80321_pci_conf_read;
	pc->pc_conf_write = i80321_pci_conf_write;

#if NPCI > 0 && defined(PCI_NETBSD_CONFIGURE)
	/*
	 * Configure the PCI bus.
	 *
	 * XXX We need to revisit this.  We only configure the Secondary
	 * bus (and its children).  The bus configure code needs changes
	 * to support how the busses are arranged on this chip.  We also
	 * need to only configure devices in the private device space on
	 * the Secondary bus.
	 */

	busno = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_PCIXSR);
	busno = PCIXSR_BUSNO(busno);
	if (busno == 0xff)
		busno = 0;

	ioext  = extent_create("pciio",
	    sc->sc_ioout_xlate + sc->sc_ioout_xlate_offset,
	    sc->sc_ioout_xlate + VERDE_OUT_XLATE_IO_WIN_SIZE - 1,
	    M_DEVBUF, NULL, 0, EX_NOWAIT);

#ifdef I80321_USE_DIRECT_WIN
	memext = extent_create("pcimem", VERDE_OUT_DIRECT_WIN_BASE + VERDE_OUT_DIRECT_WIN_SKIP,
	    VERDE_OUT_DIRECT_WIN_BASE + VERDE_OUT_DIRECT_WIN_SIZE- 1,
	    M_DEVBUF, NULL, 0, EX_NOWAIT);
#else
	memext = extent_create("pcimem", sc->sc_owin[0].owin_xlate_lo,
	    sc->sc_owin[0].owin_xlate_lo + VERDE_OUT_XLATE_MEM_WIN_SIZE - 1,
	    M_DEVBUF, NULL, 0, EX_NOWAIT);
#endif

	aprint_normal("%s: configuring PCI bus\n", sc->sc_dev.dv_xname);
	pci_configure_bus(pc, ioext, memext, NULL, busno, arm_dcache_align);

	extent_destroy(ioext);
	extent_destroy(memext);
#endif
}
Beispiel #4
0
int
iq80321_pci_intr_map(const struct pci_attach_args *pa, pci_intr_handle_t *ihp)
{
	struct i80321_softc *sc = pa->pa_pc->pc_intr_v;
	int b, d, f;
	uint32_t busno;

	busno = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_PCIXSR);
	busno = PCIXSR_BUSNO(busno);
	if (busno == 0xff)
		busno = 0;

	pci_decompose_tag(pa->pa_pc, pa->pa_intrtag, &b, &d, &f);

	/* No mappings for devices not on our bus. */
	if (b != busno)
		goto no_mapping;

	switch (d) {
	case 0:			/* i82546EB Dual GigE */
		/*
		 * This is a dual-function chip which uses INTA and INTB,
		 * connected to XINT0 and XINT1 respectively.
		 */
		if (f != 0 && f != 1)
			goto no_mapping;
		*ihp = ICU_INT_XINT(f);
		return (0);

	case 1:			/* i31244 S-ATA Interface */
		*ihp = ICU_INT_XINT(2);
		return (0);

	case 2:			/* Symbios Logic 53c1010 SCSI Controllers */
	case 3:
		/*
		 * Both controllers share a single pin
		 */
		*ihp = ICU_INT_XINT(3);
		return (0);

	default:
 no_mapping:
		printf("iq80321_pci_intr_map: no mapping for %d/%d/%d/%c\n",
		    pa->pa_bus, pa->pa_device, pa->pa_function,
		    '@' + pa->pa_intrpin);
		return (1);
	}

	return (0);
}
Beispiel #5
0
int
iq80321_pci_intr_map(const struct pci_attach_args *pa, pci_intr_handle_t *ihp)
{
	struct i80321_softc *sc = pa->pa_pc->pc_intr_v;
	int b, d, f;
	uint32_t busno;

	busno = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_PCIXSR);
	busno = PCIXSR_BUSNO(busno);
	if (busno == 0xff)
		busno = 0;

	pci_decompose_tag(pa->pa_pc, pa->pa_intrtag, &b, &d, &f);

	/* No mappings for devices not on our bus. */
	if (b != busno)
		goto no_mapping;

	switch (d) {
	case 1:			/* PCIX-PCIX bridge */
		/*
		 * The S-ATA chips are behind the bridge, and all of
		 * the S-ATA interrupts are wired together.
		 */
		*ihp = ICU_INT_XINT(2);
		return (0);

	case 2:			/* PCI slot */
		/* All pins are wired together. */
		*ihp = ICU_INT_XINT(3);
		return (0);

	case 3:			/* i82546 dual Gig-E */
		if (pa->pa_intrpin == 1 || pa->pa_intrpin == 2) {
			*ihp = ICU_INT_XINT(0);
			return (0);
		}
		goto no_mapping;

	default:
 no_mapping:
		printf("iq80321_pci_intr_map: no mapping for %d/%d/%d/%c\n",
		    pa->pa_bus, pa->pa_device, pa->pa_function,
		    '@' + pa->pa_intrpin);
		return (1);
	}

	return (0);
}
int
iyonix_pci_intr_map(const struct pci_attach_args *pa, pci_intr_handle_t *ihp)
{
	struct i80321_softc *sc = pa->pa_pc->pc_intr_v;
	int b, d, f;
	uint32_t busno;

	busno = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_PCIXSR);
	busno = PCIXSR_BUSNO(busno);
	if (busno == 0xff)
		busno = 0;

	pci_decompose_tag(pa->pa_pc, pa->pa_intrtag, &b, &d, &f);

	/* No mappings for devices not on our bus. */
	if (b != busno)
		goto no_mapping;

	/*
	 *  XXX We currently deal only with the southbridge and with
	 *      regular PCI. IOC devices may need further attention.
	 */

	/* Devices on the southbridge are all routed through xint 1 */
	if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_ALI) {
		switch (PCI_PRODUCT(pa->pa_id)) {
			case PCI_PRODUCT_ALI_M1543: /* Southbridge */
			case PCI_PRODUCT_ALI_M5229: /* ATA */
			case PCI_PRODUCT_ALI_M5237: /* ohci */
			case PCI_PRODUCT_ALI_M5257: /* Modem */
			case PCI_PRODUCT_ALI_M5451: /* AC97 */
			case PCI_PRODUCT_ALI_M7101: /* PMC */
				*ihp = ICU_INT_XINT(1);
				return (0);
		}
	}

	/* Route other interrupts with default swizzling rule */
	*ihp = ICU_INT_XINT((d + pa->pa_intrpin - 1) % 4);
	return 0;

 no_mapping:
	printf("iyonix_pci_intr_map: no mapping for %d/%d/%d\n",
	    pa->pa_bus, pa->pa_device, pa->pa_function);
	return (1);
}
Beispiel #7
0
static int
i80321_pci_attach(device_t dev)
{

	uint32_t busno;                                       
	struct i80321_pci_softc *sc = device_get_softc(dev);

	sc->sc_st = i80321_softc->sc_st;
	sc->sc_atu_sh = i80321_softc->sc_atu_sh;
	busno = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_PCIXSR);
	busno = PCIXSR_BUSNO(busno);
	if (busno == 0xff)
		busno = 0;
	sc->sc_dev = dev;
	sc->sc_busno = busno;
	sc->sc_pciio = &i80321_softc->sc_pci_iot;
	sc->sc_pcimem = &i80321_softc->sc_pci_memt;
	sc->sc_mem = i80321_softc->sc_owin[0].owin_xlate_lo +
	    VERDE_OUT_XLATE_MEM_WIN_SIZE;
	
	sc->sc_io = i80321_softc->sc_iow_vaddr;
	/* Initialize memory and i/o rmans. */
	sc->sc_io_rman.rm_type = RMAN_ARRAY;
	sc->sc_io_rman.rm_descr = "I80321 PCI I/O Ports";
	if (rman_init(&sc->sc_io_rman) != 0 ||
		rman_manage_region(&sc->sc_io_rman, 
		sc->sc_io, 
		    sc->sc_io + 
		    VERDE_OUT_XLATE_IO_WIN_SIZE) != 0) {
		panic("i80321_pci_probe: failed to set up I/O rman");
	}
	sc->sc_mem_rman.rm_type = RMAN_ARRAY;
	sc->sc_mem_rman.rm_descr = "I80321 PCI Memory";
	if (rman_init(&sc->sc_mem_rman) != 0 ||
	    rman_manage_region(&sc->sc_mem_rman, 
	    0, VERDE_OUT_XLATE_MEM_WIN_SIZE) != 0) {
		panic("i80321_pci_probe: failed to set up memory rman");
	}
	sc->sc_irq_rman.rm_type = RMAN_ARRAY;
	sc->sc_irq_rman.rm_descr = "i80321 PCI IRQs";
	if (rman_init(&sc->sc_irq_rman) != 0 ||
	    rman_manage_region(&sc->sc_irq_rman, 26, 32) != 0)
		panic("i80321_pci_probe: failed to set up IRQ rman");
	device_add_child(dev, "pci",busno);
	return (bus_generic_attach(dev));
}
Beispiel #8
0
int
iq80321_pci_intr_map(struct pci_attach_args *pa, pci_intr_handle_t *ihp)
{
	struct i80321_softc *sc = pa->pa_pc->pc_intr_v;
	pci_chipset_tag_t pc = pa->pa_pc;
	pcitag_t tag = pa->pa_intrtag;
	int i;

	int b, d, f;
	uint32_t busno;
	uint32_t intr;

	busno = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_PCIXSR);
	busno = PCIXSR_BUSNO(busno);
	if (busno == 0xff)
		busno = 0;

	pci_decompose_tag(pc, tag, &b, &d, &f);

	/* No mappings for devices not on our bus. */
	if (b != busno)
		goto no_mapping;

	for (i = 0; iq80321_irq_map[i].irq != 255; i++) {
		if (d == iq80321_irq_map[i].dev &&
		    pa->pa_intrpin == iq80321_irq_map[i].intrpin) {
			*ihp = iq80321_irq_map[i].irq;
			intr = pci_conf_read(pa->pa_pc, pa->pa_intrtag,
			    PCI_INTERRUPT_REG);
			intr = (intr & ~0xff) | iq80321_irq_map[i].irq;
			pci_conf_write(pa->pa_pc, pa->pa_intrtag,
			    PCI_INTERRUPT_REG, intr);
			return (0);
		}
	}

 no_mapping:
	intr = pci_conf_read(pa->pa_pc, pa->pa_intrtag,
	    PCI_INTERRUPT_REG);

	printf("iq80321_pci_intr_map: no mapping for %d/%d/%d (%d, %d, %d)\n",
	    pa->pa_bus, pa->pa_device, pa->pa_function, d, pa->pa_intrpin, intr);
	return (1);
}
Beispiel #9
0
extern int
machdep_pci_route_interrupt(device_t pcib, device_t dev, int pin)
{
	int bus;
	int device;
	int func;
	uint32_t busno;
	struct i80321_pci_softc *sc = device_get_softc(pcib);
	bus = pci_get_bus(dev);
	device = pci_get_slot(dev);
	func = pci_get_function(dev);
	busno = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_PCIXSR);
	busno = PCIXSR_BUSNO(busno);
	if (busno == 0xff)
		busno = 0;
	if (bus != busno)
		goto no_mapping;
	switch (device) {
		/* EP80219 PCI */
	case 1: /* Ethernet i82555 10/100 */
		printf("Device %d routed to irq %d\n", device, ICU_INT_XINT(0));
		return (ICU_INT_XINT(0));
	case 2: /* UART */
		printf("Device %d routed to irq %d\n", device, ICU_INT_XINT(1));
		return (ICU_INT_XINT(1));
	case 3:
		/*
		 * The S-ATA chips are behind the bridge, and all of
		 * the S-ATA interrupts are wired together.
		 */
		printf("Device %d routed to irq %d\n", device, ICU_INT_XINT(2));
		return (ICU_INT_XINT(2));
	case 4: /* MINI-PIC_INT */
		printf("Device %d routed to irq %d\n", device, ICU_INT_XINT(3));
		return( ICU_INT_XINT(3));
	default:
no_mapping:
		printf("No mapping for %d/%d/%d/%c\n", bus, device, func, pin);
		
	}
	return (0);

}
Beispiel #10
0
static int
i80321_pci_conf_setup(struct i80321_pci_softc *sc, int bus, int slot, int func,
    int reg, uint32_t *addr)
{
	uint32_t busno;

	busno = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_PCIXSR);
	busno = PCIXSR_BUSNO(busno);
	if (busno == 0xff)
		busno = 0;

	/*
	 * If the bus # is the same as our own, then use Type 0 cycles,
	 * else use Type 1.
	 *
	 * XXX We should filter out all non-private devices here!
	 * XXX How does private space interact with PCI-PCI bridges?
	 */
	if (bus == busno) {
		if (slot > (31 - 16))
			return (1);
		/*
		 * NOTE: PCI-X requires that that devices updated their
		 * PCIXSR on every config write with the device number
		 * specified in AD[15:11].  If we don't set this field,
		 * each device could end of thinking it is at device 0,
		 * which can cause a number of problems.  Doing this
		 * unconditionally should be OK when only PCI devices
		 * are present.
		 */
		bus &= 0xff;
		slot &= 0x1f;
		func &= 0x07;
		
		*addr = (1U << (slot + 16)) |
		    (slot << 11) | (func << 8) | reg;
	} else {
		*addr = (bus << 16) | (slot << 11) | (func << 8) | reg | 1;
	}

	return (0);
}
Beispiel #11
0
static int
i80321_pci_conf_setup(struct i80321_softc *sc, pcitag_t tag, int offset,
    struct pciconf_state *ps)
{
	uint32_t busno;

	i80321_pci_decompose_tag(sc, tag, &ps->ps_b, &ps->ps_d, &ps->ps_f);

	busno = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_PCIXSR);
	busno = PCIXSR_BUSNO(busno);
	if (busno == 0xff)
		busno = 0;

	/*
	 * If the bus # is the same as our own, then use Type 0 cycles,
	 * else use Type 1.
	 *
	 * XXX We should filter out all non-private devices here!
	 * XXX How does private space interact with PCI-PCI bridges?
	 */
	if (ps->ps_b == busno) {
		if (ps->ps_d > (31 - 16))
			return (1);
		/*
		 * NOTE: PCI-X requires that devices update their
		 * PCIXSR on every config write with the device number
		 * specified in AD[15:11].  If we don't set this field,
		 * each device could end of thinking it is at device 0,
		 * which can cause a number of problems.  Doing this
		 * unconditionally should be OK when only PCI devices
		 * are present.
		 */
		ps->ps_addr_val = (1U << (ps->ps_d + 16)) |
		    (ps->ps_d << 11) | (ps->ps_f << 8) | offset;
	} else {
		/* The tag is already in the correct format. */
		ps->ps_addr_val = tag | offset | 1;
	}

	return (0);
}
Beispiel #12
0
int
iq80321_attach(device_t dev)
{
	struct i80321_softc *sc = device_get_softc(dev);
	int b0u, b0l, b1u, b1l;
	vm_paddr_t memstart = 0;
	vm_size_t memsize = 0;
	int busno;

	/*
	 * Fill in the space tag for the i80321's own devices,
	 * and hand-craft the space handle for it (the device
	 * was mapped during early bootstrap).
	 */
	i80321_bs_init(&i80321_bs_tag, sc);
	sc->sc_st = &i80321_bs_tag;
	sc->sc_sh = IQ80321_80321_VBASE;
	sc->dev = dev;
	sc->sc_is_host = 1;

	/*
	 * Slice off a subregion for the Memory Controller -- we need it
	 * here in order read the memory size.
	 */
	if (bus_space_subregion(sc->sc_st, sc->sc_sh, VERDE_MCU_BASE,
	    VERDE_MCU_SIZE, &sc->sc_mcu_sh))
		panic("%s: unable to subregion MCU registers",
		    device_get_name(dev));

	if (bus_space_subregion(sc->sc_st, sc->sc_sh, VERDE_ATU_BASE,
	    VERDE_ATU_SIZE, &sc->sc_atu_sh))
		panic("%s: unable to subregion ATU registers",
		    device_get_name(dev));

	/*
	 * We have mapped the PCI I/O windows in the early
	 * bootstrap phase.
	 */
	sc->sc_iow_vaddr = IQ80321_IOW_VBASE;

	/*
	 * Check the configuration of the ATU to see if another BIOS
	 * has configured us.  If a PC BIOS didn't configure us, then:
	 * 	IQ80321: BAR0 00000000.0000000c BAR1 is 00000000.8000000c.
	 * 	IQ31244: BAR0 00000000.00000004 BAR1 is 00000000.0000000c.
	 * If a BIOS has configured us, at least one of those should be
	 * different.  This is pretty fragile, but it's not clear what
	 * would work better.
	 */
	b0l = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, PCIR_BARS+0x0);
	b0u = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, PCIR_BARS+0x4);
	b1l = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, PCIR_BARS+0x8);
	b1u = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, PCIR_BARS+0xc);

#ifdef VERBOSE_INIT_ARM	
	printf("i80321: BAR0 = %08x.%08x BAR1 = %08x.%08x\n",
		   b0l,b0u, b1l, b1u );
#endif

#define PCI_MAPREG_MEM_ADDR_MASK	0xfffffff0
	b0l &= PCI_MAPREG_MEM_ADDR_MASK;
	b0u &= PCI_MAPREG_MEM_ADDR_MASK;
	b1l &= PCI_MAPREG_MEM_ADDR_MASK;
	b1u &= PCI_MAPREG_MEM_ADDR_MASK;

#ifdef VERBOSE_INIT_ARM	
	printf("i80219: BAR0 = %08x.%08x BAR1 = %08x.%08x\n",
		   b0l,b0u, b1l, b1u );
#endif

	if ((b0u != b1u) || (b0l != 0) || ((b1l & ~0x80000000U) != 0))
		sc->sc_is_host = 0;
	else
		sc->sc_is_host = 1;

	/* FIXME: i force it's */	

#ifdef CPU_XSCALE_80219
	sc->sc_is_host = 1;
#endif
	
	i80321_sdram_bounds(sc->sc_st, sc->sc_mcu_sh, &memstart, &memsize);
	/*
	 * We set up the Inbound Windows as follows:
	 *
	 *	0	Access to i80321 PMMRs
	 *
	 *	1	Reserve space for private devices
	 *
	 *	2	RAM access
	 *
	 *	3	Unused.
	 *
	 * This chunk needs to be customized for each IOP321 application.
	 */
#if 0
	sc->sc_iwin[0].iwin_base_lo = VERDE_PMMR_BASE;
	sc->sc_iwin[0].iwin_base_hi = 0;
	sc->sc_iwin[0].iwin_xlate = VERDE_PMMR_BASE;
	sc->sc_iwin[0].iwin_size = VERDE_PMMR_SIZE;
#endif
	if (sc->sc_is_host) {
		
		/* Map PCI:Local 1:1. */
		sc->sc_iwin[1].iwin_base_lo = VERDE_OUT_XLATE_MEM_WIN0_BASE |
		    PCI_MAPREG_MEM_PREFETCHABLE_MASK |
		    PCI_MAPREG_MEM_TYPE_64BIT;
		sc->sc_iwin[1].iwin_base_hi = 0;
	} else {
		
		sc->sc_iwin[1].iwin_base_lo = 0;
		sc->sc_iwin[1].iwin_base_hi = 0;
	}
	sc->sc_iwin[1].iwin_xlate = VERDE_OUT_XLATE_MEM_WIN0_BASE;
	sc->sc_iwin[1].iwin_size = VERDE_OUT_XLATE_MEM_WIN_SIZE;
	
	if (sc->sc_is_host) {
		sc->sc_iwin[2].iwin_base_lo = memstart |
		    PCI_MAPREG_MEM_PREFETCHABLE_MASK |
		    PCI_MAPREG_MEM_TYPE_64BIT;
		sc->sc_iwin[2].iwin_base_hi = 0;
	} else {
		sc->sc_iwin[2].iwin_base_lo = 0;
		sc->sc_iwin[2].iwin_base_hi = 0;
	}
	sc->sc_iwin[2].iwin_xlate = memstart;
	sc->sc_iwin[2].iwin_size = memsize;

	if (sc->sc_is_host) {
		sc->sc_iwin[3].iwin_base_lo = 0 |
		    PCI_MAPREG_MEM_PREFETCHABLE_MASK |
		    PCI_MAPREG_MEM_TYPE_64BIT;
	} else {
		sc->sc_iwin[3].iwin_base_lo = 0;
	}
	sc->sc_iwin[3].iwin_base_hi = 0;
	sc->sc_iwin[3].iwin_xlate = 0;
	sc->sc_iwin[3].iwin_size = 0;
	
#ifdef 	VERBOSE_INIT_ARM
	printf("i80321: Reserve space for private devices (Inbound Window 1) \n hi:0x%08x lo:0x%08x xlate:0x%08x size:0x%08x\n",
		   sc->sc_iwin[1].iwin_base_hi,
		   sc->sc_iwin[1].iwin_base_lo,
		   sc->sc_iwin[1].iwin_xlate,
		   sc->sc_iwin[1].iwin_size
		);
	printf("i80321: RAM access (Inbound Window 2) \n hi:0x%08x lo:0x%08x xlate:0x%08x size:0x%08x\n",
		   sc->sc_iwin[2].iwin_base_hi,
		   sc->sc_iwin[2].iwin_base_lo,
		   sc->sc_iwin[2].iwin_xlate,
		   sc->sc_iwin[2].iwin_size
		);
#endif

	/*
	 * We set up the Outbound Windows as follows:
	 *
	 *	0	Access to private PCI space.
	 *
	 *	1	Unused.
	 */
#define PCI_MAPREG_MEM_ADDR(x) ((x) & 0xfffffff0)
	sc->sc_owin[0].owin_xlate_lo =
    	    PCI_MAPREG_MEM_ADDR(sc->sc_iwin[1].iwin_base_lo);
	sc->sc_owin[0].owin_xlate_hi = sc->sc_iwin[1].iwin_base_hi;
	/*
	 * Set the Secondary Outbound I/O window to map
	 * to PCI address 0 for all 64K of the I/O space.
	 */
	sc->sc_ioout_xlate = 0;
	i80321_attach(sc);
	i80321_dr.dr_sysbase = sc->sc_iwin[2].iwin_xlate;
	i80321_dr.dr_busbase = PCI_MAPREG_MEM_ADDR(sc->sc_iwin[2].iwin_base_lo);
	i80321_dr.dr_len = sc->sc_iwin[2].iwin_size;
	dma_range_init = 1;
	busno = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_PCIXSR);
	busno = PCIXSR_BUSNO(busno);
	if (busno == 0xff)
		busno = 0;
	sc->sc_irq_rman.rm_type = RMAN_ARRAY;
	sc->sc_irq_rman.rm_descr = "i80321 IRQs";
	if (rman_init(&sc->sc_irq_rman) != 0 ||
	    rman_manage_region(&sc->sc_irq_rman, 0, 25) != 0)
		panic("i80321_attach: failed to set up IRQ rman");

	device_add_child(dev, "obio", 0);
	device_add_child(dev, "itimer", 0);
	device_add_child(dev, "iopwdog", 0);
#ifndef 	CPU_XSCALE_80219
	device_add_child(dev, "iqseg", 0);
#endif	
	device_add_child(dev, "pcib", busno);
	device_add_child(dev, "i80321_dma", 0);
	device_add_child(dev, "i80321_dma", 1);
#ifndef CPU_XSCALE_80219	
	device_add_child(dev, "i80321_aau", 0);
#endif
	bus_generic_probe(dev);
	bus_generic_attach(dev);

	return (0);
}
Beispiel #13
0
/*
 * i80321_attach:
 *
 *	Board-independent attach routine for the i80321.
 */
void
i80321_attach(struct i80321_softc *sc)
{
	struct pcibus_attach_args pba;
	pcireg_t preg;

	i80321_softc = sc;

	/*
	 * Slice off some useful subregion handles.
	 */

	if (bus_space_subregion(sc->sc_st, sc->sc_sh, VERDE_ATU_BASE,
	    VERDE_ATU_SIZE, &sc->sc_atu_sh))
		panic("%s: unable to subregion ATU registers\n",
		    sc->sc_dev.dv_xname);

	/* We expect the Memory Controller to be already sliced off. */

	/*
	 * Program the Inbound windows.
	 */
	if (sc->sc_is_host) {
		bus_space_write_4(sc->sc_st, sc->sc_atu_sh,
		    PCI_MAPREG_START, sc->sc_iwin[0].iwin_base_lo);
		bus_space_write_4(sc->sc_st, sc->sc_atu_sh,
		    PCI_MAPREG_START + 0x04, sc->sc_iwin[0].iwin_base_hi);
	}
	bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IALR0,
	    (0xffffffff - (sc->sc_iwin[0].iwin_size - 1)) & 0xffffffc0);
	bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IATVR0,
	    sc->sc_iwin[0].iwin_xlate);

	if (sc->sc_is_host) {
		bus_space_write_4(sc->sc_st, sc->sc_atu_sh,
		    PCI_MAPREG_START + 0x08, sc->sc_iwin[1].iwin_base_lo);
		bus_space_write_4(sc->sc_st, sc->sc_atu_sh,
		    PCI_MAPREG_START + 0x0c, sc->sc_iwin[1].iwin_base_hi);
	}
	bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IALR1,
	    (0xffffffff - (sc->sc_iwin[1].iwin_size - 1)) & 0xffffffc0);
	/* no xlate for window 1 */

	if (sc->sc_is_host) {
		bus_space_write_4(sc->sc_st, sc->sc_atu_sh,
		    PCI_MAPREG_START + 0x10, sc->sc_iwin[2].iwin_base_lo);
		bus_space_write_4(sc->sc_st, sc->sc_atu_sh,
		    PCI_MAPREG_START + 0x14, sc->sc_iwin[2].iwin_base_hi);
	}
	bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IALR2,
	    (0xffffffff - (sc->sc_iwin[2].iwin_size - 1)) & 0xffffffc0);
	bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IATVR2,
	    sc->sc_iwin[2].iwin_xlate);

	if (sc->sc_is_host) {
		bus_space_write_4(sc->sc_st, sc->sc_atu_sh,
		    ATU_IABAR3, sc->sc_iwin[3].iwin_base_lo);
		bus_space_write_4(sc->sc_st, sc->sc_atu_sh,
		    ATU_IAUBAR3, sc->sc_iwin[3].iwin_base_hi);
	}
	bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IALR3,
	    (0xffffffff - (sc->sc_iwin[3].iwin_size - 1)) & 0xffffffc0);
	bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IATVR3,
	    sc->sc_iwin[3].iwin_xlate);

	/*
	 * Mask (disable) the ATU interrupt sources.
	 * XXX May want to revisit this if we encounter
	 * XXX an application that wants it.
	 */
	bus_space_write_4(sc->sc_st, sc->sc_atu_sh,
	    ATU_ATUIMR,
	    ATUIMR_IMW1BU|ATUIMR_ISCEM|ATUIMR_RSCEM|ATUIMR_PST|
	    ATUIMR_DPE|ATUIMR_P_SERR_ASRT|ATUIMR_PMA|ATUIMR_PTAM|
	    ATUIMR_PTAT|ATUIMR_PMPE);

	/*
	 * Program the outbound windows.
	 */
	bus_space_write_4(sc->sc_st, sc->sc_atu_sh,
	    ATU_OIOWTVR, sc->sc_ioout_xlate);

	bus_space_write_4(sc->sc_st, sc->sc_atu_sh,
	    ATU_OMWTVR0, sc->sc_owin[0].owin_xlate_lo);
	bus_space_write_4(sc->sc_st, sc->sc_atu_sh,
	    ATU_OUMWTVR0, sc->sc_owin[0].owin_xlate_hi);

	bus_space_write_4(sc->sc_st, sc->sc_atu_sh,
	    ATU_OMWTVR1, sc->sc_owin[1].owin_xlate_lo);
	bus_space_write_4(sc->sc_st, sc->sc_atu_sh,
	    ATU_OUMWTVR1, sc->sc_owin[1].owin_xlate_hi);

	/*
	 * Set up the ATU configuration register.  All we do
	 * right now is enable Outbound Windows.
	 */
	bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_ATUCR,
	    ATUCR_OUT_EN);

	/*
	 * Enable bus mastering, memory access, SERR, and parity
	 * checking on the ATU.
	 */
	if (sc->sc_is_host) {
		preg = bus_space_read_4(sc->sc_st, sc->sc_atu_sh,
		    PCI_COMMAND_STATUS_REG);
		preg |= PCI_COMMAND_MEM_ENABLE | PCI_COMMAND_MASTER_ENABLE |
		    PCI_COMMAND_PARITY_ENABLE | PCI_COMMAND_SERR_ENABLE;
		bus_space_write_4(sc->sc_st, sc->sc_atu_sh,
		    PCI_COMMAND_STATUS_REG, preg);
	}

	/*
	 * Initialize the bus space and DMA tags and the PCI chipset tag.
	 */
	i80321_io_bs_init(&sc->sc_pci_iot, sc);
	i80321_mem_bs_init(&sc->sc_pci_memt, sc);
	i80321_pci_dma_init(&sc->sc_pci_dmat, sc);
	i80321_pci_init(&sc->sc_pci_chipset, sc);

	/*
	 * Attach the PCI bus.
	 */
	preg = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_PCIXSR);
	preg = PCIXSR_BUSNO(preg);
	if (preg == 0xff)
		preg = 0;
	pba.pba_busname = "pci";
	pba.pba_iot = &sc->sc_pci_iot;
	pba.pba_memt = &sc->sc_pci_memt;
	pba.pba_dmat = &sc->sc_pci_dmat;
	pba.pba_pc = &sc->sc_pci_chipset;
	pba.pba_bus = preg;
	pba.pba_bridgetag = NULL;
	pba.pba_intrswiz = 0;	/* XXX what if busno != 0? */
	pba.pba_intrtag = 0;
	pba.pba_flags = PCI_FLAGS_IO_ENABLED | PCI_FLAGS_MEM_ENABLED |
	    PCI_FLAGS_MRL_OKAY | PCI_FLAGS_MRM_OKAY | PCI_FLAGS_MWI_OKAY;
	(void) config_found(&sc->sc_dev, &pba, i80321_pcibus_print);
}
Beispiel #14
0
int
hdlg_pci_intr_map(struct pci_attach_args *pa, pci_intr_handle_t *ihp)
{
	struct i80321_softc *sc = pa->pa_pc->pc_intr_v;
	uint32_t busno;
	int b, d, f;

	/*
	 * GigaLANDISK's interrupts are routed like so:
	 *
	 *	XINT0	Intel i82541PI Gig-E
	 *
	 *	XINT1	ACARD ATP875-A
	 *
	 *	XINT2	NEC echi/ochi
	 *
	 *	XINT3	UART
	 */

	busno = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_PCIXSR);
	busno = PCIXSR_BUSNO(busno);
	if (busno == 0xff)
		busno = 0;

	pci_decompose_tag(pa->pa_pc, pa->pa_intrtag, &b, &d, &f);

	/* No mappings for devices not on our bus. */
	if (b != busno)
		goto no_mapping;

	switch (d) {
	case 1:			/* i82541PI Gig-E */
		if (pa->pa_intrpin == 1) {
			*ihp = ICU_INT_XINT(0);
			return 0;
		}
		goto no_mapping;

	case 2:			/* ATP875-A */
		if (pa->pa_intrpin == 1) {
			*ihp = ICU_INT_XINT(1);
			return 0;
		}
		goto no_mapping;

	case 3:			/* echi/ochi */
		switch (pa->pa_intrpin) {
		case 1:	/* ohci */
		case 2:	/* ohci */
		case 3:	/* ehci */
			*ihp = ICU_INT_XINT(2);
			return 0;
		}
		goto no_mapping;

	default:
 no_mapping:
		printf("hdlg_pci_intr_map: no mapping for %d/%d/%d\n",
		    pa->pa_bus, pa->pa_device, pa->pa_function);
		return 1;
	}

	return 0;
}
Beispiel #15
0
/*
 * i80321_attach:
 *
 *	Board-independent attach routine for the i80321.
 */
void
i80321_attach(struct i80321_softc *sc)
{
	struct pcibus_attach_args pba;
	const struct iopxs_device *id;
	struct iopxs_attach_args ia;
	pcireg_t preg;

	i80321_softc = sc;

	/*
	 * Program the Inbound windows.
	 */
	bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IALR0,
	    (0xffffffff - (sc->sc_iwin[0].iwin_size - 1)) & 0xffffffc0);
	bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IATVR0,
	    sc->sc_iwin[0].iwin_xlate);

	bus_space_write_4(sc->sc_st, sc->sc_atu_sh,
	    PCI_MAPREG_START, sc->sc_iwin[0].iwin_base_lo);
	bus_space_write_4(sc->sc_st, sc->sc_atu_sh,
	    PCI_MAPREG_START + 0x04, sc->sc_iwin[0].iwin_base_hi);

	bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IALR1,
	    (0xffffffff - (sc->sc_iwin[1].iwin_size - 1)) & 0xffffffc0);
	/* no xlate for window 1 */

	bus_space_write_4(sc->sc_st, sc->sc_atu_sh,
	    PCI_MAPREG_START + 0x08, sc->sc_iwin[1].iwin_base_lo);
	bus_space_write_4(sc->sc_st, sc->sc_atu_sh,
	    PCI_MAPREG_START + 0x0c, sc->sc_iwin[1].iwin_base_hi);

	bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IALR2,
	    (0xffffffff - (sc->sc_iwin[2].iwin_size - 1)) & 0xffffffc0);
	bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IATVR2,
	    sc->sc_iwin[2].iwin_xlate);

	bus_space_write_4(sc->sc_st, sc->sc_atu_sh,
	    PCI_MAPREG_START + 0x10, sc->sc_iwin[2].iwin_base_lo);
	bus_space_write_4(sc->sc_st, sc->sc_atu_sh,
	    PCI_MAPREG_START + 0x14, sc->sc_iwin[2].iwin_base_hi);

	bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IALR3,
	    (0xffffffff - (sc->sc_iwin[3].iwin_size - 1)) & 0xffffffc0);
	bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IATVR3,
	    sc->sc_iwin[3].iwin_xlate);

	bus_space_write_4(sc->sc_st, sc->sc_atu_sh,
	    ATU_IABAR3, sc->sc_iwin[3].iwin_base_lo);
	bus_space_write_4(sc->sc_st, sc->sc_atu_sh,
	    ATU_IAUBAR3, sc->sc_iwin[3].iwin_base_hi);

	/*
	 * Mask (disable) the ATU interrupt sources.
	 * XXX May want to revisit this if we encounter
	 * XXX an application that wants it.
	 */
	bus_space_write_4(sc->sc_st, sc->sc_atu_sh,
	    ATU_ATUIMR,
	    ATUIMR_IMW1BU|ATUIMR_ISCEM|ATUIMR_RSCEM|ATUIMR_PST|
	    ATUIMR_DPE|ATUIMR_P_SERR_ASRT|ATUIMR_PMA|ATUIMR_PTAM|
	    ATUIMR_PTAT|ATUIMR_PMPE);

	/*
	 * Program the outbound windows.
	 */
	bus_space_write_4(sc->sc_st, sc->sc_atu_sh,
	    ATU_OIOWTVR, sc->sc_ioout_xlate);

	bus_space_write_4(sc->sc_st, sc->sc_atu_sh,
	    ATU_OMWTVR0, sc->sc_owin[0].owin_xlate_lo);
	bus_space_write_4(sc->sc_st, sc->sc_atu_sh,
	    ATU_OUMWTVR0, sc->sc_owin[0].owin_xlate_hi);

	bus_space_write_4(sc->sc_st, sc->sc_atu_sh,
	    ATU_OMWTVR1, sc->sc_owin[1].owin_xlate_lo);
	bus_space_write_4(sc->sc_st, sc->sc_atu_sh,
	    ATU_OUMWTVR1, sc->sc_owin[1].owin_xlate_hi);

	/*
	 * Set up the ATU configuration register.  All we do
	 * right now is enable Outbound Windows.
	 */
	bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_ATUCR,
	    ATUCR_OUT_EN);

	/*
	 * Enable bus mastering, memory access, SERR, and parity
	 * checking on the ATU.
	 */
	preg = bus_space_read_4(sc->sc_st, sc->sc_atu_sh,
	    PCI_COMMAND_STATUS_REG);
	preg |= PCI_COMMAND_MEM_ENABLE | PCI_COMMAND_MASTER_ENABLE |
	    PCI_COMMAND_PARITY_ENABLE | PCI_COMMAND_SERR_ENABLE;
	bus_space_write_4(sc->sc_st, sc->sc_atu_sh,
	    PCI_COMMAND_STATUS_REG, preg);

	/* Initialize the bus space tags. */
	i80321_io_bs_init(&sc->sc_pci_iot, sc);
	i80321_mem_bs_init(&sc->sc_pci_memt, sc);

	/* Initialize the DMA tags. */
	i80321_pci_dma_init(sc);
	i80321_local_dma_init(sc);

	/*
	 * Attach all the IOP built-ins.
	 */
	for (id = iopxs_devices; id->id_name != NULL; id++) {
		ia.ia_name = id->id_name;
		ia.ia_st = sc->sc_st;
		ia.ia_sh = sc->sc_sh;
		ia.ia_dmat = &sc->sc_local_dmat;
		ia.ia_offset = id->id_offset;
		ia.ia_size = id->id_size;

		config_found(&sc->sc_dev, &ia, i80321_iopxs_print);
	}

	/*
	 * Attach the PCI bus.
	 */
	preg = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_PCIXSR);
	preg = PCIXSR_BUSNO(preg);
	if (preg == 0xff)
		preg = 0;
	pba.pba_busname = "pci";
	pba.pba_iot = &sc->sc_pci_iot;
	pba.pba_memt = &sc->sc_pci_memt;
	pba.pba_dmat = &sc->sc_pci_dmat;
	pba.pba_pc = &sc->sc_pci_chipset;
	pba.pba_domain = pci_ndomains++;
	pba.pba_bus = preg;
	pba.pba_bridgetag = NULL;
	pba.pba_intrswiz = 0;	/* XXX what if busno != 0? */
	pba.pba_intrtag = 0;

	config_found((struct device *)sc, &pba, i80321_iopxs_print);
}