diff options
Diffstat (limited to 'include/asm-sparc64/pbm.h')
-rw-r--r-- | include/asm-sparc64/pbm.h | 248 |
1 files changed, 248 insertions, 0 deletions
diff --git a/include/asm-sparc64/pbm.h b/include/asm-sparc64/pbm.h new file mode 100644 index 0000000..9299963 --- /dev/null +++ b/include/asm-sparc64/pbm.h @@ -0,0 +1,248 @@ +/* $Id: pbm.h,v 1.27 2001/08/12 13:18:23 davem Exp $ + * pbm.h: UltraSparc PCI controller software state. + * + * Copyright (C) 1997, 1998, 1999 David S. Miller (davem@redhat.com) + */ + +#ifndef __SPARC64_PBM_H +#define __SPARC64_PBM_H + +#include <linux/types.h> +#include <linux/pci.h> +#include <linux/ioport.h> +#include <linux/spinlock.h> + +#include <asm/io.h> +#include <asm/page.h> +#include <asm/oplib.h> + +/* The abstraction used here is that there are PCI controllers, + * each with one (Sabre) or two (PSYCHO/SCHIZO) PCI bus modules + * underneath. Each PCI bus module uses an IOMMU (shared by both + * PBMs of a controller, or per-PBM), and if a streaming buffer + * is present, each PCI bus module has it's own. (ie. the IOMMU + * might be shared between PBMs, the STC is never shared) + * Furthermore, each PCI bus module controls it's own autonomous + * PCI bus. + */ + +#define PBM_LOGCLUSTERS 3 +#define PBM_NCLUSTERS (1 << PBM_LOGCLUSTERS) + +struct pci_controller_info; + +/* This contains the software state necessary to drive a PCI + * controller's IOMMU. + */ +struct pci_iommu { + /* This protects the controller's IOMMU and all + * streaming buffers underneath. + */ + spinlock_t lock; + + /* Context allocator. */ + unsigned int iommu_cur_ctx; + + /* IOMMU page table, a linear array of ioptes. */ + iopte_t *page_table; /* The page table itself. */ + int page_table_sz_bits; /* log2 of ow many pages does it map? */ + + /* Base PCI memory space address where IOMMU mappings + * begin. + */ + u32 page_table_map_base; + + /* IOMMU Controller Registers */ + unsigned long iommu_control; /* IOMMU control register */ + unsigned long iommu_tsbbase; /* IOMMU page table base register */ + unsigned long iommu_flush; /* IOMMU page flush register */ + unsigned long iommu_ctxflush; /* IOMMU context flush register */ + + /* This is a register in the PCI controller, which if + * read will have no side-effects but will guarantee + * completion of all previous writes into IOMMU/STC. + */ + unsigned long write_complete_reg; + + /* The lowest used consistent mapping entry. Since + * we allocate consistent maps out of cluster 0 this + * is relative to the beginning of closter 0. + */ + u32 lowest_consistent_map; + + /* In order to deal with some buggy third-party PCI bridges that + * do wrong prefetching, we never mark valid mappings as invalid. + * Instead we point them at this dummy page. + */ + unsigned long dummy_page; + unsigned long dummy_page_pa; + + /* If PBM_NCLUSTERS is ever decreased to 4 or lower, + * or if largest supported page_table_sz * 8K goes above + * 2GB, you must increase the size of the type of + * these counters. You have been duly warned. -DaveM + */ + struct { + u16 next; + u16 flush; + } alloc_info[PBM_NCLUSTERS]; + + /* Here a PCI controller driver describes the areas of + * PCI memory space where DMA to/from physical memory + * are addressed. Drivers interrogate the PCI layer + * if their device has addressing limitations. They + * do so via pci_dma_supported, and pass in a mask of + * DMA address bits their device can actually drive. + * + * The test for being usable is: + * (device_mask & dma_addr_mask) == dma_addr_mask + */ + u32 dma_addr_mask; +}; + +extern void pci_iommu_table_init(struct pci_iommu *, int); + +/* This describes a PCI bus module's streaming buffer. */ +struct pci_strbuf { + int strbuf_enabled; /* Present and using it? */ + + /* Streaming Buffer Control Registers */ + unsigned long strbuf_control; /* STC control register */ + unsigned long strbuf_pflush; /* STC page flush register */ + unsigned long strbuf_fsync; /* STC flush synchronization reg */ + unsigned long strbuf_ctxflush; /* STC context flush register */ + unsigned long strbuf_ctxmatch_base; /* STC context flush match reg */ + unsigned long strbuf_flushflag_pa; /* Physical address of flush flag */ + volatile unsigned long *strbuf_flushflag; /* The flush flag itself */ + + /* And this is the actual flush flag area. + * We allocate extra because the chips require + * a 64-byte aligned area. + */ + volatile unsigned long __flushflag_buf[(64 + (64 - 1)) / sizeof(long)]; +}; + +#define PCI_STC_FLUSHFLAG_INIT(STC) \ + (*((STC)->strbuf_flushflag) = 0UL) +#define PCI_STC_FLUSHFLAG_SET(STC) \ + (*((STC)->strbuf_flushflag) != 0UL) + +/* There can be quite a few ranges and interrupt maps on a PCI + * segment. Thus... + */ +#define PROM_PCIRNG_MAX 64 +#define PROM_PCIIMAP_MAX 64 + +struct pci_pbm_info { + /* PCI controller we sit under. */ + 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. */ + char name[64]; + + /* OBP specific information. */ + int prom_node; + char prom_name[64]; + struct linux_prom_pci_ranges pbm_ranges[PROM_PCIRNG_MAX]; + int num_pbm_ranges; + struct linux_prom_pci_intmap pbm_intmap[PROM_PCIIMAP_MAX]; + int num_pbm_intmap; + struct linux_prom_pci_intmask pbm_intmask; + u64 ino_bitmap; + + /* PBM I/O and Memory space resources. */ + struct resource io_space; + struct resource mem_space; + + /* Base of PCI Config space, can be per-PBM or shared. */ + unsigned long config_space; + + /* State of 66MHz capabilities on this PBM. */ + int is_66mhz_capable; + int all_devs_66mhz; + + /* This PBM's streaming buffer. */ + struct pci_strbuf stc; + + /* IOMMU state, potentially shared by both PBM segments. */ + struct pci_iommu *iommu; + + /* PCI slot mapping. */ + unsigned int pci_first_slot; + + /* Now things for the actual PCI bus probes. */ + unsigned int pci_first_busno; + unsigned int pci_last_busno; + struct pci_bus *pci_bus; +}; + +struct pci_controller_info { + /* List of all PCI controllers. */ + struct pci_controller_info *next; + + /* Each controller gets a unique index, used mostly for + * error logging purposes. + */ + int index; + + /* Do the PBMs both exist in the same PCI domain? */ + int pbms_same_domain; + + /* The PCI bus modules controlled by us. */ + struct pci_pbm_info pbm_A; + struct pci_pbm_info pbm_B; + + /* Operations which are controller specific. */ + void (*scan_bus)(struct pci_controller_info *); + unsigned int (*irq_build)(struct pci_pbm_info *, struct pci_dev *, unsigned int); + void (*base_address_update)(struct pci_dev *, int); + void (*resource_adjust)(struct pci_dev *, struct resource *, struct resource *); + + /* Now things for the actual PCI bus probes. */ + struct pci_ops *pci_ops; + unsigned int pci_first_busno; + unsigned int pci_last_busno; + + void *starfire_cookie; +}; + +/* 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; + char prom_name[64]; + int prom_node; + 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; +}; + +/* 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) */ |