#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/ide.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/gpio.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/of_gpio.h>
#include <linux/semaphore.h>
#include <linux/timer.h>
#include <linux/i2c.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include "bmi088_i2c.h"
#define bmi088i2c_CNT 1
#define bmi088i2c_NAME "bmi088i2c"
struct bmi088i2c_dev {
dev_t devid; /* 设备号 */
struct cdev cdev; /* cdev */
struct class *class; /* 类 */
struct device *device; /* 设备 */
struct device_node *nd[2]; /* 设备节点 */
unsigned char chip_addr[2]; /* 设备节点 */
int major; /* 主设备号 */
void *private_data; /* 私有数据 */
int16_t acceleration[3], gyro[3], temp; /* 芯片数据 */
};
typedef enum {
CHANELL_GYRO = 0,
CHANELL_ACC,
CHANELL_TEMP
}CHANELL_TYPE;
static struct bmi088i2c_dev bmi088i2cdev;
/*
* @description : 从bmi088i2c读取多个寄存器数据
* @param - dev: bmi088i2c设备
* @param - reg: 要读取的寄存器首地址
* @param - val: 读取到的数据
* @param - len: 要读取的数据长度
* @return : 操作结果
*/
static int bmi088i2c_read_regs(struct bmi088i2c_dev *dev,u8 chip_addr, u8 reg, void *val, int len)
{
int ret;
struct i2c_msg msg[2];
struct i2c_client *client = (struct i2c_client *)dev->private_data;
/* msg[0]为发送要读取的首地址 */
msg[0].addr = chip_addr; /* bmi088i2c地址 */
msg[0].flags = 0; /* 标记为发送数据 */
msg[0].buf = ® /* 读取的首地址 */
msg[0].len = 1; /* reg长度*/
/* msg[1]读取数据 */
msg[1].addr = chip_addr; /* bmi088i2c地址 */
msg[1].flags = I2C_M_RD; /* 标记为读取数据*/
msg[1].buf = val; /* 读取数据缓冲区 */
msg[1].len = len; /* 要读取的数据长度*/
ret = i2c_transfer(client->adapter, msg, 2);
if(ret == 2) {
ret = 0;
} else {
printk("i2c rd failed=%d reg=%06x len=%d\n",ret, reg, len);
ret = -EREMOTEIO;
}
return ret;
}
/*
* @description : 向bmi088i2c多个寄存器写入数据
* @param - dev: bmi088i2c设备
* @param - reg: 要写入的寄存器首地址
* @param - val: 要写入的数据缓冲区
* @param - len: 要写入的数据长度
* @return : 操作结果
*/
static s32 bmi088i2c_write_regs(struct bmi088i2c_dev *dev, u8 chip_addr, u8 reg, u8 *buf, u8 len)
{
u8 b[256];
struct i2c_msg msg;
struct i2c_client *client = (struct i2c_client *)dev->private_data;
b[0] = reg; /* 寄存器首地址 */
memcpy(&b[1],buf,len); /* 将要写入的数据拷贝到数组b里面 */
msg.addr = chip_addr; /* bmi088i2c地址 */
msg.flags = 0; /* 标记为写数据 */
msg.buf = b; /* 要写入的数据缓冲区 */
msg.len = len + 1; /* 要写入的数据长度 */
printk("addr %x, buf %x %x,len %d\r\n",msg.addr,msg.buf[0],msg.buf[1],msg.len);
return i2c_transfer(client->adapter, &msg, 1);
}
/*
* @description : 读取bmi088i2c指定寄存器值,读取一个寄存器
* @param - dev: bmi088i2c设备
* @param - reg: 要读取的寄存器
* @return : 读取到的寄存器值
*/
static unsigned char bmi088i2c_read_reg(struct bmi088i2c_dev *dev, CHANELL_TYPE type, u8 reg)
{
u8 data = 0;
if(type == CHANELL_GYRO)
bmi088i2c_read_regs(dev, BMI08_GYRO_I2C_ADDR_PRIMARY, reg, &data, 1);
else if(type == CHANELL_ACC)
bmi088i2c_read_regs(dev, BMI08_ACCEL_I2C_ADDR_PRIMARY, reg, &data, 1);
return data;
}
/*
* @description : 向bmi088i2c指定寄存器写入指定的值,写一个寄存器
* @param - dev: bmi088i2c设备
* @param - reg: 要写的寄存器
* @param - data: 要写入的值
* @return : 无
*/
static void bmi088i2c_write_reg(struct bmi088i2c_dev *dev, CHANELL_TYPE sensor_type, u8 reg, u8 data)
{
u8 buf = 0;
buf = data;
if(sensor_type == CHANELL_GYRO)
bmi088i2c_write_regs(dev, BMI08_GYRO_I2C_ADDR_PRIMARY, reg, &buf, 1);
else if(sensor_type == CHANELL_ACC)
bmi088i2c_write_regs(dev, BMI08_ACCEL_I2C_ADDR_PRIMARY, reg, &buf, 1);
}
static void bmi088_reset(void) {
u8 ret;
ret = bmi088i2c_read_reg(&bmi088i2cdev,CHANELL_ACC,BMI08_REG_ACCEL_CHIP_ID);
printk("read acc chip id : %x\r\n",ret);
#if 1
mdelay(30);
bmi088i2c_write_reg(&bmi088i2cdev, CHANELL_ACC, BMI08_REG_ACCEL_PWR_CONF, 0x03);
// printk("%s: %d\r\n",__func__,__LINE__);
mdelay(10);
bmi088i2c_write_reg(&bmi088i2cdev, CHANELL_ACC, BMI08_REG_ACCEL_PWR_CTRL, 0x00);
// printk("%s: %d\r\n",__func__,__LINE__);
mdelay(30);
bmi088i2c_write_reg(&bmi088i2cdev, CHANELL_ACC, BMI08_REG_ACCEL_SOFTRESET, 0xB6);
// printk("%s: %d\r\n",__func__,__LINE__);
mdelay(100);
bmi088i2c_write_reg(&bmi088i2cdev, CHANELL_ACC, BMI08_REG_ACCEL_PWR_CONF, 0x00);
// printk("%s: %d\r\n",__func__,__LINE__);
mdelay(10);
bmi088i2c_write_reg(&bmi088i2cdev, CHANELL_ACC, BMI08_REG_ACCEL_PWR_CTRL, 0x04);
// printk("%s: %d\r\n",__func__,__LINE__);
mdelay(30);
ret = bmi088i2c_read_reg(&bmi088i2cdev, CHANELL_ACC, BMI08_REG_ACCEL_PWR_CTRL);
printk("acc id(0x04) %x\r\n",ret);
mdelay(20);
bmi088i2c_write_reg(&bmi088i2cdev, CHANELL_ACC, BMI08_REG_ACCEL_CONF, 0x8B);
mdelay(20);
ret = bmi088i2c_read_reg(&bmi088i2cdev, CHANELL_ACC, BMI08_REG_ACCEL_CONF);
printk("acc id(0x8B) %x\r\n",ret);
mdelay(20);
bmi088i2c_write_reg(&bmi088i2cdev, CHANELL_ACC, BMI08_REG_ACCEL_RANGE, 0x03);
mdelay(20);
ret = bmi088i2c_read_reg(&bmi088i2cdev, CHANELL_ACC, BMI08_REG_ACCEL_RANGE);
printk("acc id(0x03) %x\r\n",ret);
mdelay(20);
#endif
printk("-------------------------\r\n");
ret = bmi088i2c_read_reg(&bmi088i2cdev,CHANELL_GYRO,BMI08_REG_GYRO_CHIP_ID);
printk("read gyro chip id : %x\r\n",ret);
#if 1
bmi088i2c_write_reg(&bmi088i2cdev, CHANELL_GYRO, BMI08_REG_GYRO_LPM1, 0x80);
printk("gyro suspend mode\r\n");
mdelay(50);
bmi088i2c_write_reg(&bmi088i2cdev, CHANELL_GYRO, BMI08_REG_GYRO_SOFTRESET, 0xB6);
printk("soft reset\r\n");
mdelay(80);
bmi088i2c_write_reg(&bmi088i2cdev, CHANELL_GYRO, BMI08_REG_GYRO_LPM1, 0x00);
printk("gyro suspend mode\r\n");
mdelay(50);
bmi088i2c_write_reg(&bmi088i2cdev, CHANELL_GYRO, BMI08_REG_GYRO_RANGE, 0x00);
ret = bmi088i2c_read_reg(&bmi088i2cdev, CHANELL_GYRO, BMI08_REG_GYRO_RANGE);
printk("gyro id(0x00) %x\r\n",ret);
mdelay(20);
bmi088i2c_write_reg(&bmi088i2cdev, CHANELL_GYRO, BMI08_REG_GYRO_BANDWIDTH, 0x81);
ret = bmi088i2c_read_reg(&bmi088i2cdev, CHANELL_GYRO, BMI08_REG_GYRO_BANDWIDTH);
printk("gyro id(0x81) %x\r\n",ret);
mdelay(20);
bmi088i2c_write_reg(&bmi088i2cdev, CHANELL_GYRO, BMI08_REG_GYRO_LPM1, 0x00);
ret = bmi088i2c_read_reg(&bmi088i2cdev, CHANELL_GYRO, BMI08_REG_GYRO_LPM1);
printk("gyro id(0x00) %x\r\n",ret);
mdelay(20);
#endif
}
/*
* @description : 读取bmi088i2c的数据,读取原始数据
* @param - dev: bmi088i2c设备
* @return : 无。
*/
void bmi088i2c_readdata(struct bmi088i2c_dev *dev, CHANELL_TYPE sensor_type)
{
unsigned char i =0;
unsigned char buf[6];
unsigned char val = 0x3B;
int ret;
if(sensor_type == CHANELL_GYRO)
{
bmi088i2c_read_regs(dev, BMI08_GYRO_I2C_ADDR_PRIMARY, BMI08_REG_GYRO_X_LSB, buf, 6);
for(i = 0; i < 3; i++)
{
dev->gyro[i] = (buf[(i * 2) + 1] << 8 | buf[i * 2]);
}
}
if(sensor_type == CHANELL_ACC)
{
ret = bmi088i2c_read_regs(dev, BMI08_ACCEL_I2C_ADDR_PRIMARY, BMI08_REG_ACCEL_X_LSB, buf, 6);
// printk("[ %d ]acc value: ",ret);
for(i = 0; i < 3; i++)
{
dev->acceleration[i] = (buf[(i * 2) + 1] << 8 | buf[i * 2]);
// printk("%x ",dev->acceleration[i]);
}
// printk("\r\n");
}
// if(sensor_type == CHANELL_TEMP)
// {
// bmi088i2c_read_regs(dev, BMI08_ACCEL_I2C_ADDR_PRIMARY, BMI08_REG_TEMP_MSB, buf, 2);
//// printk("msb : %x\r\n",buf[0]);
// dev->temp = buf[0] << 3 | (((buf[1] >> 5) & 0x07));
//// bmi088i2c_read_regs(dev, BMI08_ACCEL_I2C_ADDR_PRIMARY, BMI08_REG_TEMP_LSB, buf, 1);
//// printk("lsb : %x\r\n",buf[1]);
//// dev->temp |= ((buf[1] >> 5) & 0x07);
// }
}
/*
* @description : 打开设备
* @param - inode : 传递给驱动的inode
* @param - filp : 设备文件,file结构体有个叫做private_data的成员变量
* 一般在open的时候将private_data指向设备结构体。
* @return : 0 成功;其他 失败
*/
static int bmi088i2c_open(struct i