Index: linux-2.6.35/drivers/misc/mpu3050/compass/ami304.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6.35/drivers/misc/mpu3050/compass/ami304.c 2010-12-22 14:09:28.000000000 +0800 @@ -0,0 +1,164 @@ +/* + $License: + Copyright (C) 2010 InvenSense Corporation, All Rights Reserved. + + 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, see <http://www.gnu.org/licenses/>. + $ + */ + +/** + * @defgroup COMPASSDL (Motion Library - Accelerometer Driver Layer) + * @brief Provides the interface to setup and handle an accelerometers + * connected to the secondary I2C interface of the gyroscope. + * + * @{ + * @file ami304.c + * @brief Magnetometer setup and handling methods for Aichi ami304 compass. +*/ + +/* ------------------ */ +/* - Include Files. - */ +/* ------------------ */ + +#ifdef __KERNEL__ +#include <linux/module.h> +#endif + +#include "mpu.h" +#include "mlsl.h" +#include "mlos.h" + +#include <log.h> +#undef MPL_LOG_TAG +#define MPL_LOG_TAG "MPL-compass" + +#define AMI304_REG_DATAX (0x10) +#define AMI304_REG_STAT1 (0x18) +#define AMI304_REG_CNTL1 (0x1B) +#define AMI304_REG_CNTL2 (0x1C) +#define AMI304_REG_CNTL3 (0x1D) + +#define AMI304_BIT_CNTL1_PC1 (0x80) +#define AMI304_BIT_CNTL1_ODR1 (0x10) +#define AMI304_BIT_CNTL1_FS1 (0x02) + +#define AMI304_BIT_CNTL2_IEN (0x10) +#define AMI304_BIT_CNTL2_DREN (0x08) +#define AMI304_BIT_CNTL2_DRP (0x04) +#define AMI304_BIT_CNTL3_F0RCE (0x40) + +int ami304_suspend(void *mlsl_handle, + struct ext_slave_descr *slave, + struct ext_slave_platform_data *pdata) +{ + int result; + unsigned char reg; + result = + MLSLSerialRead(mlsl_handle, pdata->address, AMI304_REG_CNTL1, + 1, ®); + ERROR_CHECK(result); + + reg &= ~(AMI304_BIT_CNTL1_PC1|AMI304_BIT_CNTL1_FS1); + result = + MLSLSerialWriteSingle(mlsl_handle, pdata->address, + AMI304_REG_CNTL1, reg); + ERROR_CHECK(result); + + return result; +} + +int ami304_resume(void *mlsl_handle, + struct ext_slave_descr *slave, + struct ext_slave_platform_data *pdata) +{ + int result = ML_SUCCESS; + + /* Set CNTL1 reg to power model active */ + result = + MLSLSerialWriteSingle(mlsl_handle, pdata->address, + AMI304_REG_CNTL1, + AMI304_BIT_CNTL1_PC1|AMI304_BIT_CNTL1_FS1); + ERROR_CHECK(result); + /* Set CNTL2 reg to DRDY active high and enabled */ + result = + MLSLSerialWriteSingle(mlsl_handle, pdata->address, + AMI304_REG_CNTL2, + AMI304_BIT_CNTL2_DREN | + AMI304_BIT_CNTL2_DRP); + ERROR_CHECK(result); + /* Set CNTL3 reg to forced measurement period */ + result = + MLSLSerialWriteSingle(mlsl_handle, pdata->address, + AMI304_REG_CNTL3, AMI304_BIT_CNTL3_F0RCE); + + return result; +} + +int ami304_read(void *mlsl_handle, + struct ext_slave_descr *slave, + struct ext_slave_platform_data *pdata, unsigned char *data) +{ + unsigned char stat; + int result = ML_SUCCESS; + + /* Read status reg and check if data ready (DRDY) */ + result = + MLSLSerialRead(mlsl_handle, pdata->address, AMI304_REG_STAT1, + 1, &stat); + ERROR_CHECK(result); + + if (stat & 0x40) { + result = + MLSLSerialRead(mlsl_handle, pdata->address, + AMI304_REG_DATAX, 6, + (unsigned char *) data); + ERROR_CHECK(result); + /* start another measurement */ + result = + MLSLSerialWriteSingle(mlsl_handle, pdata->address, + AMI304_REG_CNTL3, + AMI304_BIT_CNTL3_F0RCE); + ERROR_CHECK(result); + + return ML_SUCCESS; + } + + return ML_ERROR_COMPASS_DATA_NOT_READY; +} + +struct ext_slave_descr ami304_descr = { + /*.suspend = */ ami304_suspend, + /*.resume = */ ami304_resume, + /*.read = */ ami304_read, + /*.name = */ "ami304", + /*.type = */ EXT_SLAVE_TYPE_COMPASS, + /*.id = */ COMPASS_ID_AICHI, + /*.reg = */ 0x06, + /*.len = */ 6, + /*.endian = */ EXT_SLAVE_LITTLE_ENDIAN, + /*.range = */ {5461, 3333} +}; + +struct ext_slave_descr *ami304_get_slave_descr(void) +{ + return &ami304_descr; +} + +#ifdef __KERNEL__ +EXPORT_SYMBOL(ami304_get_slave_descr); +#endif + +/** + * @} +**/ Index: linux-2.6.35/drivers/misc/mpu3050/mlsl-kernel.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6.35/drivers/misc/mpu3050/mlsl-kernel.c 2010-12-22 14:09:28.000000000 +0800 @@ -0,0 +1,331 @@ +/* + $License: + Copyright (C) 2010 InvenSense Corporation, All Rights Reserved. + + 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, see <http://www.gnu.org/licenses/>. + $ + */ + +#include "mlsl.h" +#include "mpu-i2c.h" + +/* ------------ */ +/* - Defines. - */ +/* ------------ */ + +/* ---------------------- */ +/* - Types definitions. - */ +/* ---------------------- */ + +/* --------------------- */ +/* - Function p-types. - */ +/* --------------------- */ + +/** + * @brief used to open the I2C or SPI serial port. + * This port is used to send and receive data to the MPU device. + * @param portNum + * The COM port number associated with the device in use. + * @return ML_SUCCESS if successful, a non-zero error code otherwise. + */ +tMLError MLSLSerialOpen(char const *port, void ** sl_handle) +{ + return ML_SUCCESS; +} + +/** + * @brief used to reset any buffering the driver may be doing + * @return ML_SUCCESS if successful, a non-zero error code otherwise. + */ +tMLError MLSLSerialReset(void *sl_handle) +{ + return ML_SUCCESS; +} + +/** + * @brief used to close the I2C or SPI serial port. + * This port is used to send and receive data to the MPU device. + * @return ML_SUCCESS if successful, a non-zero error code otherwise. + */ +tMLError MLSLSerialClose(void *sl_handle) +{ + return ML_SUCCESS; +} + +/** + * @brief used to read a single byte of data. + * This should be sent by I2C or SPI. + * + * @param slaveAddr I2C slave address of device. + * @param registerAddr Register address to read. + * @param data Single byte of data to read. + * + * @return ML_SUCCESS if the command is successful, an error code otherwise. + */ +tMLError MLSLSerialWriteSingle(void *sl_handle, + unsigned char slaveAddr, + unsigned char registerAddr, + unsigned char data) +{ + return sensor_i2c_write_register((struct i2c_adapter *) sl_handle, + slaveAddr, registerAddr, data); +} + + +/** + * @brief used to write multiple bytes of data from registers. + * This should be sent by I2C. + * + * @param slaveAddr I2C slave address of device. + * @param registerAddr Register address to write. + * @param length Length of burst of data. + * @param data Pointer to block of data. + * + * @return ML_SUCCESS if successful, a non-zero error code otherwise. + */ +tMLError MLSLSerialWrite(void *sl_handle, + unsigned char slaveAddr, + unsigned short length, unsigned char const *data) +{ + tMLError result; + const unsigned short dataLength = length - 1; + const unsigned char startRegAddr = data[0]; + unsigned char i2cWrite[SERIAL_MAX_TRANSFER_SIZE + 1]; + unsigned short bytesWritten = 0; + + while (bytesWritten < dataLength) { + unsigned short thisLen = min(SERIAL_MAX_TRANSFER_SIZE, + dataLength - bytesWritten); + if (bytesWritten == 0) { + result = sensor_i2c_write((struct i2c_adapter *) + sl_handle, slaveAddr, + 1 + thisLen, data); + } else { + /* manually increment register addr between chunks */ + i2cWrite[0] = startRegAddr + bytesWritten; + memcpy(&i2cWrite[1], &data[1 + bytesWritten], + thisLen); + result = sensor_i2c_write((struct i2c_adapter *) + sl_handle, slaveAddr, + 1 + thisLen, i2cWrite); + } + if (ML_SUCCESS != result) + return result; + bytesWritten += thisLen; + } + return ML_SUCCESS; +} + + +/** + * @brief used to read multiple bytes of data from registers. + * This should be sent by I2C. + * + * @param slaveAddr I2C slave address of device. + * @param registerAddr Register address to read. + * @param length Length of burst of data. + * @param data Pointer to block of data. + * + * @return Zero if successful; an error code otherwise + */ +tMLError MLSLSerialRead(void *sl_handle, + unsigned char slaveAddr, + unsigned char registerAddr, + unsigned short length, unsigned char *data) +{ + tMLError result; + unsigned short bytesRead = 0; + + if (registerAddr == MPUREG_FIFO_R_W + || registerAddr == MPUREG_MEM_R_W) { + return ML_ERROR_INVALID_PARAMETER; + } + while (bytesRead < length) { + unsigned short thisLen = + min(SERIAL_MAX_TRANSFER_SIZE, length - bytesRead); + result = + sensor_i2c_read((struct i2c_adapter *) sl_handle, + slaveAddr, registerAddr + bytesRead, + thisLen, &data[bytesRead]); + if (ML_SUCCESS != result) + return result; + bytesRead += thisLen; + } + return ML_SUCCESS; +} + + +/** + * @brief used to write multiple bytes of data to the memory. + * This should be sent by I2C. + * + * @param slaveAddr I2C slave address of device. + * @param memAddr The location in the memory to write to. + * @param length Length of burst data. + * @param data Pointer to block of data. + * + * @return Zero if successful; an error code otherwise + */ +tMLError MLSLSerialWriteMem(void *sl_handle, + unsigned char slaveAddr, + unsigned short memAddr, + unsigned short length, + unsigned char const *data) +{ + tMLError result; + unsigned short bytesWritten = 0; + + if ((memAddr & 0xFF) + length > MPU_MEM_BANK_SIZE) { + printk + ("memory read length (%d B) extends beyond its limits (%d) " + "if started at location %d\n", length, + MPU_MEM_BANK_SIZE, memAddr & 0xFF); + return ML_ERROR_INVALID_PARAMETER; + } + while (bytesWritten < length) { + unsigned short thisLen = + min(SERIAL_MAX_TRANSFER_SIZE, length - bytesWritten); + result = + mpu_memory_write((struct i2c_adapter *) sl_handle, + slaveAddr, memAddr + bytesWritten, + thisLen, &data[bytesWritten]); + if (ML_SUCCESS != result) + return result; + bytesWritten += thisLen; + } + return ML_SUCCESS; +} + + +/** + * @brief used to read multiple bytes of data from the memory. + * This should be sent by I2C. + * + * @param slaveAddr I2C slave address of device. + * @param memAddr The location in the memory to read from. + * @param length Length of burst data. + * @param data Pointer to block of data. + * + * @return Zero if successful; an error code otherwise + */ +tMLError MLSLSerialReadMem(void *sl_handle, + unsigned char slaveAddr, + unsigned short memAddr, + unsigned short length, unsigned char *data) +{ + tMLError result; + unsigned short bytesRead = 0; + + if ((memAddr & 0xFF) + length > MPU_MEM_BANK_SIZE) { + printk + ("memory read length (%d B) extends beyond its limits (%d) " + "if started at location %d\n", length, + MPU_MEM_BANK_SIZE, memAddr & 0xFF); + return ML_ERROR_INVALID_PARAMETER; + } + while (bytesRead < length) { + unsigned short thisLen = + min(SERIAL_MAX_TRANSFER_SIZE, length - bytesRead); + result = + mpu_memory_read((struct i2c_adapter *) sl_handle, + slaveAddr, memAddr + bytesRead, + thisLen, &data[bytesRead]); + if (ML_SUCCESS != result) + return result; + bytesRead += thisLen; + } + return ML_SUCCESS; +} + + +/** + * @brief used to write multiple bytes of data to the fifo. + * This should be sent by I2C. + * + * @param slaveAddr I2C slave address of device. + * @param length Length of burst of data. + * @param data Pointer to block of data. + * + * @return Zero if successful; an error code otherwise + */ +tMLError MLSLSerialWriteFifo(void *sl_handle, + unsigned char slaveAddr, + unsigned short length, + unsigned char const *data) +{ + tMLError result; + unsigned char i2cWrite[SERIAL_MAX_TRANSFER_SIZE + 1]; + unsigned short bytesWritten = 0; + + if (length > FIFO_HW_SIZE) { + printk(KERN_ERR + "maximum fifo write length is %d\n", FIFO_HW_SIZE); + return ML_ERROR_INVALID_PARAMETER; + } + while (bytesWritten < length) { + unsigned short thisLen = + min(SERIAL_MAX_TRANSFER_SIZE, length - bytesWritten); + i2cWrite[0] = MPUREG_FIFO_R_W; + memcpy(&i2cWrite[1], &data[bytesWritten], thisLen); + result = sensor_i2c_write((struct i2c_adapter *) sl_handle, + slaveAddr, thisLen + 1, + i2cWrite); + if (ML_SUCCESS != result) + return result; + bytesWritten += thisLen; + } + return ML_SUCCESS; +} + + +/** + * @brief used to read multiple bytes of data from the fifo. + * This should be sent by I2C. + * + * @param slaveAddr I2C slave address of device. + * @param length Length of burst of data. + * @param data Pointer to block of data. + * + * @return Zero if successful; an error code otherwise + */ +tMLError MLSLSerialReadFifo(void *sl_handle, + unsigned char slaveAddr, + unsigned short length, unsigned char *data) +{ + tMLError result; + unsigned short bytesRead = 0; + + if (length > FIFO_HW_SIZE) { + printk(KERN_ERR + "maximum fifo read length is %d\n", FIFO_HW_SIZE); + return ML_ERROR_INVALID_PARAMETER; + } + while (bytesRead < length) { + unsigned short thisLen = + min(SERIAL_MAX_TRANSFER_SIZE, length - bytesRead); + result = + sensor_i2c_read((struct i2c_adapter *) sl_handle, + slaveAddr, MPUREG_FIFO_R_W, thisLen, + &data[bytesRead]); + if (ML_SUCCESS != result) + return result; + bytesRead += thisLen; + } + + return ML_SUCCESS; +} + +/** + * @} + */ Index: linux-2.6.35/drivers/misc/mpu3050/accel/lis331.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6.35/drivers/misc/mpu3050/accel/lis331.c 2010-12-22 14:09:28.000000000 +0800 @@ -0,0 +1,187 @@ +/* + $License: + Copyright (C) 2010 InvenSense Corporation, All Rights Reserved. + + 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, see <http://www.gnu.org/licenses/>. + $ + */ + +/** + * @defgroup ACCELDL (Motion Library - Accelerometer Driver Layer) + * @brief Provides the interface to setup and handle an accelerometers + * connected to the secondary I2C interface of the gyroscope. + * + * @{ + * @file lis331.c + * @brief Accelerometer setup and handling methods for ST LIS331 + */ + +/* ------------------ */ +/* - Include Files. - */ +/* ------------------ */ + +#ifdef __KERNEL__ +#include <linux/module.h> +#endif + +#include "mpu.h" +#include "mlsl.h" +#include "mlos.h" + +#include <log.h> +#undef MPL_LOG_TAG +#define MPL_LOG_TAG "MPL-acc" + +/* full scale setting - register & mask */ +#define ACCEL_ST_CTRL_REG1 (0x20) +#define ACCEL_ST_CTRL_REG2 (0x21) +#define ACCEL_ST_CTRL_REG3 (0x22) +#define ACCEL_ST_CTRL_REG4 (0x23) +#define ACCEL_ST_CTRL_REG5 (0x24) +#define ACCEL_ST_HP_FILTER_RESET (0x25) +#define ACCEL_ST_REFERENCE (0x26) +#define ACCEL_ST_STATUS_REG (0x27) +#define ACCEL_ST_OUT_X_L (0x28) +#define ACCEL_ST_OUT_X_H (0x29) +#define ACCEL_ST_OUT_Y_L (0x2a) +#define ACCEL_ST_OUT_Y_H (0x2b) +#define ACCEL_ST_OUT_Z_L (0x2b) +#define ACCEL_ST_OUT_Z_H (0x2d) + +#define ACCEL_ST_INT1_CFG (0x30) +#define ACCEL_ST_INT1_SRC (0x31) +#define ACCEL_ST_INT1_THS (0x32) +#define ACCEL_ST_INT1_DURATION (0x33) + +#define ACCEL_ST_INT2_CFG (0x34) +#define ACCEL_ST_INT2_SRC (0x35) +#define ACCEL_ST_INT2_THS (0x36) +#define ACCEL_ST_INT2_DURATION (0x37) + +#define ACCEL_ST_CTRL_MASK (0x30) +#define ACCEL_ST_SLEEP_MASK (0x20) + +/* --------------------- */ +/* - Variables. - */ +/* --------------------- */ + +/***************************************** + Accelerometer Initialization Functions +*****************************************/ + +int lis331dlh_suspend(void *mlsl_handle, + struct ext_slave_descr *slave, + struct ext_slave_platform_data *pdata) +{ + int result; + + result = MLSLSerialWriteSingle(mlsl_handle, pdata->address, + ACCEL_ST_CTRL_REG1, 0x47); + result = MLSLSerialWriteSingle(mlsl_handle, pdata->address, + ACCEL_ST_CTRL_REG2, 0x0f); + result = MLSLSerialWriteSingle(mlsl_handle, pdata->address, + ACCEL_ST_CTRL_REG3, 0x00); + result = MLSLSerialWriteSingle(mlsl_handle, pdata->address, + ACCEL_ST_CTRL_REG4, 0x40); + result = MLSLSerialWriteSingle(mlsl_handle, pdata->address, + ACCEL_ST_INT1_THS, 0x05); + result = MLSLSerialWriteSingle(mlsl_handle, pdata->address, + ACCEL_ST_INT1_DURATION, 0x01); + result = MLSLSerialWriteSingle(mlsl_handle, pdata->address, + ACCEL_ST_INT1_CFG, 0x2a); + return result; +} + +int lis331dlh_resume(void *mlsl_handle, + struct ext_slave_descr *slave, + struct ext_slave_platform_data *pdata) +{ + int result = ML_SUCCESS; + unsigned char reg; + + result = MLSLSerialWriteSingle(mlsl_handle, pdata->address, + ACCEL_ST_CTRL_REG1, 0x37); + ERROR_CHECK(result); + MLOSSleep(500); + + /* Full Scale */ + reg = 0x40; + reg &= ~ACCEL_ST_CTRL_MASK; + if (slave->range.mantissa == 2 + && slave->range.fraction == 480) { + reg |= 0x00; + } else if (slave->range.mantissa == 4 + && slave->range.fraction == 960) { + reg |= 0x10; + } else if (slave->range.mantissa == 8 + && slave->range.fraction == 1920) { + reg |= 0x30; + } + result = MLSLSerialWriteSingle(mlsl_handle, pdata->address, + ACCEL_ST_CTRL_REG4, reg); + ERROR_CHECK(result); + + /* Configure high pass filter */ + result = MLSLSerialWriteSingle(mlsl_handle, pdata->address, + ACCEL_ST_CTRL_REG2, 0x0F); + ERROR_CHECK(result); + result = MLSLSerialWriteSingle(mlsl_handle, pdata->address, + ACCEL_ST_CTRL_REG3, 0x00); + ERROR_CHECK(result); + result = MLSLSerialWriteSingle(mlsl_handle, pdata->address, + ACCEL_ST_INT1_THS, 0x10); + ERROR_CHECK(result); + result = MLSLSerialWriteSingle(mlsl_handle, pdata->address, + ACCEL_ST_INT1_DURATION, 0x10); + ERROR_CHECK(result); + result = MLSLSerialWriteSingle(mlsl_handle, pdata->address, + ACCEL_ST_INT1_CFG, 0x00); + ERROR_CHECK(result); + MLOSSleep(50); + return result; +} + +int lis331dlh_read(void *mlsl_handle, + struct ext_slave_descr *slave, + struct ext_slave_platform_data *pdata, + unsigned char *data) +{ + return ML_ERROR_FEATURE_NOT_IMPLEMENTED; +} + +struct ext_slave_descr lis331dlh_descr = { + /*.suspend = */ lis331dlh_suspend, + /*.resume = */ lis331dlh_resume, + /*.read = */ lis331dlh_read, + /*.name = */ "lis331dlh", + /*.type = */ EXT_SLAVE_TYPE_ACCELEROMETER, + /*.id = */ ACCEL_ID_LIS331, + /*.reg = */ 0x28, + /*.len = */ 6, + /*.endian = */ EXT_SLAVE_BIG_ENDIAN, + /*.range = */ {2, 480}, +}; + +struct ext_slave_descr *lis331dlh_get_slave_descr(void) +{ + return &lis331dlh_descr; +} + +#ifdef __KERNEL__ +EXPORT_SYMBOL(lis331dlh_get_slave_descr); +#endif + +/** + * @} +**/ Index: linux-2.6.35/drivers/misc/mpu3050/accel/bma023.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6.35/drivers/misc/mpu3050/accel/bma023.c 2010-12-22 23:00:10.000000000 +0800 @@ -0,0 +1,381 @@ +/******************************************************************************* + * + * $Id: bma023.c 3687 2010-09-07 22:40:14Z kkeal $ + * + *******************************************************************************/ + +/******************************************************************************* + * Copyright (c) 2009 InvenSense Corporation, All Rights Reserved. + ******************************************************************************/ + +/** + * @defgroup ACCELDL (Motion Library - Accelerometer Driver Layer) + * @brief Provides the interface to setup and handle an accelerometers + * connected to the secondary I2C interface of the gyroscope. + * + * @{ + * @file bma023.c + * @brief Accelerometer setup and handling methods. +**/ + +/* ------------------ */ +/* - Include Files. - */ +/* ------------------ */ + +#ifdef __KERNEL__ +#include <linux/module.h> +#endif + +#include <linux/ctype.h> + +#include "mpu3050.h" +#include "mlos.h" +#include "mlsl.h" +#include "mldl_cfg.h" + +#include "bma023.h" + +/* --------------------- */ +/* - Variables. - */ +/* --------------------- */ + +/********************************************* + Accelerometer Initialization Functions +**********************************************/ + +static struct accel_config aconfig = { 0x00, 0x03, 0x00, 0x00, 0x03, 0xA0, 0x03, 0xA0, 0x00 }; + +struct accel_config* accel_get_config(void){ + return &aconfig; +} +EXPORT_SYMBOL(accel_get_config); + +static int atoi(const char *array){ + const char *parray = array; + long res; + int base; + int ret_val, nagetive = 0; + while (isspace(*parray)) + parray++; + if(parray[1]=='x') + base = 16; + else{ + base = 10; + if(parray[0] == '-'){ + nagetive = 1; + parray++; + } + } + ret_val = strict_strtoul(parray, base, &res); + if(nagetive && ~ret_val) + res *= -1; + return ret_val ? 0 : res; +} + +int bma023_read_accel_xyz(struct i2c_adapter *accel_adapter, + struct mldl_cfg *mldl_cfg, signed short *xyz_axes){ + unsigned char data[6]; + if(MLSLSerialRead(accel_adapter, mldl_cfg->pdata->accel.address, BMA023_X_AXIS_LSB_REG, 6, data)) + return -1; + xyz_axes[0] = data[0] & BMA023_OFFSET_X_LSB__MSK; + xyz_axes[0] = xyz_axes[0] >> BMA023_OFFSET_X_LSB__POS | data[1] << BMA023_OFFSET_X_LSB__LEN; + xyz_axes[0] = xyz_axes[0] << BMA023_OFFSET_X_LSB__POS; + xyz_axes[0] = xyz_axes[0] >> BMA023_OFFSET_X_LSB__POS; + xyz_axes[1] = data[2] & BMA023_OFFSET_Y_LSB__MSK; + xyz_axes[1] = xyz_axes[1] >> BMA023_OFFSET_Y_LSB__POS | data[3] << BMA023_OFFSET_Y_LSB__LEN; + xyz_axes[1] = xyz_axes[1] << BMA023_OFFSET_Y_LSB__POS; + xyz_axes[1] = xyz_axes[1] >> BMA023_OFFSET_Y_LSB__POS; + xyz_axes[2] = data[4] & BMA023_OFFSET_Z_LSB__MSK; + xyz_axes[2] = xyz_axes[2] >> BMA023_OFFSET_Z_LSB__POS | data[5] << BMA023_OFFSET_Z_LSB__LEN; + xyz_axes[2] = xyz_axes[2] << BMA023_OFFSET_Z_LSB__POS; + xyz_axes[2] = xyz_axes[2] >> BMA023_OFFSET_Z_LSB__POS; + return 0; +} + +unsigned char bma023_get_power_mode(struct i2c_adapter *accel_adapter, + struct mldl_cfg *mldl_cfg){ + unsigned char data; + if(MLSLSerialRead(accel_adapter, mldl_cfg->pdata->accel.address, BMA023_CTRL_REG, 1, &data)){ + printk("Can't get power status\n"); + return 0; + } + data &= BMA023_SLEEP__MSK; + return data; +} + +int bma023_get_bandwidth(void){ + int bw_hz=0; + unsigned char bw = aconfig.range_bandwidth & BMA023_BANDWIDTH__MSK; + switch(bw){ + case 0x00: bw_hz=25; break; + case 0x01: bw_hz=50; break; + case 0x02: bw_hz=100; break; + case 0x03: bw_hz=190; break; + case 0x04: bw_hz=375; break; + case 0x05: bw_hz=750; break; + case 0x06: bw_hz=1500; break; + default: break; + } + return bw_hz; +} + +int bma023_set_bandwidth(struct i2c_adapter *accel_adapter, const char *buf){ + unsigned char reg, bw = aconfig.range_bandwidth & BMA023_BANDWIDTH__MSK; + if(buf[0] == '-'){ + if(bw == 0x00) + return 0; + aconfig.range_bandwidth--; + } + else if(buf[0] == '+'){ + if(bw == 0x06) + return 0; + aconfig.range_bandwidth++; + } + else { + printk("accel_bw: wrong command %s",buf); + return -1; + } + if(MLSLSerialRead(accel_adapter, BMA023_I2C_ADDR, BMA023_RANGE_BWIDTH_REG, 1, ®)){ + printk("%s: Can't get bandwidth reg\n",__func__); + return -1; + } + reg &= 0xe0; + reg |= aconfig.range_bandwidth; + if(MLSLSerialWriteSingle(accel_adapter, BMA023_I2C_ADDR, BMA023_RANGE_BWIDTH_REG, reg )){ + printk("%s: Can't set bandwidth reg\n",__func__); + return -1; + } + return 0; +} + +int bma023_get_range(void){ + unsigned char range; + int g_range = 0; + range = aconfig.range_bandwidth & BMA023_RANGE__MSK; + switch(range){ + case 0x00: g_range = 2; break; + case 0x08: g_range = 4; break; + case 0x10: g_range = 8; break; + default: break; + } + return g_range; +} + +int bma023_set_range(struct i2c_adapter *accel_adapter, const char *buf){ + unsigned char reg, range = aconfig.range_bandwidth & BMA023_RANGE__MSK; + if(buf[0] == '-'){ + if(range == 0x00) + return 0; + aconfig.range_bandwidth -= 0x08; + } + else if(buf[0] == '+'){ + if(range == 0x10) + return 0; + aconfig.range_bandwidth += 0x08; + } + else { + printk("accel_range: wrong command %s\n",buf); + return -1; + } + if(MLSLSerialRead(accel_adapter, BMA023_I2C_ADDR, BMA023_RANGE_BWIDTH_REG, 1, ®)){ + printk("%s: Can't get range reg\n",__func__); + return -1; + } + reg &= 0xe0; + reg |= aconfig.range_bandwidth; + if(MLSLSerialWriteSingle(accel_adapter, BMA023_I2C_ADDR, BMA023_RANGE_BWIDTH_REG, reg )){ + printk("%s: Can't set range reg\n",__func__); + return -1; + } + return 0; +} + +int bma023_set_hg_duration(struct i2c_adapter *accel_adapter, const char *buf){ + int value; + value = atoi(buf); + if(value > 255) + aconfig.hg_dur = 0xFF; + else if(value < 0) + aconfig.hg_dur = 0x00; + else + aconfig.hg_dur = value; + if(MLSLSerialWriteSingle(accel_adapter, BMA023_I2C_ADDR, BMA023_HG_DURATION_REG, aconfig.hg_dur)){ + printk("%s: Can't set high g duration\n",__func__); + return -1; + } + return 0; +} + +int bma023_set_hg_threshold(struct i2c_adapter *accel_adapter, const char *buf){ + int value; + value = atoi(buf); + if(value > 255) + aconfig.hg_thres = 0xFF; + else if(value < 0) + aconfig.hg_thres = 0x00; + else + aconfig.hg_thres = value; + if(MLSLSerialWriteSingle(accel_adapter, BMA023_I2C_ADDR, BMA023_HG_THRESHOLD_REG, aconfig.hg_thres)){ + printk("%s: Can't set high g threshold\n",__func__); + return -1; + } + return 0; +} + +int bma023_set_lg_duration(struct i2c_adapter *accel_adapter, const char *buf){ + int value; + value = atoi(buf); + if(value > 255) + aconfig.lg_dur = 0xFF; + else if(value < 0) + aconfig.lg_dur = 0x00; + else + aconfig.lg_dur = value; + if(MLSLSerialWriteSingle(accel_adapter, BMA023_I2C_ADDR, BMA023_LG_DURATION_REG, aconfig.lg_dur)){ + printk("%s: Can't set low g duration\n",__func__); + return -1; + } + return 0; +} + +int bma023_set_lg_threshold(struct i2c_adapter *accel_adapter, const char *buf){ + int value; + value = atoi(buf); + if(value > 255) + aconfig.lg_thres = 0xFF; + else if(value < 0) + aconfig.lg_thres = 0x00; + else + aconfig.lg_thres = value; + if(MLSLSerialWriteSingle(accel_adapter, BMA023_I2C_ADDR, BMA023_LG_THRESHOLD_REG, aconfig.lg_thres)){ + printk("%s: Can't set low g threshold\n",__func__); + return -1; + } + return 0; +} + +static int bma023_set_config(void *mlsl_handle, + struct ext_slave_platform_data *pdata){ + int result = 0 ; + unsigned char reg = 0; + + // 0x14 Bandwidth & Range + reg = 0; + result = MLSLSerialRead(mlsl_handle, pdata->address, BMA023_RANGE_BWIDTH_REG, 1, ®); + ERROR_CHECK(result); + reg &= 0xe0; + reg |= aconfig.range_bandwidth; // Bandwidth 3=190 + result = MLSLSerialWriteSingle(mlsl_handle, pdata->address, BMA023_RANGE_BWIDTH_REG, reg ); + ERROR_CHECK(result); + + // 0x11 Any_motion_dur, HG_hyst, LG_hyst + result = MLSLSerialWriteSingle(mlsl_handle, pdata->address, BMA023_HYSTERESIS_REG, aconfig.hg_lg_hyst); + ERROR_CHECK(result); + + // 0x10 Any Motion Threshold + result = MLSLSerialWriteSingle(mlsl_handle, pdata->address, BMA023_MOTION_THRS_REG, aconfig.any_motion_thres); + ERROR_CHECK(result); + + // 0x0F HG Duration + result = MLSLSerialWriteSingle(mlsl_handle, pdata->address, BMA023_HG_DURATION_REG, aconfig.hg_dur); + ERROR_CHECK(result); + + // 0x0E HG Threshold + result = MLSLSerialWriteSingle(mlsl_handle, pdata->address, BMA023_HG_THRESHOLD_REG, aconfig.hg_thres); + ERROR_CHECK(result); + + // 0x0D LG duration + result = MLSLSerialWriteSingle(mlsl_handle, pdata->address, BMA023_LG_DURATION_REG, aconfig.lg_dur); + ERROR_CHECK(result); + + // 0x0C LG Threshold + result = MLSLSerialWriteSingle(mlsl_handle, pdata->address, BMA023_LG_THRESHOLD_REG, aconfig.lg_thres); + ERROR_CHECK(result); + + // 0x0B Interrupt mode + result = MLSLSerialWriteSingle(mlsl_handle, pdata->address, BMA023_CONF1_REG, aconfig.enable_count_hg_lg); + ERROR_CHECK(result); + + return result; +} + +static int bma023_suspend(void *mlsl_handle, + struct ext_slave_descr *slave, + struct ext_slave_platform_data *pdata) +{ + int result; + result = MLSLSerialWriteSingle(mlsl_handle, pdata->address, 0x0a, 0x01); + return result; +} + +// full scale setting - register and mask +#define ACCEL_BOSCH_CTRL_REG (0x14) +#define ACCEL_BOSCH_CTRL_MASK (0x18) + +static int bma023_resume(void *mlsl_handle, + struct ext_slave_descr *slave, + struct ext_slave_platform_data *pdata) +{ + int result; + + /* Soft reset */ + result = MLSLSerialWriteSingle(mlsl_handle, pdata->address, 0x0a, 0x02 ); + ERROR_CHECK(result); + MLOSSleep(10); + + result = bma023_set_config( mlsl_handle, pdata ); + ERROR_CHECK(result); + + return result; +} + +static int bma023_read(void *mlsl_handle, + struct ext_slave_descr *slave, + struct ext_slave_platform_data *pdata, + unsigned char * data) +{ + return ML_ERROR_FEATURE_NOT_IMPLEMENTED; +} + +static struct ext_slave_descr bma023_descr = { + /*.suspend = */ bma023_suspend, + /*.resume = */ bma023_resume, + /*.read = */ bma023_read, + /*.name = */ "bma023", + /*.type = */ EXT_SLAVE_TYPE_ACCELEROMETER, + /*.id = */ ACCEL_ID_BMA023, + /*.reg = */ 0x02, + /*.len = */ 6, + /*.endian = */ EXT_SLAVE_LITTLE_ENDIAN, + /*.range = */ { 2, 0 }, +}; + +struct ext_slave_descr* bma023_get_slave_descr(void) +{ + return &bma023_descr; +} +#ifdef __KERNEL__ +EXPORT_SYMBOL(bma023_get_slave_descr); +#endif + +EXPORT_SYMBOL(bma023_read_accel_xyz); +EXPORT_SYMBOL(bma023_get_power_mode); +EXPORT_SYMBOL(bma023_get_bandwidth); +EXPORT_SYMBOL(bma023_set_bandwidth); +EXPORT_SYMBOL(bma023_get_range); +EXPORT_SYMBOL(bma023_set_range); +EXPORT_SYMBOL(bma023_set_hg_duration); +EXPORT_SYMBOL(bma023_set_hg_threshold); +EXPORT_SYMBOL(bma023_set_lg_duration); +EXPORT_SYMBOL(bma023_set_lg_threshold); + +#ifdef __KERNEL__ +MODULE_AUTHOR("Wistron"); +MODULE_DESCRIPTION("User space IRQ handler for MPU3xxx devices"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("bma"); +#endif + +/** + * @} +**/ Index: linux-2.6.35/drivers/misc/mpu3050/accel/kxtf9.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6.35/drivers/misc/mpu3050/accel/kxtf9.c 2010-12-22 14:09:28.000000000 +0800 @@ -0,0 +1,154 @@ +/* + $License: + Copyright (C) 2010 InvenSense Corporation, All Rights Reserved. + + 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, see <http://www.gnu.org/licenses/>. + $ + */ + +/** + * @defgroup ACCELDL (Motion Library - Accelerometer Driver Layer) + * @brief Provides the interface to setup and handle an accelerometers + * connected to the secondary I2C interface of the gyroscope. + * + * @{ + * @file kxtf9.c + * @brief Accelerometer setup and handling methods. +*/ + +/* ------------------ */ +/* - Include Files. - */ +/* ------------------ */ + +#ifdef __KERNEL__ +#include <linux/module.h> +#endif + +#include "mpu.h" +#include "mlsl.h" +#include "mlos.h" + +#include <log.h> +#undef MPL_LOG_TAG +#define MPL_LOG_TAG "MPL-acc" + +/* --------------------- */ +/* - Variables. - */ +/* --------------------- */ + +/***************************************** + Accelerometer Initialization Functions +*****************************************/ + +static int kxtf9_suspend(void *mlsl_handle, + struct ext_slave_descr *slave, + struct ext_slave_platform_data *pdata) +{ + int result; + result = + MLSLSerialWriteSingle(mlsl_handle, pdata->address, 0x1b, 0); + ERROR_CHECK(result); + return result; +} + +/* full scale setting - register and mask */ +#define ACCEL_KIONIX_CTRL_REG (0x1b) +#define ACCEL_KIONIX_CTRL_MASK (0x18) + +static int kxtf9_resume(void *mlsl_handle, + struct ext_slave_descr *slave, + struct ext_slave_platform_data *pdata) +{ + int result = ML_SUCCESS; + unsigned char reg; + + /* RAM reset */ + result = + MLSLSerialWriteSingle(mlsl_handle, pdata->address, 0x1d, 0xcd); + ERROR_CHECK(result); + MLOSSleep(10); + /* Wake up */ + result = + MLSLSerialWriteSingle(mlsl_handle, pdata->address, 0x1b, 0x42); + ERROR_CHECK(result); + /* INT_CTRL_REG1: */ + result = + MLSLSerialWriteSingle(mlsl_handle, pdata->address, 0x1e, 0x14); + ERROR_CHECK(result); + /* WUF_THRESH: */ + result = + MLSLSerialWriteSingle(mlsl_handle, pdata->address, 0x5a, 0x00); + ERROR_CHECK(result); + /* DATA_CTRL_REG */ + result = + MLSLSerialWriteSingle(mlsl_handle, pdata->address, 0x21, 0x04); + ERROR_CHECK(result); + /* WUF_TIMER */ + result = + MLSLSerialWriteSingle(mlsl_handle, pdata->address, 0x29, 0x02); + ERROR_CHECK(result); + + /* Full Scale */ + reg = 0xc2; + reg &= ~ACCEL_KIONIX_CTRL_MASK; + reg |= 0x00; + if (slave->range.mantissa == 2) + reg |= 0x00; + else if (slave->range.mantissa == 4) + reg |= 0x08; + else if (slave->range.mantissa == 8) + reg |= 0x10; + + /* Normal operation */ + result = + MLSLSerialWriteSingle(mlsl_handle, pdata->address, 0x1b, reg); + ERROR_CHECK(result); + MLOSSleep(50); + + return ML_SUCCESS; +} + +static int kxtf9_read(void *mlsl_handle, + struct ext_slave_descr *slave, + struct ext_slave_platform_data *pdata, + unsigned char *data) +{ + return ML_ERROR_FEATURE_NOT_IMPLEMENTED; +} + +static struct ext_slave_descr kxtf9_descr = { + /*.suspend = */ kxtf9_suspend, + /*.resume = */ kxtf9_resume, + /*.read = */ kxtf9_read, + /*.name = */ "kxtf9", + /*.type = */ EXT_SLAVE_TYPE_ACCELEROMETER, + /*.id = */ ACCEL_ID_KXTF9, + /*.reg = */ 0x06, + /*.len = */ 6, + /*.endian = */ EXT_SLAVE_LITTLE_ENDIAN, + /*.range = */ {2, 0}, +}; + +struct ext_slave_descr *kxtf9_get_slave_descr(void) +{ + return &kxtf9_descr; +} + +#ifdef __KERNEL__ +EXPORT_SYMBOL(kxtf9_get_slave_descr); +#endif + +/** + * @} +**/ Index: linux-2.6.35/drivers/misc/mpu3050/accel/adxl346.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6.35/drivers/misc/mpu3050/accel/adxl346.c 2010-12-22 14:09:28.000000000 +0800 @@ -0,0 +1,156 @@ +/* + $License: + Copyright (C) 2010 InvenSense Corporation, All Rights Reserved. + + 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, see <http://www.gnu.org/licenses/>. + $ + */ + +/** + * @defgroup ACCELDL (Motion Library - Accelerometer Driver Layer) + * @brief Provides the interface to setup and handle an accelerometers + * connected to the secondary I2C interface of the gyroscope. + * + * @{ + * @file adxl346.c + * @brief Accelerometer setup and handling methods for AD adxl346. + */ + +/* ------------------ */ +/* - Include Files. - */ +/* ------------------ */ + +#ifdef __KERNEL__ +#include <linux/module.h> +#endif +#include "mpu.h" +#include "mlsl.h" +#include "mlos.h" + +#include <log.h> +#undef MPL_LOG_TAG +#define MPL_LOG_TAG "MPL-acc" + +#define ACCEL_ADI346_SLEEP_REG (0x2D) +#define ACCEL_ADI346_SLEEP_MASK (0x04) + +/* --------------------- */ +/* - Variables. - */ +/* --------------------- */ + +/***************************************** + Accelerometer Initialization Functions +*****************************************/ + +int adxl346_suspend(void *mlsl_handle, + struct ext_slave_descr *slave, + struct ext_slave_platform_data *pdata) +{ + int result; + unsigned char reg; + result = + MLSLSerialRead(mlsl_handle, pdata->address, + ACCEL_ADI346_SLEEP_REG, 1, ®); + ERROR_CHECK(result); + reg |= ACCEL_ADI346_SLEEP_MASK; + result = + MLSLSerialWriteSingle(mlsl_handle, pdata->address, + ACCEL_ADI346_SLEEP_REG, reg); + ERROR_CHECK(result); + return result; +} + +/* full scale setting - register & mask */ +#define ACCEL_ADI346_CTRL_REG (0x31) +#define ACCEL_ADI346_CTRL_MASK (0x03) + +int adxl346_resume(void *mlsl_handle, + struct ext_slave_descr *slave, + struct ext_slave_platform_data *pdata) +{ + int result = ML_SUCCESS; + unsigned char reg; + + result = + MLSLSerialRead(mlsl_handle, pdata->address, + ACCEL_ADI346_SLEEP_REG, 1, ®); + ERROR_CHECK(result); + reg &= ~ACCEL_ADI346_SLEEP_MASK; + /*wake up if sleeping */ + result = MLSLSerialWriteSingle(mlsl_handle, pdata->address, + ACCEL_ADI346_SLEEP_REG, reg); + ERROR_CHECK(result); + /*MLOSSleep(10) */ + + /* Full Scale */ + reg = 0x04; + reg &= ~ACCEL_ADI346_CTRL_MASK; + if (slave->range.mantissa == 2) + reg |= 0x0; + else if (slave->range.mantissa == 4) + reg |= 0x1; + else if (slave->range.mantissa == 8) + reg |= 0x2; + else if (slave->range.mantissa == 16) + reg |= 0x3; + + /* DATA_FORMAT: full resolution of +/-2g; data is left justified */ + result = MLSLSerialWriteSingle(mlsl_handle, pdata->address, 0x31, reg); + ERROR_CHECK(result); + /* BW_RATE: normal power operation with output data rate of 200Hz */ + result = MLSLSerialWriteSingle(mlsl_handle, pdata->address, 0x2C, 0x0B); + ERROR_CHECK(result); + /* POWER_CTL: power on in measurement mode */ + result = MLSLSerialWriteSingle(mlsl_handle, pdata->address, 0x2D, 0x28); + ERROR_CHECK(result); + /*--- after wake up, it takes at least [1/(data rate) + 1.1]ms ==> + 6.1ms to get valid sensor data ---*/ + MLOSSleep(10); + + return result; +} + +int adxl346_read(void *mlsl_handle, + struct ext_slave_descr *slave, + struct ext_slave_platform_data *pdata, + unsigned char *data) +{ + return ML_ERROR_FEATURE_NOT_IMPLEMENTED; +} + +struct ext_slave_descr adxl346_descr = { + /*.suspend = */ adxl346_suspend, + /*.resume = */ adxl346_resume, + /*.read = */ adxl346_read, + /*.name = */ "adx1346", + /*.type = */ EXT_SLAVE_TYPE_ACCELEROMETER, + /*.id = */ ACCEL_ID_ADI346, + /*.reg = */ 0x32, + /*.len = */ 6, + /*.endian = */ EXT_SLAVE_LITTLE_ENDIAN, + /*.range = */ {2, 0}, +}; + +struct ext_slave_descr *adxl346_get_slave_descr(void) +{ + return &adxl346_descr; +} + +#ifdef __KERNEL__ +EXPORT_SYMBOL(adxl346_get_slave_descr); +#endif + +/** + * @} +**/ _______________________________________________ MeeGo-kernel mailing list [email protected] http://lists.meego.com/listinfo/meego-kernel
