Jump to content

Mainline:Broadcom Kona/Introduction

From dissonant.dev wiki

The following page is a general introduction to the Broadcom Kona platform and getting started with mainlining.

Chip introduction

Broadcom Kona is a series of chips primarily marketed for mobile use, released between 2012 and 2013. It comprises of the following chips:

  • BCM28145/BCM28155 (Capri)
  • BCM21654 (Rhea)
  • BCM21663/BCM21664 (Hawaii)
  • BCM23550 (Java)

Capri kernel sources also mention BCM28150/BCM28160 which are codenamed Island and appear to be similar to Capri; however, they do not seem to have been included in any consumer-available hardware.

Similarily, mentions of chips codenamed Athena, Hera and Samoa appear in some kernel sources, but with no relevant kernel config options - it is unknown which SoCs, if any, they correspond to.

These chips all share similar components, with a similar internal register layout. They can be grouped into three "generations": the BCM281x5 is first, the BCM21654 is second, and the BCM2166x/BCM23550 is third.

The BCM2166x and BCM23550 are nearly identical - the BCM23550 has 4 Cortex A7 CPUs instead of 2 Cortex A9 CPUs, and an extra ISP block, but is otherwise identical to the BCM21664.

Downstream kernel

Two downstream kernels exist for these chips:

In both kernels, most of the relevant downstream drivers for the Kona platform are stored in arch/arm/plat-kona; the individual board files for each device and chip-specific info is stored in arch/arm/mach-(codename) (where (codename) is one of capri, rhea, hawaii or java).

Both of these kernels predate DTS being used for most devices; while the 3.4/3.10 kernel supports DT, and there are some DTS files, this support is very partial and it's not used on any of Samsung's phones with the relevant chips.

RDB

Other than the drivers, the kernels contain a very useful resource for reverse-engineering: the RDB (which presumably stands for "register database").

The RDB is a series of header files containing the internal register layout of all blocks on the SoC. Each SoC has its own RDB headers; they are located in arch/arm/mach-(codename)/include/mach/rdb (usually there are a few RDB directories named rdb_A, rdb_Bx - these appear to be chip revisions, and the rdb path should symlink to the latest one).

Each RDB folder contains a sysmap header (example: arch/arm/mach-java/include/mach/rdb/brcm_rdb_sysmap.h); this header contains the offsets for each block on the SoC, and a comment with the location of the relevant RDB header. This is useful for knowing the locations of blocks in register space, and for connecting a location to a register layout header.

The individual blocks each have their own RDB header, following the brcm_rdb_(name).h convention (example: arch/arm/mach-java/include/mach/rdb/brcm_rdb_khub_clk_mgr_reg.h. These headers contain the offsets and names of each register within the block, as well as the names and shifts/masks of each bit within those registers.

Porting drivers from downstream to mainline

This section contains hints for figuring out how to port a component from downstream to mainline, or debug a non-working driver.

Finding the downstream driver

Nowadays, most drivers in the Linux kernel are stored in the drivers/ folder and its subdirectories. In the case of the Kona downstream kernel, however, all platform drivers (with a handful of exceptions, like SDHCI) are stored in arch/arm/plat-kona, with some SoC-specific initialization code in the arch/arm/mach-(codename) directories.

The easiest way to find relevant info is to do a grep -iR "phrase" in the downstream kernel (which is why it's handy to have it downloaded).

Using the RDB

The aforementioned RDB can also be used for figuring stuff out; the platform drivers use register info from the RDB pretty extensively, so you may have some luck grepping for the register names.

For a quick overview of differences between downstream and mainline driver behavior, one can dump the relevant registers from downstream and mainline using devmem2 and compare the two. Combined with RDB data as documentation, this can give you a pretty good idea of what to add/modify to get the component working.

Example screenshot showing the output of generate-dump-diff.py

knuxify maintains a set of relevant reverse-engineering tools at github.com/refractionware/reveng. The most directly useful ones are:

  • tools/devmem-read-block.sh - given a start address and the offset of the last register (inclusive), dumps all of the registers.
  • generate-dump-diff.py creates a HTML representation of the diff of two dumps, which also lists names of all registers and shows you the bit names on hover. You will have to modify this file to point to your downstream kernel location; once you do, it should automatically find the relevant RDB files to parse as documentation.

Usually, the process looks something like this:

  • Open the RDB sysmap (see "RDB" section above) and locate the entries for all possibly relevant blocks (e.g. for storage: SDIO, PAD_CTRL, etc.); open the header files for those and get the offset of the last component (at the end of the file)
  • Copy devmem-read-block.sh to the device and dump the relevant registers; save the files in two separate directories, to make sure you don't mistake downstream for mainline
  • Run generate-dump-diff.py on the generated dumps and look at differences in the browser

Porting board files to DTS

New kernels use device trees to describe components. The Kona downstream kernels are too old to use it; rather, while they have some DTS support and files, they don't seem to actually be used in any of the production devices.

Instead, the relevant device info is stored in board files in arch/arm/mach-(codename) directories. These files contain the relevant setup for all componenets. There's usually a separate "board-bcm590xx" file that contains BCM590xx PMIC settings.

Note that board files contain configuration for lots of possible components that may not actually be present on your device; these are usually commented out with #ifdef statements referencing defconfig options. Make sure to have your device's defconfig handy for reference.

(todo: add more info here)

See also