Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6
[pandora-kernel.git] / arch / arm / mach-ux500 / board-mop500-uib.c
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
17 enum mop500_uib {
18         STUIB,
19         U8500UIB,
20 };
21
22 struct uib {
23         const char *name;
24         const char *option;
25         void (*init)(void);
26 };
27
28 static struct __initdata uib 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  */
67 void 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
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  */
99 static 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
135 module_init(mop500_uib_init);