Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
board-mop500-uib.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) ST-Ericsson SA 2010
3  *
4  * Author: Rabin Vincent <[email protected]> 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 
17 enum mop500_uib {
20 };
21 
22 struct uib {
23  const char *name;
24  const char *option;
25  void (*init)(void);
26 };
27 
28 static 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 
41 static struct uib *mop500_uib;
42 
43 static 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  */
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 
90 static 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  */
100 {
101  struct uib *uib = mop500_uib;
102  struct i2c_adapter *i2c0;
103  int ret;
104 
105  if (!cpu_is_u8500_family())
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,
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 }