diff options
Diffstat (limited to 'drivers/misc/mpu3050/compass/ak8975.c')
-rw-r--r-- | drivers/misc/mpu3050/compass/ak8975.c | 95 |
1 files changed, 66 insertions, 29 deletions
diff --git a/drivers/misc/mpu3050/compass/ak8975.c b/drivers/misc/mpu3050/compass/ak8975.c index 18606e240f1c..991de77dbd01 100644 --- a/drivers/misc/mpu3050/compass/ak8975.c +++ b/drivers/misc/mpu3050/compass/ak8975.c @@ -25,12 +25,14 @@ * @{ * @file AK8975.c * @brief Magnetometer setup and handling methods for AKM 8975 compass. -**/ + */ /* ------------------ */ /* - Include Files. - */ /* ------------------ */ +#include <string.h> + #ifdef __KERNEL__ #include <linux/module.h> #endif @@ -84,44 +86,78 @@ int ak8975_read(void *mlsl_handle, struct ext_slave_descr *slave, struct ext_slave_platform_data *pdata, unsigned char *data) { - unsigned char stat; - unsigned char stat2; + unsigned char regs[8]; + unsigned char *stat = ®s[0]; + unsigned char *stat2 = ®s[7]; int result = ML_SUCCESS; + int status = ML_SUCCESS; result = - MLSLSerialRead(mlsl_handle, pdata->address, AK8975_REG_ST1, 1, - &stat); + MLSLSerialRead(mlsl_handle, pdata->address, AK8975_REG_ST1, + 8, regs); ERROR_CHECK(result); - if (stat & 0x01) { - result = - MLSLSerialRead(mlsl_handle, pdata->address, - AK8975_REG_HXL, 6, - (unsigned char *) data); - ERROR_CHECK(result); - result = - MLSLSerialRead(mlsl_handle, pdata->address, - AK8975_REG_ST2, 1, &stat2); - ERROR_CHECK(result); - if (stat2 & 0x04) /* data error */ - return ML_ERROR_COMPASS_DATA_NOT_READY; - if (stat2 & 0x08) - return ML_ERROR_COMPASS_DATA_OVERFLOW; + /* + * ST : data ready - + * Measurement has been completed and data is ready to be read. + */ + if (*stat & 0x01) { + memcpy(data, ®s[1], 6); + status = ML_SUCCESS; + } + + /* + * ST2 : data error - + * occurs when data read is started outside of a readable period; + * data read would not be correct. + * Valid in continuous measurement mode only. + * In single measurement mode this error should not occour but we + * stil account for it and return an error, since the data would be + * corrupted. + * DERR bit is self-clearing when ST2 register is read. + */ + if (*stat2 & 0x04) + status = ML_ERROR_COMPASS_DATA_ERROR; + /* + * ST2 : overflow - + * the sum of the absolute values of all axis |X|+|Y|+|Z| < 2400uT. + * This is likely to happen in presence of an external magnetic + * disturbance; it indicates, the sensor data is incorrect and should + * be ignored. + * An error is returned. + * HOFL bit clears when a new measurement starts. + */ + if (*stat2 & 0x08) + status = ML_ERROR_COMPASS_DATA_OVERFLOW; + /* + * ST : overrun - + * the previous sample was not fetched and lost. + * Valid in continuous measurement mode only. + * In single measurement mode this error should not occour and we + * don't consider this condition an error. + * DOR bit is self-clearing when ST2 or any meas. data register is + * read. + */ + if (*stat & 0x02) { + /* status = ML_ERROR_COMPASS_DATA_UNDERFLOW; */ + status = ML_SUCCESS; + } + + /* + * trigger next measurement if: + * - stat is non zero; + * - if stat is zero and stat2 is non zero. + * Won't trigger if data is not ready and there was no error. + */ + if (*stat != 0x00 || *stat2 != 0x00) { result = MLSLSerialWriteSingle(mlsl_handle, pdata->address, AK8975_REG_CNTL, AK8975_CNTL_MODE_SINGLE_MEASUREMENT); ERROR_CHECK(result); - return ML_SUCCESS; - } else if (stat & 0x02) { - result = - MLSLSerialRead(mlsl_handle, pdata->address, - AK8975_REG_ST2, 1, &stat2); - ERROR_CHECK(result); - return ML_ERROR_COMPASS_DATA_OVERFLOW; - } else { - return ML_ERROR_COMPASS_DATA_NOT_READY; } + + return status; } struct ext_slave_descr ak8975_descr = { @@ -131,6 +167,7 @@ struct ext_slave_descr ak8975_descr = { /*.resume = */ ak8975_resume, /*.read = */ ak8975_read, /*.config = */ NULL, + /*.get_config = */ NULL, /*.name = */ "ak8975", /*.type = */ EXT_SLAVE_TYPE_COMPASS, /*.id = */ COMPASS_ID_AKM, @@ -148,4 +185,4 @@ EXPORT_SYMBOL(ak8975_get_slave_descr); /** * @} -**/ + */ |