From 150f7e3cfec42a7d96ffda6f83881a7cee101c87 Mon Sep 17 00:00:00 2001 From: Jeremy Kerr Date: Mon, 23 Apr 2007 21:35:47 +0200 Subject: [POWERPC] cell: enable RTAS-based PTCAL for Cell XDR memory Enable Periodic Recalibration (PTCAL) support for Cell XDR memory, using the new ibm,cbe-start-ptcal and ibm,cbe-stop-ptcal RTAS calls. Tested on QS20 and QS21 (by Thomas Huth). It seems that SLOF has problems disabling, at least on QS20; this patch should only be used once these problems have been addressed. Signed-off-by: Jeremy Kerr Signed-off-by: Arnd Bergmann --- arch/powerpc/platforms/cell/ras.c | 160 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 160 insertions(+) (limited to 'arch/powerpc/platforms/cell/ras.c') diff --git a/arch/powerpc/platforms/cell/ras.c b/arch/powerpc/platforms/cell/ras.c index 0984c7071695..b5ebc916388b 100644 --- a/arch/powerpc/platforms/cell/ras.c +++ b/arch/powerpc/platforms/cell/ras.c @@ -3,11 +3,13 @@ #include #include #include +#include #include #include #include #include +#include #include "ras.h" #include "cbe_regs.h" @@ -82,6 +84,164 @@ static int cbe_machine_check_handler(struct pt_regs *regs) return 0; } +struct ptcal_area { + struct list_head list; + int nid; + int order; + struct page *pages; +}; + +static LIST_HEAD(ptcal_list); + +static int ptcal_start_tok, ptcal_stop_tok; + +static int __init cbe_ptcal_enable_on_node(int nid, int order) +{ + struct ptcal_area *area; + int ret = -ENOMEM; + unsigned long addr; + +#ifdef CONFIG_CRASH_DUMP + rtas_call(ptcal_stop_tok, 1, 1, NULL, nid); +#endif + + area = kmalloc(sizeof(*area), GFP_KERNEL); + if (!area) + goto out_err; + + area->nid = nid; + area->order = order; + area->pages = alloc_pages_node(area->nid, GFP_KERNEL, area->order); + + if (!area->pages) + goto out_free_area; + + addr = __pa(page_address(area->pages)); + + ret = -EIO; + if (rtas_call(ptcal_start_tok, 3, 1, NULL, area->nid, + (unsigned int)(addr >> 32), + (unsigned int)(addr & 0xffffffff))) { + printk(KERN_ERR "%s: error enabling PTCAL on node %d!\n", + __FUNCTION__, nid); + goto out_free_pages; + } + + list_add(&area->list, &ptcal_list); + + return 0; + +out_free_pages: + __free_pages(area->pages, area->order); +out_free_area: + kfree(area); +out_err: + return ret; +} + +static int __init cbe_ptcal_enable(void) +{ + const u32 *size; + struct device_node *np; + int order, found_mic = 0; + + np = of_find_node_by_path("/rtas"); + if (!np) + return -ENODEV; + + size = get_property(np, "ibm,cbe-ptcal-size", NULL); + if (!size) + return -ENODEV; + + pr_debug("%s: enabling PTCAL, size = 0x%x\n", __FUNCTION__, *size); + order = get_order(*size); + of_node_put(np); + + /* support for malta device trees, with be@/mic@ nodes */ + for_each_node_by_type(np, "mic-tm") { + cbe_ptcal_enable_on_node(of_node_to_nid(np), order); + found_mic = 1; + } + + if (found_mic) + return 0; + + /* support for older device tree - use cpu nodes */ + for_each_node_by_type(np, "cpu") { + const u32 *nid = get_property(np, "node-id", NULL); + if (!nid) { + printk(KERN_ERR "%s: node %s is missing node-id?\n", + __FUNCTION__, np->full_name); + continue; + } + cbe_ptcal_enable_on_node(*nid, order); + found_mic = 1; + } + + return found_mic ? 0 : -ENODEV; +} + +static int cbe_ptcal_disable(void) +{ + struct ptcal_area *area, *tmp; + int ret = 0; + + pr_debug("%s: disabling PTCAL\n", __FUNCTION__); + + list_for_each_entry_safe(area, tmp, &ptcal_list, list) { + /* disable ptcal on this node */ + if (rtas_call(ptcal_stop_tok, 1, 1, NULL, area->nid)) { + printk(KERN_ERR "%s: error disabling PTCAL " + "on node %d!\n", __FUNCTION__, + area->nid); + ret = -EIO; + continue; + } + + /* ensure we can access the PTCAL area */ + memset(page_address(area->pages), 0, + 1 << (area->order + PAGE_SHIFT)); + + /* clean up */ + list_del(&area->list); + __free_pages(area->pages, area->order); + kfree(area); + } + + return ret; +} + +static int cbe_ptcal_notify_reboot(struct notifier_block *nb, + unsigned long code, void *data) +{ + return cbe_ptcal_disable(); +} + +static struct notifier_block cbe_ptcal_reboot_notifier = { + .notifier_call = cbe_ptcal_notify_reboot +}; + +int __init cbe_ptcal_init(void) +{ + int ret; + ptcal_start_tok = rtas_token("ibm,cbe-start-ptcal"); + ptcal_stop_tok = rtas_token("ibm,cbe-stop-ptcal"); + + if (ptcal_start_tok == RTAS_UNKNOWN_SERVICE + || ptcal_stop_tok == RTAS_UNKNOWN_SERVICE) + return -ENODEV; + + ret = register_reboot_notifier(&cbe_ptcal_reboot_notifier); + if (ret) { + printk(KERN_ERR "Can't disable PTCAL, so not enabling\n"); + return ret; + } + + return cbe_ptcal_enable(); +} + +arch_initcall(cbe_ptcal_init); + void __init cbe_ras_init(void) { unsigned long hid0; -- cgit v1.2.3 From 12d371a69e6df96cd949af6bcb569e978e8f9d41 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Sun, 29 Apr 2007 16:29:08 +1000 Subject: [POWERPC] get_property cleanups Just another pass through arch/powerpc for old usages. Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/cell/ras.c | 4 ++-- arch/powerpc/platforms/pasemi/cpufreq.c | 11 ++++++----- arch/powerpc/platforms/pasemi/gpio_mdio.c | 6 +++--- arch/powerpc/sysdev/uic.c | 8 ++++---- 4 files changed, 15 insertions(+), 14 deletions(-) (limited to 'arch/powerpc/platforms/cell/ras.c') diff --git a/arch/powerpc/platforms/cell/ras.c b/arch/powerpc/platforms/cell/ras.c index b5ebc916388b..3961a085b432 100644 --- a/arch/powerpc/platforms/cell/ras.c +++ b/arch/powerpc/platforms/cell/ras.c @@ -149,7 +149,7 @@ static int __init cbe_ptcal_enable(void) if (!np) return -ENODEV; - size = get_property(np, "ibm,cbe-ptcal-size", NULL); + size = of_get_property(np, "ibm,cbe-ptcal-size", NULL); if (!size) return -ENODEV; @@ -168,7 +168,7 @@ static int __init cbe_ptcal_enable(void) /* support for older device tree - use cpu nodes */ for_each_node_by_type(np, "cpu") { - const u32 *nid = get_property(np, "node-id", NULL); + const u32 *nid = of_get_property(np, "node-id", NULL); if (!nid) { printk(KERN_ERR "%s: node %s is missing node-id?\n", __FUNCTION__, np->full_name); diff --git a/arch/powerpc/platforms/pasemi/cpufreq.c b/arch/powerpc/platforms/pasemi/cpufreq.c index 4dd5c512f869..2a57d6023685 100644 --- a/arch/powerpc/platforms/pasemi/cpufreq.c +++ b/arch/powerpc/platforms/pasemi/cpufreq.c @@ -134,7 +134,8 @@ void restore_astate(int cpu) static int pas_cpufreq_cpu_init(struct cpufreq_policy *policy) { - u32 *max_freq; + const u32 *max_freqp; + u32 max_freq; int i, cur_astate; struct resource res; struct device_node *cpu, *dn; @@ -175,16 +176,16 @@ static int pas_cpufreq_cpu_init(struct cpufreq_policy *policy) pr_debug("init cpufreq on CPU %d\n", policy->cpu); - max_freq = (u32*) get_property(cpu, "clock-frequency", NULL); - if (!max_freq) { + max_freqp = of_get_property(cpu, "clock-frequency", NULL); + if (!max_freqp) { err = -EINVAL; goto out_unmap_sdcpwr; } /* we need the freq in kHz */ - *max_freq /= 1000; + max_freq = *max_freqp / 1000; - pr_debug("max clock-frequency is at %u kHz\n", *max_freq); + pr_debug("max clock-frequency is at %u kHz\n", max_freq); pr_debug("initializing frequency table\n"); /* initialize frequency table */ diff --git a/arch/powerpc/platforms/pasemi/gpio_mdio.c b/arch/powerpc/platforms/pasemi/gpio_mdio.c index b1d3b6b420ae..c91a33593bb8 100644 --- a/arch/powerpc/platforms/pasemi/gpio_mdio.c +++ b/arch/powerpc/platforms/pasemi/gpio_mdio.c @@ -258,7 +258,7 @@ static int __devinit gpio_mdio_probe(struct of_device *ofdev, new_bus->write = &gpio_mdio_write, new_bus->reset = &gpio_mdio_reset, - prop = get_property(np, "reg", NULL); + prop = of_get_property(np, "reg", NULL); new_bus->id = *prop; new_bus->priv = priv; @@ -269,10 +269,10 @@ static int __devinit gpio_mdio_probe(struct of_device *ofdev, new_bus->irq[i] = irq_create_mapping(NULL, 10); - prop = get_property(np, "mdc-pin", NULL); + prop = of_get_property(np, "mdc-pin", NULL); priv->mdc_pin = *prop; - prop = get_property(np, "mdio-pin", NULL); + prop = of_get_property(np, "mdio-pin", NULL); priv->mdio_pin = *prop; new_bus->dev = dev; diff --git a/arch/powerpc/sysdev/uic.c b/arch/powerpc/sysdev/uic.c index cdbe68437afe..968fb40af9dc 100644 --- a/arch/powerpc/sysdev/uic.c +++ b/arch/powerpc/sysdev/uic.c @@ -230,7 +230,7 @@ static struct uic * __init uic_init_one(struct device_node *node) memset(uic, 0, sizeof(*uic)); spin_lock_init(&uic->lock); uic->of_node = of_node_get(node); - indexp = get_property(node, "cell-index", &len); + indexp = of_get_property(node, "cell-index", &len); if (!indexp || (len != sizeof(u32))) { printk(KERN_ERR "uic: Device node %s has missing or invalid " "cell-index property\n", node->full_name); @@ -238,7 +238,7 @@ static struct uic * __init uic_init_one(struct device_node *node) } uic->index = *indexp; - dcrreg = get_property(node, "dcr-reg", &len); + dcrreg = of_get_property(node, "dcr-reg", &len); if (!dcrreg || (len != 2*sizeof(u32))) { printk(KERN_ERR "uic: Device node %s has missing or invalid " "dcr-reg property\n", node->full_name); @@ -278,7 +278,7 @@ void __init uic_init_tree(void) np = of_find_compatible_node(NULL, NULL, "ibm,uic"); while (np) { - interrupts = get_property(np, "interrupts", NULL); + interrupts = of_get_property(np, "interrupts", NULL); if (! interrupts) break; @@ -297,7 +297,7 @@ void __init uic_init_tree(void) /* The scan again for cascaded UICs */ np = of_find_compatible_node(NULL, NULL, "ibm,uic"); while (np) { - interrupts = get_property(np, "interrupts", NULL); + interrupts = of_get_property(np, "interrupts", NULL); if (interrupts) { /* Secondary UIC */ int cascade_virq; -- cgit v1.2.3