/**
 *  @internal
 *  @brief  Retrieve the unique MPU device identifier from the internal OTP
 *          bank 0 memory.
 *  @param  mlsl_handle
 *              serial interface handle to allow serial communication with the
 *              device, both gyro and accelerometer.
 *  @return 0 on success, a non-zero error code from the serial layer on error.
 */
static inv_error_t get_mpu_unique_id(void *mlsl_handle)
{
    inv_error_t result;
    unsigned char otp0[8];


    result =
        inv_serial_read_mem(mlsl_handle, mldl_cfg->mpu_chip_info->addr,
            (BIT_PRFTCH_EN | BIT_CFG_USER_BANK | MPU_MEM_OTP_BANK_0) << 8 |
            0x00, 6, otp0);
    if (result)
        goto close;

    MPL_LOGI("\n");
    MPL_LOGI("DIE_ID   : %06X\n",
                ((int)otp0[1] << 8 | otp0[0]) & 0x1fff);
    MPL_LOGI("WAFER_ID : %06X\n",
                (((int)otp0[2] << 8 | otp0[1]) & 0x03ff ) >> 5);
    MPL_LOGI("A_LOT_ID : %06X\n",
                ( ((int)otp0[4] << 16 | (int)otp0[3] << 8 |
                otp0[2]) & 0x3ffff) >> 2);
    MPL_LOGI("W_LOT_ID : %06X\n",
                ( ((int)otp0[5] << 8 | otp0[4]) & 0x3fff) >> 2);
    MPL_LOGI("WP_ID    : %06X\n",
                ( ((int)otp0[6] << 8 | otp0[5]) & 0x03ff) >> 7);
    MPL_LOGI("REV_ID   : %06X\n", otp0[6] >> 2);
    MPL_LOGI("\n");

close:
    result =
        inv_serial_single_write(mlsl_handle, mldl_cfg->mpu_chip_info->addr, MPUREG_BANK_SEL, 0x00);
    return result;
}
Пример #2
0
static int mpu_handle_mlsl(void *sl_handle,
			   unsigned char addr,
			   unsigned int cmd,
			   struct mpu_read_write __user *usr_msg)
{
	int retval = 0;
	struct mpu_read_write msg;
	unsigned char *user_data;
	retval = copy_from_user(&msg, usr_msg, sizeof(msg));
	if (retval)
		return -EFAULT;

	user_data = msg.data;
	if (msg.length && msg.data) {
		unsigned char *data;
		data = kmalloc(msg.length, GFP_KERNEL);
		if (!data)
			return -ENOMEM;

		retval = copy_from_user(data,
					(void __user *)msg.data, msg.length);
		if (retval) {
			retval = -EFAULT;
			kfree(data);
			return retval;
		}
		msg.data = data;
	} else {
		return -EPERM;
	}

	switch (cmd) {
	case MPU_READ:
		retval = inv_serial_read(sl_handle, addr,
					 msg.address, msg.length, msg.data);
		break;
	case MPU_WRITE:
		retval = inv_serial_write(sl_handle, addr,
					  msg.length, msg.data);
		break;
	case MPU_READ_MEM:
		retval = inv_serial_read_mem(sl_handle, addr,
					     msg.address, msg.length, msg.data);
		break;
	case MPU_WRITE_MEM:
		retval = inv_serial_write_mem(sl_handle, addr,
					      msg.address, msg.length,
					      msg.data);
		break;
	case MPU_READ_FIFO:
		retval = inv_serial_read_fifo(sl_handle, addr,
					      msg.length, msg.data);
		break;
	case MPU_WRITE_FIFO:
		retval = inv_serial_write_fifo(sl_handle, addr,
					       msg.length, msg.data);
		break;

	};
	if (retval) {
		dev_err(&((struct i2c_adapter *)sl_handle)->dev,
			"%s: i2c %d error %d\n",
			__func__, cmd, retval);
		kfree(msg.data);
		return retval;
	}
	retval = copy_to_user((unsigned char __user *)user_data,
			      msg.data, msg.length);
	kfree(msg.data);
	return retval;
}