Monday, September 16, 2013

DWC USB interrupt spam in Rockchip SoCs

Some time ago, when looking for answers to some USB 1.1 problems on the RK chips, like:
- USB 1.1 to Ethernet dongle not working
- Repeated or missing key presses
I stumbled upon some Raspberry Pi forums complaining about the same things.

This is logical since both the Rasp. Pi SoC and the RK3066/3188 are using the same USB HW IP cores (from DesignWare, that is DWC).

One of the problems they were reporting was an excessive number of interrupts per second coming from the USB while the system was idle (I've confirmed it, even with just a USB 1.1 keyboard attached).

One way to check this is with the console command:
vmstat 1
Looking below label "in" will tell you how many interrupts are there per second. In my case, Linux3188 kernel ( http://github.com/Galland/Linux3188 ) on a RK3188 Cozyswan S400 (kindly donated by KSK Electrics) the result is some 10600 interrupts per second.

And a way to see who is interrupting is simply to type:
cat /proc/interrupts
In my case, the "dwc_otg_hcd:usb1, dwc_otg_pcd" is the root cause for some more than 8000 interrupts per second, just as it happens to RPi guys.

The problem seems to stem from the DWC driver, as explained here:
"the Synopsys driver relies on the start of frame interrupt for scheduling transfers if "descriptor DMA" is not implemented (which it isn't, on BCM2835).  8000 is one interrupt per microframe."
and propose the use of a FIQ (ARM fast interrupt handler) for USB IRQs to discard USB microframes that contain no data. More info here...

And the FIQ enabled code lies in this repo (see commits starting in April 2013 by Gordon Hollingworth): https://github.com/ghollingworth/linux/commits/rpi-3.6.y


Testing real screen resolution on RK Linux

Problem:


You think you have a 1080p screen resolution but when you draw a non-aliased one pixel width line and move the window around, it doesn't look one solid line anymore.

You're not on 1080p, but likely on a scaled 720p (even if Linux reports 1080p).


Test:


On a console type:

cat /sys/devices/platform/rk-fb/graphics/fb0/disp_info

for a working 1080p setup, the result should be something like:

win0:enabled
xvir:960
xact:1920
yact:1080
xdsp:1920
ydsp:1080
x_st:192
y_st:41
x_scale:1.0
y_scale:1.0
format:RGB565
win1:disabled
xvir:0
xdsp:320
ydsp:240
x_st:10
y_st:10
format:ARGB888

That is xact and yact (the virtual resolution seen by Linux) must be the same as xdsp and ydsp (the real resolution been sent to the screen), or else you have a scaled output (x_scale and y_scale not 1.0).

Solution:


If this is the case and you find that xdsp=1280 and ydsp=720, whereas you expected a 1080p display, the solution is in this commit:
https://github.com/Galland/3188-SRC-AP6210/commit/130c1ad6bb47f3b2401b6156f205dcb5882255c7


BTW, notice the 16 bits color: RGB565
I couldn't tell the difference with normal desktop usage, but it means half the memory operations (32 bits ARGB888 <-> 16 bits RGB565).

Wednesday, September 11, 2013

Root Rockchip sticks/tablets from Linux

Since with every new device it becomes a nightmare (at least for me, that I seldom use Windows) to find the right Windows drivers for ADB access... I noticed that the rooting procedure (TPSparky Vondroid) relies only on the adb command and... that is readily accessible from Linux.

Hence this little guide came up as I put together the necessary little bits and has been tested with a RK3066 based tablet (RK3188 devices should also be rootable with this method, confirmed with Minix Neo X7).


1st Set up Linux ADB access to the device


This step is entirely done from the Linux PC (Ubuntu in this case) where the RK device is connected (through the USB). 

Please note that if your RK device has several USB ports, there will be only one that can be connected to the PC, usually marked as OTG or Slave.


1) Download the lightweight adb tools:
sudo apt-get install android-tools-adb
or, if you don't have Ubuntu, proceed to download and install the whole Android SDK :S


2) Open/create the following text file to let your standard user connect to the RK device:
sudo gedit /etc/udev/rules.d/51-android.rules
and then add a new line with the following text:
SUBSYSTEM=="usb", ATTR{idVendor}=="2207", MODE="0666", GROUP="plugdev"
Of course make sure that your Linux user is part of group "plugdev" with the following terminal command:
groups user

3) Force a reload of the USB access rules to get the latest one on:
sudo udevadm control --reload-rules

4) Add RK devices USB Vendor ID to what adb may expect for your currently logged user:
echo "0x2207" >> ~/.android/adb_usb.ini


2nd Set up the RK device for ADB access


Unplug the RK device from the USB and go to its Settings page to follow this steps:

1) Go to Settings->Storage and click at the top right on the three dots

2) Select USB computer connection in the dropdown

3) Select "Mass Storage" check box and go back to Settings

4) Browse down in Settings and select Security

5) In Security Settings, select "Unknown sources"

6) Back in Settings, select Developer Options

7) In Developer Options, select "USB debugging"

8) Close settings, and any other open apps.

9) Using a known good USB cable, connect the RK device to the PC, you'll get "Connecting to USB" in the notifications area in Android, and a USB icon in the notification area. You Do Not want to select "Connect to Pc to Transfer Files", in the notification menu, just plug in the cable and let it be.

PS: If you don't get a connection you may have to go back into Settings and select USB, then click on "Connect to PC".

3rd Rooting the RK device from Linux


The following steps are just a COPY of those in "TPSparkyRoot.bat" with a minor fix for correct SuperSU installation.

These are to be done on the Linux PC:

1) Download the package with the needed su, SuperSU, busybox, and RootExplorer binaries

2) Extract the package into a folder, open a terminal and cd into that folder

3) Create a new text file (i.e. "gedit script.sh") and copy the following contents:

   echo "*---* VonDroid.com RK device Root Tool based on work by sunnydavid *---*"
   echo "--- Plug in your device, make sure debugging is enabled in Developer Options"
   echo "--- This script will now copy files over to your RK device"
   
   adb shell mv /data/local/tmp /data/local/tmp.bak
   adb shell ln -s /data /data/local/tmp
   adb reboot
   
   echo "--- Reboot 1/3 - Press Enter once the device has rebooted (if USB debugging doesn't appear in the Android bar you may have to click Settings->USB->Connect to PC)"
   read -p "or CTRL-C to exit"
   
   adb shell rm /data/local.prop > nul
   adb shell "echo \"ro.kernel.qemu=1\" > /data/local.prop"
   adb reboot
   
   echo "--- Reboot 2/3 - Press Enter once the device has rebooted (if USB debugging doesn't appear in the Android bar you may have to click Settings->USB->Connect to PC)"
   read -p "or CTRL-C to exit"
   
   adb shell id
   
   echo "--- If the ID shows as 0(root) then continue, otherwise CTRL+C to cancel and start over"
   read -p "CTRL-C to exit"
   
   adb remount
   adb push su /system/bin/su
   adb shell chown root.shell /system/bin/su
   adb shell chmod 6755 /system/bin/su
   adb push busybox /system/bin/busybox
   adb shell chown root.shell /system/bin/busybox
   adb shell chmod 0755 /system/bin/busybox
   
   echo "--- Installing SuperSU"
   
   adb push SuperSU.apk /system/app/SuperSU.apk
   adb shell chown root.root /system/app/SuperSU.apk
   adb shell chmod 0644 /system/app/SuperSU.apk
   adb push RootExplorer.apk /system/app/RootExplorer.apk
   adb shell chown root.root /system/app/RootExplorer.apk
   adb shell chmod 0644 /system/app/RootExplorer.apk
   
   echo "Completing Root ..."
   
   adb shell rm /data/local.prop
   adb shell rm /data/local/tmp
   adb shell mv /data/local/tmp.bak /data/local/tmp
   adb reboot
   
   echo "--- Reboot 3/3 - Your RK device should now be rooted!"


4) Make the script executable with: 
chmod +x script.sh


5) Restart the adb server by typing:
adb kill-server; adb start-server
6) And now when typing the following terminal command:
adb devices
you should see the connected device listed (my tablet for example is named 12345678...)


7) Execute the previously created script ( ./script.sh ) and follow the steps to the letter, including patiently waiting for the potential several-minutes-long pauses

PS: After every reboot you MUST check that in the Android status bar the "USB Debugging" message appears (so that there is adb connection with the PC), or else you'll have to go back into Settings and select USB, then click on "Connect to PC". Only then you can hit Enter in the script to let it go on.


That's it, your device should be rooted, all from within Linux!



DISCLAIMER: I've followed this instructions to root my own devices without any trouble. The rooting procedure itself is simply the very widely used TPSparky method. However I take no responsibility for any mishappenings that may arise from your trying it on your devices. That is entirely yours.


References:
http://forum.xda-developers.com/showthread.php?t=1526487
http://linux-rockchip.info/mw/index.php?title=ADB_shell_with_RK3066
http://forum.xda-developers.com/showthread.php?t=2127573

Friday, July 12, 2013

Serial console mod for RK3188 stick Cozyswan S400

First of all, I would like to thank KSK Electrics for kindly donating this S400 stick (and a MK908) to support the Linux kernel porting on RK3188 devices.


A serial console for the Cozyswan S400 was needed in order to debug the boot problems encountered with the RK3188 kernel source "freed" by Andy from Rikomagic.

Also, since this kernel removed support for the framebuffer console (the text you [should] see on screen at boot, or in text Linux, before installing any XFCE/Gnome/...), the serial console is the only way to see what's happening when there is something wrong.

Fortunately I was able to successfully backport the framebuffer console so that now text is back on screen for Linux!

In any case here is the mod to get the serial console pins, thanks to Alok Sinha, who found those pads to be the serial output. They looked to me so much like an IR tx/rx connector that I would have tested every other pad before trying those! :)

Left to Right: The R (RX) pad for receiving keystrokes, the T (TX) pad for sending to your
Serial2USB module the text, and the required G (Ground) 

Actually only TX and Gnd are needed to receive the boot text, so I usually solder just those two.


The pads are small, with a tiny bit of solder on the iron tip and
another tiny bit on the cable, you should get good results

Omegamoon, who did the MK808 (RK3066) and MK908 (RK3188) sticks' serial console mods, recommends this nice Serial2USB module.


The three clams, as I call them

You can find here the Serial mod instructions for the Measy U2C RK3066 stick.

I hope it helps!

Tuesday, June 18, 2013

Full RK3066 Technical Reference Manual found!

Thanks to Omegamoon, who found it, here is the full RK3066 Technical Reference Manual, 1142 pages and 26MB of completely necessary data for opensource development on this platform.

https://www.dropbox.com/s/80ubbvgou4g3bmk/Rockchip%20RK30xx%20TRM%20V2.0.pdf

It is the same file found in chinese websites and named as "Rockchip RK30xx TRM V2.0.pdf"

And here is the full folder shared with more RK29 and RK30 documents:

https://www.dropbox.com/sh/pycam3nl5bahwjt/WkfqGz6BVp

Enjoy!

Monday, June 17, 2013

Measy U2C HW serial console pins

A hardware serial console is a little module soldered to at least two pin pads of a CPU (in this case the RK3066 of the Measy U2C stick) in order to transmit to a PC the stick's boot log sequence happening long before the screen turns on.

Naturally, if a kernel (like the latest one) refuses to boot and does not even get to turn on the screen, the only way to debug the reason is to use the serial console.

With the indications and the useful blogpost (for MK808) of fellow developer Omegamoon, I set out to find the two pins necessary to watch in my PC the boot sequence, that is:

- TXD: the pin where the CPU outputs the console text
- Ground: the necessary reference for the electrical levels in TXD

These had to be connected to the RXD and GND pins, respectively, of a hardware serial-to-USB module, that is then plugged to a PC's USB port. If anybody wonders about the CPU's RXD pin, it is not necessary unless you want to send commands to the stick once it's booted.

In the PC I myself use Ubuntu's CuteCom console app, connecting to serial port /dev/ttyUSB0 at 115200 bauds 8 bits data, 1 bit stop, no parity, and no handshake.


The way in which I found the RK3066's TXD pin was by trial and error. But since I saw there were small circular pads around the same area where Omegamoon had found his stick's TXD/RXD, I supposed mine should be close.

Hence, I first soldered the ground cable to the micro USB port on top of the RK3066 CPU and started very carefully making the serial-to-USB module's RXD pin's cable touch the different pads while powering on the stick, until I found the one that was transmitting data: TXD and proceeded to solder the cable and make the smallest possible hole in the Measy U2C's enclosure to get the two cables out of it while closed.

For reference, these are the places where the cables to the serial-to-USB are soldered
TXD pad of RK3066 (to RXD on serial-to-USB) and GROUND on the Micro USB connector

The TXD pad looks tiny but with a bit of care and a little bit of solder tin on the cable tip and the solder tip, you'll get good results.


Saturday, June 15, 2013

Linux on RK3188 work in progress

Please note this is not a blog post, it's a my personal pastebin where I can put in writing to myself and other fellow developers the small things I find in the latest 3.0.36 kernel that supports rk3188 devices.



MALI and CONFIG_SYNC ( sync_fence_cancel_async )

Talking about Omegamoon's codebase (but with backported drivers folder from my previous one)

Once MALI is configured in as:

CONFIG_DRM=m
CONFIG_DRM_MALI=m
# CONFIG_ION is not set
CONFIG_MALI=y
CONFIG_MALI400=m
# CONFIG_MALI400_DEBUG is not set
# CONFIG_MALI400_PROFILING is not set
CONFIG_MALI400_UMP=y
CONFIG_UMP=m
# CONFIG_UMP_DEBUG is not set

And /include/drm/drm.h is backported to rk3x's version, that is, the first:
#if defined(__linux__)
becomes:
#if defined(__KERNEL__) || defined(__linux__)

Then compiling throws this new error:
drivers/gpu/mali/mali/common/mali_kernel_core.c:1084:4: error: implicit declaration of function 'sync_fence_cancel_async'

That function is called because now CONFIG_SYNC is forced by PLAT_RK and should be implemented in /drivers/base/sync.c (see http://lists.linaro.org/pipermail/linaro-mm-sig/2012-June/002050.html) but it's missing.
Hence, since MALI has worked without CONFIG_SYNC and a quick grep of the codebase shows it's the only driver talking about CONFIG_SYNC, my fix for this is removing the dependence with PLAT_RK by going to /arch/arm/Kconfig
and in the config for PLAT_RK commenting the following lines:

# select SYNC
# select SW_SYNC
# select SW_SYNC_USER


and then in the .config removing:

CONFIG_SYNC=y
CONFIG_SW_SYNC=y
CONFIG_SW_SYNC_USER=y


Also had to add this line at the top of /drivers/video/rockchip/rk_fb.c due to missing references to 'GET_UMP_SECURE_ID_BUF2':

#include "mali_def.h"