static int i2c_imx_probe(struct platform_device *pdev) { const struct of_device_id *of_id = of_match_device(i2c_imx_dt_ids, &pdev->dev); struct imx_i2c_struct *i2c_imx; struct resource *res; struct imxi2c_platform_data *pdata = dev_get_platdata(&pdev->dev); void __iomem *base; int irq, ret; dma_addr_t phy_addr; dev_dbg(&pdev->dev, '<%s> ', func); irq = platform_get_irq(pdev, 0); if (irq < 0) { dev_err(&pdev->dev, "can't get irq number\n"); return irq; } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); base = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(base)) return PTR_ERR(base); phy_addr = (dma_addr_t)res->start; i2c_imx = devm_kzalloc(&pdev->dev, sizeof(*i2c_imx), GFP_KERNEL); if (!i2c_imx) return -ENOMEM; if (of_id) i2c_imx->hwdata = of_id->data; else i2c_imx->hwdata = (struct imx_i2c_hwdata ) platform_get_device_id(pdev)->driver_data; / Setup i2c_imx driver structure / strlcpy(i2c_imx->adapter.name, pdev->name, sizeof(i2c_imx->adapter.name)); i2c_imx->adapter.owner = THIS_MODULE; i2c_imx->adapter.algo = &i2c_imx_algo; i2c_imx->adapter.dev.parent = &pdev->dev; i2c_imx->adapter.nr = pdev->id; i2c_imx->adapter.dev.of_node = pdev->dev.of_node; i2c_imx->base = base; / Get I2C clock / i2c_imx->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(i2c_imx->clk)) { dev_err(&pdev->dev, "can't get I2C clock\n"); return PTR_ERR(i2c_imx->clk); } ret = clk_prepare_enable(i2c_imx->clk); if (ret) { dev_err(&pdev->dev, "can't enable I2C clock, ret=%d\n", ret); return ret; } / Request IRQ / ret = devm_request_irq(&pdev->dev, irq, i2c_imx_isr, IRQF_NO_SUSPEND, pdev->name, i2c_imx); if (ret) { dev_err(&pdev->dev, "can't claim irq %d\n", irq); goto clk_disable; } / Init queue / init_waitqueue_head(&i2c_imx->queue); / Set up adapter data / i2c_set_adapdata(&i2c_imx->adapter, i2c_imx); / Set up platform driver data / platform_set_drvdata(pdev, i2c_imx); pm_runtime_set_autosuspend_delay(&pdev->dev, I2C_PM_TIMEOUT); pm_runtime_use_autosuspend(&pdev->dev); pm_runtime_set_active(&pdev->dev); pm_runtime_enable(&pdev->dev); ret = pm_runtime_get_sync(&pdev->dev); if (ret < 0) goto rpm_disable; / Set up clock divider / i2c_imx->bitrate = IMX_I2C_BIT_RATE; ret = of_property_read_u32(pdev->dev.of_node, "clock-frequency", &i2c_imx->bitrate); if (ret < 0 && pdata && pdata->bitrate) i2c_imx->bitrate = pdata->bitrate; / Set up chip registers to defaults / imx_i2c_write_reg(i2c_imx->hwdata->i2cr_ien_opcode ^ I2CR_IEN, i2c_imx, IMX_I2C_I2CR); imx_i2c_write_reg(i2c_imx->hwdata->i2sr_clr_opcode, i2c_imx, IMX_I2C_I2SR); / Init optional bus recovery function / ret = i2c_imx_init_recovery_info(i2c_imx, pdev); / Give it another chance if pinctrl used is not ready yet / if (ret == -EPROBE_DEFER) goto rpm_disable; / Add I2C adapter / ret = i2c_add_numbered_adapter(&i2c_imx->adapter); if (ret < 0) goto rpm_disable; pm_runtime_mark_last_busy(&pdev->dev); pm_runtime_put_autosuspend(&pdev->dev); dev_dbg(&i2c_imx->adapter.dev, "claimed irq %d\n", irq); dev_dbg(&i2c_imx->adapter.dev, "device resources: %pR\n", res); dev_dbg(&i2c_imx->adapter.dev, "adapter name: '%s'\n", i2c_imx->adapter.name); dev_info(&i2c_imx->adapter.dev, "IMX I2C adapter registered\n"); / Init DMA config if supported / i2c_imx_dma_request(i2c_imx, phy_addr); return 0; / Return OK */ rpm_disable: pm_runtime_put_noidle(&pdev->dev); pm_runtime_disable(&pdev->dev); pm_runtime_set_suspended(&pdev->dev); pm_runtime_dont_use_autosuspend(&pdev->dev); clk_disable: clk_disable_unprepare(i2c_imx->clk); return ret; }

IMX I2C 驱动探测函数:i2c_imx_probe

原文地址: https://www.cveoy.top/t/topic/n6BW 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录