* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
-
-#undef DEBUG
-
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/smp_lock.h>
#include <linux/interrupt.h>
#include <linux/kernel_stat.h>
+#include <linux/delay.h>
#include <linux/init.h>
#include <linux/spinlock.h>
#include <linux/errno.h>
-#include <linux/irq.h>
#include <asm/ptrace.h>
#include <asm/atomic.h>
#include <asm/time.h>
#include <asm/cacheflush.h>
#include <asm/keylargo.h>
-#include <asm/pmac_low_i2c.h>
-
-#include "mpic.h"
-#ifdef DEBUG
-#define DBG(fmt...) udbg_printf(fmt)
-#else
-#define DBG(fmt...)
-#endif
+#include "open_pic.h"
extern void pmac_secondary_start_1(void);
extern void pmac_secondary_start_2(void);
extern void pmac_secondary_start_3(void);
-extern struct smp_ops_t *smp_ops;
-
-static void (*pmac_tb_freeze)(int freeze);
-static struct device_node *pmac_tb_clock_chip_host;
-static spinlock_t timebase_lock = SPIN_LOCK_UNLOCKED;
-static unsigned long timebase;
-
-static void smp_core99_cypress_tb_freeze(int freeze)
-{
- u8 data;
- int rc;
-
- /* Strangely, the device-tree says address is 0xd2, but darwin
- * accesses 0xd0 ...
- */
- pmac_low_i2c_setmode(pmac_tb_clock_chip_host, pmac_low_i2c_mode_combined);
- rc = pmac_low_i2c_xfer(pmac_tb_clock_chip_host,
- 0xd0 | pmac_low_i2c_read,
- 0x81, &data, 1);
- if (rc != 0)
- goto bail;
-
- data = (data & 0xf3) | (freeze ? 0x00 : 0x0c);
-
- pmac_low_i2c_setmode(pmac_tb_clock_chip_host, pmac_low_i2c_mode_stdsub);
- rc = pmac_low_i2c_xfer(pmac_tb_clock_chip_host,
- 0xd0 | pmac_low_i2c_write,
- 0x81, &data, 1);
-
- bail:
- if (rc != 0) {
- printk("Cypress Timebase %s rc: %d\n",
- freeze ? "freeze" : "unfreeze", rc);
- panic("Timebase freeze failed !\n");
- }
-}
-
-static void smp_core99_pulsar_tb_freeze(int freeze)
-{
- u8 data;
- int rc;
-
- /* Strangely, the device-tree says address is 0xd2, but darwin
- * accesses 0xd0 ...
- */
- pmac_low_i2c_setmode(pmac_tb_clock_chip_host, pmac_low_i2c_mode_combined);
- rc = pmac_low_i2c_xfer(pmac_tb_clock_chip_host,
- 0xd4 | pmac_low_i2c_read,
- 0x2e, &data, 1);
- if (rc != 0)
- goto bail;
-
- data = (data & 0x88) | (freeze ? 0x11 : 0x22);
-
- pmac_low_i2c_setmode(pmac_tb_clock_chip_host, pmac_low_i2c_mode_stdsub);
- rc = pmac_low_i2c_xfer(pmac_tb_clock_chip_host,
- 0xd4 | pmac_low_i2c_write,
- 0x2e, &data, 1);
- bail:
- if (rc != 0) {
- printk(KERN_ERR "Pulsar Timebase %s rc: %d\n",
- freeze ? "freeze" : "unfreeze", rc);
- panic("Timebase freeze failed !\n");
- }
-}
-
-
-static void smp_core99_give_timebase(void)
-{
- /* Open i2c bus for synchronous access */
- if (pmac_low_i2c_open(pmac_tb_clock_chip_host, 0))
- panic("Can't open i2c for TB sync !\n");
-
- spin_lock(&timebase_lock);
- (*pmac_tb_freeze)(1);
- mb();
- timebase = get_tb();
- spin_unlock(&timebase_lock);
-
- while (timebase)
- barrier();
-
- spin_lock(&timebase_lock);
- (*pmac_tb_freeze)(0);
- spin_unlock(&timebase_lock);
-
- /* Close i2c bus */
- pmac_low_i2c_close(pmac_tb_clock_chip_host);
-}
-
-
-static void __devinit smp_core99_take_timebase(void)
-{
- while (!timebase)
- barrier();
- spin_lock(&timebase_lock);
- set_tb(timebase >> 32, timebase & 0xffffffff);
- timebase = 0;
- spin_unlock(&timebase_lock);
-}
+extern void smp_openpic_message_pass(int target, int msg);
+extern struct smp_ops_t *smp_ops;
static int __init smp_core99_probe(void)
{
- struct device_node *cpus;
- struct device_node *cc;
- int ncpus = 0;
+ struct device_node *cpus;
+ int ncpus = 1;
/* Maybe use systemconfiguration here ? */
if (ppc_md.progress) ppc_md.progress("smp_core99_probe", 0x345);
+ cpus = find_type_devices("cpu");
+ if (cpus == NULL)
+ return 0;
- /* Count CPUs in the device-tree */
- for (cpus = NULL; (cpus = of_find_node_by_type(cpus, "cpu")) != NULL;)
+ while ((cpus = cpus->next) != NULL)
++ncpus;
printk(KERN_INFO "PowerMac SMP probe found %d cpus\n", ncpus);
- /* Nothing more to do if less than 2 of them */
- if (ncpus <= 1)
- return 1;
-
- /* Look for the clock chip */
- for (cc = NULL; (cc = of_find_node_by_name(cc, "i2c-hwclock")) != NULL;) {
- struct device_node *p = of_get_parent(cc);
- u32 *reg;
- int ok;
- ok = p && device_is_compatible(p, "uni-n-i2c");
- if (!ok)
- goto next;
- reg = (u32 *)get_property(cc, "reg", NULL);
- if (reg == NULL)
- goto next;
- switch (*reg) {
- case 0xd2:
- pmac_tb_freeze = smp_core99_cypress_tb_freeze;
- printk(KERN_INFO "Timebase clock is Cypress chip\n");
- break;
- case 0xd4:
- pmac_tb_freeze = smp_core99_pulsar_tb_freeze;
- printk(KERN_INFO "Timebase clock is Pulsar chip\n");
- break;
- }
- if (pmac_tb_freeze != NULL) {
- pmac_tb_clock_chip_host = p;
- smp_ops->give_timebase = smp_core99_give_timebase;
- smp_ops->take_timebase = smp_core99_take_timebase;
- break;
- }
- next:
- of_node_put(p);
- }
-
- mpic_request_ipis();
+ if (ncpus > 1)
+ openpic_request_IPIs();
return ncpus;
}
static void __init smp_core99_kick_cpu(int nr)
{
- int save_vector, j;
+ int save_vector;
unsigned long new_vector;
unsigned long flags;
volatile unsigned int *vector
* b .pmac_secondary_start - KERNELBASE
*/
switch(nr) {
- case 1:
- new_vector = (unsigned long)pmac_secondary_start_1;
- break;
- case 2:
- new_vector = (unsigned long)pmac_secondary_start_2;
- break;
- case 3:
- default:
- new_vector = (unsigned long)pmac_secondary_start_3;
- break;
+ case 1:
+ new_vector = (unsigned long)pmac_secondary_start_1;
+ break;
+ case 2:
+ new_vector = (unsigned long)pmac_secondary_start_2;
+ break;
+ case 3:
+ new_vector = (unsigned long)pmac_secondary_start_3;
+ break;
}
*vector = 0x48000002 + (new_vector - KERNELBASE);
* ideally, all that crap will be done in prom.c and the CPU left
* in a RAM-based wait loop like CHRP.
*/
- for (j = 1; j < 1000000; j++)
- mb();
+ mdelay(1);
/* Restore our exception vector */
*vector = save_vector;
static void __init smp_core99_setup_cpu(int cpu_nr)
{
- /* Setup MPIC */
- mpic_setup_this_cpu();
+ /* Setup openpic */
+ do_openpic_setup_cpu();
if (cpu_nr == 0) {
extern void g5_phy_disable_cpu1(void);
*/
if (num_online_cpus() < 2)
g5_phy_disable_cpu1();
- if (ppc_md.progress) ppc_md.progress("smp_core99_setup_cpu 0 done", 0x349);
+ if (ppc_md.progress) ppc_md.progress("core99_setup_cpu 0 done", 0x349);
}
}
+extern void smp_generic_give_timebase(void);
+extern void smp_generic_take_timebase(void);
+
struct smp_ops_t core99_smp_ops __pmacdata = {
- .message_pass = smp_mpic_message_pass,
+ .message_pass = smp_openpic_message_pass,
.probe = smp_core99_probe,
.kick_cpu = smp_core99_kick_cpu,
.setup_cpu = smp_core99_setup_cpu,