Esempio n. 1
0
int set_ddr_laws(u64 start, u64 sz, enum law_trgt_if id)
{
	immap_t *immap = (immap_t *)CONFIG_SYS_IMMR;
	law83xx_t *ecm = &immap->sysconf.ddrlaw[0];
	u64 start_align, law_sz;
	int law_sz_enc;

	if (start == 0)
		start_align = 1ull << (LAW_SIZE_2G + 1);
	else
		start_align = 1ull << (ffs64(start) - 1);
	law_sz = min(start_align, sz);
	law_sz_enc = __ilog2_u64(law_sz) - 1;

	/*
	 * Set up LAWBAR for all of DDR.
	 */
	ecm->bar = start & 0xfffff000;
	ecm->ar  = (LAWAR_EN | (id << 20) | (LAWAR_SIZE & law_sz_enc));
	debug("DDR:bar=0x%08x\n", ecm->bar);
	debug("DDR:ar=0x%08x\n", ecm->ar);

	/* recalculate size based on what was actually covered by the law */
	law_sz = 1ull << __ilog2_u64(law_sz);

	/* do we still have anything to map */
	sz = sz - law_sz;
	if (sz) {
		start += law_sz;

		start_align = 1ull << (ffs64(start) - 1);
		law_sz = min(start_align, sz);
		law_sz_enc = __ilog2_u64(law_sz) - 1;
		ecm = &immap->sysconf.ddrlaw[1];
		ecm->bar = start & 0xfffff000;
		ecm->ar  = (LAWAR_EN | (id << 20) | (LAWAR_SIZE & law_sz_enc));
		debug("DDR:bar=0x%08x\n", ecm->bar);
		debug("DDR:ar=0x%08x\n", ecm->ar);
	} else {
		return 0;
	}

	/* do we still have anything to map */
	sz = sz - law_sz;
	if (sz)
		return 1;

	return 0;
}
void fsl_pci_init(struct pci_controller *hose, u32 cfg_addr, u32 cfg_data)
{
	u16 temp16;
	u32 temp32;
	int enabled, r, inbound = 0;
	u16 ltssm;
	u8 temp8, pcie_cap;
	volatile ccsr_fsl_pci_t *pci = (ccsr_fsl_pci_t *)cfg_addr;
	struct pci_region *reg = hose->regions + hose->region_count;
	pci_dev_t dev = PCI_BDF(hose->first_busno, 0, 0);

	/* Initialize ATMU registers based on hose regions and flags */
	volatile pot_t *po = &pci->pot[1];	/* skip 0 */
	volatile pit_t *pi = &pci->pit[2];	/* ranges from: 3 to 1 */

	u64 out_hi = 0, out_lo = -1ULL;
	u32 pcicsrbar, pcicsrbar_sz;

#ifdef DEBUG
	int neg_link_w;
#endif

	pci_setup_indirect(hose, cfg_addr, cfg_data);

	/* Handle setup of outbound windows first */
	for (r = 0; r < hose->region_count; r++) {
		unsigned long flags = hose->regions[r].flags;
		u32 sz = (__ilog2_u64((u64)hose->regions[r].size) - 1);

		flags &= PCI_REGION_SYS_MEMORY|PCI_REGION_TYPE;
		if (flags != PCI_REGION_SYS_MEMORY) {
			u64 start = hose->regions[r].bus_start;
			u64 end = start + hose->regions[r].size;

			out_be32(&po->powbar, hose->regions[r].phys_start >> 12);
			out_be32(&po->potar, start >> 12);
#ifdef CONFIG_SYS_PCI_64BIT
			out_be32(&po->potear, start >> 44);
#else
			out_be32(&po->potear, 0);
#endif
			if (hose->regions[r].flags & PCI_REGION_IO) {
				out_be32(&po->powar, POWAR_EN | sz |
					POWAR_IO_READ | POWAR_IO_WRITE);
			} else {
				out_be32(&po->powar, POWAR_EN | sz |
					POWAR_MEM_READ | POWAR_MEM_WRITE);
				out_lo = min(start, out_lo);
				out_hi = max(end, out_hi);
			}
			po++;
		}
	}
/* use up to 2 LAWs for DDR, used the last available LAWs */
int set_ddr_laws(u64 start, u64 sz, enum law_trgt_if id)
{
	u64 start_align, law_sz;
	int law_sz_enc;

	if (start == 0)
		start_align = 1ull << (LAW_SIZE_32G + 1);
	else
		start_align = 1ull << (ffs64(start) - 1);
	law_sz = min(start_align, sz);
	law_sz_enc = __ilog2_u64(law_sz) - 1;

	if (set_last_law(start, law_sz_enc, id) < 0)
		return -1;

	/* recalculate size based on what was actually covered by the law */
	law_sz = 1ull << __ilog2_u64(law_sz);

	/* do we still have anything to map */
	sz = sz - law_sz;
	if (sz) {
		start += law_sz;

		start_align = 1ull << (ffs64(start) - 1);
		law_sz = min(start_align, sz);
		law_sz_enc = __ilog2_u64(law_sz) - 1;

		if (set_last_law(start, law_sz_enc, id) < 0)
			return -1;
	} else {
		return 0;
	}

	/* do we still have anything to map */
	sz = sz - law_sz;
	if (sz)
		return 1;

	return 0;
}
Esempio n. 4
0
asmlinkage void plat_irq_dispatch(void)
{
	uint64_t eirr;
	int i;

	eirr = read_c0_eirr() & read_c0_eimr();
	if (eirr & (1 << IRQ_TIMER)) {
		do_IRQ(IRQ_TIMER);
		return;
	}

	i = __ilog2_u64(eirr);
	if (i == -1)
		return;

	do_IRQ(i);
}
/* Setup one inbound ATMU window.
 *
 * We let the caller decide what the window size should be
 */
static void set_inbound_window(volatile pit_t *pi,
				struct pci_region *r,
				u64 size)
{
	u32 sz = (__ilog2_u64(size) - 1);
	u32 flag = PIWAR_EN | PIWAR_LOCAL |
			PIWAR_READ_SNOOP | PIWAR_WRITE_SNOOP;

	out_be32(&pi->pitar, r->phys_start >> 12);
	out_be32(&pi->piwbar, r->bus_start >> 12);
#ifdef CONFIG_SYS_PCI_64BIT
	out_be32(&pi->piwbear, r->bus_start >> 44);
#else
	out_be32(&pi->piwbear, 0);
#endif
	if (r->flags & PCI_REGION_PREFETCH)
		flag |= PIWAR_PF;
	out_be32(&pi->piwar, flag | sz);
}
void fsl_pci_init(struct pci_controller *hose)
{
	u16 temp16;
	u32 temp32;
	int busno = hose->first_busno;
	int enabled;
	u16 ltssm;
	u8 temp8;
	int r;
	int bridge;
	int inbound = 0;
	volatile ccsr_fsl_pci_t *pci = (ccsr_fsl_pci_t *) hose->cfg_addr;
	pci_dev_t dev = PCI_BDF(busno,0,0);

	/* Initialize ATMU registers based on hose regions and flags */
	volatile pot_t *po = &pci->pot[1];	/* skip 0 */
	volatile pit_t *pi = &pci->pit[0];	/* ranges from: 3 to 1 */

#ifdef DEBUG
	int neg_link_w;
#endif

	for (r=0; r<hose->region_count; r++) {
		u32 sz = (__ilog2_u64((u64)hose->regions[r].size) - 1);
		if (hose->regions[r].flags & PCI_REGION_SYS_MEMORY) { /* inbound */
			u32 flag = PIWAR_EN | PIWAR_LOCAL |
					PIWAR_READ_SNOOP | PIWAR_WRITE_SNOOP;
			pi->pitar = (hose->regions[r].phys_start >> 12);
			pi->piwbar = (hose->regions[r].bus_start >> 12);
#ifdef CONFIG_SYS_PCI_64BIT
			pi->piwbear = (hose->regions[r].bus_start >> 44);
#else
			pi->piwbear = 0;
#endif
			if (hose->regions[r].flags & PCI_REGION_PREFETCH)
				flag |= PIWAR_PF;
			pi->piwar = flag | sz;
			pi++;
			inbound = hose->regions[r].size > 0;
		} else { /* Outbound */
static int fsl_pci_setup_inbound_windows(struct pci_controller *hose,
					 u64 out_lo, u8 pcie_cap,
					 volatile pit_t *pi)
{
	struct pci_region *r = hose->regions + hose->region_count;
	u64 sz = min((u64)gd->ram_size, (1ull << 32));

	phys_addr_t phys_start = CONFIG_SYS_PCI_MEMORY_PHYS;
	pci_addr_t bus_start = CONFIG_SYS_PCI_MEMORY_BUS;
	pci_size_t pci_sz;

	/* we have no space available for inbound memory mapping */
	if (bus_start > out_lo) {
		printf ("no space for inbound mapping of memory\n");
		return 0;
	}

	/* limit size */
	if ((bus_start + sz) > out_lo) {
		sz = out_lo - bus_start;
		debug ("limiting size to %llx\n", sz);
	}

	pci_sz = 1ull << __ilog2_u64(sz);
	/*
	 * we can overlap inbound/outbound windows on PCI-E since RX & TX
	 * links a separate
	 */
	if ((pcie_cap == PCI_CAP_ID_EXP) && (pci_sz < sz)) {
		debug ("R0 bus_start: %llx phys_start: %llx size: %llx\n",
			(u64)bus_start, (u64)phys_start, (u64)sz);
		pci_set_region(r, bus_start, phys_start, sz,
				PCI_REGION_MEM | PCI_REGION_SYS_MEMORY |
				PCI_REGION_PREFETCH);

		/* if we aren't an exact power of two match, pci_sz is smaller
		 * round it up to the next power of two.  We report the actual
		 * size to pci region tracking.
		 */
		if (pci_sz != sz)
			sz = 2ull << __ilog2_u64(sz);

		set_inbound_window(pi--, r++, sz);
		sz = 0; /* make sure we dont set the R2 window */
	} else {
		debug ("R0 bus_start: %llx phys_start: %llx size: %llx\n",
			(u64)bus_start, (u64)phys_start, (u64)pci_sz);
		pci_set_region(r, bus_start, phys_start, pci_sz,
				PCI_REGION_MEM | PCI_REGION_SYS_MEMORY |
				PCI_REGION_PREFETCH);
		set_inbound_window(pi--, r++, pci_sz);

		sz -= pci_sz;
		bus_start += pci_sz;
		phys_start += pci_sz;

		pci_sz = 1ull << __ilog2_u64(sz);
		if (sz) {
			debug ("R1 bus_start: %llx phys_start: %llx size: %llx\n",
				(u64)bus_start, (u64)phys_start, (u64)pci_sz);
			pci_set_region(r, bus_start, phys_start, pci_sz,
					PCI_REGION_MEM | PCI_REGION_SYS_MEMORY |
					PCI_REGION_PREFETCH);
			set_inbound_window(pi--, r++, pci_sz);
			sz -= pci_sz;
			bus_start += pci_sz;
			phys_start += pci_sz;
		}
	}

#if defined(CONFIG_PHYS_64BIT) && defined(CONFIG_SYS_PCI_64BIT)
	/*
	 * On 64-bit capable systems, set up a mapping for all of DRAM
	 * in high pci address space.
	 */
	pci_sz = 1ull << __ilog2_u64(gd->ram_size);
	/* round up to the next largest power of two */
	if (gd->ram_size > pci_sz)
		pci_sz = 1ull << (__ilog2_u64(gd->ram_size) + 1);
	debug ("R64 bus_start: %llx phys_start: %llx size: %llx\n",
		(u64)CONFIG_SYS_PCI64_MEMORY_BUS,
		(u64)CONFIG_SYS_PCI_MEMORY_PHYS,
		(u64)pci_sz);
	pci_set_region(r,
			CONFIG_SYS_PCI64_MEMORY_BUS,
			CONFIG_SYS_PCI_MEMORY_PHYS,
			pci_sz,
			PCI_REGION_MEM | PCI_REGION_SYS_MEMORY |
			PCI_REGION_PREFETCH);
	set_inbound_window(pi--, r++, pci_sz);
#else
	pci_sz = 1ull << __ilog2_u64(sz);
	if (sz) {
		debug ("R2 bus_start: %llx phys_start: %llx size: %llx\n",
			(u64)bus_start, (u64)phys_start, (u64)pci_sz);
		pci_set_region(r, bus_start, phys_start, pci_sz,
				PCI_REGION_MEM | PCI_REGION_SYS_MEMORY |
				PCI_REGION_PREFETCH);
		sz -= pci_sz;
		bus_start += pci_sz;
		phys_start += pci_sz;
		set_inbound_window(pi--, r++, pci_sz);
	}
#endif

#ifdef CONFIG_PHYS_64BIT
	if (sz && (((u64)gd->ram_size) < (1ull << 32)))
		printf("Was not able to map all of memory via "
			"inbound windows -- %lld remaining\n", sz);
#endif

	hose->region_count = r - hose->regions;

	return 1;
}
int fsl_pci_setup_inbound_windows(struct pci_region *r)
{
	struct pci_region *rgn_base = r;
	u64 sz = min((u64)gd->ram_size, (1ull << 32) - 1);

	phys_addr_t phys_start = CONFIG_SYS_PCI_MEMORY_PHYS;
	pci_addr_t bus_start = CONFIG_SYS_PCI_MEMORY_BUS;
	pci_size_t pci_sz = 1ull << __ilog2_u64(sz);

	debug ("R0 bus_start: %llx phys_start: %llx size: %llx\n",
		(u64)bus_start, (u64)phys_start, (u64)pci_sz);
	pci_set_region(r++, bus_start, phys_start, pci_sz,
			PCI_REGION_MEM | PCI_REGION_SYS_MEMORY |
			PCI_REGION_PREFETCH);

	sz -= pci_sz;
	bus_start += pci_sz;
	phys_start += pci_sz;

	pci_sz = 1ull << __ilog2_u64(sz);
	if (sz) {
		debug ("R1 bus_start: %llx phys_start: %llx size: %llx\n",
			(u64)bus_start, (u64)phys_start, (u64)pci_sz);
		pci_set_region(r++, bus_start, phys_start, pci_sz,
				PCI_REGION_MEM | PCI_REGION_SYS_MEMORY |
				PCI_REGION_PREFETCH);
		sz -= pci_sz;
		bus_start += pci_sz;
		phys_start += pci_sz;
	}

#if defined(CONFIG_PHYS_64BIT) && defined(CONFIG_SYS_PCI_64BIT)
	/*
	 * On 64-bit capable systems, set up a mapping for all of DRAM
	 * in high pci address space.
	 */
	pci_sz = 1ull << __ilog2_u64(gd->ram_size);
	/* round up to the next largest power of two */
	if (gd->ram_size > pci_sz)
		pci_sz = 1ull << (__ilog2_u64(gd->ram_size) + 1);
	debug ("R64 bus_start: %llx phys_start: %llx size: %llx\n",
		(u64)CONFIG_SYS_PCI64_MEMORY_BUS,
		(u64)CONFIG_SYS_PCI_MEMORY_PHYS,
		(u64)pci_sz);
	pci_set_region(r++,
			CONFIG_SYS_PCI64_MEMORY_BUS,
			CONFIG_SYS_PCI_MEMORY_PHYS,
			pci_sz,
			PCI_REGION_MEM | PCI_REGION_SYS_MEMORY |
			PCI_REGION_PREFETCH);
#else
	pci_sz = 1ull << __ilog2_u64(sz);
	if (sz) {
		debug ("R2 bus_start: %llx phys_start: %llx size: %llx\n",
			(u64)bus_start, (u64)phys_start, (u64)pci_sz);
		pci_set_region(r++, bus_start, phys_start, pci_sz,
				PCI_REGION_MEM | PCI_REGION_SYS_MEMORY |
				PCI_REGION_PREFETCH);
		sz -= pci_sz;
		bus_start += pci_sz;
		phys_start += pci_sz;
	}
#endif

#ifdef CONFIG_PHYS_64BIT
	if (sz && (((u64)gd->ram_size) < (1ull << 32)))
		printf("Was not able to map all of memory via "
			"inbound windows -- %lld remaining\n", sz);
#endif

	return r - rgn_base;
}