提交 0278ef8b 编写于 作者: L Linus Torvalds

Merge master.kernel.org:/pub/scm/linux/kernel/git/davem/sparc-2.6

* master.kernel.org:/pub/scm/linux/kernel/git/davem/sparc-2.6: (67 commits)
  [SCSI] SUNESP: Complete driver rewrite to version 2.0
  [SPARC64]: Convert PCI over to generic struct iommu/strbuf.
  [SPARC]: device_node name constification fallout
  [SPARC64]: Convert SBUS over to generic iommu/strbuf structs.
  [SPARC64]: Add generic iommu and strbuf structs to iommu.h
  [SPARC64]: Consolidate {sbus,pci}_iommu_arena.
  [SPARC]: Make device_node name and type const
  [SPARC64]: constify some paramaters of OF routines
  [TIGON3]: of_get_property() returns const.
  [SPARC64]: Fix PCI rework to adhere to of_get_property() const return.
  [SPARC64]: Document and fix calculation of pages_avail.
  [SPARC64]: Make sure pbm->prom_node is setup easly enough in psycho.c
  [SPARC64]: Use bootmem_bootmap_pages() in choose_bootmap_pfn().
  [SPARC64]: Add proper header file extern for cmdline_memory_size.
  [SPARC64]: Kill sparc_ultra_dump_{i,d}tlb()
  [SPARC64]: Use DECLARE_BITMAP and BITS_TO_LONGS in mm/init.c
  [SPARC64]: Give move verbose show_mem() output just like i386.
  [SPARC64]: Mark show_mem() printk's with KERN_INFO.
  [SPARC64]: Kill kvaddr_to_phys() and friends.
  [SPARC64]: Privatize sun4u_get_pte() and fix name.
  ...
...@@ -36,7 +36,6 @@ lib-y = __divqu.o __remqu.o __divlu.o __remlu.o \ ...@@ -36,7 +36,6 @@ lib-y = __divqu.o __remqu.o __divlu.o __remlu.o \
$(ev6-y)csum_ipv6_magic.o \ $(ev6-y)csum_ipv6_magic.o \
$(ev6-y)clear_page.o \ $(ev6-y)clear_page.o \
$(ev6-y)copy_page.o \ $(ev6-y)copy_page.o \
strcasecmp.o \
fpreg.o \ fpreg.o \
callback_srm.o srm_puts.o srm_printk.o callback_srm.o srm_puts.o srm_printk.o
......
/*
* linux/arch/alpha/lib/strcasecmp.c
*/
#include <linux/string.h>
/* We handle nothing here except the C locale. Since this is used in
only one place, on strings known to contain only 7 bit ASCII, this
is ok. */
int strcasecmp(const char *a, const char *b)
{
int ca, cb;
do {
ca = *a++ & 0xff;
cb = *b++ & 0xff;
if (ca >= 'A' && ca <= 'Z')
ca += 'a' - 'A';
if (cb >= 'A' && cb <= 'Z')
cb += 'a' - 'A';
} while (ca == cb && ca != '\0');
return ca - cb;
}
...@@ -84,8 +84,6 @@ EXPORT_SYMBOL(strncpy); ...@@ -84,8 +84,6 @@ EXPORT_SYMBOL(strncpy);
EXPORT_SYMBOL(strcat); EXPORT_SYMBOL(strcat);
EXPORT_SYMBOL(strlen); EXPORT_SYMBOL(strlen);
EXPORT_SYMBOL(strcmp); EXPORT_SYMBOL(strcmp);
EXPORT_SYMBOL(strcasecmp);
EXPORT_SYMBOL(strncasecmp);
EXPORT_SYMBOL(csum_partial); EXPORT_SYMBOL(csum_partial);
EXPORT_SYMBOL(csum_partial_copy_generic); EXPORT_SYMBOL(csum_partial_copy_generic);
......
...@@ -7,13 +7,12 @@ EXTRA_CFLAGS += -mno-minimal-toc ...@@ -7,13 +7,12 @@ EXTRA_CFLAGS += -mno-minimal-toc
endif endif
ifeq ($(CONFIG_PPC_MERGE),y) ifeq ($(CONFIG_PPC_MERGE),y)
obj-y := string.o strcase.o obj-y := string.o
obj-$(CONFIG_PPC32) += div64.o copy_32.o checksum_32.o obj-$(CONFIG_PPC32) += div64.o copy_32.o checksum_32.o
endif endif
obj-$(CONFIG_PPC64) += checksum_64.o copypage_64.o copyuser_64.o \ obj-$(CONFIG_PPC64) += checksum_64.o copypage_64.o copyuser_64.o \
memcpy_64.o usercopy_64.o mem_64.o string.o \ memcpy_64.o usercopy_64.o mem_64.o string.o
strcase.o
obj-$(CONFIG_QUICC_ENGINE) += rheap.o obj-$(CONFIG_QUICC_ENGINE) += rheap.o
obj-$(CONFIG_XMON) += sstep.o obj-$(CONFIG_XMON) += sstep.o
obj-$(CONFIG_KPROBES) += sstep.o obj-$(CONFIG_KPROBES) += sstep.o
......
#include <linux/types.h>
#include <linux/ctype.h>
#include <linux/string.h>
int strcasecmp(const char *s1, const char *s2)
{
int c1, c2;
do {
c1 = tolower(*s1++);
c2 = tolower(*s2++);
} while (c1 == c2 && c1 != 0);
return c1 - c2;
}
int strncasecmp(const char *s1, const char *s2, size_t n)
{
int c1, c2;
do {
c1 = tolower(*s1++);
c2 = tolower(*s2++);
} while ((--n > 0) && c1 == c2 && c1 != 0);
return c1 - c2;
}
...@@ -93,8 +93,6 @@ EXPORT_SYMBOL(strncpy); ...@@ -93,8 +93,6 @@ EXPORT_SYMBOL(strncpy);
EXPORT_SYMBOL(strcat); EXPORT_SYMBOL(strcat);
EXPORT_SYMBOL(strlen); EXPORT_SYMBOL(strlen);
EXPORT_SYMBOL(strcmp); EXPORT_SYMBOL(strcmp);
EXPORT_SYMBOL(strcasecmp);
EXPORT_SYMBOL(strncasecmp);
EXPORT_SYMBOL(__div64_32); EXPORT_SYMBOL(__div64_32);
EXPORT_SYMBOL(csum_partial); EXPORT_SYMBOL(csum_partial);
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
# Makefile for ppc-specific library files.. # Makefile for ppc-specific library files..
# #
obj-y := checksum.o string.o strcase.o div64.o obj-y := checksum.o string.o div64.o
obj-$(CONFIG_8xx) += rheap.o obj-$(CONFIG_8xx) += rheap.o
obj-$(CONFIG_CPM2) += rheap.o obj-$(CONFIG_CPM2) += rheap.o
#include <linux/ctype.h>
#include <linux/types.h>
int strcasecmp(const char *s1, const char *s2)
{
int c1, c2;
do {
c1 = tolower(*s1++);
c2 = tolower(*s2++);
} while (c1 == c2 && c1 != 0);
return c1 - c2;
}
int strncasecmp(const char *s1, const char *s2, size_t n)
{
int c1, c2;
do {
c1 = tolower(*s1++);
c2 = tolower(*s2++);
} while ((--n > 0) && c1 == c2 && c1 != 0);
return c1 - c2;
}
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
# #
lib-y = delay.o memset.o memmove.o memchr.o \ lib-y = delay.o memset.o memmove.o memchr.o \
checksum.o strcasecmp.o strlen.o div64.o udivdi3.o \ checksum.o strlen.o div64.o udivdi3.o \
div64-generic.o div64-generic.o
memcpy-y := memcpy.o memcpy-y := memcpy.o
......
/*
* linux/arch/alpha/lib/strcasecmp.c
*/
#include <linux/string.h>
/* We handle nothing here except the C locale. Since this is used in
only one place, on strings known to contain only 7 bit ASCII, this
is ok. */
int strcasecmp(const char *a, const char *b)
{
int ca, cb;
do {
ca = *a++ & 0xff;
cb = *b++ & 0xff;
if (ca >= 'A' && ca <= 'Z')
ca += 'a' - 'A';
if (cb >= 'A' && cb <= 'Z')
cb += 'a' - 'A';
} while (ca == cb && ca != '\0');
return ca - cb;
}
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
struct linux_ebus *ebus_chain = NULL; struct linux_ebus *ebus_chain = NULL;
/* We are together with pcic.c under CONFIG_PCI. */ /* We are together with pcic.c under CONFIG_PCI. */
extern unsigned int pcic_pin_to_irq(unsigned int, char *name); extern unsigned int pcic_pin_to_irq(unsigned int, const char *name);
/* /*
* IRQ Blacklist * IRQ Blacklist
...@@ -69,7 +69,7 @@ static inline unsigned long ebus_alloc(size_t size) ...@@ -69,7 +69,7 @@ static inline unsigned long ebus_alloc(size_t size)
/* /*
*/ */
int __init ebus_blacklist_irq(char *name) int __init ebus_blacklist_irq(const char *name)
{ {
struct ebus_device_irq *dp; struct ebus_device_irq *dp;
...@@ -86,8 +86,8 @@ int __init ebus_blacklist_irq(char *name) ...@@ -86,8 +86,8 @@ int __init ebus_blacklist_irq(char *name)
void __init fill_ebus_child(struct device_node *dp, void __init fill_ebus_child(struct device_node *dp,
struct linux_ebus_child *dev) struct linux_ebus_child *dev)
{ {
int *regs; const int *regs;
int *irqs; const int *irqs;
int i, len; int i, len;
dev->prom_node = dp; dev->prom_node = dp;
...@@ -146,9 +146,9 @@ void __init fill_ebus_child(struct device_node *dp, ...@@ -146,9 +146,9 @@ void __init fill_ebus_child(struct device_node *dp,
void __init fill_ebus_device(struct device_node *dp, struct linux_ebus_device *dev) void __init fill_ebus_device(struct device_node *dp, struct linux_ebus_device *dev)
{ {
struct linux_prom_registers *regs; const struct linux_prom_registers *regs;
struct linux_ebus_child *child; struct linux_ebus_child *child;
int *irqs; const int *irqs;
int i, n, len; int i, n, len;
unsigned long baseaddr; unsigned long baseaddr;
...@@ -269,7 +269,7 @@ void __init fill_ebus_device(struct device_node *dp, struct linux_ebus_device *d ...@@ -269,7 +269,7 @@ void __init fill_ebus_device(struct device_node *dp, struct linux_ebus_device *d
void __init ebus_init(void) void __init ebus_init(void)
{ {
struct linux_prom_pci_registers *regs; const struct linux_prom_pci_registers *regs;
struct linux_pbm_info *pbm; struct linux_pbm_info *pbm;
struct linux_ebus_device *dev; struct linux_ebus_device *dev;
struct linux_ebus *ebus; struct linux_ebus *ebus;
......
...@@ -210,7 +210,7 @@ struct of_bus { ...@@ -210,7 +210,7 @@ struct of_bus {
int *addrc, int *sizec); int *addrc, int *sizec);
int (*map)(u32 *addr, const u32 *range, int (*map)(u32 *addr, const u32 *range,
int na, int ns, int pna); int na, int ns, int pna);
unsigned int (*get_flags)(u32 *addr); unsigned int (*get_flags)(const u32 *addr);
}; };
/* /*
...@@ -270,7 +270,7 @@ static int of_bus_default_map(u32 *addr, const u32 *range, ...@@ -270,7 +270,7 @@ static int of_bus_default_map(u32 *addr, const u32 *range,
return 0; return 0;
} }
static unsigned int of_bus_default_get_flags(u32 *addr) static unsigned int of_bus_default_get_flags(const u32 *addr)
{ {
return IORESOURCE_MEM; return IORESOURCE_MEM;
} }
...@@ -334,7 +334,7 @@ static int of_bus_pci_map(u32 *addr, const u32 *range, ...@@ -334,7 +334,7 @@ static int of_bus_pci_map(u32 *addr, const u32 *range,
return 0; return 0;
} }
static unsigned int of_bus_pci_get_flags(u32 *addr) static unsigned int of_bus_pci_get_flags(const u32 *addr)
{ {
unsigned int flags = 0; unsigned int flags = 0;
u32 w = addr[0]; u32 w = addr[0];
...@@ -375,7 +375,7 @@ static int of_bus_sbus_map(u32 *addr, const u32 *range, int na, int ns, int pna) ...@@ -375,7 +375,7 @@ static int of_bus_sbus_map(u32 *addr, const u32 *range, int na, int ns, int pna)
return of_bus_default_map(addr, range, na, ns, pna); return of_bus_default_map(addr, range, na, ns, pna);
} }
static unsigned int of_bus_sbus_get_flags(u32 *addr) static unsigned int of_bus_sbus_get_flags(const u32 *addr)
{ {
return IORESOURCE_MEM; return IORESOURCE_MEM;
} }
...@@ -432,7 +432,7 @@ static int __init build_one_resource(struct device_node *parent, ...@@ -432,7 +432,7 @@ static int __init build_one_resource(struct device_node *parent,
u32 *addr, u32 *addr,
int na, int ns, int pna) int na, int ns, int pna)
{ {
u32 *ranges; const u32 *ranges;
unsigned int rlen; unsigned int rlen;
int rone; int rone;
...@@ -470,7 +470,7 @@ static void __init build_device_resources(struct of_device *op, ...@@ -470,7 +470,7 @@ static void __init build_device_resources(struct of_device *op,
struct of_bus *bus; struct of_bus *bus;
int na, ns; int na, ns;
int index, num_reg; int index, num_reg;
void *preg; const void *preg;
if (!parent) if (!parent)
return; return;
...@@ -492,7 +492,7 @@ static void __init build_device_resources(struct of_device *op, ...@@ -492,7 +492,7 @@ static void __init build_device_resources(struct of_device *op,
for (index = 0; index < num_reg; index++) { for (index = 0; index < num_reg; index++) {
struct resource *r = &op->resource[index]; struct resource *r = &op->resource[index];
u32 addr[OF_MAX_ADDR_CELLS]; u32 addr[OF_MAX_ADDR_CELLS];
u32 *reg = (preg + (index * ((na + ns) * 4))); const u32 *reg = (preg + (index * ((na + ns) * 4)));
struct device_node *dp = op->node; struct device_node *dp = op->node;
struct device_node *pp = p_op->node; struct device_node *pp = p_op->node;
struct of_bus *pbus, *dbus; struct of_bus *pbus, *dbus;
...@@ -559,7 +559,7 @@ static struct of_device * __init scan_one_device(struct device_node *dp, ...@@ -559,7 +559,7 @@ static struct of_device * __init scan_one_device(struct device_node *dp,
struct device *parent) struct device *parent)
{ {
struct of_device *op = kzalloc(sizeof(*op), GFP_KERNEL); struct of_device *op = kzalloc(sizeof(*op), GFP_KERNEL);
struct linux_prom_irqs *intr; const struct linux_prom_irqs *intr;
int len, i; int len, i;
if (!op) if (!op)
...@@ -579,7 +579,8 @@ static struct of_device * __init scan_one_device(struct device_node *dp, ...@@ -579,7 +579,8 @@ static struct of_device * __init scan_one_device(struct device_node *dp,
for (i = 0; i < op->num_irqs; i++) for (i = 0; i < op->num_irqs; i++)
op->irqs[i] = intr[i].pri; op->irqs[i] = intr[i].pri;
} else { } else {
unsigned int *irq = of_get_property(dp, "interrupts", &len); const unsigned int *irq =
of_get_property(dp, "interrupts", &len);
if (irq) { if (irq) {
op->num_irqs = len / sizeof(unsigned int); op->num_irqs = len / sizeof(unsigned int);
...@@ -594,7 +595,7 @@ static struct of_device * __init scan_one_device(struct device_node *dp, ...@@ -594,7 +595,7 @@ static struct of_device * __init scan_one_device(struct device_node *dp,
0, 0, 1, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 0, 0, 0, 1, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 0,
}; };
struct device_node *io_unit, *sbi = dp->parent; struct device_node *io_unit, *sbi = dp->parent;
struct linux_prom_registers *regs; const struct linux_prom_registers *regs;
int board, slot; int board, slot;
while (sbi) { while (sbi) {
......
...@@ -37,8 +37,6 @@ ...@@ -37,8 +37,6 @@
#include <asm/irq_regs.h> #include <asm/irq_regs.h>
unsigned int pcic_pin_to_irq(unsigned int pin, char *name);
/* /*
* I studied different documents and many live PROMs both from 2.30 * I studied different documents and many live PROMs both from 2.30
* family and 3.xx versions. I came to the amazing conclusion: there is * family and 3.xx versions. I came to the amazing conclusion: there is
...@@ -681,7 +679,7 @@ void __devinit pcibios_fixup_bus(struct pci_bus *bus) ...@@ -681,7 +679,7 @@ void __devinit pcibios_fixup_bus(struct pci_bus *bus)
* pcic_pin_to_irq() is exported to ebus.c. * pcic_pin_to_irq() is exported to ebus.c.
*/ */
unsigned int unsigned int
pcic_pin_to_irq(unsigned int pin, char *name) pcic_pin_to_irq(unsigned int pin, const char *name)
{ {
struct linux_pcic *pcic = &pcic0; struct linux_pcic *pcic = &pcic0;
unsigned int irq; unsigned int irq;
......
...@@ -32,12 +32,13 @@ static struct device_node *allnodes; ...@@ -32,12 +32,13 @@ static struct device_node *allnodes;
*/ */
static DEFINE_RWLOCK(devtree_lock); static DEFINE_RWLOCK(devtree_lock);
int of_device_is_compatible(struct device_node *device, const char *compat) int of_device_is_compatible(const struct device_node *device,
const char *compat)
{ {
const char* cp; const char* cp;
int cplen, l; int cplen, l;
cp = (char *) of_get_property(device, "compatible", &cplen); cp = of_get_property(device, "compatible", &cplen);
if (cp == NULL) if (cp == NULL)
return 0; return 0;
while (cplen > 0) { while (cplen > 0) {
...@@ -150,13 +151,14 @@ struct device_node *of_find_compatible_node(struct device_node *from, ...@@ -150,13 +151,14 @@ struct device_node *of_find_compatible_node(struct device_node *from,
} }
EXPORT_SYMBOL(of_find_compatible_node); EXPORT_SYMBOL(of_find_compatible_node);
struct property *of_find_property(struct device_node *np, const char *name, struct property *of_find_property(const struct device_node *np,
const char *name,
int *lenp) int *lenp)
{ {
struct property *pp; struct property *pp;
for (pp = np->properties; pp != 0; pp = pp->next) { for (pp = np->properties; pp != 0; pp = pp->next) {
if (strcmp(pp->name, name) == 0) { if (strcasecmp(pp->name, name) == 0) {
if (lenp != 0) if (lenp != 0)
*lenp = pp->length; *lenp = pp->length;
break; break;
...@@ -170,7 +172,8 @@ EXPORT_SYMBOL(of_find_property); ...@@ -170,7 +172,8 @@ EXPORT_SYMBOL(of_find_property);
* Find a property with a given name for a given node * Find a property with a given name for a given node
* and return the value. * and return the value.
*/ */
void *of_get_property(struct device_node *np, const char *name, int *lenp) const void *of_get_property(const struct device_node *np, const char *name,
int *lenp)
{ {
struct property *pp = of_find_property(np,name,lenp); struct property *pp = of_find_property(np,name,lenp);
return pp ? pp->value : NULL; return pp ? pp->value : NULL;
...@@ -192,7 +195,7 @@ EXPORT_SYMBOL(of_getintprop_default); ...@@ -192,7 +195,7 @@ EXPORT_SYMBOL(of_getintprop_default);
int of_n_addr_cells(struct device_node *np) int of_n_addr_cells(struct device_node *np)
{ {
int* ip; const int* ip;
do { do {
if (np->parent) if (np->parent)
np = np->parent; np = np->parent;
...@@ -207,7 +210,7 @@ EXPORT_SYMBOL(of_n_addr_cells); ...@@ -207,7 +210,7 @@ EXPORT_SYMBOL(of_n_addr_cells);
int of_n_size_cells(struct device_node *np) int of_n_size_cells(struct device_node *np)
{ {
int* ip; const int* ip;
do { do {
if (np->parent) if (np->parent)
np = np->parent; np = np->parent;
...@@ -239,7 +242,7 @@ int of_set_property(struct device_node *dp, const char *name, void *val, int len ...@@ -239,7 +242,7 @@ int of_set_property(struct device_node *dp, const char *name, void *val, int len
while (*prevp) { while (*prevp) {
struct property *prop = *prevp; struct property *prop = *prevp;
if (!strcmp(prop->name, name)) { if (!strcasecmp(prop->name, name)) {
void *old_val = prop->value; void *old_val = prop->value;
int ret; int ret;
......
...@@ -301,7 +301,7 @@ static __inline__ void sun4_clock_probe(void) ...@@ -301,7 +301,7 @@ static __inline__ void sun4_clock_probe(void)
static int __devinit clock_probe(struct of_device *op, const struct of_device_id *match) static int __devinit clock_probe(struct of_device *op, const struct of_device_id *match)
{ {
struct device_node *dp = op->node; struct device_node *dp = op->node;
char *model = of_get_property(dp, "model", NULL); const char *model = of_get_property(dp, "model", NULL);
if (!model) if (!model)
return -ENODEV; return -ENODEV;
......
...@@ -19,6 +19,14 @@ config SPARC64 ...@@ -19,6 +19,14 @@ config SPARC64
SPARC64 ports; its web page is available at SPARC64 ports; its web page is available at
<http://www.ultralinux.org/>. <http://www.ultralinux.org/>.
config GENERIC_TIME
bool
default y
config GENERIC_CLOCKEVENTS
bool
default y
config 64BIT config 64BIT
def_bool y def_bool y
...@@ -34,10 +42,6 @@ config LOCKDEP_SUPPORT ...@@ -34,10 +42,6 @@ config LOCKDEP_SUPPORT
bool bool
default y default y
config TIME_INTERPOLATION
bool
default y
config ARCH_MAY_HAVE_PC_FDC config ARCH_MAY_HAVE_PC_FDC
bool bool
default y default y
...@@ -113,6 +117,8 @@ config GENERIC_HARDIRQS ...@@ -113,6 +117,8 @@ config GENERIC_HARDIRQS
menu "General machine setup" menu "General machine setup"
source "kernel/time/Kconfig"
config SMP config SMP
bool "Symmetric multi-processing support" bool "Symmetric multi-processing support"
---help--- ---help---
...@@ -214,6 +220,7 @@ config ARCH_SPARSEMEM_ENABLE ...@@ -214,6 +220,7 @@ config ARCH_SPARSEMEM_ENABLE
config ARCH_SPARSEMEM_DEFAULT config ARCH_SPARSEMEM_DEFAULT
def_bool y def_bool y
select SPARSEMEM_STATIC
config LARGE_ALLOCS config LARGE_ALLOCS
def_bool y def_bool y
......
...@@ -32,7 +32,7 @@ static void central_probe_failure(int line) ...@@ -32,7 +32,7 @@ static void central_probe_failure(int line)
static void central_ranges_init(struct linux_central *central) static void central_ranges_init(struct linux_central *central)
{ {
struct device_node *dp = central->prom_node; struct device_node *dp = central->prom_node;
void *pval; const void *pval;
int len; int len;
central->num_central_ranges = 0; central->num_central_ranges = 0;
...@@ -47,7 +47,7 @@ static void central_ranges_init(struct linux_central *central) ...@@ -47,7 +47,7 @@ static void central_ranges_init(struct linux_central *central)
static void fhc_ranges_init(struct linux_fhc *fhc) static void fhc_ranges_init(struct linux_fhc *fhc)
{ {
struct device_node *dp = fhc->prom_node; struct device_node *dp = fhc->prom_node;
void *pval; const void *pval;
int len; int len;
fhc->num_fhc_ranges = 0; fhc->num_fhc_ranges = 0;
...@@ -119,7 +119,7 @@ static unsigned long prom_reg_to_paddr(struct linux_prom_registers *r) ...@@ -119,7 +119,7 @@ static unsigned long prom_reg_to_paddr(struct linux_prom_registers *r)
static void probe_other_fhcs(void) static void probe_other_fhcs(void)
{ {
struct device_node *dp; struct device_node *dp;
struct linux_prom64_registers *fpregs; const struct linux_prom64_registers *fpregs;
for_each_node_by_name(dp, "fhc") { for_each_node_by_name(dp, "fhc") {
struct linux_fhc *fhc; struct linux_fhc *fhc;
...@@ -190,7 +190,8 @@ static void probe_clock_board(struct linux_central *central, ...@@ -190,7 +190,8 @@ static void probe_clock_board(struct linux_central *central,
struct device_node *fp) struct device_node *fp)
{ {
struct device_node *dp; struct device_node *dp;
struct linux_prom_registers cregs[3], *pr; struct linux_prom_registers cregs[3];
const struct linux_prom_registers *pr;
int nslots, tmp, nregs; int nslots, tmp, nregs;
dp = fp->child; dp = fp->child;
...@@ -299,7 +300,8 @@ static void init_all_fhc_hw(void) ...@@ -299,7 +300,8 @@ static void init_all_fhc_hw(void)
void central_probe(void) void central_probe(void)
{ {
struct linux_prom_registers fpregs[6], *pr; struct linux_prom_registers fpregs[6];
const struct linux_prom_registers *pr;
struct linux_fhc *fhc; struct linux_fhc *fhc;
struct device_node *dp, *fp; struct device_node *dp, *fp;
int err; int err;
......
...@@ -343,8 +343,8 @@ static int init_one_mctrl(struct device_node *dp) ...@@ -343,8 +343,8 @@ static int init_one_mctrl(struct device_node *dp)
{ {
struct mctrl_info *mp = kzalloc(sizeof(*mp), GFP_KERNEL); struct mctrl_info *mp = kzalloc(sizeof(*mp), GFP_KERNEL);
int portid = of_getintprop_default(dp, "portid", -1); int portid = of_getintprop_default(dp, "portid", -1);
struct linux_prom64_registers *regs; const struct linux_prom64_registers *regs;
void *pval; const void *pval;
int len; int len;
if (!mp) if (!mp)
......
...@@ -285,7 +285,7 @@ static void __init fill_ebus_child(struct device_node *dp, ...@@ -285,7 +285,7 @@ static void __init fill_ebus_child(struct device_node *dp,
int non_standard_regs) int non_standard_regs)
{ {
struct of_device *op; struct of_device *op;
int *regs; const int *regs;
int i, len; int i, len;
dev->prom_node = dp; dev->prom_node = dp;
...@@ -438,11 +438,9 @@ static struct pci_dev *find_next_ebus(struct pci_dev *start, int *is_rio_p) ...@@ -438,11 +438,9 @@ static struct pci_dev *find_next_ebus(struct pci_dev *start, int *is_rio_p)
void __init ebus_init(void) void __init ebus_init(void)
{ {
struct pci_pbm_info *pbm;
struct linux_ebus_device *dev; struct linux_ebus_device *dev;
struct linux_ebus *ebus; struct linux_ebus *ebus;
struct pci_dev *pdev; struct pci_dev *pdev;
struct pcidev_cookie *cookie;
struct device_node *dp; struct device_node *dp;
int is_rio; int is_rio;
int num_ebus = 0; int num_ebus = 0;
...@@ -453,8 +451,7 @@ void __init ebus_init(void) ...@@ -453,8 +451,7 @@ void __init ebus_init(void)
return; return;
} }
cookie = pdev->sysdata; dp = pci_device_to_OF_node(pdev);
dp = cookie->prom_node;
ebus_chain = ebus = ebus_alloc(sizeof(struct linux_ebus)); ebus_chain = ebus = ebus_alloc(sizeof(struct linux_ebus));
ebus->next = NULL; ebus->next = NULL;
...@@ -480,8 +477,7 @@ void __init ebus_init(void) ...@@ -480,8 +477,7 @@ void __init ebus_init(void)
break; break;
} }
ebus->is_rio = is_rio; ebus->is_rio = is_rio;
cookie = pdev->sysdata; dp = pci_device_to_OF_node(pdev);
dp = cookie->prom_node;
continue; continue;
} }
printk("ebus%d:", num_ebus); printk("ebus%d:", num_ebus);
...@@ -489,7 +485,6 @@ void __init ebus_init(void) ...@@ -489,7 +485,6 @@ void __init ebus_init(void)
ebus->index = num_ebus; ebus->index = num_ebus;
ebus->prom_node = dp; ebus->prom_node = dp;
ebus->self = pdev; ebus->self = pdev;
ebus->parent = pbm = cookie->pbm;
ebus->ofdev.node = dp; ebus->ofdev.node = dp;
ebus->ofdev.dev.parent = &pdev->dev; ebus->ofdev.dev.parent = &pdev->dev;
...@@ -531,8 +526,7 @@ void __init ebus_init(void) ...@@ -531,8 +526,7 @@ void __init ebus_init(void)
if (!pdev) if (!pdev)
break; break;
cookie = pdev->sysdata; dp = pci_device_to_OF_node(pdev);
dp = cookie->prom_node;
ebus->next = ebus_alloc(sizeof(struct linux_ebus)); ebus->next = ebus_alloc(sizeof(struct linux_ebus));
ebus = ebus->next; ebus = ebus->next;
......
...@@ -589,32 +589,6 @@ void ack_bad_irq(unsigned int virt_irq) ...@@ -589,32 +589,6 @@ void ack_bad_irq(unsigned int virt_irq)
ino, virt_irq); ino, virt_irq);
} }
#ifndef CONFIG_SMP
extern irqreturn_t timer_interrupt(int, void *);
void timer_irq(int irq, struct pt_regs *regs)
{
unsigned long clr_mask = 1 << irq;
unsigned long tick_mask = tick_ops->softint_mask;
struct pt_regs *old_regs;
if (get_softint() & tick_mask) {
irq = 0;
clr_mask = tick_mask;
}
clear_softint(clr_mask);
old_regs = set_irq_regs(regs);
irq_enter();
kstat_this_cpu.irqs[0]++;
timer_interrupt(irq, NULL);
irq_exit();
set_irq_regs(old_regs);
}
#endif
void handler_irq(int irq, struct pt_regs *regs) void handler_irq(int irq, struct pt_regs *regs)
{ {
struct ino_bucket *bucket; struct ino_bucket *bucket;
...@@ -653,7 +627,7 @@ static u64 prom_limit0, prom_limit1; ...@@ -653,7 +627,7 @@ static u64 prom_limit0, prom_limit1;
static void map_prom_timers(void) static void map_prom_timers(void)
{ {
struct device_node *dp; struct device_node *dp;
unsigned int *addr; const unsigned int *addr;
/* PROM timer node hangs out in the top level of device siblings... */ /* PROM timer node hangs out in the top level of device siblings... */
dp = of_find_node_by_path("/"); dp = of_find_node_by_path("/");
......
...@@ -24,27 +24,9 @@ static void __init report_dev(struct sparc_isa_device *isa_dev, int child) ...@@ -24,27 +24,9 @@ static void __init report_dev(struct sparc_isa_device *isa_dev, int child)
static void __init isa_dev_get_resource(struct sparc_isa_device *isa_dev) static void __init isa_dev_get_resource(struct sparc_isa_device *isa_dev)
{ {
struct linux_prom_registers *pregs; struct of_device *op = of_find_device_by_node(isa_dev->prom_node);
unsigned long base, len;
int prop_len;
pregs = of_get_property(isa_dev->prom_node, "reg", &prop_len);
if (!pregs)
return;
/* Only the first one is interesting. */
len = pregs[0].reg_size;
base = (((unsigned long)pregs[0].which_io << 32) |
(unsigned long)pregs[0].phys_addr);
base += isa_dev->bus->parent->io_space.start;
isa_dev->resource.start = base;
isa_dev->resource.end = (base + len - 1UL);
isa_dev->resource.flags = IORESOURCE_IO;
isa_dev->resource.name = isa_dev->prom_node->name;
request_resource(&isa_dev->bus->parent->io_space, memcpy(&isa_dev->resource, &op->resource[0], sizeof(struct resource));
&isa_dev->resource);
} }
static void __init isa_dev_get_irq(struct sparc_isa_device *isa_dev) static void __init isa_dev_get_irq(struct sparc_isa_device *isa_dev)
...@@ -158,19 +140,10 @@ void __init isa_init(void) ...@@ -158,19 +140,10 @@ void __init isa_init(void)
pdev = NULL; pdev = NULL;
while ((pdev = pci_get_device(vendor, device, pdev)) != NULL) { while ((pdev = pci_get_device(vendor, device, pdev)) != NULL) {
struct pcidev_cookie *pdev_cookie;
struct pci_pbm_info *pbm;
struct sparc_isa_bridge *isa_br; struct sparc_isa_bridge *isa_br;
struct device_node *dp; struct device_node *dp;
pdev_cookie = pdev->sysdata; dp = pci_device_to_OF_node(pdev);
if (!pdev_cookie) {
printk("ISA: Warning, ISA bridge ignored due to "
"lack of OBP data.\n");
continue;
}
pbm = pdev_cookie->pbm;
dp = pdev_cookie->prom_node;
isa_br = kzalloc(sizeof(*isa_br), GFP_KERNEL); isa_br = kzalloc(sizeof(*isa_br), GFP_KERNEL);
if (!isa_br) { if (!isa_br) {
...@@ -195,10 +168,9 @@ void __init isa_init(void) ...@@ -195,10 +168,9 @@ void __init isa_init(void)
isa_br->next = isa_chain; isa_br->next = isa_chain;
isa_chain = isa_br; isa_chain = isa_br;
isa_br->parent = pbm;
isa_br->self = pdev; isa_br->self = pdev;
isa_br->index = index++; isa_br->index = index++;
isa_br->prom_node = pdev_cookie->prom_node; isa_br->prom_node = dp;
printk("isa%d:", isa_br->index); printk("isa%d:", isa_br->index);
......
...@@ -245,7 +245,7 @@ struct of_bus { ...@@ -245,7 +245,7 @@ struct of_bus {
int *addrc, int *sizec); int *addrc, int *sizec);
int (*map)(u32 *addr, const u32 *range, int (*map)(u32 *addr, const u32 *range,
int na, int ns, int pna); int na, int ns, int pna);
unsigned int (*get_flags)(u32 *addr); unsigned int (*get_flags)(const u32 *addr);
}; };
/* /*
...@@ -305,7 +305,7 @@ static int of_bus_default_map(u32 *addr, const u32 *range, ...@@ -305,7 +305,7 @@ static int of_bus_default_map(u32 *addr, const u32 *range,
return 0; return 0;
} }
static unsigned int of_bus_default_get_flags(u32 *addr) static unsigned int of_bus_default_get_flags(const u32 *addr)
{ {
return IORESOURCE_MEM; return IORESOURCE_MEM;
} }
...@@ -317,6 +317,11 @@ static unsigned int of_bus_default_get_flags(u32 *addr) ...@@ -317,6 +317,11 @@ static unsigned int of_bus_default_get_flags(u32 *addr)
static int of_bus_pci_match(struct device_node *np) static int of_bus_pci_match(struct device_node *np)
{ {
if (!strcmp(np->type, "pci") || !strcmp(np->type, "pciex")) { if (!strcmp(np->type, "pci") || !strcmp(np->type, "pciex")) {
const char *model = of_get_property(np, "model", NULL);
if (model && !strcmp(model, "SUNW,simba"))
return 0;
/* Do not do PCI specific frobbing if the /* Do not do PCI specific frobbing if the
* PCI bridge lacks a ranges property. We * PCI bridge lacks a ranges property. We
* want to pass it through up to the next * want to pass it through up to the next
...@@ -332,6 +337,21 @@ static int of_bus_pci_match(struct device_node *np) ...@@ -332,6 +337,21 @@ static int of_bus_pci_match(struct device_node *np)
return 0; return 0;
} }
static int of_bus_simba_match(struct device_node *np)
{
const char *model = of_get_property(np, "model", NULL);
if (model && !strcmp(model, "SUNW,simba"))
return 1;
return 0;
}
static int of_bus_simba_map(u32 *addr, const u32 *range,
int na, int ns, int pna)
{
return 0;
}
static void of_bus_pci_count_cells(struct device_node *np, static void of_bus_pci_count_cells(struct device_node *np,
int *addrc, int *sizec) int *addrc, int *sizec)
{ {
...@@ -369,7 +389,7 @@ static int of_bus_pci_map(u32 *addr, const u32 *range, ...@@ -369,7 +389,7 @@ static int of_bus_pci_map(u32 *addr, const u32 *range,
return 0; return 0;
} }
static unsigned int of_bus_pci_get_flags(u32 *addr) static unsigned int of_bus_pci_get_flags(const u32 *addr)
{ {
unsigned int flags = 0; unsigned int flags = 0;
u32 w = addr[0]; u32 w = addr[0];
...@@ -436,6 +456,15 @@ static struct of_bus of_busses[] = { ...@@ -436,6 +456,15 @@ static struct of_bus of_busses[] = {
.map = of_bus_pci_map, .map = of_bus_pci_map,
.get_flags = of_bus_pci_get_flags, .get_flags = of_bus_pci_get_flags,
}, },
/* SIMBA */
{
.name = "simba",
.addr_prop_name = "assigned-addresses",
.match = of_bus_simba_match,
.count_cells = of_bus_pci_count_cells,
.map = of_bus_simba_map,
.get_flags = of_bus_pci_get_flags,
},
/* SBUS */ /* SBUS */
{ {
.name = "sbus", .name = "sbus",
...@@ -482,7 +511,7 @@ static int __init build_one_resource(struct device_node *parent, ...@@ -482,7 +511,7 @@ static int __init build_one_resource(struct device_node *parent,
u32 *addr, u32 *addr,
int na, int ns, int pna) int na, int ns, int pna)
{ {
u32 *ranges; const u32 *ranges;
unsigned int rlen; unsigned int rlen;
int rone; int rone;
...@@ -513,7 +542,7 @@ static int __init build_one_resource(struct device_node *parent, ...@@ -513,7 +542,7 @@ static int __init build_one_resource(struct device_node *parent,
static int __init use_1to1_mapping(struct device_node *pp) static int __init use_1to1_mapping(struct device_node *pp)
{ {
char *model; const char *model;
/* If this is on the PMU bus, don't try to translate it even /* If this is on the PMU bus, don't try to translate it even
* if a ranges property exists. * if a ranges property exists.
...@@ -548,7 +577,7 @@ static void __init build_device_resources(struct of_device *op, ...@@ -548,7 +577,7 @@ static void __init build_device_resources(struct of_device *op,
struct of_bus *bus; struct of_bus *bus;
int na, ns; int na, ns;
int index, num_reg; int index, num_reg;
void *preg; const void *preg;
if (!parent) if (!parent)
return; return;
...@@ -578,7 +607,7 @@ static void __init build_device_resources(struct of_device *op, ...@@ -578,7 +607,7 @@ static void __init build_device_resources(struct of_device *op,
for (index = 0; index < num_reg; index++) { for (index = 0; index < num_reg; index++) {
struct resource *r = &op->resource[index]; struct resource *r = &op->resource[index];
u32 addr[OF_MAX_ADDR_CELLS]; u32 addr[OF_MAX_ADDR_CELLS];
u32 *reg = (preg + (index * ((na + ns) * 4))); const u32 *reg = (preg + (index * ((na + ns) * 4)));
struct device_node *dp = op->node; struct device_node *dp = op->node;
struct device_node *pp = p_op->node; struct device_node *pp = p_op->node;
struct of_bus *pbus, *dbus; struct of_bus *pbus, *dbus;
...@@ -643,14 +672,14 @@ static void __init build_device_resources(struct of_device *op, ...@@ -643,14 +672,14 @@ static void __init build_device_resources(struct of_device *op,
static struct device_node * __init static struct device_node * __init
apply_interrupt_map(struct device_node *dp, struct device_node *pp, apply_interrupt_map(struct device_node *dp, struct device_node *pp,
u32 *imap, int imlen, u32 *imask, const u32 *imap, int imlen, const u32 *imask,
unsigned int *irq_p) unsigned int *irq_p)
{ {
struct device_node *cp; struct device_node *cp;
unsigned int irq = *irq_p; unsigned int irq = *irq_p;
struct of_bus *bus; struct of_bus *bus;
phandle handle; phandle handle;
u32 *reg; const u32 *reg;
int na, num_reg, i; int na, num_reg, i;
bus = of_match_bus(pp); bus = of_match_bus(pp);
...@@ -705,7 +734,7 @@ static unsigned int __init pci_irq_swizzle(struct device_node *dp, ...@@ -705,7 +734,7 @@ static unsigned int __init pci_irq_swizzle(struct device_node *dp,
struct device_node *pp, struct device_node *pp,
unsigned int irq) unsigned int irq)
{ {
struct linux_prom_pci_registers *regs; const struct linux_prom_pci_registers *regs;
unsigned int bus, devfn, slot, ret; unsigned int bus, devfn, slot, ret;
if (irq < 1 || irq > 4) if (irq < 1 || irq > 4)
...@@ -730,12 +759,6 @@ static unsigned int __init pci_irq_swizzle(struct device_node *dp, ...@@ -730,12 +759,6 @@ static unsigned int __init pci_irq_swizzle(struct device_node *dp,
* D: 2-bit slot number, derived from PCI device number as * D: 2-bit slot number, derived from PCI device number as
* (dev - 1) for bus A, or (dev - 2) for bus B * (dev - 1) for bus A, or (dev - 2) for bus B
* L: 2-bit line number * L: 2-bit line number
*
* Actually, more "portable" way to calculate the funky
* slot number is to subtract pbm->pci_first_slot from the
* device number, and that's exactly what the pre-OF
* sparc64 code did, but we're building this stuff generically
* using the OBP tree, not in the PCI controller layer.
*/ */
if (bus & 0x80) { if (bus & 0x80) {
/* PBM-A */ /* PBM-A */
...@@ -794,7 +817,7 @@ static unsigned int __init build_one_device_irq(struct of_device *op, ...@@ -794,7 +817,7 @@ static unsigned int __init build_one_device_irq(struct of_device *op,
pp = dp->parent; pp = dp->parent;
ip = NULL; ip = NULL;
while (pp) { while (pp) {
void *imap, *imsk; const void *imap, *imsk;
int imlen; int imlen;
imap = of_get_property(pp, "interrupt-map", &imlen); imap = of_get_property(pp, "interrupt-map", &imlen);
...@@ -859,7 +882,7 @@ static struct of_device * __init scan_one_device(struct device_node *dp, ...@@ -859,7 +882,7 @@ static struct of_device * __init scan_one_device(struct device_node *dp,
struct device *parent) struct device *parent)
{ {
struct of_device *op = kzalloc(sizeof(*op), GFP_KERNEL); struct of_device *op = kzalloc(sizeof(*op), GFP_KERNEL);
unsigned int *irq; const unsigned int *irq;
int len, i; int len, i;
if (!op) if (!op)
......
/* $Id: pci.c,v 1.39 2002/01/05 01:13:43 davem Exp $ /* pci.c: UltraSparc PCI controller support.
* pci.c: UltraSparc PCI controller support.
* *
* Copyright (C) 1997, 1998, 1999 David S. Miller (davem@redhat.com) * Copyright (C) 1997, 1998, 1999 David S. Miller (davem@redhat.com)
* Copyright (C) 1998, 1999 Eddie C. Dost (ecd@skynet.be) * Copyright (C) 1998, 1999 Eddie C. Dost (ecd@skynet.be)
* Copyright (C) 1999 Jakub Jelinek (jj@ultra.linux.cz) * Copyright (C) 1999 Jakub Jelinek (jj@ultra.linux.cz)
*
* OF tree based PCI bus probing taken from the PowerPC port
* with minor modifications, see there for credits.
*/ */
#include <linux/module.h> #include <linux/module.h>
...@@ -24,6 +26,9 @@ ...@@ -24,6 +26,9 @@
#include <asm/ebus.h> #include <asm/ebus.h>
#include <asm/isa.h> #include <asm/isa.h>
#include <asm/prom.h> #include <asm/prom.h>
#include <asm/apb.h>
#include "pci_impl.h"
unsigned long pci_memspace_mask = 0xffffffffUL; unsigned long pci_memspace_mask = 0xffffffffUL;
...@@ -277,10 +282,10 @@ int __init pcic_present(void) ...@@ -277,10 +282,10 @@ int __init pcic_present(void)
return pci_controller_scan(pci_is_controller); return pci_controller_scan(pci_is_controller);
} }
struct pci_iommu_ops *pci_iommu_ops; const struct pci_iommu_ops *pci_iommu_ops;
EXPORT_SYMBOL(pci_iommu_ops); EXPORT_SYMBOL(pci_iommu_ops);
extern struct pci_iommu_ops pci_sun4u_iommu_ops, extern const struct pci_iommu_ops pci_sun4u_iommu_ops,
pci_sun4v_iommu_ops; pci_sun4v_iommu_ops;
/* Find each controller in the system, attach and initialize /* Find each controller in the system, attach and initialize
...@@ -300,6 +305,467 @@ static void __init pci_controller_probe(void) ...@@ -300,6 +305,467 @@ static void __init pci_controller_probe(void)
pci_controller_scan(pci_controller_init); pci_controller_scan(pci_controller_init);
} }
static unsigned long pci_parse_of_flags(u32 addr0)
{
unsigned long flags = 0;
if (addr0 & 0x02000000) {
flags = IORESOURCE_MEM | PCI_BASE_ADDRESS_SPACE_MEMORY;
flags |= (addr0 >> 22) & PCI_BASE_ADDRESS_MEM_TYPE_64;
flags |= (addr0 >> 28) & PCI_BASE_ADDRESS_MEM_TYPE_1M;
if (addr0 & 0x40000000)
flags |= IORESOURCE_PREFETCH
| PCI_BASE_ADDRESS_MEM_PREFETCH;
} else if (addr0 & 0x01000000)
flags = IORESOURCE_IO | PCI_BASE_ADDRESS_SPACE_IO;
return flags;
}
/* The of_device layer has translated all of the assigned-address properties
* into physical address resources, we only have to figure out the register
* mapping.
*/
static void pci_parse_of_addrs(struct of_device *op,
struct device_node *node,
struct pci_dev *dev)
{
struct resource *op_res;
const u32 *addrs;
int proplen;
addrs = of_get_property(node, "assigned-addresses", &proplen);
if (!addrs)
return;
printk(" parse addresses (%d bytes) @ %p\n", proplen, addrs);
op_res = &op->resource[0];
for (; proplen >= 20; proplen -= 20, addrs += 5, op_res++) {
struct resource *res;
unsigned long flags;
int i;
flags = pci_parse_of_flags(addrs[0]);
if (!flags)
continue;
i = addrs[0] & 0xff;
printk(" start: %lx, end: %lx, i: %x\n",
op_res->start, op_res->end, i);
if (PCI_BASE_ADDRESS_0 <= i && i <= PCI_BASE_ADDRESS_5) {
res = &dev->resource[(i - PCI_BASE_ADDRESS_0) >> 2];
} else if (i == dev->rom_base_reg) {
res = &dev->resource[PCI_ROM_RESOURCE];
flags |= IORESOURCE_READONLY | IORESOURCE_CACHEABLE;
} else {
printk(KERN_ERR "PCI: bad cfg reg num 0x%x\n", i);
continue;
}
res->start = op_res->start;
res->end = op_res->end;
res->flags = flags;
res->name = pci_name(dev);
}
}
struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm,
struct device_node *node,
struct pci_bus *bus, int devfn,
int host_controller)
{
struct dev_archdata *sd;
struct pci_dev *dev;
const char *type;
u32 class;
dev = kzalloc(sizeof(struct pci_dev), GFP_KERNEL);
if (!dev)
return NULL;
sd = &dev->dev.archdata;
sd->iommu = pbm->iommu;
sd->stc = &pbm->stc;
sd->host_controller = pbm;
sd->prom_node = node;
sd->op = of_find_device_by_node(node);
sd->msi_num = 0xffffffff;
type = of_get_property(node, "device_type", NULL);
if (type == NULL)
type = "";
printk(" create device, devfn: %x, type: %s hostcontroller(%d)\n",
devfn, type, host_controller);
dev->bus = bus;
dev->sysdata = node;
dev->dev.parent = bus->bridge;
dev->dev.bus = &pci_bus_type;
dev->devfn = devfn;
dev->multifunction = 0; /* maybe a lie? */
if (host_controller) {
dev->vendor = 0x108e;
dev->device = 0x8000;
dev->subsystem_vendor = 0x0000;
dev->subsystem_device = 0x0000;
dev->cfg_size = 256;
dev->class = PCI_CLASS_BRIDGE_HOST << 8;
sprintf(pci_name(dev), "%04x:%02x:%02x.%d", pci_domain_nr(bus),
0x00, PCI_SLOT(devfn), PCI_FUNC(devfn));
} else {
dev->vendor = of_getintprop_default(node, "vendor-id", 0xffff);
dev->device = of_getintprop_default(node, "device-id", 0xffff);
dev->subsystem_vendor =
of_getintprop_default(node, "subsystem-vendor-id", 0);
dev->subsystem_device =
of_getintprop_default(node, "subsystem-id", 0);
dev->cfg_size = pci_cfg_space_size(dev);
/* We can't actually use the firmware value, we have
* to read what is in the register right now. One
* reason is that in the case of IDE interfaces the
* firmware can sample the value before the the IDE
* interface is programmed into native mode.
*/
pci_read_config_dword(dev, PCI_CLASS_REVISION, &class);
dev->class = class >> 8;
sprintf(pci_name(dev), "%04x:%02x:%02x.%d", pci_domain_nr(bus),
dev->bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn));
}
printk(" class: 0x%x device name: %s\n",
dev->class, pci_name(dev));
dev->current_state = 4; /* unknown power state */
dev->error_state = pci_channel_io_normal;
if (host_controller) {
dev->hdr_type = PCI_HEADER_TYPE_BRIDGE;
dev->rom_base_reg = PCI_ROM_ADDRESS1;
dev->irq = PCI_IRQ_NONE;
} else {
if (!strcmp(type, "pci") || !strcmp(type, "pciex")) {
/* a PCI-PCI bridge */
dev->hdr_type = PCI_HEADER_TYPE_BRIDGE;
dev->rom_base_reg = PCI_ROM_ADDRESS1;
} else if (!strcmp(type, "cardbus")) {
dev->hdr_type = PCI_HEADER_TYPE_CARDBUS;
} else {
dev->hdr_type = PCI_HEADER_TYPE_NORMAL;
dev->rom_base_reg = PCI_ROM_ADDRESS;
dev->irq = sd->op->irqs[0];
if (dev->irq == 0xffffffff)
dev->irq = PCI_IRQ_NONE;
}
}
pci_parse_of_addrs(sd->op, node, dev);
printk(" adding to system ...\n");
pci_device_add(dev, bus);
return dev;
}
static void __init apb_calc_first_last(u8 map, u32 *first_p, u32 *last_p)
{
u32 idx, first, last;
first = 8;
last = 0;
for (idx = 0; idx < 8; idx++) {
if ((map & (1 << idx)) != 0) {
if (first > idx)
first = idx;
if (last < idx)
last = idx;
}
}
*first_p = first;
*last_p = last;
}
static void __init pci_resource_adjust(struct resource *res,
struct resource *root)
{
res->start += root->start;
res->end += root->start;
}
/* Cook up fake bus resources for SUNW,simba PCI bridges which lack
* a proper 'ranges' property.
*/
static void __init apb_fake_ranges(struct pci_dev *dev,
struct pci_bus *bus,
struct pci_pbm_info *pbm)
{
struct resource *res;
u32 first, last;
u8 map;
pci_read_config_byte(dev, APB_IO_ADDRESS_MAP, &map);
apb_calc_first_last(map, &first, &last);
res = bus->resource[0];
res->start = (first << 21);
res->end = (last << 21) + ((1 << 21) - 1);
res->flags = IORESOURCE_IO;
pci_resource_adjust(res, &pbm->io_space);
pci_read_config_byte(dev, APB_MEM_ADDRESS_MAP, &map);
apb_calc_first_last(map, &first, &last);
res = bus->resource[1];
res->start = (first << 21);
res->end = (last << 21) + ((1 << 21) - 1);
res->flags = IORESOURCE_MEM;
pci_resource_adjust(res, &pbm->mem_space);
}
static void __init pci_of_scan_bus(struct pci_pbm_info *pbm,
struct device_node *node,
struct pci_bus *bus);
#define GET_64BIT(prop, i) ((((u64) (prop)[(i)]) << 32) | (prop)[(i)+1])
void __devinit of_scan_pci_bridge(struct pci_pbm_info *pbm,
struct device_node *node,
struct pci_dev *dev)
{
struct pci_bus *bus;
const u32 *busrange, *ranges;
int len, i, simba;
struct resource *res;
unsigned int flags;
u64 size;
printk("of_scan_pci_bridge(%s)\n", node->full_name);
/* parse bus-range property */
busrange = of_get_property(node, "bus-range", &len);
if (busrange == NULL || len != 8) {
printk(KERN_DEBUG "Can't get bus-range for PCI-PCI bridge %s\n",
node->full_name);
return;
}
ranges = of_get_property(node, "ranges", &len);
simba = 0;
if (ranges == NULL) {
const char *model = of_get_property(node, "model", NULL);
if (model && !strcmp(model, "SUNW,simba")) {
simba = 1;
} else {
printk(KERN_DEBUG "Can't get ranges for PCI-PCI bridge %s\n",
node->full_name);
return;
}
}
bus = pci_add_new_bus(dev->bus, dev, busrange[0]);
if (!bus) {
printk(KERN_ERR "Failed to create pci bus for %s\n",
node->full_name);
return;
}
bus->primary = dev->bus->number;
bus->subordinate = busrange[1];
bus->bridge_ctl = 0;
/* parse ranges property, or cook one up by hand for Simba */
/* PCI #address-cells == 3 and #size-cells == 2 always */
res = &dev->resource[PCI_BRIDGE_RESOURCES];
for (i = 0; i < PCI_NUM_RESOURCES - PCI_BRIDGE_RESOURCES; ++i) {
res->flags = 0;
bus->resource[i] = res;
++res;
}
if (simba) {
apb_fake_ranges(dev, bus, pbm);
goto simba_cont;
}
i = 1;
for (; len >= 32; len -= 32, ranges += 8) {
struct resource *root;
flags = pci_parse_of_flags(ranges[0]);
size = GET_64BIT(ranges, 6);
if (flags == 0 || size == 0)
continue;
if (flags & IORESOURCE_IO) {
res = bus->resource[0];
if (res->flags) {
printk(KERN_ERR "PCI: ignoring extra I/O range"
" for bridge %s\n", node->full_name);
continue;
}
root = &pbm->io_space;
} else {
if (i >= PCI_NUM_RESOURCES - PCI_BRIDGE_RESOURCES) {
printk(KERN_ERR "PCI: too many memory ranges"
" for bridge %s\n", node->full_name);
continue;
}
res = bus->resource[i];
++i;
root = &pbm->mem_space;
}
res->start = GET_64BIT(ranges, 1);
res->end = res->start + size - 1;
res->flags = flags;
/* Another way to implement this would be to add an of_device
* layer routine that can calculate a resource for a given
* range property value in a PCI device.
*/
pci_resource_adjust(res, root);
}
simba_cont:
sprintf(bus->name, "PCI Bus %04x:%02x", pci_domain_nr(bus),
bus->number);
printk(" bus name: %s\n", bus->name);
pci_of_scan_bus(pbm, node, bus);
}
static void __init pci_of_scan_bus(struct pci_pbm_info *pbm,
struct device_node *node,
struct pci_bus *bus)
{
struct device_node *child;
const u32 *reg;
int reglen, devfn;
struct pci_dev *dev;
printk("PCI: scan_bus[%s] bus no %d\n",
node->full_name, bus->number);
child = NULL;
while ((child = of_get_next_child(node, child)) != NULL) {
printk(" * %s\n", child->full_name);
reg = of_get_property(child, "reg", &reglen);
if (reg == NULL || reglen < 20)
continue;
devfn = (reg[0] >> 8) & 0xff;
/* create a new pci_dev for this device */
dev = of_create_pci_dev(pbm, child, bus, devfn, 0);
if (!dev)
continue;
printk("PCI: dev header type: %x\n", dev->hdr_type);
if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)
of_scan_pci_bridge(pbm, child, dev);
}
}
static ssize_t
show_pciobppath_attr(struct device * dev, struct device_attribute * attr, char * buf)
{
struct pci_dev *pdev;
struct device_node *dp;
pdev = to_pci_dev(dev);
dp = pdev->dev.archdata.prom_node;
return snprintf (buf, PAGE_SIZE, "%s\n", dp->full_name);
}
static DEVICE_ATTR(obppath, S_IRUSR | S_IRGRP | S_IROTH, show_pciobppath_attr, NULL);
static void __devinit pci_bus_register_of_sysfs(struct pci_bus *bus)
{
struct pci_dev *dev;
struct pci_bus *child_bus;
int err;
list_for_each_entry(dev, &bus->devices, bus_list) {
/* we don't really care if we can create this file or
* not, but we need to assign the result of the call
* or the world will fall under alien invasion and
* everybody will be frozen on a spaceship ready to be
* eaten on alpha centauri by some green and jelly
* humanoid.
*/
err = sysfs_create_file(&dev->dev.kobj, &dev_attr_obppath.attr);
}
list_for_each_entry(child_bus, &bus->children, node)
pci_bus_register_of_sysfs(child_bus);
}
int pci_host_bridge_read_pci_cfg(struct pci_bus *bus_dev,
unsigned int devfn,
int where, int size,
u32 *value)
{
static u8 fake_pci_config[] = {
0x8e, 0x10, /* Vendor: 0x108e (Sun) */
0x00, 0x80, /* Device: 0x8000 (PBM) */
0x46, 0x01, /* Command: 0x0146 (SERR, PARITY, MASTER, MEM) */
0xa0, 0x22, /* Status: 0x02a0 (DEVSEL_MED, FB2B, 66MHZ) */
0x00, 0x00, 0x00, 0x06, /* Class: 0x06000000 host bridge */
0x00, /* Cacheline: 0x00 */
0x40, /* Latency: 0x40 */
0x00, /* Header-Type: 0x00 normal */
};
*value = 0;
if (where >= 0 && where < sizeof(fake_pci_config) &&
(where + size) >= 0 &&
(where + size) < sizeof(fake_pci_config) &&
size <= sizeof(u32)) {
while (size--) {
*value <<= 8;
*value |= fake_pci_config[where + size];
}
}
return PCIBIOS_SUCCESSFUL;
}
int pci_host_bridge_write_pci_cfg(struct pci_bus *bus_dev,
unsigned int devfn,
int where, int size,
u32 value)
{
return PCIBIOS_SUCCESSFUL;
}
struct pci_bus * __init pci_scan_one_pbm(struct pci_pbm_info *pbm)
{
struct pci_controller_info *p = pbm->parent;
struct device_node *node = pbm->prom_node;
struct pci_dev *host_pdev;
struct pci_bus *bus;
printk("PCI: Scanning PBM %s\n", node->full_name);
/* XXX parent device? XXX */
bus = pci_create_bus(NULL, pbm->pci_first_busno, p->pci_ops, pbm);
if (!bus) {
printk(KERN_ERR "Failed to create bus for %s\n",
node->full_name);
return NULL;
}
bus->secondary = pbm->pci_first_busno;
bus->subordinate = pbm->pci_last_busno;
bus->resource[0] = &pbm->io_space;
bus->resource[1] = &pbm->mem_space;
/* Create the dummy host bridge and link it in. */
host_pdev = of_create_pci_dev(pbm, node, bus, 0x00, 1);
bus->self = host_pdev;
pci_of_scan_bus(pbm, node, bus);
pci_bus_add_devices(bus);
pci_bus_register_of_sysfs(bus);
return bus;
}
static void __init pci_scan_each_controller_bus(void) static void __init pci_scan_each_controller_bus(void)
{ {
struct pci_controller_info *p; struct pci_controller_info *p;
...@@ -360,8 +826,33 @@ void pcibios_align_resource(void *data, struct resource *res, ...@@ -360,8 +826,33 @@ void pcibios_align_resource(void *data, struct resource *res,
{ {
} }
int pcibios_enable_device(struct pci_dev *pdev, int mask) int pcibios_enable_device(struct pci_dev *dev, int mask)
{ {
u16 cmd, oldcmd;
int i;
pci_read_config_word(dev, PCI_COMMAND, &cmd);
oldcmd = cmd;
for (i = 0; i < PCI_NUM_RESOURCES; i++) {
struct resource *res = &dev->resource[i];
/* Only set up the requested stuff */
if (!(mask & (1<<i)))
continue;
if (res->flags & IORESOURCE_IO)
cmd |= PCI_COMMAND_IO;
if (res->flags & IORESOURCE_MEM)
cmd |= PCI_COMMAND_MEMORY;
}
if (cmd != oldcmd) {
printk(KERN_DEBUG "PCI: Enabling device: (%s), cmd %x\n",
pci_name(dev), cmd);
/* Enable the appropriate bits in the PCI command register. */
pci_write_config_word(dev, PCI_COMMAND, cmd);
}
return 0; return 0;
} }
...@@ -380,7 +871,7 @@ void pcibios_resource_to_bus(struct pci_dev *pdev, struct pci_bus_region *region ...@@ -380,7 +871,7 @@ void pcibios_resource_to_bus(struct pci_dev *pdev, struct pci_bus_region *region
else else
root = &pbm->mem_space; root = &pbm->mem_space;
pbm->parent->resource_adjust(pdev, &zero_res, root); pci_resource_adjust(&zero_res, root);
region->start = res->start - zero_res.start; region->start = res->start - zero_res.start;
region->end = res->end - zero_res.start; region->end = res->end - zero_res.start;
...@@ -401,7 +892,7 @@ void pcibios_bus_to_resource(struct pci_dev *pdev, struct resource *res, ...@@ -401,7 +892,7 @@ void pcibios_bus_to_resource(struct pci_dev *pdev, struct resource *res,
else else
root = &pbm->mem_space; root = &pbm->mem_space;
pbm->parent->resource_adjust(pdev, res, root); pci_resource_adjust(res, root);
} }
EXPORT_SYMBOL(pcibios_bus_to_resource); EXPORT_SYMBOL(pcibios_bus_to_resource);
...@@ -422,48 +913,11 @@ char * __devinit pcibios_setup(char *str) ...@@ -422,48 +913,11 @@ char * __devinit pcibios_setup(char *str)
static int __pci_mmap_make_offset_bus(struct pci_dev *pdev, struct vm_area_struct *vma, static int __pci_mmap_make_offset_bus(struct pci_dev *pdev, struct vm_area_struct *vma,
enum pci_mmap_state mmap_state) enum pci_mmap_state mmap_state)
{ {
struct pcidev_cookie *pcp = pdev->sysdata; struct pci_pbm_info *pbm = pdev->dev.archdata.host_controller;
struct pci_pbm_info *pbm;
struct pci_controller_info *p; struct pci_controller_info *p;
unsigned long space_size, user_offset, user_size; unsigned long space_size, user_offset, user_size;
if (!pcp)
return -ENXIO;
pbm = pcp->pbm;
if (!pbm)
return -ENXIO;
p = pbm->parent; p = pbm->parent;
if (p->pbms_same_domain) {
unsigned long lowest, highest;
lowest = ~0UL; highest = 0UL;
if (mmap_state == pci_mmap_io) {
if (p->pbm_A.io_space.flags) {
lowest = p->pbm_A.io_space.start;
highest = p->pbm_A.io_space.end + 1;
}
if (p->pbm_B.io_space.flags) {
if (lowest > p->pbm_B.io_space.start)
lowest = p->pbm_B.io_space.start;
if (highest < p->pbm_B.io_space.end + 1)
highest = p->pbm_B.io_space.end + 1;
}
space_size = highest - lowest;
} else {
if (p->pbm_A.mem_space.flags) {
lowest = p->pbm_A.mem_space.start;
highest = p->pbm_A.mem_space.end + 1;
}
if (p->pbm_B.mem_space.flags) {
if (lowest > p->pbm_B.mem_space.start)
lowest = p->pbm_B.mem_space.start;
if (highest < p->pbm_B.mem_space.end + 1)
highest = p->pbm_B.mem_space.end + 1;
}
space_size = highest - lowest;
}
} else {
if (mmap_state == pci_mmap_io) { if (mmap_state == pci_mmap_io) {
space_size = (pbm->io_space.end - space_size = (pbm->io_space.end -
pbm->io_space.start) + 1; pbm->io_space.start) + 1;
...@@ -471,7 +925,6 @@ static int __pci_mmap_make_offset_bus(struct pci_dev *pdev, struct vm_area_struc ...@@ -471,7 +925,6 @@ static int __pci_mmap_make_offset_bus(struct pci_dev *pdev, struct vm_area_struc
space_size = (pbm->mem_space.end - space_size = (pbm->mem_space.end -
pbm->mem_space.start) + 1; pbm->mem_space.start) + 1;
} }
}
/* Make sure the request is in range. */ /* Make sure the request is in range. */
user_offset = vma->vm_pgoff << PAGE_SHIFT; user_offset = vma->vm_pgoff << PAGE_SHIFT;
...@@ -481,24 +934,6 @@ static int __pci_mmap_make_offset_bus(struct pci_dev *pdev, struct vm_area_struc ...@@ -481,24 +934,6 @@ static int __pci_mmap_make_offset_bus(struct pci_dev *pdev, struct vm_area_struc
(user_offset + user_size) > space_size) (user_offset + user_size) > space_size)
return -EINVAL; return -EINVAL;
if (p->pbms_same_domain) {
unsigned long lowest = ~0UL;
if (mmap_state == pci_mmap_io) {
if (p->pbm_A.io_space.flags)
lowest = p->pbm_A.io_space.start;
if (p->pbm_B.io_space.flags &&
lowest > p->pbm_B.io_space.start)
lowest = p->pbm_B.io_space.start;
} else {
if (p->pbm_A.mem_space.flags)
lowest = p->pbm_A.mem_space.start;
if (p->pbm_B.mem_space.flags &&
lowest > p->pbm_B.mem_space.start)
lowest = p->pbm_B.mem_space.start;
}
vma->vm_pgoff = (lowest + user_offset) >> PAGE_SHIFT;
} else {
if (mmap_state == pci_mmap_io) { if (mmap_state == pci_mmap_io) {
vma->vm_pgoff = (pbm->io_space.start + vma->vm_pgoff = (pbm->io_space.start +
user_offset) >> PAGE_SHIFT; user_offset) >> PAGE_SHIFT;
...@@ -506,7 +941,6 @@ static int __pci_mmap_make_offset_bus(struct pci_dev *pdev, struct vm_area_struc ...@@ -506,7 +941,6 @@ static int __pci_mmap_make_offset_bus(struct pci_dev *pdev, struct vm_area_struc
vma->vm_pgoff = (pbm->mem_space.start + vma->vm_pgoff = (pbm->mem_space.start +
user_offset) >> PAGE_SHIFT; user_offset) >> PAGE_SHIFT;
} }
}
return 0; return 0;
} }
...@@ -639,7 +1073,6 @@ int pci_domain_nr(struct pci_bus *pbus) ...@@ -639,7 +1073,6 @@ int pci_domain_nr(struct pci_bus *pbus)
struct pci_controller_info *p = pbm->parent; struct pci_controller_info *p = pbm->parent;
ret = p->index; ret = p->index;
if (p->pbms_same_domain == 0)
ret = ((ret << 1) + ret = ((ret << 1) +
((pbm == &pbm->parent->pbm_B) ? 1 : 0)); ((pbm == &pbm->parent->pbm_B) ? 1 : 0));
} }
...@@ -651,8 +1084,7 @@ EXPORT_SYMBOL(pci_domain_nr); ...@@ -651,8 +1084,7 @@ EXPORT_SYMBOL(pci_domain_nr);
#ifdef CONFIG_PCI_MSI #ifdef CONFIG_PCI_MSI
int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc) int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc)
{ {
struct pcidev_cookie *pcp = pdev->sysdata; struct pci_pbm_info *pbm = pdev->dev.archdata.host_controller;
struct pci_pbm_info *pbm = pcp->pbm;
struct pci_controller_info *p = pbm->parent; struct pci_controller_info *p = pbm->parent;
int virt_irq, err; int virt_irq, err;
...@@ -670,8 +1102,7 @@ void arch_teardown_msi_irq(unsigned int virt_irq) ...@@ -670,8 +1102,7 @@ void arch_teardown_msi_irq(unsigned int virt_irq)
{ {
struct msi_desc *entry = get_irq_msi(virt_irq); struct msi_desc *entry = get_irq_msi(virt_irq);
struct pci_dev *pdev = entry->dev; struct pci_dev *pdev = entry->dev;
struct pcidev_cookie *pcp = pdev->sysdata; struct pci_pbm_info *pbm = pdev->dev.archdata.host_controller;
struct pci_pbm_info *pbm = pcp->pbm;
struct pci_controller_info *p = pbm->parent; struct pci_controller_info *p = pbm->parent;
if (!pbm->msi_num || !p->setup_msi_irq) if (!pbm->msi_num || !p->setup_msi_irq)
...@@ -683,9 +1114,7 @@ void arch_teardown_msi_irq(unsigned int virt_irq) ...@@ -683,9 +1114,7 @@ void arch_teardown_msi_irq(unsigned int virt_irq)
struct device_node *pci_device_to_OF_node(struct pci_dev *pdev) struct device_node *pci_device_to_OF_node(struct pci_dev *pdev)
{ {
struct pcidev_cookie *pc = pdev->sysdata; return pdev->dev.archdata.prom_node;
return pc->op->node;
} }
EXPORT_SYMBOL(pci_device_to_OF_node); EXPORT_SYMBOL(pci_device_to_OF_node);
......
此差异已折叠。
/* $Id: pci_impl.h,v 1.9 2001/06/13 06:34:30 davem Exp $ /* pci_impl.h: Helper definitions for PCI controller support.
* pci_impl.h: Helper definitions for PCI controller support.
* *
* Copyright (C) 1999 David S. Miller (davem@redhat.com) * Copyright (C) 1999, 2007 David S. Miller (davem@davemloft.net)
*/ */
#ifndef PCI_IMPL_H #ifndef PCI_IMPL_H
...@@ -13,26 +12,22 @@ ...@@ -13,26 +12,22 @@
#include <asm/prom.h> #include <asm/prom.h>
extern struct pci_controller_info *pci_controller_root; extern struct pci_controller_info *pci_controller_root;
extern unsigned long pci_memspace_mask;
extern int pci_num_controllers; extern int pci_num_controllers;
/* PCI bus scanning and fixup support. */ /* PCI bus scanning and fixup support. */
extern void pci_fixup_host_bridge_self(struct pci_bus *pbus); extern struct pci_bus *pci_scan_one_pbm(struct pci_pbm_info *pbm);
extern void pci_fill_in_pbm_cookies(struct pci_bus *pbus, extern void pci_determine_mem_io_space(struct pci_pbm_info *pbm);
struct pci_pbm_info *pbm,
struct device_node *prom_node); extern int pci_host_bridge_read_pci_cfg(struct pci_bus *bus_dev,
extern void pci_record_assignments(struct pci_pbm_info *pbm, unsigned int devfn,
struct pci_bus *pbus); int where, int size,
extern void pci_assign_unassigned(struct pci_pbm_info *pbm, u32 *value);
struct pci_bus *pbus); extern int pci_host_bridge_write_pci_cfg(struct pci_bus *bus_dev,
extern void pci_fixup_irq(struct pci_pbm_info *pbm, unsigned int devfn,
struct pci_bus *pbus); int where, int size,
extern void pci_determine_66mhz_disposition(struct pci_pbm_info *pbm, u32 value);
struct pci_bus *pbus);
extern void pci_setup_busmastering(struct pci_pbm_info *pbm,
struct pci_bus *pbus);
extern void pci_register_legacy_regions(struct resource *io_res,
struct resource *mem_res);
/* Error reporting support. */ /* Error reporting support. */
extern void pci_scan_for_target_abort(struct pci_controller_info *, struct pci_pbm_info *, struct pci_bus *); extern void pci_scan_for_target_abort(struct pci_controller_info *, struct pci_pbm_info *, struct pci_bus *);
......
/* $Id: pci_iommu.c,v 1.17 2001/12/17 07:05:09 davem Exp $ /* pci_iommu.c: UltraSparc PCI controller IOM/STC support.
* pci_iommu.c: UltraSparc PCI controller IOM/STC support.
* *
* Copyright (C) 1999 David S. Miller (davem@redhat.com) * Copyright (C) 1999, 2007 David S. Miller (davem@davemloft.net)
* Copyright (C) 1999, 2000 Jakub Jelinek (jakub@redhat.com) * Copyright (C) 1999, 2000 Jakub Jelinek (jakub@redhat.com)
*/ */
...@@ -36,7 +35,7 @@ ...@@ -36,7 +35,7 @@
"i" (ASI_PHYS_BYPASS_EC_E)) "i" (ASI_PHYS_BYPASS_EC_E))
/* Must be invoked under the IOMMU lock. */ /* Must be invoked under the IOMMU lock. */
static void __iommu_flushall(struct pci_iommu *iommu) static void __iommu_flushall(struct iommu *iommu)
{ {
unsigned long tag; unsigned long tag;
int entry; int entry;
...@@ -64,7 +63,7 @@ static void __iommu_flushall(struct pci_iommu *iommu) ...@@ -64,7 +63,7 @@ static void __iommu_flushall(struct pci_iommu *iommu)
#define IOPTE_IS_DUMMY(iommu, iopte) \ #define IOPTE_IS_DUMMY(iommu, iopte) \
((iopte_val(*iopte) & IOPTE_PAGE) == (iommu)->dummy_page_pa) ((iopte_val(*iopte) & IOPTE_PAGE) == (iommu)->dummy_page_pa)
static inline void iopte_make_dummy(struct pci_iommu *iommu, iopte_t *iopte) static inline void iopte_make_dummy(struct iommu *iommu, iopte_t *iopte)
{ {
unsigned long val = iopte_val(*iopte); unsigned long val = iopte_val(*iopte);
...@@ -75,9 +74,9 @@ static inline void iopte_make_dummy(struct pci_iommu *iommu, iopte_t *iopte) ...@@ -75,9 +74,9 @@ static inline void iopte_make_dummy(struct pci_iommu *iommu, iopte_t *iopte)
} }
/* Based largely upon the ppc64 iommu allocator. */ /* Based largely upon the ppc64 iommu allocator. */
static long pci_arena_alloc(struct pci_iommu *iommu, unsigned long npages) static long pci_arena_alloc(struct iommu *iommu, unsigned long npages)
{ {
struct pci_iommu_arena *arena = &iommu->arena; struct iommu_arena *arena = &iommu->arena;
unsigned long n, i, start, end, limit; unsigned long n, i, start, end, limit;
int pass; int pass;
...@@ -116,7 +115,7 @@ static long pci_arena_alloc(struct pci_iommu *iommu, unsigned long npages) ...@@ -116,7 +115,7 @@ static long pci_arena_alloc(struct pci_iommu *iommu, unsigned long npages)
return n; return n;
} }
static void pci_arena_free(struct pci_iommu_arena *arena, unsigned long base, unsigned long npages) static void pci_arena_free(struct iommu_arena *arena, unsigned long base, unsigned long npages)
{ {
unsigned long i; unsigned long i;
...@@ -124,7 +123,7 @@ static void pci_arena_free(struct pci_iommu_arena *arena, unsigned long base, un ...@@ -124,7 +123,7 @@ static void pci_arena_free(struct pci_iommu_arena *arena, unsigned long base, un
__clear_bit(i, arena->map); __clear_bit(i, arena->map);
} }
void pci_iommu_table_init(struct pci_iommu *iommu, int tsbsize, u32 dma_offset, u32 dma_addr_mask) void pci_iommu_table_init(struct iommu *iommu, int tsbsize, u32 dma_offset, u32 dma_addr_mask)
{ {
unsigned long i, tsbbase, order, sz, num_tsb_entries; unsigned long i, tsbbase, order, sz, num_tsb_entries;
...@@ -170,7 +169,7 @@ void pci_iommu_table_init(struct pci_iommu *iommu, int tsbsize, u32 dma_offset, ...@@ -170,7 +169,7 @@ void pci_iommu_table_init(struct pci_iommu *iommu, int tsbsize, u32 dma_offset,
iopte_make_dummy(iommu, &iommu->page_table[i]); iopte_make_dummy(iommu, &iommu->page_table[i]);
} }
static inline iopte_t *alloc_npages(struct pci_iommu *iommu, unsigned long npages) static inline iopte_t *alloc_npages(struct iommu *iommu, unsigned long npages)
{ {
long entry; long entry;
...@@ -181,12 +180,12 @@ static inline iopte_t *alloc_npages(struct pci_iommu *iommu, unsigned long npage ...@@ -181,12 +180,12 @@ static inline iopte_t *alloc_npages(struct pci_iommu *iommu, unsigned long npage
return iommu->page_table + entry; return iommu->page_table + entry;
} }
static inline void free_npages(struct pci_iommu *iommu, dma_addr_t base, unsigned long npages) static inline void free_npages(struct iommu *iommu, dma_addr_t base, unsigned long npages)
{ {
pci_arena_free(&iommu->arena, base >> IO_PAGE_SHIFT, npages); pci_arena_free(&iommu->arena, base >> IO_PAGE_SHIFT, npages);
} }
static int iommu_alloc_ctx(struct pci_iommu *iommu) static int iommu_alloc_ctx(struct iommu *iommu)
{ {
int lowest = iommu->ctx_lowest_free; int lowest = iommu->ctx_lowest_free;
int sz = IOMMU_NUM_CTXS - lowest; int sz = IOMMU_NUM_CTXS - lowest;
...@@ -205,7 +204,7 @@ static int iommu_alloc_ctx(struct pci_iommu *iommu) ...@@ -205,7 +204,7 @@ static int iommu_alloc_ctx(struct pci_iommu *iommu)
return n; return n;
} }
static inline void iommu_free_ctx(struct pci_iommu *iommu, int ctx) static inline void iommu_free_ctx(struct iommu *iommu, int ctx)
{ {
if (likely(ctx)) { if (likely(ctx)) {
__clear_bit(ctx, iommu->ctx_bitmap); __clear_bit(ctx, iommu->ctx_bitmap);
...@@ -220,8 +219,7 @@ static inline void iommu_free_ctx(struct pci_iommu *iommu, int ctx) ...@@ -220,8 +219,7 @@ 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) 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 iommu *iommu;
struct pci_iommu *iommu;
iopte_t *iopte; iopte_t *iopte;
unsigned long flags, order, first_page; unsigned long flags, order, first_page;
void *ret; void *ret;
...@@ -237,8 +235,7 @@ static void *pci_4u_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr ...@@ -237,8 +235,7 @@ static void *pci_4u_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr
return NULL; return NULL;
memset((char *)first_page, 0, PAGE_SIZE << order); memset((char *)first_page, 0, PAGE_SIZE << order);
pcp = pdev->sysdata; iommu = pdev->dev.archdata.iommu;
iommu = pcp->pbm->iommu;
spin_lock_irqsave(&iommu->lock, flags); spin_lock_irqsave(&iommu->lock, flags);
iopte = alloc_npages(iommu, size >> IO_PAGE_SHIFT); iopte = alloc_npages(iommu, size >> IO_PAGE_SHIFT);
...@@ -268,14 +265,12 @@ static void *pci_4u_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr ...@@ -268,14 +265,12 @@ static void *pci_4u_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr
/* Free and unmap a consistent DMA translation. */ /* 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) static void pci_4u_free_consistent(struct pci_dev *pdev, size_t size, void *cpu, dma_addr_t dvma)
{ {
struct pcidev_cookie *pcp; struct iommu *iommu;
struct pci_iommu *iommu;
iopte_t *iopte; iopte_t *iopte;
unsigned long flags, order, npages; unsigned long flags, order, npages;
npages = IO_PAGE_ALIGN(size) >> IO_PAGE_SHIFT; npages = IO_PAGE_ALIGN(size) >> IO_PAGE_SHIFT;
pcp = pdev->sysdata; iommu = pdev->dev.archdata.iommu;
iommu = pcp->pbm->iommu;
iopte = iommu->page_table + iopte = iommu->page_table +
((dvma - iommu->page_table_map_base) >> IO_PAGE_SHIFT); ((dvma - iommu->page_table_map_base) >> IO_PAGE_SHIFT);
...@@ -295,18 +290,16 @@ static void pci_4u_free_consistent(struct pci_dev *pdev, size_t size, void *cpu, ...@@ -295,18 +290,16 @@ 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) static dma_addr_t pci_4u_map_single(struct pci_dev *pdev, void *ptr, size_t sz, int direction)
{ {
struct pcidev_cookie *pcp; struct iommu *iommu;
struct pci_iommu *iommu; struct strbuf *strbuf;
struct pci_strbuf *strbuf;
iopte_t *base; iopte_t *base;
unsigned long flags, npages, oaddr; unsigned long flags, npages, oaddr;
unsigned long i, base_paddr, ctx; unsigned long i, base_paddr, ctx;
u32 bus_addr, ret; u32 bus_addr, ret;
unsigned long iopte_protection; unsigned long iopte_protection;
pcp = pdev->sysdata; iommu = pdev->dev.archdata.iommu;
iommu = pcp->pbm->iommu; strbuf = pdev->dev.archdata.stc;
strbuf = &pcp->pbm->stc;
if (unlikely(direction == PCI_DMA_NONE)) if (unlikely(direction == PCI_DMA_NONE))
goto bad_no_ctx; goto bad_no_ctx;
...@@ -349,7 +342,7 @@ static dma_addr_t pci_4u_map_single(struct pci_dev *pdev, void *ptr, size_t sz, ...@@ -349,7 +342,7 @@ static dma_addr_t pci_4u_map_single(struct pci_dev *pdev, void *ptr, size_t sz,
return PCI_DMA_ERROR_CODE; return PCI_DMA_ERROR_CODE;
} }
static void pci_strbuf_flush(struct pci_strbuf *strbuf, struct pci_iommu *iommu, u32 vaddr, unsigned long ctx, unsigned long npages, int direction) static void pci_strbuf_flush(struct strbuf *strbuf, struct iommu *iommu, u32 vaddr, unsigned long ctx, unsigned long npages, int direction)
{ {
int limit; int limit;
...@@ -416,9 +409,8 @@ static void pci_strbuf_flush(struct pci_strbuf *strbuf, struct pci_iommu *iommu, ...@@ -416,9 +409,8 @@ static void pci_strbuf_flush(struct pci_strbuf *strbuf, struct pci_iommu *iommu,
/* Unmap a single streaming mode DMA translation. */ /* 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) 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 iommu *iommu;
struct pci_iommu *iommu; struct strbuf *strbuf;
struct pci_strbuf *strbuf;
iopte_t *base; iopte_t *base;
unsigned long flags, npages, ctx, i; unsigned long flags, npages, ctx, i;
...@@ -428,9 +420,8 @@ static void pci_4u_unmap_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_ ...@@ -428,9 +420,8 @@ static void pci_4u_unmap_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_
return; return;
} }
pcp = pdev->sysdata; iommu = pdev->dev.archdata.iommu;
iommu = pcp->pbm->iommu; strbuf = pdev->dev.archdata.stc;
strbuf = &pcp->pbm->stc;
npages = IO_PAGE_ALIGN(bus_addr + sz) - (bus_addr & IO_PAGE_MASK); npages = IO_PAGE_ALIGN(bus_addr + sz) - (bus_addr & IO_PAGE_MASK);
npages >>= IO_PAGE_SHIFT; npages >>= IO_PAGE_SHIFT;
...@@ -549,9 +540,8 @@ static inline void fill_sg(iopte_t *iopte, struct scatterlist *sg, ...@@ -549,9 +540,8 @@ 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) static int pci_4u_map_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, int direction)
{ {
struct pcidev_cookie *pcp; struct iommu *iommu;
struct pci_iommu *iommu; struct strbuf *strbuf;
struct pci_strbuf *strbuf;
unsigned long flags, ctx, npages, iopte_protection; unsigned long flags, ctx, npages, iopte_protection;
iopte_t *base; iopte_t *base;
u32 dma_base; u32 dma_base;
...@@ -570,9 +560,8 @@ static int pci_4u_map_sg(struct pci_dev *pdev, struct scatterlist *sglist, int n ...@@ -570,9 +560,8 @@ static int pci_4u_map_sg(struct pci_dev *pdev, struct scatterlist *sglist, int n
return 1; return 1;
} }
pcp = pdev->sysdata; iommu = pdev->dev.archdata.iommu;
iommu = pcp->pbm->iommu; strbuf = pdev->dev.archdata.stc;
strbuf = &pcp->pbm->stc;
if (unlikely(direction == PCI_DMA_NONE)) if (unlikely(direction == PCI_DMA_NONE))
goto bad_no_ctx; goto bad_no_ctx;
...@@ -636,9 +625,8 @@ static int pci_4u_map_sg(struct pci_dev *pdev, struct scatterlist *sglist, int n ...@@ -636,9 +625,8 @@ static int pci_4u_map_sg(struct pci_dev *pdev, struct scatterlist *sglist, int n
/* Unmap a set of streaming mode DMA translations. */ /* 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) static void pci_4u_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, int direction)
{ {
struct pcidev_cookie *pcp; struct iommu *iommu;
struct pci_iommu *iommu; struct strbuf *strbuf;
struct pci_strbuf *strbuf;
iopte_t *base; iopte_t *base;
unsigned long flags, ctx, i, npages; unsigned long flags, ctx, i, npages;
u32 bus_addr; u32 bus_addr;
...@@ -648,9 +636,8 @@ static void pci_4u_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, in ...@@ -648,9 +636,8 @@ static void pci_4u_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, in
WARN_ON(1); WARN_ON(1);
} }
pcp = pdev->sysdata; iommu = pdev->dev.archdata.iommu;
iommu = pcp->pbm->iommu; strbuf = pdev->dev.archdata.stc;
strbuf = &pcp->pbm->stc;
bus_addr = sglist->dma_address & IO_PAGE_MASK; bus_addr = sglist->dma_address & IO_PAGE_MASK;
...@@ -696,14 +683,12 @@ static void pci_4u_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, in ...@@ -696,14 +683,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) 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 iommu *iommu;
struct pci_iommu *iommu; struct strbuf *strbuf;
struct pci_strbuf *strbuf;
unsigned long flags, ctx, npages; unsigned long flags, ctx, npages;
pcp = pdev->sysdata; iommu = pdev->dev.archdata.iommu;
iommu = pcp->pbm->iommu; strbuf = pdev->dev.archdata.stc;
strbuf = &pcp->pbm->stc;
if (!strbuf->strbuf_enabled) if (!strbuf->strbuf_enabled)
return; return;
...@@ -736,15 +721,13 @@ static void pci_4u_dma_sync_single_for_cpu(struct pci_dev *pdev, dma_addr_t bus_ ...@@ -736,15 +721,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) 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 iommu *iommu;
struct pci_iommu *iommu; struct strbuf *strbuf;
struct pci_strbuf *strbuf;
unsigned long flags, ctx, npages, i; unsigned long flags, ctx, npages, i;
u32 bus_addr; u32 bus_addr;
pcp = pdev->sysdata; iommu = pdev->dev.archdata.iommu;
iommu = pcp->pbm->iommu; strbuf = pdev->dev.archdata.stc;
strbuf = &pcp->pbm->stc;
if (!strbuf->strbuf_enabled) if (!strbuf->strbuf_enabled)
return; return;
...@@ -775,7 +758,7 @@ static void pci_4u_dma_sync_sg_for_cpu(struct pci_dev *pdev, struct scatterlist ...@@ -775,7 +758,7 @@ static void pci_4u_dma_sync_sg_for_cpu(struct pci_dev *pdev, struct scatterlist
spin_unlock_irqrestore(&iommu->lock, flags); spin_unlock_irqrestore(&iommu->lock, flags);
} }
struct pci_iommu_ops pci_sun4u_iommu_ops = { const struct pci_iommu_ops pci_sun4u_iommu_ops = {
.alloc_consistent = pci_4u_alloc_consistent, .alloc_consistent = pci_4u_alloc_consistent,
.free_consistent = pci_4u_free_consistent, .free_consistent = pci_4u_free_consistent,
.map_single = pci_4u_map_single, .map_single = pci_4u_map_single,
...@@ -809,13 +792,12 @@ static void ali_sound_dma_hack(struct pci_dev *pdev, int set_bit) ...@@ -809,13 +792,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) int pci_dma_supported(struct pci_dev *pdev, u64 device_mask)
{ {
struct pcidev_cookie *pcp = pdev->sysdata;
u64 dma_addr_mask; u64 dma_addr_mask;
if (pdev == NULL) { if (pdev == NULL) {
dma_addr_mask = 0xffffffff; dma_addr_mask = 0xffffffff;
} else { } else {
struct pci_iommu *iommu = pcp->pbm->iommu; struct iommu *iommu = pdev->dev.archdata.iommu;
dma_addr_mask = iommu->dma_addr_mask; dma_addr_mask = iommu->dma_addr_mask;
......
/* $Id: pci_psycho.c,v 1.33 2002/02/01 00:58:33 davem Exp $ /* pci_psycho.c: PSYCHO/U2P specific PCI controller support.
* pci_psycho.c: PSYCHO/U2P specific PCI controller support.
* *
* Copyright (C) 1997, 1998, 1999 David S. Miller (davem@caipfs.rutgers.edu) * Copyright (C) 1997, 1998, 1999, 2007 David S. Miller (davem@davemloft.net)
* Copyright (C) 1998, 1999 Eddie C. Dost (ecd@skynet.be) * Copyright (C) 1998, 1999 Eddie C. Dost (ecd@skynet.be)
* Copyright (C) 1999 Jakub Jelinek (jakub@redhat.com) * Copyright (C) 1999 Jakub Jelinek (jakub@redhat.com)
*/ */
...@@ -119,6 +118,10 @@ static int psycho_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn, ...@@ -119,6 +118,10 @@ static int psycho_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
u16 tmp16; u16 tmp16;
u8 tmp8; u8 tmp8;
if (bus_dev == pbm->pci_bus && devfn == 0x00)
return pci_host_bridge_read_pci_cfg(bus_dev, devfn, where,
size, value);
switch (size) { switch (size) {
case 1: case 1:
*value = 0xff; *value = 0xff;
...@@ -172,6 +175,9 @@ static int psycho_write_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn, ...@@ -172,6 +175,9 @@ static int psycho_write_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
unsigned char bus = bus_dev->number; unsigned char bus = bus_dev->number;
u32 *addr; u32 *addr;
if (bus_dev == pbm->pci_bus && devfn == 0x00)
return pci_host_bridge_write_pci_cfg(bus_dev, devfn, where,
size, value);
addr = psycho_pci_config_mkaddr(pbm, bus, devfn, where); addr = psycho_pci_config_mkaddr(pbm, bus, devfn, where);
if (!addr) if (!addr)
return PCIBIOS_SUCCESSFUL; return PCIBIOS_SUCCESSFUL;
...@@ -263,7 +269,7 @@ static void __psycho_check_one_stc(struct pci_controller_info *p, ...@@ -263,7 +269,7 @@ static void __psycho_check_one_stc(struct pci_controller_info *p,
struct pci_pbm_info *pbm, struct pci_pbm_info *pbm,
int is_pbm_a) int is_pbm_a)
{ {
struct pci_strbuf *strbuf = &pbm->stc; struct strbuf *strbuf = &pbm->stc;
unsigned long regbase = p->pbm_A.controller_regs; unsigned long regbase = p->pbm_A.controller_regs;
unsigned long err_base, tag_base, line_base; unsigned long err_base, tag_base, line_base;
u64 control; u64 control;
...@@ -412,7 +418,7 @@ static void psycho_check_iommu_error(struct pci_controller_info *p, ...@@ -412,7 +418,7 @@ static void psycho_check_iommu_error(struct pci_controller_info *p,
unsigned long afar, unsigned long afar,
enum psycho_error_type type) enum psycho_error_type type)
{ {
struct pci_iommu *iommu = p->pbm_A.iommu; struct iommu *iommu = p->pbm_A.iommu;
unsigned long iommu_tag[16]; unsigned long iommu_tag[16];
unsigned long iommu_data[16]; unsigned long iommu_data[16];
unsigned long flags; unsigned long flags;
...@@ -895,59 +901,6 @@ static void psycho_register_error_handlers(struct pci_controller_info *p) ...@@ -895,59 +901,6 @@ static void psycho_register_error_handlers(struct pci_controller_info *p)
} }
/* PSYCHO boot time probing and initialization. */ /* PSYCHO boot time probing and initialization. */
static void psycho_resource_adjust(struct pci_dev *pdev,
struct resource *res,
struct resource *root)
{
res->start += root->start;
res->end += root->start;
}
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 resource *res, *root;
u32 reg;
int where, size, is_64bit;
res = &pdev->resource[resource];
if (resource < 6) {
where = PCI_BASE_ADDRESS_0 + (resource * 4);
} else if (resource == PCI_ROM_RESOURCE) {
where = pdev->rom_base_reg;
} else {
/* Somebody might have asked allocation of a non-standard resource */
return;
}
is_64bit = 0;
if (res->flags & IORESOURCE_IO)
root = &pbm->io_space;
else {
root = &pbm->mem_space;
if ((res->flags & PCI_BASE_ADDRESS_MEM_TYPE_MASK)
== PCI_BASE_ADDRESS_MEM_TYPE_64)
is_64bit = 1;
}
size = res->end - res->start;
pci_read_config_dword(pdev, where, &reg);
reg = ((reg & size) |
(((u32)(res->start - root->start)) & ~size));
if (resource == PCI_ROM_RESOURCE) {
reg |= PCI_ROM_ADDRESS_ENABLE;
res->flags |= IORESOURCE_ROM_ENABLE;
}
pci_write_config_dword(pdev, where, reg);
/* This knows that the upper 32-bits of the address
* must be zero. Our PCI common layer enforces this.
*/
if (is_64bit)
pci_write_config_dword(pdev, where + 4, 0);
}
static void pbm_config_busmastering(struct pci_pbm_info *pbm) static void pbm_config_busmastering(struct pci_pbm_info *pbm)
{ {
u8 *addr; u8 *addr;
...@@ -968,28 +921,7 @@ static void pbm_config_busmastering(struct pci_pbm_info *pbm) ...@@ -968,28 +921,7 @@ static void pbm_config_busmastering(struct pci_pbm_info *pbm)
static void pbm_scan_bus(struct pci_controller_info *p, static void pbm_scan_bus(struct pci_controller_info *p,
struct pci_pbm_info *pbm) struct pci_pbm_info *pbm)
{ {
struct pcidev_cookie *cookie = kzalloc(sizeof(*cookie), GFP_KERNEL); pbm->pci_bus = pci_scan_one_pbm(pbm);
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);
} }
static void psycho_scan_bus(struct pci_controller_info *p) static void psycho_scan_bus(struct pci_controller_info *p)
...@@ -1009,7 +941,7 @@ static void psycho_scan_bus(struct pci_controller_info *p) ...@@ -1009,7 +941,7 @@ static void psycho_scan_bus(struct pci_controller_info *p)
static void psycho_iommu_init(struct pci_controller_info *p) static void psycho_iommu_init(struct pci_controller_info *p)
{ {
struct pci_iommu *iommu = p->pbm_A.iommu; struct iommu *iommu = p->pbm_A.iommu;
unsigned long i; unsigned long i;
u64 control; u64 control;
...@@ -1094,19 +1026,6 @@ static void psycho_controller_hwinit(struct pci_controller_info *p) ...@@ -1094,19 +1026,6 @@ static void psycho_controller_hwinit(struct pci_controller_info *p)
psycho_write(p->pbm_A.controller_regs + PSYCHO_PCIB_DIAG, tmp); psycho_write(p->pbm_A.controller_regs + PSYCHO_PCIB_DIAG, tmp);
} }
static void pbm_register_toplevel_resources(struct pci_controller_info *p,
struct pci_pbm_info *pbm)
{
char *name = pbm->name;
pbm->io_space.name = pbm->mem_space.name = name;
request_resource(&ioport_resource, &pbm->io_space);
request_resource(&iomem_resource, &pbm->mem_space);
pci_register_legacy_regions(&pbm->io_space,
&pbm->mem_space);
}
static void psycho_pbm_strbuf_init(struct pci_controller_info *p, static void psycho_pbm_strbuf_init(struct pci_controller_info *p,
struct pci_pbm_info *pbm, struct pci_pbm_info *pbm,
int is_pbm_a) int is_pbm_a)
...@@ -1172,19 +1091,11 @@ static void psycho_pbm_init(struct pci_controller_info *p, ...@@ -1172,19 +1091,11 @@ static void psycho_pbm_init(struct pci_controller_info *p,
unsigned int *busrange; unsigned int *busrange;
struct property *prop; struct property *prop;
struct pci_pbm_info *pbm; struct pci_pbm_info *pbm;
int len;
if (is_pbm_a) { if (is_pbm_a)
pbm = &p->pbm_A; pbm = &p->pbm_A;
pbm->pci_first_slot = 1; else
pbm->io_space.start = pbm->controller_regs + PSYCHO_IOSPACE_A;
pbm->mem_space.start = pbm->controller_regs + PSYCHO_MEMSPACE_A;
} else {
pbm = &p->pbm_B; pbm = &p->pbm_B;
pbm->pci_first_slot = 2;
pbm->io_space.start = pbm->controller_regs + PSYCHO_IOSPACE_B;
pbm->mem_space.start = pbm->controller_regs + PSYCHO_MEMSPACE_B;
}
pbm->chip_type = PBM_CHIP_TYPE_PSYCHO; pbm->chip_type = PBM_CHIP_TYPE_PSYCHO;
pbm->chip_version = 0; pbm->chip_version = 0;
...@@ -1196,41 +1107,15 @@ static void psycho_pbm_init(struct pci_controller_info *p, ...@@ -1196,41 +1107,15 @@ static void psycho_pbm_init(struct pci_controller_info *p,
if (prop) if (prop)
pbm->chip_revision = *(int *) prop->value; pbm->chip_revision = *(int *) prop->value;
pbm->io_space.end = pbm->io_space.start + PSYCHO_IOSPACE_SIZE;
pbm->io_space.flags = IORESOURCE_IO;
pbm->mem_space.end = pbm->mem_space.start + PSYCHO_MEMSPACE_SIZE;
pbm->mem_space.flags = IORESOURCE_MEM;
pbm->parent = p; pbm->parent = p;
pbm->prom_node = dp; pbm->prom_node = dp;
pbm->name = dp->full_name; pbm->name = dp->full_name;
pbm_register_toplevel_resources(p, pbm);
printk("%s: PSYCHO PCI Bus Module ver[%x:%x]\n", printk("%s: PSYCHO PCI Bus Module ver[%x:%x]\n",
pbm->name, pbm->name,
pbm->chip_version, pbm->chip_revision); pbm->chip_version, pbm->chip_revision);
prop = of_find_property(dp, "ranges", &len); pci_determine_mem_io_space(pbm);
if (prop) {
pbm->pbm_ranges = prop->value;
pbm->num_pbm_ranges =
(len / sizeof(struct linux_prom_pci_ranges));
} else {
pbm->num_pbm_ranges = 0;
}
prop = of_find_property(dp, "interrupt-map", &len);
if (prop) {
pbm->pbm_intmap = prop->value;
pbm->num_pbm_intmap =
(len / sizeof(struct linux_prom_pci_intmap));
prop = of_find_property(dp, "interrupt-map-mask", NULL);
pbm->pbm_intmask = prop->value;
} else {
pbm->num_pbm_intmap = 0;
}
prop = of_find_property(dp, "bus-range", NULL); prop = of_find_property(dp, "bus-range", NULL);
busrange = prop->value; busrange = prop->value;
...@@ -1246,7 +1131,7 @@ void psycho_init(struct device_node *dp, char *model_name) ...@@ -1246,7 +1131,7 @@ void psycho_init(struct device_node *dp, char *model_name)
{ {
struct linux_prom64_registers *pr_regs; struct linux_prom64_registers *pr_regs;
struct pci_controller_info *p; struct pci_controller_info *p;
struct pci_iommu *iommu; struct iommu *iommu;
struct property *prop; struct property *prop;
u32 upa_portid; u32 upa_portid;
int is_pbm_a; int is_pbm_a;
...@@ -1269,7 +1154,7 @@ void psycho_init(struct device_node *dp, char *model_name) ...@@ -1269,7 +1154,7 @@ void psycho_init(struct device_node *dp, char *model_name)
prom_printf("PSYCHO: Fatal memory allocation error.\n"); prom_printf("PSYCHO: Fatal memory allocation error.\n");
prom_halt(); prom_halt();
} }
iommu = kzalloc(sizeof(struct pci_iommu), GFP_ATOMIC); iommu = kzalloc(sizeof(struct iommu), GFP_ATOMIC);
if (!iommu) { if (!iommu) {
prom_printf("PSYCHO: Fatal memory allocation error.\n"); prom_printf("PSYCHO: Fatal memory allocation error.\n");
prom_halt(); prom_halt();
...@@ -1282,10 +1167,7 @@ void psycho_init(struct device_node *dp, char *model_name) ...@@ -1282,10 +1167,7 @@ void psycho_init(struct device_node *dp, char *model_name)
p->pbm_A.portid = upa_portid; p->pbm_A.portid = upa_portid;
p->pbm_B.portid = upa_portid; p->pbm_B.portid = upa_portid;
p->index = pci_num_controllers++; p->index = pci_num_controllers++;
p->pbms_same_domain = 0;
p->scan_bus = psycho_scan_bus; p->scan_bus = psycho_scan_bus;
p->base_address_update = psycho_base_address_update;
p->resource_adjust = psycho_resource_adjust;
p->pci_ops = &psycho_ops; p->pci_ops = &psycho_ops;
prop = of_find_property(dp, "reg", NULL); prop = of_find_property(dp, "reg", NULL);
......
/* $Id: pci_sabre.c,v 1.42 2002/01/23 11:27:32 davem Exp $ /* pci_sabre.c: Sabre specific PCI controller support.
* pci_sabre.c: Sabre specific PCI controller support.
* *
* Copyright (C) 1997, 1998, 1999 David S. Miller (davem@caipfs.rutgers.edu) * Copyright (C) 1997, 1998, 1999, 2007 David S. Miller (davem@davemloft.net)
* Copyright (C) 1998, 1999 Eddie C. Dost (ecd@skynet.be) * Copyright (C) 1998, 1999 Eddie C. Dost (ecd@skynet.be)
* Copyright (C) 1999 Jakub Jelinek (jakub@redhat.com) * Copyright (C) 1999 Jakub Jelinek (jakub@redhat.com)
*/ */
...@@ -254,9 +253,6 @@ static int __sabre_out_of_range(struct pci_pbm_info *pbm, ...@@ -254,9 +253,6 @@ static int __sabre_out_of_range(struct pci_pbm_info *pbm,
return 0; return 0;
return ((pbm->parent == 0) || return ((pbm->parent == 0) ||
((pbm == &pbm->parent->pbm_B) &&
(bus == pbm->pci_first_busno) &&
PCI_SLOT(devfn) > 8) ||
((pbm == &pbm->parent->pbm_A) && ((pbm == &pbm->parent->pbm_A) &&
(bus == pbm->pci_first_busno) && (bus == pbm->pci_first_busno) &&
PCI_SLOT(devfn) > 8)); PCI_SLOT(devfn) > 8));
...@@ -322,6 +318,12 @@ static int __sabre_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn, ...@@ -322,6 +318,12 @@ static int __sabre_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
static int sabre_read_pci_cfg(struct pci_bus *bus, unsigned int devfn, static int sabre_read_pci_cfg(struct pci_bus *bus, unsigned int devfn,
int where, int size, u32 *value) int where, int size, u32 *value)
{ {
struct pci_pbm_info *pbm = bus->sysdata;
if (bus == pbm->pci_bus && devfn == 0x00)
return pci_host_bridge_read_pci_cfg(bus, devfn, where,
size, value);
if (!bus->number && sabre_out_of_range(devfn)) { if (!bus->number && sabre_out_of_range(devfn)) {
switch (size) { switch (size) {
case 1: case 1:
...@@ -438,6 +440,12 @@ static int __sabre_write_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn, ...@@ -438,6 +440,12 @@ static int __sabre_write_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
static int sabre_write_pci_cfg(struct pci_bus *bus, unsigned int devfn, static int sabre_write_pci_cfg(struct pci_bus *bus, unsigned int devfn,
int where, int size, u32 value) int where, int size, u32 value)
{ {
struct pci_pbm_info *pbm = bus->sysdata;
if (bus == pbm->pci_bus && devfn == 0x00)
return pci_host_bridge_write_pci_cfg(bus, devfn, where,
size, value);
if (bus->number) if (bus->number)
return __sabre_write_pci_cfg(bus, devfn, where, size, value); return __sabre_write_pci_cfg(bus, devfn, where, size, value);
...@@ -490,7 +498,7 @@ static void sabre_check_iommu_error(struct pci_controller_info *p, ...@@ -490,7 +498,7 @@ static void sabre_check_iommu_error(struct pci_controller_info *p,
unsigned long afsr, unsigned long afsr,
unsigned long afar) unsigned long afar)
{ {
struct pci_iommu *iommu = p->pbm_A.iommu; struct iommu *iommu = p->pbm_A.iommu;
unsigned long iommu_tag[16]; unsigned long iommu_tag[16];
unsigned long iommu_data[16]; unsigned long iommu_data[16];
unsigned long flags; unsigned long flags;
...@@ -710,7 +718,7 @@ static irqreturn_t sabre_pcierr_intr_other(struct pci_controller_info *p) ...@@ -710,7 +718,7 @@ static irqreturn_t sabre_pcierr_intr_other(struct pci_controller_info *p)
p->index); p->index);
ret = IRQ_HANDLED; ret = IRQ_HANDLED;
} }
pci_read_config_word(sabre_root_bus->self, pci_bus_read_config_word(sabre_root_bus, 0,
PCI_STATUS, &stat); PCI_STATUS, &stat);
if (stat & (PCI_STATUS_PARITY | if (stat & (PCI_STATUS_PARITY |
PCI_STATUS_SIG_TARGET_ABORT | PCI_STATUS_SIG_TARGET_ABORT |
...@@ -719,7 +727,7 @@ static irqreturn_t sabre_pcierr_intr_other(struct pci_controller_info *p) ...@@ -719,7 +727,7 @@ static irqreturn_t sabre_pcierr_intr_other(struct pci_controller_info *p)
PCI_STATUS_SIG_SYSTEM_ERROR)) { PCI_STATUS_SIG_SYSTEM_ERROR)) {
printk("SABRE%d: PCI bus error, PCI_STATUS[%04x]\n", printk("SABRE%d: PCI bus error, PCI_STATUS[%04x]\n",
p->index, stat); p->index, stat);
pci_write_config_word(sabre_root_bus->self, pci_bus_write_config_word(sabre_root_bus, 0,
PCI_STATUS, 0xffff); PCI_STATUS, 0xffff);
ret = IRQ_HANDLED; ret = IRQ_HANDLED;
} }
...@@ -800,12 +808,10 @@ static irqreturn_t sabre_pcierr_intr(int irq, void *dev_id) ...@@ -800,12 +808,10 @@ static irqreturn_t sabre_pcierr_intr(int irq, void *dev_id)
if (error_bits & (SABRE_PIOAFSR_PTA | SABRE_PIOAFSR_STA)) { if (error_bits & (SABRE_PIOAFSR_PTA | SABRE_PIOAFSR_STA)) {
sabre_check_iommu_error(p, afsr, afar); sabre_check_iommu_error(p, afsr, afar);
pci_scan_for_target_abort(p, &p->pbm_A, p->pbm_A.pci_bus); pci_scan_for_target_abort(p, &p->pbm_A, p->pbm_A.pci_bus);
pci_scan_for_target_abort(p, &p->pbm_B, p->pbm_B.pci_bus);
} }
if (error_bits & (SABRE_PIOAFSR_PMA | SABRE_PIOAFSR_SMA)) { if (error_bits & (SABRE_PIOAFSR_PMA | SABRE_PIOAFSR_SMA))
pci_scan_for_master_abort(p, &p->pbm_A, p->pbm_A.pci_bus); pci_scan_for_master_abort(p, &p->pbm_A, p->pbm_A.pci_bus);
pci_scan_for_master_abort(p, &p->pbm_B, p->pbm_B.pci_bus);
}
/* For excessive retries, SABRE/PBM will abort the device /* For excessive retries, SABRE/PBM will abort the device
* and there is no way to specifically check for excessive * and there is no way to specifically check for excessive
* retries in the config space status registers. So what * retries in the config space status registers. So what
...@@ -813,10 +819,8 @@ static irqreturn_t sabre_pcierr_intr(int irq, void *dev_id) ...@@ -813,10 +819,8 @@ static irqreturn_t sabre_pcierr_intr(int irq, void *dev_id)
* abort events. * abort events.
*/ */
if (error_bits & (SABRE_PIOAFSR_PPERR | SABRE_PIOAFSR_SPERR)) { if (error_bits & (SABRE_PIOAFSR_PPERR | SABRE_PIOAFSR_SPERR))
pci_scan_for_parity_error(p, &p->pbm_A, p->pbm_A.pci_bus); pci_scan_for_parity_error(p, &p->pbm_A, p->pbm_A.pci_bus);
pci_scan_for_parity_error(p, &p->pbm_B, p->pbm_B.pci_bus);
}
return IRQ_HANDLED; return IRQ_HANDLED;
} }
...@@ -869,108 +873,35 @@ static void sabre_register_error_handlers(struct pci_controller_info *p) ...@@ -869,108 +873,35 @@ static void sabre_register_error_handlers(struct pci_controller_info *p)
sabre_write(base + SABRE_PCICTRL, tmp); sabre_write(base + SABRE_PCICTRL, tmp);
} }
static void sabre_resource_adjust(struct pci_dev *pdev,
struct resource *res,
struct resource *root)
{
struct pci_pbm_info *pbm = pdev->bus->sysdata;
unsigned long base;
if (res->flags & IORESOURCE_IO)
base = pbm->controller_regs + SABRE_IOSPACE;
else
base = pbm->controller_regs + SABRE_MEMSPACE;
res->start += base;
res->end += base;
}
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 resource *res;
unsigned long base;
u32 reg;
int where, size, is_64bit;
res = &pdev->resource[resource];
if (resource < 6) {
where = PCI_BASE_ADDRESS_0 + (resource * 4);
} else if (resource == PCI_ROM_RESOURCE) {
where = pdev->rom_base_reg;
} else {
/* Somebody might have asked allocation of a non-standard resource */
return;
}
is_64bit = 0;
if (res->flags & IORESOURCE_IO)
base = pbm->controller_regs + SABRE_IOSPACE;
else {
base = pbm->controller_regs + SABRE_MEMSPACE;
if ((res->flags & PCI_BASE_ADDRESS_MEM_TYPE_MASK)
== PCI_BASE_ADDRESS_MEM_TYPE_64)
is_64bit = 1;
}
size = res->end - res->start;
pci_read_config_dword(pdev, where, &reg);
reg = ((reg & size) |
(((u32)(res->start - base)) & ~size));
if (resource == PCI_ROM_RESOURCE) {
reg |= PCI_ROM_ADDRESS_ENABLE;
res->flags |= IORESOURCE_ROM_ENABLE;
}
pci_write_config_dword(pdev, where, reg);
/* This knows that the upper 32-bits of the address
* must be zero. Our PCI common layer enforces this.
*/
if (is_64bit)
pci_write_config_dword(pdev, where + 4, 0);
}
static void apb_init(struct pci_controller_info *p, struct pci_bus *sabre_bus) static void apb_init(struct pci_controller_info *p, struct pci_bus *sabre_bus)
{ {
struct pci_dev *pdev; struct pci_dev *pdev;
list_for_each_entry(pdev, &sabre_bus->devices, bus_list) { list_for_each_entry(pdev, &sabre_bus->devices, bus_list) {
if (pdev->vendor == PCI_VENDOR_ID_SUN && if (pdev->vendor == PCI_VENDOR_ID_SUN &&
pdev->device == PCI_DEVICE_ID_SUN_SIMBA) { pdev->device == PCI_DEVICE_ID_SUN_SIMBA) {
u32 word32;
u16 word16; u16 word16;
sabre_read_pci_cfg(pdev->bus, pdev->devfn, pci_read_config_word(pdev, PCI_COMMAND, &word16);
PCI_COMMAND, 2, &word32);
word16 = (u16) word32;
word16 |= PCI_COMMAND_SERR | PCI_COMMAND_PARITY | word16 |= PCI_COMMAND_SERR | PCI_COMMAND_PARITY |
PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY |
PCI_COMMAND_IO; PCI_COMMAND_IO;
word32 = (u32) word16; pci_write_config_word(pdev, PCI_COMMAND, word16);
sabre_write_pci_cfg(pdev->bus, pdev->devfn,
PCI_COMMAND, 2, word32);
/* Status register bits are "write 1 to clear". */ /* Status register bits are "write 1 to clear". */
sabre_write_pci_cfg(pdev->bus, pdev->devfn, pci_write_config_word(pdev, PCI_STATUS, 0xffff);
PCI_STATUS, 2, 0xffff); pci_write_config_word(pdev, PCI_SEC_STATUS, 0xffff);
sabre_write_pci_cfg(pdev->bus, pdev->devfn,
PCI_SEC_STATUS, 2, 0xffff);
/* Use a primary/seconday latency timer value /* Use a primary/seconday latency timer value
* of 64. * of 64.
*/ */
sabre_write_pci_cfg(pdev->bus, pdev->devfn, pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 64);
PCI_LATENCY_TIMER, 1, 64); pci_write_config_byte(pdev, PCI_SEC_LATENCY_TIMER, 64);
sabre_write_pci_cfg(pdev->bus, pdev->devfn,
PCI_SEC_LATENCY_TIMER, 1, 64);
/* Enable reporting/forwarding of master aborts, /* Enable reporting/forwarding of master aborts,
* parity, and SERR. * parity, and SERR.
*/ */
sabre_write_pci_cfg(pdev->bus, pdev->devfn, pci_write_config_byte(pdev, PCI_BRIDGE_CONTROL,
PCI_BRIDGE_CONTROL, 1,
(PCI_BRIDGE_CTL_PARITY | (PCI_BRIDGE_CTL_PARITY |
PCI_BRIDGE_CTL_SERR | PCI_BRIDGE_CTL_SERR |
PCI_BRIDGE_CTL_MASTER_ABORT)); PCI_BRIDGE_CTL_MASTER_ABORT));
...@@ -978,35 +909,16 @@ static void apb_init(struct pci_controller_info *p, struct pci_bus *sabre_bus) ...@@ -978,35 +909,16 @@ 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 void sabre_scan_bus(struct pci_controller_info *p)
{ {
static int once; static int once;
struct pci_bus *sabre_bus, *pbus; struct pci_bus *pbus;
struct pci_pbm_info *pbm;
struct pcidev_cookie *cookie;
int sabres_scanned;
/* The APB bridge speaks to the Sabre host PCI bridge /* The APB bridge speaks to the Sabre host PCI bridge
* at 66Mhz, but the front side of APB runs at 33Mhz * at 66Mhz, but the front side of APB runs at 33Mhz
* for both segments. * for both segments.
*/ */
p->pbm_A.is_66mhz_capable = 0; p->pbm_A.is_66mhz_capable = 0;
p->pbm_B.is_66mhz_capable = 0;
/* This driver has not been verified to handle /* This driver has not been verified to handle
* multiple SABREs yet, so trap this. * multiple SABREs yet, so trap this.
...@@ -1020,56 +932,13 @@ static void sabre_scan_bus(struct pci_controller_info *p) ...@@ -1020,56 +932,13 @@ static void sabre_scan_bus(struct pci_controller_info *p)
} }
once++; once++;
cookie = alloc_bridge_cookie(&p->pbm_A); pbus = pci_scan_one_pbm(&p->pbm_A);
if (!pbus)
sabre_bus = pci_scan_bus(p->pci_first_busno, return;
p->pci_ops,
&p->pbm_A);
pci_fixup_host_bridge_self(sabre_bus);
sabre_bus->self->sysdata = cookie;
sabre_root_bus = sabre_bus;
apb_init(p, sabre_bus);
sabres_scanned = 0;
list_for_each_entry(pbus, &sabre_bus->children, node) {
if (pbus->number == p->pbm_A.pci_first_busno) {
pbm = &p->pbm_A;
} else if (pbus->number == p->pbm_B.pci_first_busno) {
pbm = &p->pbm_B;
} else
continue;
cookie = alloc_bridge_cookie(pbm);
pbus->self->sysdata = cookie;
sabres_scanned++;
pbus->sysdata = pbm; sabre_root_bus = pbus;
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) { apb_init(p, pbus);
/* Hummingbird, no APBs. */
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); sabre_register_error_handlers(p);
} }
...@@ -1078,7 +947,7 @@ static void sabre_iommu_init(struct pci_controller_info *p, ...@@ -1078,7 +947,7 @@ static void sabre_iommu_init(struct pci_controller_info *p,
int tsbsize, unsigned long dvma_offset, int tsbsize, unsigned long dvma_offset,
u32 dma_mask) u32 dma_mask)
{ {
struct pci_iommu *iommu = p->pbm_A.iommu; struct iommu *iommu = p->pbm_A.iommu;
unsigned long i; unsigned long i;
u64 control; u64 control;
...@@ -1126,224 +995,31 @@ static void sabre_iommu_init(struct pci_controller_info *p, ...@@ -1126,224 +995,31 @@ static void sabre_iommu_init(struct pci_controller_info *p,
sabre_write(p->pbm_A.controller_regs + SABRE_IOMMU_CONTROL, control); sabre_write(p->pbm_A.controller_regs + SABRE_IOMMU_CONTROL, control);
} }
static void pbm_register_toplevel_resources(struct pci_controller_info *p, static void sabre_pbm_init(struct pci_controller_info *p, struct device_node *dp)
struct pci_pbm_info *pbm)
{
char *name = pbm->name;
unsigned long ibase = p->pbm_A.controller_regs + SABRE_IOSPACE;
unsigned long mbase = p->pbm_A.controller_regs + SABRE_MEMSPACE;
unsigned int devfn;
unsigned long first, last, i;
u8 *addr, map;
sprintf(name, "SABRE%d PBM%c",
p->index,
(pbm == &p->pbm_A ? 'A' : 'B'));
pbm->io_space.name = pbm->mem_space.name = name;
devfn = PCI_DEVFN(1, (pbm == &p->pbm_A) ? 0 : 1);
addr = sabre_pci_config_mkaddr(pbm, 0, devfn, APB_IO_ADDRESS_MAP);
map = 0;
pci_config_read8(addr, &map);
first = 8;
last = 0;
for (i = 0; i < 8; i++) {
if ((map & (1 << i)) != 0) {
if (first > i)
first = i;
if (last < i)
last = i;
}
}
pbm->io_space.start = ibase + (first << 21UL);
pbm->io_space.end = ibase + (last << 21UL) + ((1 << 21UL) - 1);
pbm->io_space.flags = IORESOURCE_IO;
addr = sabre_pci_config_mkaddr(pbm, 0, devfn, APB_MEM_ADDRESS_MAP);
map = 0;
pci_config_read8(addr, &map);
first = 8;
last = 0;
for (i = 0; i < 8; i++) {
if ((map & (1 << i)) != 0) {
if (first > i)
first = i;
if (last < i)
last = i;
}
}
pbm->mem_space.start = mbase + (first << 29UL);
pbm->mem_space.end = mbase + (last << 29UL) + ((1 << 29UL) - 1);
pbm->mem_space.flags = IORESOURCE_MEM;
if (request_resource(&ioport_resource, &pbm->io_space) < 0) {
prom_printf("Cannot register PBM-%c's IO space.\n",
(pbm == &p->pbm_A ? 'A' : 'B'));
prom_halt();
}
if (request_resource(&iomem_resource, &pbm->mem_space) < 0) {
prom_printf("Cannot register PBM-%c's MEM space.\n",
(pbm == &p->pbm_A ? 'A' : 'B'));
prom_halt();
}
/* Register legacy regions if this PBM covers that area. */
if (pbm->io_space.start == ibase &&
pbm->mem_space.start == mbase)
pci_register_legacy_regions(&pbm->io_space,
&pbm->mem_space);
}
static void sabre_pbm_init(struct pci_controller_info *p, struct device_node *dp, u32 dma_start, u32 dma_end)
{ {
struct pci_pbm_info *pbm; struct pci_pbm_info *pbm;
struct device_node *node;
struct property *prop;
u32 *busrange;
int len, simbas_found;
simbas_found = 0;
node = dp->child;
while (node != NULL) {
if (strcmp(node->name, "pci"))
goto next_pci;
prop = of_find_property(node, "model", NULL);
if (!prop || strncmp(prop->value, "SUNW,simba", prop->length))
goto next_pci;
simbas_found++;
prop = of_find_property(node, "bus-range", NULL);
busrange = prop->value;
if (busrange[0] == 1)
pbm = &p->pbm_B;
else
pbm = &p->pbm_A;
pbm->name = node->full_name; pbm = &p->pbm_A;
pbm->name = dp->full_name;
printk("%s: SABRE PCI Bus Module\n", pbm->name); printk("%s: SABRE PCI Bus Module\n", pbm->name);
pbm->chip_type = PBM_CHIP_TYPE_SABRE; pbm->chip_type = PBM_CHIP_TYPE_SABRE;
pbm->parent = p; pbm->parent = p;
pbm->prom_node = node;
pbm->pci_first_slot = 1;
pbm->pci_first_busno = busrange[0];
pbm->pci_last_busno = busrange[1];
prop = of_find_property(node, "ranges", &len);
if (prop) {
pbm->pbm_ranges = prop->value;
pbm->num_pbm_ranges =
(len / sizeof(struct linux_prom_pci_ranges));
} else {
pbm->num_pbm_ranges = 0;
}
prop = of_find_property(node, "interrupt-map", &len);
if (prop) {
pbm->pbm_intmap = prop->value;
pbm->num_pbm_intmap =
(len / sizeof(struct linux_prom_pci_intmap));
prop = of_find_property(node, "interrupt-map-mask",
NULL);
pbm->pbm_intmask = prop->value;
} else {
pbm->num_pbm_intmap = 0;
}
pbm_register_toplevel_resources(p, pbm);
next_pci:
node = node->sibling;
}
if (simbas_found == 0) {
struct resource *rp;
/* No APBs underneath, probably this is a hummingbird
* system.
*/
pbm = &p->pbm_A;
pbm->parent = p;
pbm->prom_node = dp; pbm->prom_node = dp;
pbm->pci_first_busno = p->pci_first_busno; pbm->pci_first_busno = p->pci_first_busno;
pbm->pci_last_busno = p->pci_last_busno; pbm->pci_last_busno = p->pci_last_busno;
prop = of_find_property(dp, "ranges", &len); pci_determine_mem_io_space(pbm);
if (prop) {
pbm->pbm_ranges = prop->value;
pbm->num_pbm_ranges =
(len / sizeof(struct linux_prom_pci_ranges));
} else {
pbm->num_pbm_ranges = 0;
}
prop = of_find_property(dp, "interrupt-map", &len);
if (prop) {
pbm->pbm_intmap = prop->value;
pbm->num_pbm_intmap =
(len / sizeof(struct linux_prom_pci_intmap));
prop = of_find_property(dp, "interrupt-map-mask",
NULL);
pbm->pbm_intmask = prop->value;
} else {
pbm->num_pbm_intmap = 0;
}
pbm->name = dp->full_name;
printk("%s: SABRE PCI Bus Module\n", pbm->name);
pbm->io_space.name = pbm->mem_space.name = pbm->name;
/* Hack up top-level resources. */
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.flags = IORESOURCE_IO;
pbm->mem_space.start =
(p->pbm_A.controller_regs + SABRE_MEMSPACE);
pbm->mem_space.end =
(pbm->mem_space.start + ((1UL << 32UL) - 1UL));
pbm->mem_space.flags = IORESOURCE_MEM;
if (request_resource(&ioport_resource, &pbm->io_space) < 0) {
prom_printf("Cannot register Hummingbird's IO space.\n");
prom_halt();
}
if (request_resource(&iomem_resource, &pbm->mem_space) < 0) {
prom_printf("Cannot register Hummingbird's MEM space.\n");
prom_halt();
}
rp = kmalloc(sizeof(*rp), GFP_KERNEL);
if (!rp) {
prom_printf("Cannot allocate IOMMU resource.\n");
prom_halt();
}
rp->name = "IOMMU";
rp->start = pbm->mem_space.start + (unsigned long) dma_start;
rp->end = pbm->mem_space.start + (unsigned long) dma_end - 1UL;
rp->flags = IORESOURCE_BUSY;
request_resource(&pbm->mem_space, rp);
pci_register_legacy_regions(&pbm->io_space,
&pbm->mem_space);
}
} }
void sabre_init(struct device_node *dp, char *model_name) void sabre_init(struct device_node *dp, char *model_name)
{ {
struct linux_prom64_registers *pr_regs; const struct linux_prom64_registers *pr_regs;
struct pci_controller_info *p; struct pci_controller_info *p;
struct pci_iommu *iommu; struct iommu *iommu;
struct property *prop;
int tsbsize; int tsbsize;
u32 *busrange; const u32 *busrange;
u32 *vdma; const u32 *vdma;
u32 upa_portid, dma_mask; u32 upa_portid, dma_mask;
u64 clear_irq; u64 clear_irq;
...@@ -1351,13 +1027,9 @@ void sabre_init(struct device_node *dp, char *model_name) ...@@ -1351,13 +1027,9 @@ void sabre_init(struct device_node *dp, char *model_name)
if (!strcmp(model_name, "pci108e,a001")) if (!strcmp(model_name, "pci108e,a001"))
hummingbird_p = 1; hummingbird_p = 1;
else if (!strcmp(model_name, "SUNW,sabre")) { else if (!strcmp(model_name, "SUNW,sabre")) {
prop = of_find_property(dp, "compatible", NULL); const char *compat = of_get_property(dp, "compatible", NULL);
if (prop) { if (compat && !strcmp(compat, "pci108e,a001"))
const char *compat = prop->value;
if (!strcmp(compat, "pci108e,a001"))
hummingbird_p = 1; hummingbird_p = 1;
}
if (!hummingbird_p) { if (!hummingbird_p) {
struct device_node *dp; struct device_node *dp;
...@@ -1381,37 +1053,28 @@ void sabre_init(struct device_node *dp, char *model_name) ...@@ -1381,37 +1053,28 @@ void sabre_init(struct device_node *dp, char *model_name)
prom_printf("SABRE: Error, kmalloc(pci_iommu) failed.\n"); prom_printf("SABRE: Error, kmalloc(pci_iommu) failed.\n");
prom_halt(); prom_halt();
} }
p->pbm_A.iommu = p->pbm_B.iommu = iommu; p->pbm_A.iommu = iommu;
upa_portid = 0xff; upa_portid = of_getintprop_default(dp, "upa-portid", 0xff);
prop = of_find_property(dp, "upa-portid", NULL);
if (prop)
upa_portid = *(u32 *) prop->value;
p->next = pci_controller_root; p->next = pci_controller_root;
pci_controller_root = p; pci_controller_root = p;
p->pbm_A.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->scan_bus = sabre_scan_bus; p->scan_bus = sabre_scan_bus;
p->base_address_update = sabre_base_address_update;
p->resource_adjust = sabre_resource_adjust;
p->pci_ops = &sabre_ops; p->pci_ops = &sabre_ops;
/* /*
* Map in SABRE register set and report the presence of this SABRE. * Map in SABRE register set and report the presence of this SABRE.
*/ */
prop = of_find_property(dp, "reg", NULL); pr_regs = of_get_property(dp, "reg", NULL);
pr_regs = prop->value;
/* /*
* First REG in property is base of entire SABRE register space. * First REG in property is base of entire SABRE register space.
*/ */
p->pbm_A.controller_regs = pr_regs[0].phys_addr; p->pbm_A.controller_regs = pr_regs[0].phys_addr;
p->pbm_B.controller_regs = pr_regs[0].phys_addr;
/* Clear interrupts */ /* Clear interrupts */
...@@ -1429,11 +1092,10 @@ void sabre_init(struct device_node *dp, char *model_name) ...@@ -1429,11 +1092,10 @@ void sabre_init(struct device_node *dp, char *model_name)
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_A.controller_regs + SABRE_CONFIGSPACE); (p->pbm_A.controller_regs + SABRE_CONFIGSPACE);
prop = of_find_property(dp, "virtual-dma", NULL); vdma = of_get_property(dp, "virtual-dma", NULL);
vdma = prop->value;
dma_mask = vdma[0]; dma_mask = vdma[0];
switch(vdma[1]) { switch(vdma[1]) {
...@@ -1457,13 +1119,12 @@ void sabre_init(struct device_node *dp, char *model_name) ...@@ -1457,13 +1119,12 @@ void sabre_init(struct device_node *dp, char *model_name)
sabre_iommu_init(p, tsbsize, vdma[0], dma_mask); sabre_iommu_init(p, tsbsize, vdma[0], dma_mask);
prop = of_find_property(dp, "bus-range", NULL); busrange = of_get_property(dp, "bus-range", NULL);
busrange = prop->value;
p->pci_first_busno = busrange[0]; p->pci_first_busno = busrange[0];
p->pci_last_busno = busrange[1]; p->pci_last_busno = busrange[1];
/* /*
* Look for APB underneath. * Look for APB underneath.
*/ */
sabre_pbm_init(p, dp, vdma[0], vdma[0] + vdma[1]); sabre_pbm_init(p, dp);
} }
/* $Id: pci_schizo.c,v 1.24 2002/01/23 11:27:32 davem Exp $ /* pci_schizo.c: SCHIZO/TOMATILLO specific PCI controller support.
* pci_schizo.c: SCHIZO/TOMATILLO specific PCI controller support.
* *
* Copyright (C) 2001, 2002, 2003 David S. Miller (davem@redhat.com) * Copyright (C) 2001, 2002, 2003, 2007 David S. Miller (davem@davemloft.net)
*/ */
#include <linux/kernel.h> #include <linux/kernel.h>
...@@ -126,6 +125,9 @@ static int schizo_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn, ...@@ -126,6 +125,9 @@ static int schizo_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
u16 tmp16; u16 tmp16;
u8 tmp8; u8 tmp8;
if (bus_dev == pbm->pci_bus && devfn == 0x00)
return pci_host_bridge_read_pci_cfg(bus_dev, devfn, where,
size, value);
switch (size) { switch (size) {
case 1: case 1:
*value = 0xff; *value = 0xff;
...@@ -179,6 +181,9 @@ static int schizo_write_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn, ...@@ -179,6 +181,9 @@ static int schizo_write_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
unsigned char bus = bus_dev->number; unsigned char bus = bus_dev->number;
u32 *addr; u32 *addr;
if (bus_dev == pbm->pci_bus && devfn == 0x00)
return pci_host_bridge_write_pci_cfg(bus_dev, devfn, where,
size, value);
addr = schizo_pci_config_mkaddr(pbm, bus, devfn, where); addr = schizo_pci_config_mkaddr(pbm, bus, devfn, where);
if (!addr) if (!addr)
return PCIBIOS_SUCCESSFUL; return PCIBIOS_SUCCESSFUL;
...@@ -274,7 +279,7 @@ struct pci_pbm_info *pbm_for_ino(struct pci_controller_info *p, u32 ino) ...@@ -274,7 +279,7 @@ struct pci_pbm_info *pbm_for_ino(struct pci_controller_info *p, u32 ino)
static void __schizo_check_stc_error_pbm(struct pci_pbm_info *pbm, static void __schizo_check_stc_error_pbm(struct pci_pbm_info *pbm,
enum schizo_error_type type) enum schizo_error_type type)
{ {
struct pci_strbuf *strbuf = &pbm->stc; struct strbuf *strbuf = &pbm->stc;
unsigned long regbase = pbm->pbm_regs; unsigned long regbase = pbm->pbm_regs;
unsigned long err_base, tag_base, line_base; unsigned long err_base, tag_base, line_base;
u64 control; u64 control;
...@@ -382,7 +387,7 @@ static void __schizo_check_stc_error_pbm(struct pci_pbm_info *pbm, ...@@ -382,7 +387,7 @@ static void __schizo_check_stc_error_pbm(struct pci_pbm_info *pbm,
static void schizo_check_iommu_error_pbm(struct pci_pbm_info *pbm, static void schizo_check_iommu_error_pbm(struct pci_pbm_info *pbm,
enum schizo_error_type type) enum schizo_error_type type)
{ {
struct pci_iommu *iommu = pbm->iommu; struct iommu *iommu = pbm->iommu;
unsigned long iommu_tag[16]; unsigned long iommu_tag[16];
unsigned long iommu_data[16]; unsigned long iommu_data[16];
unsigned long flags; unsigned long flags;
...@@ -1229,42 +1234,8 @@ static void pbm_config_busmastering(struct pci_pbm_info *pbm) ...@@ -1229,42 +1234,8 @@ static void pbm_config_busmastering(struct pci_pbm_info *pbm)
pci_config_write8(addr, 64); pci_config_write8(addr, 64);
} }
static void pbm_scan_bus(struct pci_controller_info *p, static void schizo_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);
}
static void __schizo_scan_bus(struct pci_controller_info *p,
int chip_type)
{ {
if (!p->pbm_B.prom_node || !p->pbm_A.prom_node) {
printk("PCI: Only one PCI bus module of controller found.\n");
printk("PCI: Ignoring entire controller.\n");
return;
}
pbm_config_busmastering(&p->pbm_B); pbm_config_busmastering(&p->pbm_B);
p->pbm_B.is_66mhz_capable = p->pbm_B.is_66mhz_capable =
(of_find_property(p->pbm_B.prom_node, "66mhz-capable", NULL) (of_find_property(p->pbm_B.prom_node, "66mhz-capable", NULL)
...@@ -1273,154 +1244,19 @@ static void __schizo_scan_bus(struct pci_controller_info *p, ...@@ -1273,154 +1244,19 @@ static void __schizo_scan_bus(struct pci_controller_info *p,
p->pbm_A.is_66mhz_capable = p->pbm_A.is_66mhz_capable =
(of_find_property(p->pbm_A.prom_node, "66mhz-capable", NULL) (of_find_property(p->pbm_A.prom_node, "66mhz-capable", NULL)
!= NULL); != NULL);
pbm_scan_bus(p, &p->pbm_B);
pbm_scan_bus(p, &p->pbm_A); p->pbm_B.pci_bus = pci_scan_one_pbm(&p->pbm_B);
p->pbm_A.pci_bus = pci_scan_one_pbm(&p->pbm_A);
/* After the PCI bus scan is complete, we can register /* After the PCI bus scan is complete, we can register
* the error interrupt handlers. * the error interrupt handlers.
*/ */
if (chip_type == PBM_CHIP_TYPE_TOMATILLO) if (p->pbm_B.chip_type == PBM_CHIP_TYPE_TOMATILLO)
tomatillo_register_error_handlers(p); tomatillo_register_error_handlers(p);
else else
schizo_register_error_handlers(p); schizo_register_error_handlers(p);
} }
static void schizo_scan_bus(struct pci_controller_info *p)
{
__schizo_scan_bus(p, PBM_CHIP_TYPE_SCHIZO);
}
static void tomatillo_scan_bus(struct pci_controller_info *p)
{
__schizo_scan_bus(p, PBM_CHIP_TYPE_TOMATILLO);
}
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 resource *res, *root;
u32 reg;
int where, size, is_64bit;
res = &pdev->resource[resource];
if (resource < 6) {
where = PCI_BASE_ADDRESS_0 + (resource * 4);
} else if (resource == PCI_ROM_RESOURCE) {
where = pdev->rom_base_reg;
} else {
/* Somebody might have asked allocation of a non-standard resource */
return;
}
is_64bit = 0;
if (res->flags & IORESOURCE_IO)
root = &pbm->io_space;
else {
root = &pbm->mem_space;
if ((res->flags & PCI_BASE_ADDRESS_MEM_TYPE_MASK)
== PCI_BASE_ADDRESS_MEM_TYPE_64)
is_64bit = 1;
}
size = res->end - res->start;
pci_read_config_dword(pdev, where, &reg);
reg = ((reg & size) |
(((u32)(res->start - root->start)) & ~size));
if (resource == PCI_ROM_RESOURCE) {
reg |= PCI_ROM_ADDRESS_ENABLE;
res->flags |= IORESOURCE_ROM_ENABLE;
}
pci_write_config_dword(pdev, where, reg);
/* This knows that the upper 32-bits of the address
* must be zero. Our PCI common layer enforces this.
*/
if (is_64bit)
pci_write_config_dword(pdev, where + 4, 0);
}
static void schizo_resource_adjust(struct pci_dev *pdev,
struct resource *res,
struct resource *root)
{
res->start += root->start;
res->end += root->start;
}
/* Use ranges property to determine where PCI MEM, I/O, and Config
* space are for this PCI bus module.
*/
static void schizo_determine_mem_io_space(struct pci_pbm_info *pbm)
{
int i, saw_cfg, saw_mem, saw_io;
saw_cfg = saw_mem = saw_io = 0;
for (i = 0; i < pbm->num_pbm_ranges; i++) {
struct linux_prom_pci_ranges *pr = &pbm->pbm_ranges[i];
unsigned long a;
int type;
type = (pr->child_phys_hi >> 24) & 0x3;
a = (((unsigned long)pr->parent_phys_hi << 32UL) |
((unsigned long)pr->parent_phys_lo << 0UL));
switch (type) {
case 0:
/* PCI config space, 16MB */
pbm->config_space = a;
saw_cfg = 1;
break;
case 1:
/* 16-bit IO space, 16MB */
pbm->io_space.start = a;
pbm->io_space.end = a + ((16UL*1024UL*1024UL) - 1UL);
pbm->io_space.flags = IORESOURCE_IO;
saw_io = 1;
break;
case 2:
/* 32-bit MEM space, 2GB */
pbm->mem_space.start = a;
pbm->mem_space.end = a + (0x80000000UL - 1UL);
pbm->mem_space.flags = IORESOURCE_MEM;
saw_mem = 1;
break;
default:
break;
};
}
if (!saw_cfg || !saw_io || !saw_mem) {
prom_printf("%s: Fatal error, missing %s PBM range.\n",
pbm->name,
((!saw_cfg ?
"CFG" :
(!saw_io ?
"IO" : "MEM"))));
prom_halt();
}
printk("%s: PCI CFG[%lx] IO[%lx] MEM[%lx]\n",
pbm->name,
pbm->config_space,
pbm->io_space.start,
pbm->mem_space.start);
}
static void pbm_register_toplevel_resources(struct pci_controller_info *p,
struct pci_pbm_info *pbm)
{
pbm->io_space.name = pbm->mem_space.name = pbm->name;
request_resource(&ioport_resource, &pbm->io_space);
request_resource(&iomem_resource, &pbm->mem_space);
pci_register_legacy_regions(&pbm->io_space,
&pbm->mem_space);
}
#define SCHIZO_STRBUF_CONTROL (0x02800UL) #define SCHIZO_STRBUF_CONTROL (0x02800UL)
#define SCHIZO_STRBUF_FLUSH (0x02808UL) #define SCHIZO_STRBUF_FLUSH (0x02808UL)
#define SCHIZO_STRBUF_FSYNC (0x02810UL) #define SCHIZO_STRBUF_FSYNC (0x02810UL)
...@@ -1472,7 +1308,7 @@ static void schizo_pbm_strbuf_init(struct pci_pbm_info *pbm) ...@@ -1472,7 +1308,7 @@ static void schizo_pbm_strbuf_init(struct pci_pbm_info *pbm)
static void schizo_pbm_iommu_init(struct pci_pbm_info *pbm) static void schizo_pbm_iommu_init(struct pci_pbm_info *pbm)
{ {
struct pci_iommu *iommu = pbm->iommu; struct iommu *iommu = pbm->iommu;
unsigned long i, tagbase, database; unsigned long i, tagbase, database;
struct property *prop; struct property *prop;
u32 vdma[2], dma_mask; u32 vdma[2], dma_mask;
...@@ -1654,14 +1490,12 @@ static void schizo_pbm_init(struct pci_controller_info *p, ...@@ -1654,14 +1490,12 @@ static void schizo_pbm_init(struct pci_controller_info *p,
struct device_node *dp, u32 portid, struct device_node *dp, u32 portid,
int chip_type) int chip_type)
{ {
struct linux_prom64_registers *regs; const struct linux_prom64_registers *regs;
struct property *prop; const unsigned int *busrange;
unsigned int *busrange;
struct pci_pbm_info *pbm; struct pci_pbm_info *pbm;
const char *chipset_name; const char *chipset_name;
u32 *ino_bitmap; const u32 *ino_bitmap;
int is_pbm_a; int is_pbm_a;
int len;
switch (chip_type) { switch (chip_type) {
case PBM_CHIP_TYPE_TOMATILLO: case PBM_CHIP_TYPE_TOMATILLO:
...@@ -1689,11 +1523,9 @@ static void schizo_pbm_init(struct pci_controller_info *p, ...@@ -1689,11 +1523,9 @@ static void schizo_pbm_init(struct pci_controller_info *p,
* 3) PBM PCI config space * 3) PBM PCI config space
* 4) Ichip regs * 4) Ichip regs
*/ */
prop = of_find_property(dp, "reg", NULL); regs = of_get_property(dp, "reg", NULL);
regs = prop->value;
is_pbm_a = ((regs[0].phys_addr & 0x00700000) == 0x00600000); is_pbm_a = ((regs[0].phys_addr & 0x00700000) == 0x00600000);
if (is_pbm_a) if (is_pbm_a)
pbm = &p->pbm_A; pbm = &p->pbm_A;
else else
...@@ -1702,17 +1534,10 @@ static void schizo_pbm_init(struct pci_controller_info *p, ...@@ -1702,17 +1534,10 @@ static void schizo_pbm_init(struct pci_controller_info *p,
pbm->portid = portid; pbm->portid = portid;
pbm->parent = p; pbm->parent = p;
pbm->prom_node = dp; pbm->prom_node = dp;
pbm->pci_first_slot = 1;
pbm->chip_type = chip_type; pbm->chip_type = chip_type;
pbm->chip_version = 0; pbm->chip_version = of_getintprop_default(dp, "version#", 0);
prop = of_find_property(dp, "version#", NULL); pbm->chip_revision = of_getintprop_default(dp, "module-version#", 0);
if (prop)
pbm->chip_version = *(int *) prop->value;
pbm->chip_revision = 0;
prop = of_find_property(dp, "module-revision#", NULL);
if (prop)
pbm->chip_revision = *(int *) prop->value;
pbm->pbm_regs = regs[0].phys_addr; pbm->pbm_regs = regs[0].phys_addr;
pbm->controller_regs = regs[1].phys_addr - 0x10000UL; pbm->controller_regs = regs[1].phys_addr - 0x10000UL;
...@@ -1723,40 +1548,18 @@ static void schizo_pbm_init(struct pci_controller_info *p, ...@@ -1723,40 +1548,18 @@ static void schizo_pbm_init(struct pci_controller_info *p,
pbm->name = dp->full_name; pbm->name = dp->full_name;
printk("%s: %s PCI Bus Module ver[%x:%x]\n", printk("%s: %s PCI Bus Module ver[%x:%x]\n",
pbm->name, pbm->name, chipset_name,
(chip_type == PBM_CHIP_TYPE_TOMATILLO ?
"TOMATILLO" : "SCHIZO"),
pbm->chip_version, pbm->chip_revision); pbm->chip_version, pbm->chip_revision);
schizo_pbm_hw_init(pbm); schizo_pbm_hw_init(pbm);
prop = of_find_property(dp, "ranges", &len); pci_determine_mem_io_space(pbm);
pbm->pbm_ranges = prop->value;
pbm->num_pbm_ranges =
(len / sizeof(struct linux_prom_pci_ranges));
schizo_determine_mem_io_space(pbm); ino_bitmap = of_get_property(dp, "ino-bitmap", NULL);
pbm_register_toplevel_resources(p, pbm);
prop = of_find_property(dp, "interrupt-map", &len);
if (prop) {
pbm->pbm_intmap = prop->value;
pbm->num_pbm_intmap =
(len / sizeof(struct linux_prom_pci_intmap));
prop = of_find_property(dp, "interrupt-map-mask", NULL);
pbm->pbm_intmask = prop->value;
} else {
pbm->num_pbm_intmap = 0;
}
prop = of_find_property(dp, "ino-bitmap", NULL);
ino_bitmap = prop->value;
pbm->ino_bitmap = (((u64)ino_bitmap[1] << 32UL) | pbm->ino_bitmap = (((u64)ino_bitmap[1] << 32UL) |
((u64)ino_bitmap[0] << 0UL)); ((u64)ino_bitmap[0] << 0UL));
prop = of_find_property(dp, "bus-range", NULL); busrange = of_get_property(dp, "bus-range", NULL);
busrange = prop->value;
pbm->pci_first_busno = busrange[0]; pbm->pci_first_busno = busrange[0];
pbm->pci_last_busno = busrange[1]; pbm->pci_last_busno = busrange[1];
...@@ -1777,15 +1580,10 @@ static inline int portid_compare(u32 x, u32 y, int chip_type) ...@@ -1777,15 +1580,10 @@ static inline int portid_compare(u32 x, u32 y, int chip_type)
static void __schizo_init(struct device_node *dp, char *model_name, int chip_type) static void __schizo_init(struct device_node *dp, char *model_name, int chip_type)
{ {
struct pci_controller_info *p; struct pci_controller_info *p;
struct pci_iommu *iommu; struct iommu *iommu;
struct property *prop;
int is_pbm_a;
u32 portid; u32 portid;
portid = 0xff; portid = of_getintprop_default(dp, "portid", 0xff);
prop = of_find_property(dp, "portid", NULL);
if (prop)
portid = *(u32 *) prop->value;
for (p = pci_controller_root; p; p = p->next) { for (p = pci_controller_root; p; p = p->next) {
struct pci_pbm_info *pbm; struct pci_pbm_info *pbm;
...@@ -1798,48 +1596,43 @@ static void __schizo_init(struct device_node *dp, char *model_name, int chip_typ ...@@ -1798,48 +1596,43 @@ static void __schizo_init(struct device_node *dp, char *model_name, int chip_typ
&p->pbm_B); &p->pbm_B);
if (portid_compare(pbm->portid, portid, chip_type)) { if (portid_compare(pbm->portid, portid, chip_type)) {
is_pbm_a = (p->pbm_A.prom_node == NULL);
schizo_pbm_init(p, dp, portid, chip_type); schizo_pbm_init(p, dp, portid, chip_type);
return; return;
} }
} }
p = kzalloc(sizeof(struct pci_controller_info), GFP_ATOMIC); p = kzalloc(sizeof(struct pci_controller_info), GFP_ATOMIC);
if (!p) { if (!p)
prom_printf("SCHIZO: Fatal memory allocation error.\n"); goto memfail;
prom_halt();
} iommu = kzalloc(sizeof(struct iommu), GFP_ATOMIC);
if (!iommu)
goto memfail;
iommu = kzalloc(sizeof(struct pci_iommu), GFP_ATOMIC);
if (!iommu) {
prom_printf("SCHIZO: Fatal memory allocation error.\n");
prom_halt();
}
p->pbm_A.iommu = iommu; p->pbm_A.iommu = iommu;
iommu = kzalloc(sizeof(struct pci_iommu), GFP_ATOMIC); iommu = kzalloc(sizeof(struct iommu), GFP_ATOMIC);
if (!iommu) { if (!iommu)
prom_printf("SCHIZO: Fatal memory allocation error.\n"); goto memfail;
prom_halt();
}
p->pbm_B.iommu = iommu; p->pbm_B.iommu = iommu;
p->next = pci_controller_root; p->next = pci_controller_root;
pci_controller_root = p; pci_controller_root = p;
p->index = pci_num_controllers++; p->index = pci_num_controllers++;
p->pbms_same_domain = 0; p->scan_bus = schizo_scan_bus;
p->scan_bus = (chip_type == PBM_CHIP_TYPE_TOMATILLO ?
tomatillo_scan_bus :
schizo_scan_bus);
p->base_address_update = schizo_base_address_update;
p->resource_adjust = schizo_resource_adjust;
p->pci_ops = &schizo_ops; p->pci_ops = &schizo_ops;
/* Like PSYCHO we have a 2GB aligned area for memory space. */ /* Like PSYCHO we have a 2GB aligned area for memory space. */
pci_memspace_mask = 0x7fffffffUL; pci_memspace_mask = 0x7fffffffUL;
schizo_pbm_init(p, dp, portid, chip_type); schizo_pbm_init(p, dp, portid, chip_type);
return;
memfail:
prom_printf("SCHIZO: Fatal memory allocation error.\n");
prom_halt();
} }
void schizo_init(struct device_node *dp, char *model_name) void schizo_init(struct device_node *dp, char *model_name)
......
此差异已折叠。
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#include <linux/reboot.h> #include <linux/reboot.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/compat.h> #include <linux/compat.h>
#include <linux/tick.h>
#include <linux/init.h> #include <linux/init.h>
#include <asm/oplib.h> #include <asm/oplib.h>
...@@ -88,13 +89,15 @@ void cpu_idle(void) ...@@ -88,13 +89,15 @@ void cpu_idle(void)
set_thread_flag(TIF_POLLING_NRFLAG); set_thread_flag(TIF_POLLING_NRFLAG);
while(1) { while(1) {
if (need_resched()) { tick_nohz_stop_sched_tick();
while (!need_resched())
sparc64_yield();
tick_nohz_restart_sched_tick();
preempt_enable_no_resched(); preempt_enable_no_resched();
schedule(); schedule();
preempt_disable(); preempt_disable();
} }
sparc64_yield();
}
} }
extern char reboot_command []; extern char reboot_command [];
......
...@@ -36,12 +36,13 @@ static struct device_node *allnodes; ...@@ -36,12 +36,13 @@ static struct device_node *allnodes;
*/ */
static DEFINE_RWLOCK(devtree_lock); static DEFINE_RWLOCK(devtree_lock);
int of_device_is_compatible(struct device_node *device, const char *compat) int of_device_is_compatible(const struct device_node *device,
const char *compat)
{ {
const char* cp; const char* cp;
int cplen, l; int cplen, l;
cp = (char *) of_get_property(device, "compatible", &cplen); cp = of_get_property(device, "compatible", &cplen);
if (cp == NULL) if (cp == NULL)
return 0; return 0;
while (cplen > 0) { while (cplen > 0) {
...@@ -154,13 +155,14 @@ struct device_node *of_find_compatible_node(struct device_node *from, ...@@ -154,13 +155,14 @@ struct device_node *of_find_compatible_node(struct device_node *from,
} }
EXPORT_SYMBOL(of_find_compatible_node); EXPORT_SYMBOL(of_find_compatible_node);
struct property *of_find_property(struct device_node *np, const char *name, struct property *of_find_property(const struct device_node *np,
const char *name,
int *lenp) int *lenp)
{ {
struct property *pp; struct property *pp;
for (pp = np->properties; pp != 0; pp = pp->next) { for (pp = np->properties; pp != 0; pp = pp->next) {
if (strcmp(pp->name, name) == 0) { if (strcasecmp(pp->name, name) == 0) {
if (lenp != 0) if (lenp != 0)
*lenp = pp->length; *lenp = pp->length;
break; break;
...@@ -174,7 +176,8 @@ EXPORT_SYMBOL(of_find_property); ...@@ -174,7 +176,8 @@ EXPORT_SYMBOL(of_find_property);
* Find a property with a given name for a given node * Find a property with a given name for a given node
* and return the value. * and return the value.
*/ */
void *of_get_property(struct device_node *np, const char *name, int *lenp) const void *of_get_property(const struct device_node *np, const char *name,
int *lenp)
{ {
struct property *pp = of_find_property(np,name,lenp); struct property *pp = of_find_property(np,name,lenp);
return pp ? pp->value : NULL; return pp ? pp->value : NULL;
...@@ -196,7 +199,7 @@ EXPORT_SYMBOL(of_getintprop_default); ...@@ -196,7 +199,7 @@ EXPORT_SYMBOL(of_getintprop_default);
int of_n_addr_cells(struct device_node *np) int of_n_addr_cells(struct device_node *np)
{ {
int* ip; const int* ip;
do { do {
if (np->parent) if (np->parent)
np = np->parent; np = np->parent;
...@@ -211,7 +214,7 @@ EXPORT_SYMBOL(of_n_addr_cells); ...@@ -211,7 +214,7 @@ EXPORT_SYMBOL(of_n_addr_cells);
int of_n_size_cells(struct device_node *np) int of_n_size_cells(struct device_node *np)
{ {
int* ip; const int* ip;
do { do {
if (np->parent) if (np->parent)
np = np->parent; np = np->parent;
...@@ -243,7 +246,7 @@ int of_set_property(struct device_node *dp, const char *name, void *val, int len ...@@ -243,7 +246,7 @@ int of_set_property(struct device_node *dp, const char *name, void *val, int len
while (*prevp) { while (*prevp) {
struct property *prop = *prevp; struct property *prop = *prevp;
if (!strcmp(prop->name, name)) { if (!strcasecmp(prop->name, name)) {
void *old_val = prop->value; void *old_val = prop->value;
int ret; int ret;
...@@ -397,7 +400,7 @@ static unsigned int psycho_irq_build(struct device_node *dp, ...@@ -397,7 +400,7 @@ static unsigned int psycho_irq_build(struct device_node *dp,
static void psycho_irq_trans_init(struct device_node *dp) static void psycho_irq_trans_init(struct device_node *dp)
{ {
struct linux_prom64_registers *regs; const struct linux_prom64_registers *regs;
dp->irq_trans = prom_early_alloc(sizeof(struct of_irq_controller)); dp->irq_trans = prom_early_alloc(sizeof(struct of_irq_controller));
dp->irq_trans->irq_build = psycho_irq_build; dp->irq_trans->irq_build = psycho_irq_build;
...@@ -547,7 +550,7 @@ static unsigned long __sabre_onboard_imap_off[] = { ...@@ -547,7 +550,7 @@ static unsigned long __sabre_onboard_imap_off[] = {
static int sabre_device_needs_wsync(struct device_node *dp) static int sabre_device_needs_wsync(struct device_node *dp)
{ {
struct device_node *parent = dp->parent; struct device_node *parent = dp->parent;
char *parent_model, *parent_compat; const char *parent_model, *parent_compat;
/* This traversal up towards the root is meant to /* This traversal up towards the root is meant to
* handle two cases: * handle two cases:
...@@ -589,7 +592,7 @@ static unsigned int sabre_irq_build(struct device_node *dp, ...@@ -589,7 +592,7 @@ static unsigned int sabre_irq_build(struct device_node *dp,
{ {
struct sabre_irq_data *irq_data = _data; struct sabre_irq_data *irq_data = _data;
unsigned long controller_regs = irq_data->controller_regs; unsigned long controller_regs = irq_data->controller_regs;
struct linux_prom_pci_registers *regs; const struct linux_prom_pci_registers *regs;
unsigned long imap, iclr; unsigned long imap, iclr;
unsigned long imap_off, iclr_off; unsigned long imap_off, iclr_off;
int inofixup = 0; int inofixup = 0;
...@@ -639,9 +642,9 @@ static unsigned int sabre_irq_build(struct device_node *dp, ...@@ -639,9 +642,9 @@ static unsigned int sabre_irq_build(struct device_node *dp,
static void sabre_irq_trans_init(struct device_node *dp) static void sabre_irq_trans_init(struct device_node *dp)
{ {
struct linux_prom64_registers *regs; const struct linux_prom64_registers *regs;
struct sabre_irq_data *irq_data; struct sabre_irq_data *irq_data;
u32 *busrange; const u32 *busrange;
dp->irq_trans = prom_early_alloc(sizeof(struct of_irq_controller)); dp->irq_trans = prom_early_alloc(sizeof(struct of_irq_controller));
dp->irq_trans->irq_build = sabre_irq_build; dp->irq_trans->irq_build = sabre_irq_build;
...@@ -795,7 +798,7 @@ static unsigned int schizo_irq_build(struct device_node *dp, ...@@ -795,7 +798,7 @@ static unsigned int schizo_irq_build(struct device_node *dp,
static void __schizo_irq_trans_init(struct device_node *dp, int is_tomatillo) static void __schizo_irq_trans_init(struct device_node *dp, int is_tomatillo)
{ {
struct linux_prom64_registers *regs; const struct linux_prom64_registers *regs;
struct schizo_irq_data *irq_data; struct schizo_irq_data *irq_data;
dp->irq_trans = prom_early_alloc(sizeof(struct of_irq_controller)); dp->irq_trans = prom_early_alloc(sizeof(struct of_irq_controller));
...@@ -836,7 +839,7 @@ static unsigned int pci_sun4v_irq_build(struct device_node *dp, ...@@ -836,7 +839,7 @@ static unsigned int pci_sun4v_irq_build(struct device_node *dp,
static void pci_sun4v_irq_trans_init(struct device_node *dp) static void pci_sun4v_irq_trans_init(struct device_node *dp)
{ {
struct linux_prom64_registers *regs; const struct linux_prom64_registers *regs;
dp->irq_trans = prom_early_alloc(sizeof(struct of_irq_controller)); dp->irq_trans = prom_early_alloc(sizeof(struct of_irq_controller));
dp->irq_trans->irq_build = pci_sun4v_irq_build; dp->irq_trans->irq_build = pci_sun4v_irq_build;
...@@ -940,7 +943,7 @@ static unsigned int sbus_of_build_irq(struct device_node *dp, ...@@ -940,7 +943,7 @@ static unsigned int sbus_of_build_irq(struct device_node *dp,
void *_data) void *_data)
{ {
unsigned long reg_base = (unsigned long) _data; unsigned long reg_base = (unsigned long) _data;
struct linux_prom_registers *regs; const struct linux_prom_registers *regs;
unsigned long imap, iclr; unsigned long imap, iclr;
int sbus_slot = 0; int sbus_slot = 0;
int sbus_level = 0; int sbus_level = 0;
...@@ -994,7 +997,7 @@ static unsigned int sbus_of_build_irq(struct device_node *dp, ...@@ -994,7 +997,7 @@ static unsigned int sbus_of_build_irq(struct device_node *dp,
static void sbus_irq_trans_init(struct device_node *dp) static void sbus_irq_trans_init(struct device_node *dp)
{ {
struct linux_prom64_registers *regs; const struct linux_prom64_registers *regs;
dp->irq_trans = prom_early_alloc(sizeof(struct of_irq_controller)); dp->irq_trans = prom_early_alloc(sizeof(struct of_irq_controller));
dp->irq_trans->irq_build = sbus_of_build_irq; dp->irq_trans->irq_build = sbus_of_build_irq;
...@@ -1080,7 +1083,7 @@ static unsigned int sun4v_vdev_irq_build(struct device_node *dp, ...@@ -1080,7 +1083,7 @@ static unsigned int sun4v_vdev_irq_build(struct device_node *dp,
static void sun4v_vdev_irq_trans_init(struct device_node *dp) static void sun4v_vdev_irq_trans_init(struct device_node *dp)
{ {
struct linux_prom64_registers *regs; const struct linux_prom64_registers *regs;
dp->irq_trans = prom_early_alloc(sizeof(struct of_irq_controller)); dp->irq_trans = prom_early_alloc(sizeof(struct of_irq_controller));
dp->irq_trans->irq_build = sun4v_vdev_irq_build; dp->irq_trans->irq_build = sun4v_vdev_irq_build;
......
此差异已折叠。
...@@ -45,7 +45,7 @@ ...@@ -45,7 +45,7 @@
extern void calibrate_delay(void); extern void calibrate_delay(void);
/* Please don't make this stuff initdata!!! --DaveM */ /* Please don't make this stuff initdata!!! --DaveM */
static unsigned char boot_cpu_id; unsigned char boot_cpu_id;
cpumask_t cpu_online_map __read_mostly = CPU_MASK_NONE; cpumask_t cpu_online_map __read_mostly = CPU_MASK_NONE;
cpumask_t phys_cpu_present_map __read_mostly = CPU_MASK_NONE; cpumask_t phys_cpu_present_map __read_mostly = CPU_MASK_NONE;
...@@ -81,8 +81,6 @@ void __init smp_store_cpu_info(int id) ...@@ -81,8 +81,6 @@ void __init smp_store_cpu_info(int id)
struct device_node *dp; struct device_node *dp;
int def; int def;
/* multiplier and counter set by
smp_setup_percpu_timer() */
cpu_data(id).udelay_val = loops_per_jiffy; cpu_data(id).udelay_val = loops_per_jiffy;
cpu_find_by_mid(id, &dp); cpu_find_by_mid(id, &dp);
...@@ -125,7 +123,7 @@ void __init smp_store_cpu_info(int id) ...@@ -125,7 +123,7 @@ void __init smp_store_cpu_info(int id)
cpu_data(id).ecache_size, cpu_data(id).ecache_line_size); cpu_data(id).ecache_size, cpu_data(id).ecache_line_size);
} }
static void smp_setup_percpu_timer(void); extern void setup_sparc64_timer(void);
static volatile unsigned long callin_flag = 0; static volatile unsigned long callin_flag = 0;
...@@ -140,7 +138,7 @@ void __init smp_callin(void) ...@@ -140,7 +138,7 @@ void __init smp_callin(void)
__flush_tlb_all(); __flush_tlb_all();
smp_setup_percpu_timer(); setup_sparc64_timer();
if (cheetah_pcache_forced_on) if (cheetah_pcache_forced_on)
cheetah_enable_pcache(); cheetah_enable_pcache();
...@@ -177,8 +175,6 @@ void cpu_panic(void) ...@@ -177,8 +175,6 @@ void cpu_panic(void)
panic("SMP bolixed\n"); panic("SMP bolixed\n");
} }
static unsigned long current_tick_offset __read_mostly;
/* This tick register synchronization scheme is taken entirely from /* This tick register synchronization scheme is taken entirely from
* the ia64 port, see arch/ia64/kernel/smpboot.c for details and credit. * the ia64 port, see arch/ia64/kernel/smpboot.c for details and credit.
* *
...@@ -261,7 +257,7 @@ void smp_synchronize_tick_client(void) ...@@ -261,7 +257,7 @@ void smp_synchronize_tick_client(void)
} else } else
adj = -delta; adj = -delta;
tick_ops->add_tick(adj, current_tick_offset); tick_ops->add_tick(adj);
} }
#if DEBUG_TICK_SYNC #if DEBUG_TICK_SYNC
t[i].rt = rt; t[i].rt = rt;
...@@ -1180,117 +1176,15 @@ void smp_penguin_jailcell(int irq, struct pt_regs *regs) ...@@ -1180,117 +1176,15 @@ void smp_penguin_jailcell(int irq, struct pt_regs *regs)
preempt_enable(); preempt_enable();
} }
#define prof_multiplier(__cpu) cpu_data(__cpu).multiplier
#define prof_counter(__cpu) cpu_data(__cpu).counter
void smp_percpu_timer_interrupt(struct pt_regs *regs)
{
unsigned long compare, tick, pstate;
int cpu = smp_processor_id();
int user = user_mode(regs);
struct pt_regs *old_regs;
/*
* Check for level 14 softint.
*/
{
unsigned long tick_mask = tick_ops->softint_mask;
if (!(get_softint() & tick_mask)) {
extern void handler_irq(int, struct pt_regs *);
handler_irq(14, regs);
return;
}
clear_softint(tick_mask);
}
old_regs = set_irq_regs(regs);
do {
profile_tick(CPU_PROFILING);
if (!--prof_counter(cpu)) {
irq_enter();
if (cpu == boot_cpu_id) {
kstat_this_cpu.irqs[0]++;
timer_tick_interrupt(regs);
}
update_process_times(user);
irq_exit();
prof_counter(cpu) = prof_multiplier(cpu);
}
/* Guarantee that the following sequences execute
* uninterrupted.
*/
__asm__ __volatile__("rdpr %%pstate, %0\n\t"
"wrpr %0, %1, %%pstate"
: "=r" (pstate)
: "i" (PSTATE_IE));
compare = tick_ops->add_compare(current_tick_offset);
tick = tick_ops->get_tick();
/* Restore PSTATE_IE. */
__asm__ __volatile__("wrpr %0, 0x0, %%pstate"
: /* no outputs */
: "r" (pstate));
} while (time_after_eq(tick, compare));
set_irq_regs(old_regs);
}
static void __init smp_setup_percpu_timer(void)
{
int cpu = smp_processor_id();
unsigned long pstate;
prof_counter(cpu) = prof_multiplier(cpu) = 1;
/* Guarantee that the following sequences execute
* uninterrupted.
*/
__asm__ __volatile__("rdpr %%pstate, %0\n\t"
"wrpr %0, %1, %%pstate"
: "=r" (pstate)
: "i" (PSTATE_IE));
tick_ops->init_tick(current_tick_offset);
/* Restore PSTATE_IE. */
__asm__ __volatile__("wrpr %0, 0x0, %%pstate"
: /* no outputs */
: "r" (pstate));
}
void __init smp_tick_init(void) void __init smp_tick_init(void)
{ {
boot_cpu_id = hard_smp_processor_id(); boot_cpu_id = hard_smp_processor_id();
current_tick_offset = timer_tick_offset;
prof_counter(boot_cpu_id) = prof_multiplier(boot_cpu_id) = 1;
} }
/* /proc/profile writes can call this, don't __init it please. */ /* /proc/profile writes can call this, don't __init it please. */
static DEFINE_SPINLOCK(prof_setup_lock);
int setup_profiling_timer(unsigned int multiplier) int setup_profiling_timer(unsigned int multiplier)
{ {
unsigned long flags;
int i;
if ((!multiplier) || (timer_tick_offset / multiplier) < 1000)
return -EINVAL; return -EINVAL;
spin_lock_irqsave(&prof_setup_lock, flags);
for_each_possible_cpu(i)
prof_multiplier(i) = multiplier;
current_tick_offset = (timer_tick_offset / multiplier);
spin_unlock_irqrestore(&prof_setup_lock, flags);
return 0;
} }
static void __init smp_tune_scheduling(void) static void __init smp_tune_scheduling(void)
......
...@@ -212,7 +212,6 @@ EXPORT_SYMBOL(insl); ...@@ -212,7 +212,6 @@ EXPORT_SYMBOL(insl);
#ifdef CONFIG_PCI #ifdef CONFIG_PCI
EXPORT_SYMBOL(ebus_chain); EXPORT_SYMBOL(ebus_chain);
EXPORT_SYMBOL(isa_chain); EXPORT_SYMBOL(isa_chain);
EXPORT_SYMBOL(pci_memspace_mask);
EXPORT_SYMBOL(pci_alloc_consistent); EXPORT_SYMBOL(pci_alloc_consistent);
EXPORT_SYMBOL(pci_free_consistent); EXPORT_SYMBOL(pci_free_consistent);
EXPORT_SYMBOL(pci_map_single); EXPORT_SYMBOL(pci_map_single);
......
此差异已折叠。
...@@ -60,11 +60,7 @@ tl0_irq4: BTRAP(0x44) ...@@ -60,11 +60,7 @@ tl0_irq4: BTRAP(0x44)
tl0_irq5: TRAP_IRQ(handler_irq, 5) tl0_irq5: TRAP_IRQ(handler_irq, 5)
tl0_irq6: BTRAP(0x46) BTRAP(0x47) BTRAP(0x48) BTRAP(0x49) tl0_irq6: BTRAP(0x46) BTRAP(0x47) BTRAP(0x48) BTRAP(0x49)
tl0_irq10: BTRAP(0x4a) BTRAP(0x4b) BTRAP(0x4c) BTRAP(0x4d) tl0_irq10: BTRAP(0x4a) BTRAP(0x4b) BTRAP(0x4c) BTRAP(0x4d)
#ifndef CONFIG_SMP tl0_irq14: TRAP_IRQ(timer_interrupt, 14)
tl0_irq14: TRAP_IRQ(timer_irq, 14)
#else
tl0_irq14: TICK_SMP_IRQ
#endif
tl0_irq15: TRAP_IRQ(handler_irq, 15) tl0_irq15: TRAP_IRQ(handler_irq, 15)
tl0_resv050: BTRAP(0x50) BTRAP(0x51) BTRAP(0x52) BTRAP(0x53) BTRAP(0x54) BTRAP(0x55) tl0_resv050: BTRAP(0x50) BTRAP(0x51) BTRAP(0x52) BTRAP(0x53) BTRAP(0x54) BTRAP(0x55)
tl0_resv056: BTRAP(0x56) BTRAP(0x57) BTRAP(0x58) BTRAP(0x59) BTRAP(0x5a) BTRAP(0x5b) tl0_resv056: BTRAP(0x56) BTRAP(0x57) BTRAP(0x58) BTRAP(0x59) BTRAP(0x5a) BTRAP(0x5b)
......
此差异已折叠。
...@@ -224,7 +224,8 @@ static char *serial(char *buffer, int sz) ...@@ -224,7 +224,8 @@ static char *serial(char *buffer, int sz)
*buffer = 0; *buffer = 0;
if (dp) { if (dp) {
char *val = of_get_property(dp, "system-board-serial#", &len); const char *val =
of_get_property(dp, "system-board-serial#", &len);
if (val && len > 0) { if (val && len > 0) {
if (len > sz) if (len > sz)
......
...@@ -2,6 +2,6 @@ ...@@ -2,6 +2,6 @@
# Makefile for Xtensa-specific library files. # Makefile for Xtensa-specific library files.
# #
lib-y += memcopy.o memset.o checksum.o strcasecmp.o \ lib-y += memcopy.o memset.o checksum.o \
usercopy.o strncpy_user.o strnlen_user.o usercopy.o strncpy_user.o strnlen_user.o
lib-$(CONFIG_PCI) += pci-auto.o lib-$(CONFIG_PCI) += pci-auto.o
/*
* linux/arch/xtensa/lib/strcasecmp.c
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file "COPYING" in the main directory of
* this archive for more details.
*
* Copyright (C) 2002 Tensilica Inc.
*/
#include <linux/string.h>
/* We handle nothing here except the C locale. Since this is used in
only one place, on strings known to contain only 7 bit ASCII, this
is ok. */
int strcasecmp(const char *a, const char *b)
{
int ca, cb;
do {
ca = *a++ & 0xff;
cb = *b++ & 0xff;
if (ca >= 'A' && ca <= 'Z')
ca += 'a' - 'A';
if (cb >= 'A' && cb <= 'Z')
cb += 'a' - 'A';
} while (ca == cb && ca != '\0');
return ca - cb;
}
...@@ -39,7 +39,7 @@ MODULE_VERSION("2.0"); ...@@ -39,7 +39,7 @@ MODULE_VERSION("2.0");
static LIST_HEAD(device_list); static LIST_HEAD(device_list);
struct uflash_dev { struct uflash_dev {
char *name; /* device name */ const char *name; /* device name */
struct map_info map; /* mtd map info */ struct map_info map; /* mtd map info */
struct mtd_info *mtd; /* mtd info */ struct mtd_info *mtd; /* mtd info */
}; };
...@@ -80,7 +80,7 @@ int uflash_devinit(struct linux_ebus_device *edev, struct device_node *dp) ...@@ -80,7 +80,7 @@ int uflash_devinit(struct linux_ebus_device *edev, struct device_node *dp)
up->name = of_get_property(dp, "model", NULL); up->name = of_get_property(dp, "model", NULL);
if (up->name && 0 < strlen(up->name)) if (up->name && 0 < strlen(up->name))
up->map.name = up->name; up->map.name = (char *)up->name;
up->map.phys = res->start; up->map.phys = res->start;
......
此差异已折叠。
...@@ -1025,7 +1025,7 @@ struct gem { ...@@ -1025,7 +1025,7 @@ struct gem {
struct pci_dev *pdev; struct pci_dev *pdev;
struct net_device *dev; struct net_device *dev;
#ifdef CONFIG_PPC_PMAC #if defined(CONFIG_PPC_PMAC) || defined(CONFIG_SPARC)
struct device_node *of_node; struct device_node *of_node;
#endif #endif
}; };
......
此差异已折叠。
此差异已折叠。
...@@ -63,7 +63,7 @@ MODULE_PARM_DESC (debug, "de2104x bitmapped message enable number"); ...@@ -63,7 +63,7 @@ MODULE_PARM_DESC (debug, "de2104x bitmapped message enable number");
/* Set the copy breakpoint for the copy-only-tiny-buffer Rx structure. */ /* Set the copy breakpoint for the copy-only-tiny-buffer Rx structure. */
#if defined(__alpha__) || defined(__arm__) || defined(__hppa__) \ #if defined(__alpha__) || defined(__arm__) || defined(__hppa__) \
|| defined(__sparc__) || defined(__ia64__) \ || defined(CONFIG_SPARC) || defined(__ia64__) \
|| defined(__sh__) || defined(__mips__) || defined(__sh__) || defined(__mips__)
static int rx_copybreak = 1518; static int rx_copybreak = 1518;
#else #else
......
此差异已折叠。
此差异已折叠。
...@@ -902,7 +902,7 @@ static void init_registers(struct net_device *dev) ...@@ -902,7 +902,7 @@ static void init_registers(struct net_device *dev)
} }
#elif defined(__powerpc__) || defined(__i386__) || defined(__alpha__) || defined(__ia64__) || defined(__x86_64__) #elif defined(__powerpc__) || defined(__i386__) || defined(__alpha__) || defined(__ia64__) || defined(__x86_64__)
i |= 0xE000; i |= 0xE000;
#elif defined(__sparc__) || defined (CONFIG_PARISC) #elif defined(CONFIG_SPARC) || defined (CONFIG_PARISC)
i |= 0x4800; i |= 0x4800;
#else #else
#warning Processor architecture undefined #warning Processor architecture undefined
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册