From d5b26db2cfcf09f28f4839c8c3484279cd5ea5b3 Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Wed, 19 Nov 2008 09:35:56 -0600 Subject: powerpc/85xx: Add support for SMP initialization Added 85xx specifc smp_ops structure. We use ePAPR style boot release and the MPIC for IPIs at this point. Additionally added routines for secondary cpu entry and initializtion. Signed-off-by: Andy Fleming Signed-off-by: Trent Piepho Signed-off-by: Kumar Gala --- arch/powerpc/platforms/85xx/Makefile | 2 + arch/powerpc/platforms/85xx/smp.c | 104 +++++++++++++++++++++++++++++++++++ 2 files changed, 106 insertions(+) create mode 100644 arch/powerpc/platforms/85xx/smp.c (limited to 'arch/powerpc/platforms/85xx') diff --git a/arch/powerpc/platforms/85xx/Makefile b/arch/powerpc/platforms/85xx/Makefile index cb3054e1001d..f0798c09980f 100644 --- a/arch/powerpc/platforms/85xx/Makefile +++ b/arch/powerpc/platforms/85xx/Makefile @@ -1,6 +1,8 @@ # # Makefile for the PowerPC 85xx linux kernel. # +obj-$(CONFIG_SMP) += smp.o + obj-$(CONFIG_MPC8540_ADS) += mpc85xx_ads.o obj-$(CONFIG_MPC8560_ADS) += mpc85xx_ads.o obj-$(CONFIG_MPC85xx_CDS) += mpc85xx_cds.o diff --git a/arch/powerpc/platforms/85xx/smp.c b/arch/powerpc/platforms/85xx/smp.c new file mode 100644 index 000000000000..d652c713f496 --- /dev/null +++ b/arch/powerpc/platforms/85xx/smp.c @@ -0,0 +1,104 @@ +/* + * Author: Andy Fleming + * Kumar Gala + * + * Copyright 2006-2008 Freescale Semiconductor Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +extern volatile unsigned long __secondary_hold_acknowledge; +extern void __early_start(void); + +#define BOOT_ENTRY_ADDR_UPPER 0 +#define BOOT_ENTRY_ADDR_LOWER 1 +#define BOOT_ENTRY_R3_UPPER 2 +#define BOOT_ENTRY_R3_LOWER 3 +#define BOOT_ENTRY_RESV 4 +#define BOOT_ENTRY_PIR 5 +#define BOOT_ENTRY_R6_UPPER 6 +#define BOOT_ENTRY_R6_LOWER 7 +#define NUM_BOOT_ENTRY 8 +#define SIZE_BOOT_ENTRY (NUM_BOOT_ENTRY * sizeof(u32)) + +static void __init +smp_85xx_kick_cpu(int nr) +{ + unsigned long flags; + const u64 *cpu_rel_addr; + __iomem u32 *bptr_vaddr; + struct device_node *np; + int n = 0; + + WARN_ON (nr < 0 || nr >= NR_CPUS); + + pr_debug("smp_85xx_kick_cpu: kick CPU #%d\n", nr); + + local_irq_save(flags); + + np = of_get_cpu_node(nr, NULL); + cpu_rel_addr = of_get_property(np, "cpu-release-addr", NULL); + + if (cpu_rel_addr == NULL) { + printk(KERN_ERR "No cpu-release-addr for cpu %d\n", nr); + return; + } + + /* Map the spin table */ + bptr_vaddr = ioremap(*cpu_rel_addr, SIZE_BOOT_ENTRY); + + out_be32(bptr_vaddr + BOOT_ENTRY_PIR, nr); + out_be32(bptr_vaddr + BOOT_ENTRY_ADDR_LOWER, __pa(__early_start)); + + /* Wait a bit for the CPU to ack. */ + while ((__secondary_hold_acknowledge != nr) && (++n < 1000)) + mdelay(1); + + iounmap(bptr_vaddr); + + local_irq_restore(flags); + + pr_debug("waited %d msecs for CPU #%d.\n", n, nr); +} + +static void __init +smp_85xx_setup_cpu(int cpu_nr) +{ + mpic_setup_this_cpu(); + + /* Clear any pending timer interrupts */ + mtspr(SPRN_TSR, TSR_ENW | TSR_WIS | TSR_DIS | TSR_FIS); + + /* Enable decrementer interrupt */ + mtspr(SPRN_TCR, TCR_DIE); +} + +struct smp_ops_t smp_85xx_ops = { + .message_pass = smp_mpic_message_pass, + .probe = smp_mpic_probe, + .kick_cpu = smp_85xx_kick_cpu, + .setup_cpu = smp_85xx_setup_cpu, +}; + +void __init +mpc85xx_smp_init(void) +{ + smp_ops = &smp_85xx_ops; +} -- cgit v1.2.3-59-g8ed1b From 24a99596f7465274a8e65ddd29a7d9028969b9f9 Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Wed, 3 Dec 2008 09:31:35 -0600 Subject: powerpc/85xx: Fix compile warnings in mpc85xx_mds.c arch/powerpc/platforms/85xx/mpc85xx_mds.c: In function 'board_fixups': arch/powerpc/platforms/85xx/mpc85xx_mds.c:244: warning: format '%x' expects type 'unsigned int', but argument 4 has type 'resource_size_t' arch/powerpc/platforms/85xx/mpc85xx_mds.c:250: warning: format '%x' expects type 'unsigned int', but argument 4 has type 'resource_size_t' Signed-off-by: Kumar Gala --- arch/powerpc/platforms/85xx/mpc85xx_mds.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'arch/powerpc/platforms/85xx') diff --git a/arch/powerpc/platforms/85xx/mpc85xx_mds.c b/arch/powerpc/platforms/85xx/mpc85xx_mds.c index 2494c5155919..b915bf587b3d 100644 --- a/arch/powerpc/platforms/85xx/mpc85xx_mds.c +++ b/arch/powerpc/platforms/85xx/mpc85xx_mds.c @@ -241,13 +241,15 @@ static int __init board_fixups(void) mdio = of_find_compatible_node(NULL, NULL, compstrs[i]); of_address_to_resource(mdio, 0, &res); - snprintf(phy_id, BUS_ID_SIZE, "%x:%02x", res.start, 1); + snprintf(phy_id, BUS_ID_SIZE, "%llx:%02x", + (unsigned long long)res.start, 1); phy_register_fixup_for_id(phy_id, mpc8568_fixup_125_clock); phy_register_fixup_for_id(phy_id, mpc8568_mds_phy_fixups); /* Register a workaround for errata */ - snprintf(phy_id, BUS_ID_SIZE, "%x:%02x", res.start, 7); + snprintf(phy_id, BUS_ID_SIZE, "%llx:%02x", + (unsigned long long)res.start, 7); phy_register_fixup_for_id(phy_id, mpc8568_mds_phy_fixups); of_node_put(mdio); -- cgit v1.2.3-59-g8ed1b From 06be64a366885569f46a7e0e50b351266d28f5fc Mon Sep 17 00:00:00 2001 From: Haiying Wang Date: Thu, 13 Nov 2008 07:46:12 -0600 Subject: powerpc/85xx: Don't reset the MPIC for CAMP mode on MPC8572DS The flag MPIC_WANTS_RESET shouldn't be set if we are doing cooperative asymmetric MP. The second linux shouldn't reset the pic or the first one gets very confused. Signed-off-by: Haiying Wang Signed-off-by: Kumar Gala --- arch/powerpc/platforms/85xx/mpc85xx_ds.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'arch/powerpc/platforms/85xx') diff --git a/arch/powerpc/platforms/85xx/mpc85xx_ds.c b/arch/powerpc/platforms/85xx/mpc85xx_ds.c index 613bf8c2e30d..a8301c8ad537 100644 --- a/arch/powerpc/platforms/85xx/mpc85xx_ds.c +++ b/arch/powerpc/platforms/85xx/mpc85xx_ds.c @@ -63,6 +63,7 @@ void __init mpc85xx_ds_pic_init(void) struct device_node *cascade_node = NULL; int cascade_irq; #endif + unsigned long root = of_get_flat_dt_root(); np = of_find_node_by_type(NULL, "open-pic"); if (np == NULL) { @@ -76,11 +77,19 @@ void __init mpc85xx_ds_pic_init(void) return; } - mpic = mpic_alloc(np, r.start, + if (of_flat_dt_is_compatible(root, "fsl,MPC8572DS-CAMP")) { + mpic = mpic_alloc(np, r.start, + MPIC_PRIMARY | + MPIC_BIG_ENDIAN | MPIC_BROKEN_FRR_NIRQS, + 0, 256, " OpenPIC "); + } else { + mpic = mpic_alloc(np, r.start, MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN | MPIC_BROKEN_FRR_NIRQS | MPIC_SINGLE_DEST_CPU, 0, 256, " OpenPIC "); + } + BUG_ON(mpic == NULL); of_node_put(np); -- cgit v1.2.3-59-g8ed1b From aab0d375e01d8c16e7e5b9bd915dfaa0a815418f Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Thu, 4 Dec 2008 10:02:56 -0800 Subject: powerpc: struct device - replace bus_id with dev_name(), dev_set_name() Acked-by: Geoff Levand Signed-off-by: Kay Sievers Signed-off-by: Greg Kroah-Hartman Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/ibmebus.c | 2 +- arch/powerpc/kernel/of_device.c | 18 +++++++----------- arch/powerpc/kernel/vio.c | 12 ++++++------ arch/powerpc/platforms/85xx/mpc85xx_mds.c | 6 +++--- arch/powerpc/platforms/ps3/system-bus.c | 28 ++++++++++++---------------- 5 files changed, 29 insertions(+), 37 deletions(-) (limited to 'arch/powerpc/platforms/85xx') diff --git a/arch/powerpc/kernel/ibmebus.c b/arch/powerpc/kernel/ibmebus.c index 7c6537777b2c..6e3f62493659 100644 --- a/arch/powerpc/kernel/ibmebus.c +++ b/arch/powerpc/kernel/ibmebus.c @@ -47,7 +47,7 @@ #include static struct device ibmebus_bus_device = { /* fake "parent" device */ - .bus_id = "ibmebus", + .init_name = "ibmebus", }; struct bus_type ibmebus_bus_type; diff --git a/arch/powerpc/kernel/of_device.c b/arch/powerpc/kernel/of_device.c index f3c9cae01dd5..fa983a59c4ce 100644 --- a/arch/powerpc/kernel/of_device.c +++ b/arch/powerpc/kernel/of_device.c @@ -14,7 +14,6 @@ static void of_device_make_bus_id(struct of_device *dev) { static atomic_t bus_no_reg_magic; struct device_node *node = dev->node; - char *name = dev->dev.bus_id; const u32 *reg; u64 addr; int magic; @@ -27,14 +26,12 @@ static void of_device_make_bus_id(struct of_device *dev) reg = of_get_property(node, "dcr-reg", NULL); if (reg) { #ifdef CONFIG_PPC_DCR_NATIVE - snprintf(name, BUS_ID_SIZE, "d%x.%s", - *reg, node->name); + dev_set_name(&dev->dev, "d%x.%s", *reg, node->name); #else /* CONFIG_PPC_DCR_NATIVE */ addr = of_translate_dcr_address(node, *reg, NULL); if (addr != OF_BAD_ADDR) { - snprintf(name, BUS_ID_SIZE, - "D%llx.%s", (unsigned long long)addr, - node->name); + dev_set_name(&dev->dev, "D%llx.%s", + (unsigned long long)addr, node->name); return; } #endif /* !CONFIG_PPC_DCR_NATIVE */ @@ -48,9 +45,8 @@ static void of_device_make_bus_id(struct of_device *dev) if (reg) { addr = of_translate_address(node, reg); if (addr != OF_BAD_ADDR) { - snprintf(name, BUS_ID_SIZE, - "%llx.%s", (unsigned long long)addr, - node->name); + dev_set_name(&dev->dev, "%llx.%s", + (unsigned long long)addr, node->name); return; } } @@ -60,7 +56,7 @@ static void of_device_make_bus_id(struct of_device *dev) * counter (and pray...) */ magic = atomic_add_return(1, &bus_no_reg_magic); - snprintf(name, BUS_ID_SIZE, "%s.%d", node->name, magic - 1); + dev_set_name(&dev->dev, "%s.%d", node->name, magic - 1); } struct of_device *of_device_alloc(struct device_node *np, @@ -80,7 +76,7 @@ struct of_device *of_device_alloc(struct device_node *np, dev->dev.archdata.of_node = np; if (bus_id) - strlcpy(dev->dev.bus_id, bus_id, BUS_ID_SIZE); + dev_set_name(&dev->dev, bus_id); else of_device_make_bus_id(dev); diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c index a11e6bc59b30..94aa7b011b27 100644 --- a/arch/powerpc/kernel/vio.c +++ b/arch/powerpc/kernel/vio.c @@ -41,9 +41,9 @@ static struct bus_type vio_bus_type; static struct vio_dev vio_bus_device = { /* fake "parent" device */ - .name = vio_bus_device.dev.bus_id, + .name = "vio", .type = "", - .dev.bus_id = "vio", + .dev.init_name = "vio", .dev.bus = &vio_bus_type, }; @@ -1216,7 +1216,7 @@ struct vio_dev *vio_register_device_node(struct device_node *of_node) viodev->irq = irq_of_parse_and_map(of_node, 0); - snprintf(viodev->dev.bus_id, BUS_ID_SIZE, "%x", *unit_address); + dev_set_name(&viodev->dev, "%x", *unit_address); viodev->name = of_node->name; viodev->type = of_node->type; viodev->unit_address = *unit_address; @@ -1243,7 +1243,7 @@ struct vio_dev *vio_register_device_node(struct device_node *of_node) /* register with generic device framework */ if (device_register(&viodev->dev)) { printk(KERN_ERR "%s: failed to register device %s\n", - __func__, viodev->dev.bus_id); + __func__, dev_name(&viodev->dev)); /* XXX free TCE table */ kfree(viodev); return NULL; @@ -1400,13 +1400,13 @@ static struct vio_dev *vio_find_name(const char *name) struct vio_dev *vio_find_node(struct device_node *vnode) { const uint32_t *unit_address; - char kobj_name[BUS_ID_SIZE]; + char kobj_name[20]; /* construct the kobject name from the device node */ unit_address = of_get_property(vnode, "reg", NULL); if (!unit_address) return NULL; - snprintf(kobj_name, BUS_ID_SIZE, "%x", *unit_address); + snprintf(kobj_name, sizeof(kobj_name), "%x", *unit_address); return vio_find_name(kobj_name); } diff --git a/arch/powerpc/platforms/85xx/mpc85xx_mds.c b/arch/powerpc/platforms/85xx/mpc85xx_mds.c index b915bf587b3d..658a36fab3ab 100644 --- a/arch/powerpc/platforms/85xx/mpc85xx_mds.c +++ b/arch/powerpc/platforms/85xx/mpc85xx_mds.c @@ -231,7 +231,7 @@ static void __init mpc85xx_mds_setup_arch(void) static int __init board_fixups(void) { - char phy_id[BUS_ID_SIZE]; + char phy_id[20]; char *compstrs[2] = {"fsl,gianfar-mdio", "fsl,ucc-mdio"}; struct device_node *mdio; struct resource res; @@ -241,14 +241,14 @@ static int __init board_fixups(void) mdio = of_find_compatible_node(NULL, NULL, compstrs[i]); of_address_to_resource(mdio, 0, &res); - snprintf(phy_id, BUS_ID_SIZE, "%llx:%02x", + snprintf(phy_id, sizeof(phy_id), "%llx:%02x", (unsigned long long)res.start, 1); phy_register_fixup_for_id(phy_id, mpc8568_fixup_125_clock); phy_register_fixup_for_id(phy_id, mpc8568_mds_phy_fixups); /* Register a workaround for errata */ - snprintf(phy_id, BUS_ID_SIZE, "%llx:%02x", + snprintf(phy_id, sizeof(phy_id), "%llx:%02x", (unsigned long long)res.start, 7); phy_register_fixup_for_id(phy_id, mpc8568_mds_phy_fixups); diff --git a/arch/powerpc/platforms/ps3/system-bus.c b/arch/powerpc/platforms/ps3/system-bus.c index d3da1e6e73bc..ee0d22911621 100644 --- a/arch/powerpc/platforms/ps3/system-bus.c +++ b/arch/powerpc/platforms/ps3/system-bus.c @@ -31,7 +31,7 @@ #include "platform.h" static struct device ps3_system_bus = { - .bus_id = "ps3_system", + .init_name = "ps3_system", }; /* FIXME: need device usage counters! */ @@ -356,12 +356,12 @@ static int ps3_system_bus_match(struct device *_dev, if (result) pr_info("%s:%d: dev=%u.%u(%s), drv=%u.%u(%s): match\n", __func__, __LINE__, - dev->match_id, dev->match_sub_id, dev->core.bus_id, + dev->match_id, dev->match_sub_id, dev_name(&dev->core), drv->match_id, drv->match_sub_id, drv->core.name); else pr_debug("%s:%d: dev=%u.%u(%s), drv=%u.%u(%s): miss\n", __func__, __LINE__, - dev->match_id, dev->match_sub_id, dev->core.bus_id, + dev->match_id, dev->match_sub_id, dev_name(&dev->core), drv->match_id, drv->match_sub_id, drv->core.name); return result; @@ -383,9 +383,9 @@ static int ps3_system_bus_probe(struct device *_dev) result = drv->probe(dev); else pr_debug("%s:%d: %s no probe method\n", __func__, __LINE__, - dev->core.bus_id); + dev_name(&dev->core)); - pr_debug(" <- %s:%d: %s\n", __func__, __LINE__, dev->core.bus_id); + pr_debug(" <- %s:%d: %s\n", __func__, __LINE__, dev_name(&dev->core)); return result; } @@ -407,7 +407,7 @@ static int ps3_system_bus_remove(struct device *_dev) dev_dbg(&dev->core, "%s:%d %s: no remove method\n", __func__, __LINE__, drv->core.name); - pr_debug(" <- %s:%d: %s\n", __func__, __LINE__, dev->core.bus_id); + pr_debug(" <- %s:%d: %s\n", __func__, __LINE__, dev_name(&dev->core)); return result; } @@ -432,7 +432,7 @@ static void ps3_system_bus_shutdown(struct device *_dev) BUG_ON(!drv); dev_dbg(&dev->core, "%s:%d: %s -> %s\n", __func__, __LINE__, - dev->core.bus_id, drv->core.name); + dev_name(&dev->core), drv->core.name); if (drv->shutdown) drv->shutdown(dev); @@ -744,22 +744,18 @@ int ps3_system_bus_device_register(struct ps3_system_bus_device *dev) switch (dev->dev_type) { case PS3_DEVICE_TYPE_IOC0: dev->core.archdata.dma_ops = &ps3_ioc0_dma_ops; - snprintf(dev->core.bus_id, sizeof(dev->core.bus_id), - "ioc0_%02x", ++dev_ioc0_count); + dev_set_name(&dev->core, "ioc0_%02x", ++dev_ioc0_count); break; case PS3_DEVICE_TYPE_SB: dev->core.archdata.dma_ops = &ps3_sb_dma_ops; - snprintf(dev->core.bus_id, sizeof(dev->core.bus_id), - "sb_%02x", ++dev_sb_count); + dev_set_name(&dev->core, "sb_%02x", ++dev_sb_count); break; case PS3_DEVICE_TYPE_VUART: - snprintf(dev->core.bus_id, sizeof(dev->core.bus_id), - "vuart_%02x", ++dev_vuart_count); + dev_set_name(&dev->core, "vuart_%02x", ++dev_vuart_count); break; case PS3_DEVICE_TYPE_LPM: - snprintf(dev->core.bus_id, sizeof(dev->core.bus_id), - "lpm_%02x", ++dev_lpm_count); + dev_set_name(&dev->core, "lpm_%02x", ++dev_lpm_count); break; default: BUG(); @@ -768,7 +764,7 @@ int ps3_system_bus_device_register(struct ps3_system_bus_device *dev) dev->core.archdata.of_node = NULL; set_dev_node(&dev->core, 0); - pr_debug("%s:%d add %s\n", __func__, __LINE__, dev->core.bus_id); + pr_debug("%s:%d add %s\n", __func__, __LINE__, dev_name(&dev->core)); result = device_register(&dev->core); return result; -- cgit v1.2.3-59-g8ed1b