[PATCH 1/5] capemgr: Beaglebone DT overlay based cape manager

Linus Walleij linus.walleij at linaro.org
Wed Jan 9 19:29:26 EST 2013


On Wed, Jan 9, 2013 at 9:11 AM, Lee Jones <lee.jones at linaro.org> wrote:
> On Tue, 08 Jan 2013, Arnd Bergmann wrote:
>
>> On Tuesday 08 January 2013, Pantelis Antoniou wrote:
>> > On Jan 8, 2013, at 2:12 PM, Arnd Bergmann wrote:
>> >
>> > > On Tuesday 08 January 2013, Lee Jones wrote:
>> > >>> If there is not, there is no way to automatically load the overlays; you can always
>> > >>> use the kernel command line, or have the a user space application to request the loading
>> > >>> of a specific board's overlay.
>> > >>
>> > >> Unfortunately, there is no way to probe the UIBs. :(
>> > >
>> > > I thought that some of the newer UIBs had it, just not the old ones.
>> > > As Pantelis says, we could at least detect the ones that have an EEPROM
>> > > on them, and use a command line option or device tree attribute for the others.
>> > >
>> > >       Arnd
>> >
>> > So I gather the new ones have an eeprom?
>>
>> I don't remember the details unfortunately. Lee should be the one who can find out.
>> IIRC there was at least a single integeger number on them.
>
> Not as far as I can remember. There was (is?) a crude method of
> identifying UIBs, but attempting to obtain certain I2C lines and
> testing which ones were accessible. However, if there is an issue
> with I2C, the wrong UIB was 'probed'.

Right, so the UIBs had different GPIO expanders on some I2C addresses,
so we attempt to communicate with the expander to see if it's board type A,
and if it doesn't respond it's deemed to be board type B.

This is the code:
arch/arm/mach-ux500/board-mop500-uib.c

/*
 * Detect the UIB attached based on the presence or absence of i2c devices.
 */
int __init mop500_uib_init(void)
{
        struct uib *uib = mop500_uib;
        struct i2c_adapter *i2c0;
        int ret;

        if (!cpu_is_u8500_family())
                return -ENODEV;

        if (uib) {
                __mop500_uib_init(uib, "from uib= boot argument");
                return 0;
        }

        i2c0 = i2c_get_adapter(0);
        if (!i2c0) {
                __mop500_uib_init(&mop500_uibs[STUIB],
                                "fallback, could not get i2c0");
                return -ENODEV;
        }

        /* U8500-UIB has the TC35893 at 0x44 on I2C0, the ST-UIB doesn't. */
        ret = i2c_smbus_xfer(i2c0, 0x44, 0, I2C_SMBUS_WRITE, 0,
                        I2C_SMBUS_QUICK, NULL);
        i2c_put_adapter(i2c0);

        if (ret == 0)
                uib = &mop500_uibs[U8500UIB];
        else
                uib = &mop500_uibs[STUIB];

        __mop500_uib_init(uib, "detected");

        return 0;
}

Not elegant but better than e.g. passing a kernel command line option.

As you say it has the downside of detecting the wrong UIB if there is
some (other) problem with the I2C block. But in that case the system is
likely borked anyway so I wonder if it matters...

Even with the device tree approach we'd be into trouble if say, the UIB
was unplugged (which is perfectly possible). The device tree cannot
detect that.

The larger question is how to handle, at runtime, hardware that may
or may not be present, in a device tree world.

Compare this other case: the Integrator has pluggable daughterboards,
(called LMs, logic modules) and in that case we have specific registers
to detect them, and register the daughter board on this specific bus
that Russell came up with in arch/arm/mach-integrator/lm.c,
the actual board detection is in arch/arm/mach-integrator/integrator_ap.c:

static void __init ap_init(void)
{
        unsigned long sc_dec;
        int i;

        platform_device_register(&cfi_flash_device);

        sc_dec = readl(ap_syscon_base + INTEGRATOR_SC_DEC_OFFSET);
        for (i = 0; i < 4; i++) {
                struct lm_device *lmdev;

                if ((sc_dec & (16 << i)) == 0)
                        continue;

                lmdev = kzalloc(sizeof(struct lm_device), GFP_KERNEL);
                if (!lmdev)
                        continue;

                lmdev->resource.start = 0xc0000000 + 0x10000000 * i;
                lmdev->resource.end = lmdev->resource.start + 0x0fffffff;
                lmdev->resource.flags = IORESOURCE_MEM;
                lmdev->irq = IRQ_AP_EXPINT0 + i;
                lmdev->id = i;

                lm_device_register(lmdev);
        }

        integrator_init(false);
}

In this case I think the autodetect is so nice that device tree probing
is mostly pointless. If it wasn't for the fact that we get a
cross-depenency to defined interrupts and clocks and whatever that
are coming from the device tree. Which is where DT shows its
all-or-nothing face.

So to get an elegant DT probing in this case I *guess* the right thing
to do is to dynamically add nodes to the device tree from the board
code, or have all alternatives inside the DT marked "disable" and then
mark them as "okay" from the board code by modifying the DT at
runtime.

Ideas welcome.

Yours,
Linus Walleij


More information about the devicetree-discuss mailing list