I2C驱动框架

以用i2c通信的实时时钟为例

框架入口源文件:i2c_m41t11.c

(可根据入口源文件,再按着框架到内核走一遍)

内核版本:linux_2.6.22.6   硬件平台:JZ2440

以下是驱动框架:

以下是驱动代码 i2c_m41t11.c :

#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/jiffies.h>
#include <linux/i2c.h>
#include <linux/mutex.h>
#include <linux/fs.h>

static unsigned short normal_i2c[] = {0x68,I2C_CLIENT_END}; //只有七位   0xd0 >> 1
static unsigned short probe[] = {I2C_CLIENT_END};
static unsigned short ignore[] = {I2C_CLIENT_END};

//定义一个 client 地址数据
static struct i2c_client_address_data addr_data =
{
    .normal_i2c = normal_i2c,
    .probe      = probe,
    .ignore     = ignore,
};

//定义 client
static struct i2c_client *i2c_m41t11_client;

//定义 主设备号
static int major;

//定义一个 i2c 字符驱动
static struct i2c_driver i2c_m41t11_driver;

static ssize_t i2c_m41t11_read(struct file *file, char __user *buf, size_t size, loff_t * offset)
{
  printk(" <========= this is m41t11 RTC chip =========>  \n");
  return 0;
}

static ssize_t i2c_m41t11_write(struct file *file, const char __user *buf, size_t size, loff_t * offset)
{
    printk(" <========== this is m41t11 RTC chip =========> \n");
    return 0;
}

//定义字符操作函数
static struct file_operations i2c_m41t11_fops =
{
   .owner = THIS_MODULE,
   .read  = i2c_m41t11_read,
   .write = i2c_m41t11_write,
};

//定义一个字符设备类
static struct class *i2c_m41t11_class;

//匹配处理函数
static int m41t11_match_fun(struct i2c_adapter* adpater,int addr ,int kind)
{
   printk("match m41t11 RTC chip successfully \n");
   //初始化 client 结构体
   i2c_m41t11_client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
   i2c_m41t11_client->adapter =  adpater;
   i2c_m41t11_client->driver = &i2c_m41t11_driver;
   i2c_m41t11_client->addr   = addr;
   strcpy(i2c_m41t11_client->name, "i2c_m41t11_client");
   i2c_attach_client(i2c_m41t11_client);

   //注册字符设备
    major = register_chrdev(0,"i2c_m41t11", &i2c_m41t11_fops); 

    i2c_m41t11_class = class_create(THIS_MODULE,"i2c_m41t11_class");                     //   /sys/class/i2c_m41t11_class
    class_device_create(i2c_m41t11_class, NULL, MKDEV(major, 0), NULL,"i2c_m41t11_dev"); //   /dev/i2c_m41t11_dev
    return 0;
}

static int i2c_m41t11_attach(struct i2c_adapter *adapter)
{

   printk("trying to match  m41t11 RTC chip \n");

  return   i2c_probe( adapter , &addr_data , m41t11_match_fun );
} 

static int i2c_m41t11_detach(struct i2c_client *client)
{
    printk("delect  m41t11 RTC chip \n");
   //字符设备
    unregister_chrdev(major, "i2c_m41t11");
    class_destroy(i2c_m41t11_class);
    class_device_destroy(i2c_m41t11_class,MKDEV(major, 0));

    //client
    i2c_detach_client(client);
    kfree(i2c_get_clientdata(client));
    return 0;
}

//初始化 i2c_m41t11_driver
static struct i2c_driver i2c_m41t11_driver =
{
    .driver = { .name = "i2c_m41t11", },
    .attach_adapter = i2c_m41t11_attach,
    .detach_client  = i2c_m41t11_detach,
};

static int i2c_m41t11_init(void)
{
    i2c_add_driver(&i2c_m41t11_driver);
    return 0;
}

static void i2c_m41t11_exit(void)
{
   i2c_del_driver(&i2c_m41t11_driver);
}

module_init(i2c_m41t11_init);
module_exit(i2c_m41t11_exit);

MODULE_LICENSE("GPL");

以下是编译驱动的Makefile:

KER_DIR=/work/systems/kernel/linux-2/linux-2.6.22.6
all:
make -C $(KER_DIR) M=`pwd` modules
clean:
make -C $(KER_DIR) M=`pwd` modules clean
rm -fr modules.order

obj-m += i2c_m41t11.o

原文地址:https://www.cnblogs.com/zsy12138/p/10392810.html

时间: 2024-11-09 00:49:04

I2C驱动框架的相关文章

I2C驱动框架(四)

参考:I2C子系统之platform_driver初始化--I2C_adap_s3c_init() 在完成platform_device的添加之后,i2c子系统将进行platform_driver的注册过程.platform_driver的注册通过调用初始化函数i2c_adapter_s3c_init函数来完成. static struct platform_device_id s3c24xx_driver_ids[] = { { .name = "s3c2410-i2c", .dri

I2C驱动框架之probe方式

基于Linux的I2C驱动,采用probe方式.按照如下这个框架可以写出任何支持I2C总线的器件的Linux驱动. I2C器件连接至cpu的特定的i2c的接口,也就是挂载在cpu的i2c适配器上,i2c器件要和cpu进行信息交换必须要通过cpu操作适配器来交互.cpu上有1个或多个适配器,每个适配器上可以挂载256个设备地址不一样的i2c器件,通过i2c驱动就可以让cpu和适配器上的多个不一样的i2c器件通信而不会产生冲突. 驱动包括两个文件,dev.c和drive.c,其中dev.c是构建I2

I2C驱动框架(二)

在linux内核启动的时候最先执行的和I2C子系统相关的函数应该是driver/i2c/i2c-core.c文件中的i2c_init()函数. 1 static int __init i2c_init(void) 2 { 5 retval = bus_register(&i2c_bus_type); 9 i2c_adapter_compat_class = class_compat_register("i2c-adapter"); 15 retval = i2c_add_dri

I2C驱动详解

I2C讲解: 在JZ2440开发板上,I2C是由两条数据线构成的SCL,SDA:SCL作为时钟总线,SDA作为数据总线:两条线上可挂载I2C设备,如:AT24C08 两条线连接ARM9 I2C控制器,通过控制来控制I2C设备的识别设备地址.读.写操作:如图所示 从中所知:I2C线上可以挂载很多个I2C设备:挂载简单,只需要一根数据线和一根时钟线就可以挂载上去,通过地址来去别每个设备的区别: I2C操作: 对I2C操作主要思想为:1.找到设备  2.进行读写操作 主要原理为: 1.发送开始信号S

spi驱动框架全面分析,从master驱动到设备驱动

内核版本:linux2.6.32.2 硬件资源:s3c2440 参考:  韦东山SPI视频教程 内容概括: 1.I2C 驱动框架回顾 2.SPI 框架简单介绍 3.master 驱动框架 3.1 驱动侧 3.2 设备侧 4.SPI 设备驱动框架 4.1 设备册 4.2 驱动侧 5.设备驱动程序实例 1.I2C 驱动框架回顾 在前面学习 I2C 驱动程序的时候我们知道,I2C 驱动框架分为两层,一层是控制器驱动程序 i2c_adapter,它一般是由芯片厂商写好的,主要提供一个 algorithm

TQ2440学习笔记——Linux上I2C驱动的两种实现方法(1)

作者:彭东林 邮箱:[email protected] 内核版本:Linux-3.14 u-boot版本:U-Boot 2015.04 硬件:TQ2440 (NorFlash:2M   NandFlash:256M  内存:64M) 摘要 这里并不深入分析Linux下I2C驱动的实现,只是以TQ2440硬件平台为例分析I2C驱动的两种方法. 第一种方法: 使用S3C2440自带的I2C控制器实现,这个kernel已经支持,我们只需要配置即可. 第二种方法: 使用GPIO模拟,这个在kernel中

3.4.2内核下的I2C驱动

1. 框架1.1 硬件协议简介1.2 驱动框架1.3 bus-drv-dev模型及写程序a. 设备的4种构建方法a.1 定义一个i2c_board_info, 里面有:名字, 设备地址 然后i2c_register_board_info(busnum, ...) (把它们放入__i2c_board_list链表) list_add_tail(&devinfo->list, &__i2c_board_list); 链表何时使用: i2c_register_adapter > i2

驱动: i2c驱动

1. IIC协议: <<um_s3c2440a_rev10.pdf>>  p481 Figure 20-3. IIC-Bus Interface Data Format<<AT24C08_DataSheet.pdf>>  Figure 1-12 Bus Timing and Device operations iic总线里的角色:    主机(Master):初始化发送.产生时钟信号和终止发送的器件     从机(Slave):被主机寻址的器件 I2C的原则

Linux的i2c驱动详解

目录(?)[-] 简介 架构 设备注册 I2C关键数据结构和详细注册流程 关键数据结构 详细注册流程 使用I2C子系统资源函数操作I2C设备 Gpio模拟i2c总线的通用传输算法 总结 理清i2c中的个结构体关系 i2c驱动的编写建议 1 简介 I2C 总线仅仅使用 SCL . SDA 两根信号线就实现了设备之间的数据交互,极大地简化对硬件资源和 PCB 板布线空间的占用.因此, I2C 总线被非常广泛地应用在 EEPROM .实时钟.小型 LCD 等设备与 CPU 的接口中. Linux I2