Exemplo n.º 1
0
/**
 *  @brief resume the device in the proper power state given the configuration
 *         chosen.
 *
 *  @param mlsl_handle
 *             the handle to the serial channel the device is connected to.
 *  @param slave
 *             a pointer to the slave descriptor data structure.
 *  @param pdata
 *             a pointer to the slave platform data.
 *
 *  @return INV_SUCCESS if successful or a non-zero error code.
 */
static int mma845x_resume(void *mlsl_handle,
		   struct ext_slave_descr *slave,
		   struct ext_slave_platform_data *pdata)
{
	int result = INV_SUCCESS;
	struct mma845x_private_data *private_data = pdata->private_data;

	/* Full Scale */
	if (private_data->resume.fsr == 4000)
		slave->range.mantissa = 4;
	else if (private_data->resume.fsr == 8000)
		slave->range.mantissa = 8;
	else
		slave->range.mantissa = 2;

	slave->range.fraction = 0;

	result = mma845x_set_fsr(mlsl_handle, pdata,
			&private_data->resume,
			true, private_data->resume.fsr);
	if (result) {
		LOG_RESULT_LOCATION(result);
		return result;
	}
	result = inv_serial_single_write(mlsl_handle, pdata->address,
			ACCEL_MMA845X_CTRL_REG1,
			private_data->resume.ctrl_reg1);
	if (result) {
		LOG_RESULT_LOCATION(result);
		return result;
	}

	return result;
}
static int lsm303dlx_m_resume(void *mlsl_handle,
			     struct ext_slave_descr *slave,
			     struct ext_slave_platform_data *pdata)
{
	int result = INV_SUCCESS;

	/* Use single measurement mode. Start at sleep state. */
	result =
	    inv_serial_single_write(mlsl_handle, pdata->address,
				    LSM_REG_MODE, LSM_MODE_SLEEP);
	if (result) {
		LOG_RESULT_LOCATION(result);
		return result;
	}
	/* Config normal measurement */
	result =
	    inv_serial_single_write(mlsl_handle, pdata->address,
				    LSM_REG_CONF_A, 0);
	if (result) {
		LOG_RESULT_LOCATION(result);
		return result;
	}
	/* Adjust gain to 320 LSB/Gauss */
	result =
	    inv_serial_single_write(mlsl_handle, pdata->address,
				    LSM_REG_CONF_B, LSM_CONF_B_GAIN_5_5);
	if (result) {
		LOG_RESULT_LOCATION(result);
		return result;
	}

	return result;
}
Exemplo n.º 3
0
/* -------------------------------------------------------------------------- */
static int ak8975_init(void *mlsl_handle,
		       struct ext_slave_descr *slave,
		       struct ext_slave_platform_data *pdata)
{
	int result;
	unsigned char serial_data[COMPASS_NUM_AXES];

	struct ak8975_private_data *private_data;
	private_data = (struct ak8975_private_data *)
	    kzalloc(sizeof(struct ak8975_private_data), GFP_KERNEL);

	if (!private_data)
		return INV_ERROR_MEMORY_EXAUSTED;

	result = inv_serial_single_write(mlsl_handle, pdata->address,
					 AK8975_REG_CNTL,
					 AK8975_CNTL_MODE_POWER_DOWN);
	if (result) {
		LOG_RESULT_LOCATION(result);
		return result;
	}
	/* Wait at least 100us */
	udelay(100);

	result = inv_serial_single_write(mlsl_handle, pdata->address,
					 AK8975_REG_CNTL,
					 AK8975_CNTL_MODE_FUSE_ROM_ACCESS);
	if (result) {
		LOG_RESULT_LOCATION(result);
		return result;
	}

	/* Wait at least 200us */
	udelay(200);

	result = inv_serial_read(mlsl_handle, pdata->address,
				 AK8975_REG_ASAX,
				 COMPASS_NUM_AXES, serial_data);
	if (result) {
		LOG_RESULT_LOCATION(result);
		return result;
	}

	pdata->private_data = private_data;

	private_data->init.asa[0] = serial_data[0];
	private_data->init.asa[1] = serial_data[1];
	private_data->init.asa[2] = serial_data[2];

	result = inv_serial_single_write(mlsl_handle, pdata->address,
					 AK8975_REG_CNTL,
					 AK8975_CNTL_MODE_POWER_DOWN);
	if (result) {
		LOG_RESULT_LOCATION(result);
		return result;
	}

	udelay(100);
	return INV_SUCCESS;
}
Exemplo n.º 4
0
/**
 * @brief Stop the DMP running
 *
 * @return INV_SUCCESS or non-zero error code
 */
static int dmp_stop(struct mldl_cfg *mldl_cfg, void *gyro_handle)
{
	unsigned char user_ctrl_reg;
	int result;

	if (mldl_cfg->inv_mpu_state->status & MPU_DMP_IS_SUSPENDED)
		return INV_SUCCESS;

	result = inv_serial_read(gyro_handle, mldl_cfg->mpu_chip_info->addr,
				 MPUREG_USER_CTRL, 1, &user_ctrl_reg);
	if (result) {
		LOG_RESULT_LOCATION(result);
		return result;
	}
	user_ctrl_reg = (user_ctrl_reg & (~BIT_FIFO_EN)) | BIT_FIFO_RST;
	user_ctrl_reg = (user_ctrl_reg & (~BIT_DMP_EN)) | BIT_DMP_RST;

	result = inv_serial_single_write(gyro_handle,
					 mldl_cfg->mpu_chip_info->addr,
					 MPUREG_USER_CTRL, user_ctrl_reg);
	if (result) {
		LOG_RESULT_LOCATION(result);
		return result;
	}
	mldl_cfg->inv_mpu_state->status |= MPU_DMP_IS_SUSPENDED;

	return result;
}
Exemplo n.º 5
0
static int kxtf9_read(void *mlsl_handle,
		      struct ext_slave_descr *slave,
		      struct ext_slave_platform_data *pdata,
		      unsigned char *data)
{
	int result;
	unsigned char reg;
	result = inv_serial_read(mlsl_handle, pdata->address,
				 KXTF9_INT_SRC_REG2, 1, &reg);
	if (result) {
		LOG_RESULT_LOCATION(result);
		return result;
	}

	if (!(reg & 0x10))
		return INV_ERROR_ACCEL_DATA_NOT_READY;

	result = inv_serial_read(mlsl_handle, pdata->address,
				 slave->read_reg, slave->read_len, data);
	if (result) {
		LOG_RESULT_LOCATION(result);
		return result;
	}
	return result;
}
/**
 *  @brief resume the device in the proper power state given the configuration
 *         chosen.
 *
 *  @param mlsl_handle
 *             the handle to the serial channel the device is connected to.
 *  @param slave
 *             a pointer to the slave descriptor data structure.
 *  @param pdata
 *             a pointer to the slave platform data.
 *
 *  @return INV_SUCCESS if successful or a non-zero error code.
 */
static int bma222_resume(void *mlsl_handle,
			 struct ext_slave_descr *slave,
			 struct ext_slave_platform_data *pdata)
{
	int result;
	struct bma222_config *resume_config =
		&((struct bma222_private_data *)pdata->private_data)->resume;

	/* Soft reset */
	result = inv_serial_single_write(mlsl_handle, pdata->address,
			BMA222_SOFTRESET_REG, BMA222_SOFTRESET_MASK);
	if (result) {
		LOG_RESULT_LOCATION(result);
		return result;
	}
	msleep(10);

	result = bma222_set_odr(mlsl_handle, pdata, resume_config,
				TRUE, resume_config->odr);
	if (result) {
		LOG_RESULT_LOCATION(result);
		return result;
	}
	result = bma222_set_fsr(mlsl_handle, pdata, resume_config,
				TRUE, resume_config->fsr);
	if (result) {
		LOG_RESULT_LOCATION(result);
		return result;
	}

	return result;
}
Exemplo n.º 7
0
static int inv_i2c_write(struct i2c_adapter *i2c_adap,
			    unsigned char address,
			    unsigned int len, unsigned char const *data)
{
	struct i2c_msg msgs[1];
	int res;

	if (!data || !i2c_adap) {
		LOG_RESULT_LOCATION(-EINVAL);
		return -EINVAL;
	}

	msgs[0].addr = address;
	msgs[0].flags = 0;	/* write */
	msgs[0].buf = (unsigned char *)data;
	msgs[0].len = len;

	res = i2c_transfer(i2c_adap, msgs, 1);
	if (res < 1) {
		if (res == 0)
			res = -EIO;
		LOG_RESULT_LOCATION(res);
		return res;
	} else
		return 0;
}
Exemplo n.º 8
0
int inv_serial_read(
	void *sl_handle,
	unsigned char slave_addr,
	unsigned char register_addr,
	unsigned short length,
	unsigned char *data)
{
	int result;
	unsigned short bytes_read = 0;

	if ((slave_addr & 0x7E) == DEFAULT_MPU_SLAVEADDR
		&& (register_addr == MPUREG_FIFO_R_W ||
		    register_addr == MPUREG_MEM_R_W)) {
		LOG_RESULT_LOCATION(INV_ERROR_INVALID_PARAMETER);
		return INV_ERROR_INVALID_PARAMETER;
	}

	while (bytes_read < length) {
		unsigned short this_len =
		    min(SERIAL_MAX_TRANSFER_SIZE, length - bytes_read);
		result = inv_i2c_read((struct i2c_adapter *)sl_handle,
				      slave_addr, register_addr + bytes_read,
				      this_len, &data[bytes_read]);
		if (result) {
			LOG_RESULT_LOCATION(result);
			return result;
		}
		bytes_read += this_len;
	}
	return 0;
}
Exemplo n.º 9
0
/* -------------------------------------------------------------------------- */
static int ami30x_suspend(void *mlsl_handle,
			  struct ext_slave_descr *slave,
			  struct ext_slave_platform_data *pdata)
{
	int result;
	unsigned char reg;
	result =
	    inv_serial_read(mlsl_handle, pdata->address, AMI30X_REG_CNTL1,
			    1, &reg);
	if (result) {
		LOG_RESULT_LOCATION(result);
		return result;
	}

	reg &= ~(AMI30X_BIT_CNTL1_PC1 | AMI30X_BIT_CNTL1_FS1);
	result =
	    inv_serial_single_write(mlsl_handle, pdata->address,
				    AMI30X_REG_CNTL1, reg);
	if (result) {
		LOG_RESULT_LOCATION(result);
		return result;
	}

	return result;
}
Exemplo n.º 10
0
static int hscdtd002b_resume(void *mlsl_handle,
			     struct ext_slave_descr *slave,
			     struct ext_slave_platform_data *pdata)
{
	int result = INV_SUCCESS;

	/* Soft reset */
	result =
	    inv_serial_single_write(mlsl_handle, pdata->address,
				    COMPASS_HSCDTD002B_CTRL3, 0x80);
	if (result) {
		LOG_RESULT_LOCATION(result);
		return result;
	}
	/* Force state; Power mode: active */
	result =
	    inv_serial_single_write(mlsl_handle, pdata->address,
				    COMPASS_HSCDTD002B_CTRL1, 0x82);
	if (result) {
		LOG_RESULT_LOCATION(result);
		return result;
	}
	/* Data ready enable */
	result =
	    inv_serial_single_write(mlsl_handle, pdata->address,
				    COMPASS_HSCDTD002B_CTRL2, 0x08);
	if (result) {
		LOG_RESULT_LOCATION(result);
		return result;
	}
	msleep(1);		/* turn-on time */

	return result;
}
Exemplo n.º 11
0
static int ami30x_resume(void *mlsl_handle,
			 struct ext_slave_descr *slave,
			 struct ext_slave_platform_data *pdata)
{
	int result = INV_SUCCESS;

	/* Set CNTL1 reg to power model active */
	result =
	    inv_serial_single_write(mlsl_handle, pdata->address,
				    AMI30X_REG_CNTL1,
				    AMI30X_BIT_CNTL1_PC1 |
				    AMI30X_BIT_CNTL1_FS1);
	if (result) {
		LOG_RESULT_LOCATION(result);
		return result;
	}
	/* Set CNTL2 reg to DRDY active high and enabled */
	result =
	    inv_serial_single_write(mlsl_handle, pdata->address,
				    AMI30X_REG_CNTL2,
				    AMI30X_BIT_CNTL2_DREN |
				    AMI30X_BIT_CNTL2_DRP);
	if (result) {
		LOG_RESULT_LOCATION(result);
		return result;
	}
	/* Set CNTL3 reg to forced measurement period */
	result =
	    inv_serial_single_write(mlsl_handle, pdata->address,
				    AMI30X_REG_CNTL3, AMI30X_BIT_CNTL3_F0RCE);

	return result;
}
/**
 *  @brief Simply disables the IRQ since it is not usable on BMA150 devices.
 *
 *  @param mlsl_handle
 *             the handle to the serial channel the device is connected to.
 *  @param pdata
 *             a pointer to the slave platform data.
 *  @param config
 *              configuration to apply to, suspend or resume
 *  @param apply
 *             whether to apply immediately or save the settings to be applied
 *             at the next resume.
 *  @param irq_type
 *              the type of IRQ.  Valid values are
 *              - MPU_SLAVE_IRQ_TYPE_NONE
 *              - MPU_SLAVE_IRQ_TYPE_MOTION
 *              - MPU_SLAVE_IRQ_TYPE_DATA_READY
 *              The only supported IRQ type is MPU_SLAVE_IRQ_TYPE_NONE which
 *              corresponds to disabling the IRQ completely.
 *
 *  @return INV_SUCCESS if successful or a non-zero error code.
 */
static int bma150_set_irq(void *mlsl_handle,
			  struct ext_slave_platform_data *pdata,
			  struct bma150_config *config,
			  int apply,
			  long irq_type)
{
	int result = INV_SUCCESS;

	if (irq_type != MPU_SLAVE_IRQ_TYPE_NONE)
		return INV_ERROR_FEATURE_NOT_IMPLEMENTED;

	config->irq_type = MPU_SLAVE_IRQ_TYPE_NONE;
	config->int_reg = 0x00;

	if (apply) {
		result = inv_serial_single_write(mlsl_handle, pdata->address,
			 BMA150_CTRL_REG, config->ctrl_reg);
		if (result) {
			LOG_RESULT_LOCATION(result);
			return result;
		}
		result = inv_serial_single_write(mlsl_handle, pdata->address,
			 BMA150_INT_REG, config->int_reg);
		if (result) {
			LOG_RESULT_LOCATION(result);
			return result;
		}
	}
	return result;
}
static int mpu6050_input_set_fsr(struct mpu6050_input_data *data, int fsr)
{
	unsigned char fsr_mask;
	int result;
	unsigned char reg;

	if (fsr <= 2000) {
		fsr_mask = 0x00;
	} else if (fsr <= 4000) {
		fsr_mask = 0x08;
	} else if (fsr <= 8000) {
		fsr_mask = 0x10;
	} else {		/* fsr = [8001, oo) */
		fsr_mask = 0x18;
	}

	result =
		mpu6050_i2c_read_reg(data->client,
			MPUREG_ACCEL_CONFIG, 1, &reg);
	if (result) {
		LOG_RESULT_LOCATION(result);
		return result;
	}
	result =
		mpu6050_i2c_write_single_reg(data->client, MPUREG_ACCEL_CONFIG,
					 reg | fsr_mask);
	if (result) {
		LOG_RESULT_LOCATION(result);
		return result;
	}

	return result;
}
/**
 *  @brief suspends the device to put it in its lowest power mode.
 *
 *  @param mlsl_handle
 *             the handle to the serial channel the device is connected to.
 *  @param slave
 *             a pointer to the slave descriptor data structure.
 *  @param pdata
 *             a pointer to the slave platform data.
 *
 *  @return INV_SUCCESS if successful or a non-zero error code.
 */
static int bma222_suspend(void *mlsl_handle,
			  struct ext_slave_descr *slave,
			  struct ext_slave_platform_data *pdata)
{
	int result;
	struct bma222_config *suspend_config =
		&((struct bma222_private_data *)pdata->private_data)->suspend;

	result = bma222_set_odr(mlsl_handle, pdata, suspend_config,
				TRUE, suspend_config->odr);
	if (result) {
		LOG_RESULT_LOCATION(result);
		return result;
	}
	result = bma222_set_fsr(mlsl_handle, pdata, suspend_config,
				TRUE, suspend_config->fsr);
	if (result) {
		LOG_RESULT_LOCATION(result);
		return result;
	}

	result = inv_serial_single_write(mlsl_handle, pdata->address,
				BMA222_PWR_REG, BMA222_PWR_SLEEP_MASK);
	if (result) {
		LOG_RESULT_LOCATION(result);
		return result;
	}

	msleep(3); /* 3 ms powerup time maximum */
	return result;
}
Exemplo n.º 15
0
static int inv_i2c_read(struct i2c_adapter *i2c_adap,
			   unsigned char address, unsigned char reg,
			   unsigned int len, unsigned char *data)
{
	struct i2c_msg msgs[2];
	int res;

	if (!data || !i2c_adap) {
		LOG_RESULT_LOCATION(-EINVAL);
		return -EINVAL;
	}

	msgs[0].addr = address;
	msgs[0].flags = 0;	/* write */
	msgs[0].buf = &reg;
	msgs[0].len = 1;

	msgs[1].addr = address;
	msgs[1].flags = I2C_M_RD;
	msgs[1].buf = data;
	msgs[1].len = len;

	res = i2c_transfer(i2c_adap, msgs, 2);
	if (res < 2) {
		if (res >= 0)
			res = -EIO;
		LOG_RESULT_LOCATION(res);
		return res;
	} else
		return 0;
}
Exemplo n.º 16
0
/**
 *  @brief  inv_set_control_sensitivity is used to set the sensitivity for a control
 *          signal.
 *
 *  @pre    inv_dmp_open() Must be called with MLDmpDefaultOpen() or 
 *          inv_open_low_power_pedometer().
 *
 *  @param controlSignal    Indicates which control signal is being modified.
 *                          Must be one of:
 *                          - INV_CONTROL_1,
 *                          - INV_CONTROL_2,
 *                          - INV_CONTROL_3 or
 *                          - INV_CONTROL_4.
 *
 *  @param sensitivity      The sensitivity of the control signal.
 *
 *  @return error code
 */
inv_error_t inv_set_control_sensitivity(unsigned short controlSignal,
                                        long sensitivity)
{
    INVENSENSE_FUNC_START;
    unsigned char regs[2];
    long finalSens = 0;
    inv_error_t result;

    if (inv_get_state() < INV_STATE_DMP_OPENED)
        return INV_ERROR_SM_IMPROPER_STATE;

    finalSens = sensitivity * 100;
    if (finalSens > 16384) {
        finalSens = 16384;
    }
    regs[0] = (unsigned char)(finalSens / 256);
    regs[1] = (unsigned char)(finalSens % 256);
    switch (controlSignal) {
    case INV_CONTROL_1:
        result = inv_set_mpu_memory(KEY_D_0_224, 2, regs);
        if (result) {
            LOG_RESULT_LOCATION(result);
            return result;
        }
        cntrl_params.sensitivity[0] = (unsigned short)sensitivity;
        break;
    case INV_CONTROL_2:
        result = inv_set_mpu_memory(KEY_D_0_228, 2, regs);
        if (result) {
            LOG_RESULT_LOCATION(result);
            return result;
        }
        cntrl_params.sensitivity[1] = (unsigned short)sensitivity;
        break;
    case INV_CONTROL_3:
        result = inv_set_mpu_memory(KEY_D_0_232, 2, regs);
        if (result) {
            LOG_RESULT_LOCATION(result);
            return result;
        }
        cntrl_params.sensitivity[2] = (unsigned short)sensitivity;
        break;
    case INV_CONTROL_4:
        result = inv_set_mpu_memory(KEY_D_0_236, 2, regs);
        if (result) {
            LOG_RESULT_LOCATION(result);
            return result;
        }
        cntrl_params.sensitivity[3] = (unsigned short)sensitivity;
        break;
    default:
        break;
    }
    if (finalSens != sensitivity * 100) {
        return INV_ERROR_INVALID_PARAMETER;
    } else {
        return INV_SUCCESS;
    }
}
Exemplo n.º 17
0
static int ak8963_get_config(void *mlsl_handle,
			     struct ext_slave_descr *slave,
			     struct ext_slave_platform_data *pdata,
			     struct ext_slave_config *data)
{
	struct ak8963_private_data *private_data = pdata->private_data;
	int result;
	if (!data->data)
		return INV_ERROR_INVALID_PARAMETER;

	switch (data->key) {
	case MPU_SLAVE_READ_REGISTERS:
		{
			unsigned char *serial_data =
			    (unsigned char *)data->data;
			result =
			    inv_serial_read(mlsl_handle, pdata->address,
					    serial_data[0], data->len - 1,
					    &serial_data[1]);
			if (result) {
				LOG_RESULT_LOCATION(result);
				return result;
			}
			break;
		}
	case MPU_SLAVE_READ_SCALE:
		{
			unsigned char *serial_data =
			    (unsigned char *)data->data;
			serial_data[0] = private_data->init.asa[0];
			serial_data[1] = private_data->init.asa[1];
			serial_data[2] = private_data->init.asa[2];
			result = INV_SUCCESS;
			if (result) {
				LOG_RESULT_LOCATION(result);
				return result;
			}
			break;
		}
	case MPU_SLAVE_CONFIG_ODR_SUSPEND:
		(*(unsigned long *)data->data) = 0;
		break;
	case MPU_SLAVE_CONFIG_ODR_RESUME:
		(*(unsigned long *)data->data) = 8000;
		break;
	case MPU_SLAVE_CONFIG_FSR_SUSPEND:
	case MPU_SLAVE_CONFIG_FSR_RESUME:
	case MPU_SLAVE_CONFIG_MOT_THS:
	case MPU_SLAVE_CONFIG_NMOT_THS:
	case MPU_SLAVE_CONFIG_MOT_DUR:
	case MPU_SLAVE_CONFIG_NMOT_DUR:
	case MPU_SLAVE_CONFIG_IRQ_SUSPEND:
	case MPU_SLAVE_CONFIG_IRQ_RESUME:
	default:
		return INV_ERROR_FEATURE_NOT_IMPLEMENTED;
	};

	return INV_SUCCESS;
}
Exemplo n.º 18
0
static int mpu_memory_read(struct i2c_adapter *i2c_adap,
			   unsigned char mpu_addr,
			   unsigned short mem_addr,
			   unsigned int len, unsigned char *data)
{
	unsigned char bank[2];
	unsigned char addr[2];
	unsigned char buf;

	struct i2c_msg msgs[4];
	int res;

	if (mpu_device_is_shutdown)
		return -EIO;

	if (!data || !i2c_adap) {
		LOG_RESULT_LOCATION(-EINVAL);
		return -EINVAL;
	}

	bank[0] = MPUREG_BANK_SEL;
	bank[1] = mem_addr >> 8;

	addr[0] = MPUREG_MEM_START_ADDR;
	addr[1] = mem_addr & 0xFF;

	buf = MPUREG_MEM_R_W;

	/* write message */
	msgs[0].addr = mpu_addr;
	msgs[0].flags = 0;
	msgs[0].buf = bank;
	msgs[0].len = sizeof(bank);

	msgs[1].addr = mpu_addr;
	msgs[1].flags = 0;
	msgs[1].buf = addr;
	msgs[1].len = sizeof(addr);

	msgs[2].addr = mpu_addr;
	msgs[2].flags = 0;
	msgs[2].buf = &buf;
	msgs[2].len = 1;

	msgs[3].addr = mpu_addr;
	msgs[3].flags = I2C_M_RD;
	msgs[3].buf = data;
	msgs[3].len = len;

	res = i2c_transfer(i2c_adap, msgs, 4);
	if (res != 4) {
		if (res >= 0)
			res = -EIO;
		LOG_RESULT_LOCATION(res);
		return res;
	} else
		return 0;
}
Exemplo n.º 19
0
static int mpu_memory_write(struct i2c_adapter *i2c_adap,
			    unsigned char mpu_addr,
			    unsigned short mem_addr,
			    unsigned int len, unsigned char const *data)
{
	unsigned char bank[2];
	unsigned char addr[2];
	unsigned char buf[513];

	struct i2c_msg msgs[3];
	int res;

	if (mpu_device_is_shutdown)
		return -EIO;

	if (!data || !i2c_adap) {
		LOG_RESULT_LOCATION(-EINVAL);
		return -EINVAL;
	}
	if (len >= (sizeof(buf) - 1)) {
		LOG_RESULT_LOCATION(-ENOMEM);
		return -ENOMEM;
	}

	bank[0] = MPUREG_BANK_SEL;
	bank[1] = mem_addr >> 8;

	addr[0] = MPUREG_MEM_START_ADDR;
	addr[1] = mem_addr & 0xFF;

	buf[0] = MPUREG_MEM_R_W;
	memcpy(buf + 1, data, len);

	/* write message */
	msgs[0].addr = mpu_addr;
	msgs[0].flags = 0;
	msgs[0].buf = bank;
	msgs[0].len = sizeof(bank);

	msgs[1].addr = mpu_addr;
	msgs[1].flags = 0;
	msgs[1].buf = addr;
	msgs[1].len = sizeof(addr);

	msgs[2].addr = mpu_addr;
	msgs[2].flags = 0;
	msgs[2].buf = (unsigned char *)buf;
	msgs[2].len = len + 1;

	res = i2c_transfer(i2c_adap, msgs, 3);
	if (res != 3) {
		if (res >= 0)
			res = -EIO;
		LOG_RESULT_LOCATION(res);
		return res;
	} else
		return 0;
}
Exemplo n.º 20
0
/**
 *  @brief  Get a sample of compass data from the device.
 *  @param  data
 *              the buffer to store the compass raw data for
 *              X, Y, and Z axes.
 *  @return INV_SUCCESS or a non-zero error code.
 */
inv_error_t inv_get_compass_data(long *data)
{
    inv_error_t result;
    int ii;
    struct mldl_cfg *mldl_cfg = inv_get_dl_config();

    unsigned char *tmp = inv_obj.mag->raw_data;

    if (mldl_cfg->slave[EXT_SLAVE_TYPE_COMPASS]->read_len >
        sizeof(inv_obj.mag->raw_data)) {
        LOG_RESULT_LOCATION(INV_ERROR_INVALID_CONFIGURATION);
        return INV_ERROR_INVALID_CONFIGURATION;
    }

    if (mldl_cfg->pdata_slave[EXT_SLAVE_TYPE_COMPASS]->bus ==
        EXT_SLAVE_BUS_PRIMARY ||
        !(mldl_cfg->inv_mpu_cfg->requested_sensors & INV_DMP_PROCESSOR)) {
        /*--- read the compass sensor data.
          The compass read function may return an INV_ERROR_COMPASS_* errors
          when the data is not ready (read/refresh frequency mismatch) or 
          the internal data sampling timing of the device was not respected. 
          Returning the error code will make the sensor fusion supervisor 
          ignore this compass data sample. ---*/
        result = (inv_error_t) inv_mpu_read_compass(mldl_cfg,
                                                    inv_get_serial_handle(),
                                                    inv_get_serial_handle(),
                                                    tmp);
        if (result) {
            if (COMPASS_DEBUG) {
                MPL_LOGV("inv_mpu_read_compass returned %d\n", result);
            }
            return result;
        }
        for (ii = 0; ii < 3; ii++) {
            if (EXT_SLAVE_BIG_ENDIAN ==
                mldl_cfg->slave[EXT_SLAVE_TYPE_COMPASS]->endian)
                data[ii] =
                    ((long)((signed char)tmp[2 * ii]) << 8) + tmp[2 * ii + 1];
            else
                data[ii] =
                    ((long)((signed char)tmp[2 * ii + 1]) << 8) + tmp[2 * ii];
        }
    } else { /* compass on the 2nd bus  or  DMP is off */
        result = inv_get_external_sensor_data(data, 3);
        if (result) {
            LOG_RESULT_LOCATION(result);
            return result;
        }
    }
    data[0] = inv_q30_mult(data[0], inv_obj.mag->asa[0]);
    data[1] = inv_q30_mult(data[1], inv_obj.mag->asa[1]);
    data[2] = inv_q30_mult(data[2], inv_obj.mag->asa[2]);

    return INV_SUCCESS;
}
/**
 *  @brief one-time device driver initialization function.
 *         If the driver is built as a kernel module, this function will be
 *         called when the module is loaded in the kernel.
 *         If the driver is built-in in the kernel, this function will be
 *         called at boot time.
 *
 *  @param mlsl_handle
 *             the handle to the serial channel the device is connected to.
 *  @param slave
 *             a pointer to the slave descriptor data structure.
 *  @param pdata
 *             a pointer to the slave platform data.
 *
 *  @return INV_SUCCESS if successful or a non-zero error code.
 */
static int bma222_init(void *mlsl_handle,
		       struct ext_slave_descr *slave,
		       struct ext_slave_platform_data *pdata)
{
	int result;

	struct bma222_private_data *private_data;
	private_data = (struct bma222_private_data *)
	    kzalloc(sizeof(struct bma222_private_data), GFP_KERNEL);

	if (!private_data)
		return INV_ERROR_MEMORY_EXAUSTED;

	pdata->private_data = private_data;

	result = inv_serial_single_write(mlsl_handle, pdata->address,
			BMA222_SOFTRESET_REG, BMA222_SOFTRESET_MASK);
	if (result) {
		LOG_RESULT_LOCATION(result);
		return result;
	}
	msleep(1);

	result = bma222_set_odr(mlsl_handle, pdata, &private_data->suspend,
				FALSE, 0);
	if (result) {
		LOG_RESULT_LOCATION(result);
		return result;
	}
	result = bma222_set_odr(mlsl_handle, pdata, &private_data->resume,
				FALSE, 200000);
	if (result) {
		LOG_RESULT_LOCATION(result);
		return result;
	}

	result = bma222_set_fsr(mlsl_handle, pdata, &private_data->suspend,
				FALSE, 2000);
	result = bma222_set_fsr(mlsl_handle, pdata, &private_data->resume,
				FALSE, 2000);
	if (result) {
		LOG_RESULT_LOCATION(result);
		return result;
	}

	result = inv_serial_single_write(mlsl_handle, pdata->address,
				BMA222_PWR_REG, BMA222_PWR_SLEEP_MASK);
	if (result) {
		LOG_RESULT_LOCATION(result);
		return result;
	}

	return result;
}
Exemplo n.º 22
0
/**
 *  @brief suspends the device to put it in its lowest power mode.
 *
 *  @param mlsl_handle
 *             the handle to the serial channel the device is connected to.
 *  @param slave
 *             a pointer to the slave descriptor data structure.
 *  @param pdata
 *             a pointer to the slave platform data.
 *
 *  @return INV_SUCCESS if successful or a non-zero error code.
 */
static int adxl34x_suspend(void *mlsl_handle,
			   struct ext_slave_descr *slave,
			   struct ext_slave_platform_data *pdata)
{
	int result;

	/*
	struct adxl34x_config *suspend_config =
		&((struct adxl34x_private_data *)pdata->private_data)->suspend;

	result = adxl34x_set_odr(mlsl_handle, pdata, suspend_config,
				true, suspend_config->odr);
	if (result) {
	LOG_RESULT_LOCATION(result);
	return result;
}
	result = adxl34x_set_fsr(mlsl_handle, pdata, suspend_config,
				true, suspend_config->fsr);
	if (result) {
	LOG_RESULT_LOCATION(result);
	return result;
}
	*/

	/*
	  Page 25
	  When clearing the sleep bit, it is recommended that the part
	  be placed into standby mode and then set back to measurement mode
	  with a subsequent write.
	  This is done to ensure that the device is properly biased if sleep
	  mode is manually disabled; otherwise, the first few samples of data
	  after the sleep bit is cleared may have additional noise,
	  especially if the device was asleep when the bit was cleared. */

	/* go in standy-by mode (suspends measurements) */
	result = inv_serial_single_write(mlsl_handle, pdata->address,
			ADXL34X_PWR_REG, ADXL34X_PWR_MEAS_MASK);
	if (result) {
		LOG_RESULT_LOCATION(result);
		return result;
	}
	/* and then in sleep */
	result = inv_serial_single_write(mlsl_handle, pdata->address,
			ADXL34X_PWR_REG,
			ADXL34X_PWR_MEAS_MASK | ADXL34X_PWR_SLEEP_MASK);
	if (result) {
		LOG_RESULT_LOCATION(result);
		return result;
	}
	return result;
}
/**
 *  @brief Set the output data rate for the particular configuration.
 *
 *  @param mlsl_handle
 *             the handle to the serial channel the device is connected to.
 *  @param pdata
 *             a pointer to the slave platform data.
 *  @param config
 *             Config to modify with new ODR.
 *  @param apply
 *             whether to apply immediately or save the settings to be applied
 *             at the next resume.
 *  @param odr
 *             Output data rate in units of 1/1000Hz (mHz).
 *
 *  @return INV_SUCCESS if successful or a non-zero error code.
 */
static int bma150_set_odr(void *mlsl_handle,
			struct ext_slave_platform_data *pdata,
			struct bma150_config *config,
			int apply,
			long odr)
{
	unsigned char odr_bits = 0;
	unsigned char wup_bits = 0;
	int result = INV_SUCCESS;

	if (odr > 100000) {
		config->odr = 190000;
		odr_bits = 0x03;
	} else if (odr > 50000) {
		config->odr = 100000;
		odr_bits = 0x02;
	} else if (odr > 25000) {
		config->odr = 50000;
		odr_bits = 0x01;
	} else if (odr > 0) {
		config->odr = 25000;
		odr_bits = 0x00;
	} else {
		config->odr = 0;
		wup_bits = 0x00;
	}

	config->int_reg &= BMA150_INT_MASK_WUP;
	config->ctrl_reg &= BMA150_CTRL_MASK_ODR;
	config->ctrl_reg |= odr_bits;

	MPL_LOGV("ODR: %d\n", config->odr);
	if (apply) {
		result = inv_serial_single_write(mlsl_handle, pdata->address,
					BMA150_CTRL_REG, config->ctrl_reg);
		if (result) {
			LOG_RESULT_LOCATION(result);
			return result;
		}
		result = inv_serial_single_write(mlsl_handle, pdata->address,
					BMA150_INT_REG, config->int_reg);
		if (result) {
			LOG_RESULT_LOCATION(result);
			return result;
		}
	}

	return result;
}
Exemplo n.º 24
0
int inv_serial_write_fifo(
	void *sl_handle,
	unsigned char slave_addr,
	unsigned short length,
	unsigned char const *data)
{
	int result;
	unsigned char i2c_write[SERIAL_MAX_TRANSFER_SIZE + 1];
	unsigned short bytes_written = 0;

	if (length > FIFO_HW_SIZE) {
		printk(KERN_ERR
		       "maximum fifo write length is %d\n", FIFO_HW_SIZE);
		return INV_ERROR_INVALID_PARAMETER;
	}
	while (bytes_written < length) {
		unsigned short this_len =
		    min(SERIAL_MAX_TRANSFER_SIZE, length - bytes_written);
		i2c_write[0] = MPUREG_FIFO_R_W;
		memcpy(&i2c_write[1], &data[bytes_written], this_len);
		result = inv_i2c_write((struct i2c_adapter *)sl_handle,
				       slave_addr, this_len + 1, i2c_write);
		if (result) {
			LOG_RESULT_LOCATION(result);
			return result;
		}
		bytes_written += this_len;
	}
	return 0;
}
Exemplo n.º 25
0
inv_error_t inv_compass_check_range(void)
{
    struct ext_slave_config config;
    unsigned char data[3];
    inv_error_t result;

    config.key = MPU_SLAVE_RANGE_CHECK;
    config.len = 3;
    config.apply = TRUE;
    config.data = data;

    result = inv_mpu_get_compass_config(inv_get_dl_config(),
                                        inv_get_serial_handle(),
                                        inv_get_serial_handle(), &config);
    if (result) {
        LOG_RESULT_LOCATION(result);
        return result;
    }

    if(data[0] || data[1] || data[2]) {
        /* some value clipped */
        return INV_ERROR_COMPASS_DATA_ERROR;
    }
    return INV_SUCCESS;
}
Exemplo n.º 26
0
static int ak8963_config(void *mlsl_handle,
			 struct ext_slave_descr *slave,
			 struct ext_slave_platform_data *pdata,
			 struct ext_slave_config *data)
{
	int result;
	if (!data->data)
		return INV_ERROR_INVALID_PARAMETER;

	switch (data->key) {
	case MPU_SLAVE_WRITE_REGISTERS:
		result = inv_serial_write(mlsl_handle, pdata->address,
					  data->len,
					  (unsigned char *)data->data);
		if (result) {
			LOG_RESULT_LOCATION(result);
			return result;
		}
		break;
	case MPU_SLAVE_CONFIG_ODR_SUSPEND:
	case MPU_SLAVE_CONFIG_ODR_RESUME:
	case MPU_SLAVE_CONFIG_FSR_SUSPEND:
	case MPU_SLAVE_CONFIG_FSR_RESUME:
	case MPU_SLAVE_CONFIG_MOT_THS:
	case MPU_SLAVE_CONFIG_NMOT_THS:
	case MPU_SLAVE_CONFIG_MOT_DUR:
	case MPU_SLAVE_CONFIG_NMOT_DUR:
	case MPU_SLAVE_CONFIG_IRQ_SUSPEND:
	case MPU_SLAVE_CONFIG_IRQ_RESUME:
	default:
		return INV_ERROR_FEATURE_NOT_IMPLEMENTED;
	};

	return INV_SUCCESS;
}
Exemplo n.º 27
0
int inv_serial_read_mem(
	void *sl_handle,
	unsigned char slave_addr,
	unsigned short mem_addr,
	unsigned short length,
	unsigned char *data)
{
	int result;
	unsigned short bytes_read = 0;

	if ((mem_addr & 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, mem_addr & 0xFF);
		return INV_ERROR_INVALID_PARAMETER;
	}
	while (bytes_read < length) {
		unsigned short this_len =
		    min(SERIAL_MAX_TRANSFER_SIZE, length - bytes_read);
		result =
		    mpu_memory_read((struct i2c_adapter *)sl_handle,
				    slave_addr, mem_addr + bytes_read,
				    this_len, &data[bytes_read]);
		if (result) {
			LOG_RESULT_LOCATION(result);
			return result;
		}
		bytes_read += this_len;
	}
	return 0;
}
/**
 *  @brief Set the full scale range of the accels
 *
 *  @param mlsl_handle
 *             the handle to the serial channel the device is connected to.
 *  @param pdata
 *             a pointer to the slave platform data.
 *  @param config
 *             pointer to configuration.
 *  @param apply
 *             whether to apply immediately or save the settings to be applied
 *             at the next resume.
 *  @param fsr
 *             requested full scale range.
 *
 *  @return INV_SUCCESS if successful or a non-zero error code.
 */
static int bma222_set_fsr(void *mlsl_handle,
			  struct ext_slave_platform_data *pdata,
			  struct bma222_config *config,
			  int apply,
			  long fsr)
{
	int result = INV_SUCCESS;
	unsigned char reg_fsr_mask;

	if (fsr <= 2000) {
		reg_fsr_mask = 0x03;
		config->fsr = 2000;
	} else if (fsr <= 4000) {
		reg_fsr_mask = 0x05;
		config->fsr = 4000;
	} else if (fsr <= 8000) {
		reg_fsr_mask = 0x08;
		config->fsr = 8000;
	} else { /* 8001 -> oo */
		reg_fsr_mask = 0x0C;
		config->fsr = 16000;
	}

	if (apply) {
		MPL_LOGV("FSR: %d\n", config->fsr);
		result = inv_serial_single_write(mlsl_handle, pdata->address,
				BMA222_FSR_REG, reg_fsr_mask);
		if (result) {
			LOG_RESULT_LOCATION(result);
			return result;
		}
	}
	return result;
}
Exemplo n.º 29
0
/**
 *  @brief  inv_set_control_func allows the user to choose how the sensor data will
 *          be processed in order to provide a control parameter.
 *          inv_set_control_func allows the user to choose which control functions
 *          will be incorporated in the sensor data processing.
 *          The control functions are:
 *          - INV_GRID
 *          Indicates that the user will be controlling a system that
 *          has discrete steps, such as icons, menu entries, pixels, etc.
 *          - INV_SMOOTH
 *          Indicates that noise from unintentional motion should be filtered out.
 *          - INV_DEAD_ZONE
 *          Indicates that a dead zone should be used, below which sensor
 *          data is set to zero.
 *          - INV_HYSTERESIS
 *          Indicates that, when INV_GRID is selected, hysteresis should
 *          be used to prevent the control signal from switching rapidly across
 *          elements of the grid.
 *
 *  @pre    inv_dmp_open() Must be called with MLDmpDefaultOpen() or 
 *          inv_open_low_power_pedometer().
 *
 *  @param  function    Indicates what functions will be used.
 *                      Can be a bitwise OR of several values.
 *
 *  @return Zero if the command is successful; an ML error code otherwise.
 */
inv_error_t inv_set_control_func(unsigned short function)
{
    INVENSENSE_FUNC_START;
    unsigned char regs[8] = { DINA06, DINA26,
        DINA46, DINA66,
        DINA0E, DINA2E,
        DINA4E, DINA6E
    };
    unsigned char i;
    inv_error_t result;

    if (inv_get_state() < INV_STATE_DMP_OPENED)
        return INV_ERROR_SM_IMPROPER_STATE;

    if ((function & INV_SMOOTH) == 0) {
        for (i = 0; i < 8; i++) {
            regs[i] = DINA80 + 3;
        }
    }
    result = inv_set_mpu_memory(KEY_CFG_4, 8, regs);
    if (result) {
        LOG_RESULT_LOCATION(result);
        return result;
    }
    cntrl_params.functions = function;
    result = inv_set_dead_zone();

    return result;
}
Exemplo n.º 30
0
int inv_serial_read_fifo(
	void *sl_handle,
	unsigned char slave_addr,
	unsigned short length,
	unsigned char *data)
{
	int result;
	unsigned short bytes_read = 0;

	if (length > FIFO_HW_SIZE) {
		printk(KERN_ERR
		       "maximum fifo read length is %d\n", FIFO_HW_SIZE);
		return INV_ERROR_INVALID_PARAMETER;
	}
	while (bytes_read < length) {
		unsigned short this_len =
		    min(SERIAL_MAX_TRANSFER_SIZE, length - bytes_read);
		result = inv_i2c_read((struct i2c_adapter *)sl_handle,
				      slave_addr, MPUREG_FIFO_R_W, this_len,
				      &data[bytes_read]);
		if (result) {
			LOG_RESULT_LOCATION(result);
			return result;
		}
		bytes_read += this_len;
	}

	return 0;
}