Wednesday, January 15, 2014

I2c Bus Interface

I2C bus interface

I2C is a multi-master serial single-ended bus invented by Philips that is used to attach low-speed peripherals to an embedded system. SMBus, defined by Intel in 1995, is a subset of I2C. This article is a practical guide to use the I2C bus on the Acme Systems Linux embedded boards

To have a more in depth idea of how the I2C works under Linux please read the Linux Kernel documentation on:

Using i2c-tools

The faster way to do the first experiments with this board is by installing and using the i2c-tools.
i2c-tools is a package contains a heterogeneous set of I2C tools for Linux such as:
  • a bus probing tool
  • a chip dumper
  • a register-level access helpers
  • an EEPROM decoding scripts
  • ...and more
To install i2c-tools on the FOX Board just type:
debarm:~# apt-get update
debarm:~# apt-get install i2c-tools

Using i2cdetect

i2cdetect is an userspace program to scan an I2C bus for devices. It outputs a table with the list of detected devices on the specified bus.
Example:
debarm:~# i2cdetect -y 0 
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f                             
00:          -- -- -- -- -- -- -- -- -- -- -- -- --                             
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --                             
20: 20 -- -- -- -- -- -- -- -- -- -- -- -- -- -- --                             
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --                             
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --                             
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --                             
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --                             
70: -- -- -- -- -- -- -- --                                                     
In this case a device has been detected on address 20 hex.

Using i2cset

i2cset is a small helper program to set registers visible through the I2C bus.
The following simple command writes the byte value 255 to the I2C device at address 20 hex on the i2c bus 0 (/dev/i2c-0).
debarm:~# i2cset -y 0 0x20 255
If for example you are using a DAISY-22 module with a PCF8574 I2C I/O expander this command will set all the GPIO lines to 1.

Python code example

python-smbus is a Python module allows SMBus access through the I2C /dev interface on Linux hosts. The host kernel must have I2C support, I2C device interface support, and a bus adapter driver.
The following example sends a sequence of values from 0 to 255 to the PCF8574 I2C I/O expander at address 0x20.
  • write.py
    This code example is downloadable from the Acme playground repository. File: python/i2c/write.py
    import smbus
    import time
     
    bus = smbus.SMBus(0)
     
    for a in range(0,256):
     bus.write_byte(0x20,a)
     time.sleep(0.1)

C code example

The following example sends a sequence of values from 0 to 255 to the PCF8574 I2C I/O expander at address 0x20 in C language.
  • write.c
    This code example is downloadable from the Acme playground repository. File: c/i2c/write.c
    #include 
    #include 
    #include 
    #include 
    
    #define I2C_ADDR 0x20
     
    int main (void) {
     int value;
     int fd;
    
     fd = open("/dev/i2c-0", O_RDWR);
    
     if (fd < 0) {
      printf("Error opening file: %s\n", strerror(errno));
      return 1;
     }
    
     if (ioctl(fd, I2C_SLAVE, I2C_ADDR) < 0) {
      printf("ioctl error: %s\n", strerror(errno));
      return 1;
     }
    
     for (value=0; value<=255; value++) {
      if (write(fd, &value, 1) != 1) {
       printf("Error writing file: %s\n", strerror(errno));
      }
      usleep(100000);
     }
     return 0;
    }
    

I2c Dev Interface

Usually, i2c devices are controlled by a kernel driver. But it is also
possible to access all devices on an adapter from userspace, through
the /dev interface. You need to load module i2c-dev for this.

Each registered i2c adapter gets a number, counting from 0. You can
examine /sys/class/i2c-dev/ to see what number corresponds to which adapter.
Alternatively, you can run "i2cdetect -l" to obtain a formated list of all
i2c adapters present on your system at a given time. i2cdetect is part of
the i2c-tools package.

I2C device files are character device files with major device number 89
and a minor device number corresponding to the number assigned as 
explained above. They should be called "i2c-%d" (i2c-0, i2c-1, ..., 
i2c-10, ...). All 256 minor device numbers are reserved for i2c.


C example
=========

So let's say you want to access an i2c adapter from a C program. The
first thing to do is "#include ". Please note that
there are two files named "i2c-dev.h" out there, one is distributed
with the Linux kernel and is meant to be included from kernel
driver code, the other one is distributed with i2c-tools and is
meant to be included from user-space programs. You obviously want
the second one here.

Now, you have to decide which adapter you want to access. You should
inspect /sys/class/i2c-dev/ or run "i2cdetect -l" to decide this.
Adapter numbers are assigned somewhat dynamically, so you can not
assume much about them. They can even change from one boot to the next.

Next thing, open the device file, as follows:

  int file;
  int adapter_nr = 2; /* probably dynamically determined */
  char filename[20];
  
  snprintf(filename, 19, "/dev/i2c-%d", adapter_nr);
  file = open(filename, O_RDWR);
  if (file < 0) {
    /* ERROR HANDLING; you can check errno to see what went wrong */
    exit(1);
  }

When you have opened the device, you must specify with what device
address you want to communicate:

  int addr = 0x40; /* The I2C address */

  if (ioctl(file, I2C_SLAVE, addr) < 0) {
    /* ERROR HANDLING; you can check errno to see what went wrong */
    exit(1);
  }

Well, you are all set up now. You can now use SMBus commands or plain
I2C to communicate with your device. SMBus commands are preferred if
the device supports them. Both are illustrated below.

  __u8 register = 0x10; /* Device register to access */
  __s32 res;
  char buf[10];

  /* Using SMBus commands */
  res = i2c_smbus_read_word_data(file, register);
  if (res < 0) {
    /* ERROR HANDLING: i2c transaction failed */
  } else {
    /* res contains the read word */
  }

  /* Using I2C Write, equivalent of 
     i2c_smbus_write_word_data(file, register, 0x6543) */
  buf[0] = register;
  buf[1] = 0x43;
  buf[2] = 0x65;
  if (write(file, buf, 3) ! =3) {
    /* ERROR HANDLING: i2c transaction failed */
  }

  /* Using I2C Read, equivalent of i2c_smbus_read_byte(file) */
  if (read(file, buf, 1) != 1) {
    /* ERROR HANDLING: i2c transaction failed */
  } else {
    /* buf[0] contains the read byte */
  }

Note that only a subset of the I2C and SMBus protocols can be achieved by
the means of read() and write() calls. In particular, so-called combined
transactions (mixing read and write messages in the same transaction)
aren't supported. For this reason, this interface is almost never used by
user-space programs.

IMPORTANT: because of the use of inline functions, you *have* to use
'-O' or some variation when you compile your program!


Full interface description
==========================

The following IOCTLs are defined:

ioctl(file, I2C_SLAVE, long addr)
  Change slave address. The address is passed in the 7 lower bits of the
  argument (except for 10 bit addresses, passed in the 10 lower bits in this
  case).

ioctl(file, I2C_TENBIT, long select)
  Selects ten bit addresses if select not equals 0, selects normal 7 bit
  addresses if select equals 0. Default 0.  This request is only valid
  if the adapter has I2C_FUNC_10BIT_ADDR.

ioctl(file, I2C_PEC, long select)
  Selects SMBus PEC (packet error checking) generation and verification
  if select not equals 0, disables if select equals 0. Default 0.
  Used only for SMBus transactions.  This request only has an effect if the
  the adapter has I2C_FUNC_SMBUS_PEC; it is still safe if not, it just
  doesn't have any effect.

ioctl(file, I2C_FUNCS, unsigned long *funcs)
  Gets the adapter functionality and puts it in *funcs.

ioctl(file, I2C_RDWR, struct i2c_rdwr_ioctl_data *msgset)
  Do combined read/write transaction without stop in between.
  Only valid if the adapter has I2C_FUNC_I2C.  The argument is
  a pointer to a

  struct i2c_rdwr_ioctl_data {
      struct i2c_msg *msgs;  /* ptr to array of simple messages */
      int nmsgs;             /* number of messages to exchange */
  }

  The msgs[] themselves contain further pointers into data buffers.
  The function will write or read data to or from that buffers depending
  on whether the I2C_M_RD flag is set in a particular message or not.
  The slave address and whether to use ten bit address mode has to be
  set in each message, overriding the values set with the above ioctl's.

ioctl(file, I2C_SMBUS, struct i2c_smbus_ioctl_data *args)
  Not meant to be called  directly; instead, use the access functions
  below.

You can do plain i2c transactions by using read(2) and write(2) calls.
You do not need to pass the address byte; instead, set it through
ioctl I2C_SLAVE before you try to access the device.

You can do SMBus level transactions (see documentation file smbus-protocol 
for details) through the following functions:
  __s32 i2c_smbus_write_quick(int file, __u8 value);
  __s32 i2c_smbus_read_byte(int file);
  __s32 i2c_smbus_write_byte(int file, __u8 value);
  __s32 i2c_smbus_read_byte_data(int file, __u8 command);
  __s32 i2c_smbus_write_byte_data(int file, __u8 command, __u8 value);
  __s32 i2c_smbus_read_word_data(int file, __u8 command);
  __s32 i2c_smbus_write_word_data(int file, __u8 command, __u16 value);
  __s32 i2c_smbus_process_call(int file, __u8 command, __u16 value);
  __s32 i2c_smbus_read_block_data(int file, __u8 command, __u8 *values);
  __s32 i2c_smbus_write_block_data(int file, __u8 command, __u8 length, 
                                   __u8 *values);
All these transactions return -1 on failure; you can read errno to see
what happened. The 'write' transactions return 0 on success; the
'read' transactions return the read value, except for read_block, which
returns the number of values read. The block buffers need not be longer
than 32 bytes.

The above functions are all inline functions, that resolve to calls to
the i2c_smbus_access function, that on its turn calls a specific ioctl
with the data in a specific format. Read the source code if you
want to know what happens behind the screens.


Implementation details
======================

For the interested, here's the code flow which happens inside the kernel
when you use the /dev interface to I2C:

1* Your program opens /dev/i2c-N and calls ioctl() on it, as described in
section "C example" above.

2* These open() and ioctl() calls are handled by the i2c-dev kernel
driver: see i2c-dev.c:i2cdev_open() and i2c-dev.c:i2cdev_ioctl(),
respectively. You can think of i2c-dev as a generic I2C chip driver
that can be programmed from user-space.

3* Some ioctl() calls are for administrative tasks and are handled by
i2c-dev directly. Examples include I2C_SLAVE (set the address of the
device you want to access) and I2C_PEC (enable or disable SMBus error
checking on future transactions.)

4* Other ioctl() calls are converted to in-kernel function calls by
i2c-dev. Examples include I2C_FUNCS, which queries the I2C adapter
functionality using i2c.h:i2c_get_functionality(), and I2C_SMBUS, which
performs an SMBus transaction using i2c-core.c:i2c_smbus_xfer().

The i2c-dev driver is responsible for checking all the parameters that
come from user-space for validity. After this point, there is no
difference between these calls that came from user-space through i2c-dev
and calls that would have been performed by kernel I2C chip drivers
directly. This means that I2C bus drivers don't need to implement
anything special to support access from user-space.

5* These i2c-core.c/i2c.h functions are wrappers to the actual
implementation of your I2C bus driver. Each adapter must declare
callback functions implementing these standard calls.
i2c.h:i2c_get_functionality() calls i2c_adapter.algo->functionality(),
while i2c-core.c:i2c_smbus_xfer() calls either
adapter.algo->smbus_xfer() if it is implemented, or if not,
i2c-core.c:i2c_smbus_xfer_emulated() which in turn calls
i2c_adapter.algo->master_xfer().

After your I2C bus driver has processed these requests, execution runs
up the call chain, with almost no processing done, except by i2c-dev to
package the returned data, if any, in suitable format for the ioctl.

Writing I2c Client Document

This is a small guide for those who want to write kernel drivers for I2C
or SMBus devices, using Linux as the protocol host/master (not slave).

To set up a driver, you need to do several things. Some are optional, and
some things can be done slightly or completely different. Use this as a
guide, not as a rule book!


General remarks
===============

Try to keep the kernel namespace as clean as possible. The best way to
do this is to use a unique prefix for all global symbols. This is
especially important for exported symbols, but it is a good idea to do
it for non-exported symbols too. We will use the prefix `foo_' in this
tutorial.


The driver structure
====================

Usually, you will implement a single driver structure, and instantiate
all clients from it. Remember, a driver structure contains general access
routines, and should be zero-initialized except for fields with data you
provide.  A client structure holds device-specific information like the
driver model device node, and its I2C address.

static struct i2c_device_id foo_idtable[] = {
 { "foo", my_id_for_foo },
 { "bar", my_id_for_bar },
 { }
};

MODULE_DEVICE_TABLE(i2c, foo_idtable);

static struct i2c_driver foo_driver = {
 .driver = {
  .name = "foo",
 },

 .id_table = foo_idtable,
 .probe  = foo_probe,
 .remove  = foo_remove,
 /* if device autodetection is needed: */
 .class  = I2C_CLASS_SOMETHING,
 .detect  = foo_detect,
 .address_list = normal_i2c,

 .shutdown = foo_shutdown, /* optional */
 .suspend = foo_suspend, /* optional */
 .resume  = foo_resume, /* optional */
 .command = foo_command, /* optional, deprecated */
}

The name field is the driver name, and must not contain spaces.  It
should match the module name (if the driver can be compiled as a module),
although you can use MODULE_ALIAS (passing "foo" in this example) to add
another name for the module.  If the driver name doesn't match the module
name, the module won't be automatically loaded (hotplug/coldplug).

All other fields are for call-back functions which will be explained
below.


Extra client data
=================

Each client structure has a special `data' field that can point to any
structure at all.  You should use this to keep device-specific data.

 /* store the value */
 void i2c_set_clientdata(struct i2c_client *client, void *data);

 /* retrieve the value */
 void *i2c_get_clientdata(const struct i2c_client *client);

Note that starting with kernel 2.6.34, you don't have to set the `data' field
to NULL in remove() or if probe() failed anymore. The i2c-core does this
automatically on these occasions. Those are also the only times the core will
touch this field.


Accessing the client
====================

Let's say we have a valid client structure. At some time, we will need
to gather information from the client, or write new information to the
client.

I have found it useful to define foo_read and foo_write functions for this.
For some cases, it will be easier to call the i2c functions directly,
but many chips have some kind of register-value idea that can easily
be encapsulated.

The below functions are simple examples, and should not be copied
literally.

int foo_read_value(struct i2c_client *client, u8 reg)
{
 if (reg < 0x10) /* byte-sized register */
  return i2c_smbus_read_byte_data(client, reg);
 else  /* word-sized register */
  return i2c_smbus_read_word_data(client, reg);
}

int foo_write_value(struct i2c_client *client, u8 reg, u16 value)
{
 if (reg == 0x10) /* Impossible to write - driver error! */
  return -EINVAL;
 else if (reg < 0x10) /* byte-sized register */
  return i2c_smbus_write_byte_data(client, reg, value);
 else   /* word-sized register */
  return i2c_smbus_write_word_data(client, reg, value);
}


Probing and attaching
=====================

The Linux I2C stack was originally written to support access to hardware
monitoring chips on PC motherboards, and thus used to embed some assumptions
that were more appropriate to SMBus (and PCs) than to I2C.  One of these
assumptions was that most adapters and devices drivers support the SMBUS_QUICK
protocol to probe device presence.  Another was that devices and their drivers
can be sufficiently configured using only such probe primitives.

As Linux and its I2C stack became more widely used in embedded systems
and complex components such as DVB adapters, those assumptions became more
problematic.  Drivers for I2C devices that issue interrupts need more (and
different) configuration information, as do drivers handling chip variants
that can't be distinguished by protocol probing, or which need some board
specific information to operate correctly.


Device/Driver Binding
---------------------

System infrastructure, typically board-specific initialization code or
boot firmware, reports what I2C devices exist.  For example, there may be
a table, in the kernel or from the boot loader, identifying I2C devices
and linking them to board-specific configuration information about IRQs
and other wiring artifacts, chip type, and so on.  That could be used to
create i2c_client objects for each I2C device.

I2C device drivers using this binding model work just like any other
kind of driver in Linux:  they provide a probe() method to bind to
those devices, and a remove() method to unbind.

 static int foo_probe(struct i2c_client *client,
        const struct i2c_device_id *id);
 static int foo_remove(struct i2c_client *client);

Remember that the i2c_driver does not create those client handles.  The
handle may be used during foo_probe().  If foo_probe() reports success
(zero not a negative status code) it may save the handle and use it until
foo_remove() returns.  That binding model is used by most Linux drivers.

The probe function is called when an entry in the id_table name field
matches the device's name. It is passed the entry that was matched so
the driver knows which one in the table matched.


Device Creation
---------------

If you know for a fact that an I2C device is connected to a given I2C bus,
you can instantiate that device by simply filling an i2c_board_info
structure with the device address and driver name, and calling
i2c_new_device().  This will create the device, then the driver core will
take care of finding the right driver and will call its probe() method.
If a driver supports different device types, you can specify the type you
want using the type field.  You can also specify an IRQ and platform data
if needed.

Sometimes you know that a device is connected to a given I2C bus, but you
don't know the exact address it uses.  This happens on TV adapters for
example, where the same driver supports dozens of slightly different
models, and I2C device addresses change from one model to the next.  In
that case, you can use the i2c_new_probed_device() variant, which is
similar to i2c_new_device(), except that it takes an additional list of
possible I2C addresses to probe.  A device is created for the first
responsive address in the list.  If you expect more than one device to be
present in the address range, simply call i2c_new_probed_device() that
many times.

The call to i2c_new_device() or i2c_new_probed_device() typically happens
in the I2C bus driver. You may want to save the returned i2c_client
reference for later use.


Device Detection
----------------

Sometimes you do not know in advance which I2C devices are connected to
a given I2C bus.  This is for example the case of hardware monitoring
devices on a PC's SMBus.  In that case, you may want to let your driver
detect supported devices automatically.  This is how the legacy model
was working, and is now available as an extension to the standard
driver model.

You simply have to define a detect callback which will attempt to
identify supported devices (returning 0 for supported ones and -ENODEV
for unsupported ones), a list of addresses to probe, and a device type
(or class) so that only I2C buses which may have that type of device
connected (and not otherwise enumerated) will be probed.  For example,
a driver for a hardware monitoring chip for which auto-detection is
needed would set its class to I2C_CLASS_HWMON, and only I2C adapters
with a class including I2C_CLASS_HWMON would be probed by this driver.
Note that the absence of matching classes does not prevent the use of
a device of that type on the given I2C adapter.  All it prevents is
auto-detection; explicit instantiation of devices is still possible.

Note that this mechanism is purely optional and not suitable for all
devices.  You need some reliable way to identify the supported devices
(typically using device-specific, dedicated identification registers),
otherwise misdetections are likely to occur and things can get wrong
quickly.  Keep in mind that the I2C protocol doesn't include any
standard way to detect the presence of a chip at a given address, let
alone a standard way to identify devices.  Even worse is the lack of
semantics associated to bus transfers, which means that the same
transfer can be seen as a read operation by a chip and as a write
operation by another chip.  For these reasons, explicit device
instantiation should always be preferred to auto-detection where
possible.


Device Deletion
---------------

Each I2C device which has been created using i2c_new_device() or
i2c_new_probed_device() can be unregistered by calling
i2c_unregister_device().  If you don't call it explicitly, it will be
called automatically before the underlying I2C bus itself is removed, as a
device can't survive its parent in the device driver model.


Initializing the driver
=======================

When the kernel is booted, or when your foo driver module is inserted,
you have to do some initializing. Fortunately, just registering the
driver module is usually enough.

static int __init foo_init(void)
{
 return i2c_add_driver(&foo_driver);
}
module_init(foo_init);

static void __exit foo_cleanup(void)
{
 i2c_del_driver(&foo_driver);
}
module_exit(foo_cleanup);

The module_i2c_driver() macro can be used to reduce above code.

module_i2c_driver(foo_driver);

Note that some functions are marked by `__init'.  These functions can
be removed after kernel booting (or module loading) is completed.
Likewise, functions marked by `__exit' are dropped by the compiler when
the code is built into the kernel, as they would never be called.


Driver Information
==================

/* Substitute your own name and email address */
MODULE_AUTHOR("Frodo Looijaard "
MODULE_DESCRIPTION("Driver for Barf Inc. Foo I2C devices");

/* a few non-GPL license types are also allowed */
MODULE_LICENSE("GPL");


Power Management
================

If your I2C device needs special handling when entering a system low
power state -- like putting a transceiver into a low power mode, or
activating a system wakeup mechanism -- do that in the suspend() method.
The resume() method should reverse what the suspend() method does.

These are standard driver model calls, and they work just like they
would for any other driver stack.  The calls can sleep, and can use
I2C messaging to the device being suspended or resumed (since their
parent I2C adapter is active when these calls are issued, and IRQs
are still enabled).


System Shutdown
===============

If your I2C device needs special handling when the system shuts down
or reboots (including kexec) -- like turning something off -- use a
shutdown() method.

Again, this is a standard driver model call, working just like it
would for any other driver stack:  the calls can sleep, and can use
I2C messaging.


Command function
================

A generic ioctl-like function call back is supported. You will seldom
need this, and its use is deprecated anyway, so newer design should not
use it.


Sending and receiving
=====================

If you want to communicate with your device, there are several functions
to do this. You can find all of them in .

If you can choose between plain I2C communication and SMBus level
communication, please use the latter. All adapters understand SMBus level
commands, but only some of them understand plain I2C!


Plain I2C communication
-----------------------

 int i2c_master_send(struct i2c_client *client, const char *buf,
       int count);
 int i2c_master_recv(struct i2c_client *client, char *buf, int count);

These routines read and write some bytes from/to a client. The client
contains the i2c address, so you do not have to include it. The second
parameter contains the bytes to read/write, the third the number of bytes
to read/write (must be less than the length of the buffer, also should be
less than 64k since msg.len is u16.) Returned is the actual number of bytes
read/written.

 int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msg,
    int num);

This sends a series of messages. Each message can be a read or write,
and they can be mixed in any way. The transactions are combined: no
stop bit is sent between transaction. The i2c_msg structure contains
for each message the client address, the number of bytes of the message
and the message data itself.

You can read the file `i2c-protocol' for more information about the
actual I2C protocol.


SMBus communication
-------------------

 s32 i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr,
      unsigned short flags, char read_write, u8 command,
      int size, union i2c_smbus_data *data);

This is the generic SMBus function. All functions below are implemented
in terms of it. Never use this function directly!

 s32 i2c_smbus_read_byte(struct i2c_client *client);
 s32 i2c_smbus_write_byte(struct i2c_client *client, u8 value);
 s32 i2c_smbus_read_byte_data(struct i2c_client *client, u8 command);
 s32 i2c_smbus_write_byte_data(struct i2c_client *client,
          u8 command, u8 value);
 s32 i2c_smbus_read_word_data(struct i2c_client *client, u8 command);
 s32 i2c_smbus_write_word_data(struct i2c_client *client,
          u8 command, u16 value);
 s32 i2c_smbus_read_block_data(struct i2c_client *client,
          u8 command, u8 *values);
 s32 i2c_smbus_write_block_data(struct i2c_client *client,
           u8 command, u8 length, const u8 *values);
 s32 i2c_smbus_read_i2c_block_data(struct i2c_client *client,
       u8 command, u8 length, u8 *values);
 s32 i2c_smbus_write_i2c_block_data(struct i2c_client *client,
        u8 command, u8 length,
        const u8 *values);

These ones were removed from i2c-core because they had no users, but could
be added back later if needed:

 s32 i2c_smbus_write_quick(struct i2c_client *client, u8 value);
 s32 i2c_smbus_process_call(struct i2c_client *client,
       u8 command, u16 value);
 s32 i2c_smbus_block_process_call(struct i2c_client *client,
      u8 command, u8 length, u8 *values);

All these transactions return a negative errno value on failure. The 'write'
transactions return 0 on success; the 'read' transactions return the read
value, except for block transactions, which return the number of values
read. The block buffers need not be longer than 32 bytes.

You can read the file `smbus-protocol' for more information about the
actual SMBus protocol.


General purpose routines
========================

Below all general purpose routines are listed, that were not mentioned
before.

 /* Return the adapter number for a specific adapter */
 int i2c_adapter_id(struct i2c_adapter *adap);

Writing an MLO for a BeagleBoard XM

Writing an MLO for a BeagleBoard XM
Before I started playing with the BeagleBoard XM I’ve had never booted a board directly from an MMC card and I didn’t have a clue what an ‘MLO’ file was. After some research on the internet it seemed apparent that it was used in place of the traditional first stage boot loader: XLoader. In fact it in most cases it is XLoader – a quick invocation of my toolchain’s string implementation seemed to correlate with this:
1$ arm-none-linux-gnueabi-strings /media/boot/MLO | grep X-Loader
2()*+,-./0123456789:;<=>?Texas Instruments X-Loader 1.5.0 (Mar 27 2011 - 17:37:56)
3X-Loader hangs
I was curious as to why it was named MLO, how the board boots into this Image and how I can create my own MLO with some bare metal code. This post answers these questions and results in a very simple executable MLO file. It will probably satisfy those readers who like to understand and write all the code that runs on a board. It’s very easy to use a boot loader like UBoot to obtain and execute an image from an MMC card – but it adds boot time, duplication and complexity. Besides it’s fun to get close to the metal…

Why an ‘MLO’ and how does it boot?
Like many TI SOCs the DM3730 (BeagleBoard XM SOC) contains a ROM – upon a reset release the reset exception starts executing ROM code. The purpose of the ROM is to perform some very basic system configuration and to ultimately find and boot from a device such as flash or an MMC card (This is why it’s sometimes known as an ROM Boot Loader or RBL). It overcomes the chicken-and-egg problem of being unable to boot from a device because nothing has performed required initialisation of that device. The DM3730 is a fairly complex device and can boot from a wide range of devices with various configurations – as a result the ROM is also complex. This particular ROM has enough functionality to understand FAT filesystems on an MMC card, perform boot from a UART device, it can even boot from a USB device. The key to really understanding all of this on the DM3730 is to read Chapter 26 of the Technical Reference Manual (TRM).
When the device is powered on a set of boot pins (sys_boot) are held high or low to indicate to the ROM a list of devices to boot from (a bit like a PC BIOS). One can only assume that the BeagleBoard manufactures have set these appropriately to include MMC booting. As a result of this – during power on the ROM will initialise the MMC/SD device, detect a card and look for a boot image. The ROM is capable of reading from an MMC card with or without a filesystem. In the case of a filesystem it will search for a file named ‘MLO’ which should be located in the root directory on an active partition of type FAT12/16 or FAT32. So this explains why we name Xloader MLO.
However, just renaming an x-load.bin file to MLO isn’t enough. As an MMC device is not capable of executing-in-place (XIP), a header much be appended onto the image which tells the ROM where to copy the image to (usually somewhere in SRAM) and how big the image is. The header is very straightforward and just consists of the first 4 bytes being the size of the image and the last 4 bytes being the destination address. You may have come across the signGP utility before – the signGP utility creates such headers – but usually postpends the output file name with .ift – rather than naming it MLO.
The ROM also supports an optional header – which allows you to specify additional options such as adjusting the clock frequencies, SRAM settings, MMC Interface settings, etc – read the TRM for more information on this.
Creating your own MLO
I wanted to create my own MLO – effectively a container for bare metal code. To do this I need some code to run, how about this:
1.global start
2start:
3    mov r0, #0
4    mov r1, #1
5    mov r2, #2
6    mov r3, #3
7    mov r4, #4
8    b   start
A very simple bit of assembler that does nothing but continually sets the value of registers 0 to 4. To build an MLO I invoke the following:
1$ arm-none-linux-gnueabi-gcc test.S -nostdlib -e start -Ttext=0x40200800
2$ arm-none-linux-gnueabi-objcopy -O binary a.out a.bin
3$ ./signGP a.bin
4$ mv a.bin.ift MLO
Let’s explain what’s going on here. I start by using GCC to build my assembler file – I tell it not to include any standard libraries (-nostdlib). I tell it where the entry point of my application is (-e) (as there is no main or standard libraries). And finally I ensure that the program is linked to run at the address which we intend to load it – this address is somewhere safe in SRAM.
I then convert the ELF file that GCC creates into a binary file – in other words I strip out anything that isn’t executable code. I then use the signGP program to prepend a suitable header (please note signGP by default uses 0×40200800 as a default load address). I then rename the output to MLO. To verify this looks right, I did the following:
1$ ls -la a.bin
2$ hexdump MLO
30000000 0018 0000 0800 4020 0000 e3a0 1001 e3a0
40000010 2002 e3a0 3003 e3a0 4004 e3a0 fff9 eaff
50000020
You may notice – the first 4 bytes are 0×18 – which is the size of a.bin. The next 4 bytes are 0×40200800 which is the load address. The remaining bytes are the executable image. Great – let’s put this on an MMC card, reboot the board and see what happens when we break into the board with the JTAG (Please see my last post for how to connect to the BeagleBoard XM with a JTAG device).

MLO seen running inside Code Composer Studio
As you can see from the image above – when I break into the board I can see my code in the disassembly window and the processor registers are as expected. Fantastic! As you may expect I wasn’t fortunate to get this right on my first attempt – fortunately the ROM can help here too – it contains a number of ‘dead loops’ – when something goes wrong such as an invalid header it will execute a tight loop at a known address. These are documented in the TRM and provide a good indication as to what is going on. [© 2011 embedded-bits.co.uk]
oader or RBL). It overcomes the chicken-and-egg problem of being unable to boot from a device because nothing has performed required initialisation of that device. The DM3730 is a fairly complex device and can boot from a wide range of devices with various configurations – as a result the ROM is also complex. This particular ROM has enough functionality to understand FAT filesystems on an MMC card, perform boot from a UART device, it can even boot from a USB device. The key to really understanding all of this on the DM3730 is to read Chapter 26 of the Technical Reference Manual (TRM).
When the device is powered on a set of boot pins (sys_boot) are held high or low to indicate to the ROM a list of devices to boot from (a bit like a PC BIOS). One can only assume that the BeagleBoard manufactures have set these appropriately to include MMC booting. As a result of this – during power on the ROM will initialise the MMC/SD device, detect a card and look for a boot image. The ROM is capable of reading from an MMC card with or without a filesystem. In the case of a filesystem it will search for a file named ‘MLO’ which should be located in the root directory on an active partition of type FAT12/16 or FAT32. So this explains why we name Xloader MLO.
However, just renaming an x-load.bin file to MLO isn’t enough. As an MMC device is not capable of executing-in-place (XIP), a header much be appended onto the image which tells the ROM where to copy the image to (usually somewhere in SRAM) and how big the image is. The header is very straightforward and just consists of the first 4 bytes being the size of the image and the last 4 bytes being the destination address. You may have come across the signGP utility before – the signGP utility creates such headers – but usually postpends the output file name with .ift – rather than naming it MLO.
The ROM also supports an optional header – which allows you to specify additional options such as adjusting the clock frequencies, SRAM settings, MMC Interface settings, etc – read the TRM for more information on this.
Creating your own MLO
I wanted to create my own MLO – effectively a container for bare metal code. To do this I need some code to run, how about this:
1.global start
2start:
3    mov r0, #0
4    mov r1, #1
5    mov r2, #2
6    mov r3, #3
7    mov r4, #4
8    b   start
A very simple bit of assembler that does nothing but continually sets the value of registers 0 to 4. To build an MLO I invoke the following:
1$ arm-none-linux-gnueabi-gcc test.S -nostdlib -e start -Ttext=0x40200800
2$ arm-none-linux-gnueabi-objcopy -O binary a.out a.bin
3$ ./signGP a.bin
4$ mv a.bin.ift MLO
Let’s explain what’s going on here. I start by using GCC to build my assembler file – I tell it not to include any standard libraries (-nostdlib). I tell it where the entry point of my application is (-e) (as there is no main or standard libraries). And finally I ensure that the program is linked to run at the address which we intend to load it – this address is somewhere safe in SRAM.
I then convert the ELF file that GCC creates into a binary file – in other words I strip out anything that isn’t executable code. I then use the signGP program to prepend a suitable header (please note signGP by default uses 0×40200800 as a default load address). I then rename the output to MLO. To verify this looks right, I did the following:
1$ ls -la a.bin
2$ hexdump MLO
30000000 0018 0000 0800 4020 0000 e3a0 1001 e3a0
40000010 2002 e3a0 3003 e3a0 4004 e3a0 fff9 eaff
50000020
You may notice – the first 4 bytes are 0×18 – which is the size of a.bin. The next 4 bytes are 0×40200800 which is the load address. The remaining bytes are the executable image. Great – let’s put this on an MMC card, reboot the board and see what happens when we break into the board with the JTAG (Please see my last post for how to connect to the BeagleBoard XM with a JTAG device).

MLO seen running inside Code Composer Studio
As you can see from the image above – when I break into the board I can see my code in the disassembly window and the processor registers are as expected. Fantastic! As you may expect I wasn’t fortunate to get this right on my first attempt – fortunately the ROM can help here too – it contains a number of ‘dead loops’ – when something goes wrong such as an invalid header it will execute a tight loop at a known address. These are documented in the TRM and provide a good indication as to what is going on.

Writing an I2c Client Driver

In a nutshell I2C is a simple serial bus that is often used to communicate with devices such as EEPROMs and peripherals such as touchscreens – there is also SMBus which can sometimes be considered a subset of I2C. The kernel breaks down I2C into ‘Buses’ and ‘Devices’, and then further breaks down buses into ‘Algorithms‘ and ‘Adapters‘, and devices into ‘Drivers‘ and ‘Clients‘. We’ll take a look at these in a little more detail.

Algorithms
An Algorithm performs the actual reading and writing of I2C messages to the hardware – this may involve bit banging GPIO lines or writing to an I2C controller chip. An Algorithm is represented by the very straight-foward ‘struct i2c_algorithm‘ structure and allows you to define function pointers to functions that can write I2C messages (master_xfer) or SMBus messages (smbus_xfer).

Adapters
An Adapter effectively represents a bus – it is used to tie up a particular I2C/SMBus with an algorithm and bus number. It is represented by the ‘struct i2c_adapter‘ structure. If you imagine a system where there are many I2C buses – perhaps two controlled by a controller chip and one bit-banged – then you would expect to see 3 instances of an i2c_adapter and 2 instances of an i2c_algorithm.

Clients
A Client represents a chip (slave) on the I2C/SMBus such as a Touchscreen peripheral and is represented by a ‘struct i2c_client‘ structure. This includes various members such as chip address, name and pointers to the adapter and driver.

Drivers
Finally a driver, represented by a ‘struct i2c_driver‘ structure represents the device driver for a particular class of I2C/SMBus slave devices, e.g. a touchscreen driver. The structure contains a bunch of function pointers – the ones of interest to us are the ‘probe’ and ‘remove’ pointers – which we’ll shortly come onto.
So where do we start with writing an I2C slave device driver? We start by populating a ‘struct i2c_driver’ structure. In this tutorial we’ll populate just the ‘driver’, ‘id_table’, ‘probe’, and ‘remove’ members. We’ll also use the ‘migor_ts.c‘ touchscreen driver as reference code.
1static struct i2c_driver migor_ts_driver = {
2   .driver = {
3      .name = "migor_ts",
4   },
5   .probe = migor_ts_probe,
6   .remove = migor_ts_remove,
7   .id_table = migor_ts_id,
8};
We tell the kernel about our I2C slave driver by registering the 'struct i2c_driver' structure with the I2C core - we do this with a call to 'i2c_add_driver' in our __init function as follows:
1static int __init migor_ts_init(void)
2{
3        return i2c_add_driver(&migor_ts_driver);
4}
 The __init macro will ensure this function gets called upon kernel initialisation.
Back to our ‘struct i2c_driver’ structure – the id_table member allows us to tell the framework which I2C slaves chips we support – id_table is simply an array of ‘struct i2c_device_id’ – here’s the migors:
1static struct i2c_device_id migor_ts_id[] = {
2{ "migor_ts", 0 },
3{ }
4};
So in this case we’re saying that we only support a slave chip named ‘migor_ts’. This makes us wonder – how does the kernel know which slave chips are present and what they’re called? – we know the chip doesn’t contain such friendly naming strings and I2C doesn’t support enumeration. There is no magic - there are a number of mechanisms to discover and name an I2C slave – the most common in embedded devices is to define in your board set up file what slave devices you expect to see, their address and name. For example in the arch/sh/boards/mach-migor/setup.c file we see the following:
1static struct i2c_board_info migor_i2c_devices[] = {
2{
3I2C_BOARD_INFO("migor_ts", 0x51),
4.irq = 38, /* IRQ6 */
5},
6};
7
8i2c_register_board_info(0, migor_i2c_devices, ARRAY_SIZE(migor_i2c_devices));
Without going into too much detail here – we populate a ‘struct i2c_board_info’ structure with the help of a I2C_BOARD_INFO macro - crucially we include a made up name for the slave chip and it’s I2C bus address.
So back to the migor driver. During boot, thanks to the ‘i2c_register_board_info’ call, the kernel will try to find any I2C driver which supports the ‘migor_ts’ name we provided. Upon finding such a driver, the kernel will call it’s ‘probe’ function. The idea being that the kernel believes it has found an I2C slave and would like us to probe to make sure that we are a suitable driver (It’s worth noting that the kernel won’t attempt to communicate with this device in any way).
So if all is well – upon start up the kernel should call our probe function – let’s take a look.
1static int migor_ts_probe(struct i2c_client *client, const struct i2c_device_id *idp)
2{
3...
4}
Passed along as a parameter to the probe function is a ‘struct i2c_client’ structure – this represents our I2C slave chip. Typically a probe function where possible will communicate with the device to ensure it really is the device we think it is – this can be done by reading values from a revision ID register or the like. We can communicate with the slave by calling the ‘i2c_master_send’ function with a pointer to our ‘struct i2c_client’ – e.g:
1i2c_master_send(client, buf, 1);
With regards to driver initialisation this is the last we’ll here from the kernel – so the probe function should also register with the input layer (assuming an input device) and perhaps set up an interrupt/timer. It’s also a good idea to make a note of the i2c_client for use later on. Now you can talk to your I2C slave device – what else goes on really depends on the type of device which is being supported.

How to add device tree support in linux 3.8 kernel : Beaglebone

The trouble with board files:
The old 3.2 Kernel worked pretty well, so why was a move made to 3.8, which causes so much grief to the beaglebone old timers?
The major problem with the 3.2 kernel is that uses a board-file, namely,
arch/arm/mach-omap2/board-am335xevm.c
It's pretty big (at 4K+ lines), and quite difficult to modify. The boardfile also supports, in addition to the beaglebone white, the am335x-evm and all the capes. Every new cape that is to be supported has to modify this file. Additionally you need to create the platform devices that it contains and register them. You have to make sure that you don't break any of the other boards (or capes) supported by the platform file.
This is a job for professional kernel developers, but even kernel developers have their limits as evidenced by the famous Linus rant that prompted the great cosmic shift to Device Tree:
Famous Linux rant about ARM churn
What has been decreed is simple: “No more new ARM board files”
So all new boards must support booting using Device Tree. The board file used in the new kernels is just arch/arm/mach-omap2/board-generic.c and supports booting kernels using omap2, omap3, omap4, omap5 and the am33xx family of the beaglebone.
This presented a difficult decision for the developers working on the beaglebone black Linux support:
  1. Ignore the new mainline dictums, carry on using 3.2 and make the jump to mainline sometime in the future. That would require more developer resources, when the time for mainline porting comes. On top of that most kernel developers don't bother with older vendor kernels, and any bug fix or new functionality has to be painfully back-ported from mainline.
  2. Bite the bullet, move to 3.8 using DT, and future proof the beaglebone by submitting everything for inclusion to mainline as soon as possible. 

The trouble with Device Tree:

What is Device Tree (DT) and why is it causing so many problems for new developers?
Device Tree Central
"The Device Tree is a data structure for describing hardware. Rather than hard coding every detail of a device into an operating system, many aspect of the hardware can be described in a data structure that is passed to the operating system at boot time." (Please take note of the 'boot time' reference, we'll come back to it later).
The pinmux subsystem and clocksource/clockevent frameworks are two examples of consolidated frameworks that have evolved from the ARM move to DT. Previously, each ARM "machine", such as mach-omap2/*, implemented their SoC-specific pinmux and timer/clock drivers within their machine directory. In converted ARM machines, these drivers now live in the appropriate drivers/* directory and share common code sanely with other similar drivers.
As it turns out DT isn't that new, it's a couple of decades old and has been used by Open Firmware based systems like Sun workstations and the original PowerPC based Apple Macs.
For developers the biggest change is that the kernel board file is now gone.
Simply put, every board has to be described in a DTS (foo.dts) file that is compiled via the DTC compiler to a binary format DTB (flattened device tree format) which gets parsed on boot by the kernel and the devices are created.
Therein lies the biggest change; there are no more platform device data for the device containing it's configuration. On a board file based platform what you did was:
In the foo_platform_data.h file:
 struct foo_platform_data {
  u32 bar;
 };
In the board file:
 struct foo_platform_data foo_pdata {
  .bar        = 5,
 };
 
 struct platform_device foo_dev {
                .name = "foo",
                .id = -1,
                .dev.platform_data = &foo_pdata,
        };
And in the board setup function
        platform_device_register(&foo_dev);
The driver gets access to the platform data in the probe function.
        static int foo_probe(struct platform_device *pdev)
        {
                struct foo_platform_data *pdata;
                
                pdata = pdev->dev.platform_data;
                if (pdata == NULL) /* ERROR */
                        ...
        
                /* access pdata->bar for configuration */
                ...
        }
        
        static struct platform_driver foo_driver = {
                .probe = foo_probe,
                ....
                .driver = {
                        .name = "foo",
                },
                ...
        };
        
        module_platform_driver(&foo_driver);
This method no longer works; in a DT based system what you have to do come up with device driver bindings, which contain the configuration the driver requires.
You must add a device node in board.dts under the on-chip-peripherals(OCP) device node:
        foo {
                compatible = "corp,foo";
                bar = <5>;
        };
No change in the board file (generic anyway) needs to be made, but the device driver must be updated to support the DT method, with something similar to the following:
        static struct foo_platform_data *
        foo_parse_dt(struct platform_device *pdev)
        {
                struct device_node *node = pdev->dev.of_node;
                struct foo_platform_data *pdata;
        
                pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
                if (pdata == NULL)
                        return NULL; /* out of memory */
         
                /* no such property */
                if (of_property_read_u32(node, "bar", &pdata->bar) != 0)
                        return NULL;
         
                /* pdata->bar is filled in with 5 */
                return pdata;
        }
        
        static int foo_probe(struct platform_device *pdev)
        {
                struct foo_platform_data *pdata;

                if (pdev->dev.of_node != NULL)
                        pdata = foo_parse_dt(pdev);
                else
                        pdata = pdev->dev.platform_data;

                if (pdata == NULL) /* error */
                        ...
        }

        static const struct of_device_id of_foo_match[] = {
                { .compatible = "corp,foo", },
                { },
        };


        static struct platform_driver foo_driver = {
                .probe = foo_probe,
                ....
                .driver = {
                        .name = "foo",
                        .of_match_table = of_match_ptr(of_foo_match),
                },
                ...
        };


        module_platform_driver(&foo_driver);
The driver described above can support both the platform data model and the new DT method. Using a purely DT driver model can result in more flexibility, but we won't deal with it now. Frankly, the biggest change is that now a user (by compiling the DTS) can now configure his platform without having to recompile the kernel, which is a pretty big usability gain. We use this in the new 3.8 releases to boot both versions of the beaglebone using the same kernel, and only changing the DTB we boot with.
For a developer, the biggest change of using DT, is that it is purely data driven, and that custom platform drivers are frowned upon, opting instead to using generic frameworks, one of which is the pinmux framework.
In summary, the core of the change to DT is that logic that was previously accomplished in board files is moved into a mixture of generic frameworks, abstracted devices drivers, and data to drive that software. DT imposes structure upon the embedded developer and sometimes there is considerable pushback.

Device Tree's data driven model

The data driven model of device tree causes the most pain to the embedded developer steeped in the board file/platform method. Let's examine a concrete example, that deals with the simple subject of a driver/board pinmuxing.
Pinmuxing refers to the method of modern SoC multiplexing multiple peripheral functions to a rather limited set of physical pins/balls of the SoC package. The am335x is a prime example this, having many pins with up to 8 possible peripheral functions.
For a peripheral driver to work the correct muxing configuration must be applied to the affected pins; since they are so many, and configuration is complex, a special omap specific driver has been written and has been used on the 3.2 kernel provided by TI.
Typically in the board setup file, the mux configuration for the peripheral is applied before registering the platform device.
For example the pin mux for the a gpio configured as a led would be of the form
        omap_mux_init_signal("gpmc_a2.gpio1_18",
   OMAP_MUX_MODE7 | AM33XX_PIN_OUTPUT);
The omap mux driver also provides a user-space interface for changing the mux settings. The problem with pinmuxing is that it is potentially dangerous if you don't know exactly what kind of hardware is connected to the SoC pins, so in the mainline pinmuxing is performed via the drivers on probe time.
For the sake of making the example more concrete let's have a gpio also controlling power to the device. The device's driver is only supposed to apply the mux and turn on the power to the device by setting a gpio to high (please bear in mind this is not a real-world example, but explains the issues).
Let's examine the platform data example with a call back method.
In the foo_platform_data.h file:
        struct foo_platform_data {
                u32 bar;
                void (*get_ready)(struct platform_device *pdev);
        };
In the board file:
        /* magic GPIO number of FOO’s power pin */
        #define FOO_POWER 11234


        static void foo_get_ready(struct platform_device *pdev)
        {
                int ret;


                omap_mux_init_signal("gpmc_a2.gpio1_18",
   OMAP_MUX_MODE7 | AM33XX_PIN_OUTPUT);
                ret = gpio_request(FOO_POWER, "foo-power");
                if (ret >= 0)
                        gpio_direction_output(FOO_POWER, 1);
        }
        
        struct foo_platform_data foo_pdata {
                .bar = 5,
                .get_ready = foo_get_ready,
        };
The rest of the board file has no other changes.
The driver then can call the get_ready method via the callback function pointer.
        static int foo_probe(struct platform_device *pdev)
        {
                struct foo_platform_data *pdata;

                pdata = pdev->dev.platform_data;
                if (pdata == NULL) /* ERROR */
                        ...

                /* access pdata->bar for configuration */
                ...

                /* get foo ready */
                (*pdata->get_ready)(pdev);
        }
Callback functions are impossible in a DT platform. Callbacks break the data only model of DT. What must be done is for the driver to be converted to using the generic gpio and pinmux bindings. On am33xx the generic pinctrl-single driver is used, and to be honest, is not as polished as the old omap mux driver. Nevertheless it is usable and used on many other boards as well, since it is widely supported in the ARM community. Again generic frameworks win over custom solutions.
The boot.dts file is updated with the pinmux nodes and the gpio bank nodes.
        /* point to the to the conf_* module registers */
 am33xx_pinmux: pinmux@44e10800 {
  compatible = "pinctrl-single";
  reg = <0x44e10800 0x0238="">;
                #address-cells = <1>;
  #size-cells = <0>;
                pinctrl-single,register-width = <32>;
  pinctrl-single,function-mask = <0x7f>;

                foo_pins: foo_pins {
                        pinctrl-single,pins = <
                                /* need to look into the TRM and find those values */
                                /* conf_gpmc_a2 module config reg offset and value */
                                0x0A8 0x1f
                        >;
  };
 };

        gpio2: gpio@4804c000 { 
                compatible = "ti,omap4-gpio";
                ti,hwmods = "gpio2";
                gpio-controller;
                #gpio-cells = <2>;
                interrupt-controller; 
                #interrupt-cells = <1>;
                reg = <0x4804c000 0x1000="">;
                interrupts = <98>;
        };

        foo {
                compatible = "corp,foo";
                bar = <5>;

                # the power control gpio 
                power-gpio = <&gpio2 18 0x0>;

                # the muxing
                pinctrl-names = "default";
                pinctrl-0 = <&foo_pins>;
        };

The new nodes are the am33xx_pinmux node, and the gpio2 node. Note the added node in am33xx_pinmux that contains the pinmux config for the foo driver. Please note due to the OMAP's numbering of peripherals starting with 1 every numbered peripheral is +1 from what the AM3359 TRM states. There are patches against mainline that fix that, but not on 3.8 yet.
The foo driver only need minor changes, first the pinctrl consumer interface include header must be included.
        #include < linux/pinctrl/consumer.h >
Then on the probe function we need to apply the pinctrl configuration, while on the parse_dt function we need to set the gpio to the given value.
        static struct foo_platform_data *
        foo_parse_dt(struct platform_device *pdev)
        {
                struct device_node *node = pdev->dev.of_node;
                struct foo_platform_data *pdata;
  enum of_gpio_flags ofgpioflags;
                int ret, gpio;

                pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
                if (pdata == NULL)
                        return NULL; /* out of memory */

                /* no such property */
                if (of_property_read_u32(node, "bar", &pdata->bar) != 0)
                        return NULL;

                /* now get the power gpio and set it to one */
                gpio = of_get_named_gpio_flags(pdev->dev.of_node, "power-gpio",
                                0, &ofgpioflags);
                if (!IS_ERR_VALUE(gpio)) {
                        gpioflags = GPIOF_DIR_OUT;
                        if (ofgpioflags & OF_GPIO_ACTIVE_LOW)
                                gpioflags |= GPIOF_INIT_LOW;
                        else
                                gpioflags |= GPIOF_INIT_HIGH;
                        ret = devm_gpio_request_one(&pdev->dev, gpio,
                                        gpioflags, "foo-power");
                }

                /* pdata->bar is filled in with 5 */
                return pdata;
        }

        static int foo_probe(struct platform_device *pdev)
        {
                struct pinctrl *pinctrl;

                ...
                /* apply the pinmux configuration */
                pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
                if (IS_ERR(pinctrl))
                        dev_warn(pdev->dev, "unable to select pin group\n");

                if (pdev->dev.of_node != NULL)
                        pdata = foo_parse_dt(pdev);
                else
                        pdata = pdev->dev.platform_data;

                ….
        }

Cape Manager requirements

Going over the device tree definition we see that the data structure is referred as parsed at boot-time. Beaglebone capes are not static; a different cape set might be connected each time the board boots, and the only way to find out what kind of cape is connected is to read the serial EEPROM present on each cape which contains identification information.
Beaglebone capes are mostly compatible between White and Black, but due to the presence of the eMMC flash and the HDMI framer, some special attention must be paid for capes that use the same resources.
The information stored on the EEPROM of each cape are a user readable name, serial number, part number, revision information and others. The only information that the cape manager uses to work are the part-number and the revision.
A cape-manager should perform the following:
  1. Scan the I2C bus for EEPROMs that correspond to the address defined in the beaglebone SRM. Those addresses are 0x54-0x57 on I2C1 bus, hence the 4 capes limitation.
  2. Read the EEPROM contents and parse them according to the spec. Retrieve the part-number and revision information of that cape.
  3. Match the PART-NUMBER:REVISION tuple to a configuration that would result in the system state being that as if the cape was directly attached to the base board, and perform any actions that result to it.
Additionally we need extra facilities that are useful for people developing capes:
  • An override facility so that prototyping capes with no EEPROM can be supported.
  • An option to load capes at runtime.
  • An option to unload capes at runtime.
  • An option to stop a cape from loading even if detected.
  • To guard against resource conflicts. A cape that uses the same resources as another loaded earlier should not be permitted to load.
  • To be able to forbid cape loading of capes that are not supported by a baseboard revision.
  • To be able to load 'virtual' capes that correspond to peripheral that are present on specific baseboard revisions.
  • To support the notion of a cape priority, so that in case of a conflict, the cape we define as higher priority gets loaded. This is important to allow plug in capes to take preference over capes that are part of the baseboard; i.e. when an LCD cape is attached it takes preference over the onboard HDMI virtual cape.
  • To not require source changes for any driver for a peripheral that resides on cape or onboard , i.e. the drivers should not be modified for use in a cape.
  • No kernel source changes must be required for a new cape to be supported.
  • To not require modification of the boot-loader, or of the base DTS.

Device Tree Overlays

The method used to dynamically load the cape definition to the running kernel is called a Device Tree Overlay. What a device tree overlay does is apply changes to the kernel's internal DT representation and trigger the changes that this action carries. For example adding a new enabled device node should result in a new device being created, while removing a node removes the device and so on.
The previous foo example, when reworked for usage with DT overlays is as follows:
The base.dts file has an ocp label of the on-board peripherals for the SoC.
        / {
                /* On chip peripherals */
                ocp: ocp {
                        /* peripherals that are always instantiated */
                        peripheral0 { ... };
                }
        };
The overlay when loaded must result in the same device tree as in the previous example; the overlay must be the following:
        /plugin/;        /* allow undefined label references and record them */
        / {
                ....        /*various properties for loader use; i.e. part id etc. */
                fragment@0 {
                        target = <&am33xx_pinmux>;
                        __overlay__ {
                                foo_pins: foo_pins {
                                        pinctrl-single,pins = <
                                                /* look into the TRM for values */
                                                /* conf_gpmc_a2 module reg offset/value */
                                                0x0A8 0x1f
                                        >;
                                };
                        };
                };

                fragment@1 {
                        target = <&ocp>;
                        __overlay__ {
                                /* bar peripheral */
                                foo {
                                        compatible = "corp,foo";
                                        bar = <5>;

                                        # the power control gpio 
                                        power-gpio = <&gpio2 18 0x0>;

                                        # the muxing
                                        pinctrl-names = "default";
                                        pinctrl-0 = <&foo_pins>;
                                };
                        };
                };
        };
The overlay consists of two fragments, one targeting the am33xx_pinmux node, the other the ocp node. Note that there are no foo driver changes, not any sort of platform board file hacking. When this overlay is applied the foo device will be created, just as if it was declared in the base.dts.
More information about the internal of overlays and the resolution mechanism is located in Documentation/devicetree directory of the kernel.

Cape Manager and Device Tree Overlays

Device Tree overlays is a general purpose mechanism, which is not tied to any platform. For actual platforms like the beaglebone the mechanism must be supplemented by platform specific logic.
The platform logic of the beaglebone cape manager deals with the following:
  • Reading the EEPROMs of the capes for retrieval of the part numbers & revision.
  • Allowing runtime addition/removal of cape fragments.
  • Having options to control cape loading from the kernel command line
  • Having options to force loading of capes from the base DTS
  • Having mapping options of multiple cape part numbers & revisions to a single cape
  • Resource conflict management
  • Implement cape priorities so that in case of a conflict the winner can be selected
  • Verification of the cape compatibility with a base board
  • Various cape information display (i.e. serial# etc).
  • Automatic loading of capes based on base board version (i.e. auto loading HDMI/eMMC capes)
Lets add the beaglebone specific properties to the foo DT overlay and complete the cape.
        /plugin/;        /* allow undefined label references and record them */
        / {
                /* compatible with both the original and the beaglebone black */
                compatible = "ti,beaglebone", "ti,beaglebone-black";

                /* part-number */
                part-number = "BB-FOO-01";

                /* version */
                version = "00A0";

                exclusive-use = 
                        "P8.43",        /* Header.Pin# */
                        "gpio2_8";        /* the hardware IP we use */

                /* the fragments are the same as above */
                ....
        };
The compatible property lists the platforms that this cape supports. If an attempt is made to load an unsupported cape by this platform the attempt will fail.
Similarly, the part-number and version properties guard against an attempt of loading a bad cape.
The exclusive-use property is a pretty simple attempt at implementing resource management. What it does, is allow capes to declare free-form text resources; if another cape tries to load which uses the same resource, it will be prevented of doing so. The convention in the beaglebone cape format is that we reserve the header/pin and the hardware IP block the cape wants to use, in that case pin#43 of the P8 connector, and the gpio2_8 gpio hardware block.
The name of the cape should be of the ${PART_NUMBER}:${REV}.dts format and the compilation would be (on either the host or the beaglebone):
 $ dtc -O dtb -o BB-FOO-01-00A0.dtbo -b 0 -@ BB-FOO-01-00A0.dts
Note the required -@ option; it is not part of the upstream dtc, so it's a DT overlay specific patch that enables it. The beaglebone kernel has the patch already applied on it’s internal dtc compiler copy, as well as the angstrom image, but you need the following patches for other distro’s dtc packages.
Dynamic Overlays DTC patch
Putting the resulting BB-FOO-01-00A0.dtbo file in /lib/firmware we can enable it by
        # echo BB-FOO-01 >/sys/devices/bone_capemgr*/slots
We can verify if it loaded with:
        # cat /sys/devices/bone_capemgr*/slots
         0: 54:PF--- 
         1: 55:PF--- 
         2: 56:PF--- 
         3: 57:PF--- 
         4: ff:P-O-L Bone-LT-eMMC-2G,00A0,Texas Instrument,BB-BONE-EMMC-2G
         5: ff:P-O-L Bone-Black-HDMI,00A0,Texas Instrument,BB-BONELT-HDMI
         6: ff:P-O-L Override Board Name,00A0,Override Manuf,BB-FOO-01
 
Slot #6 is the one we've loaded.
The cape can be removed by:
        # echo -6 >/sys/devices/bone_capemgr*/slots
Cape-manager also supports a method of enabling (or disabling) a cape by a kernel command line option.
        capemgr.extra-override=BB-FOO-01
Will automatically load the cape on boot, while
        capemgr.disable_partno=BB-FOO-01
will disable the cape (if it's attempted to load automatically).

Porting to the new DT kernel FAQ

Q: I have a custom kernel fork, based on a modified board file. Nothing works.
A: The biggest difference of-course is that there's no board file, so there are no platform data. You have to have device drivers with DT bindings. You can get by temporarily by creating a helper DT enabled platform device and allocate/fill the platform data from the probe method and register the platform device. But this is only a temporary fix, and DT bindings should be introduced at some point in the driver.
Q: The new pinmuxing method sucks; why can't I pinmux by the old method at runtime?
A: The old pinmux method was TI specific and although it made it in the mainline, it has no DT bindings and is duplicating functionality of the general pinmux framework. The new method is portable, but it's reliance on raw numbers is a pain. However it does offer safety, since if a device obtains the pin resources there's no way for them to be modified by some outside factor. To help in the transition a full set of peripheral drivers and their pinmux settings will be introduced shortly.
Additionally there is a pinmux helper driver that allows runtime switching between different per-state pinmux-settings. For example:
 bar_pinmux_helper {
  compatible = "bone-pinmux-helper";
  status = "okay";
  pinctrl-names = "input", "output";
  pinctrl-0 = <&bar_input_gpio_pins>;
  pinctrl-1 = <&bar_output_gpio_pins>;
 };
This device node creates a pinmux helper device which defines two pinmux states, named input and output. You can switch between them simply by
        # echo input  >/sys/devices/ocp*/bar_pinmux_helper*/state
        # echo output >/sys/devices/ocp*/bar_pinmux_helper*/state
Note that there is a very slim chance for this driver to be admitted in mainline, but you can use it if it helps you port to the new kernel.
Q: How do I support any kind GPIO/I2C/SPI etc. device. It is completely different.
A: It is. Examples will be provided on how to do most of the standard peripheral configurations. What you get for the change is the ability to create any kind of device without having to recompile the kernel.
Q: My LCD/GPMC/$RANDOM based device doesn't work on the black.
A: The eMMC and HDMI parts of the Black are using the same pins. If you define a cape with the proper resource definitions, the user cape will take precedence. Hardware restrictions might apply (i.e. pin loading issues etc).
Q: Why can't you carry on using the board file method, seems to work just fine.
A: The writing was on the wall; no way we could ever get the beaglebone in the mainline using it. On top of that any new cape that is produced, either by TI/CCO or the community had to patch the board file to make it work. While this is doable when you have a couple of capes, when you expect dozens of capes, most of them produced by community members, having to expect them to hack the board file, is completely out of the question.
Q: The pinmux values are really hard to figure out from the manuals. One has to hunt in the TRM, the datasheet of the specific processor, and the beaglebone SRM to figure them out.
A: There are resources with the muxing options. Please see: Pinmux Tables
Q: Too many words! Grog angry! Concrete example!
A: Example of an RS232 cape that uses UART2:
 /*
  * Copyright (C) 2013 Matt Ranostay 
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
 /dts-v1/;
 /plugin/;

 / {
  compatible = "ti,beaglebone", "ti,beaglebone-black";

  /* identification */
  part-number = "BB-BONE-RS232";
  version = "00A0";
  
  /* state the resources this cape uses */
  exclusive-use =
   /* the pin header uses */
   "P9.22",                /* rs232: uart2_rxd */
   "P9.21",                /* rs232: uart2_txd */
   /* the hardware IP uses */
   "uart2";

  fragment@0 {
   target = <&am33xx_pinmux>;
   __overlay__ {
    uart_pins: pinmux_uart_pins {
     pinctrl-single,pins = <
      0x150        0x21        /* spi0_sclk.uart2_rxd | 
           * MODE1 | PULL_UP */
      0x154        0x01        /* spi0_d0.uart2_txd | MODE1 */
     >;
    };
   };
  };

  fragment@1 {
   target = <&uart3>;        /* remember the +1 peculiarity */
   __overlay__ {
    status = "okay";
    pinctrl-names = "default";
    pinctrl-0 = <&uart_pins>;
   };
  };
 };
This file is located in the kernel sources at
        firmware/capes/BB-BONE-RS232-00A0.dts
Compile with:
 $ dtc -O dtb -o BB-BONE-RS232-00A0.dtbo -b 0 -@ BB-BONE-RS232-00A0.dts
Copy to /lib/firmware:
        # cp BB-BONE-RS232-00A0.dtbo /lib/firmware
Activate:
        # echo BB-BONE-RS232 >/sys/devices/bone_capemgr*/slots
Q: I still can’t figure it out! Any pointers out there on how to do stuff?
A: A lot of examples in firmware/capes exist
UART virtual capes: firmware/capes/BB-UART*.dts I2C virtual capes: firmware/capes/BB-I2C*.dts SPI virtual capes: firmware/capes/BB-SPI*.dts
        # echo BB-UART5 >/sys/devices/bone_capemgr*/slots
Configures UART5, a new /dev/ttyOx device will be created (devices are created sequentially) and will be ready to use.
Similarly
        # echo BB-I2C1 >/sys/devices/bone_capemgr*/slots
Creates a new I2C bus master. Note that when you have your own I2C devices that you need to access, you can either use the user-space I2C API, or create a device node for your device in the cape. The example capes have commented out examples on how to do that. All those virtual capes can be used as a base for your own experimentation.
Q: I still hate Device Tree!!!
A: Sorry, we cannot help you