当前位置:网站首页>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 ;
边栏推荐
- 《吐血整理》保姆级系列教程-玩转Fiddler抓包教程(2)-初识Fiddler让你理性认识一下
- [test development] software testing - Basics
- Electronic pet dog - what is the internal structure?
- Firewall basic transparent mode deployment and dual machine hot standby
- 如何进行MDM的产品测试
- Cocoscreator event dispatch use
- Web game engine
- R language plot visualization: plot visualizes overlapping histograms and uses geom at the top edge of the histogram_ The rug function adds marginal rug plots
- Pytorch deep learning quick start tutorial
- Datakit -- the real unified observability agent
猜你喜欢

聊聊异步编程的 7 种实现方式

上网成瘾改变大脑结构:语言功能受影响,让人话都说不利索

【测试开发】软件测试——基础篇

Vscode modification indentation failed, indent four spaces as soon as it is saved

解决el-input输入框.number数字输入问题,去掉type=“number“后面箭头问题也可以用这种方法代替

Hidden corners of coder Edition: five things that developers hate most

完美融入 Win11 风格,微软全新 OneDrive 客户端抢先看

DataKit——真正的统一可观测性 Agent

To sort out messy header files, I use include what you use

整理混乱的头文件,我用include what you use
随机推荐
解决el-input输入框.number数字输入问题,去掉type=“number“后面箭头问题也可以用这种方法代替
Solve the El input input box For number number input problem, this method can also be used to replace the problem of removing the arrow after type= "number"
How to choose one plus 10 pro and iPhone 13?
Datakit -- the real unified observability agent
Analysis of abnormal frequency of minor GC in container environment
电子宠物小狗-内部结构是什么?
整理混乱的头文件,我用include what you use
Rainfall warning broadcast automatic data platform bwii broadcast warning monitor
[test development] software testing - Basics
超标量处理器设计 姚永斌 第5章 指令集体系 摘录
Implementation of super large-scale warehouse clusters in large commercial banks
RecastNavigation 之 Recast
缓存穿透、缓存击穿、缓存雪崩分别是什么
公司要上监控,Zabbix 和 Prometheus 怎么选?这么选准没错!
【HCIA持续更新】WLAN工作流程概述
高中物理:力、物体和平衡
雨量预警广播自动化数据平台BWII 型广播预警监测仪
超标量处理器设计 姚永斌 第7章 寄存器重命名 摘录
长城证券开户安全吗 证券账户怎么开通
Firewall basic transparent mode deployment and dual machine hot standby