~ubuntu-branches/ubuntu/precise/linux-lowlatency/precise

« back to all changes in this revision

Viewing changes to arch/blackfin/mach-bf561/smp.c

  • Committer: Package Import Robot
  • Author(s): Alessio Igor Bogani
  • Date: 2011-10-26 11:13:05 UTC
  • Revision ID: package-import@ubuntu.com-20111026111305-tz023xykf0i6eosh
Tags: upstream-3.2.0
ImportĀ upstreamĀ versionĀ 3.2.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright 2007-2009 Analog Devices Inc.
 
3
 *               Philippe Gerum <rpm@xenomai.org>
 
4
 *
 
5
 * Licensed under the GPL-2 or later.
 
6
 */
 
7
 
 
8
#include <linux/init.h>
 
9
#include <linux/kernel.h>
 
10
#include <linux/sched.h>
 
11
#include <linux/delay.h>
 
12
#include <asm/smp.h>
 
13
#include <asm/dma.h>
 
14
#include <asm/time.h>
 
15
 
 
16
static DEFINE_SPINLOCK(boot_lock);
 
17
 
 
18
/*
 
19
 * platform_init_cpus() - Tell the world about how many cores we
 
20
 * have. This is called while setting up the architecture support
 
21
 * (setup_arch()), so don't be too demanding here with respect to
 
22
 * available kernel services.
 
23
 */
 
24
 
 
25
void __init platform_init_cpus(void)
 
26
{
 
27
        struct cpumask mask;
 
28
 
 
29
        cpumask_set_cpu(0, &mask); /* CoreA */
 
30
        cpumask_set_cpu(1, &mask); /* CoreB */
 
31
        init_cpu_possible(&mask);
 
32
}
 
33
 
 
34
void __init platform_prepare_cpus(unsigned int max_cpus)
 
35
{
 
36
        struct cpumask mask;
 
37
 
 
38
        bfin_relocate_coreb_l1_mem();
 
39
 
 
40
        /* Both cores ought to be present on a bf561! */
 
41
        cpumask_set_cpu(0, &mask); /* CoreA */
 
42
        cpumask_set_cpu(1, &mask); /* CoreB */
 
43
        init_cpu_present(&mask);
 
44
}
 
45
 
 
46
int __init setup_profiling_timer(unsigned int multiplier) /* not supported */
 
47
{
 
48
        return -EINVAL;
 
49
}
 
50
 
 
51
void __cpuinit platform_secondary_init(unsigned int cpu)
 
52
{
 
53
        /* Clone setup for peripheral interrupt sources from CoreA. */
 
54
        bfin_write_SICB_IMASK0(bfin_read_SIC_IMASK0());
 
55
        bfin_write_SICB_IMASK1(bfin_read_SIC_IMASK1());
 
56
        SSYNC();
 
57
 
 
58
        /* Clone setup for IARs from CoreA. */
 
59
        bfin_write_SICB_IAR0(bfin_read_SIC_IAR0());
 
60
        bfin_write_SICB_IAR1(bfin_read_SIC_IAR1());
 
61
        bfin_write_SICB_IAR2(bfin_read_SIC_IAR2());
 
62
        bfin_write_SICB_IAR3(bfin_read_SIC_IAR3());
 
63
        bfin_write_SICB_IAR4(bfin_read_SIC_IAR4());
 
64
        bfin_write_SICB_IAR5(bfin_read_SIC_IAR5());
 
65
        bfin_write_SICB_IAR6(bfin_read_SIC_IAR6());
 
66
        bfin_write_SICB_IAR7(bfin_read_SIC_IAR7());
 
67
        bfin_write_SICB_IWR0(IWR_DISABLE_ALL);
 
68
        bfin_write_SICB_IWR1(IWR_DISABLE_ALL);
 
69
        SSYNC();
 
70
 
 
71
        /* We are done with local CPU inits, unblock the boot CPU. */
 
72
        set_cpu_online(cpu, true);
 
73
        spin_lock(&boot_lock);
 
74
        spin_unlock(&boot_lock);
 
75
}
 
76
 
 
77
int __cpuinit platform_boot_secondary(unsigned int cpu, struct task_struct *idle)
 
78
{
 
79
        unsigned long timeout;
 
80
 
 
81
        printk(KERN_INFO "Booting Core B.\n");
 
82
 
 
83
        spin_lock(&boot_lock);
 
84
 
 
85
        if ((bfin_read_SYSCR() & COREB_SRAM_INIT) == 0) {
 
86
                /* CoreB already running, sending ipi to wakeup it */
 
87
                platform_send_ipi_cpu(cpu, IRQ_SUPPLE_0);
 
88
        } else {
 
89
                /* Kick CoreB, which should start execution from CORE_SRAM_BASE. */
 
90
                bfin_write_SYSCR(bfin_read_SYSCR() & ~COREB_SRAM_INIT);
 
91
                SSYNC();
 
92
        }
 
93
 
 
94
        timeout = jiffies + 1 * HZ;
 
95
        while (time_before(jiffies, timeout)) {
 
96
                if (cpu_online(cpu))
 
97
                        break;
 
98
                udelay(100);
 
99
                barrier();
 
100
        }
 
101
 
 
102
        if (cpu_online(cpu)) {
 
103
                /* release the lock and let coreb run */
 
104
                spin_unlock(&boot_lock);
 
105
                return 0;
 
106
        } else
 
107
                panic("CPU%u: processor failed to boot\n", cpu);
 
108
}
 
109
 
 
110
static const char supple0[] = "IRQ_SUPPLE_0";
 
111
static const char supple1[] = "IRQ_SUPPLE_1";
 
112
void __init platform_request_ipi(int irq, void *handler)
 
113
{
 
114
        int ret;
 
115
        const char *name = (irq == IRQ_SUPPLE_0) ? supple0 : supple1;
 
116
 
 
117
        ret = request_irq(irq, handler, IRQF_PERCPU, name, handler);
 
118
        if (ret)
 
119
                panic("Cannot request %s for IPI service", name);
 
120
}
 
121
 
 
122
void platform_send_ipi(cpumask_t callmap, int irq)
 
123
{
 
124
        unsigned int cpu;
 
125
        int offset = (irq == IRQ_SUPPLE_0) ? 6 : 8;
 
126
 
 
127
        for_each_cpu_mask(cpu, callmap) {
 
128
                BUG_ON(cpu >= 2);
 
129
                SSYNC();
 
130
                bfin_write_SICB_SYSCR(bfin_read_SICB_SYSCR() | (1 << (offset + cpu)));
 
131
                SSYNC();
 
132
        }
 
133
}
 
134
 
 
135
void platform_send_ipi_cpu(unsigned int cpu, int irq)
 
136
{
 
137
        int offset = (irq == IRQ_SUPPLE_0) ? 6 : 8;
 
138
        BUG_ON(cpu >= 2);
 
139
        SSYNC();
 
140
        bfin_write_SICB_SYSCR(bfin_read_SICB_SYSCR() | (1 << (offset + cpu)));
 
141
        SSYNC();
 
142
}
 
143
 
 
144
void platform_clear_ipi(unsigned int cpu, int irq)
 
145
{
 
146
        int offset = (irq == IRQ_SUPPLE_0) ? 10 : 12;
 
147
        BUG_ON(cpu >= 2);
 
148
        SSYNC();
 
149
        bfin_write_SICB_SYSCR(bfin_read_SICB_SYSCR() | (1 << (offset + cpu)));
 
150
        SSYNC();
 
151
}
 
152
 
 
153
/*
 
154
 * Setup core B's local core timer.
 
155
 * In SMP, core timer is used for clock event device.
 
156
 */
 
157
void __cpuinit bfin_local_timer_setup(void)
 
158
{
 
159
#if defined(CONFIG_TICKSOURCE_CORETMR)
 
160
        struct irq_data *data = irq_get_irq_data(IRQ_CORETMR);
 
161
        struct irq_chip *chip = irq_data_get_irq_chip(data);
 
162
 
 
163
        bfin_coretmr_init();
 
164
        bfin_coretmr_clockevent_init();
 
165
 
 
166
        chip->irq_unmask(data);
 
167
#else
 
168
        /* Power down the core timer, just to play safe. */
 
169
        bfin_write_TCNTL(0);
 
170
#endif
 
171
 
 
172
}