Rob's Technical Article: Board files and your device


I have seen a lot of documentation about drivers of all sorts, including books full of information about writing drivers, assembling embedded systems and whatnot, but nowhere have I seen any information about the board file. I am amazed that there has been so much secrecy on this subject... It's almost like there's some... dare I say it? Conspiracy.

All joking aside, systems that have I2C, SPI or other type of driver will require the person assembling the device to register their peripherals in the board file. This file is often found in your architecture area, in the kernel directory /arch/MAJOR_ARCH/SUB_ARCH/, for example, /arch/arm/mach-msm/.

First, we'll want to know where it is connected and what address it'll use. I'll freely steal code from the file /arch/arm/mach-mx5/board-cpuimx51sd.c which is in one of my kernel distros. I honestly don't know what this is, but I spotted this chip in use in the board file, so I'll use it.

NOTE: Carefully read your board file, or another one in the same architecture. Although many of the principles are the same, there will be some rather large differences between this tutorial and your architecture.

First, make sure you include the appropriate files in your board file...

#include <linux/i2c.h>
#include <linux/i2c/tsc2007.h>

Next, you'll want to establish the GPIO that's to be used for the interrupt, set up the platform data block defined in the above mentioned tsc2007.h include.


static struct tsc2007_platform_data tsc2007_info = 
{
        .model                  = 2007,
        .x_plate_ohms           = 180,
};


Assemble all of this information in the i2c_board_info block. There may already be an array of i2c_board_info blocks already in your board file.


#define TSC2007_IRQGPIO         IMX_GPIO_NR(3, 2)
static struct i2c_board_info eukrea_cpuimx35_i2c_devices[] = 
{
        {
                I2C_BOARD_INFO("pcf8563", 0x51),
        },
	{
                I2C_BOARD_INFO("tsc2007", 0x48),
                .type           = "tsc2007",
                .platform_data  = &tsc2007_info,
                .irq            = gpio_to_irq(TSC2007_IRQGPIO),
        },
};

Once we've got this all assembled, we've got to make sure that the i2c bus is initialized in the main init functions in the bottom of the board file.

static void __init eukrea_cpuimx35_init(void)
{
        mxc_iomux_v3_setup_multiple_pads(eukrea_cpuimx35_pads,
                        ARRAY_SIZE(eukrea_cpuimx35_pads));

        imx35_add_fec(NULL);
        imx35_add_imx2_wdt(NULL);

        imx35_add_imx_uart0(&uart_pdata);
        imx35_add_mxc_nand(&eukrea_cpuimx35_nand_board_info);

        i2c_register_board_info(0, eukrea_cpuimx35_i2c_devices,
                        ARRAY_SIZE(eukrea_cpuimx35_i2c_devices));
        imx35_add_imx_i2c0(&eukrea_cpuimx35_i2c0_data);

        if (otg_mode_host)
                imx35_add_mxc_ehci_otg(&otg_pdata);
        else
                imx35_add_fsl_usb2_udc(&otg_device_pdata);

        imx35_add_mxc_ehci_hs(&usbh1_pdata);

#ifdef CONFIG_MACH_EUKREA_MBIMXSD35_BASEBOARD
        eukrea_mbimxsd35_baseboard_init();
#endif
}

If you've got it all put together properly and your driver 'turned on' in the kernel configuration, you should have a working device at this point.



By: Rob Stoddard