Subject: tipb 667/800Mhz
To: None <port-macppc@netbsd.org>
From: Benjamin Herrenschmidt <benh@mipsys.com>
List: port-macppc
Date: 08/05/2002 17:17:52
Since this was discussed here earlier, I though you would be interested
in the conclusion of my experiments with having this machine actually
do 800Mhz with a non-Apple OS.
So first, forget about the OF hack that hang around on the net, all I
could do with it is let the kernel beleive it runs at 800Mhz, but run
any real benchmark of the CPU and you'll quickly discover that it's
really still at 667Mhz. This matches the result of the Open Firmware
dumps I did on this box, that is OF there doesn't seem to have code to
do the actual switch.
So how does it work ? Well, basically, it's the PMU that controls the
pin strapping of the PLL_CFG[0..3] pins. You need to send it a 0x7d
command, with 5 bytes as parameters ('W', 'O', 'O', 'F', x) where "x"
is 0x00 for high speed or 0x01 for low speed.
When you do that, the PMU enters a state similar to what happens with
the sleep command. That is it basically waits to be informed (by
uninorth I suppose) that the CPU has went to sleep, then shuts it down
(or hard resets it) with the proper PLL config. So the actual speed
switch procedure is very similar to machine sleep, except that device
drivers don't need to deal with sleep and a slight change to what you
write to UniNorth power management register.
The actual scenario I implemented successfully in linux/ppc is:
1) disable all interrupt sources on OpenPIC (basically raise the CPU
priority mask)
2) Wait for the PMU to be idle (complete outstanding battery or
environement requests)
3) Make sure the DEC won't bother us
4) disable interrupts (MSR:EE)
5) save values of L2CR and L3CR, then flush & disable L2 and L3
caches (MacOS X does this
later as part of the last step, do as you will, it was simpler
for me that way)
6) send the PMU request
7) Write 0x00000001 (BE) to UniNorth HWInitState register
(uninorth_base + 0x70). This one
tells the ROM to branch to the wakeup vector (0x80 physical in
RAM) when the CPU is restarted.
Write 0x00000001 (BE) to UniNorth PowerManagement register
(uninorth_base + 0x30)
8) write a physical pointer to the resume code at physical address
0x80 of RAM. The ROM will read
that pointer and jump to that address on wakeup. MacOS X just
uses the reset vector for that by
writing 0x100 in this location, Linux just jumps directly to the
resume code
9) flush remaining caches & disable them, backup CPU state
(registers, important SPRs, etc...)
10) put the CPU in and endless sleep loop (HID0:SLEEP, MSR:POW,
MSR:EE probably optional)
At this point, the PMU will kill the CPU, change the PLL_CFG bits, and
restart to ROM, which will
call your resume vector where you can restore the CPU state, the
caches, etc...
You can see the actual value of the PLL_CFG bits by reading the HID1
register. Refer to the 7455
docs for actual table of values for a 133Mhz bus, though I don't know
if we can instruct the PMU to
present other than 667Mhz and 800Mhz values.
Have fun !
Ben.