How to Edit Frequencies in Exynos4412?

AAccount

Senior Member
Sep 8, 2010
1,005
1,909
0
I've built a custom kernel for my Galaxy Tab 10.1 The link is in my signature. When I wanted to add custom frequencies to it, there was a very informative post that told me how to edit the frequency table to make the new clock speeds on tegra2 come out right and also how to edit the voltage tables. At least on the tegra2 it involved editing tegra2_clocks.c where you had to change the pll_x frequency table, change the pll_x max speed, virtual cpu max speed, sku max speed, and add an additional frequency table for your new clock speeds. The voltage was done in tegra2_dvfs.c where you added changed the min/max voltages accordingly and added in your new frequencies there.

I have looked all over the internet for a similar guide for my I9300. The cpufreq-4x12 looks nothing like the tegra one. It appears that every frequency has an entry in clkdiv_cpu0_4412 (for the S3 at least) with dividers for cryptic values like "divcore" "divcorem0". I've tried doing a grep search in the kernel source and couldn't find those names mentioned anywhere. There also appears to be another clkdiv_cpu1_4412 with even more cryptic values which don't appear in grep either. Then of course, there's yet another cryptic table that each frequency seems to go to called "apll_pms". It appears as the voltages go to the asv tables but how you accommodate new frequencies is beyond me. The L0,L1.. etc labels don't appear to follow the conventions stated earlier where 1800MHz is labelled L0 at the top but L-2 later.

I realize that many experienced developers probably take this information for granted and I wouldn't be asking for this if it was available somewhere else. The documentation folder in the kernel doesn't provide any information either.

Please help a startup enthusiast :confused: As a beginner, I've typically answered similar how to questions on my own thread in the beginning, when other people were interested in how to get their hands dirty with modifications. (Although now, people just seem to be interested in the final product which is fine too.)
 

AndreiLux

Senior Member
Jul 9, 2011
3,209
14,595
0
Each divider value represents the real divider minus 1. So a value of 7 divides by 8. Populate the divider talbes with new entries like that. The registers have a limit so see the register maps in /mach/regs-clock.h. The dividers divide the final CPU clock. What values you give the dividers is up to you to decide.

The CPU clock is decided by the PLL as you saw. PMS decides the PLL frequency. The source quartz runs at 24MHz. The frequency is calculated by (P * Xtal) / (M << S).

Example 500MHz: ((125<<16)|(3<<8)|(0x1)), the format is ((P<<16)|(M<<8)|(S)).

(P * Xtal) = 125*24 MHz = 3000MHz
(M << S) = 3 << 1 = 6

End result is 3000MHz / 6 = 500MHz.

That's all you need to know. Alternatively, just copy what other devs have already done. Be careful with the Lx levels when you add new ones, you need shift all the existing ones throughout the file.
 

AAccount

Senior Member
Sep 8, 2010
1,005
1,909
0
Each divider value represents the real divider minus 1. So a value of 7 divides by 8. Populate the divider talbes with new entries like that. The registers have a limit so see the register maps in /mach/regs-clock.h. The dividers divide the final CPU clock. What values you give the dividers is up to you to decide.

The CPU clock is decided by the PLL as you saw. PMS decides the PLL frequency. The source quartz runs at 24MHz. The frequency is calculated by (P * Xtal) / (M << S).

Example 500MHz: ((125<<16)|(3<<8)|(0x1)), the format is ((P<<16)|(M<<8)|(S)).

(P * Xtal) = 125*24 MHz = 3000MHz
(M << S) = 3 << 1 = 6

End result is 3000MHz / 6 = 500MHz.

That's all you need to know. Alternatively, just copy what other devs have already done. Be careful with the Lx levels when you add new ones, you need shift all the existing ones throughout the file.
I'm a bit confused by what M << S means. From lookig at the example it looks like the formula is: P * 24 / ( M * 2^s)? Also, I'm assuming the voltage tables don't have to be touched. Thanks so much for the information. And... what fun would it be if you did a straight up copy and paste? :cyclops:
 

Entropy512

Senior Recognized Developer
Aug 31, 2007
14,095
25,085
0
Owego, NY
Be careful with the Lx levels when you add new ones, you need shift all the existing ones throughout the file.
And in any other files that reference levels... Namely any that contains a level-based DVFS lock.

I think much of Samsung's newer code does frequency-based locks with a frequency-to-level lookup, but in older 4210 kernels, there were lots of locks that called out specific levels. Some of these locks were in throttling code. Levels go from high freq to low freq.

So if L2 was originally 800 MHz, and L2 is now 1000 MHz, and thermal throttling code locks to a minimum level (maximum frequency) of L2... Whoops, now the thermal throttling is broken.
 
  • Like
Reactions: AAccount

AAccount

Senior Member
Sep 8, 2010
1,005
1,909
0
Hi again,

For some reason, the exynos4 sources seem to be much more fussy than the galaxy tab 10.1 tegra2 sources I messed with in the summer. Right of the bat (with no modifications), it refuses to compile giving me issues in the file arch/arm/mvp/mvpkm/mvpkm_main.o. I haven't touched anything or made any changes yet. I downlaoded the latest sources from Samsung. I tried switching toolchains and I get 1 of 2 errors. With an older toolchain I get

/tmp/ccC3yZT8.s:4865: Error: unknown pseudo-op: `.arch_extension'.

With a newer toolchain I get an error about making a pointer to int conversion without a cast. Wow, truly unbelievable!!!??? I just want to make a baseline run, haven't touched a character of code and it refuses. I tried compiling CM10.1's kernel (also with no modifications) but for some reasons the graphics are Pentium 1 slow. ADB shell with logcat keeps saying hwcompser can't do vsync and it attempts to fake it.

I don't remember it being this hard on my galaxy tab 10.1. Am I missing something obvious?
---------------------added-----------------

I got cm sources compiling correctly. I think i forgot to undo previous experiments
 
Last edited:

ffolkes

Senior Member
Oct 18, 2006
1,342
2,106
153
New Jersey
Each divider value represents the real divider minus 1. So a value of 7 divides by 8. Populate the divider talbes with new entries like that. The registers have a limit so see the register maps in /mach/regs-clock.h. The dividers divide the final CPU clock. What values you give the dividers is up to you to decide.

The CPU clock is decided by the PLL as you saw. PMS decides the PLL frequency. The source quartz runs at 24MHz. The frequency is calculated by (P * Xtal) / (M << S).

Example 500MHz: ((125<<16)|(3<<8)|(0x1)), the format is ((P<<16)|(M<<8)|(S)).

(P * Xtal) = 125*24 MHz = 3000MHz
(M << S) = 3 << 1 = 6

End result is 3000MHz / 6 = 500MHz.

That's all you need to know. Alternatively, just copy what other devs have already done. Be careful with the Lx levels when you add new ones, you need shift all the existing ones throughout the file.
I have been meaning to thank you for this, I have not seen this information elsewhere. Could you please briefly explain how to set the values in cpufreq_clkdiv? I have noticed different kernels have different values for the same frequency, and I don't know which one is correct for me.

Example:
/*
* Clock divider value for following
* { DIVCORE, DIVCOREM0, DIVCOREM1, DIVPERIPH,
* DIVATB, DIVPCLK_DBG, DIVAPLL, DIVCORE2 }
*/

Samsung source (I believe)
/* ARM L0: 1600Mhz */
{ 0, 3, 7, 0, 6, 1, 2, 0 },

Perseus:
/* ARM L0: 1600Mhz */
{ 0, 4, 7, 0, 6, 1, 7, 0 },​
 

AndreiLux

Senior Member
Jul 9, 2011
3,209
14,595
0
I have been meaning to thank you for this, I have not seen this information elsewhere. Could you please briefly explain how to set the values in cpufreq_clkdiv? I have noticed different kernels have different values for the same frequency, and I don't know which one is correct for me.

Example:
/*
* Clock divider value for following
* { DIVCORE, DIVCOREM0, DIVCOREM1, DIVPERIPH,
* DIVATB, DIVPCLK_DBG, DIVAPLL, DIVCORE2 }
*/

Samsung source (I believe)
/* ARM L0: 1600Mhz */
{ 0, 3, 7, 0, 6, 1, 2, 0 },

Perseus:
/* ARM L0: 1600Mhz */
{ 0, 4, 7, 0, 6, 1, 7, 0 },​
I don't have any exact technical explanation behind the physical CPU blocks that those auxiliary dividers are clocking.

Personally I just fired up Excel and adjusted them in to what seemed to me a reasonable curve with the rest of the frequency clocks which Samsung provided. These are the values I put in Perseus.



You could probably adjust M0 again beyond 1800 MHz to be somewhat lower.
 
  • Like
Reactions: ffolkes
Our Apps
Get our official app!
The best way to access XDA on your phone
Nav Gestures
Add swipe gestures to any Android
One Handed Mode
Eases uses one hand with your phone