diff options
Diffstat (limited to 'drivers/mfd')
| -rw-r--r-- | drivers/mfd/Makefile | 1 | ||||
| -rw-r--r-- | drivers/mfd/m4sensorhub-core.c | 74 | ||||
| -rw-r--r-- | drivers/mfd/m4sensorhub-extern.c | 158 | ||||
| -rw-r--r-- | drivers/mfd/m4sensorhub-panic.c | 1 | ||||
| -rw-r--r-- | drivers/mfd/m4sensorhub-reg.h | 10 |
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, |