diff options
author | Rabin Vincent <rabin.vincent@stericsson.com> | 2011-01-21 00:26:16 -0500 |
---|---|---|
committer | Linus Walleij <linus.walleij@linaro.org> | 2011-03-14 09:05:10 -0400 |
commit | 705e0984444bc7109c5686c36333b27119d8a888 (patch) | |
tree | 3abc89595f1d0eabf6a7b320d2ca493af07b415e /arch/arm/mach-ux500/board-mop500-uib.c | |
parent | 871056e7dfb6164ffd6c6665752f921f9d5c6a81 (diff) |
mach-ux500: dynamic UIB (user interface boards) detection
Add support for dynamic detection of the UIB used (at the cost of one i2c error
on the lesser-used UIB) and also provide an override via a command line
parameter if needed.
Signed-off-by: Rabin Vincent <rabin.vincent@stericsson.com>
Signed-off-by: Sundar Iyer <sundar.iyer@stericsson.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'arch/arm/mach-ux500/board-mop500-uib.c')
-rw-r--r-- | arch/arm/mach-ux500/board-mop500-uib.c | 135 |
1 files changed, 135 insertions, 0 deletions
diff --git a/arch/arm/mach-ux500/board-mop500-uib.c b/arch/arm/mach-ux500/board-mop500-uib.c new file mode 100644 index 000000000000..69cce41f602a --- /dev/null +++ b/arch/arm/mach-ux500/board-mop500-uib.c | |||
@@ -0,0 +1,135 @@ | |||
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); | ||