예제 #1
0
파일: pci.c 프로젝트: CZ-NIC/u-boot-turris
unsigned int x86_pci_read_config8(pci_dev_t dev, unsigned where)
{
	uint8_t value;

	pci_hose_read_config_byte(get_hose(), dev, where, &value);

	return value;
}
static void pci_enet_fixup_irq(struct pci_controller *hose, pci_dev_t dev)
{
	/* a configurable lists of IRQs to steal when we need one */
	static int irq_list[] = {
		CONFIG_SYS_FIRST_PCI_IRQ,
		CONFIG_SYS_SECOND_PCI_IRQ,
		CONFIG_SYS_THIRD_PCI_IRQ,
		CONFIG_SYS_FORTH_PCI_IRQ
	};
	static int next_irq_index=0;

	uchar tmp_pin;
	int pin;

	pci_hose_read_config_byte(hose, dev, PCI_INTERRUPT_PIN, &tmp_pin);
	pin = tmp_pin;

	pin -= 1; /* PCI config space use 1-based numbering */
	if (pin == -1) {
		return; /* device use no irq */
	}

	/* map device number +  pin to a pin on the sc520 */
	switch (PCI_DEV(dev)) {
	case 12:	/* First Ethernet Chip */
		pin += SC520_PCI_INTA;
		break;

	case 13:	/* Second Ethernet Chip */
		pin += SC520_PCI_INTB;
		break;

	default:
		return;
	}

	pin &= 3; /* wrap around */

	if (sc520_pci_ints[pin] == -1) {
		/* re-route one interrupt for us */
		if (next_irq_index > 3) {
			return;
		}
		if (pci_sc520_set_irq(pin, irq_list[next_irq_index])) {
			return;
		}
		next_irq_index++;
	}

	if (-1 != sc520_pci_ints[pin]) {
	pci_hose_write_config_byte(hose, dev, PCI_INTERRUPT_LINE,
					   sc520_pci_ints[pin]);
	}
	printf("fixup_irq: device %d pin %c irq %d\n",
	       PCI_DEV(dev), 'A' + pin, sc520_pci_ints[pin]);
}
예제 #3
0
static void pci_pip405_fixup_irq(struct pci_controller *hose, pci_dev_t dev)
{
	unsigned char int_line = 0xff;
	unsigned char pin;
	/*
	 * Write pci interrupt line register
	 */
	if(PCI_DEV(dev)==0) /* Device0 = PPC405 -> skip */
		return;
	pci_hose_read_config_byte(hose, dev, PCI_INTERRUPT_PIN, &pin);
	if ((pin == 0) || (pin > 4))
	    return;

	int_line = ((PCI_DEV(dev) + (pin-1) + 10) % 4) + 28;
	pci_hose_write_config_byte(hose, dev, PCI_INTERRUPT_LINE, int_line);
#ifdef DEBUG
	printf("Fixup IRQ: dev %d (%x) int line %d 0x%x\n",
	       PCI_DEV(dev),dev,int_line,int_line);
#endif
}
예제 #4
0
파일: pci.c 프로젝트: OpenNoah/u-boot
int pci_hose_config_device(struct pci_controller *hose,
			   pci_dev_t dev,
			   unsigned long io,
			   pci_addr_t mem,
			   unsigned long command)
{
	u32 bar_response;
	unsigned int old_command;
	pci_addr_t bar_value;
	pci_size_t bar_size;
	unsigned char pin;
	int bar, found_mem64;

	debug("PCI Config: I/O=0x%lx, Memory=0x%llx, Command=0x%lx\n", io,
		(u64)mem, command);

	pci_hose_write_config_dword(hose, dev, PCI_COMMAND, 0);

	for (bar = PCI_BASE_ADDRESS_0; bar <= PCI_BASE_ADDRESS_5; bar += 4) {
		pci_hose_write_config_dword(hose, dev, bar, 0xffffffff);
		pci_hose_read_config_dword(hose, dev, bar, &bar_response);

		if (!bar_response)
			continue;

		found_mem64 = 0;

		/* Check the BAR type and set our address mask */
		if (bar_response & PCI_BASE_ADDRESS_SPACE) {
			bar_size = ~(bar_response & PCI_BASE_ADDRESS_IO_MASK) + 1;
			/* round up region base address to a multiple of size */
			io = ((io - 1) | (bar_size - 1)) + 1;
			bar_value = io;
			/* compute new region base address */
			io = io + bar_size;
		} else {
			if ((bar_response & PCI_BASE_ADDRESS_MEM_TYPE_MASK) ==
				PCI_BASE_ADDRESS_MEM_TYPE_64) {
				u32 bar_response_upper;
				u64 bar64;
				pci_hose_write_config_dword(hose, dev, bar + 4,
					0xffffffff);
				pci_hose_read_config_dword(hose, dev, bar + 4,
					&bar_response_upper);

				bar64 = ((u64)bar_response_upper << 32) | bar_response;

				bar_size = ~(bar64 & PCI_BASE_ADDRESS_MEM_MASK) + 1;
				found_mem64 = 1;
			} else {
				bar_size = (u32)(~(bar_response & PCI_BASE_ADDRESS_MEM_MASK) + 1);
			}

			/* round up region base address to multiple of size */
			mem = ((mem - 1) | (bar_size - 1)) + 1;
			bar_value = mem;
			/* compute new region base address */
			mem = mem + bar_size;
		}

		/* Write it out and update our limit */
		pci_hose_write_config_dword (hose, dev, bar, (u32)bar_value);

		if (found_mem64) {
			bar += 4;
#ifdef CONFIG_SYS_PCI_64BIT
			pci_hose_write_config_dword(hose, dev, bar,
				(u32)(bar_value >> 32));
#else
			pci_hose_write_config_dword(hose, dev, bar, 0x00000000);
#endif
		}
	}

	/* Configure Cache Line Size Register */
	pci_hose_write_config_byte(hose, dev, PCI_CACHE_LINE_SIZE, 0x08);

	/* Configure Latency Timer */
	pci_hose_write_config_byte(hose, dev, PCI_LATENCY_TIMER, 0x80);

	/* Disable interrupt line, if device says it wants to use interrupts */
	pci_hose_read_config_byte(hose, dev, PCI_INTERRUPT_PIN, &pin);
	if (pin != 0) {
		pci_hose_write_config_byte(hose, dev, PCI_INTERRUPT_LINE,
					   PCI_INTERRUPT_LINE_DISABLE);
	}

	pci_hose_read_config_dword(hose, dev, PCI_COMMAND, &old_command);
	pci_hose_write_config_dword(hose, dev, PCI_COMMAND,
				     (old_command & 0xffff0000) | command);

	return 0;
}
예제 #5
0
/* HJF: Changed this to return int. I think this is required
 * to get the correct result when scanning bridges
 */
int pciauto_config_device(struct pci_controller *hose, pci_dev_t dev)
{
	unsigned int sub_bus = PCI_BUS(dev);
	unsigned short class;
	unsigned char prg_iface;
	int n;

	pci_hose_read_config_word(hose, dev, PCI_CLASS_DEVICE, &class);

	switch(class) {
	case PCI_CLASS_BRIDGE_PCI:
		hose->current_busno++;
		pciauto_setup_device(hose, dev, 2, hose->pci_mem, hose->pci_io);

		DEBUGF("PCI Autoconfig: Found P2P bridge, device %d\n", PCI_DEV(dev));

		/* Passing in current_busno allows for sibling P2P bridges */
		pciauto_prescan_setup_bridge(hose, dev, hose->current_busno);
		/*
		 * need to figure out if this is a subordinate bridge on the bus
		 * to be able to properly set the pri/sec/sub bridge registers.
		 */
		n = pci_hose_scan_bus(hose, hose->current_busno);

		/* figure out the deepest we've gone for this leg */
		sub_bus = max(n, sub_bus);
		pciauto_postscan_setup_bridge(hose, dev, sub_bus);

		sub_bus = hose->current_busno;
		break;

	case PCI_CLASS_STORAGE_IDE:
		pci_hose_read_config_byte(hose, dev, PCI_CLASS_PROG, &prg_iface);
		if (!(prg_iface & PCIAUTO_IDE_MODE_MASK)) {
			DEBUGF("PCI Autoconfig: Skipping legacy mode IDE controller\n");
			return sub_bus;
		}

		pciauto_setup_device(hose, dev, 6, hose->pci_mem, hose->pci_io);
		break;

	case PCI_CLASS_BRIDGE_CARDBUS:
		/* just do a minimal setup of the bridge, let the OS take care of the rest */
		pciauto_setup_device(hose, dev, 0, hose->pci_mem, hose->pci_io);

		DEBUGF("PCI Autoconfig: Found P2CardBus bridge, device %d\n", PCI_DEV(dev));

		hose->current_busno++;
		break;

#ifdef CONFIG_MPC5200
	case PCI_CLASS_BRIDGE_OTHER:
		DEBUGF("PCI Autoconfig: Skipping bridge device %d\n",
		       PCI_DEV(dev));
		break;
#endif

	default:
		pciauto_setup_device(hose, dev, 6, hose->pci_mem, hose->pci_io);
		break;
	}

	return sub_bus;
}
예제 #6
0
static void pci_bus_scan(struct ftpci100_data *priv)
{
	struct pci_controller *hose = (struct pci_controller *)&local_hose;
	unsigned int bus, dev, func;
	pci_dev_t dev_nu;
	unsigned int data32;
	unsigned int tmp;
	unsigned char header;
	unsigned char int_pin;
	unsigned int niobars;
	unsigned int nmbars;

	priv->ndevs = 1;

	nmbars = 0;
	niobars = 0;

	for (bus = 0; bus < MAX_BUS_NUM; bus++)
		for (dev = 0; dev < MAX_DEV_NUM; dev++)
			for (func = 0; func < MAX_FUN_NUM; func++) {
				dev_nu = PCI_BDF(bus, dev, func);
				pci_hose_read_config_dword(hose, dev_nu,
							PCI_VENDOR_ID, &data32);

				/*
				 * some broken boards return 0 or ~0,
				 * if a slot is empty.
				 */
				if (data32 == 0xffffffff ||
					data32 == 0x00000000 ||
					data32 == 0x0000ffff ||
					data32 == 0xffff0000)
					continue;

				pci_hose_read_config_dword(hose, dev_nu,
							PCI_HEADER_TYPE, &tmp);
				header = (unsigned char)tmp;
				setup_pci_bar(bus, dev, func, header, priv);

				devs[priv->ndevs].v_id = (u16)(data32 & \
								0x0000ffff);

				devs[priv->ndevs].d_id = (u16)((data32 & \
							0xffff0000) >> 16);

				/* Figure out what INTX# line the card uses */
				pci_hose_read_config_byte(hose, dev_nu,
						PCI_INTERRUPT_PIN, &int_pin);

				/* assign the appropriate irq line */
				if (int_pin > PCI_IRQ_LINES) {
					printf("more irq lines than expect\n");
				} else if (int_pin != 0) {
					/* This device uses an interrupt line */
					devs[priv->ndevs].pin = int_pin;
				}

				pci_hose_read_config_dword(hose, dev_nu,
						PCI_CLASS_DEVICE, &data32);

				debug("%06d  %03d  %03d  " \
					"%04d  %08x  %08x  " \
					"%03d  %08x  %06d  %08x\n",
					priv->ndevs, devs[priv->ndevs].bus,
					devs[priv->ndevs].dev,
					devs[priv->ndevs].func,
					devs[priv->ndevs].d_id,
					devs[priv->ndevs].v_id,
					devs[priv->ndevs].pin,
					devs[priv->ndevs].bar[0].addr,
					devs[priv->ndevs].bar[0].size,
					data32 >> 8);

				priv->ndevs++;
			}
}
예제 #7
0
void
pci_mpc85xx_init(struct pci_controller *hose)
{
	volatile immap_t    *immap = (immap_t *)CFG_CCSRBAR;
	volatile ccsr_pcix_t *pcix = &immap->im_pcix;

	u16 reg16;

	hose->first_busno = 0;
	hose->last_busno = 0xff;

	pci_set_region(hose->regions + 0,
		       CFG_PCI1_MEM_BASE,
		       CFG_PCI1_MEM_PHYS,
		       CFG_PCI1_MEM_SIZE,
		       PCI_REGION_MEM);

	pci_set_region(hose->regions + 1,
		       CFG_PCI1_IO_BASE,
		       CFG_PCI1_IO_PHYS,
		       CFG_PCI1_IO_SIZE,
		       PCI_REGION_IO);

	hose->region_count = 2;

	pci_setup_indirect(hose,
			   (CFG_IMMR+0x8000),
			   (CFG_IMMR+0x8004));

	pcix->potar1   = (CFG_PCI1_MEM_BASE >> 12) & 0x000fffff;
	pcix->potear1  = 0x00000000;
	pcix->powbar1  = (CFG_PCI1_MEM_BASE >> 12) & 0x000fffff;
	pcix->powbear1 = 0x00000000;
	pcix->powar1   = 0x8004401c;	/* 512M MEM space */

	pcix->potar2   = 0x00000000;
	pcix->potear2  = 0x00000000;
	pcix->powbar2  = (CFG_PCI1_IO_BASE >> 12) & 0x000fffff;
	pcix->powbear2 = 0x00000000;
	pcix->powar2   = 0x80088017;	/* 16M IO space */

	pcix->pitar1 = 0x00000000;
	pcix->piwbar1 = 0x00000000;
	pcix->piwar1 = 0xa0f5501e;	/* Enable, Prefetch, Local Mem,
					 * Snoop R/W, 2G */

	/*
	 * Hose scan.
	 */
	pci_register_hose(hose);

	pci_read_config_word (PCI_BDF(0,0,0), PCI_COMMAND, &reg16);
	reg16 |= PCI_COMMAND_SERR | PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
	pci_write_config_word(PCI_BDF(0,0,0), PCI_COMMAND, reg16);

	/*
	 * Clear non-reserved bits in status register.
	 */
	pci_write_config_word(PCI_BDF(0,0,0), PCI_STATUS, 0xffff);
	pci_write_config_byte(PCI_BDF(0,0,0), PCI_LATENCY_TIMER,0x80);

#if defined(CONFIG_MPC8555CDS) || defined(CONFIG_MPC8541CDS)
	/*
	 * This is a SW workaround for an apparent HW problem
	 * in the PCI controller on the MPC85555/41 CDS boards.
	 * The first config cycle must be to a valid, known
	 * device on the PCI bus in order to trick the PCI
	 * controller state machine into a known valid state.
	 * Without this, the first config cycle has the chance
	 * of hanging the controller permanently, just leaving
	 * it in a semi-working state, or leaving it working.
	 *
	 * Pick on the Tundra, Device 17, to get it right.
	 */
	{
		u8 header_type;

		pci_hose_read_config_byte(hose,
					  PCI_BDF(0,17,0),
					  PCI_HEADER_TYPE,
					  &header_type);
	}
#endif

	hose->last_busno = pci_hose_scan(hose);
}