User:CesarB/cpufreq

From Openmoko

< User:CesarB(Difference between revisions)
Jump to: navigation, search
(2008-01-22: gsmd (serial) test)
(link to ML post)
 
(13 intermediate revisions by one user not shown)
Line 5: Line 5:
 
This project aims to implement the cpufreq driver (which manages the CPU frequency transitions) and a cpufreq notifier for all the affected drivers (to do two things: quiesce the device before the change, and adjust the frequency after the change). Deciding which frequency to use is the responsability of code from somewhere else (either cpufreq governors or userspace).
 
This project aims to implement the cpufreq driver (which manages the CPU frequency transitions) and a cpufreq notifier for all the affected drivers (to do two things: quiesce the device before the change, and adjust the frequency after the change). Deciding which frequency to use is the responsability of code from somewhere else (either cpufreq governors or userspace).
  
The most recent version of the code can be found at http://repo.or.cz/w/linux-2.6/s3c2410-cpufreq.git on the branches s3c2410-cpufreq (for code which applies on top of the upstream "git HEAD" kernel) and s3c2410-cpufreq-gta01 (for code which applies on top of the OpenMoko patched kernel).
+
The most recent version of the code can be found at http://repo.or.cz/w/linux-2.6/s3c2410-cpufreq.git on the s3c2410-cpufreq-om branch.
  
 
== To build ==
 
== To build ==
  
{{note|Do not run on real hardware, unless you '''''really''''' know what you are doing. This code is completely untested. It might even not compile.}}
+
{{note|Do not run on real hardware, unless you '''''really''''' know what you are doing. This code is mostly untested, and changes frequently. It might even not compile.}}
  
 
You need a fully built OpenMoko tree for the cross-compiler and uboot tools.
 
You need a fully built OpenMoko tree for the cross-compiler and uboot tools.
  
# Checkout the s3c2410-cpufreq-gta01 branch
+
# Checkout the s3c2410-cpufreq-om branch (or the wip branch for work in progress)
 
# Copy the defconfig file from branches/src/target/kernel/2.6.24.x/config on the OpenMoko svn as the <code>.config</code> file
 
# Copy the defconfig file from branches/src/target/kernel/2.6.24.x/config on the OpenMoko svn as the <code>.config</code> file
 
# Set the PATH to the correct value (check the run.* temporary files bitbake generates to find out the correct value)
 
# Set the PATH to the correct value (check the run.* temporary files bitbake generates to find out the correct value)
Line 23: Line 23:
  
 
* Enable <code>CONFIG_CPU_FREQ_DEBUG</code> and add <code>cpufreq.debug=7</code> to the kernel command line to enable the relevant debug output. You can also enable it after boot by going to the correct place at /sys/modules and changing the values there.
 
* Enable <code>CONFIG_CPU_FREQ_DEBUG</code> and add <code>cpufreq.debug=7</code> to the kernel command line to enable the relevant debug output. You can also enable it after boot by going to the correct place at /sys/modules and changing the values there.
* To test on 2.6.22.5, use <code>git format-patch -o ''dir'' master..s3c2410-cpufreq</code> to generate a set of patches, and apply them all on top of the OpenMoko patches 2.6.22.5 kernel, ''except'' the framebuffer patch(es) (the 2.6.24.x code for the framebuffer is different from the 2.6.22.5 one).
+
* Do not compile the cpufreq driver as a module, since several of the notifiers depend on functions defined in it and would thus end up being compiled as modules too.
 +
* To test on 2.6.22.5, use <code>git format-patch -o ''dir'' master-om..s3c2410-cpufreq-om</code> to generate a set of patches, and apply them all on top of the OpenMoko patches 2.6.22.5 kernel, ''except'' the framebuffer patch(es) (the 2.6.24.x code for the framebuffer is different from the 2.6.22.5 one).
 +
* When trying for the first time, it's best to start slow:
 +
*# Do all the tests without the USB cable (disconnect before changing the governor/frequencies), since it misbehaves (will be later changed to prohibit changing frequencies when the cable is connected). It's best to also remove the SD card and SIM, just in case.
 +
*# Boot with <code>cpufreq.debug=7</code> on the kernel command line and carefully inspect the kernel output for any incorrect output.
 +
*# Disable the cpufreq printk rate limit (<code>cpufreq.debug_ratelimit=0</code>; it can be set via <code>/sys/modules/cpufreq/parameters</code>).
 +
*# Set the governor to <code>userspace</code> and switch to the second highest frequency. Check the kernel output again (be on the lookout in particular for frequency mismatch messages from the cpufreq core).
 +
*# Work down the list of frequencies and check if they all work correctly (not all can be selected since the drivers reject some of them).
 +
*# Edit the code to disable the policy rejection of frequencies (returning at the top of <code>s3c2410_cpufreq_adjust_table</code> and <code>s3c2410_cpufreq_adjust_pin</code> should be enough) to be able to test all frequencies. Start again from the top of the list; watch in particular for the SLOW mode ones (12000 and below). There's no need to go all the way down to 1000; all SLOW mode ones should work the same, and it's very annoying. Test going back from SLOW mode to the lowest non-SLOW frequency, and jumping from SLOW mode to the maximum frequency (this last case can cause misterious crashes if the registers were set out of order, causing the bus to go too fast).
 +
*# Revert the changes made to the code above.
 +
*# Try the <code>conservative</code> governor.
 +
*# Try the <code>ondemand</code> governor (it's the one which stresses the most the cpufreq mechanism).
  
 
== What's already done ==
 
== What's already done ==
 +
 +
{| border="1"
 +
|-
 +
! Driver !! Status (GTA01) !! Status (GTA02)
 +
|-
 +
| core || Working || '''Untested'''
 +
|-
 +
| timer || Working || '''Untested'''
 +
|-
 +
| nand || Working || '''Untested'''
 +
|-
 +
| serial || Working || '''Untested'''
 +
|-
 +
| framebuffer || Working || '''Untested'''
 +
|}
  
 
=== S3C2410A cpufreq driver ===
 
=== S3C2410A cpufreq driver ===
Line 45: Line 71:
 
=== Framebuffer driver ===
 
=== Framebuffer driver ===
  
The cpufreq notifier on <code>drivers/video/s3c2410fb.c</code> is responsible for turning off the video before the frequency change and reloading its configuration after the frequency change.
+
The cpufreq notifier on <code>drivers/video/s3c2410fb.c</code> is responsible for dynamically changing the frequency divider used to derive the video clocks.
  
 
=== NAND driver ===
 
=== NAND driver ===
Line 52: Line 78:
  
 
== What's missing ==
 
== What's missing ==
 
=== S3C2410A cpufreq driver ===
 
 
The frequency table should be checked for better divisor values (1:1:1 might be appropriate in more situations), and the code should be able to deal with HDIVN1 and different bus modes.
 
 
=== Timer 4 driver ===
 
 
The cpufreq notifier should perhaps use a higher priority, so as to run before all the others for more precise timekeeping.
 
 
=== NAND driver ===
 
 
The cpufreq notifier should make sure the NAND is quiesced before the frequency change, or change the timings to the most conservative ones before the frequency change.
 
  
 
=== Missing drivers ===
 
=== Missing drivers ===
Line 74: Line 88:
 
* SPI
 
* SPI
  
=== Frequency restrictions ===
+
== Frequency restrictions ==
  
 
Some drivers need specific frequencies. Currently there's no way to tell the cpufreq core of that, but at minimum a cpufreq notifier should be used to turn them off if they won't be able to work with that frequency.
 
Some drivers need specific frequencies. Currently there's no way to tell the cpufreq core of that, but at minimum a cpufreq notifier should be used to turn them off if they won't be able to work with that frequency.
Line 81: Line 95:
 
* When using the IIS device, changing the frequency might not be a good idea, since it can cause audio glitches. It also probably needs a minimum frequency depending on the output audio frequency and sample size.
 
* When using the IIS device, changing the frequency might not be a good idea, since it can cause audio glitches. It also probably needs a minimum frequency depending on the output audio frequency and sample size.
 
* The LCD device might also need a minimum frequency.
 
* The LCD device might also need a minimum frequency.
 +
* The serial baudrate generator might not have a good enough divider value for some baud rates and some clock frequencies (for instance, 115200 at 12000 kHz)
  
== Testing report ==
+
== See also ==
  
=== 2008-01-19 ===
+
* [[Neo1973 GTA01 Power Management]]
  
[http://lists.openmoko.org/pipermail/openmoko-kernel/2008-January/000452.html 2.6.24.x doesn't boot on GTA01]. I hand-extracted the patches and applied them all on top of GTA01's 2.6.22.5 kernel, except for the framebuffer patch (which depends on some changes made after 2.6.24). It was booted on a GTA01 without the SD card or the SIM attached (just in case). The results were:
+
== External links ==
  
* Setting to 202800 kHz: lost the USB connection. It would be recovered only after rebooting (setting the frequency back to 266000 wasn't enough). The rest of the tests were made with the on-screen terminal.
+
* [http://lists.openmoko.org/pipermail/openmoko-kernel/2008-February/001021.html Experimental S3C2410A cpufreq driver] (2008-02-12)
* Setting to 133000 kHz (actually 135000 kHz): noticeable flicker, possibly because the framebuffer patch wasn't applied. The timer seems to be running at exactly half the correct rate (running "date" twice with 10s delay showed the GTA01's clock advanced only 5s).
+
* Rebooting (after coming back to 266000 kHz) fixed the USB connection.
+
 
+
=== 2008-01-20 ===
+
 
+
Same 2.6.22.5 kernel, with several bugfixes applied (in particular, the problem which prevented the timer notifier from running was fixed).
+
 
+
This time, the whole test was done from the terminal, to avoid the USB lockup.
+
 
+
* Setting to 133000 kHz (actually 135000 kHz): same flicker. Plugging briefly the USB shows it to still be alive. Time runs at the correct speed.
+
* Setting to 100000 kHz (actually 101250 kHz): even worse flicker.
+
* Setting to 12000 kHz (SLOW mode on): the flicker gets psychedelic (colors start oscillating). VERY slow (taking about a second to register a "key" press).
+
* Back to 266000 kHz: works normally. Plugging briefly the USB again shows it to still be alive. Time still running at correct speed.
+
 
+
=== 2008-01-22 ===
+
 
+
After a few more bugfixes, still 2.6.22.5, also tested from the terminal (untethered).
+
 
+
This time, due to the nature of the tests, I commented out all speeds below 12000 kHz.
+
 
+
* Setting governor to "conservative": works, and the flicker patterns shows neatly the change of operating frequencies.
+
* Setting governor to "ondemand": works, however after a few seconds on 12000 kHz it got "stuck" there. For some reason, <code>cat scaling_cur_speed</code> locked up (not answering to Ctrl-C/Ctrl-Z); requested a shutdown via the power menu, which worked (still with the severe flicker showing it was still at 12000 kHz.
+
 
+
Another test was to see if gsmd still worked.
+
 
+
* With "conservative": timeout.
+
* With "userspace", testing by changing the frequency and typing "at" at <code>libgsmd-tool -m atcmd</code> and checking for the response: worked at 266000, 133000, 66000, 33000, and ''failed'' at 12000 (timeout).
+
 
+
== See also ==
+
 
+
* [[Neo1973 GTA01 Power Management]]
+

Latest revision as of 02:27, 13 February 2008

The cpufreq subsystem is a Linux kernel subsystem responsible for managing the CPU frequency. It's commonly used in laptops to reduce power usage when idle.

On the S3C2410, adjusting the CPU frequency changes the clocks for almost all devices on the chip. This means that, to write a cpufreq driver for the S3C2410, you have to also adjust some values on almost all devices.

This project aims to implement the cpufreq driver (which manages the CPU frequency transitions) and a cpufreq notifier for all the affected drivers (to do two things: quiesce the device before the change, and adjust the frequency after the change). Deciding which frequency to use is the responsability of code from somewhere else (either cpufreq governors or userspace).

The most recent version of the code can be found at http://repo.or.cz/w/linux-2.6/s3c2410-cpufreq.git on the s3c2410-cpufreq-om branch.

Contents

[edit] To build

NOTE: Do not run on real hardware, unless you really know what you are doing. This code is mostly untested, and changes frequently. It might even not compile.


You need a fully built OpenMoko tree for the cross-compiler and uboot tools.

  1. Checkout the s3c2410-cpufreq-om branch (or the wip branch for work in progress)
  2. Copy the defconfig file from branches/src/target/kernel/2.6.24.x/config on the OpenMoko svn as the .config file
  3. Set the PATH to the correct value (check the run.* temporary files bitbake generates to find out the correct value)
  4. Run make ARCH=arm CROSS_COMPILE=arm-angstrom-linux-gnueabi- oldconfig and answer correctly the questions
  5. Run make ARCH=arm CROSS_COMPILE=arm-angstrom-linux-gnueabi- uImage
  6. The last line of the output tells you the correct file which should be flashed on the emulator.

[edit] Hints

  • Enable CONFIG_CPU_FREQ_DEBUG and add cpufreq.debug=7 to the kernel command line to enable the relevant debug output. You can also enable it after boot by going to the correct place at /sys/modules and changing the values there.
  • Do not compile the cpufreq driver as a module, since several of the notifiers depend on functions defined in it and would thus end up being compiled as modules too.
  • To test on 2.6.22.5, use git format-patch -o dir master-om..s3c2410-cpufreq-om to generate a set of patches, and apply them all on top of the OpenMoko patches 2.6.22.5 kernel, except the framebuffer patch(es) (the 2.6.24.x code for the framebuffer is different from the 2.6.22.5 one).
  • When trying for the first time, it's best to start slow:
    1. Do all the tests without the USB cable (disconnect before changing the governor/frequencies), since it misbehaves (will be later changed to prohibit changing frequencies when the cable is connected). It's best to also remove the SD card and SIM, just in case.
    2. Boot with cpufreq.debug=7 on the kernel command line and carefully inspect the kernel output for any incorrect output.
    3. Disable the cpufreq printk rate limit (cpufreq.debug_ratelimit=0; it can be set via /sys/modules/cpufreq/parameters).
    4. Set the governor to userspace and switch to the second highest frequency. Check the kernel output again (be on the lookout in particular for frequency mismatch messages from the cpufreq core).
    5. Work down the list of frequencies and check if they all work correctly (not all can be selected since the drivers reject some of them).
    6. Edit the code to disable the policy rejection of frequencies (returning at the top of s3c2410_cpufreq_adjust_table and s3c2410_cpufreq_adjust_pin should be enough) to be able to test all frequencies. Start again from the top of the list; watch in particular for the SLOW mode ones (12000 and below). There's no need to go all the way down to 1000; all SLOW mode ones should work the same, and it's very annoying. Test going back from SLOW mode to the lowest non-SLOW frequency, and jumping from SLOW mode to the maximum frequency (this last case can cause misterious crashes if the registers were set out of order, causing the bus to go too fast).
    7. Revert the changes made to the code above.
    8. Try the conservative governor.
    9. Try the ondemand governor (it's the one which stresses the most the cpufreq mechanism).

[edit] What's already done

Driver Status (GTA01) Status (GTA02)
core Working Untested
timer Working Untested
nand Working Untested
serial Working Untested
framebuffer Working Untested

[edit] S3C2410A cpufreq driver

This code resides on arch/arm/mach-s3c2410/s3c2410-cpufreq.c and is responsible for actually changing the frequency.

The list of available frequencies and their parameters (HCLK/PCLK dividers) can be found on this file.

[edit] Timer 4 driver

Timer 4 is used by the kernel as the periodic tick timer. The cpufreq notifier on arch/arm/plat-s3c24xx/time.c is responsible for adjusting the current and reload values of the timer to match the new frequency.

[edit] Serial driver

The cpufreq notifier on drivers/serial/s3c2410.c is responsible for (if possible) pausing both sides of the serial transmission before the frequency change and reloading the baud generator (and unpausing the serial transmission) after the change.

Pausing the transmission is currently only possible with hardware flow control. Since both serial ports on GTA01 use hardware flow control, that's not a problem (unless you are using the serial console).

[edit] Framebuffer driver

The cpufreq notifier on drivers/video/s3c2410fb.c is responsible for dynamically changing the frequency divider used to derive the video clocks.

[edit] NAND driver

The cpufreq notifier on drivers/mtd/nand/s3c2410.c is responsible for reprogramming the NAND timings after a frequency change.

[edit] What's missing

[edit] Missing drivers

  • Backlight (uses a PWM timer; not a problem with full brightness)
  • Vibrator (uses a PWM timer)
  • MMC/SD (can be avoided by not plugging it in)
  • I2C (without a notifier and booting at the maximum speed, it can only get slower; there should be no side effects, since there's no minimum bus speed)
  • IIS
  • SPI

[edit] Frequency restrictions

Some drivers need specific frequencies. Currently there's no way to tell the cpufreq core of that, but at minimum a cpufreq notifier should be used to turn them off if they won't be able to work with that frequency.

  • The datasheet says the USB device gets unstable if the frequency is below a minimum value
  • When using the IIS device, changing the frequency might not be a good idea, since it can cause audio glitches. It also probably needs a minimum frequency depending on the output audio frequency and sample size.
  • The LCD device might also need a minimum frequency.
  • The serial baudrate generator might not have a good enough divider value for some baud rates and some clock frequencies (for instance, 115200 at 12000 kHz)

[edit] See also

[edit] External links

Personal tools

The cpufreq subsystem is a Linux kernel subsystem responsible for managing the CPU frequency. It's commonly used in laptops to reduce power usage when idle.

On the S3C2410, adjusting the CPU frequency changes the clocks for almost all devices on the chip. This means that, to write a cpufreq driver for the S3C2410, you have to also adjust some values on almost all devices.

This project aims to implement the cpufreq driver (which manages the CPU frequency transitions) and a cpufreq notifier for all the affected drivers (to do two things: quiesce the device before the change, and adjust the frequency after the change). Deciding which frequency to use is the responsability of code from somewhere else (either cpufreq governors or userspace).

The most recent version of the code can be found at http://repo.or.cz/w/linux-2.6/s3c2410-cpufreq.git on the branches s3c2410-cpufreq (for code which applies on top of the upstream "git HEAD" kernel) and s3c2410-cpufreq-gta01 (for code which applies on top of the OpenMoko patched kernel).

To build

NOTE: Do not run on real hardware, unless you really know what you are doing. This code is completely untested. It might even not compile.


You need a fully built OpenMoko tree for the cross-compiler and uboot tools.

  1. Checkout the s3c2410-cpufreq-gta01 branch
  2. Copy the defconfig file from branches/src/target/kernel/2.6.24.x/config on the OpenMoko svn as the .config file
  3. Set the PATH to the correct value (check the run.* temporary files bitbake generates to find out the correct value)
  4. Run make ARCH=arm CROSS_COMPILE=arm-angstrom-linux-gnueabi- oldconfig and answer correctly the questions
  5. Run make ARCH=arm CROSS_COMPILE=arm-angstrom-linux-gnueabi- uImage
  6. The last line of the output tells you the correct file which should be flashed on the emulator.

Hints

  • Enable CONFIG_CPU_FREQ_DEBUG and add cpufreq.debug=7 to the kernel command line to enable the relevant debug output. You can also enable it after boot by going to the correct place at /sys/modules and changing the values there.
  • To test on 2.6.22.5, use git format-patch -o dir master..s3c2410-cpufreq to generate a set of patches, and apply them all on top of the OpenMoko patches 2.6.22.5 kernel, except the framebuffer patch(es) (the 2.6.24.x code for the framebuffer is different from the 2.6.22.5 one).

What's already done

S3C2410A cpufreq driver

This code resides on arch/arm/mach-s3c2410/s3c2410-cpufreq.c and is responsible for actually changing the frequency.

The list of available frequencies and their parameters (HCLK/PCLK dividers) can be found on this file.

Timer 4 driver

Timer 4 is used by the kernel as the periodic tick timer. The cpufreq notifier on arch/arm/plat-s3c24xx/time.c is responsible for adjusting the current and reload values of the timer to match the new frequency.

Serial driver

The cpufreq notifier on drivers/serial/s3c2410.c is responsible for (if possible) pausing both sides of the serial transmission before the frequency change and reloading the baud generator (and unpausing the serial transmission) after the change.

Pausing the transmission is currently only possible with hardware flow control. Since both serial ports on GTA01 use hardware flow control, that's not a problem (unless you are using the serial console).

Framebuffer driver

The cpufreq notifier on drivers/video/s3c2410fb.c is responsible for turning off the video before the frequency change and reloading its configuration after the frequency change.

NAND driver

The cpufreq notifier on drivers/mtd/nand/s3c2410.c is responsible for reprogramming the NAND timings after a frequency change.

What's missing

S3C2410A cpufreq driver

The frequency table should be checked for better divisor values (1:1:1 might be appropriate in more situations), and the code should be able to deal with HDIVN1 and different bus modes.

Timer 4 driver

The cpufreq notifier should perhaps use a higher priority, so as to run before all the others for more precise timekeeping.

NAND driver

The cpufreq notifier should make sure the NAND is quiesced before the frequency change, or change the timings to the most conservative ones before the frequency change.

Missing drivers

  • Backlight (uses a PWM timer; not a problem with full brightness)
  • Vibrator (uses a PWM timer)
  • MMC/SD (can be avoided by not plugging it in)
  • I2C (without a notifier and booting at the maximum speed, it can only get slower; there should be no side effects, since there's no minimum bus speed)
  • IIS
  • SPI

Frequency restrictions

Some drivers need specific frequencies. Currently there's no way to tell the cpufreq core of that, but at minimum a cpufreq notifier should be used to turn them off if they won't be able to work with that frequency.

  • The datasheet says the USB device gets unstable if the frequency is below a minimum value
  • When using the IIS device, changing the frequency might not be a good idea, since it can cause audio glitches. It also probably needs a minimum frequency depending on the output audio frequency and sample size.
  • The LCD device might also need a minimum frequency.

Testing report

2008-01-19

2.6.24.x doesn't boot on GTA01. I hand-extracted the patches and applied them all on top of GTA01's 2.6.22.5 kernel, except for the framebuffer patch (which depends on some changes made after 2.6.24). It was booted on a GTA01 without the SD card or the SIM attached (just in case). The results were:

  • Setting to 202800 kHz: lost the USB connection. It would be recovered only after rebooting (setting the frequency back to 266000 wasn't enough). The rest of the tests were made with the on-screen terminal.
  • Setting to 133000 kHz (actually 135000 kHz): noticeable flicker, possibly because the framebuffer patch wasn't applied. The timer seems to be running at exactly half the correct rate (running "date" twice with 10s delay showed the GTA01's clock advanced only 5s).
  • Rebooting (after coming back to 266000 kHz) fixed the USB connection.

2008-01-20

Same 2.6.22.5 kernel, with several bugfixes applied (in particular, the problem which prevented the timer notifier from running was fixed).

This time, the whole test was done from the terminal, to avoid the USB lockup.

  • Setting to 133000 kHz (actually 135000 kHz): same flicker. Plugging briefly the USB shows it to still be alive. Time runs at the correct speed.
  • Setting to 100000 kHz (actually 101250 kHz): even worse flicker.
  • Setting to 12000 kHz (SLOW mode on): the flicker gets psychedelic (colors start oscillating). VERY slow (taking about a second to register a "key" press).
  • Back to 266000 kHz: works normally. Plugging briefly the USB again shows it to still be alive. Time still running at correct speed.

2008-01-22

After a few more bugfixes, still 2.6.22.5, also tested from the terminal (untethered).

This time, due to the nature of the tests, I commented out all speeds below 12000 kHz.

  • Setting governor to "conservative": works, and the flicker patterns shows neatly the change of operating frequencies.
  • Setting governor to "ondemand": works, however after a few seconds on 12000 kHz it got "stuck" there. For some reason, cat scaling_cur_speed locked up (not answering to Ctrl-C/Ctrl-Z); requested a shutdown via the power menu, which worked (still with the severe flicker showing it was still at 12000 kHz.

Another test was to see if gsmd still worked.

  • With "conservative": timeout.
  • With "userspace", testing by changing the frequency and typing "at" at libgsmd-tool -m atcmd and checking for the response: worked at 266000, 133000, 66000, 33000, and failed at 12000 (timeout).

See also