blob: 7037d3687e9ff47ec5184f261227a15b2431e14c [file] [log] [blame]
Rabin Vincent705e0982011-01-21 10:56:16 +05301/*
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"
Linus Walleij7a4f2602012-09-19 19:31:19 +020016#include "id.h"
Rabin Vincent705e0982011-01-21 10:56:16 +053017
18enum mop500_uib {
19 STUIB,
20 U8500UIB,
21};
22
23struct uib {
24 const char *name;
25 const char *option;
26 void (*init)(void);
27};
28
Robert Marklund58402b6e32011-06-20 13:30:35 +020029static struct uib __initdata mop500_uibs[] = {
Rabin Vincent705e0982011-01-21 10:56:16 +053030 [STUIB] = {
31 .name = "ST-UIB",
32 .option = "stuib",
33 .init = mop500_stuib_init,
34 },
35 [U8500UIB] = {
36 .name = "U8500-UIB",
37 .option = "u8500uib",
38 .init = mop500_u8500uib_init,
39 },
40};
41
42static struct uib *mop500_uib;
43
44static int __init mop500_uib_setup(char *str)
45{
46 int i;
47
48 for (i = 0; i < ARRAY_SIZE(mop500_uibs); i++) {
49 struct uib *uib = &mop500_uibs[i];
50
51 if (!strcmp(str, uib->option)) {
52 mop500_uib = uib;
53 break;
54 }
55 }
56
57 if (i == ARRAY_SIZE(mop500_uibs))
58 pr_err("invalid uib= option (%s)\n", str);
59
60 return 1;
61}
62__setup("uib=", mop500_uib_setup);
63
64/*
65 * The UIBs are detected after the I2C host controllers are registered, so
66 * i2c_register_board_info() can't be used.
67 */
68void mop500_uib_i2c_add(int busnum, struct i2c_board_info *info,
69 unsigned n)
70{
71 struct i2c_adapter *adap;
72 struct i2c_client *client;
73 int i;
74
75 adap = i2c_get_adapter(busnum);
76 if (!adap) {
77 pr_err("failed to get adapter i2c%d\n", busnum);
78 return;
79 }
80
81 for (i = 0; i < n; i++) {
82 client = i2c_new_device(adap, &info[i]);
83 if (!client)
84 pr_err("failed to register %s to i2c%d\n",
85 info[i].type, busnum);
86 }
87
88 i2c_put_adapter(adap);
89}
90
91static void __init __mop500_uib_init(struct uib *uib, const char *why)
92{
93 pr_info("%s (%s)\n", uib->name, why);
94 uib->init();
95}
96
97/*
98 * Detect the UIB attached based on the presence or absence of i2c devices.
99 */
Lee Jonesfd6948b2012-05-02 09:53:48 +0100100int __init mop500_uib_init(void)
Rabin Vincent705e0982011-01-21 10:56:16 +0530101{
102 struct uib *uib = mop500_uib;
103 struct i2c_adapter *i2c0;
104 int ret;
105
Linus Walleijbc71c092012-01-23 11:54:44 +0100106 if (!cpu_is_u8500_family())
Rabin Vincent705e0982011-01-21 10:56:16 +0530107 return -ENODEV;
108
109 if (uib) {
110 __mop500_uib_init(uib, "from uib= boot argument");
111 return 0;
112 }
113
114 i2c0 = i2c_get_adapter(0);
115 if (!i2c0) {
116 __mop500_uib_init(&mop500_uibs[STUIB],
117 "fallback, could not get i2c0");
118 return -ENODEV;
119 }
120
121 /* U8500-UIB has the TC35893 at 0x44 on I2C0, the ST-UIB doesn't. */
122 ret = i2c_smbus_xfer(i2c0, 0x44, 0, I2C_SMBUS_WRITE, 0,
123 I2C_SMBUS_QUICK, NULL);
124 i2c_put_adapter(i2c0);
125
126 if (ret == 0)
127 uib = &mop500_uibs[U8500UIB];
128 else
129 uib = &mop500_uibs[STUIB];
130
131 __mop500_uib_init(uib, "detected");
132
133 return 0;
134}