开发板:讯为电子itop4412开发板,实测可行。
示例代码:
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/input.h>
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/gpio.h>
#include <linux/platform_device.h>
#ifdef CONFIG_HAS_EARLYSUSPEND
#include <linux/earlysuspend.h>
#endif
#include <linux/regulator/consumer.h>
#include <mach/gpio.h>
#include <plat/gpio-cfg.h>
#include <asm/uaccess.h>
#include <linux/miscdevice.h>
#include <linux/i2c.h>
#include <linux/hwmon.h>
#include <linux/err.h>
#include <linux/mutex.h>
static struct i2c_client *pocky_client;
ssize_t pocky_read(struct file *file, char __user *buffer, size_t num, loff_t *loff_t)
{
int ret;
struct i2c_msg msg[2];
char buf[2];
ret = copy_from_user(&buf,buffer,num);
msg[0].addr = pocky_client->addr;
msg[0].buf = buf;
msg[0].flags = 0;
msg[0].len = 1;
msg[1].addr = pocky_client->addr;
msg[1].buf = buf;
msg[1].flags = I2C_M_RD;
msg[1].len = 1;
ret = i2c_transfer(pocky_client->adapter, msg, 2);
if(ret < 0)
{
printk("read error!\n");
}
ret = copy_to_user(buffer,buf,num);
return ret;
}
ssize_t pocky_write(struct file *file, const char __user *buffer, size_t num, loff_t *loff_t)
{
int ret;
struct i2c_msg msg[1];
char buf[2];
ret = copy_from_user(&buf,buffer,num);
msg[0].addr = pocky_client->addr;
msg[0].buf = buf;
msg[0].flags = 0;
msg[0].len = num;
ret = i2c_transfer(pocky_client->adapter,msg,1);
if(ret < 0)
{
printk("write reg 0x%02x error!\n",buf[0]);
}
ret = copy_to_user(buffer,buf,num);
return ret;
}
int pocky_open(struct inode *inode, struct file *file)
{
printk("pocky_open open \n");
return 0;
}
int pocky_release (struct inode *inode, struct file *file)
{
printk("pocky_release release \n");
return 0;
}
static struct file_operations pocky_fop = {
.owner = THIS_MODULE,
.open = pocky_open,
.release = pocky_release,
.write = pocky_write,
.read = pocky_read,
};
static struct miscdevice i2c_dev = {
.minor = MISC_DYNAMIC_MINOR,
.name = "my_i2c_test",
.fops = &pocky_fop,
};
int pocky_i2c_probe(struct i2c_client *client, const struct i2c_device_id * id)
{
printk("%S %s %d \n",__FILE__,__FUNCTION__,__LINE__);
pocky_client = client;
misc_register(&i2c_dev);
return 0;
}
int pocky_i2c_remove(struct i2c_client *client)
{
printk("%S %s %d \n",__FILE__,__FUNCTION__,__LINE__);
misc_deregister(&i2c_dev);
return 0;
}
int pocky_i2c_detect(struct i2c_client *client, struct i2c_board_info *info)
{
/* 应该去访问硬件,确定设备确实存在 */
printk("at24cxx_detect : addr = 0x%x\n",client->addr);
if(client->addr == 0x38)
{
strlcpy(info->type,"i2c_pocky",I2C_NAME_SIZE);
return 0;
}
else
return -ENODEV;
}
static const unsigned short addr_list[] = {0x38,0x50,I2C_CLIENT_END};
static const struct i2c_device_id pocky_i2c_id[] = {
{ "i2c_pocky", 0 },
{ }
};
struct i2c_driver pocky_i2c_driver = {
.class = I2C_CLASS_HWMON, /* 表示去那些适配器上找设备*/
.driver = {
.name = "pocky",
.owner = THIS_MODULE,
},
.probe = pocky_i2c_probe,
.remove = pocky_i2c_remove,
.id_table = pocky_i2c_id,
.detect = pocky_i2c_detect,
.address_list = addr_list,
};
static void i2c_io_init(void)
{
int ret;
ret = gpio_request(EXYNOS4_GPL0(2), "TP1_EN");
if (ret) {
printk(KERN_ERR "failed to request TP1_EN for "
"I2C control\n");
//return err;
}
gpio_direction_output(EXYNOS4_GPL0(2), 1);
s3c_gpio_cfgpin(EXYNOS4_GPL0(2), S3C_GPIO_OUTPUT);
gpio_free(EXYNOS4_GPL0(2));
mdelay(5);
ret = gpio_request(EXYNOS4_GPX0(3), "GPX0_3");
if (ret) {
gpio_free(EXYNOS4_GPX0(3));
ret = gpio_request(EXYNOS4_GPX0(3), "GPX0_3");
if(ret)
{
printk("ft5xox: Failed to request GPX0_3 \n");
}
}
gpio_direction_output(EXYNOS4_GPX0(3), 0);
mdelay(200);
gpio_direction_output(EXYNOS4_GPX0(3), 1);
s3c_gpio_cfgpin(EXYNOS4_GPX0(3), S3C_GPIO_OUTPUT);
gpio_free(EXYNOS4_GPX0(3));
msleep(300);
}
static int pocky_init(void)
{
i2c_io_init();
i2c_add_driver(&pocky_i2c_driver);
return 0;
}
static void pocky_exit(void)
{
i2c_del_driver(&pocky_i2c_driver);
}
module_init(pocky_init);
module_exit(pocky_exit);
MODULE_LICENSE("GPL");
app:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
int main(int argc,char **argv)
{
int fd,ret;
int data_input;
char *i2c_device = "/dev/my_i2c_test";
unsigned char buffer[2];
data_input = atoi(argv[1]);
printf("open %s!\n",i2c_device);
if((fd = open(i2c_device,O_RDWR|O_NDELAY))<0)
printf("APP open %s failed",i2c_device);
else{
printf("APP open %s success!\n",i2c_device);
}
//读一个数据0xa6
buffer[0] = 0xa6;
ret = read(fd,buffer,1);
if(ret<0)
printf("i2c read failed!\n");
else{
printf("i2c read reg 0xa6 data is 0x%02x!\n",buffer[0]);
}
//01先从0x00读出一个数据,02写一个数据到0x00,03再读出来对比
//01
buffer[0] = 0x00;
read(fd,buffer,1);
printf("i2c read reg 0x00 data is 0x%02x!\n",buffer[0]);
//02
buffer[0] = 0x00;
buffer[1] = data_input;
ret = write(fd,buffer,2);
if(ret<0){
printf("i2c write failed!\n");
goto exit;
}
//03
buffer[0] = 0x00;
read(fd,buffer,1);
printf("i2c read reg 0x00 data is 0x%02x!\n",buffer[0]);
close(fd);
exit:
close(fd);
return -1;
}