Linux Audio

Check our new training course

Loading...
Note: File does not exist in v6.13.7.
  1/*
  2 *  linux/arch/arm/plat-versatile/platsmp.c
  3 *
  4 *  Copyright (C) 2002 ARM Ltd.
  5 *  All Rights Reserved
  6 *
  7 * This program is free software; you can redistribute it and/or modify
  8 * it under the terms of the GNU General Public License version 2 as
  9 * published by the Free Software Foundation.
 10 */
 11#include <linux/init.h>
 12#include <linux/errno.h>
 13#include <linux/delay.h>
 14#include <linux/device.h>
 15#include <linux/jiffies.h>
 16#include <linux/smp.h>
 17
 18#include <asm/cacheflush.h>
 19#include <asm/hardware/gic.h>
 20
 21/*
 22 * control for which core is the next to come out of the secondary
 23 * boot "holding pen"
 24 */
 25volatile int __cpuinitdata pen_release = -1;
 26
 27/*
 28 * Write pen_release in a way that is guaranteed to be visible to all
 29 * observers, irrespective of whether they're taking part in coherency
 30 * or not.  This is necessary for the hotplug code to work reliably.
 31 */
 32static void __cpuinit write_pen_release(int val)
 33{
 34	pen_release = val;
 35	smp_wmb();
 36	__cpuc_flush_dcache_area((void *)&pen_release, sizeof(pen_release));
 37	outer_clean_range(__pa(&pen_release), __pa(&pen_release + 1));
 38}
 39
 40static DEFINE_SPINLOCK(boot_lock);
 41
 42void __cpuinit platform_secondary_init(unsigned int cpu)
 43{
 44	/*
 45	 * if any interrupts are already enabled for the primary
 46	 * core (e.g. timer irq), then they will not have been enabled
 47	 * for us: do so
 48	 */
 49	gic_secondary_init(0);
 50
 51	/*
 52	 * let the primary processor know we're out of the
 53	 * pen, then head off into the C entry point
 54	 */
 55	write_pen_release(-1);
 56
 57	/*
 58	 * Synchronise with the boot thread.
 59	 */
 60	spin_lock(&boot_lock);
 61	spin_unlock(&boot_lock);
 62}
 63
 64int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
 65{
 66	unsigned long timeout;
 67
 68	/*
 69	 * Set synchronisation state between this boot processor
 70	 * and the secondary one
 71	 */
 72	spin_lock(&boot_lock);
 73
 74	/*
 75	 * This is really belt and braces; we hold unintended secondary
 76	 * CPUs in the holding pen until we're ready for them.  However,
 77	 * since we haven't sent them a soft interrupt, they shouldn't
 78	 * be there.
 79	 */
 80	write_pen_release(cpu);
 81
 82	/*
 83	 * Send the secondary CPU a soft interrupt, thereby causing
 84	 * the boot monitor to read the system wide flags register,
 85	 * and branch to the address found there.
 86	 */
 87	gic_raise_softirq(cpumask_of(cpu), 1);
 88
 89	timeout = jiffies + (1 * HZ);
 90	while (time_before(jiffies, timeout)) {
 91		smp_rmb();
 92		if (pen_release == -1)
 93			break;
 94
 95		udelay(10);
 96	}
 97
 98	/*
 99	 * now the secondary core is starting up let it run its
100	 * calibrations, then wait for it to finish
101	 */
102	spin_unlock(&boot_lock);
103
104	return pen_release != -1 ? -ENOSYS : 0;
105}