6、i2c设备驱动

I2C设备驱动要使用i2c_driver和i2c_client数据结构并填充i2c_driver中的成员函数。 i2c_client一般被包

含在设备的私有信息结构体yyy_data中, 而i2c_driver则适合被定义为全局变量并初始化

static struct i2c_driver pca954x_driver = {

.driver                = {

.name        = "pca954x",

.pm        = &pca954x_pm,

.of_match_table = pca954x_of_match,

},

.probe                = pca954x_probe,

.remove                = pca954x_remove,

.id_table        = pca954x_id,

};

static const struct of_device_id pca954x_of_match[] = {

{ .compatible = "nxp,pca9540", .data = &chips[pca_9540] },

{ .compatible = "nxp,pca9542", .data = &chips[pca_9542] },

{ .compatible = "nxp,pca9543", .data = &chips[pca_9543] },

{ .compatible = "nxp,pca9544", .data = &chips[pca_9544] },

{ .compatible = "nxp,pca9545", .data = &chips[pca_9545] },

{ .compatible = "nxp,pca9546", .data = &chips[pca_9546] },

{ .compatible = "nxp,pca9547", .data = &chips[pca_9547] },

{ .compatible = "nxp,pca9548", .data = &chips[pca_9548] },

{ .compatible = "nxp,pca9846", .data = &chips[pca_9846] },

{ .compatible = "nxp,pca9847", .data = &chips[pca_9847] },

{ .compatible = "nxp,pca9848", .data = &chips[pca_9848] },

{ .compatible = "nxp,pca9849", .data = &chips[pca_9849] },

{}

};

static const struct i2c_device_id pca954x_id[] = {

{ "pca9540", pca_9540 },

{ "pca9542", pca_9542 },

{ "pca9543", pca_9543 },

{ "pca9544", pca_9544 },

{ "pca9545", pca_9545 },

{ "pca9546", pca_9546 },

{ "pca9547", pca_9547 },

{ "pca9548", pca_9548 },

{ "pca9846", pca_9846 },

{ "pca9847", pca_9847 },

{ "pca9848", pca_9848 },

{ "pca9849", pca_9849 },

{ }

};

I2C设备驱动的模块加载函数通过I2C核心的i2c_add_driver() API函数添加i2c_driver的工作

#define i2c_add_driver(driver) \

i2c_register_driver(THIS_MODULE, driver)


int i2c_register_driver(struct module *owner, struct i2c_driver *driver)

{

int res;

/* Can't register until after driver model init */

if (WARN_ON(!is_registered))

return -EAGAIN;

/* add the driver to the list of i2c drivers in the driver core */

driver->driver.owner = owner;

driver->driver.bus = &i2c_bus_type;

INIT_LIST_HEAD(&driver->clients);

/* When registration returns, the driver core

 * will have called probe() for all matching-but-unbound devices.

 */

res = driver_register(&driver->driver);

if (res)

return res;

pr_debug("driver [%s] registered\n", driver->driver.name);

/* Walk the adapters that are already present */

i2c_for_each_dev(driver, __process_new_driver);

return 0;

}

模块卸载函数需要做相反的工作: 通过I2C核心的i2c_del_driver() 函数删除i2c_driver。

void i2c_del_driver(struct i2c_driver *driver)

{

i2c_for_each_dev(driver, __process_removed_driver);

driver_unregister(&driver->driver);

pr_debug("driver [%s] unregistered\n", driver->driver.name);

}

I2C设备驱动的数据传输

在I2C设备上读写数据的时序且数据通常通过i2c_msg数组进行组织, 最后通过i2c_transfer() 函数完成

i2c-core-acpi.c

read

static int acpi_gsb_i2c_read_bytes(struct i2c_client *client,

u8 cmd, u8 *data, u8 data_len)

{

struct i2c_msg msgs[2];

int ret;

u8 *buffer;

buffer = kzalloc(data_len, GFP_KERNEL);

if (!buffer)

return AE_NO_MEMORY;

msgs[0].addr = client->addr;

msgs[0].flags = client->flags;

msgs[0].len = 1;

msgs[0].buf = &cmd;

msgs[1].addr = client->addr;

msgs[1].flags = client->flags | I2C_M_RD;

msgs[1].len = data_len;

msgs[1].buf = buffer;

ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));

if (ret < 0) {

/* Getting a NACK is unfortunately normal with some DSTDs */

if (ret == -EREMOTEIO)

dev_dbg(&client->adapter->dev, "i2c read %d bytes from client@%#x starting at reg %#x failed, error: %d\n",

data_len, client->addr, cmd, ret);

else

dev_err(&client->adapter->dev, "i2c read %d bytes from client@%#x starting at reg %#x failed, error: %d\n",

data_len, client->addr, cmd, ret);

/* 2 transfers must have completed successfully */

} else if (ret == 2) {

memcpy(data, buffer, data_len);

ret = 0;

} else {

ret = -EIO;

}

kfree(buffer);

return ret;

}

write

static int acpi_gsb_i2c_write_bytes(struct i2c_client *client,

u8 cmd, u8 *data, u8 data_len)

{

struct i2c_msg msgs[1];

u8 *buffer;

int ret = AE_OK;

buffer = kzalloc(data_len + 1, GFP_KERNEL);

if (!buffer)

return AE_NO_MEMORY;

buffer[0] = cmd;

memcpy(buffer + 1, data, data_len);

msgs[0].addr = client->addr;

msgs[0].flags = client->flags;

msgs[0].len = data_len + 1;

msgs[0].buf = buffer;

ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));

kfree(buffer);

if (ret < 0) {

dev_err(&client->adapter->dev, "i2c write failed: %d\n", ret);

return ret;

}

/* 1 transfer must have completed successfully */

return (ret == 1) ? 0 : -EIO;

}

transfer

int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)

{

int ret;

if (!adap->algo->master_xfer) {

dev_dbg(&adap->dev, "I2C level transfers not supported\n");

return -EOPNOTSUPP;

}

/* REVISIT the fault reporting model here is weak:

 *

 *  - When we get an error after receiving N bytes from a slave,

 *    there is no way to report "N".

 *

 *  - When we get a NAK after transmitting N bytes to a slave,

 *    there is no way to report "N" ... or to let the master

 *    continue executing the rest of this combined message, if

 *    that's the appropriate response.

 *

 *  - When for example "num" is two and we successfully complete

 *    the first message but get an error part way through the

 *    second, it's unclear whether that should be reported as

 *    one (discarding status on the second message) or errno

 *    (discarding status on the first one).

 */

ret = __i2c_lock_bus_helper(adap);

if (ret)

return ret;

ret = __i2c_transfer(adap, msgs, num);

i2c_unlock_bus(adap, I2C_LOCK_SEGMENT);

return ret;

}

int __i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)

{

unsigned long orig_jiffies;

int ret, try;

if (WARN_ON(!msgs || num < 1))

return -EINVAL;

ret = __i2c_check_suspended(adap);

if (ret)

return ret;

if (adap->quirks && i2c_check_for_quirks(adap, msgs, num))

return -EOPNOTSUPP;

/*

 * i2c_trace_msg_key gets enabled when tracepoint i2c_transfer gets

 * enabled.  This is an efficient way of keeping the for-loop from

 * being executed when not needed.

 */

if (static_branch_unlikely(&i2c_trace_msg_key)) {

int i;

for (i = 0; i < num; i++)

if (msgs[i].flags & I2C_M_RD)

trace_i2c_read(adap, &msgs[i], i);

else

trace_i2c_write(adap, &msgs[i], i);

}

/* Retry automatically on arbitration loss */

orig_jiffies = jiffies;

for (ret = 0, try = 0; try <= adap->retries; try++) {

if (i2c_in_atomic_xfer_mode() && adap->algo->master_xfer_atomic)

ret = adap->algo->master_xfer_atomic(adap, msgs, num);

else

ret = adap->algo->master_xfer(adap, msgs, num);

if (ret != -EAGAIN)

break;

if (time_after(jiffies, orig_jiffies + adap->timeout))

break;

}

if (static_branch_unlikely(&i2c_trace_msg_key)) {

int i;

for (i = 0; i < ret; i++)

if (msgs[i].flags & I2C_M_RD)

trace_i2c_reply(adap, &msgs[i], i);

trace_i2c_result(adap, num, ret);

}

return ret;

}

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值