summaryrefslogtreecommitdiff
path: root/drivers/mfd
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mfd')
-rw-r--r--drivers/mfd/Makefile1
-rw-r--r--drivers/mfd/m4sensorhub-core.c74
-rw-r--r--drivers/mfd/m4sensorhub-extern.c158
-rw-r--r--drivers/mfd/m4sensorhub-panic.c1
-rw-r--r--drivers/mfd/m4sensorhub-reg.h10
5 files changed, 217 insertions, 27 deletions
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index c0704d70b97..e14fcb9363f 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -171,6 +171,7 @@ m4sensorhub-objs := m4sensorhub-core.o \
m4sensorhub-reg.o \
m4sensorhub-irq.o \
m4sensorhub-panic.o \
+ m4sensorhub-extern.o \
m4sensorhub-stm32-fw.o \
m4sensorhub-stm32_401-fw.o
diff --git a/drivers/mfd/m4sensorhub-core.c b/drivers/mfd/m4sensorhub-core.c
index a10ab20280b..203109e6ac7 100644
--- a/drivers/mfd/m4sensorhub-core.c
+++ b/drivers/mfd/m4sensorhub-core.c
@@ -90,6 +90,12 @@ static ssize_t m4sensorhub_get_dbg(struct device *dev,
/* BEGIN BOARD FILE */
/* TODO: replace with request array */
+int m4sensorhub_get_current_mode(void)
+{
+ return m4sensorhub_misc_data.mode;
+}
+EXPORT_SYMBOL_GPL(m4sensorhub_get_current_mode);
+
int m4sensorhub_set_bootmode(struct m4sensorhub_data *m4sensorhub,
enum m4sensorhub_bootmode bootmode)
{
@@ -496,6 +502,12 @@ static void m4sensorhub_initialize(const struct firmware *firmware,
return;
}
+ err = m4sensorhub_extern_init(&m4sensorhub_misc_data);
+ if (err < 0) {
+ KDEBUG(M4SH_ERROR, "%s: Extern init failed.\n", __func__);
+ return;
+ }
+
/* Initialize all the m4 drivers */
inc = inithead;
arg.p_m4sensorhub_data = &m4sensorhub_misc_data;
@@ -540,20 +552,27 @@ static DEVICE_ATTR(debug_level, S_IRUSR|S_IWUSR, m4sensorhub_get_dbg,
static ssize_t m4sensorhub_get_loglevel(struct device *dev,
struct device_attribute *attr, char *buf)
{
- unsigned long long loglevel;
+ uint32_t logenable[LOG_EN_SIZE], len, i;
m4sensorhub_reg_read(&m4sensorhub_misc_data,
- M4SH_REG_LOG_LOGENABLE, (char *)&loglevel);
- KDEBUG(M4SH_INFO, "M4 loglevel = %llx", loglevel);
- return sprintf(buf, "%llu\n", loglevel);
+ M4SH_REG_LOG_LOGENABLE, (char *)&logenable);
+
+ len = sprintf(buf, "M4 log levels = 0x");
+ for (i = 0; i < LOG_EN_SIZE; i++)
+ len += sprintf(buf+len, "%08x", logenable[i]);
+ KDEBUG(M4SH_INFO, "%s\n", buf);
+ return snprintf(buf, PAGE_SIZE, "%s\n", buf);
}
-void m4sensorhub_update_loglevels(char *tag, char *level,
- unsigned long long *log_levels)
+void m4sensorhub_update_loglevels(int8_t *tag, int8_t *level,
+ uint32_t *log_level)
{
- int i;
- int levelindex = -1;
- int tagindex = -1;
- unsigned long long mask;
+ uint32_t i;
+ int32_t levelindex = -1;
+ int32_t tagindex = -1;
+ uint32_t mask;
+ int32_t logenableindex;
+ int32_t en = LOG_TAGS_PER_ENABLE;
+ int32_t b = LOG_NO_OF_BITS_PER_TAG;
for (i = 0; i < LOG_LEVELS_MAX; i++) {
if (strcmp(acLogLevels[i], level) == 0) {
@@ -568,16 +587,21 @@ void m4sensorhub_update_loglevels(char *tag, char *level,
break;
}
}
-
if ((tagindex == -1) || (levelindex == -1))
return;
+ logenableindex = tagindex/LOG_TAGS_PER_ENABLE;
+
/*Clear the revelant bits*/
- mask = 0x03;
- *log_levels &= ~(mask << (tagindex * 2));
+ mask = LOG_TAG_MASK;
+ *(log_level+logenableindex) &= ~(mask << ((tagindex % en) * b));
/*set debug level for the relevant bits*/
- *log_levels |= (levelindex << (tagindex * 2));
- KDEBUG(M4SH_INFO, "New M4 log levels = 0x%llx\n", *log_levels);
+ *(log_level+logenableindex) |= (levelindex << ((tagindex % en) * b));
+
+ KDEBUG(M4SH_DEBUG, "New M4 log levels = ");
+ for (i = 0; i < LOG_EN_SIZE; i++)
+ KDEBUG(M4SH_DEBUG, "enable %d = 0x%08x ", i, *(log_level+i));
+ KDEBUG(M4SH_DEBUG, "\n");
}
/* Usage: adb shell into the directory of sysinterface log_level and
@@ -585,25 +609,29 @@ void m4sensorhub_update_loglevels(char *tag, char *level,
static ssize_t m4sensorhub_set_loglevel(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
- unsigned long long cur_loglevels;
+ uint32_t cur_loglevels[LOG_EN_SIZE];
char *tag, *level;
char **logbuf = (char **) &buf;
m4sensorhub_reg_read(&m4sensorhub_misc_data,
- M4SH_REG_LOG_LOGENABLE, (char *)&cur_loglevels);
+ M4SH_REG_LOG_LOGENABLE, (char *)cur_loglevels);
+
while (1) {
tag = strsep(logbuf, "=,\n ");
- if (tag == NULL)
+ if ((tag == NULL) || (logbuf == NULL))
break;
level = strsep(logbuf, "=,\n ");
- if (level == NULL)
+ if ((level == NULL) || (logbuf == NULL))
break;
- m4sensorhub_update_loglevels(tag, level, &cur_loglevels);
+ m4sensorhub_update_loglevels(tag, level,
+ (uint32_t *)cur_loglevels);
}
- return m4sensorhub_reg_write(&m4sensorhub_misc_data,
- M4SH_REG_LOG_LOGENABLE, (char *)&cur_loglevels,
- m4sh_no_mask);
+ m4sensorhub_reg_write(&m4sensorhub_misc_data,
+ M4SH_REG_LOG_LOGENABLE, (char *)cur_loglevels,
+ m4sh_no_mask);
+
+ return count;
}
static DEVICE_ATTR(log_level, S_IRUSR|S_IWUSR, m4sensorhub_get_loglevel,
diff --git a/drivers/mfd/m4sensorhub-extern.c b/drivers/mfd/m4sensorhub-extern.c
new file mode 100644
index 00000000000..771dc5cc4f3
--- /dev/null
+++ b/drivers/mfd/m4sensorhub-extern.c
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2014 Motorola, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Adds ability to program periodic interrupts from user space that
+ * can wake the phone out of low power modes.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/m4sensorhub.h>
+#include <linux/slab.h>
+
+#define m4ext_err(format, args...) KDEBUG(M4SH_ERROR, format, ## args)
+
+struct m4sensorhub_data *m4ext_m4;
+DEFINE_MUTEX(m4ext_mutex);
+uint8_t m4ext_display_status;
+uint8_t m4ext_audio_status;
+
+static void m4ext_panic_callback(struct m4sensorhub_data *m4, void *context)
+{
+ int err;
+
+ mutex_lock(&m4ext_mutex);
+
+ if (m4ext_m4 == NULL) {
+ m4ext_err("%s: M4 data is NULL.\n", __func__);
+ err = -ENODATA;
+ goto m4ext_panic_callback_fail;
+ }
+
+ err = m4sensorhub_reg_write(m4, M4SH_REG_USERSETTINGS_SCREENSTATUS,
+ (char *)&m4ext_display_status, m4sh_no_mask);
+ if (err < 0)
+ m4ext_err("%s: Screen status write failed (%d).\n",
+ __func__, err);
+ else if (err != 1)
+ m4ext_err("%s: Screen status wrote %d bytes instead of 1.\n",
+ __func__, err);
+
+ err = m4sensorhub_reg_write(m4, M4SH_REG_USERSETTINGS_AUDIOSTATUS,
+ (char *)&m4ext_audio_status, m4sh_no_mask);
+ if (err < 0)
+ m4ext_err("%s: Audio status write failed (%d).\n",
+ __func__, err);
+ else if (err != 1)
+ m4ext_err("%s: Audio status wrote %d bytes instead of 1.\n",
+ __func__, err);
+
+m4ext_panic_callback_fail:
+ mutex_unlock(&m4ext_mutex);
+ return;
+}
+
+int m4sensorhub_extern_init(struct m4sensorhub_data *m4)
+{
+ int err;
+
+ mutex_lock(&m4ext_mutex);
+
+ err = m4sensorhub_panic_register(m4, PANICHDL_EXTERN_RESTORE,
+ m4ext_panic_callback, NULL);
+ if (err < 0) {
+ m4ext_err("%s: Failed to register panic callback.\n", __func__);
+ goto m4sensorhub_extern_init_fail;
+ }
+
+ m4ext_m4 = m4;
+
+m4sensorhub_extern_init_fail:
+ mutex_unlock(&m4ext_mutex);
+ return err;
+}
+EXPORT_SYMBOL_GPL(m4sensorhub_extern_init);
+
+int m4sensorhub_extern_set_display_status(uint8_t status)
+{
+ int err;
+
+ mutex_lock(&m4ext_mutex);
+
+ if (m4ext_m4 == NULL) {
+ m4ext_err("%s: M4 data is NULL.\n", __func__);
+ err = -ENODATA;
+ goto m4sensorhub_extern_set_display_status_fail;
+ }
+
+ m4ext_display_status = status;
+
+ err = m4sensorhub_reg_write(m4ext_m4,
+ M4SH_REG_USERSETTINGS_SCREENSTATUS,
+ (char *)&status, m4sh_no_mask);
+ if (err < 0) {
+ m4ext_err("%s: I2C write failed (%d).\n", __func__, err);
+ goto m4sensorhub_extern_set_display_status_fail;
+ } else if (err != 1) {
+ m4ext_err("%s: Wrote %d bytes instead of 1.\n", __func__, err);
+ err = -EINVAL;
+ goto m4sensorhub_extern_set_display_status_fail;
+ }
+
+ err = 0;
+
+m4sensorhub_extern_set_display_status_fail:
+ mutex_unlock(&m4ext_mutex);
+ return err;
+}
+EXPORT_SYMBOL_GPL(m4sensorhub_extern_set_display_status);
+
+int m4sensorhub_extern_set_audio_status(uint8_t status)
+{
+ int err;
+
+ mutex_lock(&m4ext_mutex);
+
+ if (m4ext_m4 == NULL) {
+ m4ext_err("%s: M4 data is NULL.\n", __func__);
+ err = -ENODATA;
+ goto m4sensorhub_extern_set_audio_status_fail;
+ }
+
+ m4ext_audio_status = status;
+
+ err = m4sensorhub_reg_write(m4ext_m4,
+ M4SH_REG_USERSETTINGS_AUDIOSTATUS,
+ (char *)&status, m4sh_no_mask);
+ if (err < 0) {
+ m4ext_err("%s: I2C write failed (%d).\n", __func__, err);
+ goto m4sensorhub_extern_set_audio_status_fail;
+ } else if (err != 1) {
+ m4ext_err("%s: Wrote %d bytes instead of 1.\n", __func__, err);
+ err = -EINVAL;
+ goto m4sensorhub_extern_set_audio_status_fail;
+ }
+
+ err = 0;
+
+m4sensorhub_extern_set_audio_status_fail:
+ mutex_unlock(&m4ext_mutex);
+ return err;
+}
+EXPORT_SYMBOL_GPL(m4sensorhub_extern_set_audio_status);
diff --git a/drivers/mfd/m4sensorhub-panic.c b/drivers/mfd/m4sensorhub-panic.c
index b127adeba5c..34ad6658453 100644
--- a/drivers/mfd/m4sensorhub-panic.c
+++ b/drivers/mfd/m4sensorhub-panic.c
@@ -40,6 +40,7 @@ static const char *callback_name[PANICHDL_MAX] = {
[PANICHDL_FUSION_RESTORE] = "fusion_restore",
[PANICHDL_MPU9150_RESTORE] = "mpu9150_restore",
[PANICHDL_PEDOMETER_RESTORE] = "pedometer_restore",
+ [PANICHDL_EXTERN_RESTORE] = "extern_restore",
};
struct m4sensorhub_panic_callback {
diff --git a/drivers/mfd/m4sensorhub-reg.h b/drivers/mfd/m4sensorhub-reg.h
index 96719a08927..753ea9a8846 100644
--- a/drivers/mfd/m4sensorhub-reg.h
+++ b/drivers/mfd/m4sensorhub-reg.h
@@ -87,9 +87,9 @@ static const struct {
[M4SH_REG_FUSION_LOCALX] = {M4SH_TYPE_FUSION, 0x10, 4},
[M4SH_REG_FUSION_LOCALY] = {M4SH_TYPE_FUSION, 0x14, 4},
[M4SH_REG_FUSION_LOCALZ] = {M4SH_TYPE_FUSION, 0x18, 4},
- [M4SH_REG_FUSION_WORLDX] = {M4SH_TYPE_FUSION, 0x1c, 4},
- [M4SH_REG_FUSION_WORLDY] = {M4SH_TYPE_FUSION, 0x20, 4},
- [M4SH_REG_FUSION_WORLDZ] = {M4SH_TYPE_FUSION, 0x24, 4},
+ [M4SH_REG_FUSION_GRAVITYX] = {M4SH_TYPE_FUSION, 0x1c, 4},
+ [M4SH_REG_FUSION_GRAVITYY] = {M4SH_TYPE_FUSION, 0x20, 4},
+ [M4SH_REG_FUSION_GRAVITYZ] = {M4SH_TYPE_FUSION, 0x24, 4},
[M4SH_REG_FUSION_ROTATIONVECTOR] = {M4SH_TYPE_FUSION, 0x28, 16},
[M4SH_REG_FUSION_HEADING] = {M4SH_TYPE_FUSION, 0x38, 2},
[M4SH_REG_FUSION_HEADING_ACCURACY] = {M4SH_TYPE_FUSION, 0x3a, 1},
@@ -112,6 +112,8 @@ static const struct {
[M4SH_REG_METS_METS] = {M4SH_TYPE_METS, 0x4, 4},
[M4SH_REG_METS_CALORIES] = {M4SH_TYPE_METS, 0x8, 4},
[M4SH_REG_METS_HEALTHYMINUTES] = {M4SH_TYPE_METS, 0xc, 4},
+ [M4SH_REG_METS_METS_NO_RMR] = {M4SH_TYPE_METS, 0x10, 4},
+ [M4SH_REG_METS_CALORIES_NO_RMR] = {M4SH_TYPE_METS, 0x14, 4},
[M4SH_REG_USERSETTINGS_SCREENSTATUS] = {M4SH_TYPE_USERSETTINGS, 0x0, 1},
[M4SH_REG_USERSETTINGS_USERAGE] = {M4SH_TYPE_USERSETTINGS, 0x1, 1},
[M4SH_REG_USERSETTINGS_USERGENDER] = {M4SH_TYPE_USERSETTINGS, 0x2, 1},
@@ -205,7 +207,7 @@ static const unsigned int bank_size_tbl[M4SH_TYPE__NUM] = {
[M4SH_TYPE_FUSION] = 59,
[M4SH_TYPE_COMPASS] = 17,
[M4SH_TYPE_GYRO] = 16,
- [M4SH_TYPE_METS] = 16,
+ [M4SH_TYPE_METS] = 24,
[M4SH_TYPE_USERSETTINGS] = 8,
[M4SH_TYPE_POWER] = 9,
[M4SH_TYPE_LOCATION] = 14,