static int __init ppc4xx_setup_one_pciex_POM(struct ppc4xx_pciex_port	*port,
					     struct pci_controller	*hose,
					     void __iomem		*mbase,
					     u64			plb_addr,
					     u64			pci_addr,
					     u64			size,
					     unsigned int		flags,
					     int			index)
{
	u32 lah, lal, pciah, pcial, sa;

	if (!is_power_of_2(size) ||
	    (index < 2 && size < 0x100000) ||
	    (index == 2 && size < 0x100) ||
	    (plb_addr & (size - 1)) != 0) {
		printk(KERN_WARNING "%s: Resource out of range\n",
		       hose->dn->full_name);
		return -1;
	}

	/* Calculate register values */
	lah = RES_TO_U32_HIGH(plb_addr);
	lal = RES_TO_U32_LOW(plb_addr);
	pciah = RES_TO_U32_HIGH(pci_addr);
	pcial = RES_TO_U32_LOW(pci_addr);
	sa = (0xffffffffu << ilog2(size)) | 0x1;

	/* Program register values */
	switch (index) {
	case 0:
		out_le32(mbase + PECFG_POM0LAH, pciah);
		out_le32(mbase + PECFG_POM0LAL, pcial);
		dcr_write(port->dcrs, DCRO_PEGPL_OMR1BAH, lah);
		dcr_write(port->dcrs, DCRO_PEGPL_OMR1BAL, lal);
		dcr_write(port->dcrs, DCRO_PEGPL_OMR1MSKH, 0x7fffffff);
		/* Note that 3 here means enabled | single region */
		dcr_write(port->dcrs, DCRO_PEGPL_OMR1MSKL, sa | 3);
		break;
	case 1:
		out_le32(mbase + PECFG_POM1LAH, pciah);
		out_le32(mbase + PECFG_POM1LAL, pcial);
		dcr_write(port->dcrs, DCRO_PEGPL_OMR2BAH, lah);
		dcr_write(port->dcrs, DCRO_PEGPL_OMR2BAL, lal);
		dcr_write(port->dcrs, DCRO_PEGPL_OMR2MSKH, 0x7fffffff);
		/* Note that 3 here means enabled | single region */
		dcr_write(port->dcrs, DCRO_PEGPL_OMR2MSKL, sa | 3);
		break;
	case 2:
		out_le32(mbase + PECFG_POM2LAH, pciah);
		out_le32(mbase + PECFG_POM2LAL, pcial);
		dcr_write(port->dcrs, DCRO_PEGPL_OMR3BAH, lah);
		dcr_write(port->dcrs, DCRO_PEGPL_OMR3BAL, lal);
		dcr_write(port->dcrs, DCRO_PEGPL_OMR3MSKH, 0x7fffffff);
		/* Note that 3 here means enabled | IO space !!! */
		dcr_write(port->dcrs, DCRO_PEGPL_OMR3MSKL, sa | 3);
		break;
	}

	return 0;
}
static void __init ppc4xx_pciex_port_init_mapping(struct ppc4xx_pciex_port *port)
{
	/* We map PCI Express configuration based on the reg property */
	dcr_write(port->dcrs, DCRO_PEGPL_CFGBAH,
		  RES_TO_U32_HIGH(port->cfg_space.start));
	dcr_write(port->dcrs, DCRO_PEGPL_CFGBAL,
		  RES_TO_U32_LOW(port->cfg_space.start));

	/* XXX FIXME: Use size from reg property. For now, map 512M */
	dcr_write(port->dcrs, DCRO_PEGPL_CFGMSK, 0xe0000001);

	/* We map UTL registers based on the reg property */
	dcr_write(port->dcrs, DCRO_PEGPL_REGBAH,
		  RES_TO_U32_HIGH(port->utl_regs.start));
	dcr_write(port->dcrs, DCRO_PEGPL_REGBAL,
		  RES_TO_U32_LOW(port->utl_regs.start));

	/* XXX FIXME: Use size from reg property */
	dcr_write(port->dcrs, DCRO_PEGPL_REGMSK, 0x00007001);

	/* Disable all other outbound windows */
	dcr_write(port->dcrs, DCRO_PEGPL_OMR1MSKL, 0);
	dcr_write(port->dcrs, DCRO_PEGPL_OMR2MSKL, 0);
	dcr_write(port->dcrs, DCRO_PEGPL_OMR3MSKL, 0);
	dcr_write(port->dcrs, DCRO_PEGPL_MSGMSK, 0);
}
Example #3
0
static void __init ppc4xx_configure_pcix_POMs(struct pci_controller *hose,
					      void __iomem *reg)
{
	u32 lah, lal, pciah, pcial, sa;
	int i, j;

	/* Setup outbound memory windows */
	for (i = j = 0; i < 3; i++) {
		struct resource *res = &hose->mem_resources[i];

		/* we only care about memory windows */
		if (!(res->flags & IORESOURCE_MEM))
			continue;
		if (j > 1) {
			printk(KERN_WARNING "%s: Too many ranges\n",
			       hose->dn->full_name);
			break;
		}

		/* Calculate register values */
		lah = RES_TO_U32_HIGH(res->start);
		lal = RES_TO_U32_LOW(res->start);
		pciah = RES_TO_U32_HIGH(res->start - hose->pci_mem_offset);
		pcial = RES_TO_U32_LOW(res->start - hose->pci_mem_offset);
		sa = res->end + 1 - res->start;
		if (!is_power_of_2(sa) || sa < 0x100000 ||
		    sa > 0xffffffffu) {
			printk(KERN_WARNING "%s: Resource out of range\n",
			       hose->dn->full_name);
			continue;
		}
		sa = (0xffffffffu << ilog2(sa)) | 0x1;

		/* Program register values */
		if (j == 0) {
			writel(lah, reg + PCIX0_POM0LAH);
			writel(lal, reg + PCIX0_POM0LAL);
			writel(pciah, reg + PCIX0_POM0PCIAH);
			writel(pcial, reg + PCIX0_POM0PCIAL);
			writel(sa, reg + PCIX0_POM0SA);
		} else {
			writel(lah, reg + PCIX0_POM1LAH);
			writel(lal, reg + PCIX0_POM1LAL);
			writel(pciah, reg + PCIX0_POM1PCIAH);
			writel(pcial, reg + PCIX0_POM1PCIAL);
			writel(sa, reg + PCIX0_POM1SA);
		}
		j++;
	}
}
static int __init ppc4xx_setup_one_pcix_POM(struct pci_controller	*hose,
					    void __iomem		*reg,
					    u64				plb_addr,
					    u64				pci_addr,
					    u64				size,
					    unsigned int		flags,
					    int				index)
{
	u32 lah, lal, pciah, pcial, sa;

	if (!is_power_of_2(size) || size < 0x1000 ||
	    (plb_addr & (size - 1)) != 0) {
		printk(KERN_WARNING "%s: Resource out of range\n",
		       hose->dn->full_name);
		return -1;
	}

	/* Calculate register values */
	lah = RES_TO_U32_HIGH(plb_addr);
	lal = RES_TO_U32_LOW(plb_addr);
	pciah = RES_TO_U32_HIGH(pci_addr);
	pcial = RES_TO_U32_LOW(pci_addr);
	sa = (0xffffffffu << ilog2(size)) | 0x1;

	/* Program register values */
	if (index == 0) {
		writel(lah, reg + PCIX0_POM0LAH);
		writel(lal, reg + PCIX0_POM0LAL);
		writel(pciah, reg + PCIX0_POM0PCIAH);
		writel(pcial, reg + PCIX0_POM0PCIAL);
		writel(sa, reg + PCIX0_POM0SA);
	} else {
		writel(lah, reg + PCIX0_POM1LAH);
		writel(lal, reg + PCIX0_POM1LAL);
		writel(pciah, reg + PCIX0_POM1PCIAH);
		writel(pcial, reg + PCIX0_POM1PCIAL);
		writel(sa, reg + PCIX0_POM1SA);
	}

	return 0;
}
static int __init ppc4xx_setup_one_pci_PMM(struct pci_controller	*hose,
					   void __iomem			*reg,
					   u64				plb_addr,
					   u64				pci_addr,
					   u64				size,
					   unsigned int			flags,
					   int				index)
{
	u32 ma, pcila, pciha;

	/* Hack warning ! The "old" PCI 2.x cell only let us configure the low
	 * 32-bit of incoming PLB addresses. The top 4 bits of the 36-bit
	 * address are actually hard wired to a value that appears to depend
	 * on the specific SoC. For example, it's 0 on 440EP and 1 on 440EPx.
	 *
	 * The trick here is we just crop those top bits and ignore them when
	 * programming the chip. That means the device-tree has to be right
	 * for the specific part used (we don't print a warning if it's wrong
	 * but on the other hand, you'll crash quickly enough), but at least
	 * this code should work whatever the hard coded value is
	 */
	plb_addr &= 0xffffffffull;

	/* Note: Due to the above hack, the test below doesn't actually test
	 * if you address is above 4G, but it tests that address and
	 * (address + size) are both contained in the same 4G
	 */
	if ((plb_addr + size) > 0xffffffffull || !is_power_of_2(size) ||
	    size < 0x1000 || (plb_addr & (size - 1)) != 0) {
		printk(KERN_WARNING "%s: Resource out of range\n",
		       hose->dn->full_name);
		return -1;
	}
	ma = (0xffffffffu << ilog2(size)) | 1;
	if (flags & IORESOURCE_PREFETCH)
		ma |= 2;

	pciha = RES_TO_U32_HIGH(pci_addr);
	pcila = RES_TO_U32_LOW(pci_addr);

	writel(plb_addr, reg + PCIL0_PMM0LA + (0x10 * index));
	writel(pcila, reg + PCIL0_PMM0PCILA + (0x10 * index));
	writel(pciha, reg + PCIL0_PMM0PCIHA + (0x10 * index));
	writel(ma, reg + PCIL0_PMM0MA + (0x10 * index));

	return 0;
}
Example #6
0
static void __init ppc4xx_configure_pci_PMMs(struct pci_controller *hose,
					     void __iomem *reg)
{
	u32 la, ma, pcila, pciha;
	int i, j;

	/* Setup outbound memory windows */
	for (i = j = 0; i < 3; i++) {
		struct resource *res = &hose->mem_resources[i];

		/* we only care about memory windows */
		if (!(res->flags & IORESOURCE_MEM))
			continue;
		if (j > 2) {
			printk(KERN_WARNING "%s: Too many ranges\n",
			       hose->dn->full_name);
			break;
		}

		/* Calculate register values */
		la = res->start;
		pciha = RES_TO_U32_HIGH(res->start - hose->pci_mem_offset);
		pcila = RES_TO_U32_LOW(res->start - hose->pci_mem_offset);

		ma = res->end + 1 - res->start;
		if (!is_power_of_2(ma) || ma < 0x1000 || ma > 0xffffffffu) {
			printk(KERN_WARNING "%s: Resource out of range\n",
			       hose->dn->full_name);
			continue;
		}
		ma = (0xffffffffu << ilog2(ma)) | 0x1;
		if (res->flags & IORESOURCE_PREFETCH)
			ma |= 0x2;

		/* Program register values */
		writel(la, reg + PCIL0_PMM0LA + (0x10 * j));
		writel(pcila, reg + PCIL0_PMM0PCILA + (0x10 * j));
		writel(pciha, reg + PCIL0_PMM0PCIHA + (0x10 * j));
		writel(ma, reg + PCIL0_PMM0MA + (0x10 * j));
		j++;
	}
}
static void __init ppc4xx_configure_pciex_PIMs(struct ppc4xx_pciex_port *port,
					       struct pci_controller *hose,
					       void __iomem *mbase,
					       struct resource *res)
{
	resource_size_t size = res->end - res->start + 1;
	u64 sa;

	if (port->endpoint) {
		resource_size_t ep_addr = 0;
		resource_size_t ep_size = 32 << 20;

		/* Currently we map a fixed 64MByte window to PLB address
		 * 0 (SDRAM). This should probably be configurable via a dts
		 * property.
		 */

		/* Calculate window size */
		sa = (0xffffffffffffffffull << ilog2(ep_size));

		/* Setup BAR0 */
		out_le32(mbase + PECFG_BAR0HMPA, RES_TO_U32_HIGH(sa));
		out_le32(mbase + PECFG_BAR0LMPA, RES_TO_U32_LOW(sa) |
			 PCI_BASE_ADDRESS_MEM_TYPE_64);

		/* Disable BAR1 & BAR2 */
		out_le32(mbase + PECFG_BAR1MPA, 0);
		out_le32(mbase + PECFG_BAR2HMPA, 0);
		out_le32(mbase + PECFG_BAR2LMPA, 0);

		out_le32(mbase + PECFG_PIM01SAH, RES_TO_U32_HIGH(sa));
		out_le32(mbase + PECFG_PIM01SAL, RES_TO_U32_LOW(sa));

		out_le32(mbase + PCI_BASE_ADDRESS_0, RES_TO_U32_LOW(ep_addr));
		out_le32(mbase + PCI_BASE_ADDRESS_1, RES_TO_U32_HIGH(ep_addr));
	} else {
		/* Calculate window size */
		sa = (0xffffffffffffffffull << ilog2(size));
		if (res->flags & IORESOURCE_PREFETCH)
			sa |= 0x8;

		out_le32(mbase + PECFG_BAR0HMPA, RES_TO_U32_HIGH(sa));
		out_le32(mbase + PECFG_BAR0LMPA, RES_TO_U32_LOW(sa));

		/* The setup of the split looks weird to me ... let's see
		 * if it works
		 */
		out_le32(mbase + PECFG_PIM0LAL, 0x00000000);
		out_le32(mbase + PECFG_PIM0LAH, 0x00000000);
		out_le32(mbase + PECFG_PIM1LAL, 0x00000000);
		out_le32(mbase + PECFG_PIM1LAH, 0x00000000);
		out_le32(mbase + PECFG_PIM01SAH, 0xffff0000);
		out_le32(mbase + PECFG_PIM01SAL, 0x00000000);

		out_le32(mbase + PCI_BASE_ADDRESS_0, RES_TO_U32_LOW(res->start));
		out_le32(mbase + PCI_BASE_ADDRESS_1, RES_TO_U32_HIGH(res->start));
	}

	/* Enable inbound mapping */
	out_le32(mbase + PECFG_PIMEN, 0x1);

	/* Enable I/O, Mem, and Busmaster cycles */
	out_le16(mbase + PCI_COMMAND,
		 in_le16(mbase + PCI_COMMAND) |
		 PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
}
Example #8
0
static void __init ppc4xx_configure_pciex_POMs(struct ppc4xx_pciex_port *port,
					       struct pci_controller *hose,
					       void __iomem *mbase)
{
	u32 lah, lal, pciah, pcial, sa;
	int i, j;

	/* Setup outbound memory windows */
	for (i = j = 0; i < 3; i++) {
		struct resource *res = &hose->mem_resources[i];

		/* we only care about memory windows */
		if (!(res->flags & IORESOURCE_MEM))
			continue;
		if (j > 1) {
			printk(KERN_WARNING "%s: Too many ranges\n",
			       port->node->full_name);
			break;
		}

		/* Calculate register values */
		lah = RES_TO_U32_HIGH(res->start);
		lal = RES_TO_U32_LOW(res->start);
		pciah = RES_TO_U32_HIGH(res->start - hose->pci_mem_offset);
		pcial = RES_TO_U32_LOW(res->start - hose->pci_mem_offset);
		sa = res->end + 1 - res->start;
		if (!is_power_of_2(sa) || sa < 0x100000 ||
		    sa > 0xffffffffu) {
			printk(KERN_WARNING "%s: Resource out of range\n",
			       port->node->full_name);
			continue;
		}
		sa = (0xffffffffu << ilog2(sa)) | 0x1;

		/* Program register values */
		switch (j) {
		case 0:
			out_le32(mbase + PECFG_POM0LAH, pciah);
			out_le32(mbase + PECFG_POM0LAL, pcial);
			dcr_write(port->dcrs, DCRO_PEGPL_OMR1BAH, lah);
			dcr_write(port->dcrs, DCRO_PEGPL_OMR1BAL, lal);
			dcr_write(port->dcrs, DCRO_PEGPL_OMR1MSKH, 0x7fffffff);
			dcr_write(port->dcrs, DCRO_PEGPL_OMR1MSKL, sa | 3);
			break;
		case 1:
			out_le32(mbase + PECFG_POM1LAH, pciah);
			out_le32(mbase + PECFG_POM1LAL, pcial);
			dcr_write(port->dcrs, DCRO_PEGPL_OMR2BAH, lah);
			dcr_write(port->dcrs, DCRO_PEGPL_OMR2BAL, lal);
			dcr_write(port->dcrs, DCRO_PEGPL_OMR2MSKH, 0x7fffffff);
			dcr_write(port->dcrs, DCRO_PEGPL_OMR2MSKL, sa | 3);
			break;
		}
		j++;
	}

	/* Configure IO, always 64K starting at 0 */
	if (hose->io_resource.flags & IORESOURCE_IO) {
		lah = RES_TO_U32_HIGH(hose->io_base_phys);
		lal = RES_TO_U32_LOW(hose->io_base_phys);
		out_le32(mbase + PECFG_POM2LAH, 0);
		out_le32(mbase + PECFG_POM2LAL, 0);
		dcr_write(port->dcrs, DCRO_PEGPL_OMR3BAH, lah);
		dcr_write(port->dcrs, DCRO_PEGPL_OMR3BAL, lal);
		dcr_write(port->dcrs, DCRO_PEGPL_OMR3MSKH, 0x7fffffff);
		dcr_write(port->dcrs, DCRO_PEGPL_OMR3MSKL, 0xffff0000 | 3);
	}
}