246 lines
6.9 KiB
C
246 lines
6.9 KiB
C
#include <linux/module.h>
|
||
#include <linux/init.h>
|
||
#include <linux/kernel.h>
|
||
#include <linux/sched.h>
|
||
#include <linux/cdev.h>
|
||
#include <linux/fs.h>
|
||
#include <linux/wait.h>
|
||
#include <linux/errno.h>
|
||
#include <linux/slab.h>
|
||
#include <linux/uaccess.h>
|
||
#include <linux/device.h>
|
||
#include <linux/io.h>
|
||
#include <linux/platform_device.h>
|
||
#include <linux/of.h>
|
||
#include <linux/of_address.h>
|
||
|
||
//宏定义
|
||
#define SMPLRT_DIV 0x19
|
||
#define CONFIG 0x1A
|
||
#define GYRO_CONFIG 0x1B
|
||
#define ACCEL_CONFIG 0x1C
|
||
#define ACCEL_XOUT_H 0x3B
|
||
#define ACCEL_XOUT_L 0x3C
|
||
#define ACCEL_YOUT_H 0x3D
|
||
#define ACCEL_YOUT_L 0x3E
|
||
#define ACCEL_ZOUT_H 0x3F
|
||
#define ACCEL_ZOUT_L 0x40
|
||
#define TEMP_OUT_H 0x41
|
||
#define TEMP_OUT_L 0x42
|
||
#define GYRO_XOUT_H 0x43
|
||
#define GYRO_XOUT_L 0x44
|
||
#define GYRO_YOUT_H 0x45
|
||
#define GYRO_YOUT_L 0x46
|
||
#define GYRO_ZOUT_H 0x47
|
||
#define GYRO_ZOUT_L 0x48
|
||
#define PWR_MGMT_1 0x6B
|
||
#define WHO_AM_I 0x75
|
||
#define SlaveAddress 0xD0
|
||
#define Address 0x68 //MPU6050地址
|
||
#define I2C_RETRIES 0x0701
|
||
#define I2C_TIMEOUT 0x0702
|
||
#define I2C_SLAVE 0x0703 //IIC从器件的地址设置
|
||
#define I2C_BUS_MODE 0x0780
|
||
|
||
|
||
static struct mpu6050_dev{
|
||
struct cdev c_dev;
|
||
dev_t devno;
|
||
struct class *class;
|
||
struct device *device;
|
||
struct i2c_client *client;
|
||
};
|
||
|
||
|
||
static int i2c_write_mpu6050(struct i2c_client *mpu6050_client, u8 address, u8 data)
|
||
{
|
||
int error = 0;
|
||
u8 write_data[2];
|
||
struct i2c_msg send_msg; //要发送的数据结构体
|
||
|
||
/*设置要发送的数据*/
|
||
write_data[0] = address;
|
||
write_data[1] = data;
|
||
|
||
/*发送 iic要写入的地址 reg*/
|
||
send_msg.addr = mpu6050_client->addr; //mpu6050在 iic 总线上的地址
|
||
send_msg.flags = 0; //标记为发送数据
|
||
send_msg.buf = write_data; //写入的首地址
|
||
send_msg.len = 2; //reg长度
|
||
|
||
/*执行发送*/
|
||
error = i2c_transfer(mpu6050_client->adapter, &send_msg, 1);
|
||
if (error != 1)
|
||
{
|
||
pr_err("\n i2c_transfer error \n");
|
||
return -1;
|
||
}
|
||
return 0;
|
||
}
|
||
static int i2c_read_mpu6050(struct i2c_client *mpu6050_client, u8 address, void *data, u32 length)
|
||
{
|
||
return 0;
|
||
}
|
||
static int mpu6050_init(struct i2c_client *mpu6050_client)
|
||
{
|
||
int error = 0;
|
||
/*配置mpu6050*/
|
||
error += i2c_write_mpu6050(mpu6050_client, PWR_MGMT_1, 0X00);
|
||
error += i2c_write_mpu6050(mpu6050_client, SMPLRT_DIV, 0X07);
|
||
error += i2c_write_mpu6050(mpu6050_client, CONFIG, 0X06);
|
||
error += i2c_write_mpu6050(mpu6050_client, ACCEL_CONFIG, 0X01);
|
||
|
||
if (error < 0)
|
||
{
|
||
/*初始化错误*/
|
||
pr_err("\n mpu6050_init error \n");
|
||
return -1;
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
/*字符设备操作函数集,open函数实现*/
|
||
static int mpu6050_open(struct inode *inode, struct file *filp)
|
||
{
|
||
struct mpu6050_dev *mpu = NULL;
|
||
mpu = container_of(inode->i_cdev, struct mpu6050_dev, c_dev);
|
||
|
||
filp->private_data = mpu;
|
||
|
||
return mpu6050_init(mpu);
|
||
|
||
|
||
}
|
||
/*字符设备操作函数集,.read函数实现*/
|
||
static ssize_t mpu6050_read(struct file *filp, char __user *buf, size_t cnt, loff_t *off)
|
||
{
|
||
return 0;
|
||
}
|
||
/*字符设备操作函数集,.release函数实现*/
|
||
static int mpu6050_release(struct inode *inode, struct file *filp)
|
||
{
|
||
return 0;
|
||
}
|
||
/*字符设备操作函数集*/
|
||
static struct file_operations mpu6050_chr_dev_fops =
|
||
{
|
||
.owner = THIS_MODULE,
|
||
.open = mpu6050_open,
|
||
.read = mpu6050_read,
|
||
.release = mpu6050_release,
|
||
};
|
||
|
||
static struct mpu6050_dev mpu6050dev;
|
||
|
||
|
||
/*i2c总线设备函数集*/
|
||
static int mpu6050_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
||
{
|
||
int ret = 0;
|
||
ret = alloc_chrdev_region(&(mpu6050dev.devno),0,1,"mpu6050");
|
||
if(ret < 0){
|
||
pr_err("chrdev alloc region failed\n");
|
||
return ret;
|
||
}
|
||
|
||
pr_info("devno is %u(major:%u,minor:%u)\n",mpu6050dev.devno,MAJOR(mpu6050dev.devno), MINOR(mpu6050dev.devno));
|
||
|
||
cdev_init(&mpu6050dev.c_dev, &mpu6050_chr_dev_fops);
|
||
mpu6050dev.c_dev.owner = THIS_MODULE;
|
||
ret = cdev_add(&mpu6050dev.c_dev, mpu6050dev.devno, 1);
|
||
if(ret < 0){
|
||
pr_err("chrdev add failed\n");
|
||
goto cdev_add_err;
|
||
}
|
||
|
||
ret = class_create(THIS_MODULE, "mpu_class");
|
||
if(IS_ERR(ret))
|
||
{
|
||
pr_err("create class faild!/n");
|
||
goto class_create_err;
|
||
}
|
||
mpu6050dev.class = ret;
|
||
|
||
ret = device_create(mpu6050dev.class,NULL,devno,NULL,"mpu6050");
|
||
if(IS_ERR(ret))
|
||
{
|
||
pr_err("device_create failed\n");
|
||
goto device_create_err;
|
||
}
|
||
mpu6050dev.device = ret;
|
||
|
||
mpu6050dev.client = client;
|
||
|
||
return 0;
|
||
|
||
device_create_err:
|
||
class_destroy(mpu6050dev.class);
|
||
class_create_err:
|
||
cdev_del(&mpu6050dev.c_dev);
|
||
cdev_add_err:
|
||
unregister_chrdev_region(mpu6050dev.devno, 1);
|
||
return ret;
|
||
|
||
}
|
||
static int mpu6050_remove(struct i2c_client *client)
|
||
{
|
||
|
||
device_destroy(mpu6050dev.class, mpu6050dev.device);
|
||
class_destroy(mpu6050dev.class);
|
||
cdev_del(&mpu6050dev.c_dev);
|
||
unregister_chrdev_region(mpu6050dev.devno, 1);
|
||
|
||
return 0;
|
||
}
|
||
|
||
/*定义ID 匹配表*/
|
||
static const struct i2c_device_id gtp_device_id[] = {
|
||
{"fire,i2c_mpu6050", 0},
|
||
{}};
|
||
|
||
/*定义设备树匹配表*/
|
||
static const struct of_device_id mpu6050_of_match_table[] = {
|
||
{.compatible = "fire,i2c_mpu6050"},
|
||
{/* sentinel */}};
|
||
|
||
|
||
/*定义i2c总线设备结构体*/
|
||
struct i2c_driver mpu6050_driver = {
|
||
.probe = mpu6050_probe,
|
||
.remove = mpu6050_remove,
|
||
.id_table = gtp_device_id,
|
||
.driver = {
|
||
.name = "fire,i2c_mpu6050",
|
||
.owner = THIS_MODULE,
|
||
.of_match_table = mpu6050_of_match_table,
|
||
},
|
||
};
|
||
|
||
/*
|
||
* 驱动初始化函数
|
||
*/
|
||
static int __init mpu6050_driver_init(void)
|
||
{
|
||
int ret;
|
||
pr_info("mpu6050_driver_init\n");
|
||
ret = i2c_add_driver(&mpu6050_driver);
|
||
return 0;
|
||
}
|
||
|
||
/*
|
||
* 驱动注销函数
|
||
*/
|
||
static void __exit mpu6050_driver_exit(void)
|
||
{
|
||
pr_info("mpu6050_driver_exit\n");
|
||
i2c_del_driver(&mpu6050_driver);
|
||
}
|
||
|
||
module_init(mpu6050_driver_init);
|
||
module_exit(mpu6050_driver_exit);
|
||
|
||
MODULE_LICENSE("GPL");
|
||
|
||
|
||
|