当前位置:网站首页>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 ;
边栏推荐
- La 18e Conférence internationale de l'IET sur le transport d'électricité en courant alternatif et en courant continu (acdc2022) s'est tenue avec succès en ligne.
- R language plot visualization: plot visualization of multiple variable violin plot in R with plot
- 新享科技发布小程序UniPro小优 满足客户移动办公场景
- 缓存穿透、缓存击穿、缓存雪崩分别是什么
- Internet addiction changes brain structure: language function is affected, making people unable to speak neatly
- 完美融入 Win11 风格,微软全新 OneDrive 客户端抢先看
- To sort out messy header files, I use include what you use
- 第十八届IET交直流輸電國際會議(ACDC2022)於線上成功舉辦
- 【Proteus仿真】基于VSM 串口printf调试输出示例
- Web game engine
猜你喜欢
如何进行MDM的产品测试
斑马识别成狗,AI犯错的原因被斯坦福找到了丨开源
补能的争议路线:快充会走向大一统吗?
Analysis of abnormal frequency of minor GC in container environment
MVC mode and three-tier architecture
超大规模数仓集群在大型商业银行的落地实践
[Huawei HCIA continuous update] SDN and FVC
RecastNavigation 之 Recast
就在今天丨汇丰4位专家齐聚,共讨银行核心系统改造、迁移、重构难题
整理混乱的头文件,我用include what you use
随机推荐
With an annual income of more than 8 million, he has five full-time jobs. He still has time to play games
MVC mode and three-tier architecture
PingCode 性能测试之负载测试实践
我写了一份初学者的学习实践教程!
【模板】【luogu P4630】Duathlon 铁人两项(圆方树)
Face_recognition人脸识别之考勤统计
国产数据库TiDB初体验:简单易用,快速上手
Superscalar processor design yaoyongbin Chapter 7 register rename excerpt
Superscalar processor design yaoyongbin Chapter 6 instruction decoding excerpt
Ks007 realizes personal blog system based on JSP
How to implement a delay queue?
KS007基于JSP实现人个人博客系统
网页游戏引擎
数学分析_笔记_第7章:多元函数的微分学
[HCIA continuous update] WLAN overview and basic concepts
Is it safe for Bank of China Securities to open an account online?
How to choose one plus 10 pro and iPhone 13?
大规模服务异常日志检索
regular expression
Easy to use map visualization