summaryrefslogtreecommitdiff
path: root/arch/arm/mach-ux500/board-mop500-uib.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-ux500/board-mop500-uib.c')
-rw-r--r--arch/arm/mach-ux500/board-mop500-uib.c178
1 files changed, 163 insertions, 15 deletions
diff --git a/arch/arm/mach-ux500/board-mop500-uib.c b/arch/arm/mach-ux500/board-mop500-uib.c
index 5af36aa56c0..908c5d973da 100644
--- a/arch/arm/mach-ux500/board-mop500-uib.c
+++ b/arch/arm/mach-ux500/board-mop500-uib.c
@@ -1,4 +1,5 @@
/*
+
* Copyright (C) ST-Ericsson SA 2010
*
* Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson
@@ -10,13 +11,22 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/i2c.h>
+#include <linux/platform_device.h>
+#include <linux/input.h>
+#include <linux/gpio_keys.h>
+#include <linux/regulator/consumer.h>
#include <mach/hardware.h>
+#include <asm/mach-types.h>
+
+#include "pins.h"
#include "board-mop500.h"
enum mop500_uib {
STUIB,
U8500UIB,
+ U8500UIB_R3,
+ NO_UIB,
};
struct uib {
@@ -25,6 +35,8 @@ struct uib {
void (*init)(void);
};
+static u8 type_of_uib = NO_UIB;
+
static struct uib __initdata mop500_uibs[] = {
[STUIB] = {
.name = "ST-UIB",
@@ -36,9 +48,16 @@ static struct uib __initdata mop500_uibs[] = {
.option = "u8500uib",
.init = mop500_u8500uib_init,
},
+#ifdef CONFIG_TOUCHSCREEN_CYTTSP_SPI
+ [U8500UIB_R3] = {
+ .name = "U8500-UIBR3",
+ .option = "u8500uibr3",
+ .init = mop500_u8500uib_r3_init,
+ },
+#endif
};
-static struct uib *mop500_uib;
+static struct uib __initdata *mop500_uib;
static int __init mop500_uib_setup(char *str)
{
@@ -64,7 +83,7 @@ __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,
+void mop500_uib_i2c_add(int busnum, struct i2c_board_info const *info,
unsigned n)
{
struct i2c_adapter *adap;
@@ -90,26 +109,137 @@ void mop500_uib_i2c_add(int busnum, struct i2c_board_info *info,
static void __init __mop500_uib_init(struct uib *uib, const char *why)
{
pr_info("%s (%s)\n", uib->name, why);
+
+ if (strcmp("stuib", uib->option) == 0)
+ type_of_uib = STUIB;
+ else if (strcmp("u8500uib", uib->option) == 0)
+ type_of_uib = U8500UIB;
+ else if (strcmp("u8500uibr3", uib->option) == 0)
+ type_of_uib = U8500UIB_R3;
+
uib->init();
}
+int uib_is_stuib(void)
+{
+ return (type_of_uib == STUIB);
+}
+
+int uib_is_u8500uib(void)
+{
+ return (type_of_uib == U8500UIB);
+}
+
+int uib_is_u8500uibr3(void)
+{
+ return (type_of_uib == U8500UIB_R3);
+}
+
+
+#ifdef CONFIG_UX500_GPIO_KEYS
+static struct gpio_keys_button mop500_gpio_keys[] = {
+ {
+ .desc = "SFH7741 Proximity Sensor",
+ .type = EV_SW,
+ .code = SW_FRONT_PROXIMITY,
+ .active_low = 0,
+ .can_disable = 1,
+ },
+ {
+ .desc = "HED54XXU11 Hall Effect Sensor",
+ .type = EV_SW,
+ .code = SW_LID, /* FIXME arbitrary usage */
+ .active_low = 0,
+ .can_disable = 1,
+ }
+};
+
+static struct regulator *gpio_keys_regulator;
+static int mop500_gpio_keys_activate(struct device *dev);
+static void mop500_gpio_keys_deactivate(struct device *dev);
+
+static struct gpio_keys_platform_data mop500_gpio_keys_data = {
+ .buttons = mop500_gpio_keys,
+ .nbuttons = ARRAY_SIZE(mop500_gpio_keys),
+ .enable = mop500_gpio_keys_activate,
+ .disable = mop500_gpio_keys_deactivate,
+};
+
+static struct platform_device mop500_gpio_keys_device = {
+ .name = "gpio-keys",
+ .id = 0,
+ .dev = {
+ .platform_data = &mop500_gpio_keys_data,
+ },
+};
+
+static int mop500_gpio_keys_activate(struct device *dev)
+{
+ gpio_keys_regulator = regulator_get(&mop500_gpio_keys_device.dev,
+ "vcc");
+ if (IS_ERR(gpio_keys_regulator)) {
+ dev_err(&mop500_gpio_keys_device.dev, "no regulator\n");
+ return PTR_ERR(gpio_keys_regulator);
+ }
+ regulator_enable(gpio_keys_regulator);
+
+ /*
+ * Please be aware that the start-up time of the SFH7741 is
+ * 120 ms and during that time the output is undefined.
+ */
+
+ return 0;
+}
+
+static void mop500_gpio_keys_deactivate(struct device *dev)
+{
+ if (!IS_ERR(gpio_keys_regulator)) {
+ regulator_disable(gpio_keys_regulator);
+ regulator_put(gpio_keys_regulator);
+ }
+}
+
+static __init void mop500_gpio_keys_init(void)
+{
+ struct ux500_pins *gpio_keys_pins = ux500_pins_get("gpio-keys.0");
+
+ if (gpio_keys_pins == NULL) {
+ pr_err("gpio_keys: Fail to get pins\n");
+ return;
+ }
+
+ ux500_pins_enable(gpio_keys_pins);
+ if (type_of_uib == U8500UIB_R3)
+ mop500_gpio_keys[0].gpio = PIN_NUM(gpio_keys_pins->cfg[2]);
+ else
+ mop500_gpio_keys[0].gpio = PIN_NUM(gpio_keys_pins->cfg[0]);
+ mop500_gpio_keys[1].gpio = PIN_NUM(gpio_keys_pins->cfg[1]);
+}
+#else
+static inline void mop500_gpio_keys_init(void) { }
+#endif
+
+/* add any platform devices here - TODO */
+static struct platform_device *mop500_uib_platform_devs[] __initdata = {
+#ifdef CONFIG_UX500_GPIO_KEYS
+ &mop500_gpio_keys_device,
+#endif
+};
+
/*
* 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 uib *uib = mop500_uibs;
struct i2c_adapter *i2c0;
+ struct i2c_adapter *i2c3;
int ret;
- if (!cpu_is_u8500())
+ /* snowball and non u8500 cpus dont have uib */
+ if (!cpu_is_u8500() || machine_is_snowball())
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],
@@ -121,14 +251,32 @@ static int __init mop500_uib_init(void)
ret = i2c_smbus_xfer(i2c0, 0x44, 0, I2C_SMBUS_WRITE, 0,
I2C_SMBUS_QUICK, NULL);
i2c_put_adapter(i2c0);
+ i2c3 = i2c_get_adapter(3);
+ if (!i2c3) {
+ __mop500_uib_init(&mop500_uibs[STUIB],
+ "fallback, could not get i2c3");
+ return -ENODEV;
+ }
- if (ret == 0)
- uib = &mop500_uibs[U8500UIB];
- else
- uib = &mop500_uibs[STUIB];
-
+ if (ret == 0) {
+ ret = i2c_smbus_xfer(i2c3, 0x4B, 0, I2C_SMBUS_WRITE, 0,
+ I2C_SMBUS_QUICK, NULL);
+ i2c_put_adapter(i2c3);
+ if (ret == 0)
+ uib = &mop500_uibs[U8500UIB];
+ else
+ uib = &mop500_uibs[U8500UIB_R3];
+ } else {
+ ret = i2c_smbus_xfer(i2c3, 0x5C, 0, I2C_SMBUS_WRITE, 0,
+ I2C_SMBUS_QUICK, NULL);
+ i2c_put_adapter(i2c3);
+ if (ret == 0)
+ uib = &mop500_uibs[STUIB];
+ }
__mop500_uib_init(uib, "detected");
-
+ mop500_gpio_keys_init();
+ platform_add_devices(mop500_uib_platform_devs,
+ ARRAY_SIZE(mop500_uib_platform_devs));
return 0;
}