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