Commit b9d8be78 authored by Linus Torvalds's avatar Linus Torvalds

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

* master.kernel.org:/pub/scm/linux/kernel/git/davem/sparc-2.6: (40 commits)
  [SPARC64]: Update defconfig.
  [SPARC64]: Make auxio a real driver.
  [PARPORT] sunbpp: Convert to new SBUS device framework.
  [Documentation]: Update probing info in sbus_drivers.txt
  [SCSI] qlogicpti: Convert to new SBUS device framework.
  [SCSI] esp: Fix bug in esp_remove_common.
  [NET] sunhme: Kill useless loop over sdevs in quattro_sbus_find().
  [NET] myri_sbus: Kill unused next_module struct member.
  [NET] myri_sbus: Convert to new SBUS device layer.
  [NET] sunqe: Convert to new SBUS driver layer.
  [NET] sunbmac: Convert over to new SBUS device framework.
  [NET] sunlance: Convert to new SBUS driver framework.
  [NET] sunhme: Convert to new SBUS driver framework.
  [NET] sunhme: Kill __sparc__ and __sparc_v9__ ifdefs.
  [SCSI] sparc: Port esp to new SBUS driver layer.
  [SOUND] sparc: Port amd7930 to new SBUS device layer.
  [SBUS]: Rewrite and plug into of_device framework.
  [SPARC]: Port of_device layer and make ebus use it.
  [SPARC]: Port sparc64 in-kernel device tree code to sparc32.
  [SPARC64]: Add of_device layer and make ebus/isa use it.
  ...
parents d02f40e8 1812fd40
...@@ -25,42 +25,84 @@ the bits necessary to run your device. The most commonly ...@@ -25,42 +25,84 @@ the bits necessary to run your device. The most commonly
used members of this structure, and their typical usage, used members of this structure, and their typical usage,
will be detailed below. will be detailed below.
Here is how probing is performed by an SBUS driver Here is a piece of skeleton code for perofming a device
under Linux: probe in an SBUS driverunder Linux:
static void init_one_mydevice(struct sbus_dev *sdev) static int __devinit mydevice_probe_one(struct sbus_dev *sdev)
{ {
struct mysdevice *mp = kzalloc(sizeof(*mp), GFP_KERNEL);
if (!mp)
return -ENODEV;
...
dev_set_drvdata(&sdev->ofdev.dev, mp);
return 0;
... ...
} }
static int mydevice_match(struct sbus_dev *sdev) static int __devinit mydevice_probe(struct of_device *dev,
const struct of_device_id *match)
{ {
if (some_criteria(sdev)) struct sbus_dev *sdev = to_sbus_device(&dev->dev);
return 1;
return 0; return mydevice_probe_one(sdev);
} }
static void mydevice_probe(void) static int __devexit mydevice_remove(struct of_device *dev)
{ {
struct sbus_bus *sbus; struct sbus_dev *sdev = to_sbus_device(&dev->dev);
struct sbus_dev *sdev; struct mydevice *mp = dev_get_drvdata(&dev->dev);
for_each_sbus(sbus) { return mydevice_remove_one(sdev, mp);
for_each_sbusdev(sdev, sbus) {
if (mydevice_match(sdev))
init_one_mydevice(sdev);
}
}
} }
All this does is walk through all SBUS devices in the static struct of_device_id mydevice_match[] = {
system, checks each to see if it is of the type which {
your driver is written for, and if so it calls the init .name = "mydevice",
routine to attach the device and prepare to drive it. },
{},
};
MODULE_DEVICE_TABLE(of, mydevice_match);
"init_one_mydevice" might do things like allocate software static struct of_platform_driver mydevice_driver = {
state structures, map in I/O registers, place the hardware .name = "mydevice",
into an initialized state, etc. .match_table = mydevice_match,
.probe = mydevice_probe,
.remove = __devexit_p(mydevice_remove),
};
static int __init mydevice_init(void)
{
return of_register_driver(&mydevice_driver, &sbus_bus_type);
}
static void __exit mydevice_exit(void)
{
of_unregister_driver(&mydevice_driver);
}
module_init(mydevice_init);
module_exit(mydevice_exit);
The mydevice_match table is a series of entries which
describes what SBUS devices your driver is meant for. In the
simplest case you specify a string for the 'name' field. Every
SBUS device with a 'name' property matching your string will
be passed one-by-one to your .probe method.
You should store away your device private state structure
pointer in the drvdata area so that you can retrieve it later on
in your .remove method.
Any memory allocated, registers mapped, IRQs registered,
etc. must be undone by your .remove method so that all resources
of your device are relased by the time it returns.
You should _NOT_ use the for_each_sbus(), for_each_sbusdev(),
and for_all_sbusdev() interfaces. They are deprecated, will be
removed, and no new driver should reference them ever.
Mapping and Accessing I/O Registers Mapping and Accessing I/O Registers
...@@ -263,10 +305,3 @@ discussed above and plus it handles both PCI and SBUS boards. ...@@ -263,10 +305,3 @@ discussed above and plus it handles both PCI and SBUS boards.
Lance driver abuses consistent mappings for data transfer. Lance driver abuses consistent mappings for data transfer.
It is a nifty trick which we do not particularly recommend... It is a nifty trick which we do not particularly recommend...
Just check it out and know that it's legal. Just check it out and know that it's legal.
Bad examples, do NOT use
drivers/video/cgsix.c
This one uses result of sbus_ioremap as if it is an address.
This does NOT work on sparc64 and therefore is broken. We will
convert it at a later date.
...@@ -12,7 +12,7 @@ obj-y := entry.o wof.o wuf.o etrap.o rtrap.o traps.o $(IRQ_OBJS) \ ...@@ -12,7 +12,7 @@ obj-y := entry.o wof.o wuf.o etrap.o rtrap.o traps.o $(IRQ_OBJS) \
sys_sparc.o sunos_asm.o systbls.o \ sys_sparc.o sunos_asm.o systbls.o \
time.o windows.o cpu.o devices.o sclow.o \ time.o windows.o cpu.o devices.o sclow.o \
tadpole.o tick14.o ptrace.o sys_solaris.o \ tadpole.o tick14.o ptrace.o sys_solaris.o \
unaligned.o muldiv.o semaphore.o unaligned.o muldiv.o semaphore.o prom.o of_device.o
obj-$(CONFIG_PCI) += pcic.o obj-$(CONFIG_PCI) += pcic.o
obj-$(CONFIG_SUN4) += sun4setup.o obj-$(CONFIG_SUN4) += sun4setup.o
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include <asm/ebus.h> #include <asm/ebus.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/oplib.h> #include <asm/oplib.h>
#include <asm/prom.h>
#include <asm/bpp.h> #include <asm/bpp.h>
struct linux_ebus *ebus_chain = NULL; struct linux_ebus *ebus_chain = NULL;
...@@ -83,79 +84,81 @@ int __init ebus_blacklist_irq(char *name) ...@@ -83,79 +84,81 @@ int __init ebus_blacklist_irq(char *name)
return 0; return 0;
} }
void __init fill_ebus_child(int node, struct linux_prom_registers *preg, void __init fill_ebus_child(struct device_node *dp,
struct linux_ebus_child *dev) struct linux_ebus_child *dev)
{ {
int regs[PROMREG_MAX]; int *regs;
int irqs[PROMREG_MAX]; int *irqs;
char lbuf[128];
int i, len; int i, len;
dev->prom_node = node; dev->prom_node = dp;
prom_getstring(node, "name", lbuf, sizeof(lbuf)); regs = of_get_property(dp, "reg", &len);
strcpy(dev->prom_name, lbuf); if (!regs)
len = 0;
len = prom_getproperty(node, "reg", (void *)regs, sizeof(regs));
if (len == -1) len = 0;
dev->num_addrs = len / sizeof(regs[0]); dev->num_addrs = len / sizeof(regs[0]);
for (i = 0; i < dev->num_addrs; i++) { for (i = 0; i < dev->num_addrs; i++) {
if (regs[i] >= dev->parent->num_addrs) { if (regs[i] >= dev->parent->num_addrs) {
prom_printf("UGH: property for %s was %d, need < %d\n", prom_printf("UGH: property for %s was %d, need < %d\n",
dev->prom_name, len, dev->parent->num_addrs); dev->prom_node->name, len,
dev->parent->num_addrs);
panic(__FUNCTION__); panic(__FUNCTION__);
} }
dev->resource[i].start = dev->parent->resource[regs[i]].start; /* XXX resource */
/* XXX resource */
dev->resource[i].start =
dev->parent->resource[regs[i]].start;
} }
for (i = 0; i < PROMINTR_MAX; i++) for (i = 0; i < PROMINTR_MAX; i++)
dev->irqs[i] = PCI_IRQ_NONE; dev->irqs[i] = PCI_IRQ_NONE;
if ((dev->irqs[0] = ebus_blacklist_irq(dev->prom_name)) != 0) { if ((dev->irqs[0] = ebus_blacklist_irq(dev->prom_node->name)) != 0) {
dev->num_irqs = 1; dev->num_irqs = 1;
} else if ((len = prom_getproperty(node, "interrupts",
(char *)&irqs, sizeof(irqs))) == -1 || len == 0) {
dev->num_irqs = 0;
dev->irqs[0] = 0;
if (dev->parent->num_irqs != 0) {
dev->num_irqs = 1;
dev->irqs[0] = dev->parent->irqs[0];
/* P3 */ /* printk("EBUS: dev %s irq %d from parent\n", dev->prom_name, dev->irqs[0]); */
}
} else { } else {
dev->num_irqs = len / sizeof(irqs[0]); irqs = of_get_property(dp, "interrupts", &len);
if (irqs[0] == 0 || irqs[0] >= 8) { if (!irqs) {
/*
* XXX Zero is a valid pin number...
* This works as long as Ebus is not wired to INTA#.
*/
printk("EBUS: %s got bad irq %d from PROM\n",
dev->prom_name, irqs[0]);
dev->num_irqs = 0; dev->num_irqs = 0;
dev->irqs[0] = 0; dev->irqs[0] = 0;
if (dev->parent->num_irqs != 0) {
dev->num_irqs = 1;
dev->irqs[0] = dev->parent->irqs[0];
}
} else { } else {
dev->irqs[0] = pcic_pin_to_irq(irqs[0], dev->prom_name); dev->num_irqs = len / sizeof(irqs[0]);
if (irqs[0] == 0 || irqs[0] >= 8) {
/*
* XXX Zero is a valid pin number...
* This works as long as Ebus is not wired
* to INTA#.
*/
printk("EBUS: %s got bad irq %d from PROM\n",
dev->prom_node->name, irqs[0]);
dev->num_irqs = 0;
dev->irqs[0] = 0;
} else {
dev->irqs[0] =
pcic_pin_to_irq(irqs[0],
dev->prom_node->name);
}
} }
} }
} }
void __init fill_ebus_device(int node, struct linux_ebus_device *dev) void __init fill_ebus_device(struct device_node *dp, struct linux_ebus_device *dev)
{ {
struct linux_prom_registers regs[PROMREG_MAX]; struct linux_prom_registers *regs;
struct linux_ebus_child *child; struct linux_ebus_child *child;
int irqs[PROMINTR_MAX]; int *irqs;
char lbuf[128];
int i, n, len; int i, n, len;
unsigned long baseaddr; unsigned long baseaddr;
dev->prom_node = node; dev->prom_node = dp;
prom_getstring(node, "name", lbuf, sizeof(lbuf));
strcpy(dev->prom_name, lbuf);
len = prom_getproperty(node, "reg", (void *)regs, sizeof(regs)); regs = of_get_property(dp, "reg", &len);
if (len % sizeof(struct linux_prom_registers)) { if (len % sizeof(struct linux_prom_registers)) {
prom_printf("UGH: proplen for %s was %d, need multiple of %d\n", prom_printf("UGH: proplen for %s was %d, need multiple of %d\n",
dev->prom_name, len, dev->prom_node->name, len,
(int)sizeof(struct linux_prom_registers)); (int)sizeof(struct linux_prom_registers));
panic(__FUNCTION__); panic(__FUNCTION__);
} }
...@@ -197,7 +200,7 @@ void __init fill_ebus_device(int node, struct linux_ebus_device *dev) ...@@ -197,7 +200,7 @@ void __init fill_ebus_device(int node, struct linux_ebus_device *dev)
if ((baseaddr = (unsigned long) ioremap(baseaddr, if ((baseaddr = (unsigned long) ioremap(baseaddr,
regs[i].reg_size)) == 0) { regs[i].reg_size)) == 0) {
panic("ebus: unable to remap dev %s", panic("ebus: unable to remap dev %s",
dev->prom_name); dev->prom_node->name);
} }
} }
dev->resource[i].start = baseaddr; /* XXX Unaligned */ dev->resource[i].start = baseaddr; /* XXX Unaligned */
...@@ -206,29 +209,43 @@ void __init fill_ebus_device(int node, struct linux_ebus_device *dev) ...@@ -206,29 +209,43 @@ void __init fill_ebus_device(int node, struct linux_ebus_device *dev)
for (i = 0; i < PROMINTR_MAX; i++) for (i = 0; i < PROMINTR_MAX; i++)
dev->irqs[i] = PCI_IRQ_NONE; dev->irqs[i] = PCI_IRQ_NONE;
if ((dev->irqs[0] = ebus_blacklist_irq(dev->prom_name)) != 0) { if ((dev->irqs[0] = ebus_blacklist_irq(dev->prom_node->name)) != 0) {
dev->num_irqs = 1; dev->num_irqs = 1;
} else if ((len = prom_getproperty(node, "interrupts",
(char *)&irqs, sizeof(irqs))) == -1 || len == 0) {
dev->num_irqs = 0;
if ((dev->irqs[0] = dev->bus->self->irq) != 0) {
dev->num_irqs = 1;
/* P3 */ /* printk("EBUS: child %s irq %d from parent\n", dev->prom_name, dev->irqs[0]); */
}
} else { } else {
dev->num_irqs = 1; /* dev->num_irqs = len / sizeof(irqs[0]); */ irqs = of_get_property(dp, "interrupts", &len);
if (irqs[0] == 0 || irqs[0] >= 8) { if (!irqs) {
/* See above for the parent. XXX */
printk("EBUS: %s got bad irq %d from PROM\n",
dev->prom_name, irqs[0]);
dev->num_irqs = 0; dev->num_irqs = 0;
dev->irqs[0] = 0; if ((dev->irqs[0] = dev->bus->self->irq) != 0) {
dev->num_irqs = 1;
/* P3 */ /* printk("EBUS: child %s irq %d from parent\n", dev->prom_name, dev->irqs[0]); */
}
} else { } else {
dev->irqs[0] = pcic_pin_to_irq(irqs[0], dev->prom_name); dev->num_irqs = 1; /* dev->num_irqs = len / sizeof(irqs[0]); */
if (irqs[0] == 0 || irqs[0] >= 8) {
/* See above for the parent. XXX */
printk("EBUS: %s got bad irq %d from PROM\n",
dev->prom_node->name, irqs[0]);
dev->num_irqs = 0;
dev->irqs[0] = 0;
} else {
dev->irqs[0] =
pcic_pin_to_irq(irqs[0],
dev->prom_node->name);
}
} }
} }
if ((node = prom_getchild(node))) { dev->ofdev.node = dp;
dev->ofdev.dev.parent = &dev->bus->ofdev.dev;
dev->ofdev.dev.bus = &ebus_bus_type;
strcpy(dev->ofdev.dev.bus_id, dp->path_component_name);
/* Register with core */
if (of_device_register(&dev->ofdev) != 0)
printk(KERN_DEBUG "ebus: device registration error for %s!\n",
dev->ofdev.dev.bus_id);
if ((dp = dp->child) != NULL) {
dev->children = (struct linux_ebus_child *) dev->children = (struct linux_ebus_child *)
ebus_alloc(sizeof(struct linux_ebus_child)); ebus_alloc(sizeof(struct linux_ebus_child));
...@@ -236,9 +253,9 @@ void __init fill_ebus_device(int node, struct linux_ebus_device *dev) ...@@ -236,9 +253,9 @@ void __init fill_ebus_device(int node, struct linux_ebus_device *dev)
child->next = NULL; child->next = NULL;
child->parent = dev; child->parent = dev;
child->bus = dev->bus; child->bus = dev->bus;
fill_ebus_child(node, &regs[0], child); fill_ebus_child(dp, child);
while ((node = prom_getsibling(node)) != 0) { while ((dp = dp->sibling) != NULL) {
child->next = (struct linux_ebus_child *) child->next = (struct linux_ebus_child *)
ebus_alloc(sizeof(struct linux_ebus_child)); ebus_alloc(sizeof(struct linux_ebus_child));
...@@ -246,51 +263,49 @@ void __init fill_ebus_device(int node, struct linux_ebus_device *dev) ...@@ -246,51 +263,49 @@ void __init fill_ebus_device(int node, struct linux_ebus_device *dev)
child->next = NULL; child->next = NULL;
child->parent = dev; child->parent = dev;
child->bus = dev->bus; child->bus = dev->bus;
fill_ebus_child(node, &regs[0], child); fill_ebus_child(dp, child);
} }
} }
} }
void __init ebus_init(void) void __init ebus_init(void)
{ {
struct linux_prom_pci_registers regs[PROMREG_MAX]; struct linux_prom_pci_registers *regs;
struct linux_pbm_info *pbm; struct linux_pbm_info *pbm;
struct linux_ebus_device *dev; struct linux_ebus_device *dev;
struct linux_ebus *ebus; struct linux_ebus *ebus;
struct ebus_system_entry *sp; struct ebus_system_entry *sp;
struct pci_dev *pdev; struct pci_dev *pdev;
struct pcidev_cookie *cookie; struct pcidev_cookie *cookie;
char lbuf[128]; struct device_node *dp;
unsigned long addr, *base; unsigned long addr, *base;
unsigned short pci_command; unsigned short pci_command;
int nd, len, ebusnd; int len, reg, nreg;
int reg, nreg;
int num_ebus = 0; int num_ebus = 0;
prom_getstring(prom_root_node, "name", lbuf, sizeof(lbuf)); dp = of_find_node_by_path("/");
for (sp = ebus_blacklist; sp->esname != NULL; sp++) { for (sp = ebus_blacklist; sp->esname != NULL; sp++) {
if (strcmp(lbuf, sp->esname) == 0) { if (strcmp(dp->name, sp->esname) == 0) {
ebus_blackp = sp->ipt; ebus_blackp = sp->ipt;
break; break;
} }
} }
pdev = pci_get_device(PCI_VENDOR_ID_SUN, PCI_DEVICE_ID_SUN_EBUS, NULL); pdev = pci_get_device(PCI_VENDOR_ID_SUN, PCI_DEVICE_ID_SUN_EBUS, NULL);
if (!pdev) { if (!pdev)
return; return;
}
cookie = pdev->sysdata; cookie = pdev->sysdata;
ebusnd = cookie->prom_node; dp = cookie->prom_node;
ebus_chain = ebus = (struct linux_ebus *) ebus_chain = ebus = (struct linux_ebus *)
ebus_alloc(sizeof(struct linux_ebus)); ebus_alloc(sizeof(struct linux_ebus));
ebus->next = NULL; ebus->next = NULL;
while (ebusnd) { while (dp) {
struct device_node *nd;
prom_getstring(ebusnd, "name", lbuf, sizeof(lbuf)); ebus->prom_node = dp;
ebus->prom_node = ebusnd;
strcpy(ebus->prom_name, lbuf);
ebus->self = pdev; ebus->self = pdev;
ebus->parent = pbm = cookie->pbm; ebus->parent = pbm = cookie->pbm;
...@@ -299,9 +314,8 @@ void __init ebus_init(void) ...@@ -299,9 +314,8 @@ void __init ebus_init(void)
pci_command |= PCI_COMMAND_MASTER; pci_command |= PCI_COMMAND_MASTER;
pci_write_config_word(pdev, PCI_COMMAND, pci_command); pci_write_config_word(pdev, PCI_COMMAND, pci_command);
len = prom_getproperty(ebusnd, "reg", (void *)regs, regs = of_get_property(dp, "reg", &len);
sizeof(regs)); if (!regs) {
if (len == 0 || len == -1) {
prom_printf("%s: can't find reg property\n", prom_printf("%s: can't find reg property\n",
__FUNCTION__); __FUNCTION__);
prom_halt(); prom_halt();
...@@ -317,7 +331,18 @@ void __init ebus_init(void) ...@@ -317,7 +331,18 @@ void __init ebus_init(void)
*base++ = addr; *base++ = addr;
} }
nd = prom_getchild(ebusnd); ebus->ofdev.node = dp;
ebus->ofdev.dev.parent = &pdev->dev;
ebus->ofdev.dev.bus = &ebus_bus_type;
strcpy(ebus->ofdev.dev.bus_id, dp->path_component_name);
/* Register with core */
if (of_device_register(&ebus->ofdev) != 0)
printk(KERN_DEBUG "ebus: device registration error for %s!\n",
ebus->ofdev.dev.bus_id);
nd = dp->child;
if (!nd) if (!nd)
goto next_ebus; goto next_ebus;
...@@ -330,7 +355,7 @@ void __init ebus_init(void) ...@@ -330,7 +355,7 @@ void __init ebus_init(void)
dev->bus = ebus; dev->bus = ebus;
fill_ebus_device(nd, dev); fill_ebus_device(nd, dev);
while ((nd = prom_getsibling(nd)) != 0) { while ((nd = nd->sibling) != NULL) {
dev->next = (struct linux_ebus_device *) dev->next = (struct linux_ebus_device *)
ebus_alloc(sizeof(struct linux_ebus_device)); ebus_alloc(sizeof(struct linux_ebus_device));
...@@ -348,7 +373,7 @@ void __init ebus_init(void) ...@@ -348,7 +373,7 @@ void __init ebus_init(void)
break; break;
cookie = pdev->sysdata; cookie = pdev->sysdata;
ebusnd = cookie->prom_node; dp = cookie->prom_node;
ebus->next = (struct linux_ebus *) ebus->next = (struct linux_ebus *)
ebus_alloc(sizeof(struct linux_ebus)); ebus_alloc(sizeof(struct linux_ebus));
......
...@@ -39,6 +39,8 @@ ...@@ -39,6 +39,8 @@
#include <asm/io.h> #include <asm/io.h>
#include <asm/vaddrs.h> #include <asm/vaddrs.h>
#include <asm/oplib.h> #include <asm/oplib.h>
#include <asm/prom.h>
#include <asm/sbus.h>
#include <asm/page.h> #include <asm/page.h>
#include <asm/pgalloc.h> #include <asm/pgalloc.h>
#include <asm/dma.h> #include <asm/dma.h>
...@@ -224,10 +226,54 @@ static void _sparc_free_io(struct resource *res) ...@@ -224,10 +226,54 @@ static void _sparc_free_io(struct resource *res)
#ifdef CONFIG_SBUS #ifdef CONFIG_SBUS
void sbus_set_sbus64(struct sbus_dev *sdev, int x) { void sbus_set_sbus64(struct sbus_dev *sdev, int x)
{
printk("sbus_set_sbus64: unsupported\n"); printk("sbus_set_sbus64: unsupported\n");
} }
extern unsigned int sun4d_build_irq(struct sbus_dev *sdev, int irq);
void __init sbus_fill_device_irq(struct sbus_dev *sdev)
{
struct linux_prom_irqs irqs[PROMINTR_MAX];
int len;
len = prom_getproperty(sdev->prom_node, "intr",
(char *)irqs, sizeof(irqs));
if (len != -1) {
sdev->num_irqs = len / 8;
if (sdev->num_irqs == 0) {
sdev->irqs[0] = 0;
} else if (sparc_cpu_model == sun4d) {
for (len = 0; len < sdev->num_irqs; len++)
sdev->irqs[len] =
sun4d_build_irq(sdev, irqs[len].pri);
} else {
for (len = 0; len < sdev->num_irqs; len++)
sdev->irqs[len] = irqs[len].pri;
}
} else {
int interrupts[PROMINTR_MAX];
/* No "intr" node found-- check for "interrupts" node.
* This node contains SBus interrupt levels, not IPLs
* as in "intr", and no vector values. We convert
* SBus interrupt levels to PILs (platform specific).
*/
len = prom_getproperty(sdev->prom_node, "interrupts",
(char *)interrupts, sizeof(interrupts));
if (len == -1) {
sdev->irqs[0] = 0;
sdev->num_irqs = 0;
} else {
sdev->num_irqs = len / sizeof(int);
for (len = 0; len < sdev->num_irqs; len++) {
sdev->irqs[len] =
sbint_to_irq(sdev, interrupts[len]);
}
}
}
}
/* /*
* Allocate a chunk of memory suitable for DMA. * Allocate a chunk of memory suitable for DMA.
* Typically devices use them for control blocks. * Typically devices use them for control blocks.
...@@ -414,6 +460,89 @@ void sbus_dma_sync_sg_for_device(struct sbus_dev *sdev, struct scatterlist *sg, ...@@ -414,6 +460,89 @@ void sbus_dma_sync_sg_for_device(struct sbus_dev *sdev, struct scatterlist *sg,
{ {
printk("sbus_dma_sync_sg_for_device: not implemented yet\n"); printk("sbus_dma_sync_sg_for_device: not implemented yet\n");
} }
/* Support code for sbus_init(). */
/*
* XXX This functions appears to be a distorted version of
* prom_sbus_ranges_init(), with all sun4d stuff cut away.
* Ask DaveM what is going on here, how is sun4d supposed to work... XXX
*/
/* added back sun4d patch from Thomas Bogendoerfer - should be OK (crn) */
void __init sbus_arch_bus_ranges_init(struct device_node *pn, struct sbus_bus *sbus)
{
int parent_node = pn->node;
if (sparc_cpu_model == sun4d) {
struct linux_prom_ranges iounit_ranges[PROMREG_MAX];
int num_iounit_ranges, len;
len = prom_getproperty(parent_node, "ranges",
(char *) iounit_ranges,
sizeof (iounit_ranges));
if (len != -1) {
num_iounit_ranges =
(len / sizeof(struct linux_prom_ranges));
prom_adjust_ranges(sbus->sbus_ranges,
sbus->num_sbus_ranges,
iounit_ranges, num_iounit_ranges);
}
}
}
void __init sbus_setup_iommu(struct sbus_bus *sbus, struct device_node *dp)
{
struct device_node *parent = dp->parent;
if (sparc_cpu_model != sun4d &&
parent != NULL &&
!strcmp(parent->name, "iommu")) {
extern void iommu_init(int iommu_node, struct sbus_bus *sbus);
iommu_init(parent->node, sbus);
}
if (sparc_cpu_model == sun4d) {
extern void iounit_init(int sbi_node, int iounit_node,
struct sbus_bus *sbus);
iounit_init(dp->node, parent->node, sbus);
}
}
void __init sbus_setup_arch_props(struct sbus_bus *sbus, struct device_node *dp)
{
if (sparc_cpu_model == sun4d) {
struct device_node *parent = dp->parent;
sbus->devid = of_getintprop_default(parent, "device-id", 0);
sbus->board = of_getintprop_default(parent, "board#", 0);
}
}
int __init sbus_arch_preinit(void)
{
extern void register_proc_sparc_ioport(void);
register_proc_sparc_ioport();
#ifdef CONFIG_SUN4
{
extern void sun4_dvma_init(void);
sun4_dvma_init();
}
return 1;
#else
return 0;
#endif
}
void __init sbus_arch_postinit(void)
{
if (sparc_cpu_model == sun4d) {
extern void sun4d_init_sbi_irq(void);
sun4d_init_sbi_irq();
}
}
#endif /* CONFIG_SBUS */ #endif /* CONFIG_SBUS */
#ifdef CONFIG_PCI #ifdef CONFIG_PCI
......
#include <linux/config.h>
#include <linux/string.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/mod_devicetable.h>
#include <linux/slab.h>
#include <asm/errno.h>
#include <asm/of_device.h>
/**
* of_match_device - Tell if an of_device structure has a matching
* of_match structure
* @ids: array of of device match structures to search in
* @dev: the of device structure to match against
*
* Used by a driver to check whether an of_device present in the
* system is in its list of supported devices.
*/
const struct of_device_id *of_match_device(const struct of_device_id *matches,
const struct of_device *dev)
{
if (!dev->node)
return NULL;
while (matches->name[0] || matches->type[0] || matches->compatible[0]) {
int match = 1;
if (matches->name[0])
match &= dev->node->name
&& !strcmp(matches->name, dev->node->name);
if (matches->type[0])
match &= dev->node->type
&& !strcmp(matches->type, dev->node->type);
if (matches->compatible[0])
match &= of_device_is_compatible(dev->node,
matches->compatible);
if (match)
return matches;
matches++;
}
return NULL;
}
static int of_platform_bus_match(struct device *dev, struct device_driver *drv)
{
struct of_device * of_dev = to_of_device(dev);
struct of_platform_driver * of_drv = to_of_platform_driver(drv);
const struct of_device_id * matches = of_drv->match_table;
if (!matches)
return 0;
return of_match_device(matches, of_dev) != NULL;
}
struct of_device *of_dev_get(struct of_device *dev)
{
struct device *tmp;
if (!dev)
return NULL;
tmp = get_device(&dev->dev);
if (tmp)
return to_of_device(tmp);
else
return NULL;
}
void of_dev_put(struct of_device *dev)
{
if (dev)
put_device(&dev->dev);
}
static int of_device_probe(struct device *dev)
{
int error = -ENODEV;
struct of_platform_driver *drv;
struct of_device *of_dev;
const struct of_device_id *match;
drv = to_of_platform_driver(dev->driver);
of_dev = to_of_device(dev);
if (!drv->probe)
return error;
of_dev_get(of_dev);
match = of_match_device(drv->match_table, of_dev);
if (match)
error = drv->probe(of_dev, match);
if (error)
of_dev_put(of_dev);
return error;
}
static int of_device_remove(struct device *dev)
{
struct of_device * of_dev = to_of_device(dev);
struct of_platform_driver * drv = to_of_platform_driver(dev->driver);
if (dev->driver && drv->remove)
drv->remove(of_dev);
return 0;
}
static int of_device_suspend(struct device *dev, pm_message_t state)
{
struct of_device * of_dev = to_of_device(dev);
struct of_platform_driver * drv = to_of_platform_driver(dev->driver);
int error = 0;
if (dev->driver && drv->suspend)
error = drv->suspend(of_dev, state);
return error;
}
static int of_device_resume(struct device * dev)
{
struct of_device * of_dev = to_of_device(dev);
struct of_platform_driver * drv = to_of_platform_driver(dev->driver);
int error = 0;
if (dev->driver && drv->resume)
error = drv->resume(of_dev);
return error;
}
#ifdef CONFIG_PCI
struct bus_type ebus_bus_type = {
.name = "ebus",
.match = of_platform_bus_match,
.probe = of_device_probe,
.remove = of_device_remove,
.suspend = of_device_suspend,
.resume = of_device_resume,
};
#endif
#ifdef CONFIG_SBUS
struct bus_type sbus_bus_type = {
.name = "sbus",
.match = of_platform_bus_match,
.probe = of_device_probe,
.remove = of_device_remove,
.suspend = of_device_suspend,
.resume = of_device_resume,
};
#endif
static int __init of_bus_driver_init(void)
{
int err = 0;
#ifdef CONFIG_PCI
if (!err)
err = bus_register(&ebus_bus_type);
#endif
#ifdef CONFIG_SBUS
if (!err)
err = bus_register(&sbus_bus_type);
#endif
return 0;
}
postcore_initcall(of_bus_driver_init);
int of_register_driver(struct of_platform_driver *drv, struct bus_type *bus)
{
/* initialize common driver fields */
drv->driver.name = drv->name;
drv->driver.bus = bus;
/* register with core */
return driver_register(&drv->driver);
}
void of_unregister_driver(struct of_platform_driver *drv)
{
driver_unregister(&drv->driver);
}
static ssize_t dev_show_devspec(struct device *dev, struct device_attribute *attr, char *buf)
{
struct of_device *ofdev;
ofdev = to_of_device(dev);
return sprintf(buf, "%s", ofdev->node->full_name);
}
static DEVICE_ATTR(devspec, S_IRUGO, dev_show_devspec, NULL);
/**
* of_release_dev - free an of device structure when all users of it are finished.
* @dev: device that's been disconnected
*
* Will be called only by the device core when all users of this of device are
* done.
*/
void of_release_dev(struct device *dev)
{
struct of_device *ofdev;
ofdev = to_of_device(dev);
kfree(ofdev);
}
int of_device_register(struct of_device *ofdev)
{
int rc;
BUG_ON(ofdev->node == NULL);
rc = device_register(&ofdev->dev);
if (rc)
return rc;
device_create_file(&ofdev->dev, &dev_attr_devspec);
return 0;
}
void of_device_unregister(struct of_device *ofdev)
{
device_remove_file(&ofdev->dev, &dev_attr_devspec);
device_unregister(&ofdev->dev);
}
struct of_device* of_platform_device_create(struct device_node *np,
const char *bus_id,
struct device *parent,
struct bus_type *bus)
{
struct of_device *dev;
dev = kmalloc(sizeof(*dev), GFP_KERNEL);
if (!dev)
return NULL;
memset(dev, 0, sizeof(*dev));
dev->dev.parent = parent;
dev->dev.bus = bus;
dev->dev.release = of_release_dev;
strlcpy(dev->dev.bus_id, bus_id, BUS_ID_SIZE);
if (of_device_register(dev) != 0) {
kfree(dev);
return NULL;
}
return dev;
}
EXPORT_SYMBOL(of_match_device);
EXPORT_SYMBOL(of_register_driver);
EXPORT_SYMBOL(of_unregister_driver);
EXPORT_SYMBOL(of_device_register);
EXPORT_SYMBOL(of_device_unregister);
EXPORT_SYMBOL(of_dev_get);
EXPORT_SYMBOL(of_dev_put);
EXPORT_SYMBOL(of_platform_device_create);
EXPORT_SYMBOL(of_release_dev);
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#include <asm/irq.h> #include <asm/irq.h>
#include <asm/oplib.h> #include <asm/oplib.h>
#include <asm/prom.h>
#include <asm/pcic.h> #include <asm/pcic.h>
#include <asm/timer.h> #include <asm/timer.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
...@@ -665,7 +666,7 @@ void __init pcibios_fixup_bus(struct pci_bus *bus) ...@@ -665,7 +666,7 @@ void __init pcibios_fixup_bus(struct pci_bus *bus)
/* cookies */ /* cookies */
pcp = pci_devcookie_alloc(); pcp = pci_devcookie_alloc();
pcp->pbm = &pcic->pbm; pcp->pbm = &pcic->pbm;
pcp->prom_node = node; pcp->prom_node = of_find_node_by_phandle(node);
dev->sysdata = pcp; dev->sysdata = pcp;
/* fixing I/O to look like memory */ /* fixing I/O to look like memory */
......
This diff is collapsed.
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#include <asm/vaddrs.h> #include <asm/vaddrs.h>
#include <asm/pgalloc.h> /* bug in asm-generic/tlb.h: check_pgt_cache */ #include <asm/pgalloc.h> /* bug in asm-generic/tlb.h: check_pgt_cache */
#include <asm/tlb.h> #include <asm/tlb.h>
#include <asm/prom.h>
DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
...@@ -349,6 +350,7 @@ void __init paging_init(void) ...@@ -349,6 +350,7 @@ void __init paging_init(void)
protection_map[14] = PAGE_SHARED; protection_map[14] = PAGE_SHARED;
protection_map[15] = PAGE_SHARED; protection_map[15] = PAGE_SHARED;
btfixup(); btfixup();
prom_build_devicetree();
device_scan(); device_scan();
} }
......
# #
# Automatically generated make config: don't edit # Automatically generated make config: don't edit
# Linux kernel version: 2.6.17 # Linux kernel version: 2.6.17
# Tue Jun 20 01:26:43 2006 # Fri Jun 23 23:17:09 2006
# #
CONFIG_SPARC=y CONFIG_SPARC=y
CONFIG_SPARC64=y CONFIG_SPARC64=y
...@@ -286,6 +286,7 @@ CONFIG_STANDALONE=y ...@@ -286,6 +286,7 @@ CONFIG_STANDALONE=y
# CONFIG_PREVENT_FIRMWARE_BUILD is not set # CONFIG_PREVENT_FIRMWARE_BUILD is not set
CONFIG_FW_LOADER=y CONFIG_FW_LOADER=y
# CONFIG_DEBUG_DRIVER is not set # CONFIG_DEBUG_DRIVER is not set
# CONFIG_SYS_HYPERVISOR is not set
# #
# Connector - unified userspace <-> kernelspace linker # Connector - unified userspace <-> kernelspace linker
...@@ -434,6 +435,7 @@ CONFIG_ISCSI_TCP=m ...@@ -434,6 +435,7 @@ CONFIG_ISCSI_TCP=m
# CONFIG_MEGARAID_LEGACY is not set # CONFIG_MEGARAID_LEGACY is not set
# CONFIG_MEGARAID_SAS is not set # CONFIG_MEGARAID_SAS is not set
# CONFIG_SCSI_SATA is not set # CONFIG_SCSI_SATA is not set
# CONFIG_SCSI_HPTIOP is not set
# CONFIG_SCSI_DMX3191D is not set # CONFIG_SCSI_DMX3191D is not set
# CONFIG_SCSI_FUTURE_DOMAIN is not set # CONFIG_SCSI_FUTURE_DOMAIN is not set
# CONFIG_SCSI_IPS is not set # CONFIG_SCSI_IPS is not set
...@@ -733,6 +735,7 @@ CONFIG_I2C_ALGOBIT=y ...@@ -733,6 +735,7 @@ CONFIG_I2C_ALGOBIT=y
# CONFIG_I2C_I810 is not set # CONFIG_I2C_I810 is not set
# CONFIG_I2C_PIIX4 is not set # CONFIG_I2C_PIIX4 is not set
# CONFIG_I2C_NFORCE2 is not set # CONFIG_I2C_NFORCE2 is not set
# CONFIG_I2C_OCORES is not set
# CONFIG_I2C_PARPORT_LIGHT is not set # CONFIG_I2C_PARPORT_LIGHT is not set
# CONFIG_I2C_PROSAVAGE is not set # CONFIG_I2C_PROSAVAGE is not set
# CONFIG_I2C_SAVAGE4 is not set # CONFIG_I2C_SAVAGE4 is not set
...@@ -776,6 +779,7 @@ CONFIG_I2C_ALGOBIT=y ...@@ -776,6 +779,7 @@ CONFIG_I2C_ALGOBIT=y
# #
CONFIG_HWMON=y CONFIG_HWMON=y
# CONFIG_HWMON_VID is not set # CONFIG_HWMON_VID is not set
# CONFIG_SENSORS_ABITUGURU is not set
# CONFIG_SENSORS_ADM1021 is not set # CONFIG_SENSORS_ADM1021 is not set
# CONFIG_SENSORS_ADM1025 is not set # CONFIG_SENSORS_ADM1025 is not set
# CONFIG_SENSORS_ADM1026 is not set # CONFIG_SENSORS_ADM1026 is not set
...@@ -804,10 +808,12 @@ CONFIG_HWMON=y ...@@ -804,10 +808,12 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_PC87360 is not set # CONFIG_SENSORS_PC87360 is not set
# CONFIG_SENSORS_SIS5595 is not set # CONFIG_SENSORS_SIS5595 is not set
# CONFIG_SENSORS_SMSC47M1 is not set # CONFIG_SENSORS_SMSC47M1 is not set
# CONFIG_SENSORS_SMSC47M192 is not set
# CONFIG_SENSORS_SMSC47B397 is not set # CONFIG_SENSORS_SMSC47B397 is not set
# CONFIG_SENSORS_VIA686A is not set # CONFIG_SENSORS_VIA686A is not set
# CONFIG_SENSORS_VT8231 is not set # CONFIG_SENSORS_VT8231 is not set
# CONFIG_SENSORS_W83781D is not set # CONFIG_SENSORS_W83781D is not set
# CONFIG_SENSORS_W83791D is not set
# CONFIG_SENSORS_W83792D is not set # CONFIG_SENSORS_W83792D is not set
# CONFIG_SENSORS_W83L785TS is not set # CONFIG_SENSORS_W83L785TS is not set
# CONFIG_SENSORS_W83627HF is not set # CONFIG_SENSORS_W83627HF is not set
...@@ -1018,6 +1024,7 @@ CONFIG_USB_DEVICEFS=y ...@@ -1018,6 +1024,7 @@ CONFIG_USB_DEVICEFS=y
CONFIG_USB_EHCI_HCD=m CONFIG_USB_EHCI_HCD=m
# CONFIG_USB_EHCI_SPLIT_ISO is not set # CONFIG_USB_EHCI_SPLIT_ISO is not set
# CONFIG_USB_EHCI_ROOT_HUB_TT is not set # CONFIG_USB_EHCI_ROOT_HUB_TT is not set
# CONFIG_USB_EHCI_TT_NEWSCHED is not set
# CONFIG_USB_ISP116X_HCD is not set # CONFIG_USB_ISP116X_HCD is not set
CONFIG_USB_OHCI_HCD=y CONFIG_USB_OHCI_HCD=y
# CONFIG_USB_OHCI_BIG_ENDIAN is not set # CONFIG_USB_OHCI_BIG_ENDIAN is not set
...@@ -1097,10 +1104,12 @@ CONFIG_USB_HIDDEV=y ...@@ -1097,10 +1104,12 @@ CONFIG_USB_HIDDEV=y
# CONFIG_USB_LEGOTOWER is not set # CONFIG_USB_LEGOTOWER is not set
# CONFIG_USB_LCD is not set # CONFIG_USB_LCD is not set
# CONFIG_USB_LED is not set # CONFIG_USB_LED is not set
# CONFIG_USB_CY7C63 is not set
# CONFIG_USB_CYTHERM is not set # CONFIG_USB_CYTHERM is not set
# CONFIG_USB_PHIDGETKIT is not set # CONFIG_USB_PHIDGETKIT is not set
# CONFIG_USB_PHIDGETSERVO is not set # CONFIG_USB_PHIDGETSERVO is not set
# CONFIG_USB_IDMOUSE is not set # CONFIG_USB_IDMOUSE is not set
# CONFIG_USB_APPLEDISPLAY is not set
# CONFIG_USB_SISUSBVGA is not set # CONFIG_USB_SISUSBVGA is not set
# CONFIG_USB_LD is not set # CONFIG_USB_LD is not set
# CONFIG_USB_TEST is not set # CONFIG_USB_TEST is not set
...@@ -1198,6 +1207,7 @@ CONFIG_FS_POSIX_ACL=y ...@@ -1198,6 +1207,7 @@ CONFIG_FS_POSIX_ACL=y
# CONFIG_MINIX_FS is not set # CONFIG_MINIX_FS is not set
# CONFIG_ROMFS_FS is not set # CONFIG_ROMFS_FS is not set
CONFIG_INOTIFY=y CONFIG_INOTIFY=y
CONFIG_INOTIFY_USER=y
# CONFIG_QUOTA is not set # CONFIG_QUOTA is not set
CONFIG_DNOTIFY=y CONFIG_DNOTIFY=y
# CONFIG_AUTOFS_FS is not set # CONFIG_AUTOFS_FS is not set
......
...@@ -12,7 +12,7 @@ obj-y := process.o setup.o cpu.o idprom.o \ ...@@ -12,7 +12,7 @@ obj-y := process.o setup.o cpu.o idprom.o \
irq.o ptrace.o time.o sys_sparc.o signal.o \ irq.o ptrace.o time.o sys_sparc.o signal.o \
unaligned.o central.o pci.o starfire.o semaphore.o \ unaligned.o central.o pci.o starfire.o semaphore.o \
power.o sbus.o iommu_common.o sparc64_ksyms.o chmc.o \ power.o sbus.o iommu_common.o sparc64_ksyms.o chmc.o \
visemul.o visemul.o prom.o of_device.o
obj-$(CONFIG_PCI) += ebus.o isa.o pci_common.o pci_iommu.o \ obj-$(CONFIG_PCI) += ebus.o isa.o pci_common.o pci_iommu.o \
pci_psycho.o pci_sabre.o pci_schizo.o \ pci_psycho.o pci_sabre.o pci_schizo.o \
......
...@@ -110,43 +110,82 @@ void auxio_set_lte(int on) ...@@ -110,43 +110,82 @@ void auxio_set_lte(int on)
} }
} }
void __init auxio_probe(void) static void __devinit auxio_report_dev(struct device_node *dp)
{ {
struct sbus_bus *sbus; printk(KERN_INFO "AUXIO: Found device at %s\n",
struct sbus_dev *sdev = NULL; dp->full_name);
}
for_each_sbus(sbus) {
for_each_sbusdev(sdev, sbus) { static struct of_device_id auxio_match[] = {
if(!strcmp(sdev->prom_name, "auxio")) {
goto found_sdev; .name = "auxio",
} },
} {},
};
found_sdev:
if (sdev) { MODULE_DEVICE_TABLE(of, auxio_match);
auxio_devtype = AUXIO_TYPE_SBUS;
auxio_register = sbus_ioremap(&sdev->resource[0], 0, #ifdef CONFIG_SBUS
sdev->reg_addrs[0].reg_size, static int __devinit auxio_sbus_probe(struct of_device *dev, const struct of_device_id *match)
"auxiliaryIO"); {
} struct sbus_dev *sdev = to_sbus_device(&dev->dev);
auxio_devtype = AUXIO_TYPE_SBUS;
auxio_register = sbus_ioremap(&sdev->resource[0], 0,
sdev->reg_addrs[0].reg_size,
"auxiliaryIO");
if (!auxio_register)
return -ENODEV;
auxio_report_dev(dev->node);
return 0;
}
static struct of_platform_driver auxio_sbus_driver = {
.name = "auxio",
.match_table = auxio_match,
.probe = auxio_sbus_probe,
};
#endif
#ifdef CONFIG_PCI #ifdef CONFIG_PCI
else { static int __devinit auxio_ebus_probe(struct of_device *dev, const struct of_device_id *match)
struct linux_ebus *ebus; {
struct linux_ebus_device *edev = NULL; struct linux_ebus_device *edev = to_ebus_device(&dev->dev);
for_each_ebus(ebus) { auxio_devtype = AUXIO_TYPE_EBUS;
for_each_ebusdev(edev, ebus) { auxio_register = ioremap(edev->resource[0].start, sizeof(u32));
if (!strcmp(edev->prom_name, "auxio")) if (!auxio_register)
goto ebus_done; return -ENODEV;
}
} auxio_report_dev(dev->node);
ebus_done:
if (edev) {
auxio_devtype = AUXIO_TYPE_EBUS;
auxio_register =
ioremap(edev->resource[0].start, sizeof(u32));
}
}
auxio_set_led(AUXIO_LED_ON); auxio_set_led(AUXIO_LED_ON);
return 0;
}
static struct of_platform_driver auxio_ebus_driver = {
.name = "auxio",
.match_table = auxio_match,
.probe = auxio_ebus_probe,
};
#endif #endif
static int __init auxio_probe(void)
{
#ifdef CONFIG_SBUS
of_register_driver(&auxio_sbus_driver, &sbus_bus_type);
#endif
#ifdef CONFIG_PCI
of_register_driver(&auxio_ebus_driver, &ebus_bus_type);
#endif
return 0;
} }
/* Must be after subsys_initcall() so that busses are probed. Must
* be before device_initcall() because things like the floppy driver
* need to use the AUXIO register.
*/
fs_initcall(auxio_probe);
...@@ -29,28 +29,34 @@ static void central_probe_failure(int line) ...@@ -29,28 +29,34 @@ static void central_probe_failure(int line)
prom_halt(); prom_halt();
} }
static void central_ranges_init(int cnode, struct linux_central *central) static void central_ranges_init(struct linux_central *central)
{ {
int success; struct device_node *dp = central->prom_node;
void *pval;
int len;
central->num_central_ranges = 0; central->num_central_ranges = 0;
success = prom_getproperty(central->prom_node, "ranges", pval = of_get_property(dp, "ranges", &len);
(char *) central->central_ranges, if (pval) {
sizeof (central->central_ranges)); memcpy(central->central_ranges, pval, len);
if (success != -1) central->num_central_ranges =
central->num_central_ranges = (success/sizeof(struct linux_prom_ranges)); (len / sizeof(struct linux_prom_ranges));
}
} }
static void fhc_ranges_init(int fnode, struct linux_fhc *fhc) static void fhc_ranges_init(struct linux_fhc *fhc)
{ {
int success; struct device_node *dp = fhc->prom_node;
void *pval;
int len;
fhc->num_fhc_ranges = 0; fhc->num_fhc_ranges = 0;
success = prom_getproperty(fhc->prom_node, "ranges", pval = of_get_property(dp, "ranges", &len);
(char *) fhc->fhc_ranges, if (pval) {
sizeof (fhc->fhc_ranges)); memcpy(fhc->fhc_ranges, pval, len);
if (success != -1) fhc->num_fhc_ranges =
fhc->num_fhc_ranges = (success/sizeof(struct linux_prom_ranges)); (len / sizeof(struct linux_prom_ranges));
}
} }
/* Range application routines are exported to various drivers, /* Range application routines are exported to various drivers,
...@@ -112,15 +118,10 @@ static unsigned long prom_reg_to_paddr(struct linux_prom_registers *r) ...@@ -112,15 +118,10 @@ static unsigned long prom_reg_to_paddr(struct linux_prom_registers *r)
static void probe_other_fhcs(void) static void probe_other_fhcs(void)
{ {
struct linux_prom64_registers fpregs[6]; struct device_node *dp;
char namebuf[128]; struct linux_prom64_registers *fpregs;
int node;
node = prom_getchild(prom_root_node); for_each_node_by_name(dp, "fhc") {
node = prom_searchsiblings(node, "fhc");
if (node == 0)
central_probe_failure(__LINE__);
while (node) {
struct linux_fhc *fhc; struct linux_fhc *fhc;
int board; int board;
u32 tmp; u32 tmp;
...@@ -137,14 +138,12 @@ static void probe_other_fhcs(void) ...@@ -137,14 +138,12 @@ static void probe_other_fhcs(void)
/* Toplevel FHCs have no parent. */ /* Toplevel FHCs have no parent. */
fhc->parent = NULL; fhc->parent = NULL;
fhc->prom_node = node; fhc->prom_node = dp;
prom_getstring(node, "name", namebuf, sizeof(namebuf)); fhc_ranges_init(fhc);
strcpy(fhc->prom_name, namebuf);
fhc_ranges_init(node, fhc);
/* Non-central FHC's have 64-bit OBP format registers. */ /* Non-central FHC's have 64-bit OBP format registers. */
if (prom_getproperty(node, "reg", fpregs = of_get_property(dp, "reg", NULL);
(char *)&fpregs[0], sizeof(fpregs)) == -1) if (!fpregs)
central_probe_failure(__LINE__); central_probe_failure(__LINE__);
/* Only central FHC needs special ranges applied. */ /* Only central FHC needs special ranges applied. */
...@@ -155,7 +154,7 @@ static void probe_other_fhcs(void) ...@@ -155,7 +154,7 @@ static void probe_other_fhcs(void)
fhc->fhc_regs.uregs = fpregs[4].phys_addr; fhc->fhc_regs.uregs = fpregs[4].phys_addr;
fhc->fhc_regs.tregs = fpregs[5].phys_addr; fhc->fhc_regs.tregs = fpregs[5].phys_addr;
board = prom_getintdefault(node, "board#", -1); board = of_getintprop_default(dp, "board#", -1);
fhc->board = board; fhc->board = board;
tmp = upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_JCTRL); tmp = upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_JCTRL);
...@@ -179,33 +178,33 @@ static void probe_other_fhcs(void) ...@@ -179,33 +178,33 @@ static void probe_other_fhcs(void)
tmp = upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_CTRL); tmp = upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_CTRL);
tmp |= FHC_CONTROL_IXIST; tmp |= FHC_CONTROL_IXIST;
upa_writel(tmp, fhc->fhc_regs.pregs + FHC_PREGS_CTRL); upa_writel(tmp, fhc->fhc_regs.pregs + FHC_PREGS_CTRL);
/* Look for the next FHC. */
node = prom_getsibling(node);
if (node == 0)
break;
node = prom_searchsiblings(node, "fhc");
if (node == 0)
break;
} }
} }
static void probe_clock_board(struct linux_central *central, static void probe_clock_board(struct linux_central *central,
struct linux_fhc *fhc, struct linux_fhc *fhc,
int cnode, int fnode) struct device_node *fp)
{ {
struct linux_prom_registers cregs[3]; struct device_node *dp;
int clknode, nslots, tmp, nregs; struct linux_prom_registers cregs[3], *pr;
int nslots, tmp, nregs;
clknode = prom_searchsiblings(prom_getchild(fnode), "clock-board"); dp = fp->child;
if (clknode == 0 || clknode == -1) while (dp) {
if (!strcmp(dp->name, "clock-board"))
break;
dp = dp->sibling;
}
if (!dp)
central_probe_failure(__LINE__); central_probe_failure(__LINE__);
nregs = prom_getproperty(clknode, "reg", (char *)&cregs[0], sizeof(cregs)); pr = of_get_property(dp, "reg", &nregs);
if (nregs == -1) if (!pr)
central_probe_failure(__LINE__); central_probe_failure(__LINE__);
memcpy(cregs, pr, nregs);
nregs /= sizeof(struct linux_prom_registers); nregs /= sizeof(struct linux_prom_registers);
apply_fhc_ranges(fhc, &cregs[0], nregs); apply_fhc_ranges(fhc, &cregs[0], nregs);
apply_central_ranges(central, &cregs[0], nregs); apply_central_ranges(central, &cregs[0], nregs);
central->cfreg = prom_reg_to_paddr(&cregs[0]); central->cfreg = prom_reg_to_paddr(&cregs[0]);
...@@ -296,13 +295,13 @@ static void init_all_fhc_hw(void) ...@@ -296,13 +295,13 @@ static void init_all_fhc_hw(void)
void central_probe(void) void central_probe(void)
{ {
struct linux_prom_registers fpregs[6]; struct linux_prom_registers fpregs[6], *pr;
struct linux_fhc *fhc; struct linux_fhc *fhc;
char namebuf[128]; struct device_node *dp, *fp;
int cnode, fnode, err; int err;
cnode = prom_finddevice("/central"); dp = of_find_node_by_name(NULL, "central");
if (cnode == 0 || cnode == -1) { if (!dp) {
if (this_is_starfire) if (this_is_starfire)
starfire_cpu_setup(); starfire_cpu_setup();
return; return;
...@@ -321,31 +320,31 @@ void central_probe(void) ...@@ -321,31 +320,31 @@ void central_probe(void)
/* First init central. */ /* First init central. */
central_bus->child = fhc; central_bus->child = fhc;
central_bus->prom_node = cnode; central_bus->prom_node = dp;
central_ranges_init(central_bus);
prom_getstring(cnode, "name", namebuf, sizeof(namebuf));
strcpy(central_bus->prom_name, namebuf);
central_ranges_init(cnode, central_bus);
/* And then central's FHC. */ /* And then central's FHC. */
fhc->next = fhc_list; fhc->next = fhc_list;
fhc_list = fhc; fhc_list = fhc;
fhc->parent = central_bus; fhc->parent = central_bus;
fnode = prom_searchsiblings(prom_getchild(cnode), "fhc"); fp = dp->child;
if (fnode == 0 || fnode == -1) while (fp) {
if (!strcmp(fp->name, "fhc"))
break;
fp = fp->sibling;
}
if (!fp)
central_probe_failure(__LINE__); central_probe_failure(__LINE__);
fhc->prom_node = fnode; fhc->prom_node = fp;
prom_getstring(fnode, "name", namebuf, sizeof(namebuf)); fhc_ranges_init(fhc);
strcpy(fhc->prom_name, namebuf);
fhc_ranges_init(fnode, fhc);
/* Now, map in FHC register set. */ /* Now, map in FHC register set. */
if (prom_getproperty(fnode, "reg", (char *)&fpregs[0], sizeof(fpregs)) == -1) pr = of_get_property(fp, "reg", NULL);
if (!pr)
central_probe_failure(__LINE__); central_probe_failure(__LINE__);
memcpy(fpregs, pr, sizeof(fpregs));
apply_central_ranges(central_bus, &fpregs[0], 6); apply_central_ranges(central_bus, &fpregs[0], 6);
...@@ -366,7 +365,7 @@ void central_probe(void) ...@@ -366,7 +365,7 @@ void central_probe(void)
fhc->jtag_master = 0; fhc->jtag_master = 0;
/* Attach the clock board registers for CENTRAL. */ /* Attach the clock board registers for CENTRAL. */
probe_clock_board(central_bus, fhc, cnode, fnode); probe_clock_board(central_bus, fhc, fp);
err = upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_ID); err = upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_ID);
printk("FHC(board %d): Version[%x] PartID[%x] Manuf[%x] (CENTRAL)\n", printk("FHC(board %d): Version[%x] PartID[%x] Manuf[%x] (CENTRAL)\n",
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include <asm/spitfire.h> #include <asm/spitfire.h>
#include <asm/chmctrl.h> #include <asm/chmctrl.h>
#include <asm/oplib.h> #include <asm/oplib.h>
#include <asm/prom.h>
#include <asm/io.h> #include <asm/io.h>
#define CHMCTRL_NDGRPS 2 #define CHMCTRL_NDGRPS 2
...@@ -67,7 +68,6 @@ struct bank_info { ...@@ -67,7 +68,6 @@ struct bank_info {
struct mctrl_info { struct mctrl_info {
struct list_head list; struct list_head list;
int portid; int portid;
int index;
struct obp_mem_layout layout_prop; struct obp_mem_layout layout_prop;
int layout_size; int layout_size;
...@@ -339,12 +339,13 @@ static void fetch_decode_regs(struct mctrl_info *mp) ...@@ -339,12 +339,13 @@ static void fetch_decode_regs(struct mctrl_info *mp)
read_mcreg(mp, CHMCTRL_DECODE4)); read_mcreg(mp, CHMCTRL_DECODE4));
} }
static int init_one_mctrl(int node, int index) static int init_one_mctrl(struct device_node *dp)
{ {
struct mctrl_info *mp = kmalloc(sizeof(*mp), GFP_KERNEL); struct mctrl_info *mp = kmalloc(sizeof(*mp), GFP_KERNEL);
int portid = prom_getintdefault(node, "portid", -1); int portid = of_getintprop_default(dp, "portid", -1);
struct linux_prom64_registers p_reg_prop; struct linux_prom64_registers *regs;
int t; void *pval;
int len;
if (!mp) if (!mp)
return -1; return -1;
...@@ -353,24 +354,21 @@ static int init_one_mctrl(int node, int index) ...@@ -353,24 +354,21 @@ static int init_one_mctrl(int node, int index)
goto fail; goto fail;
mp->portid = portid; mp->portid = portid;
mp->layout_size = prom_getproplen(node, "memory-layout"); pval = of_get_property(dp, "memory-layout", &len);
if (mp->layout_size < 0) mp->layout_size = len;
if (!pval)
mp->layout_size = 0; mp->layout_size = 0;
if (mp->layout_size > sizeof(mp->layout_prop)) else {
goto fail; if (mp->layout_size > sizeof(mp->layout_prop))
goto fail;
if (mp->layout_size > 0) memcpy(&mp->layout_prop, pval, len);
prom_getproperty(node, "memory-layout", }
(char *) &mp->layout_prop,
mp->layout_size);
t = prom_getproperty(node, "reg", regs = of_get_property(dp, "reg", NULL);
(char *) &p_reg_prop, if (!regs || regs->reg_size != 0x48)
sizeof(p_reg_prop));
if (t < 0 || p_reg_prop.reg_size != 0x48)
goto fail; goto fail;
mp->regs = ioremap(p_reg_prop.phys_addr, p_reg_prop.reg_size); mp->regs = ioremap(regs->phys_addr, regs->reg_size);
if (mp->regs == NULL) if (mp->regs == NULL)
goto fail; goto fail;
...@@ -384,13 +382,11 @@ static int init_one_mctrl(int node, int index) ...@@ -384,13 +382,11 @@ static int init_one_mctrl(int node, int index)
fetch_decode_regs(mp); fetch_decode_regs(mp);
mp->index = index;
list_add(&mp->list, &mctrl_list); list_add(&mp->list, &mctrl_list);
/* Report the device. */ /* Report the device. */
printk(KERN_INFO "chmc%d: US3 memory controller at %p [%s]\n", printk(KERN_INFO "%s: US3 memory controller at %p [%s]\n",
mp->index, dp->full_name,
mp->regs, (mp->layout_size ? "ACTIVE" : "INACTIVE")); mp->regs, (mp->layout_size ? "ACTIVE" : "INACTIVE"));
return 0; return 0;
...@@ -404,34 +400,19 @@ static int init_one_mctrl(int node, int index) ...@@ -404,34 +400,19 @@ static int init_one_mctrl(int node, int index)
return -1; return -1;
} }
static int __init probe_for_string(char *name, int index)
{
int node = prom_getchild(prom_root_node);
while ((node = prom_searchsiblings(node, name)) != 0) {
int ret = init_one_mctrl(node, index);
if (!ret)
index++;
node = prom_getsibling(node);
if (!node)
break;
}
return index;
}
static int __init chmc_init(void) static int __init chmc_init(void)
{ {
int index; struct device_node *dp;
/* This driver is only for cheetah platforms. */ /* This driver is only for cheetah platforms. */
if (tlb_type != cheetah && tlb_type != cheetah_plus) if (tlb_type != cheetah && tlb_type != cheetah_plus)
return -ENODEV; return -ENODEV;
index = probe_for_string("memory-controller", 0); for_each_node_by_name(dp, "memory-controller")
index = probe_for_string("mc-us3", index); init_one_mctrl(dp);
for_each_node_by_name(dp, "mc-us3")
init_one_mctrl(dp);
return 0; return 0;
} }
......
This diff is collapsed.
This diff is collapsed.
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
#include <asm/iommu.h> #include <asm/iommu.h>
#include <asm/upa.h> #include <asm/upa.h>
#include <asm/oplib.h> #include <asm/oplib.h>
#include <asm/prom.h>
#include <asm/timer.h> #include <asm/timer.h>
#include <asm/smp.h> #include <asm/smp.h>
#include <asm/starfire.h> #include <asm/starfire.h>
...@@ -635,23 +636,29 @@ static u64 prom_limit0, prom_limit1; ...@@ -635,23 +636,29 @@ static u64 prom_limit0, prom_limit1;
static void map_prom_timers(void) static void map_prom_timers(void)
{ {
unsigned int addr[3]; struct device_node *dp;
int tnode, err; unsigned int *addr;
/* PROM timer node hangs out in the top level of device siblings... */ /* PROM timer node hangs out in the top level of device siblings... */
tnode = prom_finddevice("/counter-timer"); dp = of_find_node_by_path("/");
dp = dp->child;
while (dp) {
if (!strcmp(dp->name, "counter-timer"))
break;
dp = dp->sibling;
}
/* Assume if node is not present, PROM uses different tick mechanism /* Assume if node is not present, PROM uses different tick mechanism
* which we should not care about. * which we should not care about.
*/ */
if (tnode == 0 || tnode == -1) { if (!dp) {
prom_timers = (struct sun5_timer *) 0; prom_timers = (struct sun5_timer *) 0;
return; return;
} }
/* If PROM is really using this, it must be mapped by him. */ /* If PROM is really using this, it must be mapped by him. */
err = prom_getproperty(tnode, "address", (char *)addr, sizeof(addr)); addr = of_get_property(dp, "address", NULL);
if (err == -1) { if (!addr) {
prom_printf("PROM does not have timer mapped, trying to continue.\n"); prom_printf("PROM does not have timer mapped, trying to continue.\n");
prom_timers = (struct sun5_timer *) 0; prom_timers = (struct sun5_timer *) 0;
return; return;
......
...@@ -15,23 +15,19 @@ static void __init fatal_err(const char *reason) ...@@ -15,23 +15,19 @@ static void __init fatal_err(const char *reason)
static void __init report_dev(struct sparc_isa_device *isa_dev, int child) static void __init report_dev(struct sparc_isa_device *isa_dev, int child)
{ {
if (child) if (child)
printk(" (%s)", isa_dev->prom_name); printk(" (%s)", isa_dev->prom_node->name);
else else
printk(" [%s", isa_dev->prom_name); printk(" [%s", isa_dev->prom_node->name);
} }
static void __init isa_dev_get_resource(struct sparc_isa_device *isa_dev, static struct linux_prom_registers * __init
struct linux_prom_registers *pregs, isa_dev_get_resource(struct sparc_isa_device *isa_dev)
int pregs_size)
{ {
struct linux_prom_registers *pregs;
unsigned long base, len; unsigned long base, len;
int prop_len; int prop_len;
prop_len = prom_getproperty(isa_dev->prom_node, "reg", pregs = of_get_property(isa_dev->prom_node, "reg", &prop_len);
(char *) pregs, pregs_size);
if (prop_len <= 0)
return;
/* Only the first one is interesting. */ /* Only the first one is interesting. */
len = pregs[0].reg_size; len = pregs[0].reg_size;
...@@ -42,10 +38,12 @@ static void __init isa_dev_get_resource(struct sparc_isa_device *isa_dev, ...@@ -42,10 +38,12 @@ static void __init isa_dev_get_resource(struct sparc_isa_device *isa_dev,
isa_dev->resource.start = base; isa_dev->resource.start = base;
isa_dev->resource.end = (base + len - 1UL); isa_dev->resource.end = (base + len - 1UL);
isa_dev->resource.flags = IORESOURCE_IO; isa_dev->resource.flags = IORESOURCE_IO;
isa_dev->resource.name = isa_dev->prom_name; isa_dev->resource.name = isa_dev->prom_node->name;
request_resource(&isa_dev->bus->parent->io_space, request_resource(&isa_dev->bus->parent->io_space,
&isa_dev->resource); &isa_dev->resource);
return pregs;
} }
/* I can't believe they didn't put a real INO in the isa device /* I can't believe they didn't put a real INO in the isa device
...@@ -74,19 +72,30 @@ static struct { ...@@ -74,19 +72,30 @@ static struct {
static int __init isa_dev_get_irq_using_imap(struct sparc_isa_device *isa_dev, static int __init isa_dev_get_irq_using_imap(struct sparc_isa_device *isa_dev,
struct sparc_isa_bridge *isa_br, struct sparc_isa_bridge *isa_br,
int *interrupt, int *interrupt,
struct linux_prom_registers *pregs) struct linux_prom_registers *reg)
{ {
struct linux_prom_ebus_intmap *imap;
struct linux_prom_ebus_intmap *imask;
unsigned int hi, lo, irq; unsigned int hi, lo, irq;
int i; int i, len, n_imap;
hi = pregs->which_io & isa_br->isa_intmask.phys_hi; imap = of_get_property(isa_br->prom_node, "interrupt-map", &len);
lo = pregs->phys_addr & isa_br->isa_intmask.phys_lo; if (!imap)
irq = *interrupt & isa_br->isa_intmask.interrupt; return 0;
for (i = 0; i < isa_br->num_isa_intmap; i++) { n_imap = len / sizeof(imap[0]);
if ((isa_br->isa_intmap[i].phys_hi == hi) &&
(isa_br->isa_intmap[i].phys_lo == lo) && imask = of_get_property(isa_br->prom_node, "interrupt-map-mask", NULL);
(isa_br->isa_intmap[i].interrupt == irq)) { if (!imask)
*interrupt = isa_br->isa_intmap[i].cinterrupt; return 0;
hi = reg->which_io & imask->phys_hi;
lo = reg->phys_addr & imask->phys_lo;
irq = *interrupt & imask->interrupt;
for (i = 0; i < n_imap; i++) {
if ((imap[i].phys_hi == hi) &&
(imap[i].phys_lo == lo) &&
(imap[i].interrupt == irq)) {
*interrupt = imap[i].cinterrupt;
return 0; return 0;
} }
} }
...@@ -98,8 +107,8 @@ static void __init isa_dev_get_irq(struct sparc_isa_device *isa_dev, ...@@ -98,8 +107,8 @@ static void __init isa_dev_get_irq(struct sparc_isa_device *isa_dev,
{ {
int irq_prop; int irq_prop;
irq_prop = prom_getintdefault(isa_dev->prom_node, irq_prop = of_getintprop_default(isa_dev->prom_node,
"interrupts", -1); "interrupts", -1);
if (irq_prop <= 0) { if (irq_prop <= 0) {
goto no_irq; goto no_irq;
} else { } else {
...@@ -107,7 +116,8 @@ static void __init isa_dev_get_irq(struct sparc_isa_device *isa_dev, ...@@ -107,7 +116,8 @@ static void __init isa_dev_get_irq(struct sparc_isa_device *isa_dev,
struct pci_pbm_info *pbm; struct pci_pbm_info *pbm;
int i; int i;
if (isa_dev->bus->num_isa_intmap) { if (of_find_property(isa_dev->bus->prom_node,
"interrupt-map", NULL)) {
if (!isa_dev_get_irq_using_imap(isa_dev, if (!isa_dev_get_irq_using_imap(isa_dev,
isa_dev->bus, isa_dev->bus,
&irq_prop, &irq_prop,
...@@ -141,16 +151,15 @@ static void __init isa_dev_get_irq(struct sparc_isa_device *isa_dev, ...@@ -141,16 +151,15 @@ static void __init isa_dev_get_irq(struct sparc_isa_device *isa_dev,
static void __init isa_fill_children(struct sparc_isa_device *parent_isa_dev) static void __init isa_fill_children(struct sparc_isa_device *parent_isa_dev)
{ {
int node = prom_getchild(parent_isa_dev->prom_node); struct device_node *dp = parent_isa_dev->prom_node->child;
if (node == 0) if (!dp)
return; return;
printk(" ->"); printk(" ->");
while (node != 0) { while (dp) {
struct linux_prom_registers regs[PROMREG_MAX]; struct linux_prom_registers *regs;
struct sparc_isa_device *isa_dev; struct sparc_isa_device *isa_dev;
int prop_len;
isa_dev = kmalloc(sizeof(*isa_dev), GFP_KERNEL); isa_dev = kmalloc(sizeof(*isa_dev), GFP_KERNEL);
if (!isa_dev) { if (!isa_dev) {
...@@ -165,49 +174,46 @@ static void __init isa_fill_children(struct sparc_isa_device *parent_isa_dev) ...@@ -165,49 +174,46 @@ static void __init isa_fill_children(struct sparc_isa_device *parent_isa_dev)
parent_isa_dev->child = isa_dev; parent_isa_dev->child = isa_dev;
isa_dev->bus = parent_isa_dev->bus; isa_dev->bus = parent_isa_dev->bus;
isa_dev->prom_node = node; isa_dev->prom_node = dp;
prop_len = prom_getproperty(node, "name",
(char *) isa_dev->prom_name,
sizeof(isa_dev->prom_name));
if (prop_len <= 0) {
fatal_err("cannot get child isa_dev OBP node name");
prom_halt();
}
prop_len = prom_getproperty(node, "compatible", regs = isa_dev_get_resource(isa_dev);
(char *) isa_dev->compatible,
sizeof(isa_dev->compatible));
/* Not having this is OK. */
if (prop_len <= 0)
isa_dev->compatible[0] = '\0';
isa_dev_get_resource(isa_dev, regs, sizeof(regs));
isa_dev_get_irq(isa_dev, regs); isa_dev_get_irq(isa_dev, regs);
report_dev(isa_dev, 1); report_dev(isa_dev, 1);
node = prom_getsibling(node); dp = dp->sibling;
} }
} }
static void __init isa_fill_devices(struct sparc_isa_bridge *isa_br) static void __init isa_fill_devices(struct sparc_isa_bridge *isa_br)
{ {
int node = prom_getchild(isa_br->prom_node); struct device_node *dp = isa_br->prom_node->child;
while (node != 0) { while (dp) {
struct linux_prom_registers regs[PROMREG_MAX]; struct linux_prom_registers *regs;
struct sparc_isa_device *isa_dev; struct sparc_isa_device *isa_dev;
int prop_len;
isa_dev = kmalloc(sizeof(*isa_dev), GFP_KERNEL); isa_dev = kmalloc(sizeof(*isa_dev), GFP_KERNEL);
if (!isa_dev) { if (!isa_dev) {
fatal_err("cannot allocate isa_dev"); printk(KERN_DEBUG "ISA: cannot allocate isa_dev");
prom_halt(); return;
} }
memset(isa_dev, 0, sizeof(*isa_dev)); memset(isa_dev, 0, sizeof(*isa_dev));
isa_dev->ofdev.node = dp;
isa_dev->ofdev.dev.parent = &isa_br->ofdev.dev;
isa_dev->ofdev.dev.bus = &isa_bus_type;
strcpy(isa_dev->ofdev.dev.bus_id, dp->path_component_name);
/* Register with core */
if (of_device_register(&isa_dev->ofdev) != 0) {
printk(KERN_DEBUG "isa: device registration error for %s!\n",
isa_dev->ofdev.dev.bus_id);
kfree(isa_dev);
goto next_sibling;
}
/* Link it in. */ /* Link it in. */
isa_dev->next = NULL; isa_dev->next = NULL;
if (isa_br->devices == NULL) { if (isa_br->devices == NULL) {
...@@ -222,24 +228,9 @@ static void __init isa_fill_devices(struct sparc_isa_bridge *isa_br) ...@@ -222,24 +228,9 @@ static void __init isa_fill_devices(struct sparc_isa_bridge *isa_br)
} }
isa_dev->bus = isa_br; isa_dev->bus = isa_br;
isa_dev->prom_node = node; isa_dev->prom_node = dp;
prop_len = prom_getproperty(node, "name",
(char *) isa_dev->prom_name,
sizeof(isa_dev->prom_name));
if (prop_len <= 0) {
fatal_err("cannot get isa_dev OBP node name");
prom_halt();
}
prop_len = prom_getproperty(node, "compatible",
(char *) isa_dev->compatible,
sizeof(isa_dev->compatible));
/* Not having this is OK. */ regs = isa_dev_get_resource(isa_dev);
if (prop_len <= 0)
isa_dev->compatible[0] = '\0';
isa_dev_get_resource(isa_dev, regs, sizeof(regs));
isa_dev_get_irq(isa_dev, regs); isa_dev_get_irq(isa_dev, regs);
report_dev(isa_dev, 0); report_dev(isa_dev, 0);
...@@ -248,7 +239,8 @@ static void __init isa_fill_devices(struct sparc_isa_bridge *isa_br) ...@@ -248,7 +239,8 @@ static void __init isa_fill_devices(struct sparc_isa_bridge *isa_br)
printk("]"); printk("]");
node = prom_getsibling(node); next_sibling:
dp = dp->sibling;
} }
} }
...@@ -266,7 +258,7 @@ void __init isa_init(void) ...@@ -266,7 +258,7 @@ void __init isa_init(void)
struct pcidev_cookie *pdev_cookie; struct pcidev_cookie *pdev_cookie;
struct pci_pbm_info *pbm; struct pci_pbm_info *pbm;
struct sparc_isa_bridge *isa_br; struct sparc_isa_bridge *isa_br;
int prop_len; struct device_node *dp;
pdev_cookie = pdev->sysdata; pdev_cookie = pdev->sysdata;
if (!pdev_cookie) { if (!pdev_cookie) {
...@@ -275,15 +267,29 @@ void __init isa_init(void) ...@@ -275,15 +267,29 @@ void __init isa_init(void)
continue; continue;
} }
pbm = pdev_cookie->pbm; pbm = pdev_cookie->pbm;
dp = pdev_cookie->prom_node;
isa_br = kmalloc(sizeof(*isa_br), GFP_KERNEL); isa_br = kmalloc(sizeof(*isa_br), GFP_KERNEL);
if (!isa_br) { if (!isa_br) {
fatal_err("cannot allocate sparc_isa_bridge"); printk(KERN_DEBUG "isa: cannot allocate sparc_isa_bridge");
prom_halt(); return;
} }
memset(isa_br, 0, sizeof(*isa_br)); memset(isa_br, 0, sizeof(*isa_br));
isa_br->ofdev.node = dp;
isa_br->ofdev.dev.parent = &pdev->dev;
isa_br->ofdev.dev.bus = &isa_bus_type;
strcpy(isa_br->ofdev.dev.bus_id, dp->path_component_name);
/* Register with core */
if (of_device_register(&isa_br->ofdev) != 0) {
printk(KERN_DEBUG "isa: device registration error for %s!\n",
isa_br->ofdev.dev.bus_id);
kfree(isa_br);
return;
}
/* Link it in. */ /* Link it in. */
isa_br->next = isa_chain; isa_br->next = isa_chain;
isa_chain = isa_br; isa_chain = isa_br;
...@@ -292,33 +298,6 @@ void __init isa_init(void) ...@@ -292,33 +298,6 @@ void __init isa_init(void)
isa_br->self = pdev; isa_br->self = pdev;
isa_br->index = index++; isa_br->index = index++;
isa_br->prom_node = pdev_cookie->prom_node; isa_br->prom_node = pdev_cookie->prom_node;
strncpy(isa_br->prom_name, pdev_cookie->prom_name,
sizeof(isa_br->prom_name));
prop_len = prom_getproperty(isa_br->prom_node,
"ranges",
(char *) isa_br->isa_ranges,
sizeof(isa_br->isa_ranges));
if (prop_len <= 0)
isa_br->num_isa_ranges = 0;
else
isa_br->num_isa_ranges =
(prop_len / sizeof(struct linux_prom_isa_ranges));
prop_len = prom_getproperty(isa_br->prom_node,
"interrupt-map",
(char *) isa_br->isa_intmap,
sizeof(isa_br->isa_intmap));
if (prop_len <= 0)
isa_br->num_isa_intmap = 0;
else
isa_br->num_isa_intmap =
(prop_len / sizeof(struct linux_prom_isa_intmap));
prop_len = prom_getproperty(isa_br->prom_node,
"interrupt-map-mask",
(char *) &(isa_br->isa_intmask),
sizeof(isa_br->isa_intmask));
printk("isa%d:", isa_br->index); printk("isa%d:", isa_br->index);
......
#include <linux/config.h>
#include <linux/string.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/mod_devicetable.h>
#include <linux/slab.h>
#include <asm/errno.h>
#include <asm/of_device.h>
/**
* of_match_device - Tell if an of_device structure has a matching
* of_match structure
* @ids: array of of device match structures to search in
* @dev: the of device structure to match against
*
* Used by a driver to check whether an of_device present in the
* system is in its list of supported devices.
*/
const struct of_device_id *of_match_device(const struct of_device_id *matches,
const struct of_device *dev)
{
if (!dev->node)
return NULL;
while (matches->name[0] || matches->type[0] || matches->compatible[0]) {
int match = 1;
if (matches->name[0])
match &= dev->node->name
&& !strcmp(matches->name, dev->node->name);
if (matches->type[0])
match &= dev->node->type
&& !strcmp(matches->type, dev->node->type);
if (matches->compatible[0])
match &= of_device_is_compatible(dev->node,
matches->compatible);
if (match)
return matches;
matches++;
}
return NULL;
}
static int of_platform_bus_match(struct device *dev, struct device_driver *drv)
{
struct of_device * of_dev = to_of_device(dev);
struct of_platform_driver * of_drv = to_of_platform_driver(drv);
const struct of_device_id * matches = of_drv->match_table;
if (!matches)
return 0;
return of_match_device(matches, of_dev) != NULL;
}
struct of_device *of_dev_get(struct of_device *dev)
{
struct device *tmp;
if (!dev)
return NULL;
tmp = get_device(&dev->dev);
if (tmp)
return to_of_device(tmp);
else
return NULL;
}
void of_dev_put(struct of_device *dev)
{
if (dev)
put_device(&dev->dev);
}
static int of_device_probe(struct device *dev)
{
int error = -ENODEV;
struct of_platform_driver *drv;
struct of_device *of_dev;
const struct of_device_id *match;
drv = to_of_platform_driver(dev->driver);
of_dev = to_of_device(dev);
if (!drv->probe)
return error;
of_dev_get(of_dev);
match = of_match_device(drv->match_table, of_dev);
if (match)
error = drv->probe(of_dev, match);
if (error)
of_dev_put(of_dev);
return error;
}
static int of_device_remove(struct device *dev)
{
struct of_device * of_dev = to_of_device(dev);
struct of_platform_driver * drv = to_of_platform_driver(dev->driver);
if (dev->driver && drv->remove)
drv->remove(of_dev);
return 0;
}
static int of_device_suspend(struct device *dev, pm_message_t state)
{
struct of_device * of_dev = to_of_device(dev);
struct of_platform_driver * drv = to_of_platform_driver(dev->driver);
int error = 0;
if (dev->driver && drv->suspend)
error = drv->suspend(of_dev, state);
return error;
}
static int of_device_resume(struct device * dev)
{
struct of_device * of_dev = to_of_device(dev);
struct of_platform_driver * drv = to_of_platform_driver(dev->driver);
int error = 0;
if (dev->driver && drv->resume)
error = drv->resume(of_dev);
return error;
}
#ifdef CONFIG_PCI
struct bus_type isa_bus_type = {
.name = "isa",
.match = of_platform_bus_match,
.probe = of_device_probe,
.remove = of_device_remove,
.suspend = of_device_suspend,
.resume = of_device_resume,
};
struct bus_type ebus_bus_type = {
.name = "ebus",
.match = of_platform_bus_match,
.probe = of_device_probe,
.remove = of_device_remove,
.suspend = of_device_suspend,
.resume = of_device_resume,
};
#endif
#ifdef CONFIG_SBUS
struct bus_type sbus_bus_type = {
.name = "sbus",
.match = of_platform_bus_match,
.probe = of_device_probe,
.remove = of_device_remove,
.suspend = of_device_suspend,
.resume = of_device_resume,
};
#endif
static int __init of_bus_driver_init(void)
{
int err = 0;
#ifdef CONFIG_PCI
if (!err)
err = bus_register(&isa_bus_type);
if (!err)
err = bus_register(&ebus_bus_type);
#endif
#ifdef CONFIG_SBUS
if (!err)
err = bus_register(&sbus_bus_type);
#endif
return 0;
}
postcore_initcall(of_bus_driver_init);
int of_register_driver(struct of_platform_driver *drv, struct bus_type *bus)
{
/* initialize common driver fields */
drv->driver.name = drv->name;
drv->driver.bus = bus;
/* register with core */
return driver_register(&drv->driver);
}
void of_unregister_driver(struct of_platform_driver *drv)
{
driver_unregister(&drv->driver);
}
static ssize_t dev_show_devspec(struct device *dev, struct device_attribute *attr, char *buf)
{
struct of_device *ofdev;
ofdev = to_of_device(dev);
return sprintf(buf, "%s", ofdev->node->full_name);
}
static DEVICE_ATTR(devspec, S_IRUGO, dev_show_devspec, NULL);
/**
* of_release_dev - free an of device structure when all users of it are finished.
* @dev: device that's been disconnected
*
* Will be called only by the device core when all users of this of device are
* done.
*/
void of_release_dev(struct device *dev)
{
struct of_device *ofdev;
ofdev = to_of_device(dev);
kfree(ofdev);
}
int of_device_register(struct of_device *ofdev)
{
int rc;
BUG_ON(ofdev->node == NULL);
rc = device_register(&ofdev->dev);
if (rc)
return rc;
device_create_file(&ofdev->dev, &dev_attr_devspec);
return 0;
}
void of_device_unregister(struct of_device *ofdev)
{
device_remove_file(&ofdev->dev, &dev_attr_devspec);
device_unregister(&ofdev->dev);
}
struct of_device* of_platform_device_create(struct device_node *np,
const char *bus_id,
struct device *parent,
struct bus_type *bus)
{
struct of_device *dev;
dev = kmalloc(sizeof(*dev), GFP_KERNEL);
if (!dev)
return NULL;
memset(dev, 0, sizeof(*dev));
dev->dev.parent = parent;
dev->dev.bus = bus;
dev->dev.release = of_release_dev;
strlcpy(dev->dev.bus_id, bus_id, BUS_ID_SIZE);
if (of_device_register(dev) != 0) {
kfree(dev);
return NULL;
}
return dev;
}
EXPORT_SYMBOL(of_match_device);
EXPORT_SYMBOL(of_register_driver);
EXPORT_SYMBOL(of_unregister_driver);
EXPORT_SYMBOL(of_device_register);
EXPORT_SYMBOL(of_device_unregister);
EXPORT_SYMBOL(of_dev_get);
EXPORT_SYMBOL(of_dev_put);
EXPORT_SYMBOL(of_platform_device_create);
EXPORT_SYMBOL(of_release_dev);
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include <asm/irq.h> #include <asm/irq.h>
#include <asm/ebus.h> #include <asm/ebus.h>
#include <asm/isa.h> #include <asm/isa.h>
#include <asm/prom.h>
unsigned long pci_memspace_mask = 0xffffffffUL; unsigned long pci_memspace_mask = 0xffffffffUL;
...@@ -177,16 +178,16 @@ void pci_config_write32(u32 *addr, u32 val) ...@@ -177,16 +178,16 @@ void pci_config_write32(u32 *addr, u32 val)
} }
/* Probe for all PCI controllers in the system. */ /* Probe for all PCI controllers in the system. */
extern void sabre_init(int, char *); extern void sabre_init(struct device_node *, const char *);
extern void psycho_init(int, char *); extern void psycho_init(struct device_node *, const char *);
extern void schizo_init(int, char *); extern void schizo_init(struct device_node *, const char *);
extern void schizo_plus_init(int, char *); extern void schizo_plus_init(struct device_node *, const char *);
extern void tomatillo_init(int, char *); extern void tomatillo_init(struct device_node *, const char *);
extern void sun4v_pci_init(int, char *); extern void sun4v_pci_init(struct device_node *, const char *);
static struct { static struct {
char *model_name; char *model_name;
void (*init)(int, char *); void (*init)(struct device_node *, const char *);
} pci_controller_table[] __initdata = { } pci_controller_table[] __initdata = {
{ "SUNW,sabre", sabre_init }, { "SUNW,sabre", sabre_init },
{ "pci108e,a000", sabre_init }, { "pci108e,a000", sabre_init },
...@@ -204,7 +205,7 @@ static struct { ...@@ -204,7 +205,7 @@ static struct {
#define PCI_NUM_CONTROLLER_TYPES (sizeof(pci_controller_table) / \ #define PCI_NUM_CONTROLLER_TYPES (sizeof(pci_controller_table) / \
sizeof(pci_controller_table[0])) sizeof(pci_controller_table[0]))
static int __init pci_controller_init(char *model_name, int namelen, int node) static int __init pci_controller_init(const char *model_name, int namelen, struct device_node *dp)
{ {
int i; int i;
...@@ -212,18 +213,15 @@ static int __init pci_controller_init(char *model_name, int namelen, int node) ...@@ -212,18 +213,15 @@ static int __init pci_controller_init(char *model_name, int namelen, int node)
if (!strncmp(model_name, if (!strncmp(model_name,
pci_controller_table[i].model_name, pci_controller_table[i].model_name,
namelen)) { namelen)) {
pci_controller_table[i].init(node, model_name); pci_controller_table[i].init(dp, model_name);
return 1; return 1;
} }
} }
printk("PCI: Warning unknown controller, model name [%s]\n",
model_name);
printk("PCI: Ignoring controller...\n");
return 0; return 0;
} }
static int __init pci_is_controller(char *model_name, int namelen, int node) static int __init pci_is_controller(const char *model_name, int namelen, struct device_node *dp)
{ {
int i; int i;
...@@ -237,36 +235,35 @@ static int __init pci_is_controller(char *model_name, int namelen, int node) ...@@ -237,36 +235,35 @@ static int __init pci_is_controller(char *model_name, int namelen, int node)
return 0; return 0;
} }
static int __init pci_controller_scan(int (*handler)(char *, int, int)) static int __init pci_controller_scan(int (*handler)(const char *, int, struct device_node *))
{ {
char namebuf[64]; struct device_node *dp;
int node;
int count = 0; int count = 0;
node = prom_getchild(prom_root_node); for_each_node_by_name(dp, "pci") {
while ((node = prom_searchsiblings(node, "pci")) != 0) { struct property *prop;
int len; int len;
if ((len = prom_getproperty(node, "model", namebuf, sizeof(namebuf))) > 0 || prop = of_find_property(dp, "model", &len);
(len = prom_getproperty(node, "compatible", namebuf, sizeof(namebuf))) > 0) { if (!prop)
prop = of_find_property(dp, "compatible", &len);
if (prop) {
const char *model = prop->value;
int item_len = 0; int item_len = 0;
/* Our value may be a multi-valued string in the /* Our value may be a multi-valued string in the
* case of some compatible properties. For sanity, * case of some compatible properties. For sanity,
* only try the first one. */ * only try the first one.
*/
while (namebuf[item_len] && len) { while (model[item_len] && len) {
len--; len--;
item_len++; item_len++;
} }
if (handler(namebuf, item_len, node)) if (handler(model, item_len, dp))
count++; count++;
} }
node = prom_getsibling(node);
if (!node)
break;
} }
return count; return count;
...@@ -409,8 +406,14 @@ void pcibios_bus_to_resource(struct pci_dev *pdev, struct resource *res, ...@@ -409,8 +406,14 @@ void pcibios_bus_to_resource(struct pci_dev *pdev, struct resource *res,
} }
EXPORT_SYMBOL(pcibios_bus_to_resource); EXPORT_SYMBOL(pcibios_bus_to_resource);
extern int pci_irq_verbose;
char * __init pcibios_setup(char *str) char * __init pcibios_setup(char *str)
{ {
if (!strcmp(str, "irq_verbose")) {
pci_irq_verbose = 1;
return NULL;
}
return str; return str;
} }
......
This diff is collapsed.
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include <linux/types.h> #include <linux/types.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/prom.h>
extern struct pci_controller_info *pci_controller_root; extern struct pci_controller_info *pci_controller_root;
...@@ -19,7 +20,7 @@ extern int pci_num_controllers; ...@@ -19,7 +20,7 @@ extern int pci_num_controllers;
extern void pci_fixup_host_bridge_self(struct pci_bus *pbus); extern void pci_fixup_host_bridge_self(struct pci_bus *pbus);
extern void pci_fill_in_pbm_cookies(struct pci_bus *pbus, extern void pci_fill_in_pbm_cookies(struct pci_bus *pbus,
struct pci_pbm_info *pbm, struct pci_pbm_info *pbm,
int prom_node); struct device_node *prom_node);
extern void pci_record_assignments(struct pci_pbm_info *pbm, extern void pci_record_assignments(struct pci_pbm_info *pbm,
struct pci_bus *pbus); struct pci_bus *pbus);
extern void pci_assign_unassigned(struct pci_pbm_info *pbm, extern void pci_assign_unassigned(struct pci_pbm_info *pbm,
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include <asm/iommu.h> #include <asm/iommu.h>
#include <asm/irq.h> #include <asm/irq.h>
#include <asm/starfire.h> #include <asm/starfire.h>
#include <asm/prom.h>
#include "pci_impl.h" #include "pci_impl.h"
#include "iommu_common.h" #include "iommu_common.h"
...@@ -1291,11 +1292,12 @@ static void psycho_pbm_strbuf_init(struct pci_controller_info *p, ...@@ -1291,11 +1292,12 @@ static void psycho_pbm_strbuf_init(struct pci_controller_info *p,
#define PSYCHO_MEMSPACE_SIZE 0x07fffffffUL #define PSYCHO_MEMSPACE_SIZE 0x07fffffffUL
static void psycho_pbm_init(struct pci_controller_info *p, static void psycho_pbm_init(struct pci_controller_info *p,
int prom_node, int is_pbm_a) struct device_node *dp, int is_pbm_a)
{ {
unsigned int busrange[2]; unsigned int *busrange;
struct property *prop;
struct pci_pbm_info *pbm; struct pci_pbm_info *pbm;
int err; int len;
if (is_pbm_a) { if (is_pbm_a) {
pbm = &p->pbm_A; pbm = &p->pbm_A;
...@@ -1310,10 +1312,14 @@ static void psycho_pbm_init(struct pci_controller_info *p, ...@@ -1310,10 +1312,14 @@ static void psycho_pbm_init(struct pci_controller_info *p,
} }
pbm->chip_type = PBM_CHIP_TYPE_PSYCHO; pbm->chip_type = PBM_CHIP_TYPE_PSYCHO;
pbm->chip_version = pbm->chip_version = 0;
prom_getintdefault(prom_node, "version#", 0); prop = of_find_property(dp, "version#", NULL);
pbm->chip_revision = if (prop)
prom_getintdefault(prom_node, "module-revision#", 0); 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->io_space.end = pbm->io_space.start + PSYCHO_IOSPACE_SIZE; pbm->io_space.end = pbm->io_space.start + PSYCHO_IOSPACE_SIZE;
pbm->io_space.flags = IORESOURCE_IO; pbm->io_space.flags = IORESOURCE_IO;
...@@ -1322,45 +1328,36 @@ static void psycho_pbm_init(struct pci_controller_info *p, ...@@ -1322,45 +1328,36 @@ static void psycho_pbm_init(struct pci_controller_info *p,
pbm_register_toplevel_resources(p, pbm); pbm_register_toplevel_resources(p, pbm);
pbm->parent = p; pbm->parent = p;
pbm->prom_node = prom_node; pbm->prom_node = dp;
prom_getstring(prom_node, "name", pbm->name = dp->full_name;
pbm->prom_name,
sizeof(pbm->prom_name)); printk("%s: PSYCHO PCI Bus Module ver[%x:%x]\n",
pbm->name,
err = prom_getproperty(prom_node, "ranges", pbm->chip_version, pbm->chip_revision);
(char *)pbm->pbm_ranges,
sizeof(pbm->pbm_ranges)); prop = of_find_property(dp, "ranges", &len);
if (err != -1) if (prop) {
pbm->pbm_ranges = prop->value;
pbm->num_pbm_ranges = pbm->num_pbm_ranges =
(err / sizeof(struct linux_prom_pci_ranges)); (len / sizeof(struct linux_prom_pci_ranges));
else } else {
pbm->num_pbm_ranges = 0; pbm->num_pbm_ranges = 0;
}
err = prom_getproperty(prom_node, "interrupt-map", prop = of_find_property(dp, "interrupt-map", &len);
(char *)pbm->pbm_intmap, if (prop) {
sizeof(pbm->pbm_intmap)); pbm->pbm_intmap = prop->value;
if (err != -1) { pbm->num_pbm_intmap =
pbm->num_pbm_intmap = (err / sizeof(struct linux_prom_pci_intmap)); (len / sizeof(struct linux_prom_pci_intmap));
err = prom_getproperty(prom_node, "interrupt-map-mask",
(char *)&pbm->pbm_intmask, prop = of_find_property(dp, "interrupt-map-mask", NULL);
sizeof(pbm->pbm_intmask)); pbm->pbm_intmask = prop->value;
if (err == -1) {
prom_printf("PSYCHO-PBM: Fatal error, no "
"interrupt-map-mask.\n");
prom_halt();
}
} else { } else {
pbm->num_pbm_intmap = 0; pbm->num_pbm_intmap = 0;
memset(&pbm->pbm_intmask, 0, sizeof(pbm->pbm_intmask));
} }
err = prom_getproperty(prom_node, "bus-range", prop = of_find_property(dp, "bus-range", NULL);
(char *)&busrange[0], busrange = prop->value;
sizeof(busrange));
if (err == 0 || err == -1) {
prom_printf("PSYCHO-PBM: Fatal error, no bus-range.\n");
prom_halt();
}
pbm->pci_first_busno = busrange[0]; pbm->pci_first_busno = busrange[0];
pbm->pci_last_busno = busrange[1]; pbm->pci_last_busno = busrange[1];
...@@ -1369,20 +1366,24 @@ static void psycho_pbm_init(struct pci_controller_info *p, ...@@ -1369,20 +1366,24 @@ static void psycho_pbm_init(struct pci_controller_info *p,
#define PSYCHO_CONFIGSPACE 0x001000000UL #define PSYCHO_CONFIGSPACE 0x001000000UL
void psycho_init(int node, char *model_name) void psycho_init(struct device_node *dp, char *model_name)
{ {
struct linux_prom64_registers pr_regs[3]; struct linux_prom64_registers *pr_regs;
struct pci_controller_info *p; struct pci_controller_info *p;
struct pci_iommu *iommu; struct pci_iommu *iommu;
struct property *prop;
u32 upa_portid; u32 upa_portid;
int is_pbm_a, err; int is_pbm_a;
upa_portid = prom_getintdefault(node, "upa-portid", 0xff); upa_portid = 0xff;
prop = of_find_property(dp, "upa-portid", NULL);
if (prop)
upa_portid = *(u32 *) prop->value;
for(p = pci_controller_root; p; p = p->next) { for(p = pci_controller_root; p; p = p->next) {
if (p->pbm_A.portid == upa_portid) { if (p->pbm_A.portid == upa_portid) {
is_pbm_a = (p->pbm_A.prom_node == 0); is_pbm_a = (p->pbm_A.prom_node == NULL);
psycho_pbm_init(p, node, is_pbm_a); psycho_pbm_init(p, dp, is_pbm_a);
return; return;
} }
} }
...@@ -1412,23 +1413,14 @@ void psycho_init(int node, char *model_name) ...@@ -1412,23 +1413,14 @@ void psycho_init(int node, char *model_name)
p->resource_adjust = psycho_resource_adjust; p->resource_adjust = psycho_resource_adjust;
p->pci_ops = &psycho_ops; p->pci_ops = &psycho_ops;
err = prom_getproperty(node, "reg", prop = of_find_property(dp, "reg", NULL);
(char *)&pr_regs[0], pr_regs = prop->value;
sizeof(pr_regs));
if (err == 0 || err == -1) {
prom_printf("PSYCHO: Fatal error, no reg property.\n");
prom_halt();
}
p->pbm_A.controller_regs = pr_regs[2].phys_addr; p->pbm_A.controller_regs = pr_regs[2].phys_addr;
p->pbm_B.controller_regs = pr_regs[2].phys_addr; p->pbm_B.controller_regs = pr_regs[2].phys_addr;
printk("PCI: Found PSYCHO, control regs at %016lx\n",
p->pbm_A.controller_regs);
p->pbm_A.config_space = p->pbm_B.config_space = p->pbm_A.config_space = p->pbm_B.config_space =
(pr_regs[2].phys_addr + PSYCHO_CONFIGSPACE); (pr_regs[2].phys_addr + PSYCHO_CONFIGSPACE);
printk("PSYCHO: Shared PCI config space at %016lx\n",
p->pbm_A.config_space);
/* /*
* Psycho's PCI MEM space is mapped to a 2GB aligned area, so * Psycho's PCI MEM space is mapped to a 2GB aligned area, so
...@@ -1441,5 +1433,5 @@ void psycho_init(int node, char *model_name) ...@@ -1441,5 +1433,5 @@ void psycho_init(int node, char *model_name)
psycho_iommu_init(p); psycho_iommu_init(p);
is_pbm_a = ((pr_regs[0].phys_addr & 0x6000) == 0x2000); is_pbm_a = ((pr_regs[0].phys_addr & 0x6000) == 0x2000);
psycho_pbm_init(p, node, is_pbm_a); psycho_pbm_init(p, dp, is_pbm_a);
} }
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include <asm/irq.h> #include <asm/irq.h>
#include <asm/smp.h> #include <asm/smp.h>
#include <asm/oplib.h> #include <asm/oplib.h>
#include <asm/prom.h>
#include "pci_impl.h" #include "pci_impl.h"
#include "iommu_common.h" #include "iommu_common.h"
...@@ -1306,34 +1307,36 @@ static void pbm_register_toplevel_resources(struct pci_controller_info *p, ...@@ -1306,34 +1307,36 @@ static void pbm_register_toplevel_resources(struct pci_controller_info *p,
&pbm->mem_space); &pbm->mem_space);
} }
static void sabre_pbm_init(struct pci_controller_info *p, int sabre_node, u32 dma_begin) static void sabre_pbm_init(struct pci_controller_info *p, struct device_node *dp, u32 dma_begin)
{ {
struct pci_pbm_info *pbm; struct pci_pbm_info *pbm;
char namebuf[128]; struct device_node *node;
u32 busrange[2]; struct property *prop;
int node, simbas_found; u32 *busrange;
int len, simbas_found;
simbas_found = 0; simbas_found = 0;
node = prom_getchild(sabre_node); node = dp->child;
while ((node = prom_searchsiblings(node, "pci")) != 0) { while (node != NULL) {
int err; if (strcmp(node->name, "pci"))
err = prom_getproperty(node, "model", namebuf, sizeof(namebuf));
if ((err <= 0) || strncmp(namebuf, "SUNW,simba", err))
goto next_pci; goto next_pci;
err = prom_getproperty(node, "bus-range", prop = of_find_property(node, "model", NULL);
(char *)&busrange[0], sizeof(busrange)); if (!prop || strncmp(prop->value, "SUNW,simba", prop->length))
if (err == 0 || err == -1) { goto next_pci;
prom_printf("APB: Error, cannot get PCI bus-range.\n");
prom_halt();
}
simbas_found++; simbas_found++;
prop = of_find_property(node, "bus-range", NULL);
busrange = prop->value;
if (busrange[0] == 1) if (busrange[0] == 1)
pbm = &p->pbm_B; pbm = &p->pbm_B;
else else
pbm = &p->pbm_A; 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->chip_type = PBM_CHIP_TYPE_SABRE;
pbm->parent = p; pbm->parent = p;
pbm->prom_node = node; pbm->prom_node = node;
...@@ -1341,83 +1344,68 @@ static void sabre_pbm_init(struct pci_controller_info *p, int sabre_node, u32 dm ...@@ -1341,83 +1344,68 @@ static void sabre_pbm_init(struct pci_controller_info *p, int sabre_node, u32 dm
pbm->pci_first_busno = busrange[0]; pbm->pci_first_busno = busrange[0];
pbm->pci_last_busno = busrange[1]; pbm->pci_last_busno = busrange[1];
prom_getstring(node, "name", pbm->prom_name, sizeof(pbm->prom_name)); prop = of_find_property(node, "ranges", &len);
err = prom_getproperty(node, "ranges", if (prop) {
(char *)pbm->pbm_ranges, pbm->pbm_ranges = prop->value;
sizeof(pbm->pbm_ranges));
if (err != -1)
pbm->num_pbm_ranges = pbm->num_pbm_ranges =
(err / sizeof(struct linux_prom_pci_ranges)); (len / sizeof(struct linux_prom_pci_ranges));
else } else {
pbm->num_pbm_ranges = 0; pbm->num_pbm_ranges = 0;
}
err = prom_getproperty(node, "interrupt-map", prop = of_find_property(node, "interrupt-map", &len);
(char *)pbm->pbm_intmap, if (prop) {
sizeof(pbm->pbm_intmap)); pbm->pbm_intmap = prop->value;
if (err != -1) { pbm->num_pbm_intmap =
pbm->num_pbm_intmap = (err / sizeof(struct linux_prom_pci_intmap)); (len / sizeof(struct linux_prom_pci_intmap));
err = prom_getproperty(node, "interrupt-map-mask",
(char *)&pbm->pbm_intmask, prop = of_find_property(node, "interrupt-map-mask",
sizeof(pbm->pbm_intmask)); NULL);
if (err == -1) { pbm->pbm_intmask = prop->value;
prom_printf("APB: Fatal error, no interrupt-map-mask.\n");
prom_halt();
}
} else { } else {
pbm->num_pbm_intmap = 0; pbm->num_pbm_intmap = 0;
memset(&pbm->pbm_intmask, 0, sizeof(pbm->pbm_intmask));
} }
pbm_register_toplevel_resources(p, pbm); pbm_register_toplevel_resources(p, pbm);
next_pci: next_pci:
node = prom_getsibling(node); node = node->sibling;
if (!node)
break;
} }
if (simbas_found == 0) { if (simbas_found == 0) {
int err;
/* No APBs underneath, probably this is a hummingbird /* No APBs underneath, probably this is a hummingbird
* system. * system.
*/ */
pbm = &p->pbm_A; pbm = &p->pbm_A;
pbm->parent = p; pbm->parent = p;
pbm->prom_node = sabre_node; pbm->prom_node = dp;
pbm->pci_first_busno = p->pci_first_busno; pbm->pci_first_busno = p->pci_first_busno;
pbm->pci_last_busno = p->pci_last_busno; pbm->pci_last_busno = p->pci_last_busno;
prom_getstring(sabre_node, "name", pbm->prom_name, sizeof(pbm->prom_name)); prop = of_find_property(dp, "ranges", &len);
err = prom_getproperty(sabre_node, "ranges", if (prop) {
(char *) pbm->pbm_ranges, pbm->pbm_ranges = prop->value;
sizeof(pbm->pbm_ranges));
if (err != -1)
pbm->num_pbm_ranges = pbm->num_pbm_ranges =
(err / sizeof(struct linux_prom_pci_ranges)); (len / sizeof(struct linux_prom_pci_ranges));
else } else {
pbm->num_pbm_ranges = 0; pbm->num_pbm_ranges = 0;
}
err = prom_getproperty(sabre_node, "interrupt-map", prop = of_find_property(dp, "interrupt-map", &len);
(char *) pbm->pbm_intmap, if (prop) {
sizeof(pbm->pbm_intmap)); pbm->pbm_intmap = prop->value;
pbm->num_pbm_intmap =
if (err != -1) { (len / sizeof(struct linux_prom_pci_intmap));
pbm->num_pbm_intmap = (err / sizeof(struct linux_prom_pci_intmap));
err = prom_getproperty(sabre_node, "interrupt-map-mask", prop = of_find_property(dp, "interrupt-map-mask",
(char *)&pbm->pbm_intmask, NULL);
sizeof(pbm->pbm_intmask)); pbm->pbm_intmask = prop->value;
if (err == -1) {
prom_printf("Hummingbird: Fatal error, no interrupt-map-mask.\n");
prom_halt();
}
} else { } else {
pbm->num_pbm_intmap = 0; pbm->num_pbm_intmap = 0;
memset(&pbm->pbm_intmask, 0, sizeof(pbm->pbm_intmask));
} }
pbm->name = dp->full_name;
printk("%s: SABRE PCI Bus Module\n", pbm->name);
sprintf(pbm->name, "SABRE%d PBM%c", p->index,
(pbm == &p->pbm_A ? 'A' : 'B'));
pbm->io_space.name = pbm->mem_space.name = pbm->name; pbm->io_space.name = pbm->mem_space.name = pbm->name;
/* Hack up top-level resources. */ /* Hack up top-level resources. */
...@@ -1443,14 +1431,15 @@ static void sabre_pbm_init(struct pci_controller_info *p, int sabre_node, u32 dm ...@@ -1443,14 +1431,15 @@ static void sabre_pbm_init(struct pci_controller_info *p, int sabre_node, u32 dm
} }
} }
void sabre_init(int pnode, char *model_name) void sabre_init(struct device_node *dp, char *model_name)
{ {
struct linux_prom64_registers pr_regs[2]; struct linux_prom64_registers *pr_regs;
struct pci_controller_info *p; struct pci_controller_info *p;
struct pci_iommu *iommu; struct pci_iommu *iommu;
int tsbsize, err; struct property *prop;
u32 busrange[2]; int tsbsize;
u32 vdma[2]; u32 *busrange;
u32 *vdma;
u32 upa_portid, dma_mask; u32 upa_portid, dma_mask;
u64 clear_irq; u64 clear_irq;
...@@ -1458,22 +1447,21 @@ void sabre_init(int pnode, char *model_name) ...@@ -1458,22 +1447,21 @@ void sabre_init(int pnode, char *model_name)
if (!strcmp(model_name, "pci108e,a001")) if (!strcmp(model_name, "pci108e,a001"))
hummingbird_p = 1; hummingbird_p = 1;
else if (!strcmp(model_name, "SUNW,sabre")) { else if (!strcmp(model_name, "SUNW,sabre")) {
char compat[64]; prop = of_find_property(dp, "compatible", NULL);
if (prop) {
const char *compat = prop->value;
if (prom_getproperty(pnode, "compatible", if (!strcmp(compat, "pci108e,a001"))
compat, sizeof(compat)) > 0 && hummingbird_p = 1;
!strcmp(compat, "pci108e,a001")) { }
hummingbird_p = 1; if (!hummingbird_p) {
} else { struct device_node *dp;
int cpu_node;
/* Of course, Sun has to encode things a thousand /* Of course, Sun has to encode things a thousand
* different ways, inconsistently. * different ways, inconsistently.
*/ */
cpu_find_by_instance(0, &cpu_node, NULL); cpu_find_by_instance(0, &dp, NULL);
if (prom_getproperty(cpu_node, "name", if (!strcmp(dp->name, "SUNW,UltraSPARC-IIe"))
compat, sizeof(compat)) > 0 &&
!strcmp(compat, "SUNW,UltraSPARC-IIe"))
hummingbird_p = 1; hummingbird_p = 1;
} }
} }
...@@ -1491,7 +1479,10 @@ void sabre_init(int pnode, char *model_name) ...@@ -1491,7 +1479,10 @@ void sabre_init(int pnode, char *model_name)
} }
p->pbm_A.iommu = p->pbm_B.iommu = iommu; p->pbm_A.iommu = p->pbm_B.iommu = iommu;
upa_portid = prom_getintdefault(pnode, "upa-portid", 0xff); upa_portid = 0xff;
prop = of_find_property(dp, "upa-portid", NULL);
if (prop)
upa_portid = *(u32 *) prop->value;
p->next = pci_controller_root; p->next = pci_controller_root;
pci_controller_root = p; pci_controller_root = p;
...@@ -1509,13 +1500,9 @@ void sabre_init(int pnode, char *model_name) ...@@ -1509,13 +1500,9 @@ void sabre_init(int pnode, char *model_name)
/* /*
* Map in SABRE register set and report the presence of this SABRE. * Map in SABRE register set and report the presence of this SABRE.
*/ */
err = prom_getproperty(pnode, "reg",
(char *)&pr_regs[0], sizeof(pr_regs)); prop = of_find_property(dp, "reg", NULL);
if(err == 0 || err == -1) { pr_regs = prop->value;
prom_printf("SABRE: Error, cannot get U2P registers "
"from PROM.\n");
prom_halt();
}
/* /*
* First REG in property is base of entire SABRE register space. * First REG in property is base of entire SABRE register space.
...@@ -1523,9 +1510,6 @@ void sabre_init(int pnode, char *model_name) ...@@ -1523,9 +1510,6 @@ void sabre_init(int pnode, char *model_name)
p->pbm_A.controller_regs = pr_regs[0].phys_addr; p->pbm_A.controller_regs = pr_regs[0].phys_addr;
p->pbm_B.controller_regs = pr_regs[0].phys_addr; p->pbm_B.controller_regs = pr_regs[0].phys_addr;
printk("PCI: Found SABRE, main regs at %016lx\n",
p->pbm_A.controller_regs);
/* Clear interrupts */ /* Clear interrupts */
/* PCI first */ /* PCI first */
...@@ -1544,16 +1528,9 @@ void sabre_init(int pnode, char *model_name) ...@@ -1544,16 +1528,9 @@ void sabre_init(int pnode, char *model_name)
/* Now map in PCI config space for entire SABRE. */ /* Now map in PCI config space for entire SABRE. */
p->pbm_A.config_space = p->pbm_B.config_space = p->pbm_A.config_space = p->pbm_B.config_space =
(p->pbm_A.controller_regs + SABRE_CONFIGSPACE); (p->pbm_A.controller_regs + SABRE_CONFIGSPACE);
printk("SABRE: Shared PCI config space at %016lx\n",
p->pbm_A.config_space); prop = of_find_property(dp, "virtual-dma", NULL);
vdma = prop->value;
err = prom_getproperty(pnode, "virtual-dma",
(char *)&vdma[0], sizeof(vdma));
if(err == 0 || err == -1) {
prom_printf("SABRE: Error, cannot get virtual-dma property "
"from PROM.\n");
prom_halt();
}
dma_mask = vdma[0]; dma_mask = vdma[0];
switch(vdma[1]) { switch(vdma[1]) {
...@@ -1577,21 +1554,13 @@ void sabre_init(int pnode, char *model_name) ...@@ -1577,21 +1554,13 @@ void sabre_init(int pnode, char *model_name)
sabre_iommu_init(p, tsbsize, vdma[0], dma_mask); sabre_iommu_init(p, tsbsize, vdma[0], dma_mask);
printk("SABRE: DVMA at %08x [%08x]\n", vdma[0], vdma[1]); prop = of_find_property(dp, "bus-range", NULL);
busrange = prop->value;
err = prom_getproperty(pnode, "bus-range",
(char *)&busrange[0], sizeof(busrange));
if(err == 0 || err == -1) {
prom_printf("SABRE: Error, cannot get PCI bus-range "
" from PROM.\n");
prom_halt();
}
p->pci_first_busno = busrange[0]; p->pci_first_busno = busrange[0];
p->pci_last_busno = busrange[1]; p->pci_last_busno = busrange[1];
/* /*
* Look for APB underneath. * Look for APB underneath.
*/ */
sabre_pbm_init(p, pnode, vdma[0]); sabre_pbm_init(p, dp, vdma[0]);
} }
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include <asm/irq.h> #include <asm/irq.h>
#include <asm/upa.h> #include <asm/upa.h>
#include <asm/pstate.h> #include <asm/pstate.h>
#include <asm/prom.h>
#include "pci_impl.h" #include "pci_impl.h"
#include "iommu_common.h" #include "iommu_common.h"
...@@ -1456,10 +1457,12 @@ static void __schizo_scan_bus(struct pci_controller_info *p, ...@@ -1456,10 +1457,12 @@ static void __schizo_scan_bus(struct pci_controller_info *p,
pbm_config_busmastering(&p->pbm_B); pbm_config_busmastering(&p->pbm_B);
p->pbm_B.is_66mhz_capable = p->pbm_B.is_66mhz_capable =
prom_getbool(p->pbm_B.prom_node, "66mhz-capable"); (of_find_property(p->pbm_B.prom_node, "66mhz-capable", NULL)
!= NULL);
pbm_config_busmastering(&p->pbm_A); pbm_config_busmastering(&p->pbm_A);
p->pbm_A.is_66mhz_capable = p->pbm_A.is_66mhz_capable =
prom_getbool(p->pbm_A.prom_node, "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_B);
pbm_scan_bus(p, &p->pbm_A); pbm_scan_bus(p, &p->pbm_A);
...@@ -1661,13 +1664,18 @@ static void schizo_pbm_iommu_init(struct pci_pbm_info *pbm) ...@@ -1661,13 +1664,18 @@ static void schizo_pbm_iommu_init(struct pci_pbm_info *pbm)
{ {
struct pci_iommu *iommu = pbm->iommu; struct pci_iommu *iommu = pbm->iommu;
unsigned long i, tagbase, database; unsigned long i, tagbase, database;
struct property *prop;
u32 vdma[2], dma_mask; u32 vdma[2], dma_mask;
u64 control; u64 control;
int err, tsbsize; int tsbsize;
err = prom_getproperty(pbm->prom_node, "virtual-dma", prop = of_find_property(pbm->prom_node, "virtual-dma", NULL);
(char *)&vdma[0], sizeof(vdma)); if (prop) {
if (err == 0 || err == -1) { u32 *val = prop->value;
vdma[0] = val[0];
vdma[1] = val[1];
} else {
/* No property, use default values. */ /* No property, use default values. */
vdma[0] = 0xc0000000; vdma[0] = 0xc0000000;
vdma[1] = 0x40000000; vdma[1] = 0x40000000;
...@@ -1778,6 +1786,7 @@ static void schizo_pbm_iommu_init(struct pci_pbm_info *pbm) ...@@ -1778,6 +1786,7 @@ static void schizo_pbm_iommu_init(struct pci_pbm_info *pbm)
static void schizo_pbm_hw_init(struct pci_pbm_info *pbm) static void schizo_pbm_hw_init(struct pci_pbm_info *pbm)
{ {
struct property *prop;
u64 tmp; u64 tmp;
schizo_write(pbm->pbm_regs + SCHIZO_PCI_IRQ_RETRY, 5); schizo_write(pbm->pbm_regs + SCHIZO_PCI_IRQ_RETRY, 5);
...@@ -1791,7 +1800,8 @@ static void schizo_pbm_hw_init(struct pci_pbm_info *pbm) ...@@ -1791,7 +1800,8 @@ static void schizo_pbm_hw_init(struct pci_pbm_info *pbm)
pbm->chip_version >= 0x2) pbm->chip_version >= 0x2)
tmp |= 0x3UL << SCHIZO_PCICTRL_PTO_SHIFT; tmp |= 0x3UL << SCHIZO_PCICTRL_PTO_SHIFT;
if (!prom_getbool(pbm->prom_node, "no-bus-parking")) prop = of_find_property(pbm->prom_node, "no-bus-parking", NULL);
if (!prop)
tmp |= SCHIZO_PCICTRL_PARK; tmp |= SCHIZO_PCICTRL_PARK;
else else
tmp &= ~SCHIZO_PCICTRL_PARK; tmp &= ~SCHIZO_PCICTRL_PARK;
...@@ -1831,16 +1841,17 @@ static void schizo_pbm_hw_init(struct pci_pbm_info *pbm) ...@@ -1831,16 +1841,17 @@ static void schizo_pbm_hw_init(struct pci_pbm_info *pbm)
} }
static void schizo_pbm_init(struct pci_controller_info *p, static void schizo_pbm_init(struct pci_controller_info *p,
int prom_node, u32 portid, struct device_node *dp, u32 portid,
int chip_type) int chip_type)
{ {
struct linux_prom64_registers pr_regs[4]; struct linux_prom64_registers *regs;
unsigned int busrange[2]; struct property *prop;
unsigned int *busrange;
struct pci_pbm_info *pbm; struct pci_pbm_info *pbm;
const char *chipset_name; const char *chipset_name;
u32 ino_bitmap[2]; u32 *ino_bitmap;
int is_pbm_a; int is_pbm_a;
int err; int len;
switch (chip_type) { switch (chip_type) {
case PBM_CHIP_TYPE_TOMATILLO: case PBM_CHIP_TYPE_TOMATILLO:
...@@ -1868,16 +1879,10 @@ static void schizo_pbm_init(struct pci_controller_info *p, ...@@ -1868,16 +1879,10 @@ static void schizo_pbm_init(struct pci_controller_info *p,
* 3) PBM PCI config space * 3) PBM PCI config space
* 4) Ichip regs * 4) Ichip regs
*/ */
err = prom_getproperty(prom_node, "reg", prop = of_find_property(dp, "reg", NULL);
(char *)&pr_regs[0], regs = prop->value;
sizeof(pr_regs));
if (err == 0 || err == -1) {
prom_printf("%s: Fatal error, no reg property.\n",
chipset_name);
prom_halt();
}
is_pbm_a = ((pr_regs[0].phys_addr & 0x00700000) == 0x00600000); is_pbm_a = ((regs[0].phys_addr & 0x00700000) == 0x00600000);
if (is_pbm_a) if (is_pbm_a)
pbm = &p->pbm_A; pbm = &p->pbm_A;
...@@ -1886,92 +1891,62 @@ static void schizo_pbm_init(struct pci_controller_info *p, ...@@ -1886,92 +1891,62 @@ static void schizo_pbm_init(struct pci_controller_info *p,
pbm->portid = portid; pbm->portid = portid;
pbm->parent = p; pbm->parent = p;
pbm->prom_node = prom_node; pbm->prom_node = dp;
pbm->pci_first_slot = 1; pbm->pci_first_slot = 1;
pbm->chip_type = chip_type; pbm->chip_type = chip_type;
pbm->chip_version = pbm->chip_version = 0;
prom_getintdefault(prom_node, "version#", 0); prop = of_find_property(dp, "version#", NULL);
pbm->chip_revision = if (prop)
prom_getintdefault(prom_node, "module-revision#", 0); pbm->chip_version = *(int *) prop->value;
pbm->chip_revision = 0;
pbm->pbm_regs = pr_regs[0].phys_addr; prop = of_find_property(dp, "module-revision#", NULL);
pbm->controller_regs = pr_regs[1].phys_addr - 0x10000UL; if (prop)
pbm->chip_revision = *(int *) prop->value;
pbm->pbm_regs = regs[0].phys_addr;
pbm->controller_regs = regs[1].phys_addr - 0x10000UL;
if (chip_type == PBM_CHIP_TYPE_TOMATILLO) if (chip_type == PBM_CHIP_TYPE_TOMATILLO)
pbm->sync_reg = pr_regs[3].phys_addr + 0x1a18UL; pbm->sync_reg = regs[3].phys_addr + 0x1a18UL;
sprintf(pbm->name, pbm->name = dp->full_name;
(chip_type == PBM_CHIP_TYPE_TOMATILLO ?
"TOMATILLO%d PBM%c" :
"SCHIZO%d PBM%c"),
p->index,
(pbm == &p->pbm_A ? 'A' : 'B'));
printk("%s: ver[%x:%x], portid %x, " printk("%s: %s PCI Bus Module ver[%x:%x]\n",
"cregs[%lx] pregs[%lx]\n",
pbm->name, pbm->name,
pbm->chip_version, pbm->chip_revision, (chip_type == PBM_CHIP_TYPE_TOMATILLO ?
pbm->portid, "TOMATILLO" : "SCHIZO"),
pbm->controller_regs, pbm->chip_version, pbm->chip_revision);
pbm->pbm_regs);
schizo_pbm_hw_init(pbm); schizo_pbm_hw_init(pbm);
prom_getstring(prom_node, "name", prop = of_find_property(dp, "ranges", &len);
pbm->prom_name, pbm->pbm_ranges = prop->value;
sizeof(pbm->prom_name));
err = prom_getproperty(prom_node, "ranges",
(char *) pbm->pbm_ranges,
sizeof(pbm->pbm_ranges));
if (err == 0 || err == -1) {
prom_printf("%s: Fatal error, no ranges property.\n",
pbm->name);
prom_halt();
}
pbm->num_pbm_ranges = pbm->num_pbm_ranges =
(err / sizeof(struct linux_prom_pci_ranges)); (len / sizeof(struct linux_prom_pci_ranges));
schizo_determine_mem_io_space(pbm); schizo_determine_mem_io_space(pbm);
pbm_register_toplevel_resources(p, pbm); pbm_register_toplevel_resources(p, pbm);
err = prom_getproperty(prom_node, "interrupt-map", prop = of_find_property(dp, "interrupt-map", &len);
(char *)pbm->pbm_intmap, if (prop) {
sizeof(pbm->pbm_intmap)); pbm->pbm_intmap = prop->value;
if (err != -1) { pbm->num_pbm_intmap =
pbm->num_pbm_intmap = (err / sizeof(struct linux_prom_pci_intmap)); (len / sizeof(struct linux_prom_pci_intmap));
err = prom_getproperty(prom_node, "interrupt-map-mask",
(char *)&pbm->pbm_intmask, prop = of_find_property(dp, "interrupt-map-mask", NULL);
sizeof(pbm->pbm_intmask)); pbm->pbm_intmask = prop->value;
if (err == -1) {
prom_printf("%s: Fatal error, no "
"interrupt-map-mask.\n", pbm->name);
prom_halt();
}
} else { } else {
pbm->num_pbm_intmap = 0; pbm->num_pbm_intmap = 0;
memset(&pbm->pbm_intmask, 0, sizeof(pbm->pbm_intmask));
} }
err = prom_getproperty(prom_node, "ino-bitmap", prop = of_find_property(dp, "ino-bitmap", NULL);
(char *) &ino_bitmap[0], ino_bitmap = prop->value;
sizeof(ino_bitmap));
if (err == 0 || err == -1) {
prom_printf("%s: Fatal error, no ino-bitmap.\n", pbm->name);
prom_halt();
}
pbm->ino_bitmap = (((u64)ino_bitmap[1] << 32UL) | pbm->ino_bitmap = (((u64)ino_bitmap[1] << 32UL) |
((u64)ino_bitmap[0] << 0UL)); ((u64)ino_bitmap[0] << 0UL));
err = prom_getproperty(prom_node, "bus-range", prop = of_find_property(dp, "bus-range", NULL);
(char *)&busrange[0], busrange = prop->value;
sizeof(busrange));
if (err == 0 || err == -1) {
prom_printf("%s: Fatal error, no bus-range.\n", pbm->name);
prom_halt();
}
pbm->pci_first_busno = busrange[0]; pbm->pci_first_busno = busrange[0];
pbm->pci_last_busno = busrange[1]; pbm->pci_last_busno = busrange[1];
...@@ -1989,16 +1964,20 @@ static inline int portid_compare(u32 x, u32 y, int chip_type) ...@@ -1989,16 +1964,20 @@ static inline int portid_compare(u32 x, u32 y, int chip_type)
return (x == y); return (x == y);
} }
static void __schizo_init(int node, char *model_name, int chip_type) static void __schizo_init(struct device_node *dp, char *model_name, int chip_type)
{ {
struct pci_controller_info *p; struct pci_controller_info *p;
struct pci_iommu *iommu; struct pci_iommu *iommu;
struct property *prop;
int is_pbm_a; int is_pbm_a;
u32 portid; u32 portid;
portid = prom_getintdefault(node, "portid", 0xff); portid = 0xff;
prop = of_find_property(dp, "portid", NULL);
if (prop)
portid = *(u32 *) prop->value;
for(p = pci_controller_root; p; p = p->next) { for (p = pci_controller_root; p; p = p->next) {
struct pci_pbm_info *pbm; struct pci_pbm_info *pbm;
if (p->pbm_A.prom_node && p->pbm_B.prom_node) if (p->pbm_A.prom_node && p->pbm_B.prom_node)
...@@ -2009,8 +1988,8 @@ static void __schizo_init(int node, char *model_name, int chip_type) ...@@ -2009,8 +1988,8 @@ static void __schizo_init(int node, char *model_name, int chip_type)
&p->pbm_B); &p->pbm_B);
if (portid_compare(pbm->portid, portid, chip_type)) { if (portid_compare(pbm->portid, portid, chip_type)) {
is_pbm_a = (p->pbm_A.prom_node == 0); is_pbm_a = (p->pbm_A.prom_node == NULL);
schizo_pbm_init(p, node, portid, chip_type); schizo_pbm_init(p, dp, portid, chip_type);
return; return;
} }
} }
...@@ -2051,20 +2030,20 @@ static void __schizo_init(int node, char *model_name, int chip_type) ...@@ -2051,20 +2030,20 @@ static void __schizo_init(int node, char *model_name, int chip_type)
/* Like PSYCHO we have a 2GB aligned area for memory space. */ /* Like PSYCHO we have a 2GB aligned area for memory space. */
pci_memspace_mask = 0x7fffffffUL; pci_memspace_mask = 0x7fffffffUL;
schizo_pbm_init(p, node, portid, chip_type); schizo_pbm_init(p, dp, portid, chip_type);
} }
void schizo_init(int node, char *model_name) void schizo_init(struct device_node *dp, char *model_name)
{ {
__schizo_init(node, model_name, PBM_CHIP_TYPE_SCHIZO); __schizo_init(dp, model_name, PBM_CHIP_TYPE_SCHIZO);
} }
void schizo_plus_init(int node, char *model_name) void schizo_plus_init(struct device_node *dp, char *model_name)
{ {
__schizo_init(node, model_name, PBM_CHIP_TYPE_SCHIZO_PLUS); __schizo_init(dp, model_name, PBM_CHIP_TYPE_SCHIZO_PLUS);
} }
void tomatillo_init(int node, char *model_name) void tomatillo_init(struct device_node *dp, char *model_name)
{ {
__schizo_init(node, model_name, PBM_CHIP_TYPE_TOMATILLO); __schizo_init(dp, model_name, PBM_CHIP_TYPE_TOMATILLO);
} }
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include <asm/pstate.h> #include <asm/pstate.h>
#include <asm/oplib.h> #include <asm/oplib.h>
#include <asm/hypervisor.h> #include <asm/hypervisor.h>
#include <asm/prom.h>
#include "pci_impl.h" #include "pci_impl.h"
#include "iommu_common.h" #include "iommu_common.h"
...@@ -646,35 +647,37 @@ static int pdev_htab_add(u32 devhandle, unsigned int bus, unsigned int device, u ...@@ -646,35 +647,37 @@ static int pdev_htab_add(u32 devhandle, unsigned int bus, unsigned int device, u
/* Recursively descend into the OBP device tree, rooted at toplevel_node, /* Recursively descend into the OBP device tree, rooted at toplevel_node,
* looking for a PCI device matching bus and devfn. * looking for a PCI device matching bus and devfn.
*/ */
static int obp_find(struct linux_prom_pci_registers *pregs, int toplevel_node, unsigned int bus, unsigned int devfn) static int obp_find(struct device_node *toplevel_node, unsigned int bus, unsigned int devfn)
{ {
toplevel_node = prom_getchild(toplevel_node); toplevel_node = toplevel_node->child;
while (toplevel_node != 0) { while (toplevel_node != NULL) {
int ret = obp_find(pregs, toplevel_node, bus, devfn); struct linux_prom_pci_registers *regs;
struct property *prop;
int ret;
ret = obp_find(toplevel_node, bus, devfn);
if (ret != 0) if (ret != 0)
return ret; return ret;
ret = prom_getproperty(toplevel_node, "reg", (char *) pregs, prop = of_find_property(toplevel_node, "reg", NULL);
sizeof(*pregs) * PROMREG_MAX); if (!prop)
if (ret == 0 || ret == -1)
goto next_sibling; goto next_sibling;
if (((pregs[0].phys_hi >> 16) & 0xff) == bus && regs = prop->value;
((pregs[0].phys_hi >> 8) & 0xff) == devfn) if (((regs->phys_hi >> 16) & 0xff) == bus &&
((regs->phys_hi >> 8) & 0xff) == devfn)
break; break;
next_sibling: next_sibling:
toplevel_node = prom_getsibling(toplevel_node); toplevel_node = toplevel_node->sibling;
} }
return toplevel_node; return toplevel_node != NULL;
} }
static int pdev_htab_populate(struct pci_pbm_info *pbm) static int pdev_htab_populate(struct pci_pbm_info *pbm)
{ {
struct linux_prom_pci_registers pr[PROMREG_MAX];
u32 devhandle = pbm->devhandle; u32 devhandle = pbm->devhandle;
unsigned int bus; unsigned int bus;
...@@ -685,7 +688,7 @@ static int pdev_htab_populate(struct pci_pbm_info *pbm) ...@@ -685,7 +688,7 @@ static int pdev_htab_populate(struct pci_pbm_info *pbm)
unsigned int device = PCI_SLOT(devfn); unsigned int device = PCI_SLOT(devfn);
unsigned int func = PCI_FUNC(devfn); unsigned int func = PCI_FUNC(devfn);
if (obp_find(pr, pbm->prom_node, bus, devfn)) { if (obp_find(pbm->prom_node, bus, devfn)) {
int err = pdev_htab_add(devhandle, bus, int err = pdev_htab_add(devhandle, bus,
device, func); device, func);
if (err) if (err)
...@@ -811,8 +814,7 @@ static void pbm_scan_bus(struct pci_controller_info *p, ...@@ -811,8 +814,7 @@ static void pbm_scan_bus(struct pci_controller_info *p,
pci_fixup_host_bridge_self(pbm->pci_bus); pci_fixup_host_bridge_self(pbm->pci_bus);
pbm->pci_bus->self->sysdata = cookie; pbm->pci_bus->self->sysdata = cookie;
#endif #endif
pci_fill_in_pbm_cookies(pbm->pci_bus, pbm, pci_fill_in_pbm_cookies(pbm->pci_bus, pbm, pbm->prom_node);
pbm->prom_node);
pci_record_assignments(pbm, pbm->pci_bus); pci_record_assignments(pbm, pbm->pci_bus);
pci_assign_unassigned(pbm, pbm->pci_bus); pci_assign_unassigned(pbm, pbm->pci_bus);
pci_fixup_irq(pbm, pbm->pci_bus); pci_fixup_irq(pbm, pbm->pci_bus);
...@@ -822,15 +824,18 @@ static void pbm_scan_bus(struct pci_controller_info *p, ...@@ -822,15 +824,18 @@ static void pbm_scan_bus(struct pci_controller_info *p,
static void pci_sun4v_scan_bus(struct pci_controller_info *p) static void pci_sun4v_scan_bus(struct pci_controller_info *p)
{ {
if (p->pbm_A.prom_node) { struct property *prop;
p->pbm_A.is_66mhz_capable = struct device_node *dp;
prom_getbool(p->pbm_A.prom_node, "66mhz-capable");
if ((dp = p->pbm_A.prom_node) != NULL) {
prop = of_find_property(dp, "66mhz-capable", NULL);
p->pbm_A.is_66mhz_capable = (prop != NULL);
pbm_scan_bus(p, &p->pbm_A); pbm_scan_bus(p, &p->pbm_A);
} }
if (p->pbm_B.prom_node) { if ((dp = p->pbm_B.prom_node) != NULL) {
p->pbm_B.is_66mhz_capable = prop = of_find_property(dp, "66mhz-capable", NULL);
prom_getbool(p->pbm_B.prom_node, "66mhz-capable"); p->pbm_B.is_66mhz_capable = (prop != NULL);
pbm_scan_bus(p, &p->pbm_B); pbm_scan_bus(p, &p->pbm_B);
} }
...@@ -982,8 +987,13 @@ static unsigned long probe_existing_entries(struct pci_pbm_info *pbm, ...@@ -982,8 +987,13 @@ static unsigned long probe_existing_entries(struct pci_pbm_info *pbm,
HV_PCI_TSBID(0, i), HV_PCI_TSBID(0, i),
&io_attrs, &ra); &io_attrs, &ra);
if (ret == HV_EOK) { if (ret == HV_EOK) {
cnt++; if (page_in_phys_avail(ra)) {
__set_bit(i, arena->map); pci_sun4v_iommu_demap(devhandle,
HV_PCI_TSBID(0, i), 1);
} else {
cnt++;
__set_bit(i, arena->map);
}
} }
} }
...@@ -993,13 +1003,18 @@ static unsigned long probe_existing_entries(struct pci_pbm_info *pbm, ...@@ -993,13 +1003,18 @@ static unsigned long probe_existing_entries(struct pci_pbm_info *pbm,
static void pci_sun4v_iommu_init(struct pci_pbm_info *pbm) static void pci_sun4v_iommu_init(struct pci_pbm_info *pbm)
{ {
struct pci_iommu *iommu = pbm->iommu; struct pci_iommu *iommu = pbm->iommu;
struct property *prop;
unsigned long num_tsb_entries, sz; unsigned long num_tsb_entries, sz;
u32 vdma[2], dma_mask, dma_offset; u32 vdma[2], dma_mask, dma_offset;
int err, tsbsize; int tsbsize;
prop = of_find_property(pbm->prom_node, "virtual-dma", NULL);
if (prop) {
u32 *val = prop->value;
err = prom_getproperty(pbm->prom_node, "virtual-dma", vdma[0] = val[0];
(char *)&vdma[0], sizeof(vdma)); vdma[1] = val[1];
if (err == 0 || err == -1) { } else {
/* No property, use default values. */ /* No property, use default values. */
vdma[0] = 0x80000000; vdma[0] = 0x80000000;
vdma[1] = 0x80000000; vdma[1] = 0x80000000;
...@@ -1051,34 +1066,30 @@ static void pci_sun4v_iommu_init(struct pci_pbm_info *pbm) ...@@ -1051,34 +1066,30 @@ static void pci_sun4v_iommu_init(struct pci_pbm_info *pbm)
iommu->arena.limit = num_tsb_entries; iommu->arena.limit = num_tsb_entries;
sz = probe_existing_entries(pbm, iommu); sz = probe_existing_entries(pbm, iommu);
if (sz)
printk("%s: TSB entries [%lu], existing mapings [%lu]\n", printk("%s: Imported %lu TSB entries from OBP\n",
pbm->name, num_tsb_entries, sz); pbm->name, sz);
} }
static void pci_sun4v_get_bus_range(struct pci_pbm_info *pbm) static void pci_sun4v_get_bus_range(struct pci_pbm_info *pbm)
{ {
unsigned int busrange[2]; struct property *prop;
int prom_node = pbm->prom_node; unsigned int *busrange;
int err;
prop = of_find_property(pbm->prom_node, "bus-range", NULL);
err = prom_getproperty(prom_node, "bus-range",
(char *)&busrange[0], busrange = prop->value;
sizeof(busrange));
if (err == 0 || err == -1) {
prom_printf("%s: Fatal error, no bus-range.\n", pbm->name);
prom_halt();
}
pbm->pci_first_busno = busrange[0]; pbm->pci_first_busno = busrange[0];
pbm->pci_last_busno = busrange[1]; pbm->pci_last_busno = busrange[1];
} }
static void pci_sun4v_pbm_init(struct pci_controller_info *p, int prom_node, u32 devhandle) static void pci_sun4v_pbm_init(struct pci_controller_info *p, struct device_node *dp, u32 devhandle)
{ {
struct pci_pbm_info *pbm; struct pci_pbm_info *pbm;
int err, i; struct property *prop;
int len, i;
if (devhandle & 0x40) if (devhandle & 0x40)
pbm = &p->pbm_B; pbm = &p->pbm_B;
...@@ -1086,32 +1097,19 @@ static void pci_sun4v_pbm_init(struct pci_controller_info *p, int prom_node, u32 ...@@ -1086,32 +1097,19 @@ static void pci_sun4v_pbm_init(struct pci_controller_info *p, int prom_node, u32
pbm = &p->pbm_A; pbm = &p->pbm_A;
pbm->parent = p; pbm->parent = p;
pbm->prom_node = prom_node; pbm->prom_node = dp;
pbm->pci_first_slot = 1; pbm->pci_first_slot = 1;
pbm->devhandle = devhandle; pbm->devhandle = devhandle;
sprintf(pbm->name, "SUN4V-PCI%d PBM%c", pbm->name = dp->full_name;
p->index, (pbm == &p->pbm_A ? 'A' : 'B'));
printk("%s: devhandle[%x] prom_node[%x:%x]\n", printk("%s: SUN4V PCI Bus Module\n", pbm->name);
pbm->name, pbm->devhandle,
pbm->prom_node, prom_getchild(pbm->prom_node));
prom_getstring(prom_node, "name",
pbm->prom_name, sizeof(pbm->prom_name));
err = prom_getproperty(prom_node, "ranges",
(char *) pbm->pbm_ranges,
sizeof(pbm->pbm_ranges));
if (err == 0 || err == -1) {
prom_printf("%s: Fatal error, no ranges property.\n",
pbm->name);
prom_halt();
}
prop = of_find_property(dp, "ranges", &len);
pbm->pbm_ranges = prop->value;
pbm->num_pbm_ranges = pbm->num_pbm_ranges =
(err / sizeof(struct linux_prom_pci_ranges)); (len / sizeof(struct linux_prom_pci_ranges));
/* Mask out the top 8 bits of the ranges, leaving the real /* Mask out the top 8 bits of the ranges, leaving the real
* physical address. * physical address.
...@@ -1122,24 +1120,13 @@ static void pci_sun4v_pbm_init(struct pci_controller_info *p, int prom_node, u32 ...@@ -1122,24 +1120,13 @@ static void pci_sun4v_pbm_init(struct pci_controller_info *p, int prom_node, u32
pci_sun4v_determine_mem_io_space(pbm); pci_sun4v_determine_mem_io_space(pbm);
pbm_register_toplevel_resources(p, pbm); pbm_register_toplevel_resources(p, pbm);
err = prom_getproperty(prom_node, "interrupt-map", prop = of_find_property(dp, "interrupt-map", &len);
(char *)pbm->pbm_intmap, pbm->pbm_intmap = prop->value;
sizeof(pbm->pbm_intmap)); pbm->num_pbm_intmap =
if (err == 0 || err == -1) { (len / sizeof(struct linux_prom_pci_intmap));
prom_printf("%s: Fatal error, no interrupt-map property.\n",
pbm->name);
prom_halt();
}
pbm->num_pbm_intmap = (err / sizeof(struct linux_prom_pci_intmap)); prop = of_find_property(dp, "interrupt-map-mask", NULL);
err = prom_getproperty(prom_node, "interrupt-map-mask", pbm->pbm_intmask = prop->value;
(char *)&pbm->pbm_intmask,
sizeof(pbm->pbm_intmask));
if (err == 0 || err == -1) {
prom_printf("%s: Fatal error, no interrupt-map-mask.\n",
pbm->name);
prom_halt();
}
pci_sun4v_get_bus_range(pbm); pci_sun4v_get_bus_range(pbm);
pci_sun4v_iommu_init(pbm); pci_sun4v_iommu_init(pbm);
...@@ -1147,16 +1134,19 @@ static void pci_sun4v_pbm_init(struct pci_controller_info *p, int prom_node, u32 ...@@ -1147,16 +1134,19 @@ static void pci_sun4v_pbm_init(struct pci_controller_info *p, int prom_node, u32
pdev_htab_populate(pbm); pdev_htab_populate(pbm);
} }
void sun4v_pci_init(int node, char *model_name) void sun4v_pci_init(struct device_node *dp, char *model_name)
{ {
struct pci_controller_info *p; struct pci_controller_info *p;
struct pci_iommu *iommu; struct pci_iommu *iommu;
struct linux_prom64_registers regs; struct property *prop;
struct linux_prom64_registers *regs;
u32 devhandle; u32 devhandle;
int i; int i;
prom_getproperty(node, "reg", (char *)&regs, sizeof(regs)); prop = of_find_property(dp, "reg", NULL);
devhandle = (regs.phys_addr >> 32UL) & 0x0fffffff; regs = prop->value;
devhandle = (regs->phys_addr >> 32UL) & 0x0fffffff;
for (p = pci_controller_root; p; p = p->next) { for (p = pci_controller_root; p; p = p->next) {
struct pci_pbm_info *pbm; struct pci_pbm_info *pbm;
...@@ -1169,7 +1159,7 @@ void sun4v_pci_init(int node, char *model_name) ...@@ -1169,7 +1159,7 @@ void sun4v_pci_init(int node, char *model_name)
&p->pbm_B); &p->pbm_B);
if (pbm->devhandle == (devhandle ^ 0x40)) { if (pbm->devhandle == (devhandle ^ 0x40)) {
pci_sun4v_pbm_init(p, node, devhandle); pci_sun4v_pbm_init(p, dp, devhandle);
return; return;
} }
} }
...@@ -1220,7 +1210,7 @@ void sun4v_pci_init(int node, char *model_name) ...@@ -1220,7 +1210,7 @@ void sun4v_pci_init(int node, char *model_name)
*/ */
pci_memspace_mask = 0x7fffffffUL; pci_memspace_mask = 0x7fffffffUL;
pci_sun4v_pbm_init(p, node, devhandle); pci_sun4v_pbm_init(p, dp, devhandle);
return; return;
fatal_memory_error: fatal_memory_error:
......
...@@ -105,76 +105,25 @@ static int powerd(void *__unused) ...@@ -105,76 +105,25 @@ static int powerd(void *__unused)
return 0; return 0;
} }
static int __init has_button_interrupt(unsigned int irq, int prom_node) static int __init has_button_interrupt(unsigned int irq, struct device_node *dp)
{ {
if (irq == PCI_IRQ_NONE) if (irq == PCI_IRQ_NONE)
return 0; return 0;
if (!prom_node_has_property(prom_node, "button")) if (!of_find_property(dp, "button", NULL))
return 0; return 0;
return 1; return 1;
} }
static int __init power_probe_ebus(struct resource **resp, unsigned int *irq_p, int *prom_node_p) static void __devinit power_probe_common(struct of_device *dev, struct resource *res, unsigned int irq)
{ {
struct linux_ebus *ebus;
struct linux_ebus_device *edev;
for_each_ebus(ebus) {
for_each_ebusdev(edev, ebus) {
if (!strcmp(edev->prom_name, "power")) {
*resp = &edev->resource[0];
*irq_p = edev->irqs[0];
*prom_node_p = edev->prom_node;
return 0;
}
}
}
return -ENODEV;
}
static int __init power_probe_isa(struct resource **resp, unsigned int *irq_p, int *prom_node_p)
{
struct sparc_isa_bridge *isa_bus;
struct sparc_isa_device *isa_dev;
for_each_isa(isa_bus) {
for_each_isadev(isa_dev, isa_bus) {
if (!strcmp(isa_dev->prom_name, "power")) {
*resp = &isa_dev->resource;
*irq_p = isa_dev->irq;
*prom_node_p = isa_dev->prom_node;
return 0;
}
}
}
return -ENODEV;
}
void __init power_init(void)
{
struct resource *res = NULL;
unsigned int irq;
int prom_node;
static int invoked;
if (invoked)
return;
invoked = 1;
if (!power_probe_ebus(&res, &irq, &prom_node))
goto found;
if (!power_probe_isa(&res, &irq, &prom_node))
goto found;
return;
found:
power_reg = ioremap(res->start, 0x4); power_reg = ioremap(res->start, 0x4);
printk("power: Control reg at %p ... ", power_reg); printk("power: Control reg at %p ... ", power_reg);
poweroff_method = machine_halt; /* able to use the standard halt */ poweroff_method = machine_halt; /* able to use the standard halt */
if (has_button_interrupt(irq, prom_node)) {
if (has_button_interrupt(irq, dev->node)) {
if (kernel_thread(powerd, NULL, CLONE_FS) < 0) { if (kernel_thread(powerd, NULL, CLONE_FS) < 0) {
printk("Failed to start power daemon.\n"); printk("Failed to start power daemon.\n");
return; return;
...@@ -188,4 +137,52 @@ void __init power_init(void) ...@@ -188,4 +137,52 @@ void __init power_init(void)
printk("not using powerd.\n"); printk("not using powerd.\n");
} }
} }
static struct of_device_id power_match[] = {
{
.name = "power",
},
{},
};
static int __devinit ebus_power_probe(struct of_device *dev, const struct of_device_id *match)
{
struct linux_ebus_device *edev = to_ebus_device(&dev->dev);
struct resource *res = &edev->resource[0];
unsigned int irq = edev->irqs[0];
power_probe_common(dev, res,irq);
return 0;
}
static struct of_platform_driver ebus_power_driver = {
.name = "power",
.match_table = power_match,
.probe = ebus_power_probe,
};
static int __devinit isa_power_probe(struct of_device *dev, const struct of_device_id *match)
{
struct sparc_isa_device *idev = to_isa_device(&dev->dev);
struct resource *res = &idev->resource;
unsigned int irq = idev->irq;
power_probe_common(dev, res,irq);
return 0;
}
static struct of_platform_driver isa_power_driver = {
.name = "power",
.match_table = power_match,
.probe = isa_power_probe,
};
void __init power_init(void)
{
of_register_driver(&ebus_power_driver, &ebus_bus_type);
of_register_driver(&isa_power_driver, &isa_bus_type);
return;
}
#endif /* CONFIG_PCI */ #endif /* CONFIG_PCI */
This diff is collapsed.
This diff is collapsed.
...@@ -376,12 +376,12 @@ void __init setup_arch(char **cmdline_p) ...@@ -376,12 +376,12 @@ void __init setup_arch(char **cmdline_p)
} }
#endif #endif
smp_setup_cpu_possible_map();
/* Get boot processor trap_block[] setup. */ /* Get boot processor trap_block[] setup. */
init_cur_cpu_trap(current_thread_info()); init_cur_cpu_trap(current_thread_info());
paging_init(); paging_init();
smp_setup_cpu_possible_map();
} }
static int __init set_preferred_console(void) static int __init set_preferred_console(void)
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -279,12 +279,21 @@ static void kernel_mna_trap_fault(void) ...@@ -279,12 +279,21 @@ static void kernel_mna_trap_fault(void)
asmlinkage void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn) asmlinkage void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn)
{ {
static unsigned long count, last_time;
enum direction dir = decode_direction(insn); enum direction dir = decode_direction(insn);
int size = decode_access_size(insn); int size = decode_access_size(insn);
current_thread_info()->kern_una_regs = regs; current_thread_info()->kern_una_regs = regs;
current_thread_info()->kern_una_insn = insn; current_thread_info()->kern_una_insn = insn;
if (jiffies - last_time > 5 * HZ)
count = 0;
if (count < 5) {
last_time = jiffies;
count++;
printk("Kernel unaligned access at TPC[%lx]\n", regs->tpc);
}
if (!ok_for_kernel(insn) || dir == both) { if (!ok_for_kernel(insn) || dir == both) {
printk("Unsupported unaligned load/store trap for kernel " printk("Unsupported unaligned load/store trap for kernel "
"at <%016lx>.\n", regs->tpc); "at <%016lx>.\n", regs->tpc);
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment