[SPARC64]: Use in-kernel PROM tree for EBUS and ISA.

Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
David S. Miller
2006-06-22 19:12:03 -07:00
parent de8d28b16f
commit 690c8fd31f
21 changed files with 439 additions and 449 deletions

View File

@@ -136,7 +136,7 @@ found_sdev:
for_each_ebus(ebus) {
for_each_ebusdev(edev, ebus) {
if (!strcmp(edev->prom_name, "auxio"))
if (!strcmp(edev->prom_node->name, "auxio"))
goto ebus_done;
}
}

View File

@@ -285,36 +285,38 @@ static inline void *ebus_alloc(size_t size)
static void __init ebus_ranges_init(struct linux_ebus *ebus)
{
int success;
struct linux_prom_ebus_ranges *rngs;
int len;
ebus->num_ebus_ranges = 0;
success = prom_getproperty(ebus->prom_node, "ranges",
(char *)ebus->ebus_ranges,
sizeof(ebus->ebus_ranges));
if (success != -1)
ebus->num_ebus_ranges = (success/sizeof(struct linux_prom_ebus_ranges));
rngs = of_get_property(ebus->prom_node, "ranges", &len);
if (rngs) {
memcpy(ebus->ebus_ranges, rngs, len);
ebus->num_ebus_ranges =
(len / sizeof(struct linux_prom_ebus_ranges));
}
}
static void __init ebus_intmap_init(struct linux_ebus *ebus)
{
int success;
struct linux_prom_ebus_intmap *imap;
struct linux_prom_ebus_intmask *imask;
int len;
ebus->num_ebus_intmap = 0;
success = prom_getproperty(ebus->prom_node, "interrupt-map",
(char *)ebus->ebus_intmap,
sizeof(ebus->ebus_intmap));
if (success == -1)
imap = of_get_property(ebus->prom_node, "interrupt-map", &len);
if (!imap)
return;
ebus->num_ebus_intmap = (success/sizeof(struct linux_prom_ebus_intmap));
memcpy(ebus->ebus_intmap, imap, len);
ebus->num_ebus_intmap = (len / sizeof(struct linux_prom_ebus_intmap));
success = prom_getproperty(ebus->prom_node, "interrupt-map-mask",
(char *)&ebus->ebus_intmask,
sizeof(ebus->ebus_intmask));
if (success == -1) {
prom_printf("%s: can't get interrupt-map-mask\n", __FUNCTION__);
imask = of_get_property(ebus->prom_node, "interrupt-map-mask", &len);
if (!imask) {
prom_printf("EBUS: can't get interrupt-map-mask\n");
prom_halt();
}
memcpy(&ebus->ebus_intmask, imask, sizeof(ebus->ebus_intmask));
}
int __init ebus_intmap_match(struct linux_ebus *ebus,
@@ -341,19 +343,23 @@ int __init ebus_intmap_match(struct linux_ebus *ebus,
return -1;
}
void __init fill_ebus_child(int node, struct linux_prom_registers *preg,
struct linux_ebus_child *dev, int non_standard_regs)
void __init fill_ebus_child(struct device_node *dp,
struct linux_prom_registers *preg,
struct linux_ebus_child *dev,
int non_standard_regs)
{
int regs[PROMREG_MAX];
int irqs[PROMREG_MAX];
int *regs;
int *irqs;
int i, len;
dev->prom_node = node;
prom_getstring(node, "name", dev->prom_name, sizeof(dev->prom_name));
printk(" (%s)", dev->prom_name);
dev->prom_node = dp;
printk(" (%s)", dp->name);
len = prom_getproperty(node, "reg", (void *)regs, sizeof(regs));
dev->num_addrs = len / sizeof(regs[0]);
regs = of_get_property(dp, "reg", &len);
if (!regs)
dev->num_addrs = 0;
else
dev->num_addrs = len / sizeof(regs[0]);
if (non_standard_regs) {
/* This is to handle reg properties which are not
@@ -370,21 +376,21 @@ void __init fill_ebus_child(int node, struct linux_prom_registers *preg,
int rnum = regs[i];
if (rnum >= dev->parent->num_addrs) {
prom_printf("UGH: property for %s was %d, need < %d\n",
dev->prom_name, len, dev->parent->num_addrs);
panic(__FUNCTION__);
dp->name, len, dev->parent->num_addrs);
prom_halt();
}
dev->resource[i].start = dev->parent->resource[i].start;
dev->resource[i].end = dev->parent->resource[i].end;
dev->resource[i].flags = IORESOURCE_MEM;
dev->resource[i].name = dev->prom_name;
dev->resource[i].name = dp->name;
}
}
for (i = 0; i < PROMINTR_MAX; i++)
dev->irqs[i] = PCI_IRQ_NONE;
len = prom_getproperty(node, "interrupts", (char *)&irqs, sizeof(irqs));
if ((len == -1) || (len == 0)) {
irqs = of_get_property(dp, "interrupts", &len);
if (!irqs) {
dev->num_irqs = 0;
/*
* Oh, well, some PROMs don't export interrupts
@@ -392,8 +398,8 @@ void __init fill_ebus_child(int node, struct linux_prom_registers *preg,
*
* Be smart about PS/2 keyboard and mouse.
*/
if (!strcmp(dev->parent->prom_name, "8042")) {
if (!strcmp(dev->prom_name, "kb_ps2")) {
if (!strcmp(dev->parent->prom_node->name, "8042")) {
if (!strcmp(dev->prom_node->name, "kb_ps2")) {
dev->num_irqs = 1;
dev->irqs[0] = dev->parent->irqs[0];
} else {
@@ -423,32 +429,32 @@ void __init fill_ebus_child(int node, struct linux_prom_registers *preg,
static int __init child_regs_nonstandard(struct linux_ebus_device *dev)
{
if (!strcmp(dev->prom_name, "i2c") ||
!strcmp(dev->prom_name, "SUNW,lombus"))
if (!strcmp(dev->prom_node->name, "i2c") ||
!strcmp(dev->prom_node->name, "SUNW,lombus"))
return 1;
return 0;
}
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;
int irqs[PROMINTR_MAX];
int *irqs;
int i, n, len;
dev->prom_node = node;
prom_getstring(node, "name", dev->prom_name, sizeof(dev->prom_name));
printk(" [%s", dev->prom_name);
dev->prom_node = dp;
len = prom_getproperty(node, "reg", (void *)regs, sizeof(regs));
if (len == -1) {
printk(" [%s", dp->name);
regs = of_get_property(dp, "reg", &len);
if (!regs) {
dev->num_addrs = 0;
goto probe_interrupts;
}
if (len % sizeof(struct linux_prom_registers)) {
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));
prom_halt();
}
@@ -466,7 +472,7 @@ void __init fill_ebus_device(int node, struct linux_ebus_device *dev)
dev->resource[i].end =
(dev->resource[i].start + (unsigned long)regs[i].reg_size - 1UL);
dev->resource[i].flags = IORESOURCE_MEM;
dev->resource[i].name = dev->prom_name;
dev->resource[i].name = dev->prom_node->name;
request_resource(&dev->bus->self->resource[n],
&dev->resource[i]);
}
@@ -475,8 +481,8 @@ probe_interrupts:
for (i = 0; i < PROMINTR_MAX; i++)
dev->irqs[i] = PCI_IRQ_NONE;
len = prom_getproperty(node, "interrupts", (char *)&irqs, sizeof(irqs));
if ((len == -1) || (len == 0)) {
irqs = of_get_property(dp, "interrupts", &len);
if (!irqs) {
dev->num_irqs = 0;
} else {
dev->num_irqs = len / sizeof(irqs[0]);
@@ -497,7 +503,8 @@ probe_interrupts:
}
}
if ((node = prom_getchild(node))) {
dp = dp->child;
if (dp) {
printk(" ->");
dev->children = ebus_alloc(sizeof(struct linux_ebus_child));
@@ -505,18 +512,18 @@ probe_interrupts:
child->next = NULL;
child->parent = dev;
child->bus = dev->bus;
fill_ebus_child(node, &regs[0],
child, child_regs_nonstandard(dev));
fill_ebus_child(dp, regs, child,
child_regs_nonstandard(dev));
while ((node = prom_getsibling(node)) != 0) {
while ((dp = dp->sibling) != NULL) {
child->next = ebus_alloc(sizeof(struct linux_ebus_child));
child = child->next;
child->next = NULL;
child->parent = dev;
child->bus = dev->bus;
fill_ebus_child(node, &regs[0],
child, child_regs_nonstandard(dev));
fill_ebus_child(dp, regs, child,
child_regs_nonstandard(dev));
}
}
printk("]");
@@ -543,7 +550,8 @@ void __init ebus_init(void)
struct linux_ebus *ebus;
struct pci_dev *pdev;
struct pcidev_cookie *cookie;
int nd, ebusnd, is_rio;
struct device_node *dp;
int is_rio;
int num_ebus = 0;
pdev = find_next_ebus(NULL, &is_rio);
@@ -553,20 +561,22 @@ void __init ebus_init(void)
}
cookie = pdev->sysdata;
ebusnd = cookie->prom_node->node;
dp = cookie->prom_node;
ebus_chain = ebus = ebus_alloc(sizeof(struct linux_ebus));
ebus->next = NULL;
ebus->is_rio = is_rio;
while (ebusnd) {
while (dp) {
struct device_node *child;
/* SUNW,pci-qfe uses four empty ebuses on it.
I think we should not consider them here,
as they have half of the properties this
code expects and once we do PCI hot-plug,
we'd have to tweak with the ebus_chain
in the runtime after initialization. -jj */
if (!prom_getchild (ebusnd)) {
if (!dp->child) {
pdev = find_next_ebus(pdev, &is_rio);
if (!pdev) {
if (ebus == ebus_chain) {
@@ -578,22 +588,21 @@ void __init ebus_init(void)
}
ebus->is_rio = is_rio;
cookie = pdev->sysdata;
ebusnd = cookie->prom_node->node;
dp = cookie->prom_node;
continue;
}
printk("ebus%d:", num_ebus);
prom_getstring(ebusnd, "name", ebus->prom_name, sizeof(ebus->prom_name));
ebus->index = num_ebus;
ebus->prom_node = ebusnd;
ebus->prom_node = dp;
ebus->self = pdev;
ebus->parent = pbm = cookie->pbm;
ebus_ranges_init(ebus);
ebus_intmap_init(ebus);
nd = prom_getchild(ebusnd);
if (!nd)
child = dp->child;
if (!child)
goto next_ebus;
ebus->devices = ebus_alloc(sizeof(struct linux_ebus_device));
@@ -602,16 +611,16 @@ void __init ebus_init(void)
dev->next = NULL;
dev->children = NULL;
dev->bus = ebus;
fill_ebus_device(nd, dev);
fill_ebus_device(child, dev);
while ((nd = prom_getsibling(nd)) != 0) {
while ((child = child->sibling) != NULL) {
dev->next = ebus_alloc(sizeof(struct linux_ebus_device));
dev = dev->next;
dev->next = NULL;
dev->children = NULL;
dev->bus = ebus;
fill_ebus_device(nd, dev);
fill_ebus_device(child, dev);
}
next_ebus:
@@ -622,7 +631,7 @@ void __init ebus_init(void)
break;
cookie = pdev->sysdata;
ebusnd = cookie->prom_node->node;
dp = cookie->prom_node;
ebus->next = ebus_alloc(sizeof(struct linux_ebus));
ebus = ebus->next;

View File

@@ -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)
{
if (child)
printk(" (%s)", isa_dev->prom_name);
printk(" (%s)", isa_dev->prom_node->name);
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,
struct linux_prom_registers *pregs,
int pregs_size)
static struct linux_prom_registers * __init
isa_dev_get_resource(struct sparc_isa_device *isa_dev)
{
struct linux_prom_registers *pregs;
unsigned long base, len;
int prop_len;
prop_len = prom_getproperty(isa_dev->prom_node, "reg",
(char *) pregs, pregs_size);
if (prop_len <= 0)
return;
pregs = of_get_property(isa_dev->prom_node, "reg", &prop_len);
/* Only the first one is interesting. */
len = pregs[0].reg_size;
@@ -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.end = (base + len - 1UL);
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,
&isa_dev->resource);
return pregs;
}
/* I can't believe they didn't put a real INO in the isa device
@@ -98,8 +96,8 @@ static void __init isa_dev_get_irq(struct sparc_isa_device *isa_dev,
{
int irq_prop;
irq_prop = prom_getintdefault(isa_dev->prom_node,
"interrupts", -1);
irq_prop = of_getintprop_default(isa_dev->prom_node,
"interrupts", -1);
if (irq_prop <= 0) {
goto no_irq;
} else {
@@ -141,16 +139,15 @@ no_irq:
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;
printk(" ->");
while (node != 0) {
struct linux_prom_registers regs[PROMREG_MAX];
while (dp) {
struct linux_prom_registers *regs;
struct sparc_isa_device *isa_dev;
int prop_len;
isa_dev = kmalloc(sizeof(*isa_dev), GFP_KERNEL);
if (!isa_dev) {
@@ -165,40 +162,24 @@ static void __init isa_fill_children(struct sparc_isa_device *parent_isa_dev)
parent_isa_dev->child = isa_dev;
isa_dev->bus = parent_isa_dev->bus;
isa_dev->prom_node = node;
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();
}
isa_dev->prom_node = dp;
prop_len = prom_getproperty(node, "compatible",
(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));
regs = isa_dev_get_resource(isa_dev);
isa_dev_get_irq(isa_dev, regs);
report_dev(isa_dev, 1);
node = prom_getsibling(node);
dp = dp->sibling;
}
}
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) {
struct linux_prom_registers regs[PROMREG_MAX];
while (dp) {
struct linux_prom_registers *regs;
struct sparc_isa_device *isa_dev;
int prop_len;
isa_dev = kmalloc(sizeof(*isa_dev), GFP_KERNEL);
if (!isa_dev) {
@@ -222,24 +203,9 @@ static void __init isa_fill_devices(struct sparc_isa_bridge *isa_br)
}
isa_dev->bus = isa_br;
isa_dev->prom_node = node;
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();
}
isa_dev->prom_node = dp;
prop_len = prom_getproperty(node, "compatible",
(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));
regs = isa_dev_get_resource(isa_dev);
isa_dev_get_irq(isa_dev, regs);
report_dev(isa_dev, 0);
@@ -248,10 +214,40 @@ static void __init isa_fill_devices(struct sparc_isa_bridge *isa_br)
printk("]");
node = prom_getsibling(node);
dp = dp->sibling;
}
}
static void __init get_bridge_props(struct sparc_isa_bridge *isa_br)
{
struct device_node *dp = isa_br->prom_node;
void *pval;
int len;
pval = of_get_property(dp, "ranges", &len);
if (pval) {
memcpy(isa_br->isa_ranges, pval, len);
isa_br->num_isa_ranges =
len / sizeof(struct linux_prom_isa_ranges);
} else {
isa_br->num_isa_ranges = 0;
}
pval = of_get_property(dp, "interrupt-map", &len);
if (pval) {
memcpy(isa_br->isa_intmap, pval, len);
isa_br->num_isa_intmap =
(len / sizeof(struct linux_prom_isa_intmap));
} else {
isa_br->num_isa_intmap = 0;
}
pval = of_get_property(dp, "interrupt-map-mask", &len);
if (pval)
memcpy(&isa_br->isa_intmask, pval,
sizeof(isa_br->isa_intmask));
}
void __init isa_init(void)
{
struct pci_dev *pdev;
@@ -266,7 +262,6 @@ void __init isa_init(void)
struct pcidev_cookie *pdev_cookie;
struct pci_pbm_info *pbm;
struct sparc_isa_bridge *isa_br;
int prop_len;
pdev_cookie = pdev->sysdata;
if (!pdev_cookie) {
@@ -291,34 +286,9 @@ void __init isa_init(void)
isa_br->parent = pbm;
isa_br->self = pdev;
isa_br->index = index++;
isa_br->prom_node = pdev_cookie->prom_node->node;
strncpy(isa_br->prom_name, pdev_cookie->prom_node->name,
sizeof(isa_br->prom_name));
isa_br->prom_node = pdev_cookie->prom_node;
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));
get_bridge_props(isa_br);
printk("isa%d:", isa_br->index);

View File

@@ -105,24 +105,24 @@ again:
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)
return 0;
if (!prom_node_has_property(prom_node, "button"))
if (!of_find_property(dp, "button", NULL))
return 0;
return 1;
}
static int __init power_probe_ebus(struct resource **resp, unsigned int *irq_p, int *prom_node_p)
static int __init power_probe_ebus(struct resource **resp, unsigned int *irq_p, struct device_node **prom_node_p)
{
struct linux_ebus *ebus;
struct linux_ebus_device *edev;
for_each_ebus(ebus) {
for_each_ebusdev(edev, ebus) {
if (!strcmp(edev->prom_name, "power")) {
if (!strcmp(edev->prom_node->name, "power")) {
*resp = &edev->resource[0];
*irq_p = edev->irqs[0];
*prom_node_p = edev->prom_node;
@@ -133,14 +133,14 @@ static int __init power_probe_ebus(struct resource **resp, unsigned int *irq_p,
return -ENODEV;
}
static int __init power_probe_isa(struct resource **resp, unsigned int *irq_p, int *prom_node_p)
static int __init power_probe_isa(struct resource **resp, unsigned int *irq_p, struct device_node **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")) {
if (!strcmp(isa_dev->prom_node->name, "power")) {
*resp = &isa_dev->resource;
*irq_p = isa_dev->irq;
*prom_node_p = isa_dev->prom_node;
@@ -155,17 +155,17 @@ void __init power_init(void)
{
struct resource *res = NULL;
unsigned int irq;
int prom_node;
struct device_node *dp;
static int invoked;
if (invoked)
return;
invoked = 1;
if (!power_probe_ebus(&res, &irq, &prom_node))
if (!power_probe_ebus(&res, &irq, &dp))
goto found;
if (!power_probe_isa(&res, &irq, &prom_node))
if (!power_probe_isa(&res, &irq, &dp))
goto found;
return;
@@ -174,7 +174,7 @@ found:
power_reg = ioremap(res->start, 0x4);
printk("power: Control reg at %p ... ", power_reg);
poweroff_method = machine_halt; /* able to use the standard halt */
if (has_button_interrupt(irq, prom_node)) {
if (has_button_interrupt(irq, dp)) {
if (kernel_thread(powerd, NULL, CLONE_FS) < 0) {
printk("Failed to start power daemon.\n");
return;

View File

@@ -63,6 +63,7 @@ struct device_node *of_find_node_by_path(const char *path)
return np;
}
EXPORT_SYMBOL(of_find_node_by_path);
struct device_node *of_find_node_by_phandle(phandle handle)
{

View File

@@ -756,24 +756,200 @@ retry:
return -EOPNOTSUPP;
}
void __init clock_probe(void)
static int __init clock_model_matches(char *model)
{
if (strcmp(model, "mk48t02") &&
strcmp(model, "mk48t08") &&
strcmp(model, "mk48t59") &&
strcmp(model, "m5819") &&
strcmp(model, "m5819p") &&
strcmp(model, "m5823") &&
strcmp(model, "ds1287"))
return 0;
return 1;
}
static void __init __clock_assign_common(void __iomem *addr, char *model)
{
if (model[5] == '0' && model[6] == '2') {
mstk48t02_regs = addr;
} else if(model[5] == '0' && model[6] == '8') {
mstk48t08_regs = addr;
mstk48t02_regs = mstk48t08_regs + MOSTEK_48T08_48T02;
} else {
mstk48t59_regs = addr;
mstk48t02_regs = mstk48t59_regs + MOSTEK_48T59_48T02;
}
}
static void __init clock_assign_clk_reg(struct linux_prom_registers *clk_reg,
char *model)
{
unsigned long addr;
addr = ((unsigned long) clk_reg[0].phys_addr |
(((unsigned long) clk_reg[0].which_io) << 32UL));
__clock_assign_common((void __iomem *) addr, model);
}
static int __init clock_probe_central(void)
{
struct linux_prom_registers clk_reg[2];
char model[128];
int node, busnd = -1, err;
unsigned long flags;
struct linux_central *cbus;
char model[64];
int node;
if (!central_bus)
return 0;
/* Get Central FHC's prom node. */
node = central_bus->child->prom_node;
/* Then get the first child device below it. */
node = prom_getchild(node);
while (node) {
prom_getstring(node, "model", model, sizeof(model));
if (!clock_model_matches(model))
goto next_sibling;
prom_getproperty(node, "reg", (char *)clk_reg,
sizeof(clk_reg));
apply_fhc_ranges(central_bus->child, clk_reg, 1);
apply_central_ranges(central_bus, clk_reg, 1);
clock_assign_clk_reg(clk_reg, model);
return 1;
next_sibling:
node = prom_getsibling(node);
}
return 0;
}
#ifdef CONFIG_PCI
struct linux_ebus *ebus = NULL;
struct sparc_isa_bridge *isa_br = NULL;
static void __init clock_isa_ebus_assign_regs(struct resource *res, char *model)
{
if (!strcmp(model, "ds1287") ||
!strcmp(model, "m5819") ||
!strcmp(model, "m5819p") ||
!strcmp(model, "m5823")) {
ds1287_regs = res->start;
} else {
mstk48t59_regs = (void __iomem *) res->start;
mstk48t02_regs = mstk48t59_regs + MOSTEK_48T59_48T02;
}
}
static int __init clock_probe_one_ebus_dev(struct linux_ebus_device *edev)
{
struct device_node *dp = edev->prom_node;
char *model;
model = of_get_property(dp, "model", NULL);
if (!clock_model_matches(model))
return 0;
clock_isa_ebus_assign_regs(&edev->resource[0], model);
return 1;
}
static int __init clock_probe_ebus(void)
{
struct linux_ebus *ebus;
for_each_ebus(ebus) {
struct linux_ebus_device *edev;
for_each_ebusdev(edev, ebus) {
if (clock_probe_one_ebus_dev(edev))
return 1;
}
}
return 0;
}
static int __init clock_probe_one_isa_dev(struct sparc_isa_device *idev)
{
struct device_node *dp = idev->prom_node;
char *model;
model = of_get_property(dp, "model", NULL);
if (!clock_model_matches(model))
return 0;
clock_isa_ebus_assign_regs(&idev->resource, model);
return 1;
}
static int __init clock_probe_isa(void)
{
struct sparc_isa_bridge *isa_br;
for_each_isa(isa_br) {
struct sparc_isa_device *isa_dev;
for_each_isadev(isa_dev, isa_br) {
if (clock_probe_one_isa_dev(isa_dev))
return 1;
}
}
return 0;
}
#endif /* CONFIG_PCI */
#ifdef CONFIG_SBUS
static int __init clock_probe_one_sbus_dev(struct sbus_bus *sbus, struct sbus_dev *sdev)
{
struct resource *res;
char model[64];
void __iomem *addr;
prom_getstring(sdev->prom_node, "model", model, sizeof(model));
if (!clock_model_matches(model))
return 0;
res = &sdev->resource[0];
addr = sbus_ioremap(res, 0, 0x800UL, "eeprom");
__clock_assign_common(addr, model);
return 1;
}
static int __init clock_probe_sbus(void)
{
struct sbus_bus *sbus;
for_each_sbus(sbus) {
struct sbus_dev *sdev;
for_each_sbusdev(sdev, sbus) {
if (clock_probe_one_sbus_dev(sbus, sdev))
return 1;
}
}
return 0;
}
#endif
void __init clock_probe(void)
{
static int invoked;
unsigned long flags;
if (invoked)
return;
invoked = 1;
if (this_is_starfire) {
xtime.tv_sec = starfire_get_time();
xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ);
@@ -789,182 +965,26 @@ void __init clock_probe(void)
return;
}
local_irq_save(flags);
cbus = central_bus;
if (cbus != NULL)
busnd = central_bus->child->prom_node;
/* Check FHC Central then EBUSs then ISA bridges then SBUSs.
* That way we handle the presence of multiple properly.
*
* As a special case, machines with Central must provide the
* timer chip there.
*/
if (!clock_probe_central() &&
#ifdef CONFIG_PCI
if (ebus_chain != NULL) {
ebus = ebus_chain;
if (busnd == -1)
busnd = ebus->prom_node;
}
if (isa_chain != NULL) {
isa_br = isa_chain;
if (busnd == -1)
busnd = isa_br->prom_node;
}
!clock_probe_ebus() &&
!clock_probe_isa() &&
#endif
if (sbus_root != NULL && busnd == -1)
busnd = sbus_root->prom_node;
if (busnd == -1) {
prom_printf("clock_probe: problem, cannot find bus to search.\n");
prom_halt();
#ifdef CONFIG_SBUS
!clock_probe_sbus()
#endif
) {
printk(KERN_WARNING "No clock chip found.\n");
return;
}
node = prom_getchild(busnd);
while (1) {
if (!node)
model[0] = 0;
else
prom_getstring(node, "model", model, sizeof(model));
if (strcmp(model, "mk48t02") &&
strcmp(model, "mk48t08") &&
strcmp(model, "mk48t59") &&
strcmp(model, "m5819") &&
strcmp(model, "m5819p") &&
strcmp(model, "m5823") &&
strcmp(model, "ds1287")) {
if (cbus != NULL) {
prom_printf("clock_probe: Central bus lacks timer chip.\n");
prom_halt();
}
if (node != 0)
node = prom_getsibling(node);
#ifdef CONFIG_PCI
while ((node == 0) && ebus != NULL) {
ebus = ebus->next;
if (ebus != NULL) {
busnd = ebus->prom_node;
node = prom_getchild(busnd);
}
}
while ((node == 0) && isa_br != NULL) {
isa_br = isa_br->next;
if (isa_br != NULL) {
busnd = isa_br->prom_node;
node = prom_getchild(busnd);
}
}
#endif
if (node == 0) {
prom_printf("clock_probe: Cannot find timer chip\n");
prom_halt();
}
continue;
}
err = prom_getproperty(node, "reg", (char *)clk_reg,
sizeof(clk_reg));
if(err == -1) {
prom_printf("clock_probe: Cannot get Mostek reg property\n");
prom_halt();
}
if (cbus != NULL) {
apply_fhc_ranges(central_bus->child, clk_reg, 1);
apply_central_ranges(central_bus, clk_reg, 1);
}
#ifdef CONFIG_PCI
else if (ebus != NULL) {
struct linux_ebus_device *edev;
for_each_ebusdev(edev, ebus)
if (edev->prom_node == node)
break;
if (edev == NULL) {
if (isa_chain != NULL)
goto try_isa_clock;
prom_printf("%s: Mostek not probed by EBUS\n",
__FUNCTION__);
prom_halt();
}
if (!strcmp(model, "ds1287") ||
!strcmp(model, "m5819") ||
!strcmp(model, "m5819p") ||
!strcmp(model, "m5823")) {
ds1287_regs = edev->resource[0].start;
} else {
mstk48t59_regs = (void __iomem *)
edev->resource[0].start;
mstk48t02_regs = mstk48t59_regs + MOSTEK_48T59_48T02;
}
break;
}
else if (isa_br != NULL) {
struct sparc_isa_device *isadev;
try_isa_clock:
for_each_isadev(isadev, isa_br)
if (isadev->prom_node == node)
break;
if (isadev == NULL) {
prom_printf("%s: Mostek not probed by ISA\n");
prom_halt();
}
if (!strcmp(model, "ds1287") ||
!strcmp(model, "m5819") ||
!strcmp(model, "m5819p") ||
!strcmp(model, "m5823")) {
ds1287_regs = isadev->resource.start;
} else {
mstk48t59_regs = (void __iomem *)
isadev->resource.start;
mstk48t02_regs = mstk48t59_regs + MOSTEK_48T59_48T02;
}
break;
}
#endif
else {
if (sbus_root->num_sbus_ranges) {
int nranges = sbus_root->num_sbus_ranges;
int rngc;
for (rngc = 0; rngc < nranges; rngc++)
if (clk_reg[0].which_io ==
sbus_root->sbus_ranges[rngc].ot_child_space)
break;
if (rngc == nranges) {
prom_printf("clock_probe: Cannot find ranges for "
"clock regs.\n");
prom_halt();
}
clk_reg[0].which_io =
sbus_root->sbus_ranges[rngc].ot_parent_space;
clk_reg[0].phys_addr +=
sbus_root->sbus_ranges[rngc].ot_parent_base;
}
}
if(model[5] == '0' && model[6] == '2') {
mstk48t02_regs = (void __iomem *)
(((u64)clk_reg[0].phys_addr) |
(((u64)clk_reg[0].which_io)<<32UL));
} else if(model[5] == '0' && model[6] == '8') {
mstk48t08_regs = (void __iomem *)
(((u64)clk_reg[0].phys_addr) |
(((u64)clk_reg[0].which_io)<<32UL));
mstk48t02_regs = mstk48t08_regs + MOSTEK_48T08_48T02;
} else {
mstk48t59_regs = (void __iomem *)
(((u64)clk_reg[0].phys_addr) |
(((u64)clk_reg[0].which_io)<<32UL));
mstk48t02_regs = mstk48t59_regs + MOSTEK_48T59_48T02;
}
break;
}
local_irq_save(flags);
if (mstk48t02_regs != NULL) {
/* Report a low battery voltage condition. */