Kernel

Building a Linux kernel for this board has been a painful process, as usual.

The difficulty is that the code is imperfect and complex to configure, and the people who know how it is supposed to work don't make themselves very accessible; Freescale's designated forum for this board is http://imxcommunity.org/, but Freescale's own engineers don't post there or anywhere else that I have found. If it doesn't work "out of the box", you're faced with lots of guesswork, trial-end-error, and trying to follow complex paths through mysterious code.

Native build

I'm building natively. I have had more bad than good experiences with cross-compilation (or rather, the pain of building and setting up the tools for cross-compilation) recently, and this will be a good way to see what the performance of this board is like.

I installed ccache in the hope that it might make things faster; in fact, it seems to have a hit rate of about 10% so overall it might be making things slower.

How-Not-To: Linaro kernels

My first attempt was to build a kernel from Linaro's sources; a "Developers and Community Build" of their version 11.05 was said to be available for this platform. But it turns out that it doesn't support some fairly basic things like SATA.

It took me longer than it should to work this out because the first few builds didn't start at all. I discovered eventually that they had the "always use default kernel command line" config setting set, and the default included something that made the console not work. Once I had fixed that, it became obvious that it knew nothing about SATA and indeed the driver is missing from the source.

It would be great to know what Linaro's intentions are, but whatever work they are doing with Freescale is happening in private. As I now understand it, Freescale's kernel drivers are all GPLed. It looks to me as if some of these drivers are eventually making it into mainline, perhaps due to work by Linaro. You might imagine that Linaro's kernel distribution would include some of the Freescale code that has not yet made it to mainline - but that doesn't seem to be the case. If this is true, I don't see what the Linaro kernels are for.

The Freescale kernel source

Freescale does have a public git repository; however, they keep this very well hidden, and it's not mentioned in any of the board documentation or websites. So my first attempts were based on downloads from the Freescale website (which requires registration and a click-through license agreement, which I haven't read).

L2.6.35_11.01.00_ER_source_bundle.tar.gz is a 744 MB file; inside there are 3 nested tar.gz files, of which one is L2.6.35_11.01.00_ER_source.tar.gz, and inside that there are dozens of tar.bz2 files, one of which is linux-2.6.35.3.tar.bz2 and another is linux-2.6.35.3-imx_11.01.00.bz2! How does one unpack a triple-tar? With pipes and -O:

tar xzf L2.6.35_11.01.00_ER_source_bundle.tar.gz -O L2.6.35_11.01.00_ER_source.tar.gz |
    tar xz -O L2.6.35_11.01.00_ER_source/pkgs/linux-2.6.35.3.tar.bz2 |
    tar xj

Total size of those two tar files: 75 MB. This is actually so bad that it's funny.

There is also some useful-looking PDF documentation in there, including the "i.MX53 START Linux User's Guide", which has a section "How to Build U-Boot and Kernel in Standalone Environment". This suggests that it should be possible to do a regular kernel compile using this source. But it seems to me that this linux-2.6.35.3.tar.bz2 is a vanilla kernel, and linux-2.6.35.3-imx_11.01.00.bz2 is a (misnamed) tar file full of patches that need to be applied first. I won't go into details since git made this unnecessary (see below).

Freescale's git repository

This can be found at http://opensource.freescale.com/git?p=imx/linux-2.6-imx.git. At first glance it might appear to contain kernels up to 3.1, but apparently everything newer than 2.6.38 is missing the i.MX53-specific stuff.

I tried to build a 2.6.38 kernel but hit two problems: after a weekend of trying I failed to get sound to work, perhaps because I didn't hit upon the right config settings, and there was a problem with the console UART. It seems that the clock generators are initialised by U-Boot, but bizarrely the different versions of U-Boot on the microSD cards shipped by Freescale do this in different ways. So if you have a U-Boot that works with the 2.6.35 kernel, it will not work with a 2.6.38 kernel, or vice-versa. The symptom of having the wrong versions is garbage output.

This obviously makes kernel development rather difficult, since it becomes impossible to use the bootloader interactively to choose which kernel to boot. One suggestion is to have different microSD cards with different versions of U-Boot on them - though this works less well once your board is inside a box.

Update: A patch to make newer kernels work with the older U-Boots has been posted in this thread.

In the end I reverted to what Freescale call 2.6.35_11.01.00, which is the same as the board shipped with and so is compatible with its U-Boot. This is frustrating because it means I won't easily be able to incorporate new features from future kernels, but frankly 2.6.38 is still not cutting-edge so that doesn't really matter much. This does pretty much summarise the situation that embedded kernel users find themselves in: it is excruciatingly difficult and tedious to make a kernel that works, and once you have got one it is sensible to stick with it if at all possible.

Configuring the kernel

My most recent kernel config can be found at http://svn.chezphil.org/tvcomputer/trunk/kernel-config-2.6.35.

Patches

Here are the patches that I have applied to this kernel:

Add accept4 syscall
This system call is needed by the Debian user-space, but was added to the kernel after 2.6.35. The patch is trivial.
Return ERESTARTSYS from IPU_GET_EVENT
This fixes a fairly obvious bug in Freescale's IPU driver, which causes it to return the wrong error code if a signal occurs (e.g. a timer) while waiting for the IPU interrupt.
Sanitise ipu interrupt return value, and loop waiting for interrupt
This is a further change to the same code in IPU driver to be sure that a sensible value is always returned, and to wait for the interrupt more than once if necessary.
Add SW_MICROPHONE_INSERT input event for MIC_DET_B GPIO
The microphone plug detect was previously unused; this patch connects it up like the user-buttons to generate an input event.
Add BBC test card bootup image
This patch adds an additional boot logo option for a BBC Test Card. The patch doesn't include the image itself, which is here and should be gunzipped and installed at drivers/video/logo/logo_testcard_clut224.ppm.