Linux Audio

Check our new training course

Loading...
  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 */
 99int __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_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,
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}