Kernel Driver for Nokia Bluetooth Chips
While improving slowly, the mainline kernel’s support for smartphones is quite bad. One of the better supported phones is the Nokia N900. Apart from a few missing features, which could improve the performance of some operations (like crypto acceleration), its currently lacking support for two missing features:
- Bluetooth
- Cameras
I worked on both tasks during my master’s thesis, but in this post let’s focus on the Bluetooth module. For Bluetooth support the Nokia N900 has broadcom’s bcm2048 chip (which also supports FM radio, but that’s out of scope for this post). The module is connected via one of the SoC’s UARTs. Below is a schematic view how its interconnected with the N900’s SoC (an OMAP3430).
The Nokia kernel (which is comes together with the phone) contained a combined driver for the OMAP’s UART and Nokia’s Bluetooth module. This obviously is bad design, since it does contradict with proper device abstraction. On the other hand doing it right is not a trivial act. If a kernel driver wants to interact with a serial device so far it usually meant line disciplines were used (with the input subsystem being the exception, which may use serio).
line disciplines are a unix concept, that has been adopted by Linux. Basically
a userspace process open a tty device and attaches a line discipline (ldisc),
so that a kernel driver processes the messages. The Bluetooth subsystem currently
provides a ldisc driver for all kinds of serial attach Bluetooth chips. If your
device contains an serial attached bluetooth chip, you can load the kernel support
for it using hciattach /dev/ttyS?
. This approach has two
major disadvantages:
- Userspace interaction with device knowledge is required, despite the kernel knowing everything that is needed. So no out-of-the-box support for serial attached Bluetooth.
- The line discipline driver is not a typical kernel device, so it does not have access to resouces like GPIOs, clocks or IRQs.
The second problem is the major one, since as shown in the schematic above, the N900 bluetooth chip uses 3 GPIOs. Those must be toggled based on the data being sent over the UART interface and are essential. This was also a problem for two of the already support serial attached bluetooth chips: The intel & bcm driver register an ACPI platform device, which gets the GPIOs. Then the ldisc protocol driver try to find the associated platform device to get access to the GPIOs.
Initially I tried to mimic that behaviour with a Devicetree based platform device instead of an ACPI based one. That approach has been shut down by Greg Kroah-Hartman, since its a misuse of platform devices. Instead a proper serial device should be created. Apart from that a discussion began if serial slave devices should be referencing the master using a phandle, or if they should become a slave of the master device.
Most of that discussion happened during the last two years, but finally a solution is in sight: Rob Herring wrote a proper subsystem for serial slave devices. With that infrastructure it’s possible to write serial slave device kernel drivers, which look very similar to e.g. spi or i2c kernel drivers.
I just ported my (rewritten from scratch) nokia driver to that framework and its remarkable how much shorter it is compared to the Nokia’s original driver. My driver is currently a bit more than 800 lines of codes in a single file. Nokia’s had 2527 lines in 8 different files. The driver will also benefit from any improvements implemented in the OMAP’s UART driver and does runtime PM (the UART module is suspended while no communication is going on).