linux 3.18 -- iic,input,misc,三轴加速度设备驱动(二)

I2C设备驱动之设备树和i2c_driver接口
一 原理图
三轴加速度传感器原理图:
这里写图片描述
图中:
I2C_SCL_GSENSOR对应imx6的 UART1_TX_DATA
I2C_SDA_GSENSOR对应imx6的UART1_RX_DATA
G_INT2对应imx6的SNVS_TAMPER5

二 设备树配置
将 UART1_TX_DATA,UART1_RX_DATA配置为I2C3模式,将SNVS_TAMPER5配置为GPIO模式。

&i2c3 {
    clock_frequency = <100000>;
    pinctrl-names = "default";
    pinctrl-0 = <&pinctrl_i2c3>;
    status = "okay";
    gsensor: bma250@18 {
        compatible = "bosch,bma250";
        //从设备地址
        reg = <0x18>;
        position = <0>;
        //表示处于哪一组中断,第5组
        interrupt-parent = <&gpio5>;   
        //表示处于GPIO5的第5个io,高电平触发
        interrupts = <5 IRQ_TYPE_LEVEL_HIGH>;
    };
};

pinctrl_i2c3: i2c3grp {
        fsl,pins = <
            MX6UL_PAD_UART1_TX_DATA__I2C3_SCL 0x4001b8b0
            MX6UL_PAD_UART1_RX_DATA__I2C3_SDA 0x4001b8b0
            MX6UL_PAD_SNVS_TAMPER5__GPIO5_IO05  0x80000000  // gsenser int1 
        >;
    };

三 i2c_driver接口

/*
 *  bma250-i2c.c - Linux kernel modules for 3-Axis Smart Orientation
 *
 */
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/err.h>
#include <linux/i2c.h>
#include "bma250.h"

/***注:i2c_client一般被包含在设备的私有信息结构体yyy_data中,在本例中,被包含在bma250_data结构中。
***     而i2c_driver则适合被定义为全局变量并初始化
***/


static s32 bma250_i2c_write(struct bma250_data *pdata, u8 reg, u8 val)
{
    struct i2c_client *client = (struct i2c_client *)pdata->bus_priv;

    //向I2C设备发送一个写控制字+控制指令(寄存器地址),紧接着发送指令内容(寄存器内容,单字节)。
    return i2c_smbus_write_byte_data(client, reg, val);  
}

static int bma250_i2c_read(struct bma250_data *pdata, u8 reg)
{
    struct i2c_client *client = (struct i2c_client *)pdata->bus_priv;

    //向I2C设备发送一个写控制字+控制指令(寄存器地址),再发送一个读控制字,
    //此时I2C从设备内部的读写指针转移到指定的位置,并返回一个字节,最后返回一个无应答NA。
    return i2c_smbus_read_byte_data(client, reg);
}

static int bma250_i2c_read_block(struct bma250_data *pdata, u8 reg, u8 len, u8 *val)
{
    struct i2c_client *client = (struct i2c_client *)pdata->bus_priv;

    //向I2C设备发送一个写控制字+控制指令(寄存器地址),再发送一个读控制字,
    //此时I2C从设备内部的读写指针转移到指定的位置,并连续返回多个字节,
    //I2C主机读取到一定数量字节内容之后发送无应答NA。

    //通过I2C总线从reg寄存器开始连续读len个数据到val中。
    return i2c_smbus_read_i2c_block_data(client, reg, len, val);
}



static int bma250_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
    int ret;
    //client数据结构由系统根据设备树信息自动填充
    bma250_dev.bus_priv = client;

    bma250_dev.bus_type = BUS_I2C;
    bma250_dev.irq = client->irq; 
    bma250_dev.read = bma250_i2c_read;
    bma250_dev.write = bma250_i2c_write;
    bma250_dev.read_block = bma250_i2c_read_block;

    //将设备驱动的私有数据(bma250_dev)赋值给设备驱动client的私有指针中,方便通过client取得设备私有数据
    //对于与 i2c_get_clientdata(client);  从i2c_client获取设备私有数据
    i2c_set_clientdata(client, &bma250_dev);

    //初始化bma250,注册misc和input设备驱动(具体代码在下节)
    ret = bma250_driver_init(&bma250_dev);

    return ret;
}

//注销设备驱动
static int bma250_i2c_remove(struct i2c_client *client)
{   
    return bma250_driver_remove(&bma250_dev);
}



/*********
**电源管理部分
***********/
#ifdef CONFIG_PM
static int bma250_i2c_suspend(struct device *dev)
{
    //#define to_i2c_client(d) container_of(d, struct i2c_client, dev)  
    //通常使用device设备模型进行操作,可以通过to_i2c_client找到对应client指针

    struct i2c_client *client = to_i2c_client(dev); // 从dev 获取 i2c client 
    return bma250_driver_suspend(i2c_get_clientdata(client));
}

static int bma250_i2c_resume(struct device *dev)
{
    struct i2c_client *client = to_i2c_client(dev);
    return bma250_driver_resume(i2c_get_clientdata(client));
}
#else 
#define bma250_i2c_suspend  NULL
#define bma250_i2c_resume   NULL
#endif 

static SIMPLE_DEV_PM_OPS(bma250_pm_ops, bma250_i2c_suspend, bma250_i2c_resume); 



/*********
**设备与驱动匹配部分
***********/
//方法一:设备与驱动匹配
static const struct i2c_device_id bma250_i2c_id[] = {
    {"bma250", 0},
    {   }
};
//MODULE_DEVICE_TABLE(platform, xx_driver_ids);
//将xx_driver_ids结构输出到用户空间,这样模块加载系统在加载模块时,就知道了什么模块对应什么硬件设备。
MODULE_DEVICE_TABLE(i2c, bma250_i2c_id);

//方法二:设备与驱动匹配
/*
static const struct of_device_id bma250_i2c_of_match[] = {
    {.compatible = "bosch,bma250",},
    {}
};
MODULE_DEVICE_TABLE(of, bma250_i2c_of_match);
*/




/*********
**驱动注册部分
***********/
/*适合被定义为全局变量并初始化*/
static struct i2c_driver bma250_i2c_driver = {
    .driver = {
           .name = "bma250",
           .owner = THIS_MODULE,
           //用于电源管理
           .pm = &bma250_pm_ops,

           //of_match_table = bma250_i2c_of_match,
           },

    .probe = bma250_i2c_probe,
    .remove = bma250_i2c_remove,

    .id_table = bma250_i2c_id,
};

module_i2c_driver(bma250_i2c_driver);




MODULE_AUTHOR("chao zhang");
MODULE_DESCRIPTION("BMA250 3-Axis Acc Sensor driver");
MODULE_LICENSE("GPL");
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值