Commit a2fb23af authored by David S. Miller's avatar David S. Miller

[SPARC64]: Probe PCI bus using OF device tree.

Almost entirely taken from the 64-bit PowerPC PCI code.

This allowed to eliminate a ton of cruft from the sparc64
PCI layer.
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent deb66c45
This diff is collapsed.
This diff is collapsed.
......@@ -17,20 +17,7 @@ extern struct pci_controller_info *pci_controller_root;
extern int pci_num_controllers;
/* PCI bus scanning and fixup support. */
extern void pci_fixup_host_bridge_self(struct pci_bus *pbus);
extern void pci_fill_in_pbm_cookies(struct pci_bus *pbus,
struct pci_pbm_info *pbm,
struct device_node *prom_node);
extern void pci_record_assignments(struct pci_pbm_info *pbm,
struct pci_bus *pbus);
extern void pci_assign_unassigned(struct pci_pbm_info *pbm,
struct pci_bus *pbus);
extern void pci_fixup_irq(struct pci_pbm_info *pbm,
struct pci_bus *pbus);
extern void pci_determine_66mhz_disposition(struct pci_pbm_info *pbm,
struct pci_bus *pbus);
extern void pci_setup_busmastering(struct pci_pbm_info *pbm,
struct pci_bus *pbus);
extern struct pci_bus *pci_scan_one_pbm(struct pci_pbm_info *pbm);
extern void pci_register_legacy_regions(struct resource *io_res,
struct resource *mem_res);
......
......@@ -220,7 +220,6 @@ static inline void iommu_free_ctx(struct pci_iommu *iommu, int ctx)
*/
static void *pci_4u_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr_t *dma_addrp, gfp_t gfp)
{
struct pcidev_cookie *pcp;
struct pci_iommu *iommu;
iopte_t *iopte;
unsigned long flags, order, first_page;
......@@ -237,8 +236,7 @@ static void *pci_4u_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr
return NULL;
memset((char *)first_page, 0, PAGE_SIZE << order);
pcp = pdev->sysdata;
iommu = pcp->pbm->iommu;
iommu = pdev->dev.archdata.iommu;
spin_lock_irqsave(&iommu->lock, flags);
iopte = alloc_npages(iommu, size >> IO_PAGE_SHIFT);
......@@ -268,14 +266,12 @@ static void *pci_4u_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr
/* Free and unmap a consistent DMA translation. */
static void pci_4u_free_consistent(struct pci_dev *pdev, size_t size, void *cpu, dma_addr_t dvma)
{
struct pcidev_cookie *pcp;
struct pci_iommu *iommu;
iopte_t *iopte;
unsigned long flags, order, npages;
npages = IO_PAGE_ALIGN(size) >> IO_PAGE_SHIFT;
pcp = pdev->sysdata;
iommu = pcp->pbm->iommu;
iommu = pdev->dev.archdata.iommu;
iopte = iommu->page_table +
((dvma - iommu->page_table_map_base) >> IO_PAGE_SHIFT);
......@@ -295,7 +291,6 @@ static void pci_4u_free_consistent(struct pci_dev *pdev, size_t size, void *cpu,
*/
static dma_addr_t pci_4u_map_single(struct pci_dev *pdev, void *ptr, size_t sz, int direction)
{
struct pcidev_cookie *pcp;
struct pci_iommu *iommu;
struct pci_strbuf *strbuf;
iopte_t *base;
......@@ -304,9 +299,8 @@ static dma_addr_t pci_4u_map_single(struct pci_dev *pdev, void *ptr, size_t sz,
u32 bus_addr, ret;
unsigned long iopte_protection;
pcp = pdev->sysdata;
iommu = pcp->pbm->iommu;
strbuf = &pcp->pbm->stc;
iommu = pdev->dev.archdata.iommu;
strbuf = pdev->dev.archdata.stc;
if (unlikely(direction == PCI_DMA_NONE))
goto bad_no_ctx;
......@@ -416,7 +410,6 @@ static void pci_strbuf_flush(struct pci_strbuf *strbuf, struct pci_iommu *iommu,
/* Unmap a single streaming mode DMA translation. */
static void pci_4u_unmap_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_t sz, int direction)
{
struct pcidev_cookie *pcp;
struct pci_iommu *iommu;
struct pci_strbuf *strbuf;
iopte_t *base;
......@@ -428,9 +421,8 @@ static void pci_4u_unmap_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_
return;
}
pcp = pdev->sysdata;
iommu = pcp->pbm->iommu;
strbuf = &pcp->pbm->stc;
iommu = pdev->dev.archdata.iommu;
strbuf = pdev->dev.archdata.stc;
npages = IO_PAGE_ALIGN(bus_addr + sz) - (bus_addr & IO_PAGE_MASK);
npages >>= IO_PAGE_SHIFT;
......@@ -549,7 +541,6 @@ static inline void fill_sg(iopte_t *iopte, struct scatterlist *sg,
*/
static int pci_4u_map_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, int direction)
{
struct pcidev_cookie *pcp;
struct pci_iommu *iommu;
struct pci_strbuf *strbuf;
unsigned long flags, ctx, npages, iopte_protection;
......@@ -570,9 +561,8 @@ static int pci_4u_map_sg(struct pci_dev *pdev, struct scatterlist *sglist, int n
return 1;
}
pcp = pdev->sysdata;
iommu = pcp->pbm->iommu;
strbuf = &pcp->pbm->stc;
iommu = pdev->dev.archdata.iommu;
strbuf = pdev->dev.archdata.stc;
if (unlikely(direction == PCI_DMA_NONE))
goto bad_no_ctx;
......@@ -636,7 +626,6 @@ static int pci_4u_map_sg(struct pci_dev *pdev, struct scatterlist *sglist, int n
/* Unmap a set of streaming mode DMA translations. */
static void pci_4u_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, int direction)
{
struct pcidev_cookie *pcp;
struct pci_iommu *iommu;
struct pci_strbuf *strbuf;
iopte_t *base;
......@@ -648,9 +637,8 @@ static void pci_4u_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, in
WARN_ON(1);
}
pcp = pdev->sysdata;
iommu = pcp->pbm->iommu;
strbuf = &pcp->pbm->stc;
iommu = pdev->dev.archdata.iommu;
strbuf = pdev->dev.archdata.stc;
bus_addr = sglist->dma_address & IO_PAGE_MASK;
......@@ -696,14 +684,12 @@ static void pci_4u_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, in
*/
static void pci_4u_dma_sync_single_for_cpu(struct pci_dev *pdev, dma_addr_t bus_addr, size_t sz, int direction)
{
struct pcidev_cookie *pcp;
struct pci_iommu *iommu;
struct pci_strbuf *strbuf;
unsigned long flags, ctx, npages;
pcp = pdev->sysdata;
iommu = pcp->pbm->iommu;
strbuf = &pcp->pbm->stc;
iommu = pdev->dev.archdata.iommu;
strbuf = pdev->dev.archdata.stc;
if (!strbuf->strbuf_enabled)
return;
......@@ -736,15 +722,13 @@ static void pci_4u_dma_sync_single_for_cpu(struct pci_dev *pdev, dma_addr_t bus_
*/
static void pci_4u_dma_sync_sg_for_cpu(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, int direction)
{
struct pcidev_cookie *pcp;
struct pci_iommu *iommu;
struct pci_strbuf *strbuf;
unsigned long flags, ctx, npages, i;
u32 bus_addr;
pcp = pdev->sysdata;
iommu = pcp->pbm->iommu;
strbuf = &pcp->pbm->stc;
iommu = pdev->dev.archdata.iommu;
strbuf = pdev->dev.archdata.stc;
if (!strbuf->strbuf_enabled)
return;
......@@ -809,13 +793,12 @@ static void ali_sound_dma_hack(struct pci_dev *pdev, int set_bit)
int pci_dma_supported(struct pci_dev *pdev, u64 device_mask)
{
struct pcidev_cookie *pcp = pdev->sysdata;
u64 dma_addr_mask;
if (pdev == NULL) {
dma_addr_mask = 0xffffffff;
} else {
struct pci_iommu *iommu = pcp->pbm->iommu;
struct pci_iommu *iommu = pdev->dev.archdata.iommu;
dma_addr_mask = iommu->dma_addr_mask;
......
......@@ -905,8 +905,7 @@ static void psycho_resource_adjust(struct pci_dev *pdev,
static void psycho_base_address_update(struct pci_dev *pdev, int resource)
{
struct pcidev_cookie *pcp = pdev->sysdata;
struct pci_pbm_info *pbm = pcp->pbm;
struct pci_pbm_info *pbm = pdev->dev.archdata.host_controller;
struct resource *res, *root;
u32 reg;
int where, size, is_64bit;
......@@ -968,28 +967,7 @@ static void pbm_config_busmastering(struct pci_pbm_info *pbm)
static void pbm_scan_bus(struct pci_controller_info *p,
struct pci_pbm_info *pbm)
{
struct pcidev_cookie *cookie = kzalloc(sizeof(*cookie), GFP_KERNEL);
if (!cookie) {
prom_printf("PSYCHO: Critical allocation failure.\n");
prom_halt();
}
/* All we care about is the PBM. */
cookie->pbm = pbm;
pbm->pci_bus = pci_scan_bus(pbm->pci_first_busno,
p->pci_ops,
pbm);
pci_fixup_host_bridge_self(pbm->pci_bus);
pbm->pci_bus->self->sysdata = cookie;
pci_fill_in_pbm_cookies(pbm->pci_bus, pbm, pbm->prom_node);
pci_record_assignments(pbm, pbm->pci_bus);
pci_assign_unassigned(pbm, pbm->pci_bus);
pci_fixup_irq(pbm, pbm->pci_bus);
pci_determine_66mhz_disposition(pbm, pbm->pci_bus);
pci_setup_busmastering(pbm, pbm->pci_bus);
pbm->pci_bus = pci_scan_one_pbm(pbm);
}
static void psycho_scan_bus(struct pci_controller_info *p)
......
......@@ -710,7 +710,7 @@ static irqreturn_t sabre_pcierr_intr_other(struct pci_controller_info *p)
p->index);
ret = IRQ_HANDLED;
}
pci_read_config_word(sabre_root_bus->self,
pci_bus_read_config_word(sabre_root_bus, 0,
PCI_STATUS, &stat);
if (stat & (PCI_STATUS_PARITY |
PCI_STATUS_SIG_TARGET_ABORT |
......@@ -719,7 +719,7 @@ static irqreturn_t sabre_pcierr_intr_other(struct pci_controller_info *p)
PCI_STATUS_SIG_SYSTEM_ERROR)) {
printk("SABRE%d: PCI bus error, PCI_STATUS[%04x]\n",
p->index, stat);
pci_write_config_word(sabre_root_bus->self,
pci_bus_write_config_word(sabre_root_bus, 0,
PCI_STATUS, 0xffff);
ret = IRQ_HANDLED;
}
......@@ -887,8 +887,7 @@ static void sabre_resource_adjust(struct pci_dev *pdev,
static void sabre_base_address_update(struct pci_dev *pdev, int resource)
{
struct pcidev_cookie *pcp = pdev->sysdata;
struct pci_pbm_info *pbm = pcp->pbm;
struct pci_pbm_info *pbm = pdev->dev.archdata.host_controller;
struct resource *res;
unsigned long base;
u32 reg;
......@@ -978,27 +977,11 @@ static void apb_init(struct pci_controller_info *p, struct pci_bus *sabre_bus)
}
}
static struct pcidev_cookie *alloc_bridge_cookie(struct pci_pbm_info *pbm)
{
struct pcidev_cookie *cookie = kzalloc(sizeof(*cookie), GFP_KERNEL);
if (!cookie) {
prom_printf("SABRE: Critical allocation failure.\n");
prom_halt();
}
/* All we care about is the PBM. */
cookie->pbm = pbm;
return cookie;
}
static void sabre_scan_bus(struct pci_controller_info *p)
{
static int once;
struct pci_bus *sabre_bus, *pbus;
struct pci_pbm_info *pbm;
struct pcidev_cookie *cookie;
int sabres_scanned;
/* The APB bridge speaks to the Sabre host PCI bridge
......@@ -1020,13 +1003,9 @@ static void sabre_scan_bus(struct pci_controller_info *p)
}
once++;
cookie = alloc_bridge_cookie(&p->pbm_A);
sabre_bus = pci_scan_bus(p->pci_first_busno,
p->pci_ops,
&p->pbm_A);
pci_fixup_host_bridge_self(sabre_bus);
sabre_bus->self->sysdata = cookie;
sabre_bus = pci_scan_one_pbm(&p->pbm_A);
if (!sabre_bus)
return;
sabre_root_bus = sabre_bus;
......@@ -1043,19 +1022,9 @@ static void sabre_scan_bus(struct pci_controller_info *p)
} else
continue;
cookie = alloc_bridge_cookie(pbm);
pbus->self->sysdata = cookie;
sabres_scanned++;
pbus->sysdata = pbm;
pbm->pci_bus = pbus;
pci_fill_in_pbm_cookies(pbus, pbm, pbm->prom_node);
pci_record_assignments(pbm, pbus);
pci_assign_unassigned(pbm, pbus);
pci_fixup_irq(pbm, pbus);
pci_determine_66mhz_disposition(pbm, pbus);
pci_setup_busmastering(pbm, pbus);
}
if (!sabres_scanned) {
......@@ -1063,12 +1032,6 @@ static void sabre_scan_bus(struct pci_controller_info *p)
pbm = &p->pbm_A;
sabre_bus->sysdata = pbm;
pbm->pci_bus = sabre_bus;
pci_fill_in_pbm_cookies(sabre_bus, pbm, pbm->prom_node);
pci_record_assignments(pbm, sabre_bus);
pci_assign_unassigned(pbm, sabre_bus);
pci_fixup_irq(pbm, sabre_bus);
pci_determine_66mhz_disposition(pbm, sabre_bus);
pci_setup_busmastering(pbm, sabre_bus);
}
sabre_register_error_handlers(p);
......
......@@ -1232,28 +1232,7 @@ static void pbm_config_busmastering(struct pci_pbm_info *pbm)
static void pbm_scan_bus(struct pci_controller_info *p,
struct pci_pbm_info *pbm)
{
struct pcidev_cookie *cookie = kzalloc(sizeof(*cookie), GFP_KERNEL);
if (!cookie) {
prom_printf("%s: Critical allocation failure.\n", pbm->name);
prom_halt();
}
/* All we care about is the PBM. */
cookie->pbm = pbm;
pbm->pci_bus = pci_scan_bus(pbm->pci_first_busno,
p->pci_ops,
pbm);
pci_fixup_host_bridge_self(pbm->pci_bus);
pbm->pci_bus->self->sysdata = cookie;
pci_fill_in_pbm_cookies(pbm->pci_bus, pbm, pbm->prom_node);
pci_record_assignments(pbm, pbm->pci_bus);
pci_assign_unassigned(pbm, pbm->pci_bus);
pci_fixup_irq(pbm, pbm->pci_bus);
pci_determine_66mhz_disposition(pbm, pbm->pci_bus);
pci_setup_busmastering(pbm, pbm->pci_bus);
pbm->pci_bus = pci_scan_one_pbm(pbm);
}
static void __schizo_scan_bus(struct pci_controller_info *p,
......@@ -1297,8 +1276,7 @@ static void tomatillo_scan_bus(struct pci_controller_info *p)
static void schizo_base_address_update(struct pci_dev *pdev, int resource)
{
struct pcidev_cookie *pcp = pdev->sysdata;
struct pci_pbm_info *pbm = pcp->pbm;
struct pci_pbm_info *pbm = pdev->dev.archdata.host_controller;
struct resource *res, *root;
u32 reg;
int where, size, is_64bit;
......
This diff is collapsed.
......@@ -3,5 +3,21 @@
*
* This file is released under the GPLv2
*/
#include <asm-generic/device.h>
#ifndef _ASM_SPARC64_DEVICE_H
#define _ASM_SPARC64_DEVICE_H
struct device_node;
struct of_device;
struct dev_archdata {
void *iommu;
void *stc;
void *host_controller;
struct device_node *prom_node;
struct of_device *op;
unsigned int msi_num;
};
#endif /* _ASM_SPARC64_DEVICE_H */
......@@ -244,27 +244,4 @@ struct pci_controller_info {
unsigned int pci_last_busno;
};
/* PCI devices which are not bridges have this placed in their pci_dev
* sysdata member. This makes OBP aware PCI device drivers easier to
* code.
*/
struct pcidev_cookie {
struct pci_pbm_info *pbm;
struct device_node *prom_node;
struct of_device *op;
struct linux_prom_pci_registers prom_regs[PROMREG_MAX];
int num_prom_regs;
struct linux_prom_pci_registers prom_assignments[PROMREG_MAX];
int num_prom_assignments;
#ifdef CONFIG_PCI_MSI
unsigned int msi_num;
#endif
};
/* Currently these are the same across all PCI controllers
* we support. Someday they may not be...
*/
#define PCI_IRQ_IGN 0x000007c0 /* Interrupt Group Number */
#define PCI_IRQ_INO 0x0000003f /* Interrupt Number */
#endif /* !(__SPARC64_PBM_H) */
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