forums.ps2dev.org Forum Index forums.ps2dev.org
Homebrew PS2, PSP & PS3 Development Discussions
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

scePowerSetClockFrequency

 
Post new topic   Reply to topic    forums.ps2dev.org Forum Index -> PSP Development
View previous topic :: View next topic  
Author Message
SilverSpring



Joined: 27 Feb 2007
Posts: 115

PostPosted: Mon Mar 19, 2007 10:14 pm    Post subject: scePowerSetClockFrequency Reply with quote

In psppower.h, prototype is this:

/**
* Set Clock Frequencies
*
* NOTE: Please use scePowerSetBusClockFrequency and
* scePowerSetCpuClockFrequency instead of this function
* for clock <= 222 and bus <= 111.
*
* @param cpufreq - cpu frequency, valid from 1-333
* @param ramfreq - ram frequency, valid from 1-333
* @param busfreq - bus frequency, valid from 1-166
*/
int scePowerSetClockFrequency(int cpufreq, int ramfreq, int busfreq);

I think should be:

/**
* Set Clock Frequencies
*
* @param pllfreq - pll frequency, valid from 19-333
* @param cpufreq - cpu frequency, valid from 1-333
* @param busfreq - bus frequency, valid from 1-167
*
* and:
*
* cpufreq <= pllfreq
* busfreq*2 <= pllfreq
*
*/
int scePowerSetClockFrequency(int pllfreq, int cpufreq, int busfreq);
Back to top
View user's profile Send private message Visit poster's website
SilverSpring



Joined: 27 Feb 2007
Posts: 115

PostPosted: Fri Mar 23, 2007 2:56 am    Post subject: Reply with quote

Just to confirm:

scePowerGetPllClockFrequencyInt()
scePowerGetCpuClockFrequencyInt()
scePowerGetBusClockFrequencyInt()

does in fact return the 1st, 2nd, & 3rd arguments of

scePowerSetClockFrequency(pllfreq, cpufreq, busfreq);


eg.

setting scePowerSetClockFrequency(333, 266, 111);

then,

scePowerGetPllClockFrequencyInt() returned 333
scePowerGetCpuClockFrequencyInt() returned 265
scePowerGetBusClockFrequencyInt() returned 110

Thus the prototype should be changed accordingly, as per above post.
Back to top
View user's profile Send private message Visit poster's website
jimparis



Joined: 10 Jun 2005
Posts: 1179
Location: Boston

PostPosted: Fri Mar 23, 2007 5:25 am    Post subject: Reply with quote

I applied the changes manually, thanks.
In the future a patch (from "svn diff") is preferred.
Back to top
View user's profile Send private message
Saotome



Joined: 03 Apr 2004
Posts: 182

PostPosted: Fri Mar 23, 2007 5:29 am    Post subject: Reply with quote

does this mean that this:
Code:

* NOTE: Please use scePowerSetBusClockFrequency and
* scePowerSetCpuClockFrequency instead of this function
* for clock <= 222 and bus <= 111.

is also not valid anymore? (I guess this was just assumed because the wrong parameters didn't bring the expected results (?))

EDIT: anyway... sorry if this sounds stupid, but what's the "pll frequency" (what does it do)?
_________________
infj
Back to top
View user's profile Send private message
SilverSpring



Joined: 27 Feb 2007
Posts: 115

PostPosted: Fri Mar 23, 2007 4:37 pm    Post subject: Reply with quote

The pllfreq is what the cpu & bus freq is derived from. Its based on a ratio of x/511 of the pllfreq. Thats why even trying to set a definite freq eg. scePowerSetClockFrequency(333, 266, 111), cpu & bus wont return that exact frequency.

cpufreq will actually return (approx) 265.89 (which is 408/511 times pllfreq)
busfreq*2 will actually return (appox) 221.57 (which is 340/511 times pllfreq)

The ratio is stored 0xBC200000 for cpu & 0xBC200004 for bus (numerator is 1st 9 bits of upper halfword, denominator is 1st 9 bits of lower halfword).

You can get the ratio's with these:

// Get cpufreq ratio
int sceSysreg_driver_44704E1D(int *numerator, int *denominator);

// get busfreq ratio
int sceSysreg_driver_377F035F(int *numerator, int *denominator);

or set ratio:

// Set cpufreq by ratio
// both values have to between 1-511
// obviously numerator cant be greater than denominator
// eg. sceSysreg_driver_5664F8B5(511, 511) gives 100% of pllfreq
int sceSysreg_driver_5664F8B5(int numerator, int denominator);

// set busfreq ratio
int sceSysreg_driver_584AD989(int numerator, int denominator);

or set/get freq by float value:

// Set cpufreq by float
// Will set to nearest granuality
// eg. sceSysreg_drver_AB3185FD(200.0) will only give 199.84 (460/511 = 90.02% of default pllfreq (222))
int sceSysreg_drver_AB3185FD(float cpufreq);

// Get cpufreq
float sceSysreg_driver_0EA487FA(void);

// set busfreq
int sceSysreg_driver_136E8F5A(float busfreq);

// get busfreq
float sceSysreg_driver_F4811E00(void);


Thats about all I know....
Back to top
View user's profile Send private message Visit poster's website
hlide



Joined: 10 Sep 2006
Posts: 750

PostPosted: Fri Mar 23, 2007 8:32 pm    Post subject: Reply with quote

i knew it , i knew it ! thanx for your confirmation XD
Back to top
View user's profile Send private message
crazyc



Joined: 17 Jun 2005
Posts: 410

PostPosted: Sat Mar 24, 2007 3:42 am    Post subject: Reply with quote

It seems, from some quick testing, that the media engine cpu frequency is equal to the pll frequency.
Back to top
View user's profile Send private message
hlide



Joined: 10 Sep 2006
Posts: 750

PostPosted: Sat Mar 24, 2007 4:31 am    Post subject: Reply with quote

crazyc wrote:
It seems, from some quick testing, that the media engine cpu frequency is equal to the pll frequency.


what do you mean ? that me cpu frequency is always 1.0 * pllfreq ?
Back to top
View user's profile Send private message
J.F.



Joined: 22 Feb 2004
Posts: 2906

PostPosted: Sat Mar 24, 2007 5:09 am    Post subject: Reply with quote

hlide wrote:
crazyc wrote:
It seems, from some quick testing, that the media engine cpu frequency is equal to the pll frequency.


what do you mean ? that me cpu frequency is always 1.0 * pllfreq ?


Or maybe the ME num/den regs haven't been located yet. I would imagine the PSP kernel would simply set the ME and CPU to 1.0 and the BUS to 0.5. I'm probably complete wrong :), but it seems like the simplest thing to do.
Back to top
View user's profile Send private message AIM Address
dot_blank



Joined: 28 Sep 2005
Posts: 498
Location: Brasil

PostPosted: Sat Mar 24, 2007 8:18 am    Post subject: Reply with quote

i am so glad this is finally confirmed :) great job SS
_________________
10011011 00101010 11010111 10001001 10111010
Back to top
View user's profile Send private message
crazyc



Joined: 17 Jun 2005
Posts: 410

PostPosted: Sat Mar 24, 2007 8:26 am    Post subject: Reply with quote

J.F. wrote:

Or maybe the ME num/den regs haven't been located yet. I would imagine the PSP kernel would simply set the ME and CPU to 1.0 and the BUS to 0.5. I'm probably complete wrong :), but it seems like the simplest thing to do.


Some more testing shows that the media engine can set it's own frequency using the same rules as above, or so it would seem. When I set 0xbc200000 on the me to 0x00ff01ff or a ratio of 255/511 and set the me to the same, the me goes a lot faster. In fact when I set the pll to 222 and the me to a ratio of .5 the me is at the same clock as the sc when it is set to 191 or 86% of the PLL frequency. The me actually runs at ~50% of pllfreq at a ratio of 55/511.
Back to top
View user's profile Send private message
hlide



Joined: 10 Sep 2006
Posts: 750

PostPosted: Sat Mar 24, 2007 9:41 am    Post subject: Reply with quote

how do you measure the difference on SC and ME processors ? because I don't see any good way to do so. you'd probably need to let SC and ME processors to read their own COP0 Count register, preferrably without any interrupts.

SC processor side :

Code:

int i, j;
*_sc_count = 1;
*_me_count = 0;
me_start(); // launch ME code
*_sc_count = 0;
j = _mfc0(COP0_Count);
do { i = _mfc0(COP0_Count) - j; } while ((_me_count != 0) || i > 8192);
*_sc_count = i;



ME processor side :

Code:

int i, j;
while (*_sc_count); // wait for SC synch
j = _mfc0(COP0_Count);
do { i = _mfc0(COP0_Count) - j; } while ((_sc_count != 0) || i > 8192);
*_me_count = i;


_me_count and _sc_count are volatile non cached addresses to be readable for both processors.

ME code would wait until SC synchronizes and start to count cycles. So you should get _sc_count ~= _me_count when they use the same PLL, CPU and BUS frequencies. But you seem to tell us we would rather get something like _sc_count ~= _me_count/2 instead. Is that so ?

if 8192 is too small, just increase it.

NOTE: you could also use the ME/SC mutex to synch them.
Back to top
View user's profile Send private message
J.F.



Joined: 22 Feb 2004
Posts: 2906

PostPosted: Sat Mar 24, 2007 9:57 am    Post subject: Reply with quote

crazyc wrote:
J.F. wrote:

Or maybe the ME num/den regs haven't been located yet. I would imagine the PSP kernel would simply set the ME and CPU to 1.0 and the BUS to 0.5. I'm probably complete wrong :), but it seems like the simplest thing to do.


Some more testing shows that the media engine can set it's own frequency using the same rules as above, or so it would seem. When I set 0xbc200000 on the me to 0x00ff01ff or a ratio of 255/511 and set the me to the same, the me goes a lot faster. In fact when I set the pll to 222 and the me to a ratio of .5 the me is at the same clock as the sc when it is set to 191 or 86% of the PLL frequency. The me actually runs at ~50% of pllfreq at a ratio of 55/511.


Sounds like maybe the ME has a different restriction on the divisor. Maybe it only uses 8bits instead of 9, so 0x00ff01ff is REALLY 255/255, not 255/511. That would account for the speed difference you think you saw.
Back to top
View user's profile Send private message AIM Address
crazyc



Joined: 17 Jun 2005
Posts: 410

PostPosted: Sat Mar 24, 2007 10:35 am    Post subject: Reply with quote

J.F. wrote:

Sounds like maybe the ME has a different restriction on the divisor. Maybe it only uses 8bits instead of 9, so 0x00ff01ff is REALLY 255/255, not 255/511. That would account for the speed difference you think you saw.


The default is 0x01ff01ff and then the me clock is the equal to pllfreq. Also, when I use 1/9 (0x00010009) instead of 55/511 (0x003701ff) the me still runs at ~50% pllfreq.

Quote:
how do you measure the difference on SC and ME processors ? because I don't see any good way to do so. you'd probably need to let SC and ME processors to read their own COP0 Count register, preferrably without any interrupts.


That's what I did. Added the mutex per your suggestion.

Code:
#include <pspkernel.h>
#include <pspdebug.h>
#include <pspctrl.h>
#include <pspdisplay.h>
#include <psppower.h>
#include <stdlib.h>
#include <string.h>

PSP_MODULE_INFO("me_clock_test", 0x1000, 1, 1);
PSP_MAIN_THREAD_ATTR(0);

#define set_count(val) __asm__ ("mtc0 %0, $9\n"::"r"(val))
#define read_count(val) __asm__ volatile ("mfc0 %0, $9\n":"=r"(val))

#define sysreg_lock *((unsigned int volatile *)0xbc100048)
#define try_lock(cpu) (((sysreg_lock = (cpu+1)) & 3) == (cpu+1))
#define free_lock() (sysreg_lock = 0)

void me_run(void);
void me_end(void);

int main(int argc, char *argv[])
{
   SceCtrlData ctl;
   unsigned int count, me_count;
   int status;

   pspDebugScreenInit();

   sceCtrlSetSamplingCycle(0);
   sceCtrlSetSamplingMode(PSP_CTRL_MODE_DIGITAL);

   memcpy((void *)0xbfc00040, me_run, (int)(me_end - me_run));
   sceKernelDcacheWritebackAll();
   scePowerSetClockFrequency(222, 111, 111);

   try_lock(0);

   sceSysregMeResetEnable();
   sceSysregMeBusClockEnable();
   sceSysregMeResetDisable();
   sceSysregVmeResetDisable();
   status = pspSdkDisableInterrupts();
   free_lock();
   __asm__("sync\n");
   set_count(0);
   pspSdkEnableInterrupts(status);
   
   while(1)
   {
      pspDebugScreenSetXY(0, 1);
      sceKernelDcacheWritebackInvalidateAll();
      read_count(count);
      me_count = _lw(0xbfc00600);
      pspDebugScreenPrintf("%08x %08x %f\n", count, me_count, (float)count/(float)me_count);
      sceCtrlReadBufferPositive(&ctl, 1);
      if(ctl.Buttons & PSP_CTRL_HOME)
      {
         sceKernelExitGame();
      }

      sceDisplayWaitVblankStart();
   }
   sceSysregMeBusClockDisable();
   return 0;
}
Code:
   .set noreorder

   .global me_run
   .global me_end

   .ent me_run

me_run:
   li $2, 0xbc100000
   li $3, 7
   sw $3, 80($2)
   
1:
   lw $3, 72($2)
   bne $3, $0, 1b
   nop

   mtc0 $0, $9

   li $2, 0xbc200000
   li $3, 0x00010009
   sw $3, 0($2)
   li $2, 0xbfc00000
0:
   mfc0 $3, $9
   b 0b
   sw $3, 0x600($2)
me_end:

   .end me_run
Back to top
View user's profile Send private message
hlide



Joined: 10 Sep 2006
Posts: 750

PostPosted: Sat Mar 24, 2007 11:02 am    Post subject: Reply with quote

huh, beware that an access to memory switchs CPU frequency to BUS frequency temporary so you should avoid having a different code when running on SC and ME processors (not speaking about miss cache too).

So you should really have the same code running a certain time as I showed above without any call to external functions for instance.

EDIT:

i read somewhere that instructions like lb/lbu/lh/lhu/lw/lwl/lwr/sb/sh/sw/swl/swr runs at bus frequency and not at cpu frequency. So if you have 63 cycles for a lw instruction (miss-cache), it doesn't mean 63 cycles at 333 MHz but rather at 166 MHz.
Back to top
View user's profile Send private message
crazyc



Joined: 17 Jun 2005
Posts: 410

PostPosted: Sat Mar 24, 2007 11:45 am    Post subject: Reply with quote

hlide wrote:
huh, beware that an access to memory switchs CPU frequency to BUS frequency temporary so you should avoid having a different code when running on SC and ME processors (not speaking about miss cache too).

So you should really have the same code running a certain time as I showed above without any call to external functions for instance.

EDIT:

i read somewhere that instructions like lb/lbu/lh/lhu/lw/lwl/lwr/sb/sh/sw/swl/swr runs at bus frequency and not at cpu frequency. So if you have 63 cycles for a lw instruction (miss-cache), it doesn't mean 63 cycles at 333 MHz but rather at 166 MHz.


This may be part of the problem, but with this code, if I set cpufreq==pllfreq and the me clock multiplier to 1, both cpus run at very nearly the same rate.
Back to top
View user's profile Send private message
sakya



Joined: 28 Apr 2006
Posts: 190

PostPosted: Thu Sep 13, 2007 9:26 am    Post subject: Reply with quote

Hi! :)

I'm not able to set the bus clock to 14Mhz (or anithing less than 37Mhz != 9Mhz).
Can someone help me?
Reading here and also here http://lan.st/archive/index.php/t-854.html that's what I tried:

If I do:
Code:
scePowerSetClockFrequency(222, 222, 111);


Using these functions
Code:
// get pllfreq (default is 222Mhz)
float sceSysreg_driver_B21B6CBF(void);

// get index value (default is 3)
int sceSysreg_driver_B4560C45(void);

// set pllfreq based on table
// index is the index for the float table (0-5)
int sceSysreg_driver_DCA57573(int index);

// get basefreq (hardcoded as 37Mhz in prx)
float sceSysreg_driver_53A6838B(void);

// Get cpufreq ratio
int sceSysreg_driver_44704E1D(int *numerator, int *denominator);

// get busfreq ratio
int sceSysreg_driver_377F035F(int *numerator, int *denominator);

// Set cpufreq by ratio
// both values have to between 1-511
// obviously numerator cant be greater than denominator
// eg. sceSysreg_driver_5664F8B5(511, 511) gives 100% of pllfreq
int sceSysreg_driver_5664F8B5(int numerator, int denominator);

// set busfreq ratio
int sceSysreg_driver_584AD989(int numerator, int denominator);


I get this info:
Code:
CPU      : 222       
CPU RATIO: 511/511
BUS      : 111     
BUS RATIO: 511/511
PLL      : 222     
PLL index: 3
basefreq : 37


As I understand there's this list of values:
Code:
const float table[6] =
{
0x3DE38E39, // == 0.11111111
0x3EE38E39, // == 0.44444445
0x3F124925, // == 0.57142860
0x3F2AAAAB, // == 0.66666669
0x3F4CCCCD, // == 0.80000001
0x3F800000 // == 1
};


That represent the PLL index.
PLL clock is calculated this way:
Code:
PLL = 37*9*table[PLL_index]
PLL = 37*9*0.66666669 --> 222


While CPU clock is calculated from PLL amd a ratio:
Code:
CPU = PLL * (numerator/denominator)
CPU = 222 * (511/511) --> 222


The BUS is:
Code:
BUS = PLL/2 * (numerator/denominator)
BUS = 222/2 * (511/511) --> 111


The strange thing is that if I try:
Code:
scePowerSetClockFrequency(29, 29, 14);

I obtain this info:
Code:
CPU      : 28        = 74*(200/511)
CPU RATIO: 200/511   
BUS      : 37        = 74/2*(511/511)
BUS RATIO: 511/511
PLL      : 74        = 37*9*0,225225225 (?)
PLL index: 9
basefreq : 37


What's that PLL index = 9? Shouldn't it be from 0 to 5?
Also changing numerator and denominator with
Code:
sceSysreg_driver_584AD989(280, 511);
BUS = 74/2 * (280/511) --> 20

doesen't have any affect.

Another strange thing IMHO:
If I do
Code:
scePowerSetClockFrequency(29, 29, 14);

so the PLL index is equal to 9.
Then execute:
Code:
   sceSysreg_driver_DCA57573(8);
   scePowerSetClockFrequency(29, 29, 14);

This is the info I get (BUS 9 and CPU 18):
Code:
CPU      : 18
CPU RATIO: 511/511
BUS      : 9
BUS RATIO: 511/511
PLL      : 18
PLL index: 8
basefreq : 37


I'm a little confused. ;)

Many thanks :)
Ciaooo
Sakya
Back to top
View user's profile Send private message Visit poster's website
SilverSpring



Joined: 27 Feb 2007
Posts: 115

PostPosted: Thu Sep 13, 2007 9:58 am    Post subject: Reply with quote

Im pretty sure the reason why you cannot go lower than 37MHz is because the PLL basefreq is 37MHz, so that is as low as you can go. Trying to go lower will cause funny effects.
_________________
PSP PRX LibDocs
Back to top
View user's profile Send private message Visit poster's website
crazyc



Joined: 17 Jun 2005
Posts: 410

PostPosted: Thu Sep 13, 2007 12:38 pm    Post subject: Reply with quote

sakya wrote:

What's that PLL index = 9? Shouldn't it be from 0 to 5?
Actually the list is longer then 5. Here's what I came up with after a little testing. I got it to work at 18.6Mhz but only with a light load. For everyone, don't try to set pllfreq to anything higher then 333Mhz unless you can handle wrecking it. I set it to 370 once but only by accident.
Code:
pll fractions  0xbc100068, to set OR index with 0x80
0 1/9 (.111)
1 4/9 (.444)
2 5/9 (.571)
3 6/9 (.667)
4 7/9 (.8)
5 9/9 (1)
6 0?
7 0?
8 1/18 (.056)
9 2/9  (.222)
a 5/18 (.286)
b 3/9  (.333)
c 7/18 (.4)
d 9/18 (.5)
e 0?
f 0?

pll multiplers  0xbc1000fc 8:16
9
11
13
15

base clock = 37
           9      11      13      15
0.056      18.6   (multipler doesn't matter)
0.111      37.0   (")
0.222      74.0   90.4   107   123
0.286      95.2   116   138   159
0.333      111   135   160   184
0.400      133   163   192   222
0.444      148   181   214   246
0.500      167   204   241   278
0.571      190   232   275   317
0.667      222   271   321   370
0.800      266   326   385   444
1.000      333   407   481   555
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    forums.ps2dev.org Forum Index -> PSP Development All times are GMT + 10 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group