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.
  ...
This commit is contained in:
Linus Torvalds 2007-04-27 09:29:04 -07:00
commit 0278ef8b48
94 changed files with 5653 additions and 8106 deletions

View File

@ -36,7 +36,6 @@ lib-y = __divqu.o __remqu.o __divlu.o __remlu.o \
$(ev6-y)csum_ipv6_magic.o \
$(ev6-y)clear_page.o \
$(ev6-y)copy_page.o \
strcasecmp.o \
fpreg.o \
callback_srm.o srm_puts.o srm_printk.o

View File

@ -1,26 +0,0 @@
/*
* 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;
}

View File

@ -84,8 +84,6 @@ EXPORT_SYMBOL(strncpy);
EXPORT_SYMBOL(strcat);
EXPORT_SYMBOL(strlen);
EXPORT_SYMBOL(strcmp);
EXPORT_SYMBOL(strcasecmp);
EXPORT_SYMBOL(strncasecmp);
EXPORT_SYMBOL(csum_partial);
EXPORT_SYMBOL(csum_partial_copy_generic);

View File

@ -7,13 +7,12 @@ EXTRA_CFLAGS += -mno-minimal-toc
endif
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
endif
obj-$(CONFIG_PPC64) += checksum_64.o copypage_64.o copyuser_64.o \
memcpy_64.o usercopy_64.o mem_64.o string.o \
strcase.o
memcpy_64.o usercopy_64.o mem_64.o string.o
obj-$(CONFIG_QUICC_ENGINE) += rheap.o
obj-$(CONFIG_XMON) += sstep.o
obj-$(CONFIG_KPROBES) += sstep.o

View File

@ -1,25 +0,0 @@
#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;
}

View File

@ -93,8 +93,6 @@ EXPORT_SYMBOL(strncpy);
EXPORT_SYMBOL(strcat);
EXPORT_SYMBOL(strlen);
EXPORT_SYMBOL(strcmp);
EXPORT_SYMBOL(strcasecmp);
EXPORT_SYMBOL(strncasecmp);
EXPORT_SYMBOL(__div64_32);
EXPORT_SYMBOL(csum_partial);

View File

@ -2,7 +2,7 @@
# 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_CPM2) += rheap.o

View File

@ -1,24 +0,0 @@
#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;
}

View File

@ -3,7 +3,7 @@
#
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
memcpy-y := memcpy.o

View File

@ -1,26 +0,0 @@
/*
* 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;
}

View File

@ -25,7 +25,7 @@
struct linux_ebus *ebus_chain = NULL;
/* 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
@ -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;
@ -86,8 +86,8 @@ int __init ebus_blacklist_irq(char *name)
void __init fill_ebus_child(struct device_node *dp,
struct linux_ebus_child *dev)
{
int *regs;
int *irqs;
const int *regs;
const int *irqs;
int i, len;
dev->prom_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)
{
struct linux_prom_registers *regs;
const struct linux_prom_registers *regs;
struct linux_ebus_child *child;
int *irqs;
const int *irqs;
int i, n, len;
unsigned long baseaddr;
@ -269,7 +269,7 @@ void __init fill_ebus_device(struct device_node *dp, struct linux_ebus_device *d
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_ebus_device *dev;
struct linux_ebus *ebus;

View File

@ -210,7 +210,7 @@ struct of_bus {
int *addrc, int *sizec);
int (*map)(u32 *addr, const u32 *range,
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,
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;
}
@ -334,7 +334,7 @@ static int of_bus_pci_map(u32 *addr, const u32 *range,
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;
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)
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;
}
@ -432,7 +432,7 @@ static int __init build_one_resource(struct device_node *parent,
u32 *addr,
int na, int ns, int pna)
{
u32 *ranges;
const u32 *ranges;
unsigned int rlen;
int rone;
@ -470,7 +470,7 @@ static void __init build_device_resources(struct of_device *op,
struct of_bus *bus;
int na, ns;
int index, num_reg;
void *preg;
const void *preg;
if (!parent)
return;
@ -492,7 +492,7 @@ static void __init build_device_resources(struct of_device *op,
for (index = 0; index < num_reg; index++) {
struct resource *r = &op->resource[index];
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 *pp = p_op->node;
struct of_bus *pbus, *dbus;
@ -559,7 +559,7 @@ static struct of_device * __init scan_one_device(struct device_node *dp,
struct device *parent)
{
struct of_device *op = kzalloc(sizeof(*op), GFP_KERNEL);
struct linux_prom_irqs *intr;
const struct linux_prom_irqs *intr;
int len, i;
if (!op)
@ -579,7 +579,8 @@ static struct of_device * __init scan_one_device(struct device_node *dp,
for (i = 0; i < op->num_irqs; i++)
op->irqs[i] = intr[i].pri;
} else {
unsigned int *irq = of_get_property(dp, "interrupts", &len);
const unsigned int *irq =
of_get_property(dp, "interrupts", &len);
if (irq) {
op->num_irqs = len / sizeof(unsigned int);
@ -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,
};
struct device_node *io_unit, *sbi = dp->parent;
struct linux_prom_registers *regs;
const struct linux_prom_registers *regs;
int board, slot;
while (sbi) {

View File

@ -37,8 +37,6 @@
#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
* 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)
* pcic_pin_to_irq() is exported to ebus.c.
*/
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;
unsigned int irq;

View File

@ -32,12 +32,13 @@ static struct device_node *allnodes;
*/
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;
int cplen, l;
cp = (char *) of_get_property(device, "compatible", &cplen);
cp = of_get_property(device, "compatible", &cplen);
if (cp == NULL)
return 0;
while (cplen > 0) {
@ -150,13 +151,14 @@ struct device_node *of_find_compatible_node(struct device_node *from,
}
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)
{
struct property *pp;
for (pp = np->properties; pp != 0; pp = pp->next) {
if (strcmp(pp->name, name) == 0) {
if (strcasecmp(pp->name, name) == 0) {
if (lenp != 0)
*lenp = pp->length;
break;
@ -170,7 +172,8 @@ EXPORT_SYMBOL(of_find_property);
* Find a property with a given name for a given node
* 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);
return pp ? pp->value : NULL;
@ -192,7 +195,7 @@ EXPORT_SYMBOL(of_getintprop_default);
int of_n_addr_cells(struct device_node *np)
{
int* ip;
const int* ip;
do {
if (np->parent)
np = np->parent;
@ -207,7 +210,7 @@ EXPORT_SYMBOL(of_n_addr_cells);
int of_n_size_cells(struct device_node *np)
{
int* ip;
const int* ip;
do {
if (np->parent)
np = np->parent;
@ -239,7 +242,7 @@ int of_set_property(struct device_node *dp, const char *name, void *val, int len
while (*prevp) {
struct property *prop = *prevp;
if (!strcmp(prop->name, name)) {
if (!strcasecmp(prop->name, name)) {
void *old_val = prop->value;
int ret;

View File

@ -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)
{
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)
return -ENODEV;

View File

@ -19,6 +19,14 @@ config SPARC64
SPARC64 ports; its web page is available at
<http://www.ultralinux.org/>.
config GENERIC_TIME
bool
default y
config GENERIC_CLOCKEVENTS
bool
default y
config 64BIT
def_bool y
@ -34,10 +42,6 @@ config LOCKDEP_SUPPORT
bool
default y
config TIME_INTERPOLATION
bool
default y
config ARCH_MAY_HAVE_PC_FDC
bool
default y
@ -113,6 +117,8 @@ config GENERIC_HARDIRQS
menu "General machine setup"
source "kernel/time/Kconfig"
config SMP
bool "Symmetric multi-processing support"
---help---
@ -214,6 +220,7 @@ config ARCH_SPARSEMEM_ENABLE
config ARCH_SPARSEMEM_DEFAULT
def_bool y
select SPARSEMEM_STATIC
config LARGE_ALLOCS
def_bool y

View File

@ -32,7 +32,7 @@ static void central_probe_failure(int line)
static void central_ranges_init(struct linux_central *central)
{
struct device_node *dp = central->prom_node;
void *pval;
const void *pval;
int len;
central->num_central_ranges = 0;
@ -47,7 +47,7 @@ static void central_ranges_init(struct linux_central *central)
static void fhc_ranges_init(struct linux_fhc *fhc)
{
struct device_node *dp = fhc->prom_node;
void *pval;
const void *pval;
int len;
fhc->num_fhc_ranges = 0;
@ -119,7 +119,7 @@ static unsigned long prom_reg_to_paddr(struct linux_prom_registers *r)
static void probe_other_fhcs(void)
{
struct device_node *dp;
struct linux_prom64_registers *fpregs;
const struct linux_prom64_registers *fpregs;
for_each_node_by_name(dp, "fhc") {
struct linux_fhc *fhc;
@ -190,7 +190,8 @@ static void probe_clock_board(struct linux_central *central,
struct device_node *fp)
{
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;
dp = fp->child;
@ -299,7 +300,8 @@ static void init_all_fhc_hw(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 device_node *dp, *fp;
int err;

View File

@ -343,8 +343,8 @@ static int init_one_mctrl(struct device_node *dp)
{
struct mctrl_info *mp = kzalloc(sizeof(*mp), GFP_KERNEL);
int portid = of_getintprop_default(dp, "portid", -1);
struct linux_prom64_registers *regs;
void *pval;
const struct linux_prom64_registers *regs;
const void *pval;
int len;
if (!mp)

View File

@ -285,7 +285,7 @@ static void __init fill_ebus_child(struct device_node *dp,
int non_standard_regs)
{
struct of_device *op;
int *regs;
const int *regs;
int i, len;
dev->prom_node = dp;
@ -438,11 +438,9 @@ static struct pci_dev *find_next_ebus(struct pci_dev *start, int *is_rio_p)
void __init ebus_init(void)
{
struct pci_pbm_info *pbm;
struct linux_ebus_device *dev;
struct linux_ebus *ebus;
struct pci_dev *pdev;
struct pcidev_cookie *cookie;
struct device_node *dp;
int is_rio;
int num_ebus = 0;
@ -453,8 +451,7 @@ void __init ebus_init(void)
return;
}
cookie = pdev->sysdata;
dp = cookie->prom_node;
dp = pci_device_to_OF_node(pdev);
ebus_chain = ebus = ebus_alloc(sizeof(struct linux_ebus));
ebus->next = NULL;
@ -480,8 +477,7 @@ void __init ebus_init(void)
break;
}
ebus->is_rio = is_rio;
cookie = pdev->sysdata;
dp = cookie->prom_node;
dp = pci_device_to_OF_node(pdev);
continue;
}
printk("ebus%d:", num_ebus);
@ -489,7 +485,6 @@ void __init ebus_init(void)
ebus->index = num_ebus;
ebus->prom_node = dp;
ebus->self = pdev;
ebus->parent = pbm = cookie->pbm;
ebus->ofdev.node = dp;
ebus->ofdev.dev.parent = &pdev->dev;
@ -531,8 +526,7 @@ void __init ebus_init(void)
if (!pdev)
break;
cookie = pdev->sysdata;
dp = cookie->prom_node;
dp = pci_device_to_OF_node(pdev);
ebus->next = ebus_alloc(sizeof(struct linux_ebus));
ebus = ebus->next;

View File

@ -589,32 +589,6 @@ void ack_bad_irq(unsigned int 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)
{
struct ino_bucket *bucket;
@ -653,7 +627,7 @@ static u64 prom_limit0, prom_limit1;
static void map_prom_timers(void)
{
struct device_node *dp;
unsigned int *addr;
const unsigned int *addr;
/* PROM timer node hangs out in the top level of device siblings... */
dp = of_find_node_by_path("/");

View File

@ -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)
{
struct linux_prom_registers *pregs;
unsigned long base, len;
int prop_len;
struct of_device *op = of_find_device_by_node(isa_dev->prom_node);
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,
&isa_dev->resource);
memcpy(&isa_dev->resource, &op->resource[0], sizeof(struct resource));
}
static void __init isa_dev_get_irq(struct sparc_isa_device *isa_dev)
@ -158,19 +140,10 @@ void __init isa_init(void)
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 device_node *dp;
pdev_cookie = pdev->sysdata;
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;
dp = pci_device_to_OF_node(pdev);
isa_br = kzalloc(sizeof(*isa_br), GFP_KERNEL);
if (!isa_br) {
@ -195,10 +168,9 @@ void __init isa_init(void)
isa_br->next = isa_chain;
isa_chain = isa_br;
isa_br->parent = pbm;
isa_br->self = pdev;
isa_br->index = index++;
isa_br->prom_node = pdev_cookie->prom_node;
isa_br->prom_node = dp;
printk("isa%d:", isa_br->index);

View File

@ -245,7 +245,7 @@ struct of_bus {
int *addrc, int *sizec);
int (*map)(u32 *addr, const u32 *range,
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,
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;
}
@ -317,6 +317,11 @@ static unsigned int of_bus_default_get_flags(u32 *addr)
static int of_bus_pci_match(struct device_node *np)
{
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
* PCI bridge lacks a ranges property. We
* want to pass it through up to the next
@ -332,6 +337,21 @@ static int of_bus_pci_match(struct device_node *np)
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,
int *addrc, int *sizec)
{
@ -369,7 +389,7 @@ static int of_bus_pci_map(u32 *addr, const u32 *range,
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;
u32 w = addr[0];
@ -436,6 +456,15 @@ static struct of_bus of_busses[] = {
.map = of_bus_pci_map,
.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 */
{
.name = "sbus",
@ -482,7 +511,7 @@ static int __init build_one_resource(struct device_node *parent,
u32 *addr,
int na, int ns, int pna)
{
u32 *ranges;
const u32 *ranges;
unsigned int rlen;
int rone;
@ -513,7 +542,7 @@ static int __init build_one_resource(struct device_node *parent,
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 a ranges property exists.
@ -548,7 +577,7 @@ static void __init build_device_resources(struct of_device *op,
struct of_bus *bus;
int na, ns;
int index, num_reg;
void *preg;
const void *preg;
if (!parent)
return;
@ -578,7 +607,7 @@ static void __init build_device_resources(struct of_device *op,
for (index = 0; index < num_reg; index++) {
struct resource *r = &op->resource[index];
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 *pp = p_op->node;
struct of_bus *pbus, *dbus;
@ -643,14 +672,14 @@ static void __init build_device_resources(struct of_device *op,
static struct device_node * __init
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)
{
struct device_node *cp;
unsigned int irq = *irq_p;
struct of_bus *bus;
phandle handle;
u32 *reg;
const u32 *reg;
int na, num_reg, i;
bus = of_match_bus(pp);
@ -705,7 +734,7 @@ static unsigned int __init pci_irq_swizzle(struct device_node *dp,
struct device_node *pp,
unsigned int irq)
{
struct linux_prom_pci_registers *regs;
const struct linux_prom_pci_registers *regs;
unsigned int bus, devfn, slot, ret;
if (irq < 1 || irq > 4)
@ -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
* (dev - 1) for bus A, or (dev - 2) for bus B
* 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) {
/* PBM-A */
@ -794,7 +817,7 @@ static unsigned int __init build_one_device_irq(struct of_device *op,
pp = dp->parent;
ip = NULL;
while (pp) {
void *imap, *imsk;
const void *imap, *imsk;
int 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,
struct device *parent)
{
struct of_device *op = kzalloc(sizeof(*op), GFP_KERNEL);
unsigned int *irq;
const unsigned int *irq;
int len, i;
if (!op)

View File

@ -1,9 +1,11 @@
/* $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) 1998, 1999 Eddie C. Dost (ecd@skynet.be)
* 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>
@ -24,6 +26,9 @@
#include <asm/ebus.h>
#include <asm/isa.h>
#include <asm/prom.h>
#include <asm/apb.h>
#include "pci_impl.h"
unsigned long pci_memspace_mask = 0xffffffffUL;
@ -277,10 +282,10 @@ int __init pcic_present(void)
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);
extern struct pci_iommu_ops pci_sun4u_iommu_ops,
extern const struct pci_iommu_ops pci_sun4u_iommu_ops,
pci_sun4v_iommu_ops;
/* Find each controller in the system, attach and initialize
@ -300,6 +305,467 @@ static void __init pci_controller_probe(void)
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)
{
struct pci_controller_info *p;
@ -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;
}
@ -380,7 +871,7 @@ void pcibios_resource_to_bus(struct pci_dev *pdev, struct pci_bus_region *region
else
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->end = res->end - zero_res.start;
@ -401,7 +892,7 @@ void pcibios_bus_to_resource(struct pci_dev *pdev, struct resource *res,
else
root = &pbm->mem_space;
pbm->parent->resource_adjust(pdev, res, root);
pci_resource_adjust(res, root);
}
EXPORT_SYMBOL(pcibios_bus_to_resource);
@ -422,55 +913,17 @@ char * __devinit pcibios_setup(char *str)
static int __pci_mmap_make_offset_bus(struct pci_dev *pdev, struct vm_area_struct *vma,
enum pci_mmap_state mmap_state)
{
struct pcidev_cookie *pcp = pdev->sysdata;
struct pci_pbm_info *pbm;
struct pci_pbm_info *pbm = pdev->dev.archdata.host_controller;
struct pci_controller_info *p;
unsigned long space_size, user_offset, user_size;
if (!pcp)
return -ENXIO;
pbm = pcp->pbm;
if (!pbm)
return -ENXIO;
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;
}
if (mmap_state == pci_mmap_io) {
space_size = (pbm->io_space.end -
pbm->io_space.start) + 1;
} else {
if (mmap_state == pci_mmap_io) {
space_size = (pbm->io_space.end -
pbm->io_space.start) + 1;
} else {
space_size = (pbm->mem_space.end -
pbm->mem_space.start) + 1;
}
space_size = (pbm->mem_space.end -
pbm->mem_space.start) + 1;
}
/* Make sure the request is in range. */
@ -481,31 +934,12 @@ static int __pci_mmap_make_offset_bus(struct pci_dev *pdev, struct vm_area_struc
(user_offset + user_size) > space_size)
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;
if (mmap_state == pci_mmap_io) {
vma->vm_pgoff = (pbm->io_space.start +
user_offset) >> PAGE_SHIFT;
} else {
if (mmap_state == pci_mmap_io) {
vma->vm_pgoff = (pbm->io_space.start +
user_offset) >> PAGE_SHIFT;
} else {
vma->vm_pgoff = (pbm->mem_space.start +
user_offset) >> PAGE_SHIFT;
}
vma->vm_pgoff = (pbm->mem_space.start +
user_offset) >> PAGE_SHIFT;
}
return 0;
@ -639,9 +1073,8 @@ int pci_domain_nr(struct pci_bus *pbus)
struct pci_controller_info *p = pbm->parent;
ret = p->index;
if (p->pbms_same_domain == 0)
ret = ((ret << 1) +
((pbm == &pbm->parent->pbm_B) ? 1 : 0));
ret = ((ret << 1) +
((pbm == &pbm->parent->pbm_B) ? 1 : 0));
}
return ret;
@ -651,8 +1084,7 @@ EXPORT_SYMBOL(pci_domain_nr);
#ifdef CONFIG_PCI_MSI
int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc)
{
struct pcidev_cookie *pcp = pdev->sysdata;
struct pci_pbm_info *pbm = pcp->pbm;
struct pci_pbm_info *pbm = pdev->dev.archdata.host_controller;
struct pci_controller_info *p = pbm->parent;
int virt_irq, err;
@ -670,8 +1102,7 @@ void arch_teardown_msi_irq(unsigned int virt_irq)
{
struct msi_desc *entry = get_irq_msi(virt_irq);
struct pci_dev *pdev = entry->dev;
struct pcidev_cookie *pcp = pdev->sysdata;
struct pci_pbm_info *pbm = pcp->pbm;
struct pci_pbm_info *pbm = pdev->dev.archdata.host_controller;
struct pci_controller_info *p = pbm->parent;
if (!pbm->msi_num || !p->setup_msi_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 pcidev_cookie *pc = pdev->sysdata;
return pc->op->node;
return pdev->dev.archdata.prom_node;
}
EXPORT_SYMBOL(pci_device_to_OF_node);

View File

@ -1,7 +1,6 @@
/* $Id: pci_common.c,v 1.29 2002/02/01 00:56:03 davem Exp $
* pci_common.c: PCI controller common support.
/* pci_common.c: PCI controller common support.
*
* Copyright (C) 1999 David S. Miller (davem@redhat.com)
* Copyright (C) 1999, 2007 David S. Miller (davem@davemloft.net)
*/
#include <linux/string.h>
@ -16,715 +15,8 @@
#include "pci_impl.h"
/* Fix self device of BUS and hook it into BUS->self.
* The pci_scan_bus does not do this for the host bridge.
*/
void __init pci_fixup_host_bridge_self(struct pci_bus *pbus)
{
struct pci_dev *pdev;
list_for_each_entry(pdev, &pbus->devices, bus_list) {
if (pdev->class >> 8 == PCI_CLASS_BRIDGE_HOST) {
pbus->self = pdev;
return;
}
}
prom_printf("PCI: Critical error, cannot find host bridge PDEV.\n");
prom_halt();
}
/* Find the OBP PROM device tree node for a PCI device. */
static struct device_node * __init
find_device_prom_node(struct pci_pbm_info *pbm, struct pci_dev *pdev,
struct device_node *bus_node,
struct linux_prom_pci_registers **pregs,
int *nregs)
{
struct device_node *dp;
*nregs = 0;
/*
* Return the PBM's PROM node in case we are it's PCI device,
* as the PBM's reg property is different to standard PCI reg
* properties. We would delete this device entry otherwise,
* which confuses XFree86's device probing...
*/
if ((pdev->bus->number == pbm->pci_bus->number) && (pdev->devfn == 0) &&
(pdev->vendor == PCI_VENDOR_ID_SUN) &&
(pdev->device == PCI_DEVICE_ID_SUN_PBM ||
pdev->device == PCI_DEVICE_ID_SUN_SCHIZO ||
pdev->device == PCI_DEVICE_ID_SUN_TOMATILLO ||
pdev->device == PCI_DEVICE_ID_SUN_SABRE ||
pdev->device == PCI_DEVICE_ID_SUN_HUMMINGBIRD))
return bus_node;
dp = bus_node->child;
while (dp) {
struct linux_prom_pci_registers *regs;
struct property *prop;
int len;
prop = of_find_property(dp, "reg", &len);
if (!prop)
goto do_next_sibling;
regs = prop->value;
if (((regs[0].phys_hi >> 8) & 0xff) == pdev->devfn) {
*pregs = regs;
*nregs = len / sizeof(struct linux_prom_pci_registers);
return dp;
}
do_next_sibling:
dp = dp->sibling;
}
return NULL;
}
/* Older versions of OBP on PCI systems encode 64-bit MEM
* space assignments incorrectly, this fixes them up. We also
* take the opportunity here to hide other kinds of bogus
* assignments.
*/
static void __init fixup_obp_assignments(struct pci_dev *pdev,
struct pcidev_cookie *pcp)
{
int i;
if (pdev->vendor == PCI_VENDOR_ID_AL &&
(pdev->device == PCI_DEVICE_ID_AL_M7101 ||
pdev->device == PCI_DEVICE_ID_AL_M1533)) {
int i;
/* Zap all of the normal resources, they are
* meaningless and generate bogus resource collision
* messages. This is OpenBoot's ill-fated attempt to
* represent the implicit resources that these devices
* have.
*/
pcp->num_prom_assignments = 0;
for (i = 0; i < 6; i++) {
pdev->resource[i].start =
pdev->resource[i].end =
pdev->resource[i].flags = 0;
}
pdev->resource[PCI_ROM_RESOURCE].start =
pdev->resource[PCI_ROM_RESOURCE].end =
pdev->resource[PCI_ROM_RESOURCE].flags = 0;
return;
}
for (i = 0; i < pcp->num_prom_assignments; i++) {
struct linux_prom_pci_registers *ap;
int space;
ap = &pcp->prom_assignments[i];
space = ap->phys_hi >> 24;
if ((space & 0x3) == 2 &&
(space & 0x4) != 0) {
ap->phys_hi &= ~(0x7 << 24);
ap->phys_hi |= 0x3 << 24;
}
}
}
static ssize_t
show_pciobppath_attr(struct device * dev, struct device_attribute * attr, char * buf)
{
struct pci_dev *pdev;
struct pcidev_cookie *sysdata;
pdev = to_pci_dev(dev);
sysdata = pdev->sysdata;
return snprintf (buf, PAGE_SIZE, "%s\n", sysdata->prom_node->full_name);
}
static DEVICE_ATTR(obppath, S_IRUSR | S_IRGRP | S_IROTH, show_pciobppath_attr, NULL);
/* Fill in the PCI device cookie sysdata for the given
* PCI device. This cookie is the means by which one
* can get to OBP and PCI controller specific information
* for a PCI device.
*/
static void __init pdev_cookie_fillin(struct pci_pbm_info *pbm,
struct pci_dev *pdev,
struct device_node *bus_node)
{
struct linux_prom_pci_registers *pregs = NULL;
struct pcidev_cookie *pcp;
struct device_node *dp;
struct property *prop;
int nregs, len, err;
dp = find_device_prom_node(pbm, pdev, bus_node,
&pregs, &nregs);
if (!dp) {
/* If it is not in the OBP device tree then
* there must be a damn good reason for it.
*
* So what we do is delete the device from the
* PCI device tree completely. This scenario
* is seen, for example, on CP1500 for the
* second EBUS/HappyMeal pair if the external
* connector for it is not present.
*/
pci_remove_bus_device(pdev);
return;
}
pcp = kzalloc(sizeof(*pcp), GFP_ATOMIC);
if (pcp == NULL) {
prom_printf("PCI_COOKIE: Fatal malloc error, aborting...\n");
prom_halt();
}
pcp->pbm = pbm;
pcp->prom_node = dp;
pcp->op = of_find_device_by_node(dp);
memcpy(pcp->prom_regs, pregs,
nregs * sizeof(struct linux_prom_pci_registers));
pcp->num_prom_regs = nregs;
/* We can't have the pcidev_cookie assignments be just
* direct pointers into the property value, since they
* are potentially modified by the probing process.
*/
prop = of_find_property(dp, "assigned-addresses", &len);
if (!prop) {
pcp->num_prom_assignments = 0;
} else {
memcpy(pcp->prom_assignments, prop->value, len);
pcp->num_prom_assignments =
(len / sizeof(pcp->prom_assignments[0]));
}
if (strcmp(dp->name, "ebus") == 0) {
struct linux_prom_ebus_ranges *erng;
int iter;
/* EBUS is special... */
prop = of_find_property(dp, "ranges", &len);
if (!prop) {
prom_printf("EBUS: Fatal error, no range property\n");
prom_halt();
}
erng = prop->value;
len = (len / sizeof(erng[0]));
for (iter = 0; iter < len; iter++) {
struct linux_prom_ebus_ranges *ep = &erng[iter];
struct linux_prom_pci_registers *ap;
ap = &pcp->prom_assignments[iter];
ap->phys_hi = ep->parent_phys_hi;
ap->phys_mid = ep->parent_phys_mid;
ap->phys_lo = ep->parent_phys_lo;
ap->size_hi = 0;
ap->size_lo = ep->size;
}
pcp->num_prom_assignments = len;
}
fixup_obp_assignments(pdev, pcp);
pdev->sysdata = pcp;
/* 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(&pdev->dev.kobj, &dev_attr_obppath.attr);
}
void __init pci_fill_in_pbm_cookies(struct pci_bus *pbus,
struct pci_pbm_info *pbm,
struct device_node *dp)
{
struct pci_dev *pdev, *pdev_next;
struct pci_bus *this_pbus, *pbus_next;
/* This must be _safe because the cookie fillin
routine can delete devices from the tree. */
list_for_each_entry_safe(pdev, pdev_next, &pbus->devices, bus_list)
pdev_cookie_fillin(pbm, pdev, dp);
list_for_each_entry_safe(this_pbus, pbus_next, &pbus->children, node) {
struct pcidev_cookie *pcp = this_pbus->self->sysdata;
pci_fill_in_pbm_cookies(this_pbus, pbm, pcp->prom_node);
}
}
static void __init bad_assignment(struct pci_dev *pdev,
struct linux_prom_pci_registers *ap,
struct resource *res,
int do_prom_halt)
{
prom_printf("PCI: Bogus PROM assignment. BUS[%02x] DEVFN[%x]\n",
pdev->bus->number, pdev->devfn);
if (ap)
prom_printf("PCI: phys[%08x:%08x:%08x] size[%08x:%08x]\n",
ap->phys_hi, ap->phys_mid, ap->phys_lo,
ap->size_hi, ap->size_lo);
if (res)
prom_printf("PCI: RES[%016lx-->%016lx:(%lx)]\n",
res->start, res->end, res->flags);
if (do_prom_halt)
prom_halt();
}
static struct resource *
__init get_root_resource(struct linux_prom_pci_registers *ap,
struct pci_pbm_info *pbm)
{
int space = (ap->phys_hi >> 24) & 3;
switch (space) {
case 0:
/* Configuration space, silently ignore it. */
return NULL;
case 1:
/* 16-bit IO space */
return &pbm->io_space;
case 2:
/* 32-bit MEM space */
return &pbm->mem_space;
case 3:
/* 64-bit MEM space, these are allocated out of
* the 32-bit mem_space range for the PBM, ie.
* we just zero out the upper 32-bits.
*/
return &pbm->mem_space;
default:
printk("PCI: What is resource space %x?\n", space);
return NULL;
};
}
static struct resource *
__init get_device_resource(struct linux_prom_pci_registers *ap,
struct pci_dev *pdev)
{
struct resource *res;
int breg = (ap->phys_hi & 0xff);
switch (breg) {
case PCI_ROM_ADDRESS:
/* Unfortunately I have seen several cases where
* buggy FCODE uses a space value of '1' (I/O space)
* in the register property for the ROM address
* so disable this sanity check for now.
*/
#if 0
{
int space = (ap->phys_hi >> 24) & 3;
/* It had better be MEM space. */
if (space != 2)
bad_assignment(pdev, ap, NULL, 0);
}
#endif
res = &pdev->resource[PCI_ROM_RESOURCE];
break;
case PCI_BASE_ADDRESS_0:
case PCI_BASE_ADDRESS_1:
case PCI_BASE_ADDRESS_2:
case PCI_BASE_ADDRESS_3:
case PCI_BASE_ADDRESS_4:
case PCI_BASE_ADDRESS_5:
res = &pdev->resource[(breg - PCI_BASE_ADDRESS_0) / 4];
break;
default:
bad_assignment(pdev, ap, NULL, 0);
res = NULL;
break;
};
return res;
}
static void __init pdev_record_assignments(struct pci_pbm_info *pbm,
struct pci_dev *pdev)
{
struct pcidev_cookie *pcp = pdev->sysdata;
int i;
for (i = 0; i < pcp->num_prom_assignments; i++) {
struct linux_prom_pci_registers *ap;
struct resource *root, *res;
/* The format of this property is specified in
* the PCI Bus Binding to IEEE1275-1994.
*/
ap = &pcp->prom_assignments[i];
root = get_root_resource(ap, pbm);
res = get_device_resource(ap, pdev);
if (root == NULL || res == NULL ||
res->flags == 0)
continue;
/* Ok we know which resource this PROM assignment is
* for, sanity check it.
*/
if ((res->start & 0xffffffffUL) != ap->phys_lo)
bad_assignment(pdev, ap, res, 1);
/* If it is a 64-bit MEM space assignment, verify that
* the resource is too and that the upper 32-bits match.
*/
if (((ap->phys_hi >> 24) & 3) == 3) {
if (((res->flags & IORESOURCE_MEM) == 0) ||
((res->flags & PCI_BASE_ADDRESS_MEM_TYPE_MASK)
!= PCI_BASE_ADDRESS_MEM_TYPE_64))
bad_assignment(pdev, ap, res, 1);
if ((res->start >> 32) != ap->phys_mid)
bad_assignment(pdev, ap, res, 1);
/* PBM cannot generate cpu initiated PIOs
* to the full 64-bit space. Therefore the
* upper 32-bits better be zero. If it is
* not, just skip it and we will assign it
* properly ourselves.
*/
if ((res->start >> 32) != 0UL) {
printk(KERN_ERR "PCI: OBP assigns out of range MEM address "
"%016lx for region %ld on device %s\n",
res->start, (res - &pdev->resource[0]), pci_name(pdev));
continue;
}
}
/* Adjust the resource into the physical address space
* of this PBM.
*/
pbm->parent->resource_adjust(pdev, res, root);
if (request_resource(root, res) < 0) {
int rnum;
/* OK, there is some conflict. But this is fine
* since we'll reassign it in the fixup pass.
*
* Do not print the warning for ROM resources
* as such a conflict is quite common and
* harmless as the ROM bar is disabled.
*/
rnum = (res - &pdev->resource[0]);
if (rnum != PCI_ROM_RESOURCE)
printk(KERN_ERR "PCI: Resource collision, "
"region %d "
"[%016lx:%016lx] of device %s\n",
rnum,
res->start, res->end,
pci_name(pdev));
}
}
}
void __init pci_record_assignments(struct pci_pbm_info *pbm,
struct pci_bus *pbus)
{
struct pci_dev *dev;
struct pci_bus *bus;
list_for_each_entry(dev, &pbus->devices, bus_list)
pdev_record_assignments(pbm, dev);
list_for_each_entry(bus, &pbus->children, node)
pci_record_assignments(pbm, bus);
}
/* Return non-zero if PDEV has implicit I/O resources even
* though it may not have an I/O base address register
* active.
*/
static int __init has_implicit_io(struct pci_dev *pdev)
{
int class = pdev->class >> 8;
if (class == PCI_CLASS_NOT_DEFINED ||
class == PCI_CLASS_NOT_DEFINED_VGA ||
class == PCI_CLASS_STORAGE_IDE ||
(pdev->class >> 16) == PCI_BASE_CLASS_DISPLAY)
return 1;
return 0;
}
static void __init pdev_assign_unassigned(struct pci_pbm_info *pbm,
struct pci_dev *pdev)
{
u32 reg;
u16 cmd;
int i, io_seen, mem_seen;
io_seen = mem_seen = 0;
for (i = 0; i < PCI_NUM_RESOURCES; i++) {
struct resource *root, *res;
unsigned long size, min, max, align;
res = &pdev->resource[i];
if (res->flags & IORESOURCE_IO)
io_seen++;
else if (res->flags & IORESOURCE_MEM)
mem_seen++;
/* If it is already assigned or the resource does
* not exist, there is nothing to do.
*/
if (res->parent != NULL || res->flags == 0UL)
continue;
/* Determine the root we allocate from. */
if (res->flags & IORESOURCE_IO) {
root = &pbm->io_space;
min = root->start + 0x400UL;
max = root->end;
} else {
root = &pbm->mem_space;
min = root->start;
max = min + 0x80000000UL;
}
size = res->end - res->start;
align = size + 1;
if (allocate_resource(root, res, size + 1, min, max, align, NULL, NULL) < 0) {
/* uh oh */
prom_printf("PCI: Failed to allocate resource %d for %s\n",
i, pci_name(pdev));
prom_halt();
}
/* Update PCI config space. */
pbm->parent->base_address_update(pdev, i);
}
/* Special case, disable the ROM. Several devices
* act funny (ie. do not respond to memory space writes)
* when it is left enabled. A good example are Qlogic,ISP
* adapters.
*/
pci_read_config_dword(pdev, PCI_ROM_ADDRESS, &reg);
reg &= ~PCI_ROM_ADDRESS_ENABLE;
pci_write_config_dword(pdev, PCI_ROM_ADDRESS, reg);
/* If we saw I/O or MEM resources, enable appropriate
* bits in PCI command register.
*/
if (io_seen || mem_seen) {
pci_read_config_word(pdev, PCI_COMMAND, &cmd);
if (io_seen || has_implicit_io(pdev))
cmd |= PCI_COMMAND_IO;
if (mem_seen)
cmd |= PCI_COMMAND_MEMORY;
pci_write_config_word(pdev, PCI_COMMAND, cmd);
}
/* If this is a PCI bridge or an IDE controller,
* enable bus mastering. In the former case also
* set the cache line size correctly.
*/
if (((pdev->class >> 8) == PCI_CLASS_BRIDGE_PCI) ||
(((pdev->class >> 8) == PCI_CLASS_STORAGE_IDE) &&
((pdev->class & 0x80) != 0))) {
pci_read_config_word(pdev, PCI_COMMAND, &cmd);
cmd |= PCI_COMMAND_MASTER;
pci_write_config_word(pdev, PCI_COMMAND, cmd);
if ((pdev->class >> 8) == PCI_CLASS_BRIDGE_PCI)
pci_write_config_byte(pdev,
PCI_CACHE_LINE_SIZE,
(64 / sizeof(u32)));
}
}
void __init pci_assign_unassigned(struct pci_pbm_info *pbm,
struct pci_bus *pbus)
{
struct pci_dev *dev;
struct pci_bus *bus;
list_for_each_entry(dev, &pbus->devices, bus_list)
pdev_assign_unassigned(pbm, dev);
list_for_each_entry(bus, &pbus->children, node)
pci_assign_unassigned(pbm, bus);
}
static void __init pdev_fixup_irq(struct pci_dev *pdev)
{
struct pcidev_cookie *pcp = pdev->sysdata;
struct of_device *op = pcp->op;
if (op->irqs[0] == 0xffffffff) {
pdev->irq = PCI_IRQ_NONE;
return;
}
pdev->irq = op->irqs[0];
pci_write_config_byte(pdev, PCI_INTERRUPT_LINE,
pdev->irq & PCI_IRQ_INO);
}
void __init pci_fixup_irq(struct pci_pbm_info *pbm,
struct pci_bus *pbus)
{
struct pci_dev *dev;
struct pci_bus *bus;
list_for_each_entry(dev, &pbus->devices, bus_list)
pdev_fixup_irq(dev);
list_for_each_entry(bus, &pbus->children, node)
pci_fixup_irq(pbm, bus);
}
static void pdev_setup_busmastering(struct pci_dev *pdev, int is_66mhz)
{
u16 cmd;
u8 hdr_type, min_gnt, ltimer;
pci_read_config_word(pdev, PCI_COMMAND, &cmd);
cmd |= PCI_COMMAND_MASTER;
pci_write_config_word(pdev, PCI_COMMAND, cmd);
/* Read it back, if the mastering bit did not
* get set, the device does not support bus
* mastering so we have nothing to do here.
*/
pci_read_config_word(pdev, PCI_COMMAND, &cmd);
if ((cmd & PCI_COMMAND_MASTER) == 0)
return;
/* Set correct cache line size, 64-byte on all
* Sparc64 PCI systems. Note that the value is
* measured in 32-bit words.
*/
pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE,
64 / sizeof(u32));
pci_read_config_byte(pdev, PCI_HEADER_TYPE, &hdr_type);
hdr_type &= ~0x80;
if (hdr_type != PCI_HEADER_TYPE_NORMAL)
return;
/* If the latency timer is already programmed with a non-zero
* value, assume whoever set it (OBP or whoever) knows what
* they are doing.
*/
pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &ltimer);
if (ltimer != 0)
return;
/* XXX Since I'm tipping off the min grant value to
* XXX choose a suitable latency timer value, I also
* XXX considered making use of the max latency value
* XXX as well. Unfortunately I've seen too many bogusly
* XXX low settings for it to the point where it lacks
* XXX any usefulness. In one case, an ethernet card
* XXX claimed a min grant of 10 and a max latency of 5.
* XXX Now, if I had two such cards on the same bus I
* XXX could not set the desired burst period (calculated
* XXX from min grant) without violating the max latency
* XXX bound. Duh...
* XXX
* XXX I blame dumb PC bios implementors for stuff like
* XXX this, most of them don't even try to do something
* XXX sensible with latency timer values and just set some
* XXX default value (usually 32) into every device.
*/
pci_read_config_byte(pdev, PCI_MIN_GNT, &min_gnt);
if (min_gnt == 0) {
/* If no min_gnt setting then use a default
* value.
*/
if (is_66mhz)
ltimer = 16;
else
ltimer = 32;
} else {
int shift_factor;
if (is_66mhz)
shift_factor = 2;
else
shift_factor = 3;
/* Use a default value when the min_gnt value
* is erroneously high.
*/
if (((unsigned int) min_gnt << shift_factor) > 512 ||
((min_gnt << shift_factor) & 0xff) == 0) {
ltimer = 8 << shift_factor;
} else {
ltimer = min_gnt << shift_factor;
}
}
pci_write_config_byte(pdev, PCI_LATENCY_TIMER, ltimer);
}
void pci_determine_66mhz_disposition(struct pci_pbm_info *pbm,
struct pci_bus *pbus)
{
struct pci_dev *pdev;
int all_are_66mhz;
u16 status;
if (pbm->is_66mhz_capable == 0) {
all_are_66mhz = 0;
goto out;
}
all_are_66mhz = 1;
list_for_each_entry(pdev, &pbus->devices, bus_list) {
pci_read_config_word(pdev, PCI_STATUS, &status);
if (!(status & PCI_STATUS_66MHZ)) {
all_are_66mhz = 0;
break;
}
}
out:
pbm->all_devs_66mhz = all_are_66mhz;
printk("PCI%d(PBM%c): Bus running at %dMHz\n",
pbm->parent->index,
(pbm == &pbm->parent->pbm_A) ? 'A' : 'B',
(all_are_66mhz ? 66 : 33));
}
void pci_setup_busmastering(struct pci_pbm_info *pbm,
struct pci_bus *pbus)
{
struct pci_dev *dev;
struct pci_bus *bus;
int is_66mhz;
is_66mhz = pbm->is_66mhz_capable && pbm->all_devs_66mhz;
list_for_each_entry(dev, &pbus->devices, bus_list)
pdev_setup_busmastering(dev, is_66mhz);
list_for_each_entry(bus, &pbus->children, node)
pci_setup_busmastering(pbm, bus);
}
void pci_register_legacy_regions(struct resource *io_res,
struct resource *mem_res)
static void pci_register_legacy_regions(struct resource *io_res,
struct resource *mem_res)
{
struct resource *p;
@ -760,6 +52,102 @@ void pci_register_legacy_regions(struct resource *io_res,
request_resource(mem_res, p);
}
static void pci_register_iommu_region(struct pci_pbm_info *pbm)
{
const u32 *vdma = of_get_property(pbm->prom_node, "virtual-dma", NULL);
if (vdma) {
struct resource *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) vdma[0];
rp->end = rp->start + (unsigned long) vdma[1] - 1UL;
rp->flags = IORESOURCE_BUSY;
request_resource(&pbm->mem_space, rp);
}
}
void pci_determine_mem_io_space(struct pci_pbm_info *pbm)
{
const struct linux_prom_pci_ranges *pbm_ranges;
int i, saw_mem, saw_io;
int num_pbm_ranges;
saw_mem = saw_io = 0;
pbm_ranges = of_get_property(pbm->prom_node, "ranges", &i);
num_pbm_ranges = i / sizeof(*pbm_ranges);
for (i = 0; i < num_pbm_ranges; i++) {
const struct linux_prom_pci_ranges *pr = &pbm_ranges[i];
unsigned long a;
u32 parent_phys_hi, parent_phys_lo;
int type;
parent_phys_hi = pr->parent_phys_hi;
parent_phys_lo = pr->parent_phys_lo;
if (tlb_type == hypervisor)
parent_phys_hi &= 0x0fffffff;
type = (pr->child_phys_hi >> 24) & 0x3;
a = (((unsigned long)parent_phys_hi << 32UL) |
((unsigned long)parent_phys_lo << 0UL));
switch (type) {
case 0:
/* PCI config space, 16MB */
pbm->config_space = a;
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;
case 3:
/* XXX 64-bit MEM handling XXX */
default:
break;
};
}
if (!saw_io || !saw_mem) {
prom_printf("%s: Fatal error, missing %s PBM range.\n",
pbm->name,
(!saw_io ? "IO" : "MEM"));
prom_halt();
}
printk("%s: PCI IO[%lx] MEM[%lx]\n",
pbm->name,
pbm->io_space.start,
pbm->mem_space.start);
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);
pci_register_iommu_region(pbm);
}
/* Generic helper routines for PCI error reporting. */
void pci_scan_for_target_abort(struct pci_controller_info *p,
struct pci_pbm_info *pbm,

View File

@ -1,7 +1,6 @@
/* $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
@ -13,26 +12,22 @@
#include <asm/prom.h>
extern struct pci_controller_info *pci_controller_root;
extern unsigned long pci_memspace_mask;
extern int pci_num_controllers;
/* PCI bus scanning and fixup support. */
extern void pci_fixup_host_bridge_self(struct pci_bus *pbus);
extern void pci_fill_in_pbm_cookies(struct pci_bus *pbus,
struct pci_pbm_info *pbm,
struct device_node *prom_node);
extern void pci_record_assignments(struct pci_pbm_info *pbm,
struct pci_bus *pbus);
extern void pci_assign_unassigned(struct pci_pbm_info *pbm,
struct pci_bus *pbus);
extern void pci_fixup_irq(struct pci_pbm_info *pbm,
struct pci_bus *pbus);
extern void pci_determine_66mhz_disposition(struct pci_pbm_info *pbm,
struct pci_bus *pbus);
extern void pci_setup_busmastering(struct pci_pbm_info *pbm,
struct pci_bus *pbus);
extern void pci_register_legacy_regions(struct resource *io_res,
struct resource *mem_res);
extern struct pci_bus *pci_scan_one_pbm(struct pci_pbm_info *pbm);
extern void pci_determine_mem_io_space(struct pci_pbm_info *pbm);
extern int pci_host_bridge_read_pci_cfg(struct pci_bus *bus_dev,
unsigned int devfn,
int where, int size,
u32 *value);
extern int pci_host_bridge_write_pci_cfg(struct pci_bus *bus_dev,
unsigned int devfn,
int where, int size,
u32 value);
/* Error reporting support. */
extern void pci_scan_for_target_abort(struct pci_controller_info *, struct pci_pbm_info *, struct pci_bus *);

View File

@ -1,7 +1,6 @@
/* $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)
*/
@ -36,7 +35,7 @@
"i" (ASI_PHYS_BYPASS_EC_E))
/* 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;
int entry;
@ -64,7 +63,7 @@ static void __iommu_flushall(struct pci_iommu *iommu)
#define IOPTE_IS_DUMMY(iommu, iopte) \
((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);
@ -75,9 +74,9 @@ static inline void iopte_make_dummy(struct pci_iommu *iommu, iopte_t *iopte)
}
/* 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;
int pass;
@ -116,7 +115,7 @@ again:
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;
@ -124,7 +123,7 @@ static void pci_arena_free(struct pci_iommu_arena *arena, unsigned long base, un
__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;
@ -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]);
}
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;
@ -181,12 +180,12 @@ static inline iopte_t *alloc_npages(struct pci_iommu *iommu, unsigned long npage
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);
}
static int iommu_alloc_ctx(struct pci_iommu *iommu)
static int iommu_alloc_ctx(struct iommu *iommu)
{
int lowest = iommu->ctx_lowest_free;
int sz = IOMMU_NUM_CTXS - lowest;
@ -205,7 +204,7 @@ static int iommu_alloc_ctx(struct pci_iommu *iommu)
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)) {
__clear_bit(ctx, iommu->ctx_bitmap);
@ -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)
{
struct pcidev_cookie *pcp;
struct pci_iommu *iommu;
struct iommu *iommu;
iopte_t *iopte;
unsigned long flags, order, first_page;
void *ret;
@ -237,8 +235,7 @@ static void *pci_4u_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr
return NULL;
memset((char *)first_page, 0, PAGE_SIZE << order);
pcp = pdev->sysdata;
iommu = pcp->pbm->iommu;
iommu = pdev->dev.archdata.iommu;
spin_lock_irqsave(&iommu->lock, flags);
iopte = alloc_npages(iommu, size >> IO_PAGE_SHIFT);
@ -268,14 +265,12 @@ static void *pci_4u_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr
/* Free and unmap a consistent DMA translation. */
static void pci_4u_free_consistent(struct pci_dev *pdev, size_t size, void *cpu, dma_addr_t dvma)
{
struct pcidev_cookie *pcp;
struct pci_iommu *iommu;
struct iommu *iommu;
iopte_t *iopte;
unsigned long flags, order, npages;
npages = IO_PAGE_ALIGN(size) >> IO_PAGE_SHIFT;
pcp = pdev->sysdata;
iommu = pcp->pbm->iommu;
iommu = pdev->dev.archdata.iommu;
iopte = iommu->page_table +
((dvma - iommu->page_table_map_base) >> IO_PAGE_SHIFT);
@ -295,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)
{
struct pcidev_cookie *pcp;
struct pci_iommu *iommu;
struct pci_strbuf *strbuf;
struct iommu *iommu;
struct strbuf *strbuf;
iopte_t *base;
unsigned long flags, npages, oaddr;
unsigned long i, base_paddr, ctx;
u32 bus_addr, ret;
unsigned long iopte_protection;
pcp = pdev->sysdata;
iommu = pcp->pbm->iommu;
strbuf = &pcp->pbm->stc;
iommu = pdev->dev.archdata.iommu;
strbuf = pdev->dev.archdata.stc;
if (unlikely(direction == PCI_DMA_NONE))
goto bad_no_ctx;
@ -349,7 +342,7 @@ bad_no_ctx:
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;
@ -416,9 +409,8 @@ do_flush_sync:
/* Unmap a single streaming mode DMA translation. */
static void pci_4u_unmap_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_t sz, int direction)
{
struct pcidev_cookie *pcp;
struct pci_iommu *iommu;
struct pci_strbuf *strbuf;
struct iommu *iommu;
struct strbuf *strbuf;
iopte_t *base;
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_
return;
}
pcp = pdev->sysdata;
iommu = pcp->pbm->iommu;
strbuf = &pcp->pbm->stc;
iommu = pdev->dev.archdata.iommu;
strbuf = pdev->dev.archdata.stc;
npages = IO_PAGE_ALIGN(bus_addr + sz) - (bus_addr & IO_PAGE_MASK);
npages >>= IO_PAGE_SHIFT;
@ -549,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)
{
struct pcidev_cookie *pcp;
struct pci_iommu *iommu;
struct pci_strbuf *strbuf;
struct iommu *iommu;
struct strbuf *strbuf;
unsigned long flags, ctx, npages, iopte_protection;
iopte_t *base;
u32 dma_base;
@ -570,9 +560,8 @@ static int pci_4u_map_sg(struct pci_dev *pdev, struct scatterlist *sglist, int n
return 1;
}
pcp = pdev->sysdata;
iommu = pcp->pbm->iommu;
strbuf = &pcp->pbm->stc;
iommu = pdev->dev.archdata.iommu;
strbuf = pdev->dev.archdata.stc;
if (unlikely(direction == PCI_DMA_NONE))
goto bad_no_ctx;
@ -636,9 +625,8 @@ bad_no_ctx:
/* Unmap a set of streaming mode DMA translations. */
static void pci_4u_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, int direction)
{
struct pcidev_cookie *pcp;
struct pci_iommu *iommu;
struct pci_strbuf *strbuf;
struct iommu *iommu;
struct strbuf *strbuf;
iopte_t *base;
unsigned long flags, ctx, i, npages;
u32 bus_addr;
@ -648,9 +636,8 @@ static void pci_4u_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, in
WARN_ON(1);
}
pcp = pdev->sysdata;
iommu = pcp->pbm->iommu;
strbuf = &pcp->pbm->stc;
iommu = pdev->dev.archdata.iommu;
strbuf = pdev->dev.archdata.stc;
bus_addr = sglist->dma_address & IO_PAGE_MASK;
@ -696,14 +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)
{
struct pcidev_cookie *pcp;
struct pci_iommu *iommu;
struct pci_strbuf *strbuf;
struct iommu *iommu;
struct strbuf *strbuf;
unsigned long flags, ctx, npages;
pcp = pdev->sysdata;
iommu = pcp->pbm->iommu;
strbuf = &pcp->pbm->stc;
iommu = pdev->dev.archdata.iommu;
strbuf = pdev->dev.archdata.stc;
if (!strbuf->strbuf_enabled)
return;
@ -736,15 +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)
{
struct pcidev_cookie *pcp;
struct pci_iommu *iommu;
struct pci_strbuf *strbuf;
struct iommu *iommu;
struct strbuf *strbuf;
unsigned long flags, ctx, npages, i;
u32 bus_addr;
pcp = pdev->sysdata;
iommu = pcp->pbm->iommu;
strbuf = &pcp->pbm->stc;
iommu = pdev->dev.archdata.iommu;
strbuf = pdev->dev.archdata.stc;
if (!strbuf->strbuf_enabled)
return;
@ -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);
}
struct pci_iommu_ops pci_sun4u_iommu_ops = {
const struct pci_iommu_ops pci_sun4u_iommu_ops = {
.alloc_consistent = pci_4u_alloc_consistent,
.free_consistent = pci_4u_free_consistent,
.map_single = pci_4u_map_single,
@ -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)
{
struct pcidev_cookie *pcp = pdev->sysdata;
u64 dma_addr_mask;
if (pdev == NULL) {
dma_addr_mask = 0xffffffff;
} else {
struct pci_iommu *iommu = pcp->pbm->iommu;
struct iommu *iommu = pdev->dev.archdata.iommu;
dma_addr_mask = iommu->dma_addr_mask;

View File

@ -1,7 +1,6 @@
/* $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) 1999 Jakub Jelinek (jakub@redhat.com)
*/
@ -119,6 +118,10 @@ static int psycho_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
u16 tmp16;
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) {
case 1:
*value = 0xff;
@ -172,6 +175,9 @@ static int psycho_write_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
unsigned char bus = bus_dev->number;
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);
if (!addr)
return PCIBIOS_SUCCESSFUL;
@ -263,7 +269,7 @@ static void __psycho_check_one_stc(struct pci_controller_info *p,
struct pci_pbm_info *pbm,
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 err_base, tag_base, line_base;
u64 control;
@ -412,7 +418,7 @@ static void psycho_check_iommu_error(struct pci_controller_info *p,
unsigned long afar,
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_data[16];
unsigned long flags;
@ -895,59 +901,6 @@ static void psycho_register_error_handlers(struct pci_controller_info *p)
}
/* 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)
{
u8 *addr;
@ -968,28 +921,7 @@ static void pbm_config_busmastering(struct pci_pbm_info *pbm)
static void pbm_scan_bus(struct pci_controller_info *p,
struct pci_pbm_info *pbm)
{
struct pcidev_cookie *cookie = kzalloc(sizeof(*cookie), GFP_KERNEL);
if (!cookie) {
prom_printf("PSYCHO: Critical allocation failure.\n");
prom_halt();
}
/* All we care about is the PBM. */
cookie->pbm = pbm;
pbm->pci_bus = pci_scan_bus(pbm->pci_first_busno,
p->pci_ops,
pbm);
pci_fixup_host_bridge_self(pbm->pci_bus);
pbm->pci_bus->self->sysdata = cookie;
pci_fill_in_pbm_cookies(pbm->pci_bus, pbm, pbm->prom_node);
pci_record_assignments(pbm, pbm->pci_bus);
pci_assign_unassigned(pbm, pbm->pci_bus);
pci_fixup_irq(pbm, pbm->pci_bus);
pci_determine_66mhz_disposition(pbm, pbm->pci_bus);
pci_setup_busmastering(pbm, pbm->pci_bus);
pbm->pci_bus = pci_scan_one_pbm(pbm);
}
static void psycho_scan_bus(struct pci_controller_info *p)
@ -1009,7 +941,7 @@ static void psycho_scan_bus(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;
u64 control;
@ -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);
}
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,
struct pci_pbm_info *pbm,
int is_pbm_a)
@ -1172,19 +1091,11 @@ static void psycho_pbm_init(struct pci_controller_info *p,
unsigned int *busrange;
struct property *prop;
struct pci_pbm_info *pbm;
int len;
if (is_pbm_a) {
if (is_pbm_a)
pbm = &p->pbm_A;
pbm->pci_first_slot = 1;
pbm->io_space.start = pbm->controller_regs + PSYCHO_IOSPACE_A;
pbm->mem_space.start = pbm->controller_regs + PSYCHO_MEMSPACE_A;
} else {
else
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_version = 0;
@ -1196,41 +1107,15 @@ static void psycho_pbm_init(struct pci_controller_info *p,
if (prop)
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->prom_node = dp;
pbm->name = dp->full_name;
pbm_register_toplevel_resources(p, pbm);
printk("%s: PSYCHO PCI Bus Module ver[%x:%x]\n",
pbm->name,
pbm->chip_version, pbm->chip_revision);
prop = of_find_property(dp, "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(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;
}
pci_determine_mem_io_space(pbm);
prop = of_find_property(dp, "bus-range", NULL);
busrange = prop->value;
@ -1246,7 +1131,7 @@ void psycho_init(struct device_node *dp, char *model_name)
{
struct linux_prom64_registers *pr_regs;
struct pci_controller_info *p;
struct pci_iommu *iommu;
struct iommu *iommu;
struct property *prop;
u32 upa_portid;
int is_pbm_a;
@ -1269,7 +1154,7 @@ void psycho_init(struct device_node *dp, char *model_name)
prom_printf("PSYCHO: Fatal memory allocation error.\n");
prom_halt();
}
iommu = kzalloc(sizeof(struct pci_iommu), GFP_ATOMIC);
iommu = kzalloc(sizeof(struct iommu), GFP_ATOMIC);
if (!iommu) {
prom_printf("PSYCHO: Fatal memory allocation error.\n");
prom_halt();
@ -1282,10 +1167,7 @@ void psycho_init(struct device_node *dp, char *model_name)
p->pbm_A.portid = upa_portid;
p->pbm_B.portid = upa_portid;
p->index = pci_num_controllers++;
p->pbms_same_domain = 0;
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;
prop = of_find_property(dp, "reg", NULL);

View File

@ -1,7 +1,6 @@
/* $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) 1999 Jakub Jelinek (jakub@redhat.com)
*/
@ -254,9 +253,6 @@ static int __sabre_out_of_range(struct pci_pbm_info *pbm,
return 0;
return ((pbm->parent == 0) ||
((pbm == &pbm->parent->pbm_B) &&
(bus == pbm->pci_first_busno) &&
PCI_SLOT(devfn) > 8) ||
((pbm == &pbm->parent->pbm_A) &&
(bus == pbm->pci_first_busno) &&
PCI_SLOT(devfn) > 8));
@ -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,
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)) {
switch (size) {
case 1:
@ -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,
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)
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,
unsigned long afsr,
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_data[16];
unsigned long flags;
@ -710,8 +718,8 @@ static irqreturn_t sabre_pcierr_intr_other(struct pci_controller_info *p)
p->index);
ret = IRQ_HANDLED;
}
pci_read_config_word(sabre_root_bus->self,
PCI_STATUS, &stat);
pci_bus_read_config_word(sabre_root_bus, 0,
PCI_STATUS, &stat);
if (stat & (PCI_STATUS_PARITY |
PCI_STATUS_SIG_TARGET_ABORT |
PCI_STATUS_REC_TARGET_ABORT |
@ -719,8 +727,8 @@ static irqreturn_t sabre_pcierr_intr_other(struct pci_controller_info *p)
PCI_STATUS_SIG_SYSTEM_ERROR)) {
printk("SABRE%d: PCI bus error, PCI_STATUS[%04x]\n",
p->index, stat);
pci_write_config_word(sabre_root_bus->self,
PCI_STATUS, 0xffff);
pci_bus_write_config_word(sabre_root_bus, 0,
PCI_STATUS, 0xffff);
ret = IRQ_HANDLED;
}
return ret;
@ -800,12 +808,10 @@ static irqreturn_t sabre_pcierr_intr(int irq, void *dev_id)
if (error_bits & (SABRE_PIOAFSR_PTA | SABRE_PIOAFSR_STA)) {
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_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_B, p->pbm_B.pci_bus);
}
/* For excessive retries, SABRE/PBM will abort the device
* and there is no way to specifically check for excessive
* retries in the config space status registers. So what
@ -813,10 +819,8 @@ static irqreturn_t sabre_pcierr_intr(int irq, void *dev_id)
* 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_B, p->pbm_B.pci_bus);
}
return IRQ_HANDLED;
}
@ -869,144 +873,52 @@ static void sabre_register_error_handlers(struct pci_controller_info *p)
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)
{
struct pci_dev *pdev;
list_for_each_entry(pdev, &sabre_bus->devices, bus_list) {
if (pdev->vendor == PCI_VENDOR_ID_SUN &&
pdev->device == PCI_DEVICE_ID_SUN_SIMBA) {
u32 word32;
u16 word16;
sabre_read_pci_cfg(pdev->bus, pdev->devfn,
PCI_COMMAND, 2, &word32);
word16 = (u16) word32;
pci_read_config_word(pdev, PCI_COMMAND, &word16);
word16 |= PCI_COMMAND_SERR | PCI_COMMAND_PARITY |
PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY |
PCI_COMMAND_IO;
word32 = (u32) word16;
sabre_write_pci_cfg(pdev->bus, pdev->devfn,
PCI_COMMAND, 2, word32);
pci_write_config_word(pdev, PCI_COMMAND, word16);
/* Status register bits are "write 1 to clear". */
sabre_write_pci_cfg(pdev->bus, pdev->devfn,
PCI_STATUS, 2, 0xffff);
sabre_write_pci_cfg(pdev->bus, pdev->devfn,
PCI_SEC_STATUS, 2, 0xffff);
pci_write_config_word(pdev, PCI_STATUS, 0xffff);
pci_write_config_word(pdev, PCI_SEC_STATUS, 0xffff);
/* Use a primary/seconday latency timer value
* of 64.
*/
sabre_write_pci_cfg(pdev->bus, pdev->devfn,
PCI_LATENCY_TIMER, 1, 64);
sabre_write_pci_cfg(pdev->bus, pdev->devfn,
PCI_SEC_LATENCY_TIMER, 1, 64);
pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 64);
pci_write_config_byte(pdev, PCI_SEC_LATENCY_TIMER, 64);
/* Enable reporting/forwarding of master aborts,
* parity, and SERR.
*/
sabre_write_pci_cfg(pdev->bus, pdev->devfn,
PCI_BRIDGE_CONTROL, 1,
(PCI_BRIDGE_CTL_PARITY |
PCI_BRIDGE_CTL_SERR |
PCI_BRIDGE_CTL_MASTER_ABORT));
pci_write_config_byte(pdev, PCI_BRIDGE_CONTROL,
(PCI_BRIDGE_CTL_PARITY |
PCI_BRIDGE_CTL_SERR |
PCI_BRIDGE_CTL_MASTER_ABORT));
}
}
}
static struct pcidev_cookie *alloc_bridge_cookie(struct pci_pbm_info *pbm)
{
struct pcidev_cookie *cookie = kzalloc(sizeof(*cookie), GFP_KERNEL);
if (!cookie) {
prom_printf("SABRE: Critical allocation failure.\n");
prom_halt();
}
/* All we care about is the PBM. */
cookie->pbm = pbm;
return cookie;
}
static void sabre_scan_bus(struct pci_controller_info *p)
{
static int once;
struct pci_bus *sabre_bus, *pbus;
struct pci_pbm_info *pbm;
struct pcidev_cookie *cookie;
int sabres_scanned;
struct pci_bus *pbus;
/* The APB bridge speaks to the Sabre host PCI bridge
* at 66Mhz, but the front side of APB runs at 33Mhz
* for both segments.
*/
p->pbm_A.is_66mhz_capable = 0;
p->pbm_B.is_66mhz_capable = 0;
/* This driver has not been verified to handle
* multiple SABREs yet, so trap this.
@ -1020,56 +932,13 @@ static void sabre_scan_bus(struct pci_controller_info *p)
}
once++;
cookie = alloc_bridge_cookie(&p->pbm_A);
pbus = pci_scan_one_pbm(&p->pbm_A);
if (!pbus)
return;
sabre_bus = pci_scan_bus(p->pci_first_busno,
p->pci_ops,
&p->pbm_A);
pci_fixup_host_bridge_self(sabre_bus);
sabre_bus->self->sysdata = cookie;
sabre_root_bus = pbus;
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;
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) {
/* 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);
}
apb_init(p, pbus);
sabre_register_error_handlers(p);
}
@ -1078,7 +947,7 @@ static void sabre_iommu_init(struct pci_controller_info *p,
int tsbsize, unsigned long dvma_offset,
u32 dma_mask)
{
struct pci_iommu *iommu = p->pbm_A.iommu;
struct iommu *iommu = p->pbm_A.iommu;
unsigned long i;
u64 control;
@ -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);
}
static void pbm_register_toplevel_resources(struct pci_controller_info *p,
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)
static void sabre_pbm_init(struct pci_controller_info *p, struct device_node *dp)
{
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;
pbm = &p->pbm_A;
pbm->name = dp->full_name;
printk("%s: SABRE PCI Bus Module\n", pbm->name);
prop = of_find_property(node, "model", NULL);
if (!prop || strncmp(prop->value, "SUNW,simba", prop->length))
goto next_pci;
pbm->chip_type = PBM_CHIP_TYPE_SABRE;
pbm->parent = p;
pbm->prom_node = dp;
pbm->pci_first_busno = p->pci_first_busno;
pbm->pci_last_busno = p->pci_last_busno;
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;
printk("%s: SABRE PCI Bus Module\n", pbm->name);
pbm->chip_type = PBM_CHIP_TYPE_SABRE;
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->pci_first_busno = p->pci_first_busno;
pbm->pci_last_busno = p->pci_last_busno;
prop = of_find_property(dp, "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(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);
}
pci_determine_mem_io_space(pbm);
}
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_iommu *iommu;
struct property *prop;
struct iommu *iommu;
int tsbsize;
u32 *busrange;
u32 *vdma;
const u32 *busrange;
const u32 *vdma;
u32 upa_portid, dma_mask;
u64 clear_irq;
@ -1351,13 +1027,9 @@ void sabre_init(struct device_node *dp, char *model_name)
if (!strcmp(model_name, "pci108e,a001"))
hummingbird_p = 1;
else if (!strcmp(model_name, "SUNW,sabre")) {
prop = of_find_property(dp, "compatible", NULL);
if (prop) {
const char *compat = prop->value;
if (!strcmp(compat, "pci108e,a001"))
hummingbird_p = 1;
}
const char *compat = of_get_property(dp, "compatible", NULL);
if (compat && !strcmp(compat, "pci108e,a001"))
hummingbird_p = 1;
if (!hummingbird_p) {
struct device_node *dp;
@ -1381,37 +1053,28 @@ void sabre_init(struct device_node *dp, char *model_name)
prom_printf("SABRE: Error, kmalloc(pci_iommu) failed.\n");
prom_halt();
}
p->pbm_A.iommu = p->pbm_B.iommu = iommu;
p->pbm_A.iommu = iommu;
upa_portid = 0xff;
prop = of_find_property(dp, "upa-portid", NULL);
if (prop)
upa_portid = *(u32 *) prop->value;
upa_portid = of_getintprop_default(dp, "upa-portid", 0xff);
p->next = pci_controller_root;
pci_controller_root = p;
p->pbm_A.portid = upa_portid;
p->pbm_B.portid = upa_portid;
p->index = pci_num_controllers++;
p->pbms_same_domain = 1;
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;
/*
* Map in SABRE register set and report the presence of this SABRE.
*/
prop = of_find_property(dp, "reg", NULL);
pr_regs = prop->value;
pr_regs = of_get_property(dp, "reg", NULL);
/*
* First REG in property is base of entire SABRE register space.
*/
p->pbm_A.controller_regs = pr_regs[0].phys_addr;
p->pbm_B.controller_regs = pr_regs[0].phys_addr;
/* Clear interrupts */
@ -1429,11 +1092,10 @@ void sabre_init(struct device_node *dp, char *model_name)
SABRE_PCICTRL_ARBPARK | SABRE_PCICTRL_AEN));
/* 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);
prop = of_find_property(dp, "virtual-dma", NULL);
vdma = prop->value;
vdma = of_get_property(dp, "virtual-dma", NULL);
dma_mask = vdma[0];
switch(vdma[1]) {
@ -1457,13 +1119,12 @@ void sabre_init(struct device_node *dp, char *model_name)
sabre_iommu_init(p, tsbsize, vdma[0], dma_mask);
prop = of_find_property(dp, "bus-range", NULL);
busrange = prop->value;
busrange = of_get_property(dp, "bus-range", NULL);
p->pci_first_busno = busrange[0];
p->pci_last_busno = busrange[1];
/*
* Look for APB underneath.
*/
sabre_pbm_init(p, dp, vdma[0], vdma[0] + vdma[1]);
sabre_pbm_init(p, dp);
}

View File

@ -1,7 +1,6 @@
/* $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>
@ -126,6 +125,9 @@ static int schizo_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
u16 tmp16;
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) {
case 1:
*value = 0xff;
@ -179,6 +181,9 @@ static int schizo_write_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
unsigned char bus = bus_dev->number;
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);
if (!addr)
return PCIBIOS_SUCCESSFUL;
@ -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,
enum schizo_error_type type)
{
struct pci_strbuf *strbuf = &pbm->stc;
struct strbuf *strbuf = &pbm->stc;
unsigned long regbase = pbm->pbm_regs;
unsigned long err_base, tag_base, line_base;
u64 control;
@ -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,
enum schizo_error_type type)
{
struct pci_iommu *iommu = pbm->iommu;
struct iommu *iommu = pbm->iommu;
unsigned long iommu_tag[16];
unsigned long iommu_data[16];
unsigned long flags;
@ -1229,42 +1234,8 @@ static void pbm_config_busmastering(struct pci_pbm_info *pbm)
pci_config_write8(addr, 64);
}
static void pbm_scan_bus(struct pci_controller_info *p,
struct pci_pbm_info *pbm)
static void schizo_scan_bus(struct pci_controller_info *p)
{
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);
p->pbm_B.is_66mhz_capable =
(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,
p->pbm_A.is_66mhz_capable =
(of_find_property(p->pbm_A.prom_node, "66mhz-capable", 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
* 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);
else
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_FLUSH (0x02808UL)
#define SCHIZO_STRBUF_FSYNC (0x02810UL)
@ -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)
{
struct pci_iommu *iommu = pbm->iommu;
struct iommu *iommu = pbm->iommu;
unsigned long i, tagbase, database;
struct property *prop;
u32 vdma[2], dma_mask;
@ -1654,14 +1490,12 @@ static void schizo_pbm_init(struct pci_controller_info *p,
struct device_node *dp, u32 portid,
int chip_type)
{
struct linux_prom64_registers *regs;
struct property *prop;
unsigned int *busrange;
const struct linux_prom64_registers *regs;
const unsigned int *busrange;
struct pci_pbm_info *pbm;
const char *chipset_name;
u32 *ino_bitmap;
const u32 *ino_bitmap;
int is_pbm_a;
int len;
switch (chip_type) {
case PBM_CHIP_TYPE_TOMATILLO:
@ -1689,11 +1523,9 @@ static void schizo_pbm_init(struct pci_controller_info *p,
* 3) PBM PCI config space
* 4) Ichip regs
*/
prop = of_find_property(dp, "reg", NULL);
regs = prop->value;
regs = of_get_property(dp, "reg", NULL);
is_pbm_a = ((regs[0].phys_addr & 0x00700000) == 0x00600000);
if (is_pbm_a)
pbm = &p->pbm_A;
else
@ -1702,17 +1534,10 @@ static void schizo_pbm_init(struct pci_controller_info *p,
pbm->portid = portid;
pbm->parent = p;
pbm->prom_node = dp;
pbm->pci_first_slot = 1;
pbm->chip_type = chip_type;
pbm->chip_version = 0;
prop = of_find_property(dp, "version#", NULL);
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->chip_version = of_getintprop_default(dp, "version#", 0);
pbm->chip_revision = of_getintprop_default(dp, "module-version#", 0);
pbm->pbm_regs = regs[0].phys_addr;
pbm->controller_regs = regs[1].phys_addr - 0x10000UL;
@ -1723,40 +1548,18 @@ static void schizo_pbm_init(struct pci_controller_info *p,
pbm->name = dp->full_name;
printk("%s: %s PCI Bus Module ver[%x:%x]\n",
pbm->name,
(chip_type == PBM_CHIP_TYPE_TOMATILLO ?
"TOMATILLO" : "SCHIZO"),
pbm->name, chipset_name,
pbm->chip_version, pbm->chip_revision);
schizo_pbm_hw_init(pbm);
prop = of_find_property(dp, "ranges", &len);
pbm->pbm_ranges = prop->value;
pbm->num_pbm_ranges =
(len / sizeof(struct linux_prom_pci_ranges));
pci_determine_mem_io_space(pbm);
schizo_determine_mem_io_space(pbm);
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;
ino_bitmap = of_get_property(dp, "ino-bitmap", NULL);
pbm->ino_bitmap = (((u64)ino_bitmap[1] << 32UL) |
((u64)ino_bitmap[0] << 0UL));
prop = of_find_property(dp, "bus-range", NULL);
busrange = prop->value;
busrange = of_get_property(dp, "bus-range", NULL);
pbm->pci_first_busno = busrange[0];
pbm->pci_last_busno = busrange[1];
@ -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)
{
struct pci_controller_info *p;
struct pci_iommu *iommu;
struct property *prop;
int is_pbm_a;
struct iommu *iommu;
u32 portid;
portid = 0xff;
prop = of_find_property(dp, "portid", NULL);
if (prop)
portid = *(u32 *) prop->value;
portid = of_getintprop_default(dp, "portid", 0xff);
for (p = pci_controller_root; p; p = p->next) {
struct pci_pbm_info *pbm;
@ -1798,48 +1596,43 @@ static void __schizo_init(struct device_node *dp, char *model_name, int chip_typ
&p->pbm_B);
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);
return;
}
}
p = kzalloc(sizeof(struct pci_controller_info), GFP_ATOMIC);
if (!p) {
prom_printf("SCHIZO: Fatal memory allocation error.\n");
prom_halt();
}
if (!p)
goto memfail;
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;
iommu = kzalloc(sizeof(struct pci_iommu), GFP_ATOMIC);
if (!iommu) {
prom_printf("SCHIZO: Fatal memory allocation error.\n");
prom_halt();
}
iommu = kzalloc(sizeof(struct iommu), GFP_ATOMIC);
if (!iommu)
goto memfail;
p->pbm_B.iommu = iommu;
p->next = pci_controller_root;
pci_controller_root = p;
p->index = pci_num_controllers++;
p->pbms_same_domain = 0;
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->scan_bus = schizo_scan_bus;
p->pci_ops = &schizo_ops;
/* Like PSYCHO we have a 2GB aligned area for memory space. */
pci_memspace_mask = 0x7fffffffUL;
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)

View File

@ -1,6 +1,6 @@
/* pci_sun4v.c: SUN4V specific PCI controller support.
*
* Copyright (C) 2006 David S. Miller (davem@davemloft.net)
* Copyright (C) 2006, 2007 David S. Miller (davem@davemloft.net)
*/
#include <linux/kernel.h>
@ -29,7 +29,7 @@
#define PGLIST_NENTS (PAGE_SIZE / sizeof(u64))
struct pci_iommu_batch {
struct iommu_batch {
struct pci_dev *pdev; /* Device mapping is for. */
unsigned long prot; /* IOMMU page protections */
unsigned long entry; /* Index into IOTSB. */
@ -37,12 +37,12 @@ struct pci_iommu_batch {
unsigned long npages; /* Number of pages in list. */
};
static DEFINE_PER_CPU(struct pci_iommu_batch, pci_iommu_batch);
static DEFINE_PER_CPU(struct iommu_batch, pci_iommu_batch);
/* Interrupts must be disabled. */
static inline void pci_iommu_batch_start(struct pci_dev *pdev, unsigned long prot, unsigned long entry)
{
struct pci_iommu_batch *p = &__get_cpu_var(pci_iommu_batch);
struct iommu_batch *p = &__get_cpu_var(pci_iommu_batch);
p->pdev = pdev;
p->prot = prot;
@ -51,10 +51,10 @@ static inline void pci_iommu_batch_start(struct pci_dev *pdev, unsigned long pro
}
/* Interrupts must be disabled. */
static long pci_iommu_batch_flush(struct pci_iommu_batch *p)
static long pci_iommu_batch_flush(struct iommu_batch *p)
{
struct pcidev_cookie *pcp = p->pdev->sysdata;
unsigned long devhandle = pcp->pbm->devhandle;
struct pci_pbm_info *pbm = p->pdev->dev.archdata.host_controller;
unsigned long devhandle = pbm->devhandle;
unsigned long prot = p->prot;
unsigned long entry = p->entry;
u64 *pglist = p->pglist;
@ -89,7 +89,7 @@ static long pci_iommu_batch_flush(struct pci_iommu_batch *p)
/* Interrupts must be disabled. */
static inline long pci_iommu_batch_add(u64 phys_page)
{
struct pci_iommu_batch *p = &__get_cpu_var(pci_iommu_batch);
struct iommu_batch *p = &__get_cpu_var(pci_iommu_batch);
BUG_ON(p->npages >= PGLIST_NENTS);
@ -103,14 +103,14 @@ static inline long pci_iommu_batch_add(u64 phys_page)
/* Interrupts must be disabled. */
static inline long pci_iommu_batch_end(void)
{
struct pci_iommu_batch *p = &__get_cpu_var(pci_iommu_batch);
struct iommu_batch *p = &__get_cpu_var(pci_iommu_batch);
BUG_ON(p->npages >= PGLIST_NENTS);
return pci_iommu_batch_flush(p);
}
static long pci_arena_alloc(struct pci_iommu_arena *arena, unsigned long npages)
static long pci_arena_alloc(struct iommu_arena *arena, unsigned long npages)
{
unsigned long n, i, start, end, limit;
int pass;
@ -149,7 +149,7 @@ again:
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;
@ -159,8 +159,7 @@ static void pci_arena_free(struct pci_iommu_arena *arena, unsigned long base, un
static void *pci_4v_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr_t *dma_addrp, gfp_t gfp)
{
struct pcidev_cookie *pcp;
struct pci_iommu *iommu;
struct iommu *iommu;
unsigned long flags, order, first_page, npages, n;
void *ret;
long entry;
@ -178,8 +177,7 @@ static void *pci_4v_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr
memset((char *)first_page, 0, PAGE_SIZE << order);
pcp = pdev->sysdata;
iommu = pcp->pbm->iommu;
iommu = pdev->dev.archdata.iommu;
spin_lock_irqsave(&iommu->lock, flags);
entry = pci_arena_alloc(&iommu->arena, npages);
@ -226,15 +224,15 @@ arena_alloc_fail:
static void pci_4v_free_consistent(struct pci_dev *pdev, size_t size, void *cpu, dma_addr_t dvma)
{
struct pcidev_cookie *pcp;
struct pci_iommu *iommu;
struct pci_pbm_info *pbm;
struct iommu *iommu;
unsigned long flags, order, npages, entry;
u32 devhandle;
npages = IO_PAGE_ALIGN(size) >> IO_PAGE_SHIFT;
pcp = pdev->sysdata;
iommu = pcp->pbm->iommu;
devhandle = pcp->pbm->devhandle;
iommu = pdev->dev.archdata.iommu;
pbm = pdev->dev.archdata.host_controller;
devhandle = pbm->devhandle;
entry = ((dvma - iommu->page_table_map_base) >> IO_PAGE_SHIFT);
spin_lock_irqsave(&iommu->lock, flags);
@ -259,16 +257,14 @@ static void pci_4v_free_consistent(struct pci_dev *pdev, size_t size, void *cpu,
static dma_addr_t pci_4v_map_single(struct pci_dev *pdev, void *ptr, size_t sz, int direction)
{
struct pcidev_cookie *pcp;
struct pci_iommu *iommu;
struct iommu *iommu;
unsigned long flags, npages, oaddr;
unsigned long i, base_paddr;
u32 bus_addr, ret;
unsigned long prot;
long entry;
pcp = pdev->sysdata;
iommu = pcp->pbm->iommu;
iommu = pdev->dev.archdata.iommu;
if (unlikely(direction == PCI_DMA_NONE))
goto bad;
@ -324,8 +320,8 @@ iommu_map_fail:
static void pci_4v_unmap_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_t sz, int direction)
{
struct pcidev_cookie *pcp;
struct pci_iommu *iommu;
struct pci_pbm_info *pbm;
struct iommu *iommu;
unsigned long flags, npages;
long entry;
u32 devhandle;
@ -336,9 +332,9 @@ static void pci_4v_unmap_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_
return;
}
pcp = pdev->sysdata;
iommu = pcp->pbm->iommu;
devhandle = pcp->pbm->devhandle;
iommu = pdev->dev.archdata.iommu;
pbm = pdev->dev.archdata.host_controller;
devhandle = pbm->devhandle;
npages = IO_PAGE_ALIGN(bus_addr + sz) - (bus_addr & IO_PAGE_MASK);
npages >>= IO_PAGE_SHIFT;
@ -460,8 +456,7 @@ iommu_map_failed:
static int pci_4v_map_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, int direction)
{
struct pcidev_cookie *pcp;
struct pci_iommu *iommu;
struct iommu *iommu;
unsigned long flags, npages, prot;
u32 dma_base;
struct scatterlist *sgtmp;
@ -480,8 +475,7 @@ static int pci_4v_map_sg(struct pci_dev *pdev, struct scatterlist *sglist, int n
return 1;
}
pcp = pdev->sysdata;
iommu = pcp->pbm->iommu;
iommu = pdev->dev.archdata.iommu;
if (unlikely(direction == PCI_DMA_NONE))
goto bad;
@ -537,8 +531,8 @@ iommu_map_failed:
static void pci_4v_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, int direction)
{
struct pcidev_cookie *pcp;
struct pci_iommu *iommu;
struct pci_pbm_info *pbm;
struct iommu *iommu;
unsigned long flags, i, npages;
long entry;
u32 devhandle, bus_addr;
@ -548,9 +542,9 @@ static void pci_4v_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, in
WARN_ON(1);
}
pcp = pdev->sysdata;
iommu = pcp->pbm->iommu;
devhandle = pcp->pbm->devhandle;
iommu = pdev->dev.archdata.iommu;
pbm = pdev->dev.archdata.host_controller;
devhandle = pbm->devhandle;
bus_addr = sglist->dma_address & IO_PAGE_MASK;
@ -589,7 +583,7 @@ static void pci_4v_dma_sync_sg_for_cpu(struct pci_dev *pdev, struct scatterlist
/* Nothing to do... */
}
struct pci_iommu_ops pci_sun4v_iommu_ops = {
const struct pci_iommu_ops pci_sun4v_iommu_ops = {
.alloc_consistent = pci_4v_alloc_consistent,
.free_consistent = pci_4v_free_consistent,
.map_single = pci_4v_map_single,
@ -600,132 +594,12 @@ struct pci_iommu_ops pci_sun4v_iommu_ops = {
.dma_sync_sg_for_cpu = pci_4v_dma_sync_sg_for_cpu,
};
/* SUN4V PCI configuration space accessors. */
struct pdev_entry {
struct pdev_entry *next;
u32 devhandle;
unsigned int bus;
unsigned int device;
unsigned int func;
};
#define PDEV_HTAB_SIZE 16
#define PDEV_HTAB_MASK (PDEV_HTAB_SIZE - 1)
static struct pdev_entry *pdev_htab[PDEV_HTAB_SIZE];
static inline unsigned int pdev_hashfn(u32 devhandle, unsigned int bus, unsigned int device, unsigned int func)
{
unsigned int val;
val = (devhandle ^ (devhandle >> 4));
val ^= bus;
val ^= device;
val ^= func;
return val & PDEV_HTAB_MASK;
}
static int pdev_htab_add(u32 devhandle, unsigned int bus, unsigned int device, unsigned int func)
{
struct pdev_entry *p = kmalloc(sizeof(*p), GFP_KERNEL);
struct pdev_entry **slot;
if (!p)
return -ENOMEM;
slot = &pdev_htab[pdev_hashfn(devhandle, bus, device, func)];
p->next = *slot;
*slot = p;
p->devhandle = devhandle;
p->bus = bus;
p->device = device;
p->func = func;
return 0;
}
/* Recursively descend into the OBP device tree, rooted at toplevel_node,
* looking for a PCI device matching bus and devfn.
*/
static int obp_find(struct device_node *toplevel_node, unsigned int bus, unsigned int devfn)
{
toplevel_node = toplevel_node->child;
while (toplevel_node != NULL) {
struct linux_prom_pci_registers *regs;
struct property *prop;
int ret;
ret = obp_find(toplevel_node, bus, devfn);
if (ret != 0)
return ret;
prop = of_find_property(toplevel_node, "reg", NULL);
if (!prop)
goto next_sibling;
regs = prop->value;
if (((regs->phys_hi >> 16) & 0xff) == bus &&
((regs->phys_hi >> 8) & 0xff) == devfn)
break;
next_sibling:
toplevel_node = toplevel_node->sibling;
}
return toplevel_node != NULL;
}
static int pdev_htab_populate(struct pci_pbm_info *pbm)
{
u32 devhandle = pbm->devhandle;
unsigned int bus;
for (bus = pbm->pci_first_busno; bus <= pbm->pci_last_busno; bus++) {
unsigned int devfn;
for (devfn = 0; devfn < 256; devfn++) {
unsigned int device = PCI_SLOT(devfn);
unsigned int func = PCI_FUNC(devfn);
if (obp_find(pbm->prom_node, bus, devfn)) {
int err = pdev_htab_add(devhandle, bus,
device, func);
if (err)
return err;
}
}
}
return 0;
}
static struct pdev_entry *pdev_find(u32 devhandle, unsigned int bus, unsigned int device, unsigned int func)
{
struct pdev_entry *p;
p = pdev_htab[pdev_hashfn(devhandle, bus, device, func)];
while (p) {
if (p->devhandle == devhandle &&
p->bus == bus &&
p->device == device &&
p->func == func)
break;
p = p->next;
}
return p;
}
static inline int pci_sun4v_out_of_range(struct pci_pbm_info *pbm, unsigned int bus, unsigned int device, unsigned int func)
{
if (bus < pbm->pci_first_busno ||
bus > pbm->pci_last_busno)
return 1;
return pdev_find(pbm->devhandle, bus, device, func) == NULL;
return 0;
}
static int pci_sun4v_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
@ -738,6 +612,9 @@ static int pci_sun4v_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
unsigned int func = PCI_FUNC(devfn);
unsigned long ret;
if (bus_dev == pbm->pci_bus && devfn == 0x00)
return pci_host_bridge_read_pci_cfg(bus_dev, devfn, where,
size, value);
if (pci_sun4v_out_of_range(pbm, bus, device, func)) {
ret = ~0UL;
} else {
@ -776,6 +653,9 @@ static int pci_sun4v_write_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
unsigned int func = PCI_FUNC(devfn);
unsigned long ret;
if (bus_dev == pbm->pci_bus && devfn == 0x00)
return pci_host_bridge_write_pci_cfg(bus_dev, devfn, where,
size, value);
if (pci_sun4v_out_of_range(pbm, bus, device, func)) {
/* Do nothing. */
} else {
@ -800,27 +680,7 @@ static struct pci_ops pci_sun4v_ops = {
static void pbm_scan_bus(struct pci_controller_info *p,
struct pci_pbm_info *pbm)
{
struct pcidev_cookie *cookie = kzalloc(sizeof(*cookie), GFP_KERNEL);
if (!cookie) {
prom_printf("%s: Critical allocation failure.\n", pbm->name);
prom_halt();
}
/* All we care about is the PBM. */
cookie->pbm = pbm;
pbm->pci_bus = pci_scan_bus(pbm->pci_first_busno, p->pci_ops, pbm);
#if 0
pci_fixup_host_bridge_self(pbm->pci_bus);
pbm->pci_bus->self->sysdata = cookie;
#endif
pci_fill_in_pbm_cookies(pbm->pci_bus, pbm, pbm->prom_node);
pci_record_assignments(pbm, pbm->pci_bus);
pci_assign_unassigned(pbm, pbm->pci_bus);
pci_fixup_irq(pbm, pbm->pci_bus);
pci_determine_66mhz_disposition(pbm, pbm->pci_bus);
pci_setup_busmastering(pbm, pbm->pci_bus);
pbm->pci_bus = pci_scan_one_pbm(pbm);
}
static void pci_sun4v_scan_bus(struct pci_controller_info *p)
@ -844,130 +704,10 @@ static void pci_sun4v_scan_bus(struct pci_controller_info *p)
/* XXX register error interrupt handlers XXX */
}
static void pci_sun4v_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;
}
/* XXX 64-bit MEM handling is not %100 correct... XXX */
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 pci_sun4v_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 pci_sun4v_determine_mem_io_space(struct pci_pbm_info *pbm)
{
int i, saw_mem, saw_io;
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 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;
case 3:
/* XXX 64-bit MEM handling XXX */
default:
break;
};
}
if (!saw_io || !saw_mem) {
prom_printf("%s: Fatal error, missing %s PBM range.\n",
pbm->name,
(!saw_io ? "IO" : "MEM"));
prom_halt();
}
printk("%s: PCI IO[%lx] MEM[%lx]\n",
pbm->name,
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);
}
static unsigned long probe_existing_entries(struct pci_pbm_info *pbm,
struct pci_iommu *iommu)
struct iommu *iommu)
{
struct pci_iommu_arena *arena = &iommu->arena;
struct iommu_arena *arena = &iommu->arena;
unsigned long i, cnt = 0;
u32 devhandle;
@ -994,7 +734,7 @@ static unsigned long probe_existing_entries(struct pci_pbm_info *pbm,
static void pci_sun4v_iommu_init(struct pci_pbm_info *pbm)
{
struct pci_iommu *iommu = pbm->iommu;
struct iommu *iommu = pbm->iommu;
struct property *prop;
unsigned long num_tsb_entries, sz;
u32 vdma[2], dma_mask, dma_offset;
@ -1281,7 +1021,7 @@ h_error:
static void pci_sun4v_msi_init(struct pci_pbm_info *pbm)
{
u32 *val;
const u32 *val;
int len;
val = of_get_property(pbm->prom_node, "#msi-eqs", &len);
@ -1289,16 +1029,16 @@ static void pci_sun4v_msi_init(struct pci_pbm_info *pbm)
goto no_msi;
pbm->msiq_num = *val;
if (pbm->msiq_num) {
struct msiq_prop {
const struct msiq_prop {
u32 first_msiq;
u32 num_msiq;
u32 first_devino;
} *mqp;
struct msi_range_prop {
const struct msi_range_prop {
u32 first_msi;
u32 num_msi;
} *mrng;
struct addr_range_prop {
const struct addr_range_prop {
u32 msi32_high;
u32 msi32_low;
u32 msi32_len;
@ -1410,8 +1150,7 @@ static int pci_sun4v_setup_msi_irq(unsigned int *virt_irq_p,
struct pci_dev *pdev,
struct msi_desc *entry)
{
struct pcidev_cookie *pcp = pdev->sysdata;
struct pci_pbm_info *pbm = pcp->pbm;
struct pci_pbm_info *pbm = pdev->dev.archdata.host_controller;
unsigned long devino, msiqid;
struct msi_msg msg;
int msi_num, err;
@ -1455,7 +1194,7 @@ static int pci_sun4v_setup_msi_irq(unsigned int *virt_irq_p,
if (pci_sun4v_msi_setvalid(pbm->devhandle, msi_num, HV_MSIVALID_VALID))
goto out_err;
pcp->msi_num = msi_num;
pdev->dev.archdata.msi_num = msi_num;
if (entry->msi_attrib.is_64) {
msg.address_hi = pbm->msi64_start >> 32;
@ -1484,12 +1223,11 @@ out_err:
static void pci_sun4v_teardown_msi_irq(unsigned int virt_irq,
struct pci_dev *pdev)
{
struct pcidev_cookie *pcp = pdev->sysdata;
struct pci_pbm_info *pbm = pcp->pbm;
struct pci_pbm_info *pbm = pdev->dev.archdata.host_controller;
unsigned long msiqid, err;
unsigned int msi_num;
msi_num = pcp->msi_num;
msi_num = pdev->dev.archdata.msi_num;
err = pci_sun4v_msi_getmsiq(pbm->devhandle, msi_num, &msiqid);
if (err) {
printk(KERN_ERR "%s: getmsiq gives error %lu\n",
@ -1516,8 +1254,6 @@ static void pci_sun4v_msi_init(struct pci_pbm_info *pbm)
static void pci_sun4v_pbm_init(struct pci_controller_info *p, struct device_node *dp, u32 devhandle)
{
struct pci_pbm_info *pbm;
struct property *prop;
int len, i;
if (devhandle & 0x40)
pbm = &p->pbm_B;
@ -1526,7 +1262,6 @@ static void pci_sun4v_pbm_init(struct pci_controller_info *p, struct device_node
pbm->parent = p;
pbm->prom_node = dp;
pbm->pci_first_slot = 1;
pbm->devhandle = devhandle;
@ -1534,39 +1269,17 @@ static void pci_sun4v_pbm_init(struct pci_controller_info *p, struct device_node
printk("%s: SUN4V PCI Bus Module\n", pbm->name);
prop = of_find_property(dp, "ranges", &len);
pbm->pbm_ranges = prop->value;
pbm->num_pbm_ranges =
(len / sizeof(struct linux_prom_pci_ranges));
/* Mask out the top 8 bits of the ranges, leaving the real
* physical address.
*/
for (i = 0; i < pbm->num_pbm_ranges; i++)
pbm->pbm_ranges[i].parent_phys_hi &= 0x0fffffff;
pci_sun4v_determine_mem_io_space(pbm);
pbm_register_toplevel_resources(p, pbm);
prop = of_find_property(dp, "interrupt-map", &len);
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;
pci_determine_mem_io_space(pbm);
pci_sun4v_get_bus_range(pbm);
pci_sun4v_iommu_init(pbm);
pci_sun4v_msi_init(pbm);
pdev_htab_populate(pbm);
}
void sun4v_pci_init(struct device_node *dp, char *model_name)
{
struct pci_controller_info *p;
struct pci_iommu *iommu;
struct iommu *iommu;
struct property *prop;
struct linux_prom64_registers *regs;
u32 devhandle;
@ -1606,13 +1319,13 @@ void sun4v_pci_init(struct device_node *dp, char *model_name)
if (!p)
goto fatal_memory_error;
iommu = kzalloc(sizeof(struct pci_iommu), GFP_ATOMIC);
iommu = kzalloc(sizeof(struct iommu), GFP_ATOMIC);
if (!iommu)
goto fatal_memory_error;
p->pbm_A.iommu = iommu;
iommu = kzalloc(sizeof(struct pci_iommu), GFP_ATOMIC);
iommu = kzalloc(sizeof(struct iommu), GFP_ATOMIC);
if (!iommu)
goto fatal_memory_error;
@ -1622,11 +1335,8 @@ void sun4v_pci_init(struct device_node *dp, char *model_name)
pci_controller_root = p;
p->index = pci_num_controllers++;
p->pbms_same_domain = 0;
p->scan_bus = pci_sun4v_scan_bus;
p->base_address_update = pci_sun4v_base_address_update;
p->resource_adjust = pci_sun4v_resource_adjust;
#ifdef CONFIG_PCI_MSI
p->setup_msi_irq = pci_sun4v_setup_msi_irq;
p->teardown_msi_irq = pci_sun4v_teardown_msi_irq;

View File

@ -28,6 +28,7 @@
#include <linux/reboot.h>
#include <linux/delay.h>
#include <linux/compat.h>
#include <linux/tick.h>
#include <linux/init.h>
#include <asm/oplib.h>
@ -88,12 +89,14 @@ void cpu_idle(void)
set_thread_flag(TIF_POLLING_NRFLAG);
while(1) {
if (need_resched()) {
preempt_enable_no_resched();
schedule();
preempt_disable();
}
sparc64_yield();
tick_nohz_stop_sched_tick();
while (!need_resched())
sparc64_yield();
tick_nohz_restart_sched_tick();
preempt_enable_no_resched();
schedule();
preempt_disable();
}
}

View File

@ -36,12 +36,13 @@ static struct device_node *allnodes;
*/
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;
int cplen, l;
cp = (char *) of_get_property(device, "compatible", &cplen);
cp = of_get_property(device, "compatible", &cplen);
if (cp == NULL)
return 0;
while (cplen > 0) {
@ -154,13 +155,14 @@ struct device_node *of_find_compatible_node(struct device_node *from,
}
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)
{
struct property *pp;
for (pp = np->properties; pp != 0; pp = pp->next) {
if (strcmp(pp->name, name) == 0) {
if (strcasecmp(pp->name, name) == 0) {
if (lenp != 0)
*lenp = pp->length;
break;
@ -174,7 +176,8 @@ EXPORT_SYMBOL(of_find_property);
* Find a property with a given name for a given node
* 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);
return pp ? pp->value : NULL;
@ -196,7 +199,7 @@ EXPORT_SYMBOL(of_getintprop_default);
int of_n_addr_cells(struct device_node *np)
{
int* ip;
const int* ip;
do {
if (np->parent)
np = np->parent;
@ -211,7 +214,7 @@ EXPORT_SYMBOL(of_n_addr_cells);
int of_n_size_cells(struct device_node *np)
{
int* ip;
const int* ip;
do {
if (np->parent)
np = np->parent;
@ -243,7 +246,7 @@ int of_set_property(struct device_node *dp, const char *name, void *val, int len
while (*prevp) {
struct property *prop = *prevp;
if (!strcmp(prop->name, name)) {
if (!strcasecmp(prop->name, name)) {
void *old_val = prop->value;
int ret;
@ -397,7 +400,7 @@ static unsigned int psycho_irq_build(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->irq_build = psycho_irq_build;
@ -547,7 +550,7 @@ static unsigned long __sabre_onboard_imap_off[] = {
static int sabre_device_needs_wsync(struct device_node *dp)
{
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
* handle two cases:
@ -589,7 +592,7 @@ static unsigned int sabre_irq_build(struct device_node *dp,
{
struct sabre_irq_data *irq_data = _data;
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_off, iclr_off;
int inofixup = 0;
@ -639,9 +642,9 @@ static unsigned int sabre_irq_build(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;
u32 *busrange;
const u32 *busrange;
dp->irq_trans = prom_early_alloc(sizeof(struct of_irq_controller));
dp->irq_trans->irq_build = sabre_irq_build;
@ -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)
{
struct linux_prom64_registers *regs;
const struct linux_prom64_registers *regs;
struct schizo_irq_data *irq_data;
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,
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->irq_build = pci_sun4v_irq_build;
@ -940,7 +943,7 @@ static unsigned int sbus_of_build_irq(struct device_node *dp,
void *_data)
{
unsigned long reg_base = (unsigned long) _data;
struct linux_prom_registers *regs;
const struct linux_prom_registers *regs;
unsigned long imap, iclr;
int sbus_slot = 0;
int sbus_level = 0;
@ -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)
{
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->irq_build = sbus_of_build_irq;
@ -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)
{
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->irq_build = sun4v_vdev_irq_build;

View File

@ -26,23 +26,9 @@
#define MAP_BASE ((u32)0xc0000000)
struct sbus_iommu_arena {
unsigned long *map;
unsigned int hint;
unsigned int limit;
};
struct sbus_iommu {
spinlock_t lock;
struct sbus_iommu_arena arena;
iopte_t *page_table;
unsigned long strbuf_regs;
unsigned long iommu_regs;
unsigned long sbus_control_reg;
volatile unsigned long strbuf_flushflag;
struct sbus_info {
struct iommu iommu;
struct strbuf strbuf;
};
/* Offsets from iommu_regs */
@ -58,16 +44,17 @@ struct sbus_iommu {
#define IOMMU_DRAM_VALID (1UL << 30UL)
static void __iommu_flushall(struct sbus_iommu *iommu)
static void __iommu_flushall(struct iommu *iommu)
{
unsigned long tag = iommu->iommu_regs + IOMMU_TAGDIAG;
unsigned long tag;
int entry;
tag = iommu->iommu_control + (IOMMU_TAGDIAG - IOMMU_CONTROL);
for (entry = 0; entry < 16; entry++) {
upa_writeq(0, tag);
tag += 8UL;
}
upa_readq(iommu->sbus_control_reg);
upa_readq(iommu->write_complete_reg);
}
/* Offsets from strbuf_regs */
@ -82,15 +69,14 @@ static void __iommu_flushall(struct sbus_iommu *iommu)
#define STRBUF_TAG_VALID 0x02UL
static void sbus_strbuf_flush(struct sbus_iommu *iommu, u32 base, unsigned long npages, int direction)
static void sbus_strbuf_flush(struct iommu *iommu, struct strbuf *strbuf, u32 base, unsigned long npages, int direction)
{
unsigned long n;
int limit;
n = npages;
while (n--)
upa_writeq(base + (n << IO_PAGE_SHIFT),
iommu->strbuf_regs + STRBUF_PFLUSH);
upa_writeq(base + (n << IO_PAGE_SHIFT), strbuf->strbuf_pflush);
/* If the device could not have possibly put dirty data into
* the streaming cache, no flush-flag synchronization needs
@ -99,15 +85,14 @@ static void sbus_strbuf_flush(struct sbus_iommu *iommu, u32 base, unsigned long
if (direction == SBUS_DMA_TODEVICE)
return;
iommu->strbuf_flushflag = 0UL;
*(strbuf->strbuf_flushflag) = 0UL;
/* Whoopee cushion! */
upa_writeq(__pa(&iommu->strbuf_flushflag),
iommu->strbuf_regs + STRBUF_FSYNC);
upa_readq(iommu->sbus_control_reg);
upa_writeq(strbuf->strbuf_flushflag_pa, strbuf->strbuf_fsync);
upa_readq(iommu->write_complete_reg);
limit = 100000;
while (iommu->strbuf_flushflag == 0UL) {
while (*(strbuf->strbuf_flushflag) == 0UL) {
limit--;
if (!limit)
break;
@ -121,9 +106,9 @@ static void sbus_strbuf_flush(struct sbus_iommu *iommu, u32 base, unsigned long
}
/* Based largely upon the ppc64 iommu allocator. */
static long sbus_arena_alloc(struct sbus_iommu *iommu, unsigned long npages)
static long sbus_arena_alloc(struct iommu *iommu, unsigned long npages)
{
struct sbus_iommu_arena *arena = &iommu->arena;
struct iommu_arena *arena = &iommu->arena;
unsigned long n, i, start, end, limit;
int pass;
@ -162,7 +147,7 @@ again:
return n;
}
static void sbus_arena_free(struct sbus_iommu_arena *arena, unsigned long base, unsigned long npages)
static void sbus_arena_free(struct iommu_arena *arena, unsigned long base, unsigned long npages)
{
unsigned long i;
@ -170,7 +155,7 @@ static void sbus_arena_free(struct sbus_iommu_arena *arena, unsigned long base,
__clear_bit(i, arena->map);
}
static void sbus_iommu_table_init(struct sbus_iommu *iommu, unsigned int tsbsize)
static void sbus_iommu_table_init(struct iommu *iommu, unsigned int tsbsize)
{
unsigned long tsbbase, order, sz, num_tsb_entries;
@ -178,13 +163,14 @@ static void sbus_iommu_table_init(struct sbus_iommu *iommu, unsigned int tsbsize
/* Setup initial software IOMMU state. */
spin_lock_init(&iommu->lock);
iommu->page_table_map_base = MAP_BASE;
/* Allocate and initialize the free area map. */
sz = num_tsb_entries / 8;
sz = (sz + 7UL) & ~7UL;
iommu->arena.map = kzalloc(sz, GFP_KERNEL);
if (!iommu->arena.map) {
prom_printf("PCI_IOMMU: Error, kmalloc(arena.map) failed.\n");
prom_printf("SBUS_IOMMU: Error, kmalloc(arena.map) failed.\n");
prom_halt();
}
iommu->arena.limit = num_tsb_entries;
@ -200,7 +186,7 @@ static void sbus_iommu_table_init(struct sbus_iommu *iommu, unsigned int tsbsize
memset(iommu->page_table, 0, tsbsize);
}
static inline iopte_t *alloc_npages(struct sbus_iommu *iommu, unsigned long npages)
static inline iopte_t *alloc_npages(struct iommu *iommu, unsigned long npages)
{
long entry;
@ -211,14 +197,15 @@ static inline iopte_t *alloc_npages(struct sbus_iommu *iommu, unsigned long npag
return iommu->page_table + entry;
}
static inline void free_npages(struct sbus_iommu *iommu, dma_addr_t base, unsigned long npages)
static inline void free_npages(struct iommu *iommu, dma_addr_t base, unsigned long npages)
{
sbus_arena_free(&iommu->arena, base >> IO_PAGE_SHIFT, npages);
}
void *sbus_alloc_consistent(struct sbus_dev *sdev, size_t size, dma_addr_t *dvma_addr)
{
struct sbus_iommu *iommu;
struct sbus_info *info;
struct iommu *iommu;
iopte_t *iopte;
unsigned long flags, order, first_page;
void *ret;
@ -234,7 +221,8 @@ void *sbus_alloc_consistent(struct sbus_dev *sdev, size_t size, dma_addr_t *dvma
return NULL;
memset((char *)first_page, 0, PAGE_SIZE << order);
iommu = sdev->bus->iommu;
info = sdev->bus->iommu;
iommu = &info->iommu;
spin_lock_irqsave(&iommu->lock, flags);
iopte = alloc_npages(iommu, size >> IO_PAGE_SHIFT);
@ -245,7 +233,7 @@ void *sbus_alloc_consistent(struct sbus_dev *sdev, size_t size, dma_addr_t *dvma
return NULL;
}
*dvma_addr = (MAP_BASE +
*dvma_addr = (iommu->page_table_map_base +
((iopte - iommu->page_table) << IO_PAGE_SHIFT));
ret = (void *) first_page;
npages = size >> IO_PAGE_SHIFT;
@ -263,18 +251,20 @@ void *sbus_alloc_consistent(struct sbus_dev *sdev, size_t size, dma_addr_t *dvma
void sbus_free_consistent(struct sbus_dev *sdev, size_t size, void *cpu, dma_addr_t dvma)
{
struct sbus_iommu *iommu;
struct sbus_info *info;
struct iommu *iommu;
iopte_t *iopte;
unsigned long flags, order, npages;
npages = IO_PAGE_ALIGN(size) >> IO_PAGE_SHIFT;
iommu = sdev->bus->iommu;
info = sdev->bus->iommu;
iommu = &info->iommu;
iopte = iommu->page_table +
((dvma - MAP_BASE) >> IO_PAGE_SHIFT);
((dvma - iommu->page_table_map_base) >> IO_PAGE_SHIFT);
spin_lock_irqsave(&iommu->lock, flags);
free_npages(iommu, dvma - MAP_BASE, npages);
free_npages(iommu, dvma - iommu->page_table_map_base, npages);
spin_unlock_irqrestore(&iommu->lock, flags);
@ -285,14 +275,16 @@ void sbus_free_consistent(struct sbus_dev *sdev, size_t size, void *cpu, dma_add
dma_addr_t sbus_map_single(struct sbus_dev *sdev, void *ptr, size_t sz, int direction)
{
struct sbus_iommu *iommu;
struct sbus_info *info;
struct iommu *iommu;
iopte_t *base;
unsigned long flags, npages, oaddr;
unsigned long i, base_paddr;
u32 bus_addr, ret;
unsigned long iopte_protection;
iommu = sdev->bus->iommu;
info = sdev->bus->iommu;
iommu = &info->iommu;
if (unlikely(direction == SBUS_DMA_NONE))
BUG();
@ -308,7 +300,7 @@ dma_addr_t sbus_map_single(struct sbus_dev *sdev, void *ptr, size_t sz, int dire
if (unlikely(!base))
BUG();
bus_addr = (MAP_BASE +
bus_addr = (iommu->page_table_map_base +
((base - iommu->page_table) << IO_PAGE_SHIFT));
ret = bus_addr | (oaddr & ~IO_PAGE_MASK);
base_paddr = __pa(oaddr & IO_PAGE_MASK);
@ -325,7 +317,9 @@ dma_addr_t sbus_map_single(struct sbus_dev *sdev, void *ptr, size_t sz, int dire
void sbus_unmap_single(struct sbus_dev *sdev, dma_addr_t bus_addr, size_t sz, int direction)
{
struct sbus_iommu *iommu = sdev->bus->iommu;
struct sbus_info *info = sdev->bus->iommu;
struct iommu *iommu = &info->iommu;
struct strbuf *strbuf = &info->strbuf;
iopte_t *base;
unsigned long flags, npages, i;
@ -335,15 +329,15 @@ void sbus_unmap_single(struct sbus_dev *sdev, dma_addr_t bus_addr, size_t sz, in
npages = IO_PAGE_ALIGN(bus_addr + sz) - (bus_addr & IO_PAGE_MASK);
npages >>= IO_PAGE_SHIFT;
base = iommu->page_table +
((bus_addr - MAP_BASE) >> IO_PAGE_SHIFT);
((bus_addr - iommu->page_table_map_base) >> IO_PAGE_SHIFT);
bus_addr &= IO_PAGE_MASK;
spin_lock_irqsave(&iommu->lock, flags);
sbus_strbuf_flush(iommu, bus_addr, npages, direction);
sbus_strbuf_flush(iommu, strbuf, bus_addr, npages, direction);
for (i = 0; i < npages; i++)
iopte_val(base[i]) = 0UL;
free_npages(iommu, bus_addr - MAP_BASE, npages);
free_npages(iommu, bus_addr - iommu->page_table_map_base, npages);
spin_unlock_irqrestore(&iommu->lock, flags);
}
@ -425,7 +419,8 @@ static inline void fill_sg(iopte_t *iopte, struct scatterlist *sg,
int sbus_map_sg(struct sbus_dev *sdev, struct scatterlist *sglist, int nelems, int direction)
{
struct sbus_iommu *iommu;
struct sbus_info *info;
struct iommu *iommu;
unsigned long flags, npages, iopte_protection;
iopte_t *base;
u32 dma_base;
@ -442,7 +437,8 @@ int sbus_map_sg(struct sbus_dev *sdev, struct scatterlist *sglist, int nelems, i
return 1;
}
iommu = sdev->bus->iommu;
info = sdev->bus->iommu;
iommu = &info->iommu;
if (unlikely(direction == SBUS_DMA_NONE))
BUG();
@ -456,7 +452,7 @@ int sbus_map_sg(struct sbus_dev *sdev, struct scatterlist *sglist, int nelems, i
if (unlikely(base == NULL))
BUG();
dma_base = MAP_BASE +
dma_base = iommu->page_table_map_base +
((base - iommu->page_table) << IO_PAGE_SHIFT);
/* Normalize DVMA addresses. */
@ -485,7 +481,9 @@ int sbus_map_sg(struct sbus_dev *sdev, struct scatterlist *sglist, int nelems, i
void sbus_unmap_sg(struct sbus_dev *sdev, struct scatterlist *sglist, int nelems, int direction)
{
struct sbus_iommu *iommu;
struct sbus_info *info;
struct iommu *iommu;
struct strbuf *strbuf;
iopte_t *base;
unsigned long flags, i, npages;
u32 bus_addr;
@ -493,7 +491,9 @@ void sbus_unmap_sg(struct sbus_dev *sdev, struct scatterlist *sglist, int nelems
if (unlikely(direction == SBUS_DMA_NONE))
BUG();
iommu = sdev->bus->iommu;
info = sdev->bus->iommu;
iommu = &info->iommu;
strbuf = &info->strbuf;
bus_addr = sglist->dma_address & IO_PAGE_MASK;
@ -505,29 +505,33 @@ void sbus_unmap_sg(struct sbus_dev *sdev, struct scatterlist *sglist, int nelems
bus_addr) >> IO_PAGE_SHIFT;
base = iommu->page_table +
((bus_addr - MAP_BASE) >> IO_PAGE_SHIFT);
((bus_addr - iommu->page_table_map_base) >> IO_PAGE_SHIFT);
spin_lock_irqsave(&iommu->lock, flags);
sbus_strbuf_flush(iommu, bus_addr, npages, direction);
sbus_strbuf_flush(iommu, strbuf, bus_addr, npages, direction);
for (i = 0; i < npages; i++)
iopte_val(base[i]) = 0UL;
free_npages(iommu, bus_addr - MAP_BASE, npages);
free_npages(iommu, bus_addr - iommu->page_table_map_base, npages);
spin_unlock_irqrestore(&iommu->lock, flags);
}
void sbus_dma_sync_single_for_cpu(struct sbus_dev *sdev, dma_addr_t bus_addr, size_t sz, int direction)
{
struct sbus_iommu *iommu;
struct sbus_info *info;
struct iommu *iommu;
struct strbuf *strbuf;
unsigned long flags, npages;
iommu = sdev->bus->iommu;
info = sdev->bus->iommu;
iommu = &info->iommu;
strbuf = &info->strbuf;
npages = IO_PAGE_ALIGN(bus_addr + sz) - (bus_addr & IO_PAGE_MASK);
npages >>= IO_PAGE_SHIFT;
bus_addr &= IO_PAGE_MASK;
spin_lock_irqsave(&iommu->lock, flags);
sbus_strbuf_flush(iommu, bus_addr, npages, direction);
sbus_strbuf_flush(iommu, strbuf, bus_addr, npages, direction);
spin_unlock_irqrestore(&iommu->lock, flags);
}
@ -537,11 +541,15 @@ void sbus_dma_sync_single_for_device(struct sbus_dev *sdev, dma_addr_t base, siz
void sbus_dma_sync_sg_for_cpu(struct sbus_dev *sdev, struct scatterlist *sglist, int nelems, int direction)
{
struct sbus_iommu *iommu;
struct sbus_info *info;
struct iommu *iommu;
struct strbuf *strbuf;
unsigned long flags, npages, i;
u32 bus_addr;
iommu = sdev->bus->iommu;
info = sdev->bus->iommu;
iommu = &info->iommu;
strbuf = &info->strbuf;
bus_addr = sglist[0].dma_address & IO_PAGE_MASK;
for (i = 0; i < nelems; i++) {
@ -553,7 +561,7 @@ void sbus_dma_sync_sg_for_cpu(struct sbus_dev *sdev, struct scatterlist *sglist,
- bus_addr) >> IO_PAGE_SHIFT;
spin_lock_irqsave(&iommu->lock, flags);
sbus_strbuf_flush(iommu, bus_addr, npages, direction);
sbus_strbuf_flush(iommu, strbuf, bus_addr, npages, direction);
spin_unlock_irqrestore(&iommu->lock, flags);
}
@ -564,12 +572,13 @@ void sbus_dma_sync_sg_for_device(struct sbus_dev *sdev, struct scatterlist *sg,
/* Enable 64-bit DVMA mode for the given device. */
void sbus_set_sbus64(struct sbus_dev *sdev, int bursts)
{
struct sbus_iommu *iommu = sdev->bus->iommu;
struct sbus_info *info = sdev->bus->iommu;
struct iommu *iommu = &info->iommu;
int slot = sdev->slot;
unsigned long cfg_reg;
u64 val;
cfg_reg = iommu->sbus_control_reg;
cfg_reg = iommu->write_complete_reg;
switch (slot) {
case 0:
cfg_reg += 0x20UL;
@ -704,8 +713,9 @@ static unsigned long sysio_imap_to_iclr(unsigned long imap)
unsigned int sbus_build_irq(void *buscookie, unsigned int ino)
{
struct sbus_bus *sbus = (struct sbus_bus *)buscookie;
struct sbus_iommu *iommu = sbus->iommu;
unsigned long reg_base = iommu->sbus_control_reg - 0x2000UL;
struct sbus_info *info = sbus->iommu;
struct iommu *iommu = &info->iommu;
unsigned long reg_base = iommu->write_complete_reg - 0x2000UL;
unsigned long imap, iclr;
int sbus_level = 0;
@ -766,8 +776,9 @@ unsigned int sbus_build_irq(void *buscookie, unsigned int ino)
static irqreturn_t sysio_ue_handler(int irq, void *dev_id)
{
struct sbus_bus *sbus = dev_id;
struct sbus_iommu *iommu = sbus->iommu;
unsigned long reg_base = iommu->sbus_control_reg - 0x2000UL;
struct sbus_info *info = sbus->iommu;
struct iommu *iommu = &info->iommu;
unsigned long reg_base = iommu->write_complete_reg - 0x2000UL;
unsigned long afsr_reg, afar_reg;
unsigned long afsr, afar, error_bits;
int reported;
@ -838,8 +849,9 @@ static irqreturn_t sysio_ue_handler(int irq, void *dev_id)
static irqreturn_t sysio_ce_handler(int irq, void *dev_id)
{
struct sbus_bus *sbus = dev_id;
struct sbus_iommu *iommu = sbus->iommu;
unsigned long reg_base = iommu->sbus_control_reg - 0x2000UL;
struct sbus_info *info = sbus->iommu;
struct iommu *iommu = &info->iommu;
unsigned long reg_base = iommu->write_complete_reg - 0x2000UL;
unsigned long afsr_reg, afar_reg;
unsigned long afsr, afar, error_bits;
int reported;
@ -915,12 +927,13 @@ static irqreturn_t sysio_ce_handler(int irq, void *dev_id)
static irqreturn_t sysio_sbus_error_handler(int irq, void *dev_id)
{
struct sbus_bus *sbus = dev_id;
struct sbus_iommu *iommu = sbus->iommu;
struct sbus_info *info = sbus->iommu;
struct iommu *iommu = &info->iommu;
unsigned long afsr_reg, afar_reg, reg_base;
unsigned long afsr, afar, error_bits;
int reported;
reg_base = iommu->sbus_control_reg - 0x2000UL;
reg_base = iommu->write_complete_reg - 0x2000UL;
afsr_reg = reg_base + SYSIO_SBUS_AFSR;
afar_reg = reg_base + SYSIO_SBUS_AFAR;
@ -982,8 +995,9 @@ static irqreturn_t sysio_sbus_error_handler(int irq, void *dev_id)
static void __init sysio_register_error_handlers(struct sbus_bus *sbus)
{
struct sbus_iommu *iommu = sbus->iommu;
unsigned long reg_base = iommu->sbus_control_reg - 0x2000UL;
struct sbus_info *info = sbus->iommu;
struct iommu *iommu = &info->iommu;
unsigned long reg_base = iommu->write_complete_reg - 0x2000UL;
unsigned int irq;
u64 control;
@ -1017,18 +1031,20 @@ static void __init sysio_register_error_handlers(struct sbus_bus *sbus)
SYSIO_ECNTRL_CEEN),
reg_base + ECC_CONTROL);
control = upa_readq(iommu->sbus_control_reg);
control = upa_readq(iommu->write_complete_reg);
control |= 0x100UL; /* SBUS Error Interrupt Enable */
upa_writeq(control, iommu->sbus_control_reg);
upa_writeq(control, iommu->write_complete_reg);
}
/* Boot time initialization. */
static void __init sbus_iommu_init(int __node, struct sbus_bus *sbus)
{
struct linux_prom64_registers *pr;
const struct linux_prom64_registers *pr;
struct device_node *dp;
struct sbus_iommu *iommu;
unsigned long regs;
struct sbus_info *info;
struct iommu *iommu;
struct strbuf *strbuf;
unsigned long regs, reg_base;
u64 control;
int i;
@ -1043,33 +1059,42 @@ static void __init sbus_iommu_init(int __node, struct sbus_bus *sbus)
}
regs = pr->phys_addr;
iommu = kmalloc(sizeof(*iommu) + SMP_CACHE_BYTES, GFP_ATOMIC);
if (iommu == NULL) {
prom_printf("sbus_iommu_init: Fatal error, kmalloc(iommu) failed\n");
info = kzalloc(sizeof(*info), GFP_ATOMIC);
if (info == NULL) {
prom_printf("sbus_iommu_init: Fatal error, "
"kmalloc(info) failed\n");
prom_halt();
}
/* Align on E$ line boundary. */
iommu = (struct sbus_iommu *)
(((unsigned long)iommu + (SMP_CACHE_BYTES - 1UL)) &
~(SMP_CACHE_BYTES - 1UL));
iommu = &info->iommu;
strbuf = &info->strbuf;
memset(iommu, 0, sizeof(*iommu));
reg_base = regs + SYSIO_IOMMUREG_BASE;
iommu->iommu_control = reg_base + IOMMU_CONTROL;
iommu->iommu_tsbbase = reg_base + IOMMU_TSBBASE;
iommu->iommu_flush = reg_base + IOMMU_FLUSH;
/* Setup spinlock. */
spin_lock_init(&iommu->lock);
reg_base = regs + SYSIO_STRBUFREG_BASE;
strbuf->strbuf_control = reg_base + STRBUF_CONTROL;
strbuf->strbuf_pflush = reg_base + STRBUF_PFLUSH;
strbuf->strbuf_fsync = reg_base + STRBUF_FSYNC;
/* Init register offsets. */
iommu->iommu_regs = regs + SYSIO_IOMMUREG_BASE;
iommu->strbuf_regs = regs + SYSIO_STRBUFREG_BASE;
strbuf->strbuf_enabled = 1;
strbuf->strbuf_flushflag = (volatile unsigned long *)
((((unsigned long)&strbuf->__flushflag_buf[0])
+ 63UL)
& ~63UL);
strbuf->strbuf_flushflag_pa = (unsigned long)
__pa(strbuf->strbuf_flushflag);
/* The SYSIO SBUS control register is used for dummy reads
* in order to ensure write completion.
*/
iommu->sbus_control_reg = regs + 0x2000UL;
iommu->write_complete_reg = regs + 0x2000UL;
/* Link into SYSIO software state. */
sbus->iommu = iommu;
sbus->iommu = info;
printk("SYSIO: UPA portID %x, at %016lx\n",
sbus->portid, regs);
@ -1077,40 +1102,44 @@ static void __init sbus_iommu_init(int __node, struct sbus_bus *sbus)
/* Setup for TSB_SIZE=7, TBW_SIZE=0, MMU_DE=1, MMU_EN=1 */
sbus_iommu_table_init(iommu, IO_TSB_SIZE);
control = upa_readq(iommu->iommu_regs + IOMMU_CONTROL);
control = upa_readq(iommu->iommu_control);
control = ((7UL << 16UL) |
(0UL << 2UL) |
(1UL << 1UL) |
(1UL << 0UL));
upa_writeq(control, iommu->iommu_regs + IOMMU_CONTROL);
upa_writeq(control, iommu->iommu_control);
/* Clean out any cruft in the IOMMU using
* diagnostic accesses.
*/
for (i = 0; i < 16; i++) {
unsigned long dram = iommu->iommu_regs + IOMMU_DRAMDIAG;
unsigned long tag = iommu->iommu_regs + IOMMU_TAGDIAG;
unsigned long dram, tag;
dram = iommu->iommu_control + (IOMMU_DRAMDIAG - IOMMU_CONTROL);
tag = iommu->iommu_control + (IOMMU_TAGDIAG - IOMMU_CONTROL);
dram += (unsigned long)i * 8UL;
tag += (unsigned long)i * 8UL;
upa_writeq(0, dram);
upa_writeq(0, tag);
}
upa_readq(iommu->sbus_control_reg);
upa_readq(iommu->write_complete_reg);
/* Give the TSB to SYSIO. */
upa_writeq(__pa(iommu->page_table), iommu->iommu_regs + IOMMU_TSBBASE);
upa_writeq(__pa(iommu->page_table), iommu->iommu_tsbbase);
/* Setup streaming buffer, DE=1 SB_EN=1 */
control = (1UL << 1UL) | (1UL << 0UL);
upa_writeq(control, iommu->strbuf_regs + STRBUF_CONTROL);
upa_writeq(control, strbuf->strbuf_control);
/* Clear out the tags using diagnostics. */
for (i = 0; i < 16; i++) {
unsigned long ptag, ltag;
ptag = iommu->strbuf_regs + STRBUF_PTAGDIAG;
ltag = iommu->strbuf_regs + STRBUF_LTAGDIAG;
ptag = strbuf->strbuf_control +
(STRBUF_PTAGDIAG - STRBUF_CONTROL);
ltag = strbuf->strbuf_control +
(STRBUF_LTAGDIAG - STRBUF_CONTROL);
ptag += (unsigned long)i * 8UL;
ltag += (unsigned long)i * 8UL;
@ -1119,9 +1148,9 @@ static void __init sbus_iommu_init(int __node, struct sbus_bus *sbus)
}
/* Enable DVMA arbitration for all devices/slots. */
control = upa_readq(iommu->sbus_control_reg);
control = upa_readq(iommu->write_complete_reg);
control |= 0x3fUL;
upa_writeq(control, iommu->sbus_control_reg);
upa_writeq(control, iommu->write_complete_reg);
/* Now some Xfire specific grot... */
if (this_is_starfire)
@ -1133,7 +1162,7 @@ static void __init sbus_iommu_init(int __node, struct sbus_bus *sbus)
void sbus_fill_device_irq(struct sbus_dev *sdev)
{
struct device_node *dp = of_find_node_by_phandle(sdev->prom_node);
struct linux_prom_irqs *irqs;
const struct linux_prom_irqs *irqs;
irqs = of_get_property(dp, "interrupts", NULL);
if (!irqs) {

View File

@ -45,7 +45,7 @@
extern void calibrate_delay(void);
/* 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 phys_cpu_present_map __read_mostly = CPU_MASK_NONE;
@ -81,8 +81,6 @@ void __init smp_store_cpu_info(int id)
struct device_node *dp;
int def;
/* multiplier and counter set by
smp_setup_percpu_timer() */
cpu_data(id).udelay_val = loops_per_jiffy;
cpu_find_by_mid(id, &dp);
@ -125,7 +123,7 @@ void __init smp_store_cpu_info(int id)
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;
@ -140,7 +138,7 @@ void __init smp_callin(void)
__flush_tlb_all();
smp_setup_percpu_timer();
setup_sparc64_timer();
if (cheetah_pcache_forced_on)
cheetah_enable_pcache();
@ -177,8 +175,6 @@ void cpu_panic(void)
panic("SMP bolixed\n");
}
static unsigned long current_tick_offset __read_mostly;
/* This tick register synchronization scheme is taken entirely from
* the ia64 port, see arch/ia64/kernel/smpboot.c for details and credit.
*
@ -261,7 +257,7 @@ void smp_synchronize_tick_client(void)
} else
adj = -delta;
tick_ops->add_tick(adj, current_tick_offset);
tick_ops->add_tick(adj);
}
#if DEBUG_TICK_SYNC
t[i].rt = rt;
@ -1180,117 +1176,15 @@ void smp_penguin_jailcell(int irq, struct pt_regs *regs)
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)
{
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. */
static DEFINE_SPINLOCK(prof_setup_lock);
int setup_profiling_timer(unsigned int multiplier)
{
unsigned long flags;
int i;
if ((!multiplier) || (timer_tick_offset / multiplier) < 1000)
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;
return -EINVAL;
}
static void __init smp_tune_scheduling(void)

View File

@ -212,7 +212,6 @@ EXPORT_SYMBOL(insl);
#ifdef CONFIG_PCI
EXPORT_SYMBOL(ebus_chain);
EXPORT_SYMBOL(isa_chain);
EXPORT_SYMBOL(pci_memspace_mask);
EXPORT_SYMBOL(pci_alloc_consistent);
EXPORT_SYMBOL(pci_free_consistent);
EXPORT_SYMBOL(pci_map_single);

View File

@ -31,6 +31,9 @@
#include <linux/profile.h>
#include <linux/miscdevice.h>
#include <linux/rtc.h>
#include <linux/kernel_stat.h>
#include <linux/clockchips.h>
#include <linux/clocksource.h>
#include <asm/oplib.h>
#include <asm/mostek.h>
@ -60,6 +63,7 @@ static void __iomem *mstk48t59_regs;
static int set_rtc_mmss(unsigned long);
#define TICK_PRIV_BIT (1UL << 63)
#define TICKCMP_IRQ_BIT (1UL << 63)
#ifdef CONFIG_SMP
unsigned long profile_pc(struct pt_regs *regs)
@ -93,21 +97,22 @@ static void tick_disable_protection(void)
: "g2");
}
static void tick_init_tick(unsigned long offset)
static void tick_disable_irq(void)
{
tick_disable_protection();
__asm__ __volatile__(
" rd %%tick, %%g1\n"
" andn %%g1, %1, %%g1\n"
" ba,pt %%xcc, 1f\n"
" add %%g1, %0, %%g1\n"
" nop\n"
" .align 64\n"
"1: wr %%g1, 0x0, %%tick_cmpr\n"
"1: wr %0, 0x0, %%tick_cmpr\n"
" rd %%tick_cmpr, %%g0"
: /* no outputs */
: "r" (offset), "r" (TICK_PRIV_BIT)
: "g1");
: "r" (TICKCMP_IRQ_BIT));
}
static void tick_init_tick(void)
{
tick_disable_protection();
tick_disable_irq();
}
static unsigned long tick_get_tick(void)
@ -121,20 +126,14 @@ static unsigned long tick_get_tick(void)
return ret & ~TICK_PRIV_BIT;
}
static unsigned long tick_get_compare(void)
static int tick_add_compare(unsigned long adj)
{
unsigned long ret;
unsigned long orig_tick, new_tick, new_compare;
__asm__ __volatile__("rd %%tick_cmpr, %0\n\t"
"mov %0, %0"
: "=r" (ret));
__asm__ __volatile__("rd %%tick, %0"
: "=r" (orig_tick));
return ret;
}
static unsigned long tick_add_compare(unsigned long adj)
{
unsigned long new_compare;
orig_tick &= ~TICKCMP_IRQ_BIT;
/* Workaround for Spitfire Errata (#54 I think??), I discovered
* this via Sun BugID 4008234, mentioned in Solaris-2.5.1 patch
@ -145,44 +144,41 @@ static unsigned long tick_add_compare(unsigned long adj)
* at the start of an I-cache line, and perform a dummy
* read back from %tick_cmpr right after writing to it. -DaveM
*/
__asm__ __volatile__("rd %%tick_cmpr, %0\n\t"
"ba,pt %%xcc, 1f\n\t"
" add %0, %1, %0\n\t"
__asm__ __volatile__("ba,pt %%xcc, 1f\n\t"
" add %1, %2, %0\n\t"
".align 64\n"
"1:\n\t"
"wr %0, 0, %%tick_cmpr\n\t"
"rd %%tick_cmpr, %%g0"
: "=&r" (new_compare)
: "r" (adj));
"rd %%tick_cmpr, %%g0\n\t"
: "=r" (new_compare)
: "r" (orig_tick), "r" (adj));
return new_compare;
__asm__ __volatile__("rd %%tick, %0"
: "=r" (new_tick));
new_tick &= ~TICKCMP_IRQ_BIT;
return ((long)(new_tick - (orig_tick+adj))) > 0L;
}
static unsigned long tick_add_tick(unsigned long adj, unsigned long offset)
static unsigned long tick_add_tick(unsigned long adj)
{
unsigned long new_tick, tmp;
unsigned long new_tick;
/* Also need to handle Blackbird bug here too. */
__asm__ __volatile__("rd %%tick, %0\n\t"
"add %0, %2, %0\n\t"
"add %0, %1, %0\n\t"
"wrpr %0, 0, %%tick\n\t"
"andn %0, %4, %1\n\t"
"ba,pt %%xcc, 1f\n\t"
" add %1, %3, %1\n\t"
".align 64\n"
"1:\n\t"
"wr %1, 0, %%tick_cmpr\n\t"
"rd %%tick_cmpr, %%g0"
: "=&r" (new_tick), "=&r" (tmp)
: "r" (adj), "r" (offset), "r" (TICK_PRIV_BIT));
: "=&r" (new_tick)
: "r" (adj));
return new_tick;
}
static struct sparc64_tick_ops tick_operations __read_mostly = {
.name = "tick",
.init_tick = tick_init_tick,
.disable_irq = tick_disable_irq,
.get_tick = tick_get_tick,
.get_compare = tick_get_compare,
.add_tick = tick_add_tick,
.add_compare = tick_add_compare,
.softint_mask = 1UL << 0,
@ -190,7 +186,15 @@ static struct sparc64_tick_ops tick_operations __read_mostly = {
struct sparc64_tick_ops *tick_ops __read_mostly = &tick_operations;
static void stick_init_tick(unsigned long offset)
static void stick_disable_irq(void)
{
__asm__ __volatile__(
"wr %0, 0x0, %%asr25"
: /* no outputs */
: "r" (TICKCMP_IRQ_BIT));
}
static void stick_init_tick(void)
{
/* Writes to the %tick and %stick register are not
* allowed on sun4v. The Hypervisor controls that
@ -198,6 +202,7 @@ static void stick_init_tick(unsigned long offset)
*/
if (tlb_type != hypervisor) {
tick_disable_protection();
tick_disable_irq();
/* Let the user get at STICK too. */
__asm__ __volatile__(
@ -209,14 +214,7 @@ static void stick_init_tick(unsigned long offset)
: "g1", "g2");
}
__asm__ __volatile__(
" rd %%asr24, %%g1\n"
" andn %%g1, %1, %%g1\n"
" add %%g1, %0, %%g1\n"
" wr %%g1, 0x0, %%asr25"
: /* no outputs */
: "r" (offset), "r" (TICK_PRIV_BIT)
: "g1");
stick_disable_irq();
}
static unsigned long stick_get_tick(void)
@ -229,49 +227,43 @@ static unsigned long stick_get_tick(void)
return ret & ~TICK_PRIV_BIT;
}
static unsigned long stick_get_compare(void)
static unsigned long stick_add_tick(unsigned long adj)
{
unsigned long ret;
__asm__ __volatile__("rd %%asr25, %0"
: "=r" (ret));
return ret;
}
static unsigned long stick_add_tick(unsigned long adj, unsigned long offset)
{
unsigned long new_tick, tmp;
unsigned long new_tick;
__asm__ __volatile__("rd %%asr24, %0\n\t"
"add %0, %2, %0\n\t"
"add %0, %1, %0\n\t"
"wr %0, 0, %%asr24\n\t"
"andn %0, %4, %1\n\t"
"add %1, %3, %1\n\t"
"wr %1, 0, %%asr25"
: "=&r" (new_tick), "=&r" (tmp)
: "r" (adj), "r" (offset), "r" (TICK_PRIV_BIT));
: "=&r" (new_tick)
: "r" (adj));
return new_tick;
}
static unsigned long stick_add_compare(unsigned long adj)
static int stick_add_compare(unsigned long adj)
{
unsigned long new_compare;
unsigned long orig_tick, new_tick;
__asm__ __volatile__("rd %%asr25, %0\n\t"
"add %0, %1, %0\n\t"
"wr %0, 0, %%asr25"
: "=&r" (new_compare)
: "r" (adj));
__asm__ __volatile__("rd %%asr24, %0"
: "=r" (orig_tick));
orig_tick &= ~TICKCMP_IRQ_BIT;
return new_compare;
__asm__ __volatile__("wr %0, 0, %%asr25"
: /* no outputs */
: "r" (orig_tick + adj));
__asm__ __volatile__("rd %%asr24, %0"
: "=r" (new_tick));
new_tick &= ~TICKCMP_IRQ_BIT;
return ((long)(new_tick - (orig_tick+adj))) > 0L;
}
static struct sparc64_tick_ops stick_operations __read_mostly = {
.name = "stick",
.init_tick = stick_init_tick,
.disable_irq = stick_disable_irq,
.get_tick = stick_get_tick,
.get_compare = stick_get_compare,
.add_tick = stick_add_tick,
.add_compare = stick_add_compare,
.softint_mask = 1UL << 16,
@ -320,20 +312,6 @@ static unsigned long __hbird_read_stick(void)
return ret;
}
static unsigned long __hbird_read_compare(void)
{
unsigned long low, high;
unsigned long addr = HBIRD_STICKCMP_ADDR;
__asm__ __volatile__("ldxa [%2] %3, %0\n\t"
"add %2, 0x8, %2\n\t"
"ldxa [%2] %3, %1"
: "=&r" (low), "=&r" (high), "=&r" (addr)
: "i" (ASI_PHYS_BYPASS_EC_E), "2" (addr));
return (high << 32UL) | low;
}
static void __hbird_write_stick(unsigned long val)
{
unsigned long low = (val & 0xffffffffUL);
@ -364,10 +342,13 @@ static void __hbird_write_compare(unsigned long val)
"i" (ASI_PHYS_BYPASS_EC_E));
}
static void hbtick_init_tick(unsigned long offset)
static void hbtick_disable_irq(void)
{
unsigned long val;
__hbird_write_compare(TICKCMP_IRQ_BIT);
}
static void hbtick_init_tick(void)
{
tick_disable_protection();
/* XXX This seems to be necessary to 'jumpstart' Hummingbird
@ -377,8 +358,7 @@ static void hbtick_init_tick(unsigned long offset)
*/
__hbird_write_stick(__hbird_read_stick());
val = __hbird_read_stick() & ~TICK_PRIV_BIT;
__hbird_write_compare(val + offset);
hbtick_disable_irq();
}
static unsigned long hbtick_get_tick(void)
@ -386,122 +366,95 @@ static unsigned long hbtick_get_tick(void)
return __hbird_read_stick() & ~TICK_PRIV_BIT;
}
static unsigned long hbtick_get_compare(void)
{
return __hbird_read_compare();
}
static unsigned long hbtick_add_tick(unsigned long adj, unsigned long offset)
static unsigned long hbtick_add_tick(unsigned long adj)
{
unsigned long val;
val = __hbird_read_stick() + adj;
__hbird_write_stick(val);
val &= ~TICK_PRIV_BIT;
__hbird_write_compare(val + offset);
return val;
}
static unsigned long hbtick_add_compare(unsigned long adj)
static int hbtick_add_compare(unsigned long adj)
{
unsigned long val = __hbird_read_compare() + adj;
unsigned long val = __hbird_read_stick();
unsigned long val2;
val &= ~TICK_PRIV_BIT;
val &= ~TICKCMP_IRQ_BIT;
val += adj;
__hbird_write_compare(val);
return val;
val2 = __hbird_read_stick() & ~TICKCMP_IRQ_BIT;
return ((long)(val2 - val)) > 0L;
}
static struct sparc64_tick_ops hbtick_operations __read_mostly = {
.name = "hbtick",
.init_tick = hbtick_init_tick,
.disable_irq = hbtick_disable_irq,
.get_tick = hbtick_get_tick,
.get_compare = hbtick_get_compare,
.add_tick = hbtick_add_tick,
.add_compare = hbtick_add_compare,
.softint_mask = 1UL << 0,
};
/* timer_interrupt() needs to keep up the real-time clock,
* as well as call the "do_timer()" routine every clocktick
*
* NOTE: On SUN5 systems the ticker interrupt comes in using 2
* interrupts, one at level14 and one with softint bit 0.
*/
unsigned long timer_tick_offset __read_mostly;
static unsigned long timer_ticks_per_nsec_quotient __read_mostly;
#define TICK_SIZE (tick_nsec / 1000)
static inline void timer_check_rtc(void)
#define USEC_AFTER 500000
#define USEC_BEFORE 500000
static void sync_cmos_clock(unsigned long dummy);
static DEFINE_TIMER(sync_cmos_timer, sync_cmos_clock, 0, 0);
static void sync_cmos_clock(unsigned long dummy)
{
/* last time the cmos clock got updated */
static long last_rtc_update;
struct timeval now, next;
int fail = 1;
/* Determine when to update the Mostek clock. */
if (ntp_synced() &&
xtime.tv_sec > last_rtc_update + 660 &&
(xtime.tv_nsec / 1000) >= 500000 - ((unsigned) TICK_SIZE) / 2 &&
(xtime.tv_nsec / 1000) <= 500000 + ((unsigned) TICK_SIZE) / 2) {
if (set_rtc_mmss(xtime.tv_sec) == 0)
last_rtc_update = xtime.tv_sec;
else
last_rtc_update = xtime.tv_sec - 600;
/* do it again in 60 s */
}
}
irqreturn_t timer_interrupt(int irq, void *dev_id)
{
unsigned long ticks, compare, pstate;
write_seqlock(&xtime_lock);
do {
#ifndef CONFIG_SMP
profile_tick(CPU_PROFILING);
update_process_times(user_mode(get_irq_regs()));
#endif
do_timer(1);
/* Guarantee that the following sequences execute
* uninterrupted.
/*
* If we have an externally synchronized Linux clock, then update
* CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
* called as close as possible to 500 ms before the new second starts.
* This code is run on a timer. If the clock is set, that timer
* may not expire at the correct time. Thus, we adjust...
*/
if (!ntp_synced())
/*
* Not synced, exit, do not restart a timer (if one is
* running, let it run out).
*/
__asm__ __volatile__("rdpr %%pstate, %0\n\t"
"wrpr %0, %1, %%pstate"
: "=r" (pstate)
: "i" (PSTATE_IE));
return;
compare = tick_ops->add_compare(timer_tick_offset);
ticks = tick_ops->get_tick();
do_gettimeofday(&now);
if (now.tv_usec >= USEC_AFTER - ((unsigned) TICK_SIZE) / 2 &&
now.tv_usec <= USEC_BEFORE + ((unsigned) TICK_SIZE) / 2)
fail = set_rtc_mmss(now.tv_sec);
/* Restore PSTATE_IE. */
__asm__ __volatile__("wrpr %0, 0x0, %%pstate"
: /* no outputs */
: "r" (pstate));
} while (time_after_eq(ticks, compare));
next.tv_usec = USEC_AFTER - now.tv_usec;
if (next.tv_usec <= 0)
next.tv_usec += USEC_PER_SEC;
timer_check_rtc();
if (!fail)
next.tv_sec = 659;
else
next.tv_sec = 0;
write_sequnlock(&xtime_lock);
return IRQ_HANDLED;
if (next.tv_usec >= USEC_PER_SEC) {
next.tv_sec++;
next.tv_usec -= USEC_PER_SEC;
}
mod_timer(&sync_cmos_timer, jiffies + timeval_to_jiffies(&next));
}
#ifdef CONFIG_SMP
void timer_tick_interrupt(struct pt_regs *regs)
void notify_arch_cmos_timer(void)
{
write_seqlock(&xtime_lock);
do_timer(1);
timer_check_rtc();
write_sequnlock(&xtime_lock);
mod_timer(&sync_cmos_timer, jiffies + 1);
}
#endif
/* Kick start a stopped clock (procedure from the Sun NVRAM/hostid FAQ). */
static void __init kick_start_clock(void)
@ -751,7 +704,7 @@ retry:
return -EOPNOTSUPP;
}
static int __init clock_model_matches(char *model)
static int __init clock_model_matches(const char *model)
{
if (strcmp(model, "mk48t02") &&
strcmp(model, "mk48t08") &&
@ -768,7 +721,7 @@ static int __init clock_model_matches(char *model)
static int __devinit clock_probe(struct of_device *op, const struct of_device_id *match)
{
struct device_node *dp = op->node;
char *model = of_get_property(dp, "model", NULL);
const char *model = of_get_property(dp, "model", NULL);
unsigned long size, flags;
void __iomem *regs;
@ -900,7 +853,6 @@ static unsigned long sparc64_init_timers(void)
prop = of_find_property(dp, "stick-frequency", NULL);
}
clock = *(unsigned int *) prop->value;
timer_tick_offset = clock / HZ;
#ifdef CONFIG_SMP
smp_tick_init();
@ -909,26 +861,6 @@ static unsigned long sparc64_init_timers(void)
return clock;
}
static void sparc64_start_timers(void)
{
unsigned long pstate;
/* 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(timer_tick_offset);
/* Restore PSTATE_IE. */
__asm__ __volatile__("wrpr %0, 0x0, %%pstate"
: /* no outputs */
: "r" (pstate));
}
struct freq_table {
unsigned long clock_tick_ref;
unsigned int ref_freq;
@ -975,29 +907,148 @@ static struct notifier_block sparc64_cpufreq_notifier_block = {
#endif /* CONFIG_CPU_FREQ */
static struct time_interpolator sparc64_cpu_interpolator = {
.source = TIME_SOURCE_CPU,
.shift = 16,
.mask = 0xffffffffffffffffLL
static int sparc64_next_event(unsigned long delta,
struct clock_event_device *evt)
{
return tick_ops->add_compare(delta) ? -ETIME : 0;
}
static void sparc64_timer_setup(enum clock_event_mode mode,
struct clock_event_device *evt)
{
switch (mode) {
case CLOCK_EVT_MODE_ONESHOT:
break;
case CLOCK_EVT_MODE_SHUTDOWN:
tick_ops->disable_irq();
break;
case CLOCK_EVT_MODE_PERIODIC:
case CLOCK_EVT_MODE_UNUSED:
WARN_ON(1);
break;
};
}
static struct clock_event_device sparc64_clockevent = {
.features = CLOCK_EVT_FEAT_ONESHOT,
.set_mode = sparc64_timer_setup,
.set_next_event = sparc64_next_event,
.rating = 100,
.shift = 30,
.irq = -1,
};
static DEFINE_PER_CPU(struct clock_event_device, sparc64_events);
void timer_interrupt(int irq, struct pt_regs *regs)
{
struct pt_regs *old_regs = set_irq_regs(regs);
unsigned long tick_mask = tick_ops->softint_mask;
int cpu = smp_processor_id();
struct clock_event_device *evt = &per_cpu(sparc64_events, cpu);
clear_softint(tick_mask);
irq_enter();
kstat_this_cpu.irqs[0]++;
if (unlikely(!evt->event_handler)) {
printk(KERN_WARNING
"Spurious SPARC64 timer interrupt on cpu %d\n", cpu);
} else
evt->event_handler(evt);
irq_exit();
set_irq_regs(old_regs);
}
void __devinit setup_sparc64_timer(void)
{
struct clock_event_device *sevt;
unsigned long pstate;
/* 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();
/* Restore PSTATE_IE. */
__asm__ __volatile__("wrpr %0, 0x0, %%pstate"
: /* no outputs */
: "r" (pstate));
sevt = &__get_cpu_var(sparc64_events);
memcpy(sevt, &sparc64_clockevent, sizeof(*sevt));
sevt->cpumask = cpumask_of_cpu(smp_processor_id());
clockevents_register_device(sevt);
}
#define SPARC64_NSEC_PER_CYC_SHIFT 32UL
static struct clocksource clocksource_tick = {
.rating = 100,
.mask = CLOCKSOURCE_MASK(64),
.shift = 16,
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
};
/* The quotient formula is taken from the IA64 port. */
#define SPARC64_NSEC_PER_CYC_SHIFT 10UL
static void __init setup_clockevent_multiplier(unsigned long hz)
{
unsigned long mult, shift = 32;
while (1) {
mult = div_sc(hz, NSEC_PER_SEC, shift);
if (mult && (mult >> 32UL) == 0UL)
break;
shift--;
}
sparc64_clockevent.shift = shift;
sparc64_clockevent.mult = mult;
}
void __init time_init(void)
{
unsigned long clock = sparc64_init_timers();
sparc64_cpu_interpolator.frequency = clock;
register_time_interpolator(&sparc64_cpu_interpolator);
/* Now that the interpolator is registered, it is
* safe to start the timer ticking.
*/
sparc64_start_timers();
timer_ticks_per_nsec_quotient =
(((NSEC_PER_SEC << SPARC64_NSEC_PER_CYC_SHIFT) +
(clock / 2)) / clock);
clocksource_hz2mult(clock, SPARC64_NSEC_PER_CYC_SHIFT);
clocksource_tick.name = tick_ops->name;
clocksource_tick.mult =
clocksource_hz2mult(clock,
clocksource_tick.shift);
clocksource_tick.read = tick_ops->get_tick;
printk("clocksource: mult[%x] shift[%d]\n",
clocksource_tick.mult, clocksource_tick.shift);
clocksource_register(&clocksource_tick);
sparc64_clockevent.name = tick_ops->name;
setup_clockevent_multiplier(clock);
sparc64_clockevent.max_delta_ns =
clockevent_delta2ns(0x7fffffffffffffff, &sparc64_clockevent);
sparc64_clockevent.min_delta_ns =
clockevent_delta2ns(0xF, &sparc64_clockevent);
printk("clockevent: mult[%lx] shift[%d]\n",
sparc64_clockevent.mult, sparc64_clockevent.shift);
setup_sparc64_timer();
#ifdef CONFIG_CPU_FREQ
cpufreq_register_notifier(&sparc64_cpufreq_notifier_block,
@ -1126,10 +1177,6 @@ static int set_rtc_mmss(unsigned long nowtime)
#define RTC_IS_OPEN 0x01 /* means /dev/rtc is in use */
static unsigned char mini_rtc_status; /* bitmapped status byte. */
/* months start at 0 now */
static unsigned char days_in_mo[] =
{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
#define FEBRUARY 2
#define STARTOFTIME 1970
#define SECDAY 86400L
@ -1278,8 +1325,7 @@ static int mini_rtc_ioctl(struct inode *inode, struct file *file,
case RTC_SET_TIME: /* Set the RTC */
{
int year;
unsigned char leap_yr;
int year, days;
if (!capable(CAP_SYS_TIME))
return -EACCES;
@ -1288,14 +1334,14 @@ static int mini_rtc_ioctl(struct inode *inode, struct file *file,
return -EFAULT;
year = wtime.tm_year + 1900;
leap_yr = ((!(year % 4) && (year % 100)) ||
!(year % 400));
days = month_days[wtime.tm_mon] +
((wtime.tm_mon == 1) && leapyear(year));
if ((wtime.tm_mon < 0 || wtime.tm_mon > 11) || (wtime.tm_mday < 1))
if ((wtime.tm_mon < 0 || wtime.tm_mon > 11) ||
(wtime.tm_mday < 1))
return -EINVAL;
if (wtime.tm_mday < 0 || wtime.tm_mday >
(days_in_mo[wtime.tm_mon] + ((wtime.tm_mon == 1) && leap_yr)))
if (wtime.tm_mday < 0 || wtime.tm_mday > days)
return -EINVAL;
if (wtime.tm_hour < 0 || wtime.tm_hour >= 24 ||

View File

@ -60,11 +60,7 @@ tl0_irq4: BTRAP(0x44)
tl0_irq5: TRAP_IRQ(handler_irq, 5)
tl0_irq6: BTRAP(0x46) BTRAP(0x47) BTRAP(0x48) BTRAP(0x49)
tl0_irq10: BTRAP(0x4a) BTRAP(0x4b) BTRAP(0x4c) BTRAP(0x4d)
#ifndef CONFIG_SMP
tl0_irq14: TRAP_IRQ(timer_irq, 14)
#else
tl0_irq14: TICK_SMP_IRQ
#endif
tl0_irq14: TRAP_IRQ(timer_interrupt, 14)
tl0_irq15: TRAP_IRQ(handler_irq, 15)
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)

View File

@ -122,26 +122,21 @@ static void __init read_obp_memory(const char *property,
size = 0UL;
base = new_base;
}
if (size == 0UL) {
/* If it is empty, simply get rid of it.
* This simplifies the logic of the other
* functions that process these arrays.
*/
memmove(&regs[i], &regs[i + 1],
(ents - i - 1) * sizeof(regs[0]));
i--;
ents--;
continue;
}
regs[i].phys_addr = base;
regs[i].reg_size = size;
}
for (i = 0; i < ents; i++) {
if (regs[i].reg_size == 0UL) {
int j;
for (j = i; j < ents - 1; j++) {
regs[j].phys_addr =
regs[j+1].phys_addr;
regs[j].reg_size =
regs[j+1].reg_size;
}
ents--;
i--;
}
}
*num_ents = ents;
sort(regs, ents, sizeof(struct linux_prom64_registers),
@ -154,15 +149,6 @@ unsigned long *sparc64_valid_addr_bitmap __read_mostly;
unsigned long kern_base __read_mostly;
unsigned long kern_size __read_mostly;
/* get_new_mmu_context() uses "cache + 1". */
DEFINE_SPINLOCK(ctx_alloc_lock);
unsigned long tlb_context_cache = CTX_FIRST_VERSION - 1;
#define CTX_BMAP_SLOTS (1UL << (CTX_NR_BITS - 6))
unsigned long mmu_context_bmap[CTX_BMAP_SLOTS];
/* References to special section boundaries */
extern char _start[], _end[];
/* Initial ramdisk setup */
extern unsigned long sparc_ramdisk_image64;
extern unsigned int sparc_ramdisk_image;
@ -406,19 +392,70 @@ void __kprobes flush_icache_range(unsigned long start, unsigned long end)
if (tlb_type == spitfire) {
unsigned long kaddr;
for (kaddr = start; kaddr < end; kaddr += PAGE_SIZE)
__flush_icache_page(__get_phys(kaddr));
/* This code only runs on Spitfire cpus so this is
* why we can assume _PAGE_PADDR_4U.
*/
for (kaddr = start; kaddr < end; kaddr += PAGE_SIZE) {
unsigned long paddr, mask = _PAGE_PADDR_4U;
if (kaddr >= PAGE_OFFSET)
paddr = kaddr & mask;
else {
pgd_t *pgdp = pgd_offset_k(kaddr);
pud_t *pudp = pud_offset(pgdp, kaddr);
pmd_t *pmdp = pmd_offset(pudp, kaddr);
pte_t *ptep = pte_offset_kernel(pmdp, kaddr);
paddr = pte_val(*ptep) & mask;
}
__flush_icache_page(paddr);
}
}
}
void show_mem(void)
{
printk("Mem-info:\n");
unsigned long total = 0, reserved = 0;
unsigned long shared = 0, cached = 0;
pg_data_t *pgdat;
printk(KERN_INFO "Mem-info:\n");
show_free_areas();
printk("Free swap: %6ldkB\n",
printk(KERN_INFO "Free swap: %6ldkB\n",
nr_swap_pages << (PAGE_SHIFT-10));
printk("%ld pages of RAM\n", num_physpages);
printk("%lu free pages\n", nr_free_pages());
for_each_online_pgdat(pgdat) {
unsigned long i, flags;
pgdat_resize_lock(pgdat, &flags);
for (i = 0; i < pgdat->node_spanned_pages; i++) {
struct page *page = pgdat_page_nr(pgdat, i);
total++;
if (PageReserved(page))
reserved++;
else if (PageSwapCache(page))
cached++;
else if (page_count(page))
shared += page_count(page) - 1;
}
pgdat_resize_unlock(pgdat, &flags);
}
printk(KERN_INFO "%lu pages of RAM\n", total);
printk(KERN_INFO "%lu reserved pages\n", reserved);
printk(KERN_INFO "%lu pages shared\n", shared);
printk(KERN_INFO "%lu pages swap cached\n", cached);
printk(KERN_INFO "%lu pages dirty\n",
global_page_state(NR_FILE_DIRTY));
printk(KERN_INFO "%lu pages writeback\n",
global_page_state(NR_WRITEBACK));
printk(KERN_INFO "%lu pages mapped\n",
global_page_state(NR_FILE_MAPPED));
printk(KERN_INFO "%lu pages slab\n",
global_page_state(NR_SLAB_RECLAIMABLE) +
global_page_state(NR_SLAB_UNRECLAIMABLE));
printk(KERN_INFO "%lu pages pagetables\n",
global_page_state(NR_PAGETABLE));
}
void mmu_info(struct seq_file *m)
@ -658,6 +695,13 @@ void __flush_dcache_range(unsigned long start, unsigned long end)
}
#endif /* DCACHE_ALIASING_POSSIBLE */
/* get_new_mmu_context() uses "cache + 1". */
DEFINE_SPINLOCK(ctx_alloc_lock);
unsigned long tlb_context_cache = CTX_FIRST_VERSION - 1;
#define MAX_CTX_NR (1UL << CTX_NR_BITS)
#define CTX_BMAP_SLOTS BITS_TO_LONGS(MAX_CTX_NR)
DECLARE_BITMAP(mmu_context_bmap, MAX_CTX_NR);
/* Caller does TLB context flushing on local CPU if necessary.
* The caller also ensures that CTX_VALID(mm->context) is false.
*
@ -717,95 +761,6 @@ out:
smp_new_mmu_context_version();
}
void sparc_ultra_dump_itlb(void)
{
int slot;
if (tlb_type == spitfire) {
printk ("Contents of itlb: ");
for (slot = 0; slot < 14; slot++) printk (" ");
printk ("%2x:%016lx,%016lx\n",
0,
spitfire_get_itlb_tag(0), spitfire_get_itlb_data(0));
for (slot = 1; slot < 64; slot+=3) {
printk ("%2x:%016lx,%016lx %2x:%016lx,%016lx %2x:%016lx,%016lx\n",
slot,
spitfire_get_itlb_tag(slot), spitfire_get_itlb_data(slot),
slot+1,
spitfire_get_itlb_tag(slot+1), spitfire_get_itlb_data(slot+1),
slot+2,
spitfire_get_itlb_tag(slot+2), spitfire_get_itlb_data(slot+2));
}
} else if (tlb_type == cheetah || tlb_type == cheetah_plus) {
printk ("Contents of itlb0:\n");
for (slot = 0; slot < 16; slot+=2) {
printk ("%2x:%016lx,%016lx %2x:%016lx,%016lx\n",
slot,
cheetah_get_litlb_tag(slot), cheetah_get_litlb_data(slot),
slot+1,
cheetah_get_litlb_tag(slot+1), cheetah_get_litlb_data(slot+1));
}
printk ("Contents of itlb2:\n");
for (slot = 0; slot < 128; slot+=2) {
printk ("%2x:%016lx,%016lx %2x:%016lx,%016lx\n",
slot,
cheetah_get_itlb_tag(slot), cheetah_get_itlb_data(slot),
slot+1,
cheetah_get_itlb_tag(slot+1), cheetah_get_itlb_data(slot+1));
}
}
}
void sparc_ultra_dump_dtlb(void)
{
int slot;
if (tlb_type == spitfire) {
printk ("Contents of dtlb: ");
for (slot = 0; slot < 14; slot++) printk (" ");
printk ("%2x:%016lx,%016lx\n", 0,
spitfire_get_dtlb_tag(0), spitfire_get_dtlb_data(0));
for (slot = 1; slot < 64; slot+=3) {
printk ("%2x:%016lx,%016lx %2x:%016lx,%016lx %2x:%016lx,%016lx\n",
slot,
spitfire_get_dtlb_tag(slot), spitfire_get_dtlb_data(slot),
slot+1,
spitfire_get_dtlb_tag(slot+1), spitfire_get_dtlb_data(slot+1),
slot+2,
spitfire_get_dtlb_tag(slot+2), spitfire_get_dtlb_data(slot+2));
}
} else if (tlb_type == cheetah || tlb_type == cheetah_plus) {
printk ("Contents of dtlb0:\n");
for (slot = 0; slot < 16; slot+=2) {
printk ("%2x:%016lx,%016lx %2x:%016lx,%016lx\n",
slot,
cheetah_get_ldtlb_tag(slot), cheetah_get_ldtlb_data(slot),
slot+1,
cheetah_get_ldtlb_tag(slot+1), cheetah_get_ldtlb_data(slot+1));
}
printk ("Contents of dtlb2:\n");
for (slot = 0; slot < 512; slot+=2) {
printk ("%2x:%016lx,%016lx %2x:%016lx,%016lx\n",
slot,
cheetah_get_dtlb_tag(slot, 2), cheetah_get_dtlb_data(slot, 2),
slot+1,
cheetah_get_dtlb_tag(slot+1, 2), cheetah_get_dtlb_data(slot+1, 2));
}
if (tlb_type == cheetah_plus) {
printk ("Contents of dtlb3:\n");
for (slot = 0; slot < 512; slot+=2) {
printk ("%2x:%016lx,%016lx %2x:%016lx,%016lx\n",
slot,
cheetah_get_dtlb_tag(slot, 3), cheetah_get_dtlb_data(slot, 3),
slot+1,
cheetah_get_dtlb_tag(slot+1, 3), cheetah_get_dtlb_data(slot+1, 3));
}
}
}
}
extern unsigned long cmdline_memory_size;
/* Find a free area for the bootmem map, avoiding the kernel image
* and the initial ramdisk.
*/
@ -815,8 +770,8 @@ static unsigned long __init choose_bootmap_pfn(unsigned long start_pfn,
unsigned long avoid_start, avoid_end, bootmap_size;
int i;
bootmap_size = ((end_pfn - start_pfn) + 7) / 8;
bootmap_size = ALIGN(bootmap_size, sizeof(long));
bootmap_size = bootmem_bootmap_pages(end_pfn - start_pfn);
bootmap_size <<= PAGE_SHIFT;
avoid_start = avoid_end = 0;
#ifdef CONFIG_BLK_DEV_INITRD
@ -983,6 +938,20 @@ static void __init trim_pavail(unsigned long *cur_size_p,
}
}
/* About pages_avail, this is the value we will use to calculate
* the zholes_size[] argument given to free_area_init_node(). The
* page allocator uses this to calculate nr_kernel_pages,
* nr_all_pages and zone->present_pages. On NUMA it is used
* to calculate zone->min_unmapped_pages and zone->min_slab_pages.
*
* So this number should really be set to what the page allocator
* actually ends up with. This means:
* 1) It should include bootmem map pages, we'll release those.
* 2) It should not include the kernel image, except for the
* __init sections which we will also release.
* 3) It should include the initrd image, since we'll release
* that too.
*/
static unsigned long __init bootmem_init(unsigned long *pages_avail,
unsigned long phys_base)
{
@ -1069,7 +1038,6 @@ static unsigned long __init bootmem_init(unsigned long *pages_avail,
initrd_start, initrd_end);
#endif
reserve_bootmem(initrd_start, size);
*pages_avail -= PAGE_ALIGN(size) >> PAGE_SHIFT;
initrd_start += PAGE_OFFSET;
initrd_end += PAGE_OFFSET;
@ -1082,6 +1050,11 @@ static unsigned long __init bootmem_init(unsigned long *pages_avail,
reserve_bootmem(kern_base, kern_size);
*pages_avail -= PAGE_ALIGN(kern_size) >> PAGE_SHIFT;
/* Add back in the initmem pages. */
size = ((unsigned long)(__init_end) & PAGE_MASK) -
PAGE_ALIGN((unsigned long)__init_begin);
*pages_avail += size >> PAGE_SHIFT;
/* Reserve the bootmem map. We do not account for it
* in pages_avail because we will release that memory
* in free_all_bootmem.
@ -1092,7 +1065,6 @@ static unsigned long __init bootmem_init(unsigned long *pages_avail,
(bootmap_pfn << PAGE_SHIFT), size);
#endif
reserve_bootmem((bootmap_pfn << PAGE_SHIFT), size);
*pages_avail -= PAGE_ALIGN(size) >> PAGE_SHIFT;
for (i = 0; i < pavail_ents; i++) {
unsigned long start_pfn, end_pfn;
@ -1584,6 +1556,10 @@ void __init mem_init(void)
#ifdef CONFIG_DEBUG_BOOTMEM
prom_printf("mem_init: Calling free_all_bootmem().\n");
#endif
/* We subtract one to account for the mem_map_zero page
* allocated below.
*/
totalram_pages = num_physpages = free_all_bootmem() - 1;
/*
@ -1883,62 +1859,6 @@ static unsigned long kern_large_tte(unsigned long paddr)
return val | paddr;
}
/*
* Translate PROM's mapping we capture at boot time into physical address.
* The second parameter is only set from prom_callback() invocations.
*/
unsigned long prom_virt_to_phys(unsigned long promva, int *error)
{
unsigned long mask;
int i;
mask = _PAGE_PADDR_4U;
if (tlb_type == hypervisor)
mask = _PAGE_PADDR_4V;
for (i = 0; i < prom_trans_ents; i++) {
struct linux_prom_translation *p = &prom_trans[i];
if (promva >= p->virt &&
promva < (p->virt + p->size)) {
unsigned long base = p->data & mask;
if (error)
*error = 0;
return base + (promva & (8192 - 1));
}
}
if (error)
*error = 1;
return 0UL;
}
/* XXX We should kill off this ugly thing at so me point. XXX */
unsigned long sun4u_get_pte(unsigned long addr)
{
pgd_t *pgdp;
pud_t *pudp;
pmd_t *pmdp;
pte_t *ptep;
unsigned long mask = _PAGE_PADDR_4U;
if (tlb_type == hypervisor)
mask = _PAGE_PADDR_4V;
if (addr >= PAGE_OFFSET)
return addr & mask;
if ((addr >= LOW_OBP_ADDRESS) && (addr < HI_OBP_ADDRESS))
return prom_virt_to_phys(addr, NULL);
pgdp = pgd_offset_k(addr);
pudp = pud_offset(pgdp, addr);
pmdp = pmd_offset(pudp, addr);
ptep = pte_offset_kernel(pmdp, addr);
return pte_val(*ptep) & mask;
}
/* If not locked, zap it. */
void __flush_tlb_all(void)
{

View File

@ -224,7 +224,8 @@ static char *serial(char *buffer, int sz)
*buffer = 0;
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 (len > sz)

View File

@ -2,6 +2,6 @@
# 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
lib-$(CONFIG_PCI) += pci-auto.o

View File

@ -1,32 +0,0 @@
/*
* 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;
}

View File

@ -39,7 +39,7 @@ MODULE_VERSION("2.0");
static LIST_HEAD(device_list);
struct uflash_dev {
char *name; /* device name */
const char *name; /* device name */
struct map_info map; /* mtd map info */
struct mtd_info *mtd; /* mtd info */
};
@ -80,7 +80,7 @@ int uflash_devinit(struct linux_ebus_device *edev, struct device_node *dp)
up->name = of_get_property(dp, "model", NULL);
if (up->name && 0 < strlen(up->name))
up->map.name = up->name;
up->map.name = (char *)up->name;
up->map.phys = res->start;

View File

@ -64,11 +64,9 @@
#include <asm/uaccess.h>
#include <asm/irq.h>
#ifdef __sparc__
#ifdef CONFIG_SPARC
#include <asm/idprom.h>
#include <asm/openprom.h>
#include <asm/oplib.h>
#include <asm/pbm.h>
#include <asm/prom.h>
#endif
#ifdef CONFIG_PPC_PMAC
@ -2846,7 +2844,7 @@ static int gem_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
return rc;
}
#if (!defined(__sparc__) && !defined(CONFIG_PPC_PMAC))
#if (!defined(CONFIG_SPARC) && !defined(CONFIG_PPC_PMAC))
/* Fetch MAC address from vital product data of PCI ROM. */
static int find_eth_addr_in_vpd(void __iomem *rom_base, int len, unsigned char *dev_addr)
{
@ -2901,36 +2899,19 @@ static void get_gem_mac_nonobp(struct pci_dev *pdev, unsigned char *dev_addr)
static int __devinit gem_get_device_address(struct gem *gp)
{
#if defined(__sparc__) || defined(CONFIG_PPC_PMAC)
#if defined(CONFIG_SPARC) || defined(CONFIG_PPC_PMAC)
struct net_device *dev = gp->dev;
#endif
#if defined(__sparc__)
struct pci_dev *pdev = gp->pdev;
struct pcidev_cookie *pcp = pdev->sysdata;
int use_idprom = 1;
if (pcp != NULL) {
unsigned char *addr;
int len;
addr = of_get_property(pcp->prom_node, "local-mac-address",
&len);
if (addr && len == 6) {
use_idprom = 0;
memcpy(dev->dev_addr, addr, 6);
}
}
if (use_idprom)
memcpy(dev->dev_addr, idprom->id_ethaddr, 6);
#elif defined(CONFIG_PPC_PMAC)
const unsigned char *addr;
addr = get_property(gp->of_node, "local-mac-address", NULL);
if (addr == NULL) {
#ifdef CONFIG_SPARC
addr = idprom->id_ethaddr;
#else
printk("\n");
printk(KERN_ERR "%s: can't get mac-address\n", dev->name);
return -1;
#endif
}
memcpy(dev->dev_addr, addr, 6);
#else
@ -3088,7 +3069,7 @@ static int __devinit gem_init_one(struct pci_dev *pdev,
/* On Apple, we want a reference to the Open Firmware device-tree
* node. We use it for clock control.
*/
#ifdef CONFIG_PPC_PMAC
#if defined(CONFIG_PPC_PMAC) || defined(CONFIG_SPARC)
gp->of_node = pci_device_to_OF_node(pdev);
#endif

View File

@ -1025,7 +1025,7 @@ struct gem {
struct pci_dev *pdev;
struct net_device *dev;
#ifdef CONFIG_PPC_PMAC
#if defined(CONFIG_PPC_PMAC) || defined(CONFIG_SPARC)
struct device_node *of_node;
#endif
};

View File

@ -55,9 +55,6 @@
#ifdef CONFIG_PCI
#include <linux/pci.h>
#ifdef CONFIG_SPARC
#include <asm/pbm.h>
#endif
#endif
#include "sunhme.h"
@ -2701,7 +2698,7 @@ static int __devinit happy_meal_sbus_probe_one(struct sbus_dev *sdev, int is_qfe
dev->dev_addr[i] = macaddr[i];
macaddr[5]++;
} else {
unsigned char *addr;
const unsigned char *addr;
int len;
addr = of_get_property(dp, "local-mac-address", &len);
@ -2983,7 +2980,7 @@ static int __devinit happy_meal_pci_probe(struct pci_dev *pdev,
{
struct quattro *qp = NULL;
#ifdef CONFIG_SPARC
struct pcidev_cookie *pcp;
struct device_node *dp;
#endif
struct happy_meal *hp;
struct net_device *dev;
@ -2995,13 +2992,8 @@ static int __devinit happy_meal_pci_probe(struct pci_dev *pdev,
/* Now make sure pci_dev cookie is there. */
#ifdef CONFIG_SPARC
pcp = pdev->sysdata;
if (pcp == NULL) {
printk(KERN_ERR "happymeal(PCI): Some PCI device info missing\n");
return -ENODEV;
}
strcpy(prom_name, pcp->prom_node->name);
dp = pci_device_to_OF_node(pdev);
strcpy(prom_name, dp->name);
#else
if (is_quattro_p(pdev))
strcpy(prom_name, "SUNW,qfe");
@ -3078,11 +3070,11 @@ static int __devinit happy_meal_pci_probe(struct pci_dev *pdev,
macaddr[5]++;
} else {
#ifdef CONFIG_SPARC
unsigned char *addr;
const unsigned char *addr;
int len;
if (qfe_slot != -1 &&
(addr = of_get_property(pcp->prom_node,
(addr = of_get_property(dp,
"local-mac-address", &len)) != NULL
&& len == 6) {
memcpy(dev->dev_addr, addr, 6);
@ -3102,7 +3094,7 @@ static int __devinit happy_meal_pci_probe(struct pci_dev *pdev,
hp->tcvregs = (hpreg_base + 0x7000UL);
#ifdef CONFIG_SPARC
hp->hm_revision = of_getintprop_default(pcp->prom_node, "hm-rev", 0xff);
hp->hm_revision = of_getintprop_default(dp, "hm-rev", 0xff);
if (hp->hm_revision == 0xff) {
unsigned char prev;
@ -3297,7 +3289,7 @@ static int __devinit hme_sbus_probe(struct of_device *dev, const struct of_devic
{
struct sbus_dev *sdev = to_sbus_device(&dev->dev);
struct device_node *dp = dev->node;
char *model = of_get_property(dp, "model", NULL);
const char *model = of_get_property(dp, "model", NULL);
int is_qfe = (match->data != NULL);
if (!is_qfe && model && !strcmp(model, "SUNW,sbus-qfe"))

View File

@ -47,10 +47,9 @@
#include <asm/byteorder.h>
#include <asm/uaccess.h>
#ifdef CONFIG_SPARC64
#ifdef CONFIG_SPARC
#include <asm/idprom.h>
#include <asm/oplib.h>
#include <asm/pbm.h>
#include <asm/prom.h>
#endif
#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
@ -10987,24 +10986,20 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
return err;
}
#ifdef CONFIG_SPARC64
#ifdef CONFIG_SPARC
static int __devinit tg3_get_macaddr_sparc(struct tg3 *tp)
{
struct net_device *dev = tp->dev;
struct pci_dev *pdev = tp->pdev;
struct pcidev_cookie *pcp = pdev->sysdata;
struct device_node *dp = pci_device_to_OF_node(pdev);
const unsigned char *addr;
int len;
if (pcp != NULL) {
unsigned char *addr;
int len;
addr = of_get_property(pcp->prom_node, "local-mac-address",
&len);
if (addr && len == 6) {
memcpy(dev->dev_addr, addr, 6);
memcpy(dev->perm_addr, dev->dev_addr, 6);
return 0;
}
addr = of_get_property(dp, "local-mac-address", &len);
if (addr && len == 6) {
memcpy(dev->dev_addr, addr, 6);
memcpy(dev->perm_addr, dev->dev_addr, 6);
return 0;
}
return -ENODEV;
}
@ -11025,7 +11020,7 @@ static int __devinit tg3_get_device_address(struct tg3 *tp)
u32 hi, lo, mac_offset;
int addr_ok = 0;
#ifdef CONFIG_SPARC64
#ifdef CONFIG_SPARC
if (!tg3_get_macaddr_sparc(tp))
return 0;
#endif

View File

@ -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. */
#if defined(__alpha__) || defined(__arm__) || defined(__hppa__) \
|| defined(__sparc__) || defined(__ia64__) \
|| defined(CONFIG_SPARC) || defined(__ia64__) \
|| defined(__sh__) || defined(__mips__)
static int rx_copybreak = 1518;
#else

View File

@ -1160,7 +1160,7 @@ de4x5_hw_init(struct net_device *dev, u_long iobase, struct device *gendev)
sprintf(lp->adapter_name,"%s (%s)", name, gendev->bus_id);
lp->dma_size = (NUM_RX_DESC + NUM_TX_DESC) * sizeof(struct de4x5_desc);
#if defined(__alpha__) || defined(__powerpc__) || defined(__sparc_v9__) || defined(DE4X5_DO_MEMCPY)
#if defined(__alpha__) || defined(__powerpc__) || defined(CONFIG_SPARC) || defined(DE4X5_DO_MEMCPY)
lp->dma_size += RX_BUFF_SZ * NUM_RX_DESC + DE4X5_ALIGN;
#endif
lp->rx_ring = dma_alloc_coherent(gendev, lp->dma_size,
@ -1175,7 +1175,7 @@ de4x5_hw_init(struct net_device *dev, u_long iobase, struct device *gendev)
** Set up the RX descriptor ring (Intels)
** Allocate contiguous receive buffers, long word aligned (Alphas)
*/
#if !defined(__alpha__) && !defined(__powerpc__) && !defined(__sparc_v9__) && !defined(DE4X5_DO_MEMCPY)
#if !defined(__alpha__) && !defined(__powerpc__) && !defined(CONFIG_SPARC) && !defined(DE4X5_DO_MEMCPY)
for (i=0; i<NUM_RX_DESC; i++) {
lp->rx_ring[i].status = 0;
lp->rx_ring[i].des1 = cpu_to_le32(RX_BUFF_SZ);
@ -1252,11 +1252,7 @@ de4x5_hw_init(struct net_device *dev, u_long iobase, struct device *gendev)
mii_get_phy(dev);
}
#ifndef __sparc_v9__
printk(" and requires IRQ%d (provided by %s).\n", dev->irq,
#else
printk(" and requires IRQ%x (provided by %s).\n", dev->irq,
#endif
((lp->bus == PCI) ? "PCI BIOS" : "EISA CNFG"));
}
@ -3627,7 +3623,7 @@ de4x5_alloc_rx_buff(struct net_device *dev, int index, int len)
struct de4x5_private *lp = netdev_priv(dev);
struct sk_buff *p;
#if !defined(__alpha__) && !defined(__powerpc__) && !defined(__sparc_v9__) && !defined(DE4X5_DO_MEMCPY)
#if !defined(__alpha__) && !defined(__powerpc__) && !defined(CONFIG_SPARC) && !defined(DE4X5_DO_MEMCPY)
struct sk_buff *ret;
u_long i=0, tmp;

View File

@ -36,8 +36,8 @@
#include <asm/unaligned.h>
#include <asm/uaccess.h>
#ifdef __sparc__
#include <asm/pbm.h>
#ifdef CONFIG_SPARC
#include <asm/prom.h>
#endif
static char version[] __devinitdata =
@ -67,7 +67,7 @@ const char * const medianame[32] = {
/* Set the copy breakpoint for the copy-only-tiny-buffer Rx structure. */
#if defined(__alpha__) || defined(__arm__) || defined(__hppa__) \
|| defined(__sparc__) || defined(__ia64__) \
|| defined(CONFIG_SPARC) || defined(__ia64__) \
|| defined(__sh__) || defined(__mips__)
static int rx_copybreak = 1518;
#else
@ -91,7 +91,7 @@ static int rx_copybreak = 100;
static int csr0 = 0x01A00000 | 0xE000;
#elif defined(__i386__) || defined(__powerpc__) || defined(__x86_64__)
static int csr0 = 0x01A00000 | 0x8000;
#elif defined(__sparc__) || defined(__hppa__)
#elif defined(CONFIG_SPARC) || defined(__hppa__)
/* The UltraSparc PCI controllers will disconnect at every 64-byte
* crossing anyways so it makes no sense to tell Tulip to burst
* any more than that.
@ -1315,7 +1315,7 @@ static int __devinit tulip_init_one (struct pci_dev *pdev,
/* DM9102A has troubles with MRM & clear reserved bits 24:22, 20, 16, 7:1 */
if (tulip_uli_dm_quirk(pdev)) {
csr0 &= ~0x01f100ff;
#if defined(__sparc__)
#if defined(CONFIG_SPARC)
csr0 = (csr0 & ~0xff00) | 0xe000;
#endif
}
@ -1535,23 +1535,19 @@ static int __devinit tulip_init_one (struct pci_dev *pdev,
Many PCI BIOSes also incorrectly report the IRQ line, so we correct
that here as well. */
if (sum == 0 || sum == 6*0xff) {
#if defined(__sparc__)
struct pcidev_cookie *pcp = pdev->sysdata;
#if defined(CONFIG_SPARC)
struct device_node *dp = pci_device_to_OF_node(pdev);
const unsigned char *addr;
int len;
#endif
eeprom_missing = 1;
for (i = 0; i < 5; i++)
dev->dev_addr[i] = last_phys_addr[i];
dev->dev_addr[i] = last_phys_addr[i] + 1;
#if defined(__sparc__)
if (pcp) {
unsigned char *addr;
int len;
addr = of_get_property(pcp->prom_node,
"local-mac-address", &len);
if (addr && len == 6)
memcpy(dev->dev_addr, addr, 6);
}
#if defined(CONFIG_SPARC)
addr = of_get_property(dp, "local-mac-address", &len);
if (addr && len == 6)
memcpy(dev->dev_addr, addr, 6);
#endif
#if defined(__i386__) || defined(__x86_64__) /* Patch up x86 BIOS bug. */
if (last_irq)

View File

@ -902,7 +902,7 @@ static void init_registers(struct net_device *dev)
}
#elif defined(__powerpc__) || defined(__i386__) || defined(__alpha__) || defined(__ia64__) || defined(__x86_64__)
i |= 0xE000;
#elif defined(__sparc__) || defined (CONFIG_PARISC)
#elif defined(CONFIG_SPARC) || defined (CONFIG_PARISC)
i |= 0x4800;
#else
#warning Processor architecture undefined

View File

@ -65,7 +65,7 @@ static int rx_copybreak = 100;
static int csr0 = 0x01A00000 | 0xE000;
#elif defined(__powerpc__)
static int csr0 = 0x01B00000 | 0x8000;
#elif defined(__sparc__)
#elif defined(CONFIG_SPARC)
static int csr0 = 0x01B00080 | 0x8000;
#elif defined(__i386__)
static int csr0 = 0x01A00000 | 0x8000;

View File

@ -726,7 +726,7 @@ static struct miscdevice envctrl_dev = {
* Return: None.
*/
static void envctrl_set_mon(struct i2c_child_t *pchild,
char *chnl_desc,
const char *chnl_desc,
int chnl_no)
{
/* Firmware only has temperature type. It does not distinguish
@ -763,8 +763,8 @@ static void envctrl_set_mon(struct i2c_child_t *pchild,
static void envctrl_init_adc(struct i2c_child_t *pchild, struct device_node *dp)
{
int i = 0, len;
char *pos;
unsigned int *pval;
const char *pos;
const unsigned int *pval;
/* Firmware describe channels into a stream separated by a '\0'. */
pos = of_get_property(dp, "channels-description", &len);
@ -859,7 +859,7 @@ static void envctrl_init_i2c_child(struct linux_ebus_child *edev_child,
{
int len, i, tbls_size = 0;
struct device_node *dp = edev_child->prom_node;
void *pval;
const void *pval;
/* Get device address. */
pval = of_get_property(dp, "reg", &len);

View File

@ -190,7 +190,7 @@ static int __init flash_init(void)
}
if (!sdev) {
#ifdef CONFIG_PCI
struct linux_prom_registers *ebus_regs;
const struct linux_prom_registers *ebus_regs;
for_each_ebus(ebus) {
for_each_ebusdev(edev, ebus) {

View File

@ -44,7 +44,6 @@
#include <asm/openpromio.h>
#ifdef CONFIG_PCI
#include <linux/pci.h>
#include <asm/pbm.h>
#endif
MODULE_AUTHOR("Thomas K. Dyas (tdyas@noc.rutgers.edu) and Eddie C. Dost (ecd@skynet.be)");
@ -141,7 +140,7 @@ static int copyout(void __user *info, struct openpromio *opp, int len)
static int opromgetprop(void __user *argp, struct device_node *dp, struct openpromio *op, int bufsize)
{
void *pval;
const void *pval;
int len;
if (!dp ||
@ -248,18 +247,17 @@ static int oprompci2node(void __user *argp, struct device_node *dp, struct openp
if (bufsize >= 2*sizeof(int)) {
#ifdef CONFIG_PCI
struct pci_dev *pdev;
struct pcidev_cookie *pcp;
struct device_node *dp;
pdev = pci_get_bus_and_slot (((int *) op->oprom_array)[0],
((int *) op->oprom_array)[1]);
pcp = pdev->sysdata;
if (pcp != NULL) {
dp = pcp->prom_node;
data->current_node = dp;
*((int *)op->oprom_array) = dp->node;
op->oprom_size = sizeof(int);
err = copyout(argp, op, bufsize + sizeof(int));
}
dp = pci_device_to_OF_node(pdev);
data->current_node = dp;
*((int *)op->oprom_array) = dp->node;
op->oprom_size = sizeof(int);
err = copyout(argp, op, bufsize + sizeof(int));
pci_dev_put(pdev);
#endif
}
@ -410,7 +408,7 @@ static int opiocget(void __user *argp, DATA *data)
struct opiocdesc op;
struct device_node *dp;
char *str;
void *pval;
const void *pval;
int err, len;
if (copy_from_user(&op, argp, sizeof(op)))

View File

@ -35,7 +35,7 @@ struct sbus_bus *sbus_root;
static void __init fill_sbus_device(struct device_node *dp, struct sbus_dev *sdev)
{
unsigned long base;
void *pval;
const void *pval;
int len, err;
sdev->prom_node = dp->node;
@ -86,7 +86,7 @@ static void __init fill_sbus_device(struct device_node *dp, struct sbus_dev *sde
static void __init sbus_bus_ranges_init(struct device_node *dp, struct sbus_bus *sbus)
{
void *pval;
const void *pval;
int len;
pval = of_get_property(dp, "ranges", &len);

View File

@ -1763,9 +1763,15 @@ config SUN3X_ESP
The ESP was an on-board SCSI controller used on Sun 3/80
machines. Say Y here to compile in support for it.
config SCSI_ESP_CORE
tristate "ESP Scsi Driver Core"
depends on SCSI
select SCSI_SPI_ATTRS
config SCSI_SUNESP
tristate "Sparc ESP Scsi Driver"
depends on SBUS && SCSI
select SCSI_ESP_CORE
help
This is the driver for the Sun ESP SCSI host adapter. The ESP
chipset is present in most SPARC SBUS-based computers.

View File

@ -106,7 +106,8 @@ obj-$(CONFIG_MEGARAID_LEGACY) += megaraid.o
obj-$(CONFIG_MEGARAID_NEWGEN) += megaraid/
obj-$(CONFIG_MEGARAID_SAS) += megaraid/
obj-$(CONFIG_SCSI_ACARD) += atp870u.o
obj-$(CONFIG_SCSI_SUNESP) += esp.o
obj-$(CONFIG_SCSI_ESP_CORE) += esp_scsi.o
obj-$(CONFIG_SCSI_SUNESP) += sun_esp.o
obj-$(CONFIG_SCSI_GDTH) += gdth.o
obj-$(CONFIG_SCSI_INITIO) += initio.o
obj-$(CONFIG_SCSI_INIA100) += a100u2w.o

File diff suppressed because it is too large Load Diff

View File

@ -1,406 +0,0 @@
/* $Id: esp.h,v 1.29 2001/12/11 04:55:47 davem Exp $
* esp.h: Defines and structures for the Sparc ESP (Enhanced SCSI
* Processor) driver under Linux.
*
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
*/
#ifndef _SPARC_ESP_H
#define _SPARC_ESP_H
/* For dvma controller register definitions. */
#include <asm/dma.h>
/* The ESP SCSI controllers have their register sets in three
* "classes":
*
* 1) Registers which are both read and write.
* 2) Registers which are read only.
* 3) Registers which are write only.
*
* Yet, they all live within the same IO space.
*/
/* All the ESP registers are one byte each and are accessed longwords
* apart with a big-endian ordering to the bytes.
*/
/* Access Description Offset */
#define ESP_TCLOW 0x00UL /* rw Low bits of the transfer count 0x00 */
#define ESP_TCMED 0x04UL /* rw Mid bits of the transfer count 0x04 */
#define ESP_FDATA 0x08UL /* rw FIFO data bits 0x08 */
#define ESP_CMD 0x0cUL /* rw SCSI command bits 0x0c */
#define ESP_STATUS 0x10UL /* ro ESP status register 0x10 */
#define ESP_BUSID ESP_STATUS /* wo Bus ID for select/reselect 0x10 */
#define ESP_INTRPT 0x14UL /* ro Kind of interrupt 0x14 */
#define ESP_TIMEO ESP_INTRPT /* wo Timeout value for select/resel 0x14 */
#define ESP_SSTEP 0x18UL /* ro Sequence step register 0x18 */
#define ESP_STP ESP_SSTEP /* wo Transfer period per sync 0x18 */
#define ESP_FFLAGS 0x1cUL /* ro Bits of current FIFO info 0x1c */
#define ESP_SOFF ESP_FFLAGS /* wo Sync offset 0x1c */
#define ESP_CFG1 0x20UL /* rw First configuration register 0x20 */
#define ESP_CFACT 0x24UL /* wo Clock conversion factor 0x24 */
#define ESP_STATUS2 ESP_CFACT /* ro HME status2 register 0x24 */
#define ESP_CTEST 0x28UL /* wo Chip test register 0x28 */
#define ESP_CFG2 0x2cUL /* rw Second configuration register 0x2c */
#define ESP_CFG3 0x30UL /* rw Third configuration register 0x30 */
#define ESP_TCHI 0x38UL /* rw High bits of transfer count 0x38 */
#define ESP_UID ESP_TCHI /* ro Unique ID code 0x38 */
#define FAS_RLO ESP_TCHI /* rw HME extended counter 0x38 */
#define ESP_FGRND 0x3cUL /* rw Data base for fifo 0x3c */
#define FAS_RHI ESP_FGRND /* rw HME extended counter 0x3c */
#define ESP_REG_SIZE 0x40UL
/* Various revisions of the ESP board. */
enum esp_rev {
esp100 = 0x00, /* NCR53C90 - very broken */
esp100a = 0x01, /* NCR53C90A */
esp236 = 0x02,
fas236 = 0x03,
fas100a = 0x04,
fast = 0x05,
fashme = 0x06,
espunknown = 0x07
};
/* We allocate one of these for each scsi device and attach it to
* SDptr->hostdata for use in the driver
*/
struct esp_device {
unsigned char sync_min_period;
unsigned char sync_max_offset;
unsigned sync:1;
unsigned wide:1;
unsigned disconnect:1;
};
struct scsi_cmnd;
/* We get one of these for each ESP probed. */
struct esp {
void __iomem *eregs; /* ESP controller registers */
void __iomem *dregs; /* DMA controller registers */
struct sbus_dma *dma; /* DMA controller sw state */
struct Scsi_Host *ehost; /* Backpointer to SCSI Host */
struct sbus_dev *sdev; /* Pointer to SBus entry */
/* ESP Configuration Registers */
u8 config1; /* Copy of the 1st config register */
u8 config2; /* Copy of the 2nd config register */
u8 config3[16]; /* Copy of the 3rd config register */
/* The current command we are sending to the ESP chip. This esp_command
* ptr needs to be mapped in DVMA area so we can send commands and read
* from the ESP fifo without burning precious CPU cycles. Programmed I/O
* sucks when we have the DVMA to do it for us. The ESP is stupid and will
* only send out 6, 10, and 12 byte SCSI commands, others we need to send
* one byte at a time. esp_slowcmd being set says that we are doing one
* of the command types ESP doesn't understand, esp_scmdp keeps track of
* which byte we are sending, esp_scmdleft says how many bytes to go.
*/
volatile u8 *esp_command; /* Location of command (CPU view) */
__u32 esp_command_dvma;/* Location of command (DVMA view) */
unsigned char esp_clen; /* Length of this command */
unsigned char esp_slowcmd;
unsigned char *esp_scmdp;
unsigned char esp_scmdleft;
/* The following are used to determine the cause of an IRQ. Upon every
* IRQ entry we synchronize these with the hardware registers.
*/
u8 ireg; /* Copy of ESP interrupt register */
u8 sreg; /* Copy of ESP status register */
u8 seqreg; /* Copy of ESP sequence step register */
u8 sreg2; /* Copy of HME status2 register */
/* To save register writes to the ESP, which can be expensive, we
* keep track of the previous value that various registers had for
* the last target we connected to. If they are the same for the
* current target, we skip the register writes as they are not needed.
*/
u8 prev_soff, prev_stp;
u8 prev_cfg3, __cache_pad;
/* We also keep a cache of the previous FAS/HME DMA CSR register value. */
u32 prev_hme_dmacsr;
/* The HME is the biggest piece of shit I have ever seen. */
u8 hme_fifo_workaround_buffer[16 * 2];
u8 hme_fifo_workaround_count;
/* For each target we keep track of save/restore data
* pointer information. This needs to be updated majorly
* when we add support for tagged queueing. -DaveM
*/
struct esp_pointers {
char *saved_ptr;
struct scatterlist *saved_buffer;
int saved_this_residual;
int saved_buffers_residual;
} data_pointers[16] /*XXX [MAX_TAGS_PER_TARGET]*/;
/* Clock periods, frequencies, synchronization, etc. */
unsigned int cfreq; /* Clock frequency in HZ */
unsigned int cfact; /* Clock conversion factor */
unsigned int raw_cfact; /* Raw copy from probing */
unsigned int ccycle; /* One ESP clock cycle */
unsigned int ctick; /* One ESP clock time */
unsigned int radelay; /* FAST chip req/ack delay */
unsigned int neg_defp; /* Default negotiation period */
unsigned int sync_defp; /* Default sync transfer period */
unsigned int max_period; /* longest our period can be */
unsigned int min_period; /* shortest period we can withstand */
struct esp *next; /* Next ESP we probed or NULL */
char prom_name[64]; /* Name of ESP device from prom */
int prom_node; /* Prom node where ESP found */
int esp_id; /* Unique per-ESP ID number */
/* For slow to medium speed input clock rates we shoot for 5mb/s,
* but for high input clock rates we try to do 10mb/s although I
* don't think a transfer can even run that fast with an ESP even
* with DMA2 scatter gather pipelining.
*/
#define SYNC_DEFP_SLOW 0x32 /* 5mb/s */
#define SYNC_DEFP_FAST 0x19 /* 10mb/s */
unsigned int snip; /* Sync. negotiation in progress */
unsigned int wnip; /* WIDE negotiation in progress */
unsigned int targets_present;/* targets spoken to before */
int current_transfer_size; /* Set at beginning of data dma */
u8 espcmdlog[32]; /* Log of current esp cmds sent. */
u8 espcmdent; /* Current entry in esp cmd log. */
/* Misc. info about this ESP */
enum esp_rev erev; /* ESP revision */
int irq; /* SBus IRQ for this ESP */
int scsi_id; /* Who am I as initiator? */
int scsi_id_mask; /* Bitmask of 'me'. */
int diff; /* Differential SCSI bus? */
int bursts; /* Burst sizes our DVMA supports */
/* Our command queues, only one cmd lives in the current_SC queue. */
struct scsi_cmnd *issue_SC; /* Commands to be issued */
struct scsi_cmnd *current_SC; /* Who is currently working the bus */
struct scsi_cmnd *disconnected_SC;/* Commands disconnected from the bus */
/* Message goo */
u8 cur_msgout[16];
u8 cur_msgin[16];
u8 prevmsgout, prevmsgin;
u8 msgout_len, msgin_len;
u8 msgout_ctr, msgin_ctr;
/* States that we cannot keep in the per cmd structure because they
* cannot be assosciated with any specific command.
*/
u8 resetting_bus;
wait_queue_head_t reset_queue;
};
/* Bitfield meanings for the above registers. */
/* ESP config reg 1, read-write, found on all ESP chips */
#define ESP_CONFIG1_ID 0x07 /* My BUS ID bits */
#define ESP_CONFIG1_CHTEST 0x08 /* Enable ESP chip tests */
#define ESP_CONFIG1_PENABLE 0x10 /* Enable parity checks */
#define ESP_CONFIG1_PARTEST 0x20 /* Parity test mode enabled? */
#define ESP_CONFIG1_SRRDISAB 0x40 /* Disable SCSI reset reports */
#define ESP_CONFIG1_SLCABLE 0x80 /* Enable slow cable mode */
/* ESP config reg 2, read-write, found only on esp100a+esp200+esp236 chips */
#define ESP_CONFIG2_DMAPARITY 0x01 /* enable DMA Parity (200,236) */
#define ESP_CONFIG2_REGPARITY 0x02 /* enable reg Parity (200,236) */
#define ESP_CONFIG2_BADPARITY 0x04 /* Bad parity target abort */
#define ESP_CONFIG2_SCSI2ENAB 0x08 /* Enable SCSI-2 features (tmode only) */
#define ESP_CONFIG2_HI 0x10 /* High Impedance DREQ ??? */
#define ESP_CONFIG2_HMEFENAB 0x10 /* HME features enable */
#define ESP_CONFIG2_BCM 0x20 /* Enable byte-ctrl (236) */
#define ESP_CONFIG2_DISPINT 0x20 /* Disable pause irq (hme) */
#define ESP_CONFIG2_FENAB 0x40 /* Enable features (fas100,esp216) */
#define ESP_CONFIG2_SPL 0x40 /* Enable status-phase latch (esp236) */
#define ESP_CONFIG2_MKDONE 0x40 /* HME magic feature */
#define ESP_CONFIG2_HME32 0x80 /* HME 32 extended */
#define ESP_CONFIG2_MAGIC 0xe0 /* Invalid bits... */
/* ESP config register 3 read-write, found only esp236+fas236+fas100a+hme chips */
#define ESP_CONFIG3_FCLOCK 0x01 /* FAST SCSI clock rate (esp100a/hme) */
#define ESP_CONFIG3_TEM 0x01 /* Enable thresh-8 mode (esp/fas236) */
#define ESP_CONFIG3_FAST 0x02 /* Enable FAST SCSI (esp100a/hme) */
#define ESP_CONFIG3_ADMA 0x02 /* Enable alternate-dma (esp/fas236) */
#define ESP_CONFIG3_TENB 0x04 /* group2 SCSI2 support (esp100a/hme) */
#define ESP_CONFIG3_SRB 0x04 /* Save residual byte (esp/fas236) */
#define ESP_CONFIG3_TMS 0x08 /* Three-byte msg's ok (esp100a/hme) */
#define ESP_CONFIG3_FCLK 0x08 /* Fast SCSI clock rate (esp/fas236) */
#define ESP_CONFIG3_IDMSG 0x10 /* ID message checking (esp100a/hme) */
#define ESP_CONFIG3_FSCSI 0x10 /* Enable FAST SCSI (esp/fas236) */
#define ESP_CONFIG3_GTM 0x20 /* group2 SCSI2 support (esp/fas236) */
#define ESP_CONFIG3_IDBIT3 0x20 /* Bit 3 of HME SCSI-ID (hme) */
#define ESP_CONFIG3_TBMS 0x40 /* Three-byte msg's ok (esp/fas236) */
#define ESP_CONFIG3_EWIDE 0x40 /* Enable Wide-SCSI (hme) */
#define ESP_CONFIG3_IMS 0x80 /* ID msg chk'ng (esp/fas236) */
#define ESP_CONFIG3_OBPUSH 0x80 /* Push odd-byte to dma (hme) */
/* ESP command register read-write */
/* Group 1 commands: These may be sent at any point in time to the ESP
* chip. None of them can generate interrupts 'cept
* the "SCSI bus reset" command if you have not disabled
* SCSI reset interrupts in the config1 ESP register.
*/
#define ESP_CMD_NULL 0x00 /* Null command, ie. a nop */
#define ESP_CMD_FLUSH 0x01 /* FIFO Flush */
#define ESP_CMD_RC 0x02 /* Chip reset */
#define ESP_CMD_RS 0x03 /* SCSI bus reset */
/* Group 2 commands: ESP must be an initiator and connected to a target
* for these commands to work.
*/
#define ESP_CMD_TI 0x10 /* Transfer Information */
#define ESP_CMD_ICCSEQ 0x11 /* Initiator cmd complete sequence */
#define ESP_CMD_MOK 0x12 /* Message okie-dokie */
#define ESP_CMD_TPAD 0x18 /* Transfer Pad */
#define ESP_CMD_SATN 0x1a /* Set ATN */
#define ESP_CMD_RATN 0x1b /* De-assert ATN */
/* Group 3 commands: ESP must be in the MSGOUT or MSGIN state and be connected
* to a target as the initiator for these commands to work.
*/
#define ESP_CMD_SMSG 0x20 /* Send message */
#define ESP_CMD_SSTAT 0x21 /* Send status */
#define ESP_CMD_SDATA 0x22 /* Send data */
#define ESP_CMD_DSEQ 0x23 /* Discontinue Sequence */
#define ESP_CMD_TSEQ 0x24 /* Terminate Sequence */
#define ESP_CMD_TCCSEQ 0x25 /* Target cmd cmplt sequence */
#define ESP_CMD_DCNCT 0x27 /* Disconnect */
#define ESP_CMD_RMSG 0x28 /* Receive Message */
#define ESP_CMD_RCMD 0x29 /* Receive Command */
#define ESP_CMD_RDATA 0x2a /* Receive Data */
#define ESP_CMD_RCSEQ 0x2b /* Receive cmd sequence */
/* Group 4 commands: The ESP must be in the disconnected state and must
* not be connected to any targets as initiator for
* these commands to work.
*/
#define ESP_CMD_RSEL 0x40 /* Reselect */
#define ESP_CMD_SEL 0x41 /* Select w/o ATN */
#define ESP_CMD_SELA 0x42 /* Select w/ATN */
#define ESP_CMD_SELAS 0x43 /* Select w/ATN & STOP */
#define ESP_CMD_ESEL 0x44 /* Enable selection */
#define ESP_CMD_DSEL 0x45 /* Disable selections */
#define ESP_CMD_SA3 0x46 /* Select w/ATN3 */
#define ESP_CMD_RSEL3 0x47 /* Reselect3 */
/* This bit enables the ESP's DMA on the SBus */
#define ESP_CMD_DMA 0x80 /* Do DMA? */
/* ESP status register read-only */
#define ESP_STAT_PIO 0x01 /* IO phase bit */
#define ESP_STAT_PCD 0x02 /* CD phase bit */
#define ESP_STAT_PMSG 0x04 /* MSG phase bit */
#define ESP_STAT_PMASK 0x07 /* Mask of phase bits */
#define ESP_STAT_TDONE 0x08 /* Transfer Completed */
#define ESP_STAT_TCNT 0x10 /* Transfer Counter Is Zero */
#define ESP_STAT_PERR 0x20 /* Parity error */
#define ESP_STAT_SPAM 0x40 /* Real bad error */
/* This indicates the 'interrupt pending' condition on esp236, it is a reserved
* bit on other revs of the ESP.
*/
#define ESP_STAT_INTR 0x80 /* Interrupt */
/* HME only: status 2 register */
#define ESP_STAT2_SCHBIT 0x01 /* Upper bits 3-7 of sstep enabled */
#define ESP_STAT2_FFLAGS 0x02 /* The fifo flags are now latched */
#define ESP_STAT2_XCNT 0x04 /* The transfer counter is latched */
#define ESP_STAT2_CREGA 0x08 /* The command reg is active now */
#define ESP_STAT2_WIDE 0x10 /* Interface on this adapter is wide */
#define ESP_STAT2_F1BYTE 0x20 /* There is one byte at top of fifo */
#define ESP_STAT2_FMSB 0x40 /* Next byte in fifo is most significant */
#define ESP_STAT2_FEMPTY 0x80 /* FIFO is empty */
/* The status register can be masked with ESP_STAT_PMASK and compared
* with the following values to determine the current phase the ESP
* (at least thinks it) is in. For our purposes we also add our own
* software 'done' bit for our phase management engine.
*/
#define ESP_DOP (0) /* Data Out */
#define ESP_DIP (ESP_STAT_PIO) /* Data In */
#define ESP_CMDP (ESP_STAT_PCD) /* Command */
#define ESP_STATP (ESP_STAT_PCD|ESP_STAT_PIO) /* Status */
#define ESP_MOP (ESP_STAT_PMSG|ESP_STAT_PCD) /* Message Out */
#define ESP_MIP (ESP_STAT_PMSG|ESP_STAT_PCD|ESP_STAT_PIO) /* Message In */
/* ESP interrupt register read-only */
#define ESP_INTR_S 0x01 /* Select w/o ATN */
#define ESP_INTR_SATN 0x02 /* Select w/ATN */
#define ESP_INTR_RSEL 0x04 /* Reselected */
#define ESP_INTR_FDONE 0x08 /* Function done */
#define ESP_INTR_BSERV 0x10 /* Bus service */
#define ESP_INTR_DC 0x20 /* Disconnect */
#define ESP_INTR_IC 0x40 /* Illegal command given */
#define ESP_INTR_SR 0x80 /* SCSI bus reset detected */
/* Interrupt status macros */
#define ESP_SRESET_IRQ(esp) ((esp)->intreg & (ESP_INTR_SR))
#define ESP_ILLCMD_IRQ(esp) ((esp)->intreg & (ESP_INTR_IC))
#define ESP_SELECT_WITH_ATN_IRQ(esp) ((esp)->intreg & (ESP_INTR_SATN))
#define ESP_SELECT_WITHOUT_ATN_IRQ(esp) ((esp)->intreg & (ESP_INTR_S))
#define ESP_SELECTION_IRQ(esp) ((ESP_SELECT_WITH_ATN_IRQ(esp)) || \
(ESP_SELECT_WITHOUT_ATN_IRQ(esp)))
#define ESP_RESELECTION_IRQ(esp) ((esp)->intreg & (ESP_INTR_RSEL))
/* ESP sequence step register read-only */
#define ESP_STEP_VBITS 0x07 /* Valid bits */
#define ESP_STEP_ASEL 0x00 /* Selection&Arbitrate cmplt */
#define ESP_STEP_SID 0x01 /* One msg byte sent */
#define ESP_STEP_NCMD 0x02 /* Was not in command phase */
#define ESP_STEP_PPC 0x03 /* Early phase chg caused cmnd
* bytes to be lost
*/
#define ESP_STEP_FINI4 0x04 /* Command was sent ok */
/* Ho hum, some ESP's set the step register to this as well... */
#define ESP_STEP_FINI5 0x05
#define ESP_STEP_FINI6 0x06
#define ESP_STEP_FINI7 0x07
/* ESP chip-test register read-write */
#define ESP_TEST_TARG 0x01 /* Target test mode */
#define ESP_TEST_INI 0x02 /* Initiator test mode */
#define ESP_TEST_TS 0x04 /* Tristate test mode */
/* ESP unique ID register read-only, found on fas236+fas100a only */
#define ESP_UID_F100A 0x00 /* ESP FAS100A */
#define ESP_UID_F236 0x02 /* ESP FAS236 */
#define ESP_UID_REV 0x07 /* ESP revision */
#define ESP_UID_FAM 0xf8 /* ESP family */
/* ESP fifo flags register read-only */
/* Note that the following implies a 16 byte FIFO on the ESP. */
#define ESP_FF_FBYTES 0x1f /* Num bytes in FIFO */
#define ESP_FF_ONOTZERO 0x20 /* offset ctr not zero (esp100) */
#define ESP_FF_SSTEP 0xe0 /* Sequence step */
/* ESP clock conversion factor register write-only */
#define ESP_CCF_F0 0x00 /* 35.01MHz - 40MHz */
#define ESP_CCF_NEVER 0x01 /* Set it to this and die */
#define ESP_CCF_F2 0x02 /* 10MHz */
#define ESP_CCF_F3 0x03 /* 10.01MHz - 15MHz */
#define ESP_CCF_F4 0x04 /* 15.01MHz - 20MHz */
#define ESP_CCF_F5 0x05 /* 20.01MHz - 25MHz */
#define ESP_CCF_F6 0x06 /* 25.01MHz - 30MHz */
#define ESP_CCF_F7 0x07 /* 30.01MHz - 35MHz */
/* HME only... */
#define ESP_BUSID_RESELID 0x10
#define ESP_BUSID_CTR32BIT 0x40
#define ESP_BUS_TIMEOUT 275 /* In milli-seconds */
#define ESP_TIMEO_CONST 8192
#define ESP_NEG_DEFP(mhz, cfact) \
((ESP_BUS_TIMEOUT * ((mhz) / 1000)) / (8192 * (cfact)))
#define ESP_MHZ_TO_CYCLE(mhertz) ((1000000000) / ((mhertz) / 1000))
#define ESP_TICK(ccf, cycle) ((7682 * (ccf) * (cycle) / 1000))
#endif /* !(_SPARC_ESP_H) */

2710
drivers/scsi/esp_scsi.c Normal file

File diff suppressed because it is too large Load Diff

560
drivers/scsi/esp_scsi.h Normal file
View File

@ -0,0 +1,560 @@
/* esp_scsi.h: Defines and structures for the ESP drier.
*
* Copyright (C) 2007 David S. Miller (davem@davemloft.net)
*/
#ifndef _ESP_SCSI_H
#define _ESP_SCSI_H
/* Access Description Offset */
#define ESP_TCLOW 0x00UL /* rw Low bits transfer count 0x00 */
#define ESP_TCMED 0x01UL /* rw Mid bits transfer count 0x04 */
#define ESP_FDATA 0x02UL /* rw FIFO data bits 0x08 */
#define ESP_CMD 0x03UL /* rw SCSI command bits 0x0c */
#define ESP_STATUS 0x04UL /* ro ESP status register 0x10 */
#define ESP_BUSID ESP_STATUS /* wo BusID for sel/resel 0x10 */
#define ESP_INTRPT 0x05UL /* ro Kind of interrupt 0x14 */
#define ESP_TIMEO ESP_INTRPT /* wo Timeout for sel/resel 0x14 */
#define ESP_SSTEP 0x06UL /* ro Sequence step register 0x18 */
#define ESP_STP ESP_SSTEP /* wo Transfer period/sync 0x18 */
#define ESP_FFLAGS 0x07UL /* ro Bits current FIFO info 0x1c */
#define ESP_SOFF ESP_FFLAGS /* wo Sync offset 0x1c */
#define ESP_CFG1 0x08UL /* rw First cfg register 0x20 */
#define ESP_CFACT 0x09UL /* wo Clock conv factor 0x24 */
#define ESP_STATUS2 ESP_CFACT /* ro HME status2 register 0x24 */
#define ESP_CTEST 0x0aUL /* wo Chip test register 0x28 */
#define ESP_CFG2 0x0bUL /* rw Second cfg register 0x2c */
#define ESP_CFG3 0x0cUL /* rw Third cfg register 0x30 */
#define ESP_TCHI 0x0eUL /* rw High bits transf count 0x38 */
#define ESP_UID ESP_TCHI /* ro Unique ID code 0x38 */
#define FAS_RLO ESP_TCHI /* rw HME extended counter 0x38 */
#define ESP_FGRND 0x0fUL /* rw Data base for fifo 0x3c */
#define FAS_RHI ESP_FGRND /* rw HME extended counter 0x3c */
#define SBUS_ESP_REG_SIZE 0x40UL
/* Bitfield meanings for the above registers. */
/* ESP config reg 1, read-write, found on all ESP chips */
#define ESP_CONFIG1_ID 0x07 /* My BUS ID bits */
#define ESP_CONFIG1_CHTEST 0x08 /* Enable ESP chip tests */
#define ESP_CONFIG1_PENABLE 0x10 /* Enable parity checks */
#define ESP_CONFIG1_PARTEST 0x20 /* Parity test mode enabled? */
#define ESP_CONFIG1_SRRDISAB 0x40 /* Disable SCSI reset reports */
#define ESP_CONFIG1_SLCABLE 0x80 /* Enable slow cable mode */
/* ESP config reg 2, read-write, found only on esp100a+esp200+esp236 chips */
#define ESP_CONFIG2_DMAPARITY 0x01 /* enable DMA Parity (200,236) */
#define ESP_CONFIG2_REGPARITY 0x02 /* enable reg Parity (200,236) */
#define ESP_CONFIG2_BADPARITY 0x04 /* Bad parity target abort */
#define ESP_CONFIG2_SCSI2ENAB 0x08 /* Enable SCSI-2 features (tgtmode) */
#define ESP_CONFIG2_HI 0x10 /* High Impedance DREQ ??? */
#define ESP_CONFIG2_HMEFENAB 0x10 /* HME features enable */
#define ESP_CONFIG2_BCM 0x20 /* Enable byte-ctrl (236) */
#define ESP_CONFIG2_DISPINT 0x20 /* Disable pause irq (hme) */
#define ESP_CONFIG2_FENAB 0x40 /* Enable features (fas100,216) */
#define ESP_CONFIG2_SPL 0x40 /* Enable status-phase latch (236) */
#define ESP_CONFIG2_MKDONE 0x40 /* HME magic feature */
#define ESP_CONFIG2_HME32 0x80 /* HME 32 extended */
#define ESP_CONFIG2_MAGIC 0xe0 /* Invalid bits... */
/* ESP config register 3 read-write, found only esp236+fas236+fas100a+hme chips */
#define ESP_CONFIG3_FCLOCK 0x01 /* FAST SCSI clock rate (esp100a/hme) */
#define ESP_CONFIG3_TEM 0x01 /* Enable thresh-8 mode (esp/fas236) */
#define ESP_CONFIG3_FAST 0x02 /* Enable FAST SCSI (esp100a/hme) */
#define ESP_CONFIG3_ADMA 0x02 /* Enable alternate-dma (esp/fas236) */
#define ESP_CONFIG3_TENB 0x04 /* group2 SCSI2 support (esp100a/hme) */
#define ESP_CONFIG3_SRB 0x04 /* Save residual byte (esp/fas236) */
#define ESP_CONFIG3_TMS 0x08 /* Three-byte msg's ok (esp100a/hme) */
#define ESP_CONFIG3_FCLK 0x08 /* Fast SCSI clock rate (esp/fas236) */
#define ESP_CONFIG3_IDMSG 0x10 /* ID message checking (esp100a/hme) */
#define ESP_CONFIG3_FSCSI 0x10 /* Enable FAST SCSI (esp/fas236) */
#define ESP_CONFIG3_GTM 0x20 /* group2 SCSI2 support (esp/fas236) */
#define ESP_CONFIG3_IDBIT3 0x20 /* Bit 3 of HME SCSI-ID (hme) */
#define ESP_CONFIG3_TBMS 0x40 /* Three-byte msg's ok (esp/fas236) */
#define ESP_CONFIG3_EWIDE 0x40 /* Enable Wide-SCSI (hme) */
#define ESP_CONFIG3_IMS 0x80 /* ID msg chk'ng (esp/fas236) */
#define ESP_CONFIG3_OBPUSH 0x80 /* Push odd-byte to dma (hme) */
/* ESP command register read-write */
/* Group 1 commands: These may be sent at any point in time to the ESP
* chip. None of them can generate interrupts 'cept
* the "SCSI bus reset" command if you have not disabled
* SCSI reset interrupts in the config1 ESP register.
*/
#define ESP_CMD_NULL 0x00 /* Null command, ie. a nop */
#define ESP_CMD_FLUSH 0x01 /* FIFO Flush */
#define ESP_CMD_RC 0x02 /* Chip reset */
#define ESP_CMD_RS 0x03 /* SCSI bus reset */
/* Group 2 commands: ESP must be an initiator and connected to a target
* for these commands to work.
*/
#define ESP_CMD_TI 0x10 /* Transfer Information */
#define ESP_CMD_ICCSEQ 0x11 /* Initiator cmd complete sequence */
#define ESP_CMD_MOK 0x12 /* Message okie-dokie */
#define ESP_CMD_TPAD 0x18 /* Transfer Pad */
#define ESP_CMD_SATN 0x1a /* Set ATN */
#define ESP_CMD_RATN 0x1b /* De-assert ATN */
/* Group 3 commands: ESP must be in the MSGOUT or MSGIN state and be connected
* to a target as the initiator for these commands to work.
*/
#define ESP_CMD_SMSG 0x20 /* Send message */
#define ESP_CMD_SSTAT 0x21 /* Send status */
#define ESP_CMD_SDATA 0x22 /* Send data */
#define ESP_CMD_DSEQ 0x23 /* Discontinue Sequence */
#define ESP_CMD_TSEQ 0x24 /* Terminate Sequence */
#define ESP_CMD_TCCSEQ 0x25 /* Target cmd cmplt sequence */
#define ESP_CMD_DCNCT 0x27 /* Disconnect */
#define ESP_CMD_RMSG 0x28 /* Receive Message */
#define ESP_CMD_RCMD 0x29 /* Receive Command */
#define ESP_CMD_RDATA 0x2a /* Receive Data */
#define ESP_CMD_RCSEQ 0x2b /* Receive cmd sequence */
/* Group 4 commands: The ESP must be in the disconnected state and must
* not be connected to any targets as initiator for
* these commands to work.
*/
#define ESP_CMD_RSEL 0x40 /* Reselect */
#define ESP_CMD_SEL 0x41 /* Select w/o ATN */
#define ESP_CMD_SELA 0x42 /* Select w/ATN */
#define ESP_CMD_SELAS 0x43 /* Select w/ATN & STOP */
#define ESP_CMD_ESEL 0x44 /* Enable selection */
#define ESP_CMD_DSEL 0x45 /* Disable selections */
#define ESP_CMD_SA3 0x46 /* Select w/ATN3 */
#define ESP_CMD_RSEL3 0x47 /* Reselect3 */
/* This bit enables the ESP's DMA on the SBus */
#define ESP_CMD_DMA 0x80 /* Do DMA? */
/* ESP status register read-only */
#define ESP_STAT_PIO 0x01 /* IO phase bit */
#define ESP_STAT_PCD 0x02 /* CD phase bit */
#define ESP_STAT_PMSG 0x04 /* MSG phase bit */
#define ESP_STAT_PMASK 0x07 /* Mask of phase bits */
#define ESP_STAT_TDONE 0x08 /* Transfer Completed */
#define ESP_STAT_TCNT 0x10 /* Transfer Counter Is Zero */
#define ESP_STAT_PERR 0x20 /* Parity error */
#define ESP_STAT_SPAM 0x40 /* Real bad error */
/* This indicates the 'interrupt pending' condition on esp236, it is a reserved
* bit on other revs of the ESP.
*/
#define ESP_STAT_INTR 0x80 /* Interrupt */
/* The status register can be masked with ESP_STAT_PMASK and compared
* with the following values to determine the current phase the ESP
* (at least thinks it) is in. For our purposes we also add our own
* software 'done' bit for our phase management engine.
*/
#define ESP_DOP (0) /* Data Out */
#define ESP_DIP (ESP_STAT_PIO) /* Data In */
#define ESP_CMDP (ESP_STAT_PCD) /* Command */
#define ESP_STATP (ESP_STAT_PCD|ESP_STAT_PIO) /* Status */
#define ESP_MOP (ESP_STAT_PMSG|ESP_STAT_PCD) /* Message Out */
#define ESP_MIP (ESP_STAT_PMSG|ESP_STAT_PCD|ESP_STAT_PIO) /* Message In */
/* HME only: status 2 register */
#define ESP_STAT2_SCHBIT 0x01 /* Upper bits 3-7 of sstep enabled */
#define ESP_STAT2_FFLAGS 0x02 /* The fifo flags are now latched */
#define ESP_STAT2_XCNT 0x04 /* The transfer counter is latched */
#define ESP_STAT2_CREGA 0x08 /* The command reg is active now */
#define ESP_STAT2_WIDE 0x10 /* Interface on this adapter is wide */
#define ESP_STAT2_F1BYTE 0x20 /* There is one byte at top of fifo */
#define ESP_STAT2_FMSB 0x40 /* Next byte in fifo is most significant */
#define ESP_STAT2_FEMPTY 0x80 /* FIFO is empty */
/* ESP interrupt register read-only */
#define ESP_INTR_S 0x01 /* Select w/o ATN */
#define ESP_INTR_SATN 0x02 /* Select w/ATN */
#define ESP_INTR_RSEL 0x04 /* Reselected */
#define ESP_INTR_FDONE 0x08 /* Function done */
#define ESP_INTR_BSERV 0x10 /* Bus service */
#define ESP_INTR_DC 0x20 /* Disconnect */
#define ESP_INTR_IC 0x40 /* Illegal command given */
#define ESP_INTR_SR 0x80 /* SCSI bus reset detected */
/* ESP sequence step register read-only */
#define ESP_STEP_VBITS 0x07 /* Valid bits */
#define ESP_STEP_ASEL 0x00 /* Selection&Arbitrate cmplt */
#define ESP_STEP_SID 0x01 /* One msg byte sent */
#define ESP_STEP_NCMD 0x02 /* Was not in command phase */
#define ESP_STEP_PPC 0x03 /* Early phase chg caused cmnd
* bytes to be lost
*/
#define ESP_STEP_FINI4 0x04 /* Command was sent ok */
/* Ho hum, some ESP's set the step register to this as well... */
#define ESP_STEP_FINI5 0x05
#define ESP_STEP_FINI6 0x06
#define ESP_STEP_FINI7 0x07
/* ESP chip-test register read-write */
#define ESP_TEST_TARG 0x01 /* Target test mode */
#define ESP_TEST_INI 0x02 /* Initiator test mode */
#define ESP_TEST_TS 0x04 /* Tristate test mode */
/* ESP unique ID register read-only, found on fas236+fas100a only */
#define ESP_UID_F100A 0x00 /* ESP FAS100A */
#define ESP_UID_F236 0x02 /* ESP FAS236 */
#define ESP_UID_REV 0x07 /* ESP revision */
#define ESP_UID_FAM 0xf8 /* ESP family */
/* ESP fifo flags register read-only */
/* Note that the following implies a 16 byte FIFO on the ESP. */
#define ESP_FF_FBYTES 0x1f /* Num bytes in FIFO */
#define ESP_FF_ONOTZERO 0x20 /* offset ctr not zero (esp100) */
#define ESP_FF_SSTEP 0xe0 /* Sequence step */
/* ESP clock conversion factor register write-only */
#define ESP_CCF_F0 0x00 /* 35.01MHz - 40MHz */
#define ESP_CCF_NEVER 0x01 /* Set it to this and die */
#define ESP_CCF_F2 0x02 /* 10MHz */
#define ESP_CCF_F3 0x03 /* 10.01MHz - 15MHz */
#define ESP_CCF_F4 0x04 /* 15.01MHz - 20MHz */
#define ESP_CCF_F5 0x05 /* 20.01MHz - 25MHz */
#define ESP_CCF_F6 0x06 /* 25.01MHz - 30MHz */
#define ESP_CCF_F7 0x07 /* 30.01MHz - 35MHz */
/* HME only... */
#define ESP_BUSID_RESELID 0x10
#define ESP_BUSID_CTR32BIT 0x40
#define ESP_BUS_TIMEOUT 250 /* In milli-seconds */
#define ESP_TIMEO_CONST 8192
#define ESP_NEG_DEFP(mhz, cfact) \
((ESP_BUS_TIMEOUT * ((mhz) / 1000)) / (8192 * (cfact)))
#define ESP_MHZ_TO_CYCLE(mhertz) ((1000000000) / ((mhertz) / 1000))
#define ESP_TICK(ccf, cycle) ((7682 * (ccf) * (cycle) / 1000))
/* For slow to medium speed input clock rates we shoot for 5mb/s, but for high
* input clock rates we try to do 10mb/s although I don't think a transfer can
* even run that fast with an ESP even with DMA2 scatter gather pipelining.
*/
#define SYNC_DEFP_SLOW 0x32 /* 5mb/s */
#define SYNC_DEFP_FAST 0x19 /* 10mb/s */
struct esp_cmd_priv {
union {
dma_addr_t dma_addr;
int num_sg;
} u;
unsigned int cur_residue;
struct scatterlist *cur_sg;
unsigned int tot_residue;
};
#define ESP_CMD_PRIV(CMD) ((struct esp_cmd_priv *)(&(CMD)->SCp))
enum esp_rev {
ESP100 = 0x00, /* NCR53C90 - very broken */
ESP100A = 0x01, /* NCR53C90A */
ESP236 = 0x02,
FAS236 = 0x03,
FAS100A = 0x04,
FAST = 0x05,
FASHME = 0x06,
};
struct esp_cmd_entry {
struct list_head list;
struct scsi_cmnd *cmd;
unsigned int saved_cur_residue;
struct scatterlist *saved_cur_sg;
unsigned int saved_tot_residue;
u8 flags;
#define ESP_CMD_FLAG_WRITE 0x01 /* DMA is a write */
#define ESP_CMD_FLAG_ABORT 0x02 /* being aborted */
#define ESP_CMD_FLAG_AUTOSENSE 0x04 /* Doing automatic REQUEST_SENSE */
u8 tag[2];
u8 status;
u8 message;
unsigned char *sense_ptr;
unsigned char *saved_sense_ptr;
dma_addr_t sense_dma;
struct completion *eh_done;
};
/* XXX make this configurable somehow XXX */
#define ESP_DEFAULT_TAGS 16
#define ESP_MAX_TARGET 16
#define ESP_MAX_LUN 8
#define ESP_MAX_TAG 256
struct esp_lun_data {
struct esp_cmd_entry *non_tagged_cmd;
int num_tagged;
int hold;
struct esp_cmd_entry *tagged_cmds[ESP_MAX_TAG];
};
struct esp_target_data {
/* These are the ESP_STP, ESP_SOFF, and ESP_CFG3 register values which
* match the currently negotiated settings for this target. The SCSI
* protocol values are maintained in spi_{offset,period,wide}(starget).
*/
u8 esp_period;
u8 esp_offset;
u8 esp_config3;
u8 flags;
#define ESP_TGT_WIDE 0x01
#define ESP_TGT_DISCONNECT 0x02
#define ESP_TGT_NEGO_WIDE 0x04
#define ESP_TGT_NEGO_SYNC 0x08
#define ESP_TGT_CHECK_NEGO 0x40
#define ESP_TGT_BROKEN 0x80
/* When ESP_TGT_CHECK_NEGO is set, on the next scsi command to this
* device we will try to negotiate the following parameters.
*/
u8 nego_goal_period;
u8 nego_goal_offset;
u8 nego_goal_width;
u8 nego_goal_tags;
struct scsi_target *starget;
};
struct esp_event_ent {
u8 type;
#define ESP_EVENT_TYPE_EVENT 0x01
#define ESP_EVENT_TYPE_CMD 0x02
u8 val;
u8 sreg;
u8 seqreg;
u8 sreg2;
u8 ireg;
u8 select_state;
u8 event;
u8 __pad;
};
struct esp;
struct esp_driver_ops {
/* Read and write the ESP 8-bit registers. On some
* applications of the ESP chip the registers are at 4-byte
* instead of 1-byte intervals.
*/
void (*esp_write8)(struct esp *esp, u8 val, unsigned long reg);
u8 (*esp_read8)(struct esp *esp, unsigned long reg);
/* Map and unmap DMA memory. Eventually the driver will be
* converted to the generic DMA API as soon as SBUS is able to
* cope with that. At such time we can remove this.
*/
dma_addr_t (*map_single)(struct esp *esp, void *buf,
size_t sz, int dir);
int (*map_sg)(struct esp *esp, struct scatterlist *sg,
int num_sg, int dir);
void (*unmap_single)(struct esp *esp, dma_addr_t addr,
size_t sz, int dir);
void (*unmap_sg)(struct esp *esp, struct scatterlist *sg,
int num_sg, int dir);
/* Return non-zero if there is an IRQ pending. Usually this
* status bit lives in the DMA controller sitting in front of
* the ESP. This has to be accurate or else the ESP interrupt
* handler will not run.
*/
int (*irq_pending)(struct esp *esp);
/* Reset the DMA engine entirely. On return, ESP interrupts
* should be enabled. Often the interrupt enabling is
* controlled in the DMA engine.
*/
void (*reset_dma)(struct esp *esp);
/* Drain any pending DMA in the DMA engine after a transfer.
* This is for writes to memory.
*/
void (*dma_drain)(struct esp *esp);
/* Invalidate the DMA engine after a DMA transfer. */
void (*dma_invalidate)(struct esp *esp);
/* Setup an ESP command that will use a DMA transfer.
* The 'esp_count' specifies what transfer length should be
* programmed into the ESP transfer counter registers, whereas
* the 'dma_count' is the length that should be programmed into
* the DMA controller. Usually they are the same. If 'write'
* is non-zero, this transfer is a write into memory. 'cmd'
* holds the ESP command that should be issued by calling
* scsi_esp_cmd() at the appropriate time while programming
* the DMA hardware.
*/
void (*send_dma_cmd)(struct esp *esp, u32 dma_addr, u32 esp_count,
u32 dma_count, int write, u8 cmd);
/* Return non-zero if the DMA engine is reporting an error
* currently.
*/
int (*dma_error)(struct esp *esp);
};
#define ESP_MAX_MSG_SZ 8
#define ESP_EVENT_LOG_SZ 32
#define ESP_QUICKIRQ_LIMIT 100
#define ESP_RESELECT_TAG_LIMIT 2500
struct esp {
void __iomem *regs;
void __iomem *dma_regs;
const struct esp_driver_ops *ops;
struct Scsi_Host *host;
void *dev;
struct esp_cmd_entry *active_cmd;
struct list_head queued_cmds;
struct list_head active_cmds;
u8 *command_block;
dma_addr_t command_block_dma;
unsigned int data_dma_len;
/* The following are used to determine the cause of an IRQ. Upon every
* IRQ entry we synchronize these with the hardware registers.
*/
u8 sreg;
u8 seqreg;
u8 sreg2;
u8 ireg;
u32 prev_hme_dmacsr;
u8 prev_soff;
u8 prev_stp;
u8 prev_cfg3;
u8 __pad;
struct list_head esp_cmd_pool;
struct esp_target_data target[ESP_MAX_TARGET];
int fifo_cnt;
u8 fifo[16];
struct esp_event_ent esp_event_log[ESP_EVENT_LOG_SZ];
int esp_event_cur;
u8 msg_out[ESP_MAX_MSG_SZ];
int msg_out_len;
u8 msg_in[ESP_MAX_MSG_SZ];
int msg_in_len;
u8 bursts;
u8 config1;
u8 config2;
u8 scsi_id;
u32 scsi_id_mask;
enum esp_rev rev;
u32 flags;
#define ESP_FLAG_DIFFERENTIAL 0x00000001
#define ESP_FLAG_RESETTING 0x00000002
#define ESP_FLAG_DOING_SLOWCMD 0x00000004
#define ESP_FLAG_WIDE_CAPABLE 0x00000008
#define ESP_FLAG_QUICKIRQ_CHECK 0x00000010
u8 select_state;
#define ESP_SELECT_NONE 0x00 /* Not selecting */
#define ESP_SELECT_BASIC 0x01 /* Select w/o MSGOUT phase */
#define ESP_SELECT_MSGOUT 0x02 /* Select with MSGOUT */
/* When we are not selecting, we are expecting an event. */
u8 event;
#define ESP_EVENT_NONE 0x00
#define ESP_EVENT_CMD_START 0x01
#define ESP_EVENT_CMD_DONE 0x02
#define ESP_EVENT_DATA_IN 0x03
#define ESP_EVENT_DATA_OUT 0x04
#define ESP_EVENT_DATA_DONE 0x05
#define ESP_EVENT_MSGIN 0x06
#define ESP_EVENT_MSGIN_MORE 0x07
#define ESP_EVENT_MSGIN_DONE 0x08
#define ESP_EVENT_MSGOUT 0x09
#define ESP_EVENT_MSGOUT_DONE 0x0a
#define ESP_EVENT_STATUS 0x0b
#define ESP_EVENT_FREE_BUS 0x0c
#define ESP_EVENT_CHECK_PHASE 0x0d
#define ESP_EVENT_RESET 0x10
/* Probed in esp_get_clock_params() */
u32 cfact;
u32 cfreq;
u32 ccycle;
u32 ctick;
u32 neg_defp;
u32 sync_defp;
/* Computed in esp_reset_esp() */
u32 max_period;
u32 min_period;
u32 radelay;
/* Slow command state. */
u8 *cmd_bytes_ptr;
int cmd_bytes_left;
struct completion *eh_reset;
struct sbus_dma *dma;
};
#define host_to_esp(host) ((struct esp *)(host)->hostdata)
/* A front-end driver for the ESP chip should do the following in
* it's device probe routine:
* 1) Allocate the host and private area using scsi_host_alloc()
* with size 'sizeof(struct esp)'. The first argument to
* scsi_host_alloc() should be &scsi_esp_template.
* 2) Set host->max_id as appropriate.
* 3) Set esp->host to the scsi_host itself, and esp->dev
* to the device object pointer.
* 4) Hook up esp->ops to the front-end implementation.
* 5) If the ESP chip supports wide transfers, set ESP_FLAG_WIDE_CAPABLE
* in esp->flags.
* 6) Map the DMA and ESP chip registers.
* 7) DMA map the ESP command block, store the DMA address
* in esp->command_block_dma.
* 8) Register the scsi_esp_intr() interrupt handler.
* 9) Probe for and provide the following chip properties:
* esp->scsi_id (assign to esp->host->this_id too)
* esp->scsi_id_mask
* If ESP bus is differential, set ESP_FLAG_DIFFERENTIAL
* esp->cfreq
* DMA burst bit mask in esp->bursts, if necessary
* 10) Perform any actions necessary before the ESP device can
* be programmed for the first time. On some configs, for
* example, the DMA engine has to be reset before ESP can
* be programmed.
* 11) If necessary, call dev_set_drvdata() as needed.
* 12) Call scsi_esp_register() with prepared 'esp' structure
* and a device pointer if possible.
* 13) Check scsi_esp_register() return value, release all resources
* if an error was returned.
*/
extern struct scsi_host_template scsi_esp_template;
extern int scsi_esp_register(struct esp *, struct device *);
extern void scsi_esp_unregister(struct esp *);
extern irqreturn_t scsi_esp_intr(int, void *);
extern void scsi_esp_cmd(struct esp *, u8);
#endif /* !(_ESP_SCSI_H) */

View File

@ -1403,7 +1403,7 @@ static int __devinit qpti_sbus_probe(struct of_device *dev, const struct of_devi
struct scsi_host_template *tpnt = match->data;
struct Scsi_Host *host;
struct qlogicpti *qpti;
char *fcode;
const char *fcode;
/* Sometimes Antares cards come up not completely
* setup, and we get a report of a zero IRQ.

634
drivers/scsi/sun_esp.c Normal file
View File

@ -0,0 +1,634 @@
/* sun_esp.c: ESP front-end for Sparc SBUS systems.
*
* Copyright (C) 2007 David S. Miller (davem@davemloft.net)
*/
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/module.h>
#include <linux/init.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <asm/dma.h>
#include <asm/sbus.h>
#include <scsi/scsi_host.h>
#include "esp_scsi.h"
#define DRV_MODULE_NAME "sun_esp"
#define PFX DRV_MODULE_NAME ": "
#define DRV_VERSION "1.000"
#define DRV_MODULE_RELDATE "April 19, 2007"
#define dma_read32(REG) \
sbus_readl(esp->dma_regs + (REG))
#define dma_write32(VAL, REG) \
sbus_writel((VAL), esp->dma_regs + (REG))
static int __devinit esp_sbus_find_dma(struct esp *esp, struct sbus_dev *dma_sdev)
{
struct sbus_dev *sdev = esp->dev;
struct sbus_dma *dma;
if (dma_sdev != NULL) {
for_each_dvma(dma) {
if (dma->sdev == dma_sdev)
break;
}
} else {
for_each_dvma(dma) {
if (dma->sdev == NULL)
break;
/* If bus + slot are the same and it has the
* correct OBP name, it's ours.
*/
if (sdev->bus == dma->sdev->bus &&
sdev->slot == dma->sdev->slot &&
(!strcmp(dma->sdev->prom_name, "dma") ||
!strcmp(dma->sdev->prom_name, "espdma")))
break;
}
}
if (dma == NULL) {
printk(KERN_ERR PFX "[%s] Cannot find dma.\n",
sdev->ofdev.node->full_name);
return -ENODEV;
}
esp->dma = dma;
esp->dma_regs = dma->regs;
return 0;
}
static int __devinit esp_sbus_map_regs(struct esp *esp, int hme)
{
struct sbus_dev *sdev = esp->dev;
struct resource *res;
/* On HME, two reg sets exist, first is DVMA,
* second is ESP registers.
*/
if (hme)
res = &sdev->resource[1];
else
res = &sdev->resource[0];
esp->regs = sbus_ioremap(res, 0, SBUS_ESP_REG_SIZE, "ESP");
if (!esp->regs)
return -ENOMEM;
return 0;
}
static int __devinit esp_sbus_map_command_block(struct esp *esp)
{
struct sbus_dev *sdev = esp->dev;
esp->command_block = sbus_alloc_consistent(sdev, 16,
&esp->command_block_dma);
if (!esp->command_block)
return -ENOMEM;
return 0;
}
static int __devinit esp_sbus_register_irq(struct esp *esp)
{
struct Scsi_Host *host = esp->host;
struct sbus_dev *sdev = esp->dev;
host->irq = sdev->irqs[0];
return request_irq(host->irq, scsi_esp_intr, IRQF_SHARED, "ESP", esp);
}
static void __devinit esp_get_scsi_id(struct esp *esp)
{
struct sbus_dev *sdev = esp->dev;
struct device_node *dp = sdev->ofdev.node;
esp->scsi_id = of_getintprop_default(dp, "initiator-id", 0xff);
if (esp->scsi_id != 0xff)
goto done;
esp->scsi_id = of_getintprop_default(dp, "scsi-initiator-id", 0xff);
if (esp->scsi_id != 0xff)
goto done;
if (!sdev->bus) {
/* SUN4 */
esp->scsi_id = 7;
goto done;
}
esp->scsi_id = of_getintprop_default(sdev->bus->ofdev.node,
"scsi-initiator-id", 7);
done:
esp->host->this_id = esp->scsi_id;
esp->scsi_id_mask = (1 << esp->scsi_id);
}
static void __devinit esp_get_differential(struct esp *esp)
{
struct sbus_dev *sdev = esp->dev;
struct device_node *dp = sdev->ofdev.node;
if (of_find_property(dp, "differential", NULL))
esp->flags |= ESP_FLAG_DIFFERENTIAL;
else
esp->flags &= ~ESP_FLAG_DIFFERENTIAL;
}
static void __devinit esp_get_clock_params(struct esp *esp)
{
struct sbus_dev *sdev = esp->dev;
struct device_node *dp = sdev->ofdev.node;
struct device_node *bus_dp;
int fmhz;
bus_dp = NULL;
if (sdev != NULL && sdev->bus != NULL)
bus_dp = sdev->bus->ofdev.node;
fmhz = of_getintprop_default(dp, "clock-frequency", 0);
if (fmhz == 0)
fmhz = (!bus_dp) ? 0 :
of_getintprop_default(bus_dp, "clock-frequency", 0);
esp->cfreq = fmhz;
}
static void __devinit esp_get_bursts(struct esp *esp, struct sbus_dev *dma)
{
struct sbus_dev *sdev = esp->dev;
struct device_node *dp = sdev->ofdev.node;
u8 bursts;
bursts = of_getintprop_default(dp, "burst-sizes", 0xff);
if (dma) {
struct device_node *dma_dp = dma->ofdev.node;
u8 val = of_getintprop_default(dma_dp, "burst-sizes", 0xff);
if (val != 0xff)
bursts &= val;
}
if (sdev->bus) {
u8 val = of_getintprop_default(sdev->bus->ofdev.node,
"burst-sizes", 0xff);
if (val != 0xff)
bursts &= val;
}
if (bursts == 0xff ||
(bursts & DMA_BURST16) == 0 ||
(bursts & DMA_BURST32) == 0)
bursts = (DMA_BURST32 - 1);
esp->bursts = bursts;
}
static void __devinit esp_sbus_get_props(struct esp *esp, struct sbus_dev *espdma)
{
esp_get_scsi_id(esp);
esp_get_differential(esp);
esp_get_clock_params(esp);
esp_get_bursts(esp, espdma);
}
static void sbus_esp_write8(struct esp *esp, u8 val, unsigned long reg)
{
sbus_writeb(val, esp->regs + (reg * 4UL));
}
static u8 sbus_esp_read8(struct esp *esp, unsigned long reg)
{
return sbus_readb(esp->regs + (reg * 4UL));
}
static dma_addr_t sbus_esp_map_single(struct esp *esp, void *buf,
size_t sz, int dir)
{
return sbus_map_single(esp->dev, buf, sz, dir);
}
static int sbus_esp_map_sg(struct esp *esp, struct scatterlist *sg,
int num_sg, int dir)
{
return sbus_map_sg(esp->dev, sg, num_sg, dir);
}
static void sbus_esp_unmap_single(struct esp *esp, dma_addr_t addr,
size_t sz, int dir)
{
sbus_unmap_single(esp->dev, addr, sz, dir);
}
static void sbus_esp_unmap_sg(struct esp *esp, struct scatterlist *sg,
int num_sg, int dir)
{
sbus_unmap_sg(esp->dev, sg, num_sg, dir);
}
static int sbus_esp_irq_pending(struct esp *esp)
{
if (dma_read32(DMA_CSR) & (DMA_HNDL_INTR | DMA_HNDL_ERROR))
return 1;
return 0;
}
static void sbus_esp_reset_dma(struct esp *esp)
{
int can_do_burst16, can_do_burst32, can_do_burst64;
int can_do_sbus64, lim;
u32 val;
can_do_burst16 = (esp->bursts & DMA_BURST16) != 0;
can_do_burst32 = (esp->bursts & DMA_BURST32) != 0;
can_do_burst64 = 0;
can_do_sbus64 = 0;
if (sbus_can_dma_64bit(esp->dev))
can_do_sbus64 = 1;
if (sbus_can_burst64(esp->sdev))
can_do_burst64 = (esp->bursts & DMA_BURST64) != 0;
/* Put the DVMA into a known state. */
if (esp->dma->revision != dvmahme) {
val = dma_read32(DMA_CSR);
dma_write32(val | DMA_RST_SCSI, DMA_CSR);
dma_write32(val & ~DMA_RST_SCSI, DMA_CSR);
}
switch (esp->dma->revision) {
case dvmahme:
dma_write32(DMA_RESET_FAS366, DMA_CSR);
dma_write32(DMA_RST_SCSI, DMA_CSR);
esp->prev_hme_dmacsr = (DMA_PARITY_OFF | DMA_2CLKS |
DMA_SCSI_DISAB | DMA_INT_ENAB);
esp->prev_hme_dmacsr &= ~(DMA_ENABLE | DMA_ST_WRITE |
DMA_BRST_SZ);
if (can_do_burst64)
esp->prev_hme_dmacsr |= DMA_BRST64;
else if (can_do_burst32)
esp->prev_hme_dmacsr |= DMA_BRST32;
if (can_do_sbus64) {
esp->prev_hme_dmacsr |= DMA_SCSI_SBUS64;
sbus_set_sbus64(esp->dev, esp->bursts);
}
lim = 1000;
while (dma_read32(DMA_CSR) & DMA_PEND_READ) {
if (--lim == 0) {
printk(KERN_ALERT PFX "esp%d: DMA_PEND_READ "
"will not clear!\n",
esp->host->unique_id);
break;
}
udelay(1);
}
dma_write32(0, DMA_CSR);
dma_write32(esp->prev_hme_dmacsr, DMA_CSR);
dma_write32(0, DMA_ADDR);
break;
case dvmarev2:
if (esp->rev != ESP100) {
val = dma_read32(DMA_CSR);
dma_write32(val | DMA_3CLKS, DMA_CSR);
}
break;
case dvmarev3:
val = dma_read32(DMA_CSR);
val &= ~DMA_3CLKS;
val |= DMA_2CLKS;
if (can_do_burst32) {
val &= ~DMA_BRST_SZ;
val |= DMA_BRST32;
}
dma_write32(val, DMA_CSR);
break;
case dvmaesc1:
val = dma_read32(DMA_CSR);
val |= DMA_ADD_ENABLE;
val &= ~DMA_BCNT_ENAB;
if (!can_do_burst32 && can_do_burst16) {
val |= DMA_ESC_BURST;
} else {
val &= ~(DMA_ESC_BURST);
}
dma_write32(val, DMA_CSR);
break;
default:
break;
}
/* Enable interrupts. */
val = dma_read32(DMA_CSR);
dma_write32(val | DMA_INT_ENAB, DMA_CSR);
}
static void sbus_esp_dma_drain(struct esp *esp)
{
u32 csr;
int lim;
if (esp->dma->revision == dvmahme)
return;
csr = dma_read32(DMA_CSR);
if (!(csr & DMA_FIFO_ISDRAIN))
return;
if (esp->dma->revision != dvmarev3 && esp->dma->revision != dvmaesc1)
dma_write32(csr | DMA_FIFO_STDRAIN, DMA_CSR);
lim = 1000;
while (dma_read32(DMA_CSR) & DMA_FIFO_ISDRAIN) {
if (--lim == 0) {
printk(KERN_ALERT PFX "esp%d: DMA will not drain!\n",
esp->host->unique_id);
break;
}
udelay(1);
}
}
static void sbus_esp_dma_invalidate(struct esp *esp)
{
if (esp->dma->revision == dvmahme) {
dma_write32(DMA_RST_SCSI, DMA_CSR);
esp->prev_hme_dmacsr = ((esp->prev_hme_dmacsr |
(DMA_PARITY_OFF | DMA_2CLKS |
DMA_SCSI_DISAB | DMA_INT_ENAB)) &
~(DMA_ST_WRITE | DMA_ENABLE));
dma_write32(0, DMA_CSR);
dma_write32(esp->prev_hme_dmacsr, DMA_CSR);
/* This is necessary to avoid having the SCSI channel
* engine lock up on us.
*/
dma_write32(0, DMA_ADDR);
} else {
u32 val;
int lim;
lim = 1000;
while ((val = dma_read32(DMA_CSR)) & DMA_PEND_READ) {
if (--lim == 0) {
printk(KERN_ALERT PFX "esp%d: DMA will not "
"invalidate!\n", esp->host->unique_id);
break;
}
udelay(1);
}
val &= ~(DMA_ENABLE | DMA_ST_WRITE | DMA_BCNT_ENAB);
val |= DMA_FIFO_INV;
dma_write32(val, DMA_CSR);
val &= ~DMA_FIFO_INV;
dma_write32(val, DMA_CSR);
}
}
static void sbus_esp_send_dma_cmd(struct esp *esp, u32 addr, u32 esp_count,
u32 dma_count, int write, u8 cmd)
{
u32 csr;
BUG_ON(!(cmd & ESP_CMD_DMA));
sbus_esp_write8(esp, (esp_count >> 0) & 0xff, ESP_TCLOW);
sbus_esp_write8(esp, (esp_count >> 8) & 0xff, ESP_TCMED);
if (esp->rev == FASHME) {
sbus_esp_write8(esp, (esp_count >> 16) & 0xff, FAS_RLO);
sbus_esp_write8(esp, 0, FAS_RHI);
scsi_esp_cmd(esp, cmd);
csr = esp->prev_hme_dmacsr;
csr |= DMA_SCSI_DISAB | DMA_ENABLE;
if (write)
csr |= DMA_ST_WRITE;
else
csr &= ~DMA_ST_WRITE;
esp->prev_hme_dmacsr = csr;
dma_write32(dma_count, DMA_COUNT);
dma_write32(addr, DMA_ADDR);
dma_write32(csr, DMA_CSR);
} else {
csr = dma_read32(DMA_CSR);
csr |= DMA_ENABLE;
if (write)
csr |= DMA_ST_WRITE;
else
csr &= ~DMA_ST_WRITE;
dma_write32(csr, DMA_CSR);
if (esp->dma->revision == dvmaesc1) {
u32 end = PAGE_ALIGN(addr + dma_count + 16U);
dma_write32(end - addr, DMA_COUNT);
}
dma_write32(addr, DMA_ADDR);
scsi_esp_cmd(esp, cmd);
}
}
static int sbus_esp_dma_error(struct esp *esp)
{
u32 csr = dma_read32(DMA_CSR);
if (csr & DMA_HNDL_ERROR)
return 1;
return 0;
}
static const struct esp_driver_ops sbus_esp_ops = {
.esp_write8 = sbus_esp_write8,
.esp_read8 = sbus_esp_read8,
.map_single = sbus_esp_map_single,
.map_sg = sbus_esp_map_sg,
.unmap_single = sbus_esp_unmap_single,
.unmap_sg = sbus_esp_unmap_sg,
.irq_pending = sbus_esp_irq_pending,
.reset_dma = sbus_esp_reset_dma,
.dma_drain = sbus_esp_dma_drain,
.dma_invalidate = sbus_esp_dma_invalidate,
.send_dma_cmd = sbus_esp_send_dma_cmd,
.dma_error = sbus_esp_dma_error,
};
static int __devinit esp_sbus_probe_one(struct device *dev,
struct sbus_dev *esp_dev,
struct sbus_dev *espdma,
struct sbus_bus *sbus,
int hme)
{
struct scsi_host_template *tpnt = &scsi_esp_template;
struct Scsi_Host *host;
struct esp *esp;
int err;
host = scsi_host_alloc(tpnt, sizeof(struct esp));
err = -ENOMEM;
if (!host)
goto fail;
host->max_id = (hme ? 16 : 8);
esp = host_to_esp(host);
esp->host = host;
esp->dev = esp_dev;
esp->ops = &sbus_esp_ops;
if (hme)
esp->flags |= ESP_FLAG_WIDE_CAPABLE;
err = esp_sbus_find_dma(esp, espdma);
if (err < 0)
goto fail_unlink;
err = esp_sbus_map_regs(esp, hme);
if (err < 0)
goto fail_unlink;
err = esp_sbus_map_command_block(esp);
if (err < 0)
goto fail_unmap_regs;
err = esp_sbus_register_irq(esp);
if (err < 0)
goto fail_unmap_command_block;
esp_sbus_get_props(esp, espdma);
/* Before we try to touch the ESP chip, ESC1 dma can
* come up with the reset bit set, so make sure that
* is clear first.
*/
if (esp->dma->revision == dvmaesc1) {
u32 val = dma_read32(DMA_CSR);
dma_write32(val & ~DMA_RST_SCSI, DMA_CSR);
}
dev_set_drvdata(&esp_dev->ofdev.dev, esp);
err = scsi_esp_register(esp, dev);
if (err)
goto fail_free_irq;
return 0;
fail_free_irq:
free_irq(host->irq, esp);
fail_unmap_command_block:
sbus_free_consistent(esp->dev, 16,
esp->command_block,
esp->command_block_dma);
fail_unmap_regs:
sbus_iounmap(esp->regs, SBUS_ESP_REG_SIZE);
fail_unlink:
scsi_host_put(host);
fail:
return err;
}
static int __devinit esp_sbus_probe(struct of_device *dev, const struct of_device_id *match)
{
struct sbus_dev *sdev = to_sbus_device(&dev->dev);
struct device_node *dp = dev->node;
struct sbus_dev *dma_sdev = NULL;
int hme = 0;
if (dp->parent &&
(!strcmp(dp->parent->name, "espdma") ||
!strcmp(dp->parent->name, "dma")))
dma_sdev = sdev->parent;
else if (!strcmp(dp->name, "SUNW,fas")) {
dma_sdev = sdev;
hme = 1;
}
return esp_sbus_probe_one(&dev->dev, sdev, dma_sdev,
sdev->bus, hme);
}
static int __devexit esp_sbus_remove(struct of_device *dev)
{
struct esp *esp = dev_get_drvdata(&dev->dev);
unsigned int irq = esp->host->irq;
u32 val;
scsi_esp_unregister(esp);
/* Disable interrupts. */
val = dma_read32(DMA_CSR);
dma_write32(val & ~DMA_INT_ENAB, DMA_CSR);
free_irq(irq, esp);
sbus_free_consistent(esp->dev, 16,
esp->command_block,
esp->command_block_dma);
sbus_iounmap(esp->regs, SBUS_ESP_REG_SIZE);
scsi_host_put(esp->host);
return 0;
}
static struct of_device_id esp_match[] = {
{
.name = "SUNW,esp",
},
{
.name = "SUNW,fas",
},
{
.name = "esp",
},
{},
};
MODULE_DEVICE_TABLE(of, esp_match);
static struct of_platform_driver esp_sbus_driver = {
.name = "esp",
.match_table = esp_match,
.probe = esp_sbus_probe,
.remove = __devexit_p(esp_sbus_remove),
};
static int __init sunesp_init(void)
{
return of_register_driver(&esp_sbus_driver, &sbus_bus_type);
}
static void __exit sunesp_exit(void)
{
of_unregister_driver(&esp_sbus_driver);
}
MODULE_DESCRIPTION("Sun ESP SCSI driver");
MODULE_AUTHOR("David S. Miller (davem@davemloft.net)");
MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_VERSION);
module_init(sunesp_init);
module_exit(sunesp_exit);

View File

@ -1387,8 +1387,8 @@ static enum su_type __devinit su_get_type(struct device_node *dp)
struct device_node *ap = of_find_node_by_path("/aliases");
if (ap) {
char *keyb = of_get_property(ap, "keyboard", NULL);
char *ms = of_get_property(ap, "mouse", NULL);
const char *keyb = of_get_property(ap, "keyboard", NULL);
const char *ms = of_get_property(ap, "mouse", NULL);
if (keyb) {
if (dp == of_find_node_by_path(keyb))

View File

@ -2899,7 +2899,7 @@ static int __devinit atyfb_setup_sparc(struct pci_dev *pdev,
struct fb_info *info, unsigned long addr)
{
struct atyfb_par *par = info->par;
struct pcidev_cookie *pcp;
struct device_node *dp;
char prop[128];
int node, len, i, j, ret;
u32 mem, chip_id;
@ -3037,8 +3037,8 @@ static int __devinit atyfb_setup_sparc(struct pci_dev *pdev,
node = 0;
}
pcp = pdev->sysdata;
if (node == pcp->prom_node->node) {
dp = pci_device_to_OF_node(pdev);
if (node == dp->node) {
struct fb_var_screeninfo *var = &default_var;
unsigned int N, P, Q, M, T, R;
u32 v_total, h_total;

View File

@ -410,7 +410,7 @@ static int __devinit radeon_find_mem_vbios(struct radeonfb_info *rinfo)
}
#endif
#ifdef CONFIG_PPC_OF
#if defined(CONFIG_PPC_OF) || defined(CONFIG_SPARC)
/*
* Read XTAL (ref clock), SCLK and MCLK from Open Firmware device
* tree. Hopefully, ATI OF driver is kind enough to fill these
@ -440,7 +440,7 @@ static int __devinit radeon_read_xtal_OF (struct radeonfb_info *rinfo)
return 0;
}
#endif /* CONFIG_PPC_OF */
#endif /* CONFIG_PPC_OF || CONFIG_SPARC */
/*
* Read PLL infos from chip registers
@ -645,7 +645,7 @@ static void __devinit radeon_get_pllinfo(struct radeonfb_info *rinfo)
rinfo->pll.ref_div = INPLL(PPLL_REF_DIV) & PPLL_REF_DIV_MASK;
#ifdef CONFIG_PPC_OF
#if defined(CONFIG_PPC_OF) || defined(CONFIG_SPARC)
/*
* Retrieve PLL infos from Open Firmware first
*/
@ -653,7 +653,7 @@ static void __devinit radeon_get_pllinfo(struct radeonfb_info *rinfo)
printk(KERN_INFO "radeonfb: Retrieved PLL infos from Open Firmware\n");
goto found;
}
#endif /* CONFIG_PPC_OF */
#endif /* CONFIG_PPC_OF || CONFIG_SPARC */
/*
* Check out if we have an X86 which gave us some PLL informations
@ -2231,7 +2231,7 @@ static int __devinit radeonfb_pci_register (struct pci_dev *pdev,
rinfo->family == CHIP_FAMILY_RS200)
rinfo->errata |= CHIP_ERRATA_PLL_DELAY;
#ifdef CONFIG_PPC_OF
#if defined(CONFIG_PPC_OF) || defined(CONFIG_SPARC)
/* On PPC, we obtain the OF device-node pointer to the firmware
* data for this chip
*/
@ -2240,6 +2240,8 @@ static int __devinit radeonfb_pci_register (struct pci_dev *pdev,
printk(KERN_WARNING "radeonfb (%s): Cannot match card to OF node !\n",
pci_name(rinfo->pdev));
#endif /* CONFIG_PPC_OF || CONFIG_SPARC */
#ifdef CONFIG_PPC_OF
/* On PPC, the firmware sets up a memory mapping that tends
* to cause lockups when enabling the engine. We reconfigure
* the card internal memory mappings properly

View File

@ -52,7 +52,7 @@ static char *radeon_get_mon_name(int type)
}
#ifdef CONFIG_PPC_OF
#if defined(CONFIG_PPC_OF) || defined(CONFIG_SPARC)
/*
* Try to find monitor informations & EDID data out of the Open Firmware
* device-tree. This also contains some "hacks" to work around a few machine
@ -156,7 +156,7 @@ static int __devinit radeon_probe_OF_head(struct radeonfb_info *rinfo, int head_
}
return MT_NONE;
}
#endif /* CONFIG_PPC_OF */
#endif /* CONFIG_PPC_OF || CONFIG_SPARC */
static int __devinit radeon_get_panel_info_BIOS(struct radeonfb_info *rinfo)
@ -495,11 +495,11 @@ void __devinit radeon_probe_screens(struct radeonfb_info *rinfo,
* Old single head cards
*/
if (!rinfo->has_CRTC2) {
#ifdef CONFIG_PPC_OF
#if defined(CONFIG_PPC_OF) || defined(CONFIG_SPARC)
if (rinfo->mon1_type == MT_NONE)
rinfo->mon1_type = radeon_probe_OF_head(rinfo, 0,
&rinfo->mon1_EDID);
#endif /* CONFIG_PPC_OF */
#endif /* CONFIG_PPC_OF || CONFIG_SPARC */
#ifdef CONFIG_FB_RADEON_I2C
if (rinfo->mon1_type == MT_NONE)
rinfo->mon1_type =
@ -544,11 +544,11 @@ void __devinit radeon_probe_screens(struct radeonfb_info *rinfo,
/*
* Probe primary head (DVI or laptop internal panel)
*/
#ifdef CONFIG_PPC_OF
#if defined(CONFIG_PPC_OF) || defined(CONFIG_SPARC)
if (rinfo->mon1_type == MT_NONE)
rinfo->mon1_type = radeon_probe_OF_head(rinfo, 0,
&rinfo->mon1_EDID);
#endif /* CONFIG_PPC_OF */
#endif /* CONFIG_PPC_OF || CONFIG_SPARC */
#ifdef CONFIG_FB_RADEON_I2C
if (rinfo->mon1_type == MT_NONE)
rinfo->mon1_type = radeon_probe_i2c_connector(rinfo, ddc_dvi,
@ -572,11 +572,11 @@ void __devinit radeon_probe_screens(struct radeonfb_info *rinfo,
/*
* Probe secondary head (mostly VGA, can be DVI)
*/
#ifdef CONFIG_PPC_OF
#if defined(CONFIG_PPC_OF) || defined(CONFIG_SPARC)
if (rinfo->mon2_type == MT_NONE)
rinfo->mon2_type = radeon_probe_OF_head(rinfo, 1,
&rinfo->mon2_EDID);
#endif /* CONFIG_PPC_OF */
#endif /* CONFIG_PPC_OF || defined(CONFIG_SPARC) */
#ifdef CONFIG_FB_RADEON_I2C
if (rinfo->mon2_type == MT_NONE)
rinfo->mon2_type = radeon_probe_i2c_connector(rinfo, ddc_vga,

View File

@ -16,7 +16,7 @@
#include <asm/io.h>
#ifdef CONFIG_PPC_OF
#if defined(CONFIG_PPC_OF) || defined(CONFIG_SPARC)
#include <asm/prom.h>
#endif
@ -292,7 +292,7 @@ struct radeonfb_info {
unsigned long fb_local_base;
struct pci_dev *pdev;
#ifdef CONFIG_PPC_OF
#if defined(CONFIG_PPC_OF) || defined(CONFIG_SPARC)
struct device_node *of_node;
#endif

View File

@ -266,7 +266,7 @@ static void __devinit cg3_init_fix(struct fb_info *info, int linebytes,
static void __devinit cg3_rdi_maybe_fixup_var(struct fb_var_screeninfo *var,
struct device_node *dp)
{
char *params;
const char *params;
char *p;
int ww, hh;

View File

@ -44,8 +44,8 @@
#include <asm/io.h>
#ifdef __sparc__
#include <asm/pbm.h>
#ifdef CONFIG_SPARC
#include <asm/prom.h>
#include <asm/pcic.h>
#endif
@ -96,7 +96,7 @@ struct fb_var_screeninfo default_var = {
.vmode = FB_VMODE_NONINTERLACED
};
#ifdef __sparc__
#ifdef CONFIG_SPARC
struct fb_var_screeninfo default_var_1024x768 __initdata = {
/* 1024x768, 75 Hz, Non-Interlaced (78.75 MHz dotclock) */
.xres = 1024,
@ -188,7 +188,7 @@ static inline void iga_outb(struct iga_par *par, unsigned char val,
pci_outb(par, val, reg+1);
}
#endif /* __sparc__ */
#endif /* CONFIG_SPARC */
/*
* Very important functionality for the JavaEngine1 computer:
@ -217,7 +217,7 @@ static void iga_blank_border(struct iga_par *par)
iga_outb(par, 0, IGA_EXT_CNTRL, IGA_IDX_OVERSCAN_COLOR + i);
}
#ifdef __sparc__
#ifdef CONFIG_SPARC
static int igafb_mmap(struct fb_info *info,
struct vm_area_struct *vma)
{
@ -271,7 +271,7 @@ static int igafb_mmap(struct fb_info *info,
vma->vm_flags |= VM_IO;
return 0;
}
#endif /* __sparc__ */
#endif /* CONFIG_SPARC */
static int igafb_setcolreg(unsigned regno, unsigned red, unsigned green,
unsigned blue, unsigned transp,
@ -323,7 +323,7 @@ static struct fb_ops igafb_ops = {
.fb_fillrect = cfb_fillrect,
.fb_copyarea = cfb_copyarea,
.fb_imageblit = cfb_imageblit,
#ifdef __sparc__
#ifdef CONFIG_SPARC
.fb_mmap = igafb_mmap,
#endif
};
@ -424,7 +424,7 @@ int __init igafb_init(void)
par->frame_buffer_phys = addr & PCI_BASE_ADDRESS_MEM_MASK;
#ifdef __sparc__
#ifdef CONFIG_SPARC
/*
* The following is sparc specific and this is why:
*
@ -477,8 +477,8 @@ int __init igafb_init(void)
* Set default vmode and cmode from PROM properties.
*/
{
struct pcidev_cookie *cookie = pdev->sysdata;
int node = cookie->prom_node;
struct device_node *dp = pci_device_to_OF_node(pdev);
int node = dp->node;
int width = prom_getintdefault(node, "width", 1024);
int height = prom_getintdefault(node, "height", 768);
int depth = prom_getintdefault(node, "depth", 8);
@ -534,7 +534,7 @@ int __init igafb_init(void)
kfree(info);
}
#ifdef __sparc__
#ifdef CONFIG_SPARC
/*
* Add /dev/fb mmap values.
*/
@ -552,7 +552,7 @@ int __init igafb_init(void)
par->mmap_map[1].size = PAGE_SIZE * 2; /* X wants 2 pages */
par->mmap_map[1].prot_mask = SRMMU_CACHE;
par->mmap_map[1].prot_flag = SRMMU_WRITE;
#endif /* __sparc__ */
#endif /* CONFIG_SPARC */
return 0;
}

View File

@ -61,8 +61,6 @@ extern void * __memsetw(void *dest, unsigned short, size_t count);
? __constant_c_memset((s),0x0001000100010001UL*(unsigned short)(c),(n)) \
: __memsetw((s),(c),(n)))
extern int strcasecmp(const char *, const char *);
#endif /* __KERNEL__ */
#endif /* __ALPHA_STRING_H__ */

View File

@ -14,8 +14,6 @@
#define __HAVE_ARCH_MEMCMP
#define __HAVE_ARCH_MEMCHR
extern int strcasecmp(const char *, const char *);
extern int strncasecmp(const char *, const char *, __kernel_size_t);
extern char * strcpy(char *,const char *);
extern char * strncpy(char *,const char *, __kernel_size_t);
extern __kernel_size_t strlen(const char *);

View File

@ -126,9 +126,6 @@ extern void *memchr(const void *__s, int __c, size_t __n);
#define __HAVE_ARCH_STRLEN
extern size_t strlen(const char *);
/* arch/sh/lib/strcasecmp.c */
extern int strcasecmp(const char *, const char *);
#endif /* __KERNEL__ */
#endif /* __ASM_SH_STRING_H */

View File

@ -35,8 +35,8 @@ struct property {
};
struct device_node {
char *name;
char *type;
const char *name;
const char *type;
phandle node;
char *path_component_name;
char *full_name;
@ -85,12 +85,14 @@ extern struct device_node *of_find_node_by_phandle(phandle handle);
extern struct device_node *of_get_parent(const struct device_node *node);
extern struct device_node *of_get_next_child(const struct device_node *node,
struct device_node *prev);
extern struct property *of_find_property(struct device_node *np,
extern struct property *of_find_property(const struct device_node *np,
const char *name,
int *lenp);
extern int of_device_is_compatible(struct device_node *device, const char *);
extern void *of_get_property(struct device_node *node, const char *name,
int *lenp);
extern int of_device_is_compatible(const struct device_node *device,
const char *);
extern const void *of_get_property(const struct device_node *node,
const char *name,
int *lenp);
#define get_property(node,name,lenp) of_get_property(node,name,lenp)
extern int of_set_property(struct device_node *node, const char *name, void *val, int len);
extern int of_getintprop_default(struct device_node *np,

View File

@ -17,8 +17,8 @@
typedef struct {
/* Dcache line 1 */
unsigned int __softirq_pending; /* must be 1st, see rtrap.S */
unsigned int multiplier;
unsigned int counter;
unsigned int __pad0_1;
unsigned int __pad0_2;
unsigned int __pad1;
unsigned long clock_tick; /* %tick's per second */
unsigned long udelay_val;

View File

@ -3,5 +3,21 @@
*
* This file is released under the GPLv2
*/
#include <asm-generic/device.h>
#ifndef _ASM_SPARC64_DEVICE_H
#define _ASM_SPARC64_DEVICE_H
struct device_node;
struct of_device;
struct dev_archdata {
void *iommu;
void *stc;
void *host_controller;
struct device_node *prom_node;
struct of_device *op;
unsigned int msi_num;
};
#endif /* _ASM_SPARC64_DEVICE_H */

View File

@ -8,7 +8,6 @@
#ifndef __SPARC64_EBUS_H
#define __SPARC64_EBUS_H
#include <asm/pbm.h>
#include <asm/oplib.h>
#include <asm/prom.h>
#include <asm/of_device.h>
@ -41,7 +40,6 @@ struct linux_ebus {
struct of_device ofdev;
struct linux_ebus *next;
struct linux_ebus_device *devices;
struct pci_pbm_info *parent;
struct pci_dev *self;
int index;
int is_rio;

View File

@ -549,7 +549,7 @@ static int __init ebus_fdthree_p(struct linux_ebus_device *edev)
if (!strcmp(edev->prom_node->name, "fdthree"))
return 1;
if (!strcmp(edev->prom_node->name, "floppy")) {
char *compat;
const char *compat;
compat = of_get_property(edev->prom_node,
"compatible", NULL);
@ -661,7 +661,7 @@ static unsigned long __init sun_floppy_init(void)
struct linux_ebus_device *edev = NULL;
unsigned long config = 0;
void __iomem *auxio_reg;
char *state_prop;
const char *state_prop;
for_each_ebus(ebus) {
for_each_ebusdev(edev, ebus) {

View File

@ -24,14 +24,6 @@ extern unsigned long kern_base, kern_size;
#define page_to_phys(page) (page_to_pfn(page) << PAGE_SHIFT)
#define BIO_VMERGE_BOUNDARY 8192
/* Different PCI controllers we support have their PCI MEM space
* mapped to an either 2GB (Psycho) or 4GB (Sabre) aligned area,
* so need to chop off the top 33 or 32 bits.
*/
extern unsigned long pci_memspace_mask;
#define bus_dvma_to_mem(__vaddr) ((__vaddr) & pci_memspace_mask)
static __inline__ u8 _inb(unsigned long addr)
{
u8 ret;

View File

@ -7,15 +7,50 @@
#define _SPARC64_IOMMU_H
/* The format of an iopte in the page tables. */
#define IOPTE_VALID 0x8000000000000000UL /* IOPTE is valid */
#define IOPTE_64K 0x2000000000000000UL /* IOPTE is for 64k page */
#define IOPTE_STBUF 0x1000000000000000UL /* DVMA can use streaming buffer */
#define IOPTE_INTRA 0x0800000000000000UL /* SBUS slot-->slot direct transfer*/
#define IOPTE_CONTEXT 0x07ff800000000000UL /* Context number */
#define IOPTE_PAGE 0x00007fffffffe000UL /* Physical page number (PA[42:13])*/
#define IOPTE_CACHE 0x0000000000000010UL /* Cached (in UPA E-cache) */
#define IOPTE_WRITE 0x0000000000000002UL /* Writeable */
#define IOPTE_VALID 0x8000000000000000UL
#define IOPTE_64K 0x2000000000000000UL
#define IOPTE_STBUF 0x1000000000000000UL
#define IOPTE_INTRA 0x0800000000000000UL
#define IOPTE_CONTEXT 0x07ff800000000000UL
#define IOPTE_PAGE 0x00007fffffffe000UL
#define IOPTE_CACHE 0x0000000000000010UL
#define IOPTE_WRITE 0x0000000000000002UL
#define IOMMU_NUM_CTXS 4096
struct iommu_arena {
unsigned long *map;
unsigned int hint;
unsigned int limit;
};
struct iommu {
spinlock_t lock;
struct iommu_arena arena;
iopte_t *page_table;
u32 page_table_map_base;
unsigned long iommu_control;
unsigned long iommu_tsbbase;
unsigned long iommu_flush;
unsigned long iommu_ctxflush;
unsigned long write_complete_reg;
unsigned long dummy_page;
unsigned long dummy_page_pa;
unsigned long ctx_lowest_free;
DECLARE_BITMAP(ctx_bitmap, IOMMU_NUM_CTXS);
u32 dma_addr_mask;
};
struct strbuf {
int strbuf_enabled;
unsigned long strbuf_control;
unsigned long strbuf_pflush;
unsigned long strbuf_fsync;
unsigned long strbuf_ctxflush;
unsigned long strbuf_ctxmatch_base;
unsigned long strbuf_flushflag_pa;
volatile unsigned long *strbuf_flushflag;
volatile unsigned long __flushflag_buf[(64+(64-1)) / sizeof(long)];
};
#endif /* !(_SPARC_IOMMU_H) */

View File

@ -7,7 +7,6 @@
#ifndef __SPARC64_ISA_H
#define __SPARC64_ISA_H
#include <asm/pbm.h>
#include <asm/oplib.h>
#include <asm/prom.h>
#include <asm/of_device.h>
@ -29,7 +28,6 @@ struct sparc_isa_bridge {
struct of_device ofdev;
struct sparc_isa_bridge *next;
struct sparc_isa_device *devices;
struct pci_pbm_info *parent;
struct pci_dev *self;
int index;
struct device_node *prom_node;

View File

@ -103,7 +103,7 @@ static int ebus_ecpp_p(struct linux_ebus_device *edev)
if (!strcmp(edev->prom_node->name, "ecpp"))
return 1;
if (!strcmp(edev->prom_node->name, "parallel")) {
char *compat;
const char *compat;
compat = of_get_property(edev->prom_node,
"compatible", NULL);

View File

@ -1,7 +1,6 @@
/* $Id: pbm.h,v 1.27 2001/08/12 13:18:23 davem Exp $
* pbm.h: UltraSparc PCI controller software state.
/* pbm.h: UltraSparc PCI controller software state.
*
* Copyright (C) 1997, 1998, 1999 David S. Miller (davem@redhat.com)
* Copyright (C) 1997, 1998, 1999, 2007 David S. Miller (davem@davemloft.net)
*/
#ifndef __SPARC64_PBM_H
@ -30,90 +29,7 @@
* PCI bus.
*/
struct pci_controller_info;
/* This contains the software state necessary to drive a PCI
* controller's IOMMU.
*/
struct pci_iommu_arena {
unsigned long *map;
unsigned int hint;
unsigned int limit;
};
struct pci_iommu {
/* This protects the controller's IOMMU and all
* streaming buffers underneath.
*/
spinlock_t lock;
struct pci_iommu_arena arena;
/* IOMMU page table, a linear array of ioptes. */
iopte_t *page_table; /* The page table itself. */
/* Base PCI memory space address where IOMMU mappings
* begin.
*/
u32 page_table_map_base;
/* IOMMU Controller Registers */
unsigned long iommu_control; /* IOMMU control register */
unsigned long iommu_tsbbase; /* IOMMU page table base register */
unsigned long iommu_flush; /* IOMMU page flush register */
unsigned long iommu_ctxflush; /* IOMMU context flush register */
/* This is a register in the PCI controller, which if
* read will have no side-effects but will guarantee
* completion of all previous writes into IOMMU/STC.
*/
unsigned long write_complete_reg;
/* In order to deal with some buggy third-party PCI bridges that
* do wrong prefetching, we never mark valid mappings as invalid.
* Instead we point them at this dummy page.
*/
unsigned long dummy_page;
unsigned long dummy_page_pa;
/* CTX allocation. */
unsigned long ctx_lowest_free;
unsigned long ctx_bitmap[IOMMU_NUM_CTXS / (sizeof(unsigned long) * 8)];
/* Here a PCI controller driver describes the areas of
* PCI memory space where DMA to/from physical memory
* are addressed. Drivers interrogate the PCI layer
* if their device has addressing limitations. They
* do so via pci_dma_supported, and pass in a mask of
* DMA address bits their device can actually drive.
*
* The test for being usable is:
* (device_mask & dma_addr_mask) == dma_addr_mask
*/
u32 dma_addr_mask;
};
extern void pci_iommu_table_init(struct pci_iommu *iommu, int tsbsize, u32 dma_offset, u32 dma_addr_mask);
/* This describes a PCI bus module's streaming buffer. */
struct pci_strbuf {
int strbuf_enabled; /* Present and using it? */
/* Streaming Buffer Control Registers */
unsigned long strbuf_control; /* STC control register */
unsigned long strbuf_pflush; /* STC page flush register */
unsigned long strbuf_fsync; /* STC flush synchronization reg */
unsigned long strbuf_ctxflush; /* STC context flush register */
unsigned long strbuf_ctxmatch_base; /* STC context flush match reg */
unsigned long strbuf_flushflag_pa; /* Physical address of flush flag */
volatile unsigned long *strbuf_flushflag; /* The flush flag itself */
/* And this is the actual flush flag area.
* We allocate extra because the chips require
* a 64-byte aligned area.
*/
volatile unsigned long __flushflag_buf[(64 + (64 - 1)) / sizeof(long)];
};
extern void pci_iommu_table_init(struct iommu *iommu, int tsbsize, u32 dma_offset, u32 dma_addr_mask);
#define PCI_STC_FLUSHFLAG_INIT(STC) \
(*((STC)->strbuf_flushflag) = 0UL)
@ -126,6 +42,8 @@ struct pci_strbuf {
#define PROM_PCIRNG_MAX 64
#define PROM_PCIIMAP_MAX 64
struct pci_controller_info;
struct pci_pbm_info {
/* PCI controller we sit under. */
struct pci_controller_info *parent;
@ -160,11 +78,6 @@ struct pci_pbm_info {
/* OBP specific information. */
struct device_node *prom_node;
struct linux_prom_pci_ranges *pbm_ranges;
int num_pbm_ranges;
struct linux_prom_pci_intmap *pbm_intmap;
int num_pbm_intmap;
struct linux_prom_pci_intmask *pbm_intmask;
u64 ino_bitmap;
/* PBM I/O and Memory space resources. */
@ -197,13 +110,10 @@ struct pci_pbm_info {
#endif /* !(CONFIG_PCI_MSI) */
/* This PBM's streaming buffer. */
struct pci_strbuf stc;
struct strbuf stc;
/* IOMMU state, potentially shared by both PBM segments. */
struct pci_iommu *iommu;
/* PCI slot mapping. */
unsigned int pci_first_slot;
struct iommu *iommu;
/* Now things for the actual PCI bus probes. */
unsigned int pci_first_busno;
@ -220,17 +130,12 @@ struct pci_controller_info {
*/
int index;
/* Do the PBMs both exist in the same PCI domain? */
int pbms_same_domain;
/* The PCI bus modules controlled by us. */
struct pci_pbm_info pbm_A;
struct pci_pbm_info pbm_B;
/* Operations which are controller specific. */
void (*scan_bus)(struct pci_controller_info *);
void (*base_address_update)(struct pci_dev *, int);
void (*resource_adjust)(struct pci_dev *, struct resource *, struct resource *);
#ifdef CONFIG_PCI_MSI
int (*setup_msi_irq)(unsigned int *virt_irq_p, struct pci_dev *pdev,
@ -244,27 +149,4 @@ struct pci_controller_info {
unsigned int pci_last_busno;
};
/* PCI devices which are not bridges have this placed in their pci_dev
* sysdata member. This makes OBP aware PCI device drivers easier to
* code.
*/
struct pcidev_cookie {
struct pci_pbm_info *pbm;
struct device_node *prom_node;
struct of_device *op;
struct linux_prom_pci_registers prom_regs[PROMREG_MAX];
int num_prom_regs;
struct linux_prom_pci_registers prom_assignments[PROMREG_MAX];
int num_prom_assignments;
#ifdef CONFIG_PCI_MSI
unsigned int msi_num;
#endif
};
/* Currently these are the same across all PCI controllers
* we support. Someday they may not be...
*/
#define PCI_IRQ_IGN 0x000007c0 /* Interrupt Group Number */
#define PCI_IRQ_INO 0x0000003f /* Interrupt Number */
#endif /* !(__SPARC64_PBM_H) */

View File

@ -54,7 +54,7 @@ struct pci_iommu_ops {
void (*dma_sync_sg_for_cpu)(struct pci_dev *, struct scatterlist *, int, int);
};
extern struct pci_iommu_ops *pci_iommu_ops;
extern const struct pci_iommu_ops *pci_iommu_ops;
/* Allocate and map kernel buffer using consistent mode DMA for a device.
* hwdev should be valid struct pci_dev pointer for PCI devices.

View File

@ -737,20 +737,6 @@ extern unsigned long pte_file(pte_t);
extern pte_t pgoff_to_pte(unsigned long);
#define PTE_FILE_MAX_BITS (64UL - PAGE_SHIFT - 1UL)
extern unsigned long prom_virt_to_phys(unsigned long, int *);
extern unsigned long sun4u_get_pte(unsigned long);
static inline unsigned long __get_phys(unsigned long addr)
{
return sun4u_get_pte(addr);
}
static inline int __get_iospace(unsigned long addr)
{
return ((sun4u_get_pte(addr) & 0xf0000000) >> 28);
}
extern unsigned long *sparc64_valid_addr_bitmap;
/* Needs to be defined here and not in linux/mm.h, as it is arch dependent */
@ -791,6 +777,8 @@ extern void pgtable_cache_init(void);
extern void sun4v_register_fault_status(void);
extern void sun4v_ktsb_register(void);
extern unsigned long cmdline_memory_size;
#endif /* !(__ASSEMBLY__) */
#endif /* !(_SPARC64_PGTABLE_H) */

View File

@ -36,8 +36,8 @@ struct property {
struct of_irq_controller;
struct device_node {
char *name;
char *type;
const char *name;
const char *type;
phandle node;
char *path_component_name;
char *full_name;
@ -93,11 +93,13 @@ extern struct device_node *of_find_node_by_phandle(phandle handle);
extern struct device_node *of_get_parent(const struct device_node *node);
extern struct device_node *of_get_next_child(const struct device_node *node,
struct device_node *prev);
extern struct property *of_find_property(struct device_node *np,
extern struct property *of_find_property(const struct device_node *np,
const char *name,
int *lenp);
extern int of_device_is_compatible(struct device_node *device, const char *);
extern void *of_get_property(struct device_node *node, const char *name,
extern int of_device_is_compatible(const struct device_node *device,
const char *);
extern const void *of_get_property(const struct device_node *node,
const char *name,
int *lenp);
#define get_property(node,name,lenp) of_get_property(node,name,lenp)
extern int of_set_property(struct device_node *node, const char *name, void *val, int len);

View File

@ -42,15 +42,15 @@ extern int hard_smp_processor_id(void);
#define raw_smp_processor_id() (current_thread_info()->cpu)
extern void smp_setup_cpu_possible_map(void);
extern unsigned char boot_cpu_id;
#endif /* !(__ASSEMBLY__) */
#else
#define smp_setup_cpu_possible_map() do { } while (0)
#define boot_cpu_id (0)
#endif /* !(CONFIG_SMP) */
#define NO_PROC_ID 0xFF
#endif /* !(_SPARC64_SMP_H) */

View File

@ -3,7 +3,7 @@
#ifdef __KERNEL__
#define SECTION_SIZE_BITS 26
#define SECTION_SIZE_BITS 31
#define MAX_PHYSADDR_BITS 42
#define MAX_PHYSMEM_BITS 42

View File

@ -11,22 +11,19 @@
struct sparc64_tick_ops {
void (*init_tick)(unsigned long);
unsigned long (*get_tick)(void);
unsigned long (*get_compare)(void);
unsigned long (*add_tick)(unsigned long, unsigned long);
unsigned long (*add_compare)(unsigned long);
int (*add_compare)(unsigned long);
unsigned long softint_mask;
void (*disable_irq)(void);
void (*init_tick)(void);
unsigned long (*add_tick)(unsigned long);
char *name;
};
extern struct sparc64_tick_ops *tick_ops;
#ifdef CONFIG_SMP
extern unsigned long timer_tick_offset;
struct pt_regs;
extern void timer_tick_interrupt(struct pt_regs *);
#endif
extern unsigned long sparc64_get_clock_tick(unsigned int cpu);
#endif /* _SPARC64_TIMER_H */

View File

@ -157,23 +157,6 @@
ba,a,pt %xcc, rtrap_irq; \
.previous;
#define TICK_SMP_IRQ \
rdpr %pil, %g2; \
wrpr %g0, 15, %pil; \
sethi %hi(1f-4), %g7; \
ba,pt %xcc, etrap_irq; \
or %g7, %lo(1f-4), %g7; \
nop; \
nop; \
nop; \
.subsection 2; \
1: call trace_hardirqs_off; \
nop; \
call smp_percpu_timer_interrupt; \
add %sp, PTREGS_OFF, %o0; \
ba,a,pt %xcc, rtrap_irq; \
.previous;
#else
#define TRAP_IRQ(routine, level) \
@ -186,16 +169,6 @@
add %sp, PTREGS_OFF, %o1; \
ba,a,pt %xcc, rtrap_irq;
#define TICK_SMP_IRQ \
rdpr %pil, %g2; \
wrpr %g0, 15, %pil; \
sethi %hi(109f), %g7; \
ba,pt %xcc, etrap_irq; \
109: or %g7, %lo(109b), %g7; \
call smp_percpu_timer_interrupt; \
add %sp, PTREGS_OFF, %o0; \
ba,a,pt %xcc, rtrap_irq;
#endif
#define TRAP_IVEC TRAP_NOSAVE(do_ivec)

View File

@ -47,6 +47,12 @@ extern int strncmp(const char *,const char *,__kernel_size_t);
#ifndef __HAVE_ARCH_STRNICMP
extern int strnicmp(const char *, const char *, __kernel_size_t);
#endif
#ifndef __HAVE_ARCH_STRCASECMP
extern int strcasecmp(const char *s1, const char *s2);
#endif
#ifndef __HAVE_ARCH_STRNCASECMP
extern int strncasecmp(const char *s1, const char *s2, size_t n);
#endif
#ifndef __HAVE_ARCH_STRCHR
extern char * strchr(const char *,int);
#endif

View File

@ -60,6 +60,34 @@ int strnicmp(const char *s1, const char *s2, size_t len)
EXPORT_SYMBOL(strnicmp);
#endif
#ifndef __HAVE_ARCH_STRCASECMP
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;
}
EXPORT_SYMBOL(strcasecmp);
#endif
#ifndef __HAVE_ARCH_STRNCASECMP
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;
}
EXPORT_SYMBOL(strncasecmp);
#endif
#ifndef __HAVE_ARCH_STRCPY
/**
* strcpy - Copy a %NUL terminated string

View File

@ -1067,8 +1067,8 @@ out_err:
static int __devinit amd7930_obio_attach(struct device_node *dp)
{
struct linux_prom_registers *regs;
struct linux_prom_irqs *irqp;
const struct linux_prom_registers *regs;
const struct linux_prom_irqs *irqp;
struct resource res, *rp;
int len;

View File

@ -2284,7 +2284,7 @@ static int __init cs4231_init(void)
if (!strcmp(edev->prom_node->name, "SUNW,CS4231")) {
match = 1;
} else if (!strcmp(edev->prom_node->name, "audio")) {
char *compat;
const char *compat;
compat = of_get_property(edev->prom_node,
"compatible", NULL);