mftbu r8 ; Get the upper one again
cmplw r9,r8 ; Did the top tick?
bne- yesnap ; Yeah, need to get it again...
+
stw r8,napStamp(r12) ; Set high order time stamp
stw r7,napStamp+4(r12) ; Set low order nap stamp
+ rlwinm. r0,r11,0,pfAltivecb,pfAltivecb ; Do we have altivec?
+ beq- minovec ; No...
+ dssall ; Stop the streams before we nap/doze
+ sync
+ lwz r8,napStamp(r12) ; Reload high order time stamp
+clearpipe:
+ cmplw r8,r8
+ bne- clearpipe
+ isync
+minovec:
+
rlwinm. r7,r11,0,pfNoL2PFNapb,pfNoL2PFNapb ; Turn off L2 Prefetch before nap?
beq miL2PFok
isync ; Make sure it is set
mtmsr r7 ; Enable for interrupts
- rlwinm. r11,r11,0,pfAltivecb,pfAltivecb ; Do we have altivec?
- beq- minovec ; No...
- dssall ; Stop the streams before we nap/doze
-minovec:
bf-- pf64Bitb,mipowloop ; skip if 32-bit...
li r3,0x10 ; Fancy nap threashold is 0x10 ticks
/* Initialize processor thermal monitoring
* void ml_thrm_init(void)
*
- * Build initial TAU registers and start them all going.
- * We ca not do this at initial start up because we need to have the processor frequency first.
- * And just why is this in assembler when it does not have to be?? Cause I am just too
- * lazy to open up a "C" file, thats why.
+ * Obsolete, deprecated and will be removed.
*/
; Force a line boundry here
.globl EXT(ml_thrm_init)
LEXT(ml_thrm_init)
-
- mfsprg r12,0 ; Get the per_proc blok
- lis r11,hi16(EXT(gPEClockFrequencyInfo)) ; Get top of processor information
- mfsprg r10,2 ; Get CPU specific features
- ori r11,r11,lo16(EXT(gPEClockFrequencyInfo)) ; Get bottom of processor information
- mtcrf 0x40,r10 ; Get the installed features
-
- li r3,lo16(thrmtidm|thrmvm) ; Set for lower-than thermal event at 0 degrees
- bflr pfThermalb ; No thermal monitoring on this cpu
- mtspr thrm1,r3 ; Do it
-
- lwz r3,thrmthrottleTemp(r12) ; Get our throttle temprature
- rlwinm r3,r3,31-thrmthre,thrmthrs,thrmthre ; Position it
- ori r3,r3,lo16(thrmvm) ; Set for higher-than event
- mtspr thrm2,r3 ; Set it
-
- lis r4,hi16(1000000) ; Top of million
-;
-; Note: some CPU manuals say this is processor clocks, some say bus rate. The latter
-; makes more sense because otherwise we can not get over about 400MHz.
-#if 0
- lwz r3,PECFIcpurate(r11) ; Get the processor speed
-#else
- lwz r3,PECFIbusrate(r11) ; Get the bus speed
-#endif
- ori r4,r4,lo16(1000000) ; Bottom of million
- lis r7,hi16(thrmsitvm>>1) ; Get top of highest possible value
- divwu r3,r3,r4 ; Get number of cycles per microseconds
- ori r7,r7,lo16(thrmsitvm>>1) ; Get the bottom of the highest possible value
- addi r3,r3,1 ; Insure we have enough
- mulli r3,r3,20 ; Get 20 microseconds worth of cycles
- cmplw r3,r7 ; Check against max
- ble+ smallenuf ; It is ok...
- mr r3,r7 ; Saturate
-
-smallenuf: rlwinm r3,r3,31-thrmsitve,thrmsitvs,thrmsitve ; Position
- ori r3,r3,lo16(thrmem) ; Enable with at least 20micro sec sample
- stw r3,thrm3val(r12) ; Save this in case we need it later
- mtspr thrm3,r3 ; Do it
blr
-
/* Set thermal monitor bounds
* void ml_thrm_set(unsigned int low, unsigned int high)
*
- * Set TAU to interrupt below low and above high. A value of
- * zero disables interruptions in that direction.
+ * Obsolete, deprecated and will be removed.
*/
; Force a line boundry here
.globl EXT(ml_thrm_set)
LEXT(ml_thrm_set)
-
- mfmsr r0 ; Get the MSR
- rlwinm r0,r0,0,MSR_FP_BIT+1,MSR_FP_BIT-1 ; Force floating point off
- rlwinm r0,r0,0,MSR_VEC_BIT+1,MSR_VEC_BIT-1 ; Force vectors off
- rlwinm r6,r0,0,MSR_EE_BIT+1,MSR_EE_BIT-1 ; Clear EE bit
- mtmsr r6
- isync
-
- mfsprg r12,0 ; Get the per_proc blok
-
- rlwinm. r6,r3,31-thrmthre,thrmthrs,thrmthre ; Position it and see if enabled
- mfsprg r9,2 ; Get CPU specific features
- stw r3,thrmlowTemp(r12) ; Set the low temprature
- mtcrf 0x40,r9 ; See if we can thermal this machine
- rlwinm r9,r9,(((31-thrmtie)+(pfThermIntb+1))&31),thrmtie,thrmtie ; Set interrupt enable if this machine can handle it
- bf pfThermalb,tsetcant ; No can do...
- beq tsetlowo ; We are setting the low off...
- ori r6,r6,lo16(thrmtidm|thrmvm) ; Set the lower-than and valid bit
- or r6,r6,r9 ; Set interruption request if supported
-
-tsetlowo: mtspr thrm1,r6 ; Cram the register
-
- rlwinm. r6,r4,31-thrmthre,thrmthrs,thrmthre ; Position it and see if enabled
- stw r4,thrmhighTemp(r12) ; Set the high temprature
- beq tsethigho ; We are setting the high off...
- ori r6,r6,lo16(thrmvm) ; Set valid bit
- or r6,r6,r9 ; Set interruption request if supported
-
-tsethigho: mtspr thrm2,r6 ; Cram the register
-
-tsetcant: mtmsr r0 ; Reenable interruptions
- blr ; Leave...
+ blr
/* Read processor temprature
* unsigned int ml_read_temp(void)
*
+ * Obsolete, deprecated and will be removed.
*/
; Force a line boundry here
.globl EXT(ml_read_temp)
LEXT(ml_read_temp)
-
- mfmsr r9 ; Save the MSR
- li r5,15 ; Starting point for ranging (start at 15 so we do not overflow)
- rlwinm r9,r9,0,MSR_FP_BIT+1,MSR_FP_BIT-1 ; Force floating point off
- rlwinm r9,r9,0,MSR_VEC_BIT+1,MSR_VEC_BIT-1 ; Force vectors off
- rlwinm r8,r9,0,MSR_EE_BIT+1,MSR_EE_BIT-1 ; Turn off interruptions
- mfsprg r7,2 ; Get CPU specific features
- mtmsr r8 ; Do not allow interruptions
- mtcrf 0x40,r7 ; See if we can thermal this machine
- bf pfThermalb,thrmcant ; No can do...
-
- mfspr r11,thrm1 ; Save thrm1
-
-thrmrange: rlwinm r4,r5,31-thrmthre,thrmthrs,thrmthre ; Position it
- ori r4,r4,lo16(thrmtidm|thrmvm) ; Flip on the valid bit and make comparision for less than
-
- mtspr thrm1,r4 ; Set the test value
-
-thrmreada: mfspr r3,thrm1 ; Get the thermal register back
- rlwinm. r0,r3,0,thrmtiv,thrmtiv ; Has it settled yet?
- beq+ thrmreada ; Nope...
-
- rlwinm. r0,r3,0,thrmtin,thrmtin ; Are we still under the threshold?
- bne thrmsearch ; No, we went over...
-
- addi r5,r5,16 ; Start by trying every 16 degrees
- cmplwi r5,127 ; Have we hit the max?
- blt- thrmrange ; Got some more to do...
-
-thrmsearch: rlwinm r4,r5,31-thrmthre,thrmthrs,thrmthre ; Position it
- ori r4,r4,lo16(thrmtidm|thrmvm) ; Flip on the valid bit and make comparision for less than
-
- mtspr thrm1,r4 ; Set the test value
-
-thrmread: mfspr r3,thrm1 ; Get the thermal register back
- rlwinm. r0,r3,0,thrmtiv,thrmtiv ; Has it settled yet?
- beq+ thrmread ; Nope...
-
- rlwinm. r0,r3,0,thrmtin,thrmtin ; Are we still under the threshold?
- beq thrmdone ; No, we hit it...
- addic. r5,r5,-1 ; Go down a degree
- bge+ thrmsearch ; Try again (until we are below freezing)...
-
-thrmdone: addi r3,r5,1 ; Return the temprature (bump it up to make it correct)
- mtspr thrm1,r11 ; Restore the thermal register
- mtmsr r9 ; Re-enable interruptions
- blr ; Leave...
-
-thrmcant: eqv r3,r3,r3 ; Return bogus temprature because we can not read it
- mtmsr r9 ; Re-enable interruptions
- blr ; Leave...
+ li r3,-1
+ blr
/* Throttle processor speed up or down
* unsigned int ml_throttle(unsigned int step)
* Returns old speed and sets new. Both step and return are values from 0 to
* 255 that define number of throttle steps, 0 being off and "ictcfim" is max * 2.
*
+ * Obsolete, deprecated and will be removed.
*/
; Force a line boundry here
.globl EXT(ml_throttle)
LEXT(ml_throttle)
-
- mfmsr r9 ; Save the MSR
- rlwinm r9,r9,0,MSR_FP_BIT+1,MSR_FP_BIT-1 ; Force floating point off
- rlwinm r9,r9,0,MSR_VEC_BIT+1,MSR_VEC_BIT-1 ; Force vectors off
- rlwinm r8,r9,0,MSR_EE_BIT+1,MSR_EE_BIT-1 ; Turn off interruptions
- cmplwi r3,lo16(ictcfim>>1) ; See if we are going too far
- mtmsr r8 ; Do not allow interruptions
- isync
- ble+ throtok ; Throttle value is ok...
- li r3,lo16(ictcfim>>1) ; Set max
-
-throtok: rlwinm. r4,r3,1,ictcfib,ictcfie ; Set the throttle
- beq throtoff ; Skip if we are turning it off...
- ori r4,r4,lo16(thrmvm) ; Turn on the valid bit
-
-throtoff: mfspr r3,ictc ; Get the old throttle
- mtspr ictc,r4 ; Set the new
- rlwinm r3,r3,31,1,31 ; Shift throttle value over
- mtmsr r9 ; Restore interruptions
- blr ; Return...
+ li r3,0
+ blr
/*
** ml_get_timebase()
.globl EXT(ml_set_processor_speed)
LEXT(ml_set_processor_speed)
- mfsprg r5, 0 ; Get the per_proc_info
+ mflr r0 ; Save the link register
+ stwu r1, -(FM_ALIGN(4*4)+FM_SIZE)(r1) ; Make some space on the stack
+ stw r28, FM_ARG0+0x00(r1) ; Save a register
+ stw r29, FM_ARG0+0x04(r1) ; Save a register
+ stw r30, FM_ARG0+0x08(r1) ; Save a register
+ stw r31, FM_ARG0+0x0C(r1) ; Save a register
+ stw r0, (FM_ALIGN(4*4)+FM_SIZE+FM_LR_SAVE)(r1) ; Save the return
- lwz r6, pfPowerModes(r5) ; Get the supported power modes
+ mfsprg r31, 0 ; Get the per_proc_info
+
+ lwz r30, pfPowerModes(r31) ; Get the supported power modes
- rlwinm. r0, r6, 0, pmDualPLLb, pmDualPLLb ; Is DualPLL supported?
+ rlwinm. r0, r30, 0, pmDualPLLb, pmDualPLLb ; Is DualPLL supported?
bne spsDPLL
- rlwinm. r0, r6, 0, pmDFSb, pmDFSb ; Is DFS supported?
+ rlwinm. r0, r30, 0, pmDFSb, pmDFSb ; Is DFS supported?
bne spsDFS
- rlwinm. r0, r6, 0, pmPowerTuneb, pmPowerTuneb ; Is DualPLL supported?
+ rlwinm. r0, r30, 0, pmPowerTuneb, pmPowerTuneb ; Is PowerTune supported?
bne spsPowerTune
b spsDone ; No supported power modes
spsDPLL1:
mfspr r4, hid1 ; Get the current PLL settings
rlwimi r4, r3, 31-hid1ps, hid1ps, hid1ps ; Copy the PLL Select bit
- stw r4, pfHID1(r5) ; Save the new hid1 value
+ stw r4, pfHID1(r31) ; Save the new hid1 value
mtspr hid1, r4 ; Select desired PLL
cmpli cr0, r3, 0 ; Restore BTIC after high speed
bne spsDone
- lwz r4, pfHID0(r5) ; Load the hid0 value
+ lwz r4, pfHID0(r31) ; Load the hid0 value
sync
mtspr hid0, r4 ; Set the hid0 value
isync
rlwinm r3, r3, 0, hid1dfs1+1, hid1dfs0-1 ; assume full speed, clear dfs bits
beq spsDFS1
oris r3, r3, hi16(hid1dfs1m) ; slow, set half speed dfs1 bit
+
spsDFS1:
- stw r3, pfHID1(r5) ; Save the new hid1 value
+ stw r3, pfHID1(r31) ; Save the new hid1 value
sync
mtspr hid1, r3 ; Set the new HID1
sync
b spsDone
spsPowerTune:
+ rlwinm r28, r3, 31-dnap, dnap, dnap ; Shift the 1 bit to the dnap+32 bit
+ rlwinm r3, r3, 2, 29, 29 ; Shift the 1 to a 4 and mask
+ addi r3, r3, pfPowerTune0 ; Add in the pfPowerTune0 offset
+ lwzx r29, r31, r3 ; Load the PowerTune number 0 or 1
+
+ sldi r28, r28, 32 ; Shift to the top half
+ ld r3, pfHID0(r31) ; Load the saved hid0 value
+ and r28, r28, r3 ; Save the dnap bit
+ lis r4, hi16(dnapm) ; Make a mask for the dnap bit
+ sldi r4, r4, 32 ; Shift to the top half
+ andc r3, r3, r4 ; Clear the dnap bit
+ or r28, r28, r3 ; Insert the dnap bit as needed for later
+
+ sync
+ mtspr hid0, r3 ; Turn off dnap in hid0
+ mfspr r3, hid0 ; Yes, this is silly, keep it here
+ mfspr r3, hid0 ; Yes, this is a duplicate, keep it here
+ mfspr r3, hid0 ; Yes, this is a duplicate, keep it here
+ mfspr r3, hid0 ; Yes, this is a duplicate, keep it here
+ mfspr r3, hid0 ; Yes, this is a duplicate, keep it here
+ mfspr r3, hid0 ; Yes, this is a duplicate, keep it here
+ isync ; Make sure it is set
+
+ lis r3, hi16(PowerTuneControlReg) ; Write zero to the PCR
+ ori r3, r3, lo16(PowerTuneControlReg)
+ li r4, 0
+ li r5, 0
+ bl _ml_scom_write
+
+ lis r3, hi16(PowerTuneControlReg) ; Write the PowerTune value to the PCR
+ ori r3, r3, lo16(PowerTuneControlReg)
+ li r4, 0
+ mr r5, r29
+ bl _ml_scom_write
+
+ rlwinm r29, r29, 13-6, 6, 7 ; Move to PSR speed location and isolate the requested speed
+spsPowerTuneLoop:
+ lis r3, hi16(PowerTuneStatusReg) ; Read the status from the PSR
+ ori r3, r3, lo16(PowerTuneStatusReg)
+ li r4, 0
+ bl _ml_scom_read
+ srdi r5, r5, 32
+ rlwinm r0, r5, 0, 6, 7 ; Isolate the current speed
+ rlwimi r0, r5, 0, 2, 2 ; Copy in the change in progress bit
+ cmpw r0, r29 ; Compare the requested and current speeds
+ beq spsPowerTuneDone
+ rlwinm. r0, r5, 0, 3, 3
+ beq spsPowerTuneLoop
+
+spsPowerTuneDone:
+ sync
+ mtspr hid0, r28 ; Turn on dnap in hid0 if needed
+ mfspr r28, hid0 ; Yes, this is silly, keep it here
+ mfspr r28, hid0 ; Yes, this is a duplicate, keep it here
+ mfspr r28, hid0 ; Yes, this is a duplicate, keep it here
+ mfspr r28, hid0 ; Yes, this is a duplicate, keep it here
+ mfspr r28, hid0 ; Yes, this is a duplicate, keep it here
+ mfspr r28, hid0 ; Yes, this is a duplicate, keep it here
+ isync ; Make sure it is set
+
b spsDone
spsDone:
+ lwz r0, (FM_ALIGN(4*4)+FM_SIZE+FM_LR_SAVE)(r1) ; Get the return
+ lwz r28, FM_ARG0+0x00(r1) ; Restore a register
+ lwz r29, FM_ARG0+0x04(r1) ; Restore a register
+ lwz r30, FM_ARG0+0x08(r1) ; Restore a register
+ lwz r31, FM_ARG0+0x0C(r1) ; Restore a register
+ lwz r1, FM_BACKPTR(r1) ; Pop the stack
+ mtlr r0
blr
/*
spvDone:
blr
+
+
+;
+; unsigned int ml_scom_write(unsigned int reg, unsigned long long data)
+; 64-bit machines only
+; returns status
+;
+
+ .align 5
+ .globl EXT(ml_scom_write)
+
+LEXT(ml_scom_write)
+
+ rldicr r3,r3,8,47 ; Align register it correctly
+ rldimi r5,r4,32,0 ; Merge the high part of data
+ sync ; Clean up everything
+
+ mtspr scomd,r5 ; Stick in the data
+ mtspr scomc,r3 ; Set write to register
+ sync
+ isync
+
+ mfspr r3,scomc ; Read back status
+ blr ; leave....
+
+;
+; unsigned int ml_read_scom(unsigned int reg, unsigned long long *data)
+; 64-bit machines only
+; returns status
+; ASM Callers: data (r4) can be zero and the 64 bit data will be returned in r5
+;
+
+ .align 5
+ .globl EXT(ml_scom_read)
+
+LEXT(ml_scom_read)
+
+ mfsprg r0,2 ; Get the feature flags
+ rldicr r3,r3,8,47 ; Align register it correctly
+ rlwinm r0,r0,pfSCOMFixUpb+1,31,31 ; Set shift if we need a fix me up
+
+ ori r3,r3,0x8000 ; Set to read data
+ sync
+
+ mtspr scomc,r3 ; Request the register
+ mfspr r5,scomd ; Get the register contents
+ mfspr r3,scomc ; Get back the status
+ sync
+ isync
+
+ sld r5,r5,r0 ; Fix up if needed
+
+ cmplwi r4, 0 ; If data pointer is null, just return
+ beqlr ; the received data in r5
+ std r5,0(r4) ; Pass back the received data
+ blr ; Leave...