linux/arch/arm/mach-ux500/board-mop500-uib.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) ST-Ericsson SA 2010
   3 *
   4 * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson
   5 * License terms: GNU General Public License (GPL), version 2
   6 */
   7
   8#define pr_fmt(fmt)     "mop500-uib: " fmt
   9
  10#include <linux/kernel.h>
  11#include <linux/init.h>
  12#include <linux/i2c.h>
  13
  14#include <mach/hardware.h>
  15#include "board-mop500.h"
  16
  17enum mop500_uib {
  18        STUIB,
  19        U8500UIB,
  20};
  21
  22struct uib {
  23        const char *name;
  24        const char *option;
  25        void (*init)(void);
  26};
  27
  28static struct uib __initdata mop500_uibs[] = {
  29        [STUIB] = {
  30                .name   = "ST-UIB",
  31                .option = "stuib",
  32                .init   = mop500_stuib_init,
  33        },
  34        [U8500UIB] = {
  35                .name   = "U8500-UIB",
  36                .option = "u8500uib",
  37                .init   = mop500_u8500uib_init,
  38        },
  39};
  40
  41static struct uib *mop500_uib;
  42
  43static int __init mop500_uib_setup(char *str)
  44{
  45        int i;
  46
  47        for (i = 0; i < ARRAY_SIZE(mop500_uibs); i++) {
  48                struct uib *uib = &mop500_uibs[i];
  49
  50                if (!strcmp(str, uib->option)) {
  51                        mop500_uib = uib;
  52                        break;
  53                }
  54        }
  55
  56        if (i == ARRAY_SIZE(mop500_uibs))
  57                pr_err("invalid uib= option (%s)\n", str);
  58
  59        return 1;
  60}
  61__setup("uib=", mop500_uib_setup);
  62
  63/*
  64 * The UIBs are detected after the I2C host controllers are registered, so
  65 * i2c_register_board_info() can't be used.
  66 */
  67void mop500_uib_i2c_add(int busnum, struct i2c_board_info *info,
  68                unsigned n)
  69{
  70        struct i2c_adapter *adap;
  71        struct i2c_client *client;
  72        int i;
  73
  74        adap = i2c_get_adapter(busnum);
  75        if (!adap) {
  76                pr_err("failed to get adapter i2c%d\n", busnum);
  77                return;
  78        }
  79
  80        for (i = 0; i < n; i++) {
  81                client = i2c_new_device(adap, &info[i]);
  82                if (!client)
  83                        pr_err("failed to register %s to i2c%d\n",
  84                                        info[i].type, busnum);
  85        }
  86
  87        i2c_put_adapter(adap);
  88}
  89
  90static void __init __mop500_uib_init(struct uib *uib, const char *why)
  91{
  92        pr_info("%s (%s)\n", uib->name, why);
  93        uib->init();
  94}
  95
  96/*
  97 * Detect the UIB attached based on the presence or absence of i2c devices.
  98 */
  99static int __init mop500_uib_init(void)
 100{
 101        struct uib *uib = mop500_uib;
 102        struct i2c_adapter *i2c0;
 103        int ret;
 104
 105        if (!cpu_is_u8500())
 106                return -ENODEV;
 107
 108        if (uib) {
 109                __mop500_uib_init(uib, "from uib= boot argument");
 110                return 0;
 111        }
 112
 113        i2c0 = i2c_get_adapter(0);
 114        if (!i2c0) {
 115                __mop500_uib_init(&mop500_uibs[STUIB],
 116                                "fallback, could not get i2c0");
 117                return -ENODEV;
 118        }
 119
 120        /* U8500-UIB has the TC35893 at 0x44 on I2C0, the ST-UIB doesn't. */
 121        ret = i2c_smbus_xfer(i2c0, 0x44, 0, I2C_SMBUS_WRITE, 0,
 122                        I2C_SMBUS_QUICK, NULL);
 123        i2c_put_adapter(i2c0);
 124
 125        if (ret == 0)
 126                uib = &mop500_uibs[U8500UIB];
 127        else
 128                uib = &mop500_uibs[STUIB];
 129
 130        __mop500_uib_init(uib, "detected");
 131
 132        return 0;
 133}
 134
 135module_init(mop500_uib_init);
 136