source: trunk/target/linux/cns3xxx/patches-3.1/049-cns3xxx_smp_support.patch @ 28165

Last change on this file since 28165 was 28165, checked in by kaloz, 5 years ago

[cns3xxx]: upgrade testing kernel support to 3.1

File size: 10.0 KB
  • arch/arm/mach-cns3xxx/Makefile

    a b  
    11obj-$(CONFIG_ARCH_CNS3XXX)              += core.o pm.o devices.o 
    22obj-$(CONFIG_PCI)                       += pcie.o 
    33obj-$(CONFIG_MACH_CNS3420VB)            += cns3420vb.o 
     4obj-$(CONFIG_SMP)                       += platsmp.o headsmp.o 
     5obj-$(CONFIG_HOTPLUG_CPU)               += hotplug.o 
     6obj-$(CONFIG_LOCAL_TIMERS)              += localtimer.o 
  • new file arch/arm/mach-cns3xxx/headsmp.S

    - +  
     1/* 
     2 *  linux/arch/arm/mach-cns3xxx/headsmp.S 
     3 * 
     4 *  Cloned from linux/arch/arm/plat-versatile/headsmp.S 
     5 * 
     6 *  Copyright (c) 2003 ARM Limited 
     7 *  All Rights Reserved 
     8 * 
     9 * This program is free software; you can redistribute it and/or modify 
     10 * it under the terms of the GNU General Public License version 2 as 
     11 * published by the Free Software Foundation. 
     12 */ 
     13#include <linux/linkage.h> 
     14#include <linux/init.h> 
     15 
     16        __INIT 
     17 
     18/* 
     19 * CNS3XXX specific entry point for secondary CPUs.  This provides 
     20 * a "holding pen" into which all secondary cores are held until we're 
     21 * ready for them to initialise. 
     22 */ 
     23ENTRY(cns3xxx_secondary_startup) 
     24        mrc     p15, 0, r0, c0, c0, 5 
     25        and     r0, r0, #15 
     26        adr     r4, 1f 
     27        ldmia   r4, {r5, r6} 
     28        sub     r4, r4, r5 
     29        add     r6, r6, r4 
     30pen:    ldr     r7, [r6] 
     31        cmp     r7, r0 
     32        bne     pen 
     33 
     34        /* 
     35         * we've been released from the holding pen: secondary_stack 
     36         * should now contain the SVC stack for this core 
     37         */ 
     38        b       secondary_startup 
     39 
     40        .align 
     411:      .long   . 
     42        .long   pen_release 
  • new file arch/arm/mach-cns3xxx/hotplug.c

    - +  
     1/* linux arch/arm/mach-cns3xxx/hotplug.c 
     2 * 
     3 *  Cloned from linux/arch/arm/mach-realview/hotplug.c 
     4 * 
     5 *  Copyright (C) 2002 ARM Ltd. 
     6 *  All Rights Reserved 
     7 * 
     8 * This program is free software; you can redistribute it and/or modify 
     9 * it under the terms of the GNU General Public License version 2 as 
     10 * published by the Free Software Foundation. 
     11*/ 
     12 
     13#include <linux/kernel.h> 
     14#include <linux/errno.h> 
     15#include <linux/smp.h> 
     16 
     17#include <asm/cacheflush.h> 
     18 
     19extern volatile int pen_release; 
     20 
     21static inline void cpu_enter_lowpower(void) 
     22{ 
     23        unsigned int v; 
     24 
     25        flush_cache_all(); 
     26        asm volatile( 
     27        "       mcr     p15, 0, %1, c7, c5, 0\n" 
     28        "       mcr     p15, 0, %1, c7, c10, 4\n" 
     29        /* 
     30         * Turn off coherency 
     31         */ 
     32        "       mrc     p15, 0, %0, c1, c0, 1\n" 
     33        "       bic     %0, %0, %3\n" 
     34        "       mcr     p15, 0, %0, c1, c0, 1\n" 
     35        "       mrc     p15, 0, %0, c1, c0, 0\n" 
     36        "       bic     %0, %0, %2\n" 
     37        "       mcr     p15, 0, %0, c1, c0, 0\n" 
     38          : "=&r" (v) 
     39          : "r" (0), "Ir" (CR_C), "Ir" (0x40) 
     40          : "cc"); 
     41} 
     42 
     43static inline void cpu_leave_lowpower(void) 
     44{ 
     45        unsigned int v; 
     46 
     47        asm volatile( 
     48        "mrc    p15, 0, %0, c1, c0, 0\n" 
     49        "       orr     %0, %0, %1\n" 
     50        "       mcr     p15, 0, %0, c1, c0, 0\n" 
     51        "       mrc     p15, 0, %0, c1, c0, 1\n" 
     52        "       orr     %0, %0, %2\n" 
     53        "       mcr     p15, 0, %0, c1, c0, 1\n" 
     54          : "=&r" (v) 
     55          : "Ir" (CR_C), "Ir" (0x40) 
     56          : "cc"); 
     57} 
     58 
     59static inline void platform_do_lowpower(unsigned int cpu, int *spurious) 
     60{ 
     61        /* 
     62         * there is no power-control hardware on this platform, so all 
     63         * we can do is put the core into WFI; this is safe as the calling 
     64         * code will have already disabled interrupts 
     65         */ 
     66        for (;;) { 
     67                /* 
     68                 * here's the WFI 
     69                 */ 
     70                asm(".word      0xe320f003\n" 
     71                    : 
     72                    : 
     73                    : "memory", "cc"); 
     74 
     75                if (pen_release == cpu) { 
     76                        /* 
     77                         * OK, proper wakeup, we're done 
     78                         */ 
     79                        break; 
     80                } 
     81 
     82                /* 
     83                 * Getting here, means that we have come out of WFI without 
     84                 * having been woken up - this shouldn't happen 
     85                 * 
     86                 * Just note it happening - when we're woken, we can report 
     87                 * its occurrence. 
     88                 */ 
     89                (*spurious)++; 
     90        } 
     91} 
     92 
     93int platform_cpu_kill(unsigned int cpu) 
     94{ 
     95        return 1; 
     96} 
     97 
     98/* 
     99 * platform-specific code to shutdown a CPU 
     100 * 
     101 * Called with IRQs disabled 
     102 */ 
     103void platform_cpu_die(unsigned int cpu) 
     104{ 
     105        int spurious = 0; 
     106 
     107        /* 
     108         * we're ready for shutdown now, so do it 
     109         */ 
     110        cpu_enter_lowpower(); 
     111        platform_do_lowpower(cpu, &spurious); 
     112 
     113        /* 
     114         * bring this CPU back into the world of cache 
     115         * coherency, and then restore interrupts 
     116         */ 
     117        cpu_leave_lowpower(); 
     118 
     119        if (spurious) 
     120                pr_warn("CPU%u: %u spurious wakeup calls\n", cpu, spurious); 
     121} 
     122 
     123int platform_cpu_disable(unsigned int cpu) 
     124{ 
     125        /* 
     126         * we don't allow CPU 0 to be shutdown (it is still too special 
     127         * e.g. clock tick interrupts) 
     128         */ 
     129        return cpu == 0 ? -EPERM : 0; 
     130} 
  • arch/arm/mach-cns3xxx/Kconfig

    a b menu "CNS3XXX platform type" 
    33 
    44config MACH_CNS3420VB 
    55        bool "Support for CNS3420 Validation Board" 
     6        select HAVE_ARM_SCU if SMP 
    67        select MIGHT_HAVE_PCI 
    78        help 
    89          Include support for the Cavium Networks CNS3420 MPCore Platform 
  • new file arch/arm/mach-cns3xxx/localtimer.c

    - +  
     1/* linux/arch/arm/mach-cns3xxx/localtimer.c 
     2 * 
     3 * Cloned from linux/arch/arm/mach-realview/localtimer.c 
     4 * 
     5 *  Copyright (C) 2002 ARM Ltd. 
     6 *  All Rights Reserved 
     7 * 
     8 * This program is free software; you can redistribute it and/or modify 
     9 * it under the terms of the GNU General Public License version 2 as 
     10 * published by the Free Software Foundation. 
     11*/ 
     12 
     13#include <linux/clockchips.h> 
     14 
     15#include <asm/irq.h> 
     16#include <asm/localtimer.h> 
     17 
     18/* 
     19 * Setup the local clock events for a CPU. 
     20 */ 
     21int __cpuinit local_timer_setup(struct clock_event_device *evt) 
     22{ 
     23        evt->irq = IRQ_LOCALTIMER; 
     24        twd_timer_setup(evt); 
     25        return 0; 
     26} 
  • new file arch/arm/mach-cns3xxx/platsmp.c

    - +  
     1/* linux/arch/arm/mach-cns3xxx/platsmp.c 
     2 * 
     3 * Copyright 2011 Gateworks Corporation 
     4 *                 Chris Lang <clang@gateworks.com> 
     5 * 
     6 * Cloned from linux/arch/arm/mach-vexpress/platsmp.c 
     7 * 
     8 *  Copyright (C) 2002 ARM Ltd. 
     9 *  All Rights Reserved 
     10 * 
     11 * This program is free software; you can redistribute it and/or modify 
     12 * it under the terms of the GNU General Public License version 2 as 
     13 * published by the Free Software Foundation. 
     14*/ 
     15 
     16#include <linux/init.h> 
     17#include <linux/errno.h> 
     18#include <linux/delay.h> 
     19#include <linux/device.h> 
     20#include <linux/jiffies.h> 
     21#include <linux/smp.h> 
     22#include <linux/io.h> 
     23 
     24#include <asm/cacheflush.h> 
     25#include <asm/hardware/gic.h> 
     26#include <asm/smp_scu.h> 
     27#include <asm/unified.h> 
     28 
     29#include <mach/cns3xxx.h> 
     30 
     31extern void cns3xxx_secondary_startup(void); 
     32 
     33/* 
     34 * control for which core is the next to come out of the secondary 
     35 * boot "holding pen" 
     36 */ 
     37 
     38volatile int __cpuinitdata pen_release = -1; 
     39 
     40/* 
     41 * Write pen_release in a way that is guaranteed to be visible to all 
     42 * observers, irrespective of whether they're taking part in coherency 
     43 * or not.  This is necessary for the hotplug code to work reliably. 
     44 */ 
     45static void write_pen_release(int val) 
     46{ 
     47        pen_release = val; 
     48        smp_wmb(); 
     49        __cpuc_flush_dcache_area((void *)&pen_release, sizeof(pen_release)); 
     50        outer_clean_range(__pa(&pen_release), __pa(&pen_release + 1)); 
     51} 
     52 
     53static void __iomem *scu_base_addr(void) 
     54{ 
     55        return (void __iomem *)(CNS3XXX_TC11MP_SCU_BASE_VIRT); 
     56} 
     57 
     58static DEFINE_SPINLOCK(boot_lock); 
     59 
     60void __cpuinit platform_secondary_init(unsigned int cpu) 
     61{ 
     62        /* 
     63         * if any interrupts are already enabled for the primary 
     64         * core (e.g. timer irq), then they will not have been enabled 
     65         * for us: do so 
     66         */ 
     67        gic_secondary_init(0); 
     68 
     69        /* 
     70         * let the primary processor know we're out of the 
     71         * pen, then head off into the C entry point 
     72         */ 
     73        write_pen_release(-1); 
     74 
     75        /* 
     76         * Synchronise with the boot thread. 
     77         */ 
     78        spin_lock(&boot_lock); 
     79        spin_unlock(&boot_lock); 
     80} 
     81 
     82int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) 
     83{ 
     84        unsigned long timeout; 
     85 
     86        /* 
     87         * Set synchronisation state between this boot processor 
     88         * and the secondary one 
     89         */ 
     90        spin_lock(&boot_lock); 
     91 
     92        /* 
     93         * The secondary processor is waiting to be released from 
     94         * the holding pen - release it, then wait for it to flag 
     95         * that it has been released by resetting pen_release. 
     96         * 
     97         * Note that "pen_release" is the hardware CPU ID, whereas 
     98         * "cpu" is Linux's internal ID. 
     99         */ 
     100        write_pen_release(cpu); 
     101 
     102        /* 
     103         * Send the secondary CPU a soft interrupt, thereby causing 
     104         * the boot monitor to read the system wide flags register, 
     105         * and branch to the address found there. 
     106         */ 
     107        gic_raise_softirq(cpumask_of(cpu), 1); 
     108 
     109        timeout = jiffies + (1 * HZ); 
     110        while (time_before(jiffies, timeout)) { 
     111                smp_rmb(); 
     112                if (pen_release == -1) 
     113                        break; 
     114 
     115                udelay(10); 
     116        } 
     117 
     118        /* 
     119         * now the secondary core is starting up let it run its 
     120         * calibrations, then wait for it to finish 
     121         */ 
     122        spin_unlock(&boot_lock); 
     123 
     124        return pen_release != -1 ? -ENOSYS : 0; 
     125} 
     126 
     127/* 
     128 * Initialise the CPU possible map early - this describes the CPUs 
     129 * which may be present or become present in the system. 
     130 */ 
     131 
     132void __init smp_init_cpus(void) 
     133{ 
     134        void __iomem *scu_base = scu_base_addr(); 
     135        unsigned int i, ncores; 
     136 
     137        ncores = scu_base ? scu_get_core_count(scu_base) : 1; 
     138 
     139        /* sanity check */ 
     140        if (ncores > NR_CPUS) { 
     141                printk(KERN_WARNING 
     142                       "cns3xxx: no. of cores (%d) greater than configured " 
     143                       "maximum of %d - clipping\n", 
     144                       ncores, NR_CPUS); 
     145                ncores = NR_CPUS; 
     146        } 
     147 
     148        for (i = 0; i < ncores; i++) 
     149                set_cpu_possible(i, true); 
     150 
     151        set_smp_cross_call(gic_raise_softirq); 
     152} 
     153 
     154void __init platform_smp_prepare_cpus(unsigned int max_cpus) 
     155{ 
     156        int i; 
     157 
     158        /* 
     159         * Initialise the present map, which describes the set of CPUs 
     160         * actually populated at the present time. 
     161         */ 
     162        for (i = 0; i < max_cpus; i++) 
     163                set_cpu_present(i, true); 
     164 
     165        scu_enable(scu_base_addr()); 
     166 
     167        /* 
     168         * Write the address of secondary startup into the 
     169         * system-wide flags register. The boot monitor waits 
     170         * until it receives a soft interrupt, and then the 
     171         * secondary CPU branches to this address. 
     172         */ 
     173        __raw_writel(virt_to_phys(cns3xxx_secondary_startup), 
     174                        (void __iomem *)(CNS3XXX_MISC_BASE_VIRT + 0x0600)); 
     175} 
  • arch/arm/Kconfig

    a b config SMP 
    13501350        depends on REALVIEW_EB_ARM11MP || REALVIEW_EB_A9MP || \ 
    13511351                 MACH_REALVIEW_PB11MP || MACH_REALVIEW_PBX || ARCH_OMAP4 || \ 
    13521352                 ARCH_EXYNOS4 || ARCH_TEGRA || ARCH_U8500 || ARCH_VEXPRESS_CA9X4 || \ 
    1353                  ARCH_MSM_SCORPIONMP || ARCH_SHMOBILE 
     1353                 ARCH_MSM_SCORPIONMP || ARCH_SHMOBILE || ARCH_CNS3XXX 
    13541354        select USE_GENERIC_SMP_HELPERS 
    13551355        select HAVE_ARM_SCU if !ARCH_MSM_SCORPIONMP 
    13561356        help 
Note: See TracBrowser for help on using the repository browser.