I2C Linux
root@embsys-VirtualBox:/boot/grub# tree
/sys/class/i2c*---->IMP:i2c-0 and i2c-1 are two i2c master each suppports
upto- 0x03-0x77 slaves.
/sys/class/i2c-adapter
├── i2c-0 ->
../../devices/pci0000:00/0000:00:07.0/i2c-0--->Master 1---> Can have
multiple Slave ( 0x03-0x77)
└── i2c-1 -> ../../devices/i2c-1--------------------------->Master
2---> Can have multiple Slave ( 0x03-0x77)
/sys/class/i2c-dev
├── i2c-0 ->
../../devices/pci0000:00/0000:00:07.0/i2c-0/i2c-dev/i2c-0
└── i2c-1 -> ../../devices/i2c-1/i2c-dev/i2c-1
I2C User Space Application to
Interact with I2C Client Driver.
#include
1./* Which I2C Adapter/Master to Open*/
fd = open(/dev/i2c-1, O_RDWR)0---->use i2cdetect
-l or /sys/class/i2c-dev/
2./*Check functionality of I2C master*/
if (ioctl(file, I2C_FUNCS, &funcs) < 0) {
/* Some kind of
error handling */
exit(1);
}
if (!(funcs & I2C_FUNC_I2C)) {
/* Plain
read/write not available only use smbus_..*/
exit(1);
}
3./*address of I2CSlave device on this Bus*/
int addr = 0x40;
/* Send I2C slave address to Master for communication*/
ioctl(fd, I2C_SLAVE, addr)
4./* Write to I2C slave Device*/
a) i2c_smbus_write_word_data(fd, reg, 0x6543)
( Preferred Way)
or
b) buf[0] = reg; /Addres location inside I2c Slave
device
buf[1] = 0x43;
buf[2] = 0x65;
write(file, buf, 3) != 3)
5./*Read from i2c slave */
a)int result;
resutl = i2c_smbus_read_word_data(fd, reg)
( result contains data/(preferred way)
or
b)read(file, buf, 1)
( buf[0] contains data);
*
IMPORTANT: because of the use of inline functions, you *have* to use
'-O'
or some variation when you compile your program!
Why to use SMBUS Protocl
The Linux I2C stack was originally
written to support access to hardware monitoring chips on PC motherboards, and
thus used to embed some assumptions
that were more appropriate to SMBus
(and PCs) than to I2C. All adapters understand SMBus level commands, but only
some of them understand plain I2C!
I2C
Client Driver
1. Create i2c_device_id table
static struct i2c_device_id foo_idtable[] = {
{ "foo", my_id_for_foo },
{}
};
MODULE_DEVICE_TABLE(i2c, foo_idtable);
2.Create I2c_drive structure with table passing , and
probe/remove function.
static struct i2c_driver foo_driver = {
.driver = {
.name =
"foo", /* name should match name of module*/
.owner = THIS_MODULE;
},
.id_table =
foo_idtable,
.probe =
foo_probe,
.remove =
foo_remove,
}
3.Init /exit
with i2c_add_driver and i2c_del_driver
static int __init foo_init(void)
{
return i2c_add_driver(&foo_driver);
}
module_init(foo_init);
static void __exit foo_cleanup(void)
{
i2c_del_driver(&foo_driver);
}
module_exit(foo_cleanup);
or Better to use a macro for all these in single Line
module_i2c_driver(foo_driver);
4. Read/write
you can use
a) smbus function
b) plain i2c function
>Plain I2C communication
int i2c_master_send(struct i2c_client *client, const char *buf,
int count);
int i2c_master_recv(struct i2c_client *client, char *buf, int
count);
>SMBUS Functuons
i2c_smbus_read_word/byte/block_data(client, reg);
i2c_smbus_write_word/byte/block_data(client, reg,value);
It is recommened to use smbus functions as all devices supports
this only few supports i2c variant.
5.Probe/REmove
-Initialize Hadware
The probe function is called when an entry in the id_table name
field
matches the device's name. It is passed the entry that was
matched so
the driver knows which one in the table matched.
- you can here setclient data
/* store the value */
void i2c_set_clientdata(struct
i2c_client *client, void *data);
/* retrieve the value */
void *i2c_get_clientdata(const
struct i2c_client *client);
- Also check for cabability
The i2c core provides two functions for
this: i2c_check_functionality() checks whether a particular function is
supported,
and i2c_get_functionality()
returns a mask containing all of adapter’s supported functions.
-Memory Allocation
No comments:
Post a Comment