4 * Copyright (C) 2007 Paul Mundt
5 * Copyright (C) 2007 Magnus Damm
7 * This file is subject to the terms and conditions of the GNU General Public
8 * License. See the file "COPYING" in the main directory of this archive
11 #include <linux/init.h>
12 #include <linux/cpumask.h>
13 #include <linux/smp.h>
14 #include <linux/interrupt.h>
17 void __init
plat_smp_setup(void)
22 cpus_clear(cpu_possible_map
);
23 cpu_set(cpu
, cpu_possible_map
);
25 __cpu_number_map
[0] = 0;
26 __cpu_logical_map
[0] = 0;
29 * Do this stupidly for now.. we don't have an easy way to probe
30 * for the total number of cores.
32 for (i
= 1, num
= 0; i
< NR_CPUS
; i
++) {
33 cpu_set(i
, cpu_possible_map
);
34 __cpu_number_map
[i
] = ++num
;
35 __cpu_logical_map
[num
] = i
;
38 printk(KERN_INFO
"Detected %i available secondary CPU(s)\n", num
);
41 void __init
plat_prepare_cpus(unsigned int max_cpus
)
45 #define STBCR_REG(phys_id) (0xfe400004 | (phys_id << 12))
46 #define RESET_REG(phys_id) (0xfe400008 | (phys_id << 12))
48 #define STBCR_MSTP 0x00000001
49 #define STBCR_RESET 0x00000002
50 #define STBCR_LTSLP 0x80000000
52 #define STBCR_AP_VAL (STBCR_RESET | STBCR_LTSLP)
54 void plat_start_cpu(unsigned int cpu
, unsigned long entry_point
)
56 ctrl_outl(entry_point
, RESET_REG(cpu
));
58 if (!(ctrl_inl(STBCR_REG(cpu
)) & STBCR_MSTP
))
59 ctrl_outl(STBCR_MSTP
, STBCR_REG(cpu
));
61 while (!(ctrl_inl(STBCR_REG(cpu
)) & STBCR_MSTP
))
64 /* Start up secondary processor by sending a reset */
65 ctrl_outl(STBCR_AP_VAL
, STBCR_REG(cpu
));
68 int plat_smp_processor_id(void)
70 return ctrl_inl(0xff000048); /* CPIDR */
73 void plat_send_ipi(unsigned int cpu
, unsigned int message
)
75 unsigned long addr
= 0xfe410070 + (cpu
* 4);
78 BUG_ON(message
>= SMP_MSG_NR
);
80 ctrl_outl(1 << (message
<< 2), addr
); /* C0INTICI..CnINTICI */
84 void (*handler
)(void *);
89 static irqreturn_t
ipi_interrupt_handler(int irq
, void *arg
)
91 struct ipi_data
*id
= arg
;
92 unsigned int cpu
= hard_smp_processor_id();
93 unsigned int offs
= 4 * cpu
;
96 x
= ctrl_inl(0xfe410070 + offs
); /* C0INITICI..CnINTICI */
97 x
&= (1 << (id
->message
<< 2));
98 ctrl_outl(x
, 0xfe410080 + offs
); /* C0INTICICLR..CnINTICICLR */
100 id
->handler(id
->arg
);
105 static struct ipi_data ipi_handlers
[SMP_MSG_NR
];
107 int plat_register_ipi_handler(unsigned int message
,
108 void (*handler
)(void *), void *arg
)
110 struct ipi_data
*id
= &ipi_handlers
[message
];
112 BUG_ON(SMP_MSG_NR
>= 8);
113 BUG_ON(message
>= SMP_MSG_NR
);
115 id
->handler
= handler
;
117 id
->message
= message
;
119 return request_irq(104 + message
, ipi_interrupt_handler
, 0, "IPI", id
);