#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/ioctl.h>
#include <linux/mm.h>
#include <asm/uaccess.h>
#include <linux/blkdev.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/kdev_t.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/major.h>
#include <linux/errno.h>
#include <linux/module.h>
#include <linux/seq_file.h>
#include <linux/kobject.h>
#include <linux/kobj_map.h>
#include <linux/cdev.h>
#include <linux/mutex.h>
#include <linux/backing-dev.h>
#include <linux/tty.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/hrtimer.h>
#include <linux/i2c.h>
#include <linux/input.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/platform_device.h>
#include <linux/async.h>
#include <linux/irq.h>
#include <linux/workqueue.h>
#include <linux/proc_fs.h>
#include <linux/input/mt.h>
#include <linux/of_gpio.h>
#include <linux/gpio.h>
#include <linux/slab.h>
#include <linux/device.h>
#include <linux/MCP23017.h>
static int mcp23017_i2c_write( struct i2c_client* client,uint8_t reg,uint8_t data,int device_addr)
{
unsigned char buffer[2];
int ret;
buffer[0] = reg;
buffer[1] = data;
mcp_iic_addr = device_addr;
struct i2c_msg msgs[] = {
{
.addr = mcp_iic_addr,
.flags = 0,
// .len = writelen,
.len = sizeof(buffer),
.buf = buffer,
},
};
client->addr=mcp_iic_addr;
ret = i2c_transfer(client->adapter, msgs, 1);
if (ret < 0)
{
dev_err(&client->dev, "%s: i2c write error.\n", __func__);
printk("i2c write error\n");
return 0;
}
return 0;
}
static int mcp23017_i2c_read( struct i2c_client* client,unsigned char reg,uint8_t *data)
{
int ret;
struct i2c_msg msgs[] = {
{
.addr = mcp_iic_addr,
.flags = 0,
// .len = 1,
.len = sizeof(reg),
.buf = ®,// 寄存器地址
},
{
.addr = mcp_iic_addr,
// .flags = I2C_M_RD,0x01
.flags = I2C_M_RD,
.len = sizeof(data),
.buf = data,// 寄存器的值
},
};
ret = i2c_transfer(client->adapter, msgs, 2);
if (ret < 0)
{
printk("i2c read error\n");
}
return ret;
}
static struct kobject *mcp23017_kobj;
struct mcp23017_control_attribute {
struct attribute attr;
ssize_t (*show)(struct kobject *kobj, struct kobj_attribute *attr,
char *buf);
ssize_t (*store)(struct kobject *kobj, struct kobj_attribute *attr,
const char *buf, size_t n);
};
static struct mcp23017_control_attribute mcp23017_attribute[] = {
// node_name permision show_func store_func
//__ATTR(hdmiin_test, S_IRUGO | S_IWUSR, hdmiin_test_show, hdmiin_test_store),
__ATTR(leda, 0777, NULL, leda_store),
__ATTR(ledb, 0777, NULL, ledb_store),
__ATTR(leda1, 0777, NULL, leda1_store),
__ATTR(ledb1, 0777, NULL, ledb1_store),
};
int k =0;
static int mcp23017_probe(struct i2c_client *client, struct i2c_device_id *id)
{
int i =0;
k++;
for(i=0; i < 2; i++)
{
sysfs_create_file(mcp23017_kobj, &mcp23017_attribute[(k-1)*2 + i].attr);
}
mcp23017_client = client;
...
}
static const struct i2c_device_id mcp23017_id[] = {
{"mcp23017_A", 0},
{"mcp23017_B", 0},
{}
};
MODULE_DEVICE_TABLE(i2c, mcp23017_id);
static struct i2c_driver mcp23017_drv = {
.driver = {
.name = "mcp23017",
.owner = THIS_MODULE,
},
.probe = mcp23017_probe,
.id_table = mcp23017_id,
};
static int mcp23017_init(void)
{
mcp23017_kobj = kobject_create_and_add("hello_mcp23017", NULL);
i2c_add_driver(&mcp23017_drv);
return 0;
}
static void mcp23017_exit(void)
{
i2c_del_driver(&mcp23017_drv);
k =0;
}
module_init(mcp23017_init);
module_exit(mcp23017_exit);
MODULE_LICENSE("GPL");
设备树
&i2c2 {
status = "okay";
mcp23017_A@24
{
compatible = "mcp23017_A";
reg = <0x24>;
status = "okay";
};
mcp23017_B@25
{
compatible = "mcp23017_B";
reg = <0x25>;
status = "okay";
};
}