Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 81167
b: refs/heads/master
c: c839e0e
h: refs/heads/master
i:
  81165: 628c07b
  81163: 97c1faa
  81159: 7432f55
  81151: 3ef13a0
v: v3
  • Loading branch information
Benjamin Herrenschmidt authored and Josh Boyer committed Dec 23, 2007
1 parent 4f9dfbd commit fe73719
Show file tree
Hide file tree
Showing 3 changed files with 199 additions and 2 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 5738ec6d00b7abbcd4cd342af83fd18d192b0979
refs/heads/master: c839e0eff500af03de65e560c2e21c3831586e6e
180 changes: 179 additions & 1 deletion trunk/arch/powerpc/sysdev/ppc4xx_pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,36 @@ static int dma_offset_set;
/* Move that to a useable header */
extern unsigned long total_memory;

static void fixup_ppc4xx_pci_bridge(struct pci_dev *dev)
{
struct pci_controller *hose;
int i;

if (dev->devfn != 0 || dev->bus->self != NULL)
return;

hose = pci_bus_to_host(dev->bus);
if (hose == NULL)
return;

if (!of_device_is_compatible(hose->dn, "ibm,plb-pciex") &&
!of_device_is_compatible(hose->dn, "ibm,plb-pcix") &&
!of_device_is_compatible(hose->dn, "ibm,plb-pci"))
return;

/* Hide the PCI host BARs from the kernel as their content doesn't
* fit well in the resource management
*/
for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
dev->resource[i].start = dev->resource[i].end = 0;
dev->resource[i].flags = 0;
}

printk(KERN_INFO "PCI: Hiding 4xx host bridge resources %s\n",
pci_name(dev));
}
DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, fixup_ppc4xx_pci_bridge);

static int __init ppc4xx_parse_dma_ranges(struct pci_controller *hose,
void __iomem *reg,
struct resource *res)
Expand Down Expand Up @@ -126,9 +156,157 @@ static int __init ppc4xx_parse_dma_ranges(struct pci_controller *hose,
/*
* 4xx PCI 2.x part
*/

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;
#ifdef CONFIG_RESOURCES_64BIT
pciha = (res->start - hose->pci_mem_offset) >> 32;
pcila = (res->start - hose->pci_mem_offset) & 0xffffffffu;
#else
pciha = 0;
pcila = res->start - hose->pci_mem_offset;
#endif

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_pci_PTMs(struct pci_controller *hose,
void __iomem *reg,
const struct resource *res)
{
resource_size_t size = res->end - res->start + 1;
u32 sa;

/* Calculate window size */
sa = (0xffffffffu << ilog2(size)) | 1;
sa |= 0x1;

/* RAM is always at 0 local for now */
writel(0, reg + PCIL0_PTM1LA);
writel(sa, reg + PCIL0_PTM1MS);

/* Map on PCI side */
early_write_config_dword(hose, hose->first_busno, 0,
PCI_BASE_ADDRESS_1, res->start);
early_write_config_dword(hose, hose->first_busno, 0,
PCI_BASE_ADDRESS_2, 0x00000000);
early_write_config_word(hose, hose->first_busno, 0,
PCI_COMMAND, 0x0006);
}

static void __init ppc4xx_probe_pci_bridge(struct device_node *np)
{
/* NYI */
struct resource rsrc_cfg;
struct resource rsrc_reg;
struct resource dma_window;
struct pci_controller *hose = NULL;
void __iomem *reg = NULL;
const int *bus_range;
int primary = 0;

/* Fetch config space registers address */
if (of_address_to_resource(np, 0, &rsrc_cfg)) {
printk(KERN_ERR "%s:Can't get PCI config register base !",
np->full_name);
return;
}
/* Fetch host bridge internal registers address */
if (of_address_to_resource(np, 3, &rsrc_reg)) {
printk(KERN_ERR "%s: Can't get PCI internal register base !",
np->full_name);
return;
}

/* Check if primary bridge */
if (of_get_property(np, "primary", NULL))
primary = 1;

/* Get bus range if any */
bus_range = of_get_property(np, "bus-range", NULL);

/* Map registers */
reg = ioremap(rsrc_reg.start, rsrc_reg.end + 1 - rsrc_reg.start);
if (reg == NULL) {
printk(KERN_ERR "%s: Can't map registers !", np->full_name);
goto fail;
}

/* Allocate the host controller data structure */
hose = pcibios_alloc_controller(np);
if (!hose)
goto fail;

hose->first_busno = bus_range ? bus_range[0] : 0x0;
hose->last_busno = bus_range ? bus_range[1] : 0xff;

/* Setup config space */
setup_indirect_pci(hose, rsrc_cfg.start, rsrc_cfg.start + 0x4, 0);

/* Disable all windows */
writel(0, reg + PCIL0_PMM0MA);
writel(0, reg + PCIL0_PMM1MA);
writel(0, reg + PCIL0_PMM2MA);
writel(0, reg + PCIL0_PTM1MS);
writel(0, reg + PCIL0_PTM2MS);

/* Parse outbound mapping resources */
pci_process_bridge_OF_ranges(hose, np, primary);

/* Parse inbound mapping resources */
if (ppc4xx_parse_dma_ranges(hose, reg, &dma_window) != 0)
goto fail;

/* Configure outbound ranges POMs */
ppc4xx_configure_pci_PMMs(hose, reg);

/* Configure inbound ranges PIMs */
ppc4xx_configure_pci_PTMs(hose, reg, &dma_window);

/* We don't need the registers anymore */
iounmap(reg);
return;

fail:
if (hose)
pcibios_free_controller(hose);
if (reg)
iounmap(reg);
}

/*
Expand All @@ -155,7 +333,7 @@ static void __init ppc4xx_configure_pcix_POMs(struct pci_controller *hose,
}

/* Calculate register values */
#ifdef CONFIG_PTE_64BIT
#ifdef CONFIG_RESOURCES_64BIT
lah = res->start >> 32;
lal = res->start & 0xffffffffu;
pciah = (res->start - hose->pci_mem_offset) >> 32;
Expand Down
19 changes: 19 additions & 0 deletions trunk/arch/powerpc/sysdev/ppc4xx_pci.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,25 @@
#define PCIX0_MSGOH 0x10c
#define PCIX0_IM 0x1f8

/*
* 4xx PCI bridge register definitions
*/
#define PCIL0_PMM0LA 0x00
#define PCIL0_PMM0MA 0x04
#define PCIL0_PMM0PCILA 0x08
#define PCIL0_PMM0PCIHA 0x0c
#define PCIL0_PMM1LA 0x10
#define PCIL0_PMM1MA 0x14
#define PCIL0_PMM1PCILA 0x18
#define PCIL0_PMM1PCIHA 0x1c
#define PCIL0_PMM2LA 0x20
#define PCIL0_PMM2MA 0x24
#define PCIL0_PMM2PCILA 0x28
#define PCIL0_PMM2PCIHA 0x2c
#define PCIL0_PTM1MS 0x30
#define PCIL0_PTM1LA 0x34
#define PCIL0_PTM2MS 0x38
#define PCIL0_PTM2LA 0x3c


#endif /* __PPC4XX_PCI_H__ */

0 comments on commit fe73719

Please sign in to comment.