当前位置:网站首页>Analysis of I2C adapter driver of s5pv210 chip (i2c-s3c2410. C)
Analysis of I2C adapter driver of s5pv210 chip (i2c-s3c2410. C)
2022-07-04 17:43:00 【Snail taking off】
1、 What is an adapter driver
(1) Adapter driver is used to control Soc Upper I2C Controller , encapsulation I2C Communication mode of controller ;
(2) The adapter driver will send I2C Core layer registration ,I2C The core layer will manage all the registered adapter drivers in the kernel , Every registered adapter driver represents Soc One of them I2C controller ;
(3)I2C The driver of the interface device will pass I2C The bus matches the corresponding adapter , Then call the data transceiver interface provided by the adapter to communicate ;
2、 How does the adapter driver work with Soc Upper I2C The controller corresponds to
/*********gslX680.c**************/
#define GSLX680_I2C_NAME "gslX680"
static struct i2c_driver gsl_ts_driver = {
.driver = {
.name = GSLX680_I2C_NAME,
.owner = THIS_MODULE,
},
#ifndef CONFIG_HAS_EARLYSUSPEND
.suspend = gsl_ts_suspend,
.resume = gsl_ts_resume,
#endif
.probe = gsl_ts_probe,
.remove = __devexit_p(gsl_ts_remove),
.id_table = gsl_ts_id,
};
// Function call relationship
gsl_ts_init() // Driver loading function
i2c_add_driver(&gsl_ts_driver); // towards I2C Bus registration gslX680 drive
gsl_ts_probe() // When gslX680 Drive in I2C Match on the bus struct i2c_client Is called probe Method
/********* Kernel registration i2c_board_info Information ************/
static struct i2c_board_info i2c_devs1[] __initdata = {
{
I2C_BOARD_INFO("gslX680", 0x40), //gslX680 Is the name used to match the driver ,0x40 The device is I2C Address on the bus
},
};
smdkc110_machine_init() //struct machine_desc->init_machine()
i2c_register_board_info(1, i2c_devs1, ARRAY_SIZE(i2c_devs1)); // The direction number is 1 Adapter registration for i2c_board_info Information
(1) It's on it gslX680 Touch screen driver code and in I2C The code matching the relevant part on the bus ;
(2)struct i2c_board_info Structure : Will be used to form struct i2c_client Structure , future I2C The driver of the interface device is I2C When matching devices on the bus , Will match by name ,
Which adapter has the name of the driver will match with which adapter successfully , And will also put struct i2c_board_info The information in the structure is transmitted to I2C drive , such as : Device address 、 Interrupt number ;
(3) Each adapter will register struct i2c_board_info Structure information , future struct i2c_board_info The name in the structure will match I2C Match the name of the driver , I2C The driver and adapter are matched ,
future I2C The driver communicates through the adapter on the matching , That is, hardware I2C Which interface device is connected I2C controller ;
3、 Adapter driven loading process
static struct platform_device_id s3c24xx_driver_ids[] = {
{
.name = "s3c2410-i2c",
.driver_data = TYPE_S3C2410,
}, {
.name = "s3c2440-i2c",
.driver_data = TYPE_S3C2440,
}, {
},
};
static struct platform_driver s3c24xx_i2c_driver = {
.probe = s3c24xx_i2c_probe,
.remove = s3c24xx_i2c_remove,
.id_table = s3c24xx_driver_ids, // stay platform Use when matching devices on the bus
.driver = {
.owner = THIS_MODULE,
.name = "s3c-i2c",
.pm = S3C24XX_DEV_PM_OPS,
},
};
i2c_adap_s3c_init() // Driver loading function
platform_driver_register(&s3c24xx_i2c_driver); // Use the platform bus to register
s3c24xx_i2c_probe() // Call after matching the device on the platform bus probe function
i2c_add_numbered_adapter(&i2c->adap); // utilize platform_device The transferred data builds the adapter structure , And to I2C Core layer registration
(1) In the kernel struct machine_desc->init_machine() Function will register plat_device, There will be multiple plat_device and platform Bus driver s3c24xx_i2c_driver On the match ,
Is basically Soc There are several I2C The controller is matched several times , That is to say, I would like to I2C The core layer registers multiple adapters ;
(2) Although it has been matched many times , But every time plat_device The data transmitted are all different , Include I2C Register physical address of the controller 、 Interrupt number 、 Adapter number, etc ;
4、I2C Bus driven description structure
struct s3c24xx_i2c {
spinlock_t lock;
wait_queue_head_t wait; // In order to synchronize , send i2c->algorithm->master_xfer Function can return when the transmission process in interruption is completed
unsigned int suspended:1;
// Record the information of the data to be transmitted
struct i2c_msg *msg; // Message queue
unsigned int msg_num; // Number of messages in the message queue
unsigned int msg_idx; // Which message in the sequence is currently transmitted
unsigned int msg_ptr; // The current number of bytes is transmitted
unsigned int tx_setup; // Transmission setup delay
unsigned int irq; // Interrupt number used
enum s3c24xx_i2c_state state; // Current transmission status , Where to go
unsigned long clkrate;
void __iomem *regs; // Used to access the kernel IO Actual address of memory
struct clk *clk;
struct device *dev;
struct resource *ioarea; //IO Memory resources
struct i2c_adapter adap; // Corresponding adapter
};
5、 Adapter driven probe Method realization
static int s3c24xx_i2c_probe(struct platform_device *pdev)
{
struct s3c24xx_i2c *i2c;
struct s3c2410_platform_i2c *pdata;
struct resource *res;
int ret;
// Analysis Division platform Information transmitted by bus devices
pdata = pdev->dev.platform_data;
i2c = kzalloc(sizeof(struct s3c24xx_i2c), GFP_KERNEL);
// Set the name of the adapter
strlcpy(i2c->adap.name, "s3c2410-i2c", sizeof(i2c->adap.name));
// Build the adapter structure adap
i2c->adap.owner = THIS_MODULE;
i2c->adap.algo = &s3c24xx_i2c_algorithm; // Set the communication method of the adapter
i2c->adap.retries = 2; // The number of retransmissions is 2
i2c->adap.class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
i2c->tx_setup = 50;
// Initialize spinlock and wait queue
spin_lock_init(&i2c->lock);
init_waitqueue_head(&i2c->wait);
/* obtain I2C The clock of the controller is not enabled */
i2c->dev = &pdev->dev;
i2c->clk = clk_get(&pdev->dev, "i2c"); // Get the clock system to I2C The clock frequency provided by the controller
clk_enable(i2c->clk); // Can make the clock
/* obtain I2C Controller IO Address resources */
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
······
// Apply for the physical address of the register
i2c->ioarea = request_mem_region(res->start, resource_size(res),
pdev->name);
// Dynamically map physical addresses
i2c->regs = ioremap(res->start, resource_size(res));
// stay master_xfer And other methods can pass the adapter algo_data Get the corresponding i2c object
i2c->adap.algo_data = i2c;
i2c->adap.dev.parent = &pdev->dev;
// Initialize the chip I2C controller : To interrupt 、ACK Can make 、 Set the corresponding GPIO、 Initialization clock, etc
ret = s3c24xx_i2c_init(i2c);
if (ret != 0)
goto err_iomap;
// Get interrupt number resource
i2c->irq = ret = platform_get_irq(pdev, 0);
if (ret <= 0) {
dev_err(&pdev->dev, "cannot find IRQ\n");
goto err_iomap;
}
// Apply for interrupt number and bind interrupt handler s3c24xx_i2c_irq
ret = request_irq(i2c->irq, s3c24xx_i2c_irq, IRQF_DISABLED,
dev_name(&pdev->dev), i2c);
// Using the kernel notification chain mechanism , When CPU When the frequency changes , when I2C The clock setting can be adjusted
ret = s3c24xx_i2c_register_cpufreq(i2c);
if (ret < 0) {
dev_err(&pdev->dev, "failed to register cpufreq notifier\n");
goto err_irq;
}
// from platform The bus device obtains the bus number of the adapter
i2c->adap.nr = pdata->bus_num;
// towards I2C The core layer registers the adapter
ret = i2c_add_numbered_adapter(&i2c->adap);
if (ret < 0) {
dev_err(&pdev->dev, "failed to add bus to i2c core\n");
goto err_cpufreq;
}
// take i2c Save to pdev->dev->p->driver_data
platform_set_drvdata(pdev, i2c);
clk_disable(i2c->clk);
dev_info(&pdev->dev, "%s: S3C I2C adapter\n", dev_name(&i2c->adap.dev));
return 0;
······
}
6、I2C Bus communication method
6.1、 Communication method of adapter
static const struct i2c_algorithm s3c24xx_i2c_algorithm = {
.master_xfer = s3c24xx_i2c_xfer,
.functionality = s3c24xx_i2c_func,
};
6.2、 Function call relationship of data communication
s3c24xx_i2c_xfer() //adap->algo->master_xfer
s3c24xx_i2c_doxfer()
s3c24xx_i2c_set_master() // Ensure current I2C Controller is idle , Before continuing the following operation
s3c24xx_i2c_enable_irq() // Can make i2C-Bus Of Tx/Rx interrupt
s3c24xx_i2c_message_start() // Turn on I2C signal communication
wait_event_timeout(i2c->wait, i2c->msg_num == 0, HZ * 5); // Send function into wait , Until the message is sent or exceeds 5s return
Wake up the waiting queue in the interrupt program :
s3c24xx_i2c_irq() // Adapter bound interrupt handler
i2c_s3c_irq_nextbyte() // send data
s3c24xx_i2c_stop() // Stop this transmission when data transmission and reception is completed or communication error occurs
s3c24xx_i2c_master_complete() // This transmission is completed
wake_up(&i2c->wait); // Wake up waiting line
(1)I2C Adapter description structure struct i2c_adapter in algo Variables are the communication methods of the adapter , In the driver's prob Function assignment ;
(2) Communication is based on messages (struct i2c_msg) In units , The message description structure will indicate the address of the device to be sent 、 Data transmission direction, etc ;
6.3、 Communication process
(1) First of all I2C The device driver invokes the adapter adap->algo->master_xfer To send a message ,master_xfer Method after some initialization , Open this I2C signal communication , Then enter the waiting queue , Until the message is sent or 5 Return after seconds timeout ;
(2) The specific sending is in probe Method is bound to the interrupt function , The interrupt function is I2C Interrupt handling function of controller , After sending data or making errors , Will wake up before waiting s3c24xx_i2c_doxfer() function ;
边栏推荐
- 正则表达式
- Web game engine
- About the pit of firewall opening 8848 when Nacos is started
- curl 命令妙用
- 解读数据安全治理能力评估框架2.0,第四批DSG评估征集中
- Internet addiction changes brain structure: language function is affected, making people unable to speak neatly
- 【系统分析师之路】第七章 复盘系统设计(结构化开发方法)
- wuzhicms代码审计
- Go micro tutorial - Chapter 2 go micro V3 using gin and etcd
- 整理混乱的头文件,我用include what you use
猜你喜欢
Ble HCI flow control mechanism
Vb无法访问数据库stocks
Developers, MySQL column finish, help you easily from installation to entry
超标量处理器设计 姚永斌 第6章 指令解码 摘录
就在今天丨汇丰4位专家齐聚,共讨银行核心系统改造、迁移、重构难题
【Unity UGUI】ScrollRect 动态缩放格子大小,自动定位到中间的格子
居家打工年入800多万,一共五份全职工作,他还有时间打游戏
Zhijieyun - meta universe comprehensive solution service provider
如何进行MDM的产品测试
离线、开源版的 Notion—— 笔记软件Anytype 综合评测
随机推荐
一文掌握数仓中auto analyze的使用
我写了一份初学者的学习实践教程!
What is low code development?
Internet addiction changes brain structure: language function is affected, making people unable to speak neatly
TP configuring multiple databases
补能的争议路线:快充会走向大一统吗?
一加10 Pro和iPhone 13怎么选?
智捷云——元宇宙综合解决方案服务商
简单易用的地图可视化
wuzhicms代码审计
Using win10 scheduling task program to automatically run jar package at fixed time
Win32 API access route encrypted web pages
Ble HCI flow control mechanism
The 18th IET AC / DC transmission International Conference (acdc2022) was successfully held online
Superscalar processor design yaoyongbin Chapter 5 instruction set excerpt
Pytorch deep learning quick start tutorial
Mathematical analysis_ Notes_ Chapter 7: differential calculus of multivariate functions
Win32 API 访问路由的加密网页
PingCode 性能测试之负载测试实践
MVC mode and three-tier architecture