Commit 52a77587 authored by David S. Miller's avatar David S. Miller

[SPARC64]: Sanitize PCI controller handling to support Tomatillo better.

- Move varions controller datums into pbm structure.
- Add controller type/version/revision info to pbm structure.
- SCHIZO/TOMATILLO fixes:
  - Treat PBM etc. register bases as PBM local.
  - Use PBM prom node ranges property to figure out where
    CFG/MEM/IO space physical bases are.
parent 63eceba1
...@@ -185,6 +185,7 @@ void pci_config_write32(u32 *addr, u32 val) ...@@ -185,6 +185,7 @@ void pci_config_write32(u32 *addr, u32 val)
extern void sabre_init(int, char *); extern void sabre_init(int, char *);
extern void psycho_init(int, char *); extern void psycho_init(int, char *);
extern void schizo_init(int, char *); extern void schizo_init(int, char *);
extern void schizo_plus_init(int, char *);
extern void tomatillo_init(int, char *); extern void tomatillo_init(int, char *);
static struct { static struct {
...@@ -198,6 +199,8 @@ static struct { ...@@ -198,6 +199,8 @@ static struct {
{ "pci108e,8000", psycho_init }, { "pci108e,8000", psycho_init },
{ "SUNW,schizo", schizo_init }, { "SUNW,schizo", schizo_init },
{ "pci108e,8001", schizo_init }, { "pci108e,8001", schizo_init },
{ "SUNW,schizo+", schizo_plus_init },
{ "pci108e,8002", schizo_plus_init },
{ "SUNW,tomatillo", tomatillo_init }, { "SUNW,tomatillo", tomatillo_init },
{ "pci108e,a801", tomatillo_init }, { "pci108e,a801", tomatillo_init },
}; };
......
...@@ -686,7 +686,7 @@ static void __init pdev_fixup_irq(struct pci_dev *pdev) ...@@ -686,7 +686,7 @@ static void __init pdev_fixup_irq(struct pci_dev *pdev)
struct pcidev_cookie *pcp = pdev->sysdata; struct pcidev_cookie *pcp = pdev->sysdata;
struct pci_pbm_info *pbm = pcp->pbm; struct pci_pbm_info *pbm = pcp->pbm;
struct pci_controller_info *p = pbm->parent; struct pci_controller_info *p = pbm->parent;
unsigned int portid = p->portid; unsigned int portid = pbm->portid;
unsigned int prom_irq; unsigned int prom_irq;
int prom_node = pcp->prom_node; int prom_node = pcp->prom_node;
int err; int err;
......
This diff is collapsed.
...@@ -591,7 +591,6 @@ static unsigned int __init sabre_irq_build(struct pci_pbm_info *pbm, ...@@ -591,7 +591,6 @@ static unsigned int __init sabre_irq_build(struct pci_pbm_info *pbm,
struct pci_dev *pdev, struct pci_dev *pdev,
unsigned int ino) unsigned int ino)
{ {
struct pci_controller_info *p = pbm->parent;
struct ino_bucket *bucket; struct ino_bucket *bucket;
unsigned long imap, iclr; unsigned long imap, iclr;
unsigned long imap_off, iclr_off; unsigned long imap_off, iclr_off;
...@@ -616,11 +615,11 @@ static unsigned int __init sabre_irq_build(struct pci_pbm_info *pbm, ...@@ -616,11 +615,11 @@ static unsigned int __init sabre_irq_build(struct pci_pbm_info *pbm,
if (PIL_RESERVED(pil)) if (PIL_RESERVED(pil))
BUG(); BUG();
imap = p->controller_regs + imap_off; imap = pbm->controller_regs + imap_off;
imap += 4; imap += 4;
iclr_off = sabre_iclr_offset(ino); iclr_off = sabre_iclr_offset(ino);
iclr = p->controller_regs + iclr_off; iclr = pbm->controller_regs + iclr_off;
iclr += 4; iclr += 4;
if ((ino & 0x20) == 0) if ((ino & 0x20) == 0)
...@@ -698,7 +697,7 @@ static void sabre_check_iommu_error(struct pci_controller_info *p, ...@@ -698,7 +697,7 @@ static void sabre_check_iommu_error(struct pci_controller_info *p,
sabre_write(iommu->iommu_control, sabre_write(iommu->iommu_control,
(control | SABRE_IOMMUCTRL_DENAB)); (control | SABRE_IOMMUCTRL_DENAB));
for (i = 0; i < 16; i++) { for (i = 0; i < 16; i++) {
unsigned long base = p->controller_regs; unsigned long base = p->pbm_A.controller_regs;
iommu_tag[i] = iommu_tag[i] =
sabre_read(base + SABRE_IOMMU_TAG + (i * 8UL)); sabre_read(base + SABRE_IOMMU_TAG + (i * 8UL));
...@@ -747,8 +746,8 @@ static void sabre_check_iommu_error(struct pci_controller_info *p, ...@@ -747,8 +746,8 @@ static void sabre_check_iommu_error(struct pci_controller_info *p,
static irqreturn_t sabre_ue_intr(int irq, void *dev_id, struct pt_regs *regs) static irqreturn_t sabre_ue_intr(int irq, void *dev_id, struct pt_regs *regs)
{ {
struct pci_controller_info *p = dev_id; struct pci_controller_info *p = dev_id;
unsigned long afsr_reg = p->controller_regs + SABRE_UE_AFSR; unsigned long afsr_reg = p->pbm_A.controller_regs + SABRE_UE_AFSR;
unsigned long afar_reg = p->controller_regs + SABRE_UECE_AFAR; unsigned long afar_reg = p->pbm_A.controller_regs + SABRE_UECE_AFAR;
unsigned long afsr, afar, error_bits; unsigned long afsr, afar, error_bits;
int reported; int reported;
...@@ -807,8 +806,8 @@ static irqreturn_t sabre_ue_intr(int irq, void *dev_id, struct pt_regs *regs) ...@@ -807,8 +806,8 @@ static irqreturn_t sabre_ue_intr(int irq, void *dev_id, struct pt_regs *regs)
static irqreturn_t sabre_ce_intr(int irq, void *dev_id, struct pt_regs *regs) static irqreturn_t sabre_ce_intr(int irq, void *dev_id, struct pt_regs *regs)
{ {
struct pci_controller_info *p = dev_id; struct pci_controller_info *p = dev_id;
unsigned long afsr_reg = p->controller_regs + SABRE_CE_AFSR; unsigned long afsr_reg = p->pbm_A.controller_regs + SABRE_CE_AFSR;
unsigned long afar_reg = p->controller_regs + SABRE_UECE_AFAR; unsigned long afar_reg = p->pbm_A.controller_regs + SABRE_UECE_AFAR;
unsigned long afsr, afar, error_bits; unsigned long afsr, afar, error_bits;
int reported; int reported;
...@@ -867,8 +866,8 @@ static irqreturn_t sabre_pcierr_intr(int irq, void *dev_id, struct pt_regs *regs ...@@ -867,8 +866,8 @@ static irqreturn_t sabre_pcierr_intr(int irq, void *dev_id, struct pt_regs *regs
unsigned long afsr, afar, error_bits; unsigned long afsr, afar, error_bits;
int reported; int reported;
afsr_reg = p->controller_regs + SABRE_PIOAFSR; afsr_reg = p->pbm_A.controller_regs + SABRE_PIOAFSR;
afar_reg = p->controller_regs + SABRE_PIOAFAR; afar_reg = p->pbm_A.controller_regs + SABRE_PIOAFAR;
/* Latch error status. */ /* Latch error status. */
afar = sabre_read(afar_reg); afar = sabre_read(afar_reg);
...@@ -962,8 +961,8 @@ static irqreturn_t sabre_pcierr_intr(int irq, void *dev_id, struct pt_regs *regs ...@@ -962,8 +961,8 @@ static irqreturn_t sabre_pcierr_intr(int irq, void *dev_id, struct pt_regs *regs
static void __init sabre_register_error_handlers(struct pci_controller_info *p) static void __init sabre_register_error_handlers(struct pci_controller_info *p)
{ {
struct pci_pbm_info *pbm = &p->pbm_A; /* arbitrary */ struct pci_pbm_info *pbm = &p->pbm_A; /* arbitrary */
unsigned long base = p->controller_regs; unsigned long base = pbm->controller_regs;
unsigned long irq, portid = p->portid; unsigned long irq, portid = pbm->portid;
u64 tmp; u64 tmp;
/* We clear the error bits in the appropriate AFSR before /* We clear the error bits in the appropriate AFSR before
...@@ -1011,13 +1010,12 @@ static void __init sabre_resource_adjust(struct pci_dev *pdev, ...@@ -1011,13 +1010,12 @@ static void __init sabre_resource_adjust(struct pci_dev *pdev,
struct resource *root) struct resource *root)
{ {
struct pci_pbm_info *pbm = pdev->bus->sysdata; struct pci_pbm_info *pbm = pdev->bus->sysdata;
struct pci_controller_info *p = pbm->parent;
unsigned long base; unsigned long base;
if (res->flags & IORESOURCE_IO) if (res->flags & IORESOURCE_IO)
base = p->controller_regs + SABRE_IOSPACE; base = pbm->controller_regs + SABRE_IOSPACE;
else else
base = p->controller_regs + SABRE_MEMSPACE; base = pbm->controller_regs + SABRE_MEMSPACE;
res->start += base; res->start += base;
res->end += base; res->end += base;
...@@ -1027,7 +1025,6 @@ static void __init sabre_base_address_update(struct pci_dev *pdev, int resource) ...@@ -1027,7 +1025,6 @@ static void __init sabre_base_address_update(struct pci_dev *pdev, int resource)
{ {
struct pcidev_cookie *pcp = pdev->sysdata; struct pcidev_cookie *pcp = pdev->sysdata;
struct pci_pbm_info *pbm = pcp->pbm; struct pci_pbm_info *pbm = pcp->pbm;
struct pci_controller_info *p = pbm->parent;
struct resource *res; struct resource *res;
unsigned long base; unsigned long base;
u32 reg; u32 reg;
...@@ -1045,9 +1042,9 @@ static void __init sabre_base_address_update(struct pci_dev *pdev, int resource) ...@@ -1045,9 +1042,9 @@ static void __init sabre_base_address_update(struct pci_dev *pdev, int resource)
is_64bit = 0; is_64bit = 0;
if (res->flags & IORESOURCE_IO) if (res->flags & IORESOURCE_IO)
base = p->controller_regs + SABRE_IOSPACE; base = pbm->controller_regs + SABRE_IOSPACE;
else { else {
base = p->controller_regs + SABRE_MEMSPACE; base = pbm->controller_regs + SABRE_MEMSPACE;
if ((res->flags & PCI_BASE_ADDRESS_MEM_TYPE_MASK) if ((res->flags & PCI_BASE_ADDRESS_MEM_TYPE_MASK)
== PCI_BASE_ADDRESS_MEM_TYPE_64) == PCI_BASE_ADDRESS_MEM_TYPE_64)
is_64bit = 1; is_64bit = 1;
...@@ -1229,21 +1226,21 @@ static void __init sabre_iommu_init(struct pci_controller_info *p, ...@@ -1229,21 +1226,21 @@ static void __init sabre_iommu_init(struct pci_controller_info *p,
iommu->iommu_cur_ctx = 0; iommu->iommu_cur_ctx = 0;
/* Register addresses. */ /* Register addresses. */
iommu->iommu_control = p->controller_regs + SABRE_IOMMU_CONTROL; iommu->iommu_control = p->pbm_A.controller_regs + SABRE_IOMMU_CONTROL;
iommu->iommu_tsbbase = p->controller_regs + SABRE_IOMMU_TSBBASE; iommu->iommu_tsbbase = p->pbm_A.controller_regs + SABRE_IOMMU_TSBBASE;
iommu->iommu_flush = p->controller_regs + SABRE_IOMMU_FLUSH; iommu->iommu_flush = p->pbm_A.controller_regs + SABRE_IOMMU_FLUSH;
iommu->write_complete_reg = p->controller_regs + SABRE_WRSYNC; iommu->write_complete_reg = p->pbm_A.controller_regs + SABRE_WRSYNC;
/* Sabre's IOMMU lacks ctx flushing. */ /* Sabre's IOMMU lacks ctx flushing. */
iommu->iommu_ctxflush = 0; iommu->iommu_ctxflush = 0;
/* Invalidate TLB Entries. */ /* Invalidate TLB Entries. */
control = sabre_read(p->controller_regs + SABRE_IOMMU_CONTROL); control = sabre_read(p->pbm_A.controller_regs + SABRE_IOMMU_CONTROL);
control |= SABRE_IOMMUCTRL_DENAB; control |= SABRE_IOMMUCTRL_DENAB;
sabre_write(p->controller_regs + SABRE_IOMMU_CONTROL, control); sabre_write(p->pbm_A.controller_regs + SABRE_IOMMU_CONTROL, control);
for(i = 0; i < 16; i++) { for(i = 0; i < 16; i++) {
sabre_write(p->controller_regs + SABRE_IOMMU_TAG + (i * 8UL), 0); sabre_write(p->pbm_A.controller_regs + SABRE_IOMMU_TAG + (i * 8UL), 0);
sabre_write(p->controller_regs + SABRE_IOMMU_DATA + (i * 8UL), 0); sabre_write(p->pbm_A.controller_regs + SABRE_IOMMU_DATA + (i * 8UL), 0);
} }
/* Leave diag mode enabled for full-flushing done /* Leave diag mode enabled for full-flushing done
...@@ -1260,9 +1257,9 @@ static void __init sabre_iommu_init(struct pci_controller_info *p, ...@@ -1260,9 +1257,9 @@ static void __init sabre_iommu_init(struct pci_controller_info *p,
iommu->dma_addr_mask = dma_mask; iommu->dma_addr_mask = dma_mask;
memset((char *)tsbbase, 0, PAGE_SIZE << order); memset((char *)tsbbase, 0, PAGE_SIZE << order);
sabre_write(p->controller_regs + SABRE_IOMMU_TSBBASE, __pa(tsbbase)); sabre_write(p->pbm_A.controller_regs + SABRE_IOMMU_TSBBASE, __pa(tsbbase));
control = sabre_read(p->controller_regs + SABRE_IOMMU_CONTROL); control = sabre_read(p->pbm_A.controller_regs + SABRE_IOMMU_CONTROL);
control &= ~(SABRE_IOMMUCTRL_TSBSZ | SABRE_IOMMUCTRL_TBWSZ); control &= ~(SABRE_IOMMUCTRL_TSBSZ | SABRE_IOMMUCTRL_TBWSZ);
control |= SABRE_IOMMUCTRL_ENAB; control |= SABRE_IOMMUCTRL_ENAB;
switch(tsbsize) { switch(tsbsize) {
...@@ -1279,7 +1276,7 @@ static void __init sabre_iommu_init(struct pci_controller_info *p, ...@@ -1279,7 +1276,7 @@ static void __init sabre_iommu_init(struct pci_controller_info *p,
prom_halt(); prom_halt();
break; break;
} }
sabre_write(p->controller_regs + SABRE_IOMMU_CONTROL, control); sabre_write(p->pbm_A.controller_regs + SABRE_IOMMU_CONTROL, control);
/* We start with no consistent mappings. */ /* We start with no consistent mappings. */
iommu->lowest_consistent_map = iommu->lowest_consistent_map =
...@@ -1295,8 +1292,8 @@ static void __init pbm_register_toplevel_resources(struct pci_controller_info *p ...@@ -1295,8 +1292,8 @@ static void __init pbm_register_toplevel_resources(struct pci_controller_info *p
struct pci_pbm_info *pbm) struct pci_pbm_info *pbm)
{ {
char *name = pbm->name; char *name = pbm->name;
unsigned long ibase = p->controller_regs + SABRE_IOSPACE; unsigned long ibase = p->pbm_A.controller_regs + SABRE_IOSPACE;
unsigned long mbase = p->controller_regs + SABRE_MEMSPACE; unsigned long mbase = p->pbm_A.controller_regs + SABRE_MEMSPACE;
unsigned int devfn; unsigned int devfn;
unsigned long first, last, i; unsigned long first, last, i;
u8 *addr, map; u8 *addr, map;
...@@ -1389,6 +1386,7 @@ static void __init sabre_pbm_init(struct pci_controller_info *p, int sabre_node, ...@@ -1389,6 +1386,7 @@ static void __init sabre_pbm_init(struct pci_controller_info *p, int sabre_node,
pbm = &p->pbm_B; pbm = &p->pbm_B;
else else
pbm = &p->pbm_A; pbm = &p->pbm_A;
pbm->chip_type = PBM_CHIP_TYPE_SABRE;
pbm->parent = p; pbm->parent = p;
pbm->prom_node = node; pbm->prom_node = node;
pbm->pci_first_slot = 1; pbm->pci_first_slot = 1;
...@@ -1475,11 +1473,11 @@ static void __init sabre_pbm_init(struct pci_controller_info *p, int sabre_node, ...@@ -1475,11 +1473,11 @@ static void __init sabre_pbm_init(struct pci_controller_info *p, int sabre_node,
pbm->io_space.name = pbm->mem_space.name = pbm->name; pbm->io_space.name = pbm->mem_space.name = pbm->name;
/* Hack up top-level resources. */ /* Hack up top-level resources. */
pbm->io_space.start = p->controller_regs + SABRE_IOSPACE; pbm->io_space.start = p->pbm_A.controller_regs + SABRE_IOSPACE;
pbm->io_space.end = pbm->io_space.start + (1UL << 24) - 1UL; pbm->io_space.end = pbm->io_space.start + (1UL << 24) - 1UL;
pbm->io_space.flags = IORESOURCE_IO; pbm->io_space.flags = IORESOURCE_IO;
pbm->mem_space.start = p->controller_regs + SABRE_MEMSPACE; pbm->mem_space.start = p->pbm_A.controller_regs + SABRE_MEMSPACE;
pbm->mem_space.end = pbm->mem_space.start + (unsigned long)dma_begin - 1UL; pbm->mem_space.end = pbm->mem_space.start + (unsigned long)dma_begin - 1UL;
pbm->mem_space.flags = IORESOURCE_MEM; pbm->mem_space.flags = IORESOURCE_MEM;
...@@ -1554,7 +1552,8 @@ void __init sabre_init(int pnode, char *model_name) ...@@ -1554,7 +1552,8 @@ void __init sabre_init(int pnode, char *model_name)
pci_controller_root = p; pci_controller_root = p;
spin_unlock_irqrestore(&pci_controller_lock, flags); spin_unlock_irqrestore(&pci_controller_lock, flags);
p->portid = upa_portid; p->pbm_A.portid = upa_portid;
p->pbm_B.portid = upa_portid;
p->index = pci_num_controllers++; p->index = pci_num_controllers++;
p->pbms_same_domain = 1; p->pbms_same_domain = 1;
p->scan_bus = sabre_scan_bus; p->scan_bus = sabre_scan_bus;
...@@ -1577,30 +1576,31 @@ void __init sabre_init(int pnode, char *model_name) ...@@ -1577,30 +1576,31 @@ void __init sabre_init(int pnode, char *model_name)
/* /*
* First REG in property is base of entire SABRE register space. * First REG in property is base of entire SABRE register space.
*/ */
p->controller_regs = pr_regs[0].phys_addr; p->pbm_A.controller_regs = pr_regs[0].phys_addr;
pci_dma_wsync = p->controller_regs + SABRE_WRSYNC; p->pbm_B.controller_regs = pr_regs[0].phys_addr;
pci_dma_wsync = p->pbm_A.controller_regs + SABRE_WRSYNC;
printk("PCI: Found SABRE, main regs at %016lx, wsync at %016lx\n", printk("PCI: Found SABRE, main regs at %016lx, wsync at %016lx\n",
p->controller_regs, pci_dma_wsync); p->pbm_A.controller_regs, pci_dma_wsync);
/* Clear interrupts */ /* Clear interrupts */
/* PCI first */ /* PCI first */
for (clear_irq = SABRE_ICLR_A_SLOT0; clear_irq < SABRE_ICLR_B_SLOT0 + 0x80; clear_irq += 8) for (clear_irq = SABRE_ICLR_A_SLOT0; clear_irq < SABRE_ICLR_B_SLOT0 + 0x80; clear_irq += 8)
sabre_write(p->controller_regs + clear_irq, 0x0UL); sabre_write(p->pbm_A.controller_regs + clear_irq, 0x0UL);
/* Then OBIO */ /* Then OBIO */
for (clear_irq = SABRE_ICLR_SCSI; clear_irq < SABRE_ICLR_SCSI + 0x80; clear_irq += 8) for (clear_irq = SABRE_ICLR_SCSI; clear_irq < SABRE_ICLR_SCSI + 0x80; clear_irq += 8)
sabre_write(p->controller_regs + clear_irq, 0x0UL); sabre_write(p->pbm_A.controller_regs + clear_irq, 0x0UL);
/* Error interrupts are enabled later after the bus scan. */ /* Error interrupts are enabled later after the bus scan. */
sabre_write(p->controller_regs + SABRE_PCICTRL, sabre_write(p->pbm_A.controller_regs + SABRE_PCICTRL,
(SABRE_PCICTRL_MRLEN | SABRE_PCICTRL_SERR | (SABRE_PCICTRL_MRLEN | SABRE_PCICTRL_SERR |
SABRE_PCICTRL_ARBPARK | SABRE_PCICTRL_AEN)); SABRE_PCICTRL_ARBPARK | SABRE_PCICTRL_AEN));
/* Now map in PCI config space for entire SABRE. */ /* Now map in PCI config space for entire SABRE. */
p->pbm_A.config_space = p->pbm_B.config_space = p->pbm_A.config_space = p->pbm_B.config_space =
(p->controller_regs + SABRE_CONFIGSPACE); (p->pbm_A.controller_regs + SABRE_CONFIGSPACE);
printk("SABRE: Shared PCI config space at %016lx\n", printk("SABRE: Shared PCI config space at %016lx\n",
p->pbm_A.config_space); p->pbm_A.config_space);
......
This diff is collapsed.
...@@ -128,6 +128,25 @@ struct pci_pbm_info { ...@@ -128,6 +128,25 @@ struct pci_pbm_info {
/* PCI controller we sit under. */ /* PCI controller we sit under. */
struct pci_controller_info *parent; struct pci_controller_info *parent;
/* Physical address base of controller registers. */
unsigned long controller_regs;
/* Physical address base of PBM registers. */
unsigned long pbm_regs;
/* Opaque 32-bit system bus Port ID. */
u32 portid;
/* Chipset version information. */
int chip_type;
#define PBM_CHIP_TYPE_SABRE 1
#define PBM_CHIP_TYPE_PSYCHO 2
#define PBM_CHIP_TYPE_SCHIZO 3
#define PBM_CHIP_TYPE_SCHIZO_PLUS 4
#define PBM_CHIP_TYPE_TOMATILLO 5
int chip_version;
int chip_revision;
/* Name used for top-level resources. */ /* Name used for top-level resources. */
char name[64]; char name[64];
...@@ -170,12 +189,6 @@ struct pci_controller_info { ...@@ -170,12 +189,6 @@ struct pci_controller_info {
/* List of all PCI controllers. */ /* List of all PCI controllers. */
struct pci_controller_info *next; struct pci_controller_info *next;
/* Physical address base of controller registers. */
unsigned long controller_regs;
/* Opaque 32-bit system bus Port ID. */
u32 portid;
/* Each controller gets a unique index, used mostly for /* Each controller gets a unique index, used mostly for
* error logging purposes. * error logging purposes.
*/ */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment