[PATCH] ppc64: Fix g5 hw timebase sync
The hardware sync of the timebase on SMP G5s uses a black magic incantation to the i2c clock chip that was inspired from what Darwin does. However, this was an earlier version of Darwin that was ... buggy ! heh. This causes the latest models to break though when starting SMP, so it's worth fixing. Here's a new version of the incantation based on careful transcription of the said incantations as found in the latest version of apple's temple. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
parent
e16fa6b9d2
commit
f10d20c1f1
1 changed files with 21 additions and 7 deletions
|
@ -68,6 +68,7 @@ extern struct smp_ops_t *smp_ops;
|
||||||
|
|
||||||
static void (*pmac_tb_freeze)(int freeze);
|
static void (*pmac_tb_freeze)(int freeze);
|
||||||
static struct device_node *pmac_tb_clock_chip_host;
|
static struct device_node *pmac_tb_clock_chip_host;
|
||||||
|
static u8 pmac_tb_pulsar_addr;
|
||||||
static DEFINE_SPINLOCK(timebase_lock);
|
static DEFINE_SPINLOCK(timebase_lock);
|
||||||
static unsigned long timebase;
|
static unsigned long timebase;
|
||||||
|
|
||||||
|
@ -106,12 +107,9 @@ static void smp_core99_pulsar_tb_freeze(int freeze)
|
||||||
u8 data;
|
u8 data;
|
||||||
int rc;
|
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);
|
pmac_low_i2c_setmode(pmac_tb_clock_chip_host, pmac_low_i2c_mode_combined);
|
||||||
rc = pmac_low_i2c_xfer(pmac_tb_clock_chip_host,
|
rc = pmac_low_i2c_xfer(pmac_tb_clock_chip_host,
|
||||||
0xd4 | pmac_low_i2c_read,
|
pmac_tb_pulsar_addr | pmac_low_i2c_read,
|
||||||
0x2e, &data, 1);
|
0x2e, &data, 1);
|
||||||
if (rc != 0)
|
if (rc != 0)
|
||||||
goto bail;
|
goto bail;
|
||||||
|
@ -120,7 +118,7 @@ static void smp_core99_pulsar_tb_freeze(int freeze)
|
||||||
|
|
||||||
pmac_low_i2c_setmode(pmac_tb_clock_chip_host, pmac_low_i2c_mode_stdsub);
|
pmac_low_i2c_setmode(pmac_tb_clock_chip_host, pmac_low_i2c_mode_stdsub);
|
||||||
rc = pmac_low_i2c_xfer(pmac_tb_clock_chip_host,
|
rc = pmac_low_i2c_xfer(pmac_tb_clock_chip_host,
|
||||||
0xd4 | pmac_low_i2c_write,
|
pmac_tb_pulsar_addr | pmac_low_i2c_write,
|
||||||
0x2e, &data, 1);
|
0x2e, &data, 1);
|
||||||
bail:
|
bail:
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
|
@ -185,6 +183,12 @@ static int __init smp_core99_probe(void)
|
||||||
if (ncpus <= 1)
|
if (ncpus <= 1)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
/* HW sync only on these platforms */
|
||||||
|
if (!machine_is_compatible("PowerMac7,2") &&
|
||||||
|
!machine_is_compatible("PowerMac7,3") &&
|
||||||
|
!machine_is_compatible("RackMac3,1"))
|
||||||
|
goto nohwsync;
|
||||||
|
|
||||||
/* Look for the clock chip */
|
/* Look for the clock chip */
|
||||||
for (cc = NULL; (cc = of_find_node_by_name(cc, "i2c-hwclock")) != NULL;) {
|
for (cc = NULL; (cc = of_find_node_by_name(cc, "i2c-hwclock")) != NULL;) {
|
||||||
struct device_node *p = of_get_parent(cc);
|
struct device_node *p = of_get_parent(cc);
|
||||||
|
@ -198,11 +202,18 @@ static int __init smp_core99_probe(void)
|
||||||
goto next;
|
goto next;
|
||||||
switch (*reg) {
|
switch (*reg) {
|
||||||
case 0xd2:
|
case 0xd2:
|
||||||
|
if (device_is_compatible(cc, "pulsar-legacy-slewing")) {
|
||||||
|
pmac_tb_freeze = smp_core99_pulsar_tb_freeze;
|
||||||
|
pmac_tb_pulsar_addr = 0xd2;
|
||||||
|
printk(KERN_INFO "Timebase clock is Pulsar chip\n");
|
||||||
|
} else if (device_is_compatible(cc, "cy28508")) {
|
||||||
pmac_tb_freeze = smp_core99_cypress_tb_freeze;
|
pmac_tb_freeze = smp_core99_cypress_tb_freeze;
|
||||||
printk(KERN_INFO "Timebase clock is Cypress chip\n");
|
printk(KERN_INFO "Timebase clock is Cypress chip\n");
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 0xd4:
|
case 0xd4:
|
||||||
pmac_tb_freeze = smp_core99_pulsar_tb_freeze;
|
pmac_tb_freeze = smp_core99_pulsar_tb_freeze;
|
||||||
|
pmac_tb_pulsar_addr = 0xd4;
|
||||||
printk(KERN_INFO "Timebase clock is Pulsar chip\n");
|
printk(KERN_INFO "Timebase clock is Pulsar chip\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -210,12 +221,15 @@ static int __init smp_core99_probe(void)
|
||||||
pmac_tb_clock_chip_host = p;
|
pmac_tb_clock_chip_host = p;
|
||||||
smp_ops->give_timebase = smp_core99_give_timebase;
|
smp_ops->give_timebase = smp_core99_give_timebase;
|
||||||
smp_ops->take_timebase = smp_core99_take_timebase;
|
smp_ops->take_timebase = smp_core99_take_timebase;
|
||||||
|
of_node_put(cc);
|
||||||
|
of_node_put(p);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
next:
|
next:
|
||||||
of_node_put(p);
|
of_node_put(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nohwsync:
|
||||||
mpic_request_ipis();
|
mpic_request_ipis();
|
||||||
|
|
||||||
return ncpus;
|
return ncpus;
|
||||||
|
|
Loading…
Add table
Reference in a new issue