当前位置:网站首页>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 ;
边栏推荐
- 斑马识别成狗,AI犯错的原因被斯坦福找到了丨开源
- 【系统分析师之路】第七章 复盘系统设计(结构化开发方法)
- Go micro tutorial - Chapter 2 go micro V3 using gin and etcd
- Implementation of super large-scale warehouse clusters in large commercial banks
- 第十八届IET交直流輸電國際會議(ACDC2022)於線上成功舉辦
- I2C子系统之适配器的设备接口分析(i2c-dev.c文件分析)
- [Huawei HCIA continuous update] SDN and FVC
- Developers, MySQL column finish, help you easily from installation to entry
- 解决el-input输入框.number数字输入问题,去掉type=“number“后面箭头问题也可以用这种方法代替
- 电子宠物小狗-内部结构是什么?
猜你喜欢
Go micro tutorial - Chapter 2 go micro V3 using gin and etcd
[unity ugui] scrollrect dynamically scales the grid size and automatically locates the middle grid
Superscalar processor design yaoyongbin Chapter 5 instruction set excerpt
使用3DMAX制作一枚手雷
[Huawei HCIA continuous update] SDN and FVC
7 RSA Cryptosystem
It's too convenient. You can complete the code release and approval by nailing it!
Chow Tai Fook fulfills the "centenary commitment" and sincerely serves to promote green environmental protection
【Unity UGUI】ScrollRect 动态缩放格子大小,自动定位到中间的格子
How to choose one plus 10 pro and iPhone 13?
随机推荐
大规模服务异常日志检索
Flask 轻量web框架
Zebras are recognized as dogs, and the reason for AI's mistakes is found by Stanford
我写了一份初学者的学习实践教程!
Ble HCI flow control mechanism
超标量处理器设计 姚永斌 第7章 寄存器重命名 摘录
国产数据库TiDB初体验:简单易用,快速上手
【Hot100】32. 最长有效括号
What grade does Anxin securities belong to? Is it safe to open an account
【HCIA持续更新】WLAN概述与基本概念
It's too convenient. You can complete the code release and approval by nailing it!
Vscode modification indentation failed, indent four spaces as soon as it is saved
The 18th IET AC / DC transmission International Conference (acdc2022) was successfully held online
码农版隐秘的角落:作为开发者最讨厌的5件
Recast of recastnavigation
CANN算子:利用迭代器高效实现Tensor数据切割分块处理
Is it safe for Great Wall Securities to open an account? How to open a securities account
MVC mode and three-tier architecture
PingCode 性能测试之负载测试实践
Pytorch deep learning quick start tutorial