i2c linux 框架,linux驱动之I2C总线驱动框架分析

Table of Contents

1、I2C模型框图

daa39c2632b1a2aa353f2edeb3284b2b.png

2、设备信息层

2.1、非设备树形式

static struct mma7660_platform_data mma7660_pdata = {

.irq= IRQ_EINT(25),

.poll_interval= 100,

.input_fuzz= 4,

.input_flat= 4,

};

static struct i2c_board_info smdk4x12_i2c_devs3[] __initdata = {

{

I2C_BOARD_INFO("mma7660", 0x4c),

.platform_data = &mma7660_pdata,

},

};

i2c_register_board_info(3, smdk4x12_i2c_devs3,ARRAY_SIZE(smdk4x12_i2c_devs3));

list_add_tail(&devinfo->list, &__i2c_board_list);

2.2、设备树形式

&i2c_3 {

#address-cells = <1>;

#size-cells = <0>;

compatible = "samsung,s3c2440-i2c";

reg = <0x13890000 0x100>;

interrupts = ;

clocks = ;

clock-names = "i2c";

samsung,i2c-sda-delay = <100>;

samsung,i2c-slave-addr = <0x10>;

samsung,i2c-max-bus-freq = <100000>;

pinctrl-0 = ;

pinctrl-names = "default";

status = "okay";

codec: mma7660@1a {

compatible = "mma7660";

reg = <0x4c>;

clocks = ;

clock-names = "MCLK1";

};

};

3、芯片控制器层adapter

3.1、控制器初始化

处理器有n个i2c控制器,那么就需要注册n个adapter

一个i2c控制器(接口)下可能接有多个i2c器件,因此一个adapter可能对应多个clientstatic struct platform_driver s3c24xx_i2c_driver = {

.probe= s3c24xx_i2c_probe,

.remove= s3c24xx_i2c_remove,

.id_table= s3c24xx_driver_ids,

.driver= {

.owner= THIS_MODULE,

.name= "s3c-i2c",

.pm= S3C24XX_DEV_PM_OPS,

.of_match_table = of_match_ptr(s3c24xx_i2c_match),

},

};

static int __init i2c_adap_s3c_init(void)

{

return platform_driver_register(&s3c24xx_i2c_driver);

}

static int s3c24xx_i2c_probe(struct platform_device *pdev)

{

ret = s3c24xx_i2c_init(i2c); //初始化i2c硬件控制器

ret = i2c_add_numbered_adapter(&i2c->adap); //注册adapter,并转化设备信息为client

of_i2c_register_devices(&i2c->adap); //转化设备树节点为client

return ret;

}

3.2、控制器底层传输函数(起始,数据,应答,停止)

static const struct i2c_algorithm s3c24xx_i2c_algorithm = {

.master_xfer= s3c24xx_i2c_xfer,

.functionality= s3c24xx_i2c_func,

};

static int s3c24xx_i2c_xfer(struct i2c_adapter *adap,

struct i2c_msg *msgs, int num)

{

struct s3c24xx_i2c *i2c = (struct s3c24xx_i2c *)adap->algo_data;

ret = s3c24xx_i2c_doxfer(i2c, msgs, num);

return -EREMOTEIO;

}

static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c,

struct i2c_msg *msgs, int num)

{

unsigned long timeout;

int ret;

if (i2c->suspended)

return -EIO;

ret = s3c24xx_i2c_set_master(i2c);

if (ret != 0) {

dev_err(i2c->dev, "cannot get bus (error %d)\n", ret);

ret = -EAGAIN;

goto out;

}

i2c->msg = msgs;

i2c->msg_num = num;

i2c->msg_ptr = 0;

i2c->msg_idx = 0;

i2c->state = STATE_START;

s3c24xx_i2c_enable_irq(i2c);

s3c24xx_i2c_message_start(i2c, msgs); //开始传输

}

4、核心层core.c   i2c_bus

4.1、i2c_bus总线初始化

struct bus_type i2c_bus_type = {

.name= "i2c",

.match= i2c_device_match,

.probe= i2c_device_probe,

.remove= i2c_device_remove,

.shutdown= i2c_device_shutdown,

.pm= &i2c_device_pm_ops,

};

static int __init i2c_init(void)

{

retval = bus_register(&i2c_bus_type);

}

4.2、client(设备)和i2c_driver(设备驱动)匹配过程

4.2.1、创建client(设备)时匹配i2c_driver(驱动)过程

i2c_new_device

device_register

device_add

bus_probe_device

device_attach

bus_for_each_drv

__device_attach

driver_match_device //匹配

drv->bus->match

driver_probe_device //探测

really_probe

dev->bus->probe

4.2.2、注册i2c_driver(驱动)时匹配client(设备)过程

i2c_add_driver

i2c_register_driver

driver_register

bus_add_driver

driver_attach

bus_for_each_dev

__driver_attach

driver_match_device //匹配

drv->bus->match

driver_probe_device //探测

really_probe

dev->bus->probe

4.3、总线探测probe

static int i2c_device_probe(struct device *dev)

{

driver = to_i2c_driver(dev->driver); //获得设备驱动

client->driver = driver;

//调用设备驱动probe函数

status = driver->probe(client, i2c_match_id(driver->id_table, client));

return status;

}

5、设备驱动层

5.1、设备驱动注册

static struct i2c_driver i2c_mma7660_driver = {

.driver= {

.name= MMA7660_NAME,

},

.probe= mma7660_probe,

.remove= __devexit_p(mma7660_remove),

.suspend= mma7660_suspend,

.resume= mma7660_resume,

.id_table= mma7660_ids,

};

static int __init init_mma7660(void)

{

int ret;

ret = i2c_add_driver(&i2c_mma7660_driver); //注册驱动

printk(KERN_INFO "MMA7660 sensor driver registered.\n");

return ret;

}

5.2、设备驱动探测probe,并初始化i2c器件

static int __devinit mma7660_probe(struct i2c_client *client,

const struct i2c_device_id *id)

{

struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); //得到i2c控制器信息

mma7660_initialize(client); //i2c器件初始化

ret = input_register_polled_device(mma7660_idev);//把i2c设备当输入设备访问

return 0;

}

5.3、数据传输

整体调用过程

mma7660_read_xyz

i2c_smbus_read_byte_data

i2c_smbus_xfer

adapter->algo->smbus_xfer

详细调用过程

static void mma7660_dev_poll(struct input_polled_dev *dev)

{

mma7660_report_abs();

}

static void mma7660_report_abs(void)

{

int axis[3];

int i;

for (i = 0; i < 3; i++) {

mma7660_read_xyz(mma7660_client, i, &axis[i]);

}

input_report_abs(mma7660_idev->input, ABS_X, axis[0]);

input_report_abs(mma7660_idev->input, ABS_Y, axis[1]);

input_report_abs(mma7660_idev->input, ABS_Z, axis[2]);

input_sync(mma7660_idev->input);

//printk("3-Axis ... %3d, %3d, %3d\n", axis[0], axis[1], axis[2]);

}

static int mma7660_read_xyz(struct i2c_client *client, int idx, int *xyz)

{

val = i2c_smbus_read_byte_data(client, idx + MMA7660_XOUT);

return 0;

}

s32 i2c_smbus_read_byte_data(const struct i2c_client *client, u8 command)

{

union i2c_smbus_data data;

int status;

status = i2c_smbus_xfer(client->adapter, client->addr, client->flags,

I2C_SMBUS_READ, command,

I2C_SMBUS_BYTE_DATA, &data);

return (status < 0) ? status : data.byte;

}

s32 i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr, unsigned short flags,

char read_write, u8 command, int protocol,

union i2c_smbus_data *data)

{

res = adapter->algo->smbus_xfer(adapter, addr, flags,

read_write, command,

protocol, data);

return res;

}

标签:i2c,struct,probe,driver,client,linux,驱动,I2C,mma7660

来源: https://blog.csdn.net/shenlong1356/article/details/105949261

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值