/** * @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; }
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; }