summaryrefslogtreecommitdiff
path: root/arch/arm/mach-ux500/board-mop500-uib.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2011-03-18 05:08:06 +0300
committerLinus Torvalds <torvalds@linux-foundation.org>2011-03-18 05:08:06 +0300
commit411f5c7a502769ccc0377c5ba36cb0b283847ba8 (patch)
tree2c3a29671e3f923de48c55f94194849264a7bf53 /arch/arm/mach-ux500/board-mop500-uib.c
parent6d7ed21d17e640b120b902a314143e5ef4917a70 (diff)
parent9ced9f03d12d7539e86b0bff5bc750153c976c34 (diff)
downloadlinux-411f5c7a502769ccc0377c5ba36cb0b283847ba8.tar.xz
Merge branch 'devel-stable' of master.kernel.org:/home/rmk/linux-2.6-arm
* 'devel-stable' of master.kernel.org:/home/rmk/linux-2.6-arm: (289 commits) davinci: DM644x EVM: register MUSB device earlier davinci: add spi devices on tnetv107x evm davinci: add ssp config for tnetv107x evm board davinci: add tnetv107x ssp platform device spi: add ti-ssp spi master driver mfd: add driver for sequencer serial port ARM: EXYNOS4: Implement Clock gating for System MMU ARM: EXYNOS4: Enhancement of System MMU driver ARM: EXYNOS4: Add support for gpio interrupts ARM: S5P: Add function to register gpio interrupt bank data ARM: S5P: Cleanup S5P gpio interrupt code ARM: EXYNOS4: Add missing GPYx banks ARM: S3C64XX: Fix section mismatch from cpufreq init ARM: EXYNOS4: Add keypad device to the SMDKV310 ARM: EXYNOS4: Update clocks for keypad ARM: EXYNOS4: Update keypad base address ARM: EXYNOS4: Add keypad device helpers ARM: EXYNOS4: Add support for SATA on ARMLEX4210 plat-nomadik: make GPIO interrupts work with cpuidle ApSleep mach-u300: define a dummy filter function for coh901318 ... Fix up various conflicts in - arch/arm/mach-exynos4/cpufreq.c - arch/arm/mach-mxs/gpio.c - drivers/net/Kconfig - drivers/tty/serial/Kconfig - drivers/tty/serial/Makefile - drivers/usb/gadget/fsl_mxc_udc.c - drivers/video/Kconfig
Diffstat (limited to 'arch/arm/mach-ux500/board-mop500-uib.c')
-rw-r--r--arch/arm/mach-ux500/board-mop500-uib.c135
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 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson
+ * License terms: GNU General Public License (GPL), version 2
+ */
+
+#define pr_fmt(fmt) "mop500-uib: " fmt
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/i2c.h>
+
+#include <mach/hardware.h>
+#include "board-mop500.h"
+
+enum mop500_uib {
+ STUIB,
+ U8500UIB,
+};
+
+struct uib {
+ const char *name;
+ const char *option;
+ void (*init)(void);
+};
+
+static struct __initdata uib mop500_uibs[] = {
+ [STUIB] = {
+ .name = "ST-UIB",
+ .option = "stuib",
+ .init = mop500_stuib_init,
+ },
+ [U8500UIB] = {
+ .name = "U8500-UIB",
+ .option = "u8500uib",
+ .init = mop500_u8500uib_init,
+ },
+};
+
+static struct uib *mop500_uib;
+
+static int __init mop500_uib_setup(char *str)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(mop500_uibs); i++) {
+ struct uib *uib = &mop500_uibs[i];
+
+ if (!strcmp(str, uib->option)) {
+ mop500_uib = uib;
+ break;
+ }
+ }
+
+ if (i == ARRAY_SIZE(mop500_uibs))
+ pr_err("invalid uib= option (%s)\n", str);
+
+ return 1;
+}
+__setup("uib=", mop500_uib_setup);
+
+/*
+ * The UIBs are detected after the I2C host controllers are registered, so
+ * i2c_register_board_info() can't be used.
+ */
+void mop500_uib_i2c_add(int busnum, struct i2c_board_info *info,
+ unsigned n)
+{
+ struct i2c_adapter *adap;
+ struct i2c_client *client;
+ int i;
+
+ adap = i2c_get_adapter(busnum);
+ if (!adap) {
+ pr_err("failed to get adapter i2c%d\n", busnum);
+ return;
+ }
+
+ for (i = 0; i < n; i++) {
+ client = i2c_new_device(adap, &info[i]);
+ if (!client)
+ pr_err("failed to register %s to i2c%d\n",
+ info[i].type, busnum);
+ }
+
+ i2c_put_adapter(adap);
+}
+
+static void __init __mop500_uib_init(struct uib *uib, const char *why)
+{
+ pr_info("%s (%s)\n", uib->name, why);
+ uib->init();
+}
+
+/*
+ * Detect the UIB attached based on the presence or absence of i2c devices.
+ */
+static int __init mop500_uib_init(void)
+{
+ struct uib *uib = mop500_uib;
+ struct i2c_adapter *i2c0;
+ int ret;
+
+ if (!cpu_is_u8500())
+ return -ENODEV;
+
+ if (uib) {
+ __mop500_uib_init(uib, "from uib= boot argument");
+ return 0;
+ }
+
+ i2c0 = i2c_get_adapter(0);
+ if (!i2c0) {
+ __mop500_uib_init(&mop500_uibs[STUIB],
+ "fallback, could not get i2c0");
+ return -ENODEV;
+ }
+
+ /* U8500-UIB has the TC35893 at 0x44 on I2C0, the ST-UIB doesn't. */
+ ret = i2c_smbus_xfer(i2c0, 0x44, 0, I2C_SMBUS_WRITE, 0,
+ I2C_SMBUS_QUICK, NULL);
+ i2c_put_adapter(i2c0);
+
+ if (ret == 0)
+ uib = &mop500_uibs[U8500UIB];
+ else
+ uib = &mop500_uibs[STUIB];
+
+ __mop500_uib_init(uib, "detected");
+
+ return 0;
+}
+
+module_init(mop500_uib_init);