s3c24xx.c看i2c控制器驱动的编写(2)

probe主要负责"申请资源+初始化+提供接口", 通过对probe的分析, 就可以对整个驱动的构建有一个
提纲挈领的理解

1072 static int s3c24xx_i2c_probe(struct platform_device *pdev) 1073 { 1074 struct s3c24xx_i2c *i2c; 1075 struct s3c2410_platform_i2c *pdata = NULL; 1076 struct resource *res; 1077 int ret; 1078 1079 if (!pdev->dev.of_node) { 1080 pdata = dev_get_platdata(&pdev->dev); 1085 } 1086 1087 i2c = devm_kzalloc(&pdev->dev, sizeof(struct s3c24xx_i2c), GFP_KERNEL); 1092 1093 i2c->pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); 1098 1099 i2c->quirks = s3c24xx_get_device_quirks(pdev); 1100 if (pdata) 1101 memcpy(i2c->pdata, pdata, sizeof(*pdata)); 1102 else 1103 s3c24xx_i2c_parse_dt(pdev->dev.of_node, i2c); 1104 1105 strlcpy(i2c->adap.name, "s3c2410-i2c", sizeof(i2c->adap.name)); 1106 i2c->adap.owner = THIS_MODULE; 1107 i2c->adap.algo = &s3c24xx_i2c_algorithm; 1108 i2c->adap.retries = 2; 1109 i2c->adap.class = I2C_CLASS_HWMON | I2C_CLASS_SPD; 1110 i2c->tx_setup = 50; 1111 1112 init_waitqueue_head(&i2c->wait); 1113 1114 /* find the clock and enable it */ 1116 i2c->dev = &pdev->dev; 1117 i2c->clk = devm_clk_get(&pdev->dev, "i2c"); 1124 1126 /* map the registers */ 1128 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1129 i2c->regs = devm_ioremap_resource(&pdev->dev, res); 1136 1137 /* setup info block for the i2c core */ 1139 i2c->adap.algo_data = i2c; 1140 i2c->adap.dev.parent = &pdev->dev; 1141 1142 i2c->pctrl = devm_pinctrl_get_select_default(i2c->dev); 1143 1144 /* inititalise the i2c gpio lines */ 1146 if (i2c->pdata->cfg_gpio) { 1147 i2c->pdata->cfg_gpio(to_platform_device(i2c->dev)); 1148 } else if (IS_ERR(i2c->pctrl) && s3c24xx_i2c_parse_dt_gpio(i2c)) { 1149 return -EINVAL; 1150 } 1151 1152 /* initialise the i2c controller */ 1154 clk_prepare_enable(i2c->clk); 1155 ret = s3c24xx_i2c_init(i2c); 1156 clk_disable_unprepare(i2c->clk); 1161 /* find the IRQ for this unit (note, this relies on the init call to 1162 * ensure no current IRQs pending 1163 */ 1165 if (!(i2c->quirks & QUIRK_POLL)) { 1166 i2c->irq = ret = platform_get_irq(pdev, 0); 1171 1172 ret = devm_request_irq(&pdev->dev, i2c->irq, s3c24xx_i2c_irq, 0, 1173 dev_name(&pdev->dev), i2c); 1179 } 1180 1181 ret = s3c24xx_i2c_register_cpufreq(i2c); 1192 1193 i2c->adap.nr = i2c->pdata->bus_num; 1194 i2c->adap.dev.of_node = pdev->dev.of_node; 1196 ret = i2c_add_numbered_adapter(&i2c->adap); 1202 1203 platform_set_drvdata(pdev, i2c); 1204 1205 pm_runtime_enable(&pdev->dev); 1206 pm_runtime_enable(&i2c->adap.dev); 1209 return 0; 1210 }

s3c24xx_i2c_probe()
--1074-1077-->准备好指针与变量, 准备从传入的对象中提取数据, 虽说这是C89的语法要求, 但这种写法确实比较舒服, 遇到不认识的变量就去函数开头找
--1079-->如果pdev->dev.of_node为空, 表示设备不是通过设备树获得的, 那么就调用dev_get_platdata获取pdev->dev.oplatform_data中的数据, 显然, 在编写设备文件的时候这里藏的是一个s3c2410_platform_i2c对象, 所以我们用pdata取出来以备使用
--1087-->pdev->dev是device类型, 以它为的detach为标志分配一个我们自己的对象的空间并将分配的首地址返回给i2c。 这里使用的是devm_kzalloc(), 函数 devm_kzalloc()和kzalloc()一样都是内核内存分配函数,但是devm_kzalloc()是跟设备(device)有关的,当设备(device)被detached或者驱动(driver)卸载(unloaded)时,内存会被自动释放。另外,当内存不在使用时,可以使用函数devm_kfree()释放。而kzalloc()则需要手动释放(使用kfree()),但如果工程师检查不仔细,则有可能造成内存泄漏
--1100-1103-->如果在--1079--中获得了相应的s3c2410_platform_i2c对象地址,就将其拷贝到资源对象中的相应的域存起来,否则自己去设备树中找
--1106-1110-->使用赋值的方式直接对一部分资源对象的域进行初始化
--1112-->初始化资源对象中的等待队列头wait_queue_head_t wait
--1116-->初始化资源对象中的device dev
--1117-->初始化资源对象中的struct clk
--1128-->获取pdev中的地址resource, ioremap之后用于初始化资源对象中的regs域, 使用的是devm_ioremap_resource(), 同样是基于device的资源自动回收API
--1139-->将自定义资源对象指针藏到algo_data中, 和--1203--的作用一样, 给xfer()接口函数用
--1140-->初始化资源对象中的i2c_adapter对象中的部分成员, 指定其父设备是控制器设备的device域
--1142-->初始化资源对象中的pctrl域, 使用的是devm_pinctrl_get_select_default()
--1147-->使用to_platform_device(其实就是container_of)通过i2c->dev找到包含它的platform_device对象, 回调cfg_gpio()函数, 配置GPIO引脚
--1154-->初始化时钟
--1166-->获取中断资源
--1171-->注册中断, devm_request_irq
--1193-1194-->初始化i2c->adap对象, 总线编号是来自于设备的
--1196-->将构造的adapter对象注册到内核
--1203-->设置私有数据, pdev->dev->p->driver_data = i2c; 由于i2c->dev==pdev->dev, 所以其实就是将资源对象的首地址赋值给藏到device->device_private->driver_data中, 因为所有的接口都是使用platform_device作为形参的, 这种方法可以方便的找到自定义资源对象, 所以才叫void * driver_data
--1205-->设置dev的电源管理
--1206-->设置adap的电源管理

s3c24xx_i2c_algorithm

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/825e664c37210e780ae4cfe945a1ed77.html