ThinkChat🤖让你学习和工作更高效,注册即送10W Token,即刻开启你的AI之旅 广告
# BSP 内核启动错误及警告 ## pll错误 ~~~ [ 0.118408] Not Found clk pll_isp in script [ 0.118535] Not Found clk pll_video in script [ 0.118732] Not Found clk pll_ve in script [ 0.118841] Not Found clk pll_periph0 in script [ 0.119038] Not Found clk pll_de in script ~~~ drivers/clk/sunxi/clk-default.c 似乎是废弃的代码,warning不管 ## I2C 错误 ~~~ [ 0.126676] twi_chan_cfg()340 - [twi0] has no twi_regulator. [ 0.126891] twi_chan_cfg()340 - [twi1] has no twi_regulator. [ 0.127229] twi_request_gpio()408 - TWI0 devm_pinctrl_get() failed! return -22 [ 0.127447] sunxi_i2c_hw_init()1128 - [i2c0] request i2c gpio failed! [ 0.127587] twi: probe of twi0 failed with error -5 ~~~ drivers/i2c/busses/i2c-sunxi.c ~~~ static int __init sunxi_i2c_adap_init(void) { sunxi_twi_device_scan(); //填充platformdata twi_chan_cfg(sunxi_twi_pdata); //获取twi通道在script里的使能情况 for (i=0; i<SUNXI_TWI_NUM; i++) { if (twi_chan_is_enable(i)) { I2C_DBG("Sunxi I2C init channel %d \n", i); ret = platform_device_register(&sunxi_twi_device[i]); //注册平台设备 if (ret < 0) { I2C_ERR("platform_device_register(%d) failed, return %d\n", i, ret); return ret; } sunxi_i2c_sysfs(&sunxi_twi_device[i]); //新建sys/devices/platform/twi.0 } } if (twi_used_mask) return platform_driver_register(&sunxi_i2c_driver); //注册平台驱动 I2C_DBG("cannot find any using configuration for all twi controllers!\n"); return 0; } subsys_initcall(sunxi_i2c_adap_init); ~~~ 驱动信息: ~~~ static struct platform_driver sunxi_i2c_driver = { .probe = sunxi_i2c_probe, .remove = __devexit_p(sunxi_i2c_remove), .driver = { .name = SUNXI_TWI_DEV_NAME, .owner = THIS_MODULE, .pm = SUNXI_I2C_DEV_PM_OPS, }, }; ~~~ 驱动插入 ~~~ static int __devinit sunxi_i2c_probe(struct platform_device *pdev) { struct sunxi_i2c *i2c = NULL; struct resource *res = NULL; struct sunxi_i2c_platform_data *pdata = NULL; int ret, irq; //获取内存和中断 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); irq = platform_get_irq(pdev, 0); …… request_mem_region(res->start, resource_size(res), res->name) …… //适配器的一些参数设置 i2c->adap.owner = THIS_MODULE; i2c->adap.nr = pdata->bus_num; i2c->adap.retries = 3; i2c->adap.timeout = 5*HZ; i2c->adap.class = I2C_CLASS_HWMON | I2C_CLASS_SPD; i2c->bus_freq = pdata->frequency; i2c->irq = irq; i2c->bus_num = pdata->bus_num; i2c->status = I2C_XFER_IDLE; i2c->suspended = 0; snprintf(i2c->adap.name, sizeof(i2c->adap.name), SUNXI_TWI_DEV_NAME"%u", i2c->adap.nr); pdev->dev.init_name = i2c->adap.name; i2c->mclk = clk_get(NULL, i2c->adap.name); //获取twi0时钟 i2c->base_addr = ioremap(res->start, resource_size(res)); //映射地址 i2c->adap.algo = &sunxi_i2c_algorithm; //i2c发送的具体方法 ret = request_irq(irq, sunxi_i2c_handler, IRQF_DISABLED, i2c->adap.name, i2c); //申请中断 i2c->adap.algo_data = i2c; i2c->adap.dev.parent = &pdev->dev; sunxi_i2c_hw_init(i2c, pdata) //硬件初始化i2c ret = i2c_add_numbered_adapter(&i2c->adap); //i2c总线注册adapter device和client device, platform_set_drvdata(pdev, i2c); return 0; …… } ~~~ 硬件初始化过程 ~~~ static int sunxi_i2c_hw_init(struct sunxi_i2c *i2c, struct sunxi_i2c_platform_data *pdata) { …… ret = twi_request_gpio(i2c); if (ret < 0) { I2C_ERR("[i2c%d] request i2c gpio failed!\n", i2c->bus_num); return -1; } if (sunxi_i2c_clk_init(i2c)) { I2C_ERR("[i2c%d] init i2c clock failed!\n", i2c->bus_num); return -1; } twi_soft_reset(i2c->base_addr); return ret; } ~~~ 申请GPIO ~~~ static int twi_request_gpio(struct sunxi_i2c *i2c) { I2C_DBG("Pinctrl init %d ... [%s]\n", i2c->bus_num, i2c->adap.dev.parent->init_name); if (!twi_chan_is_enable(i2c->bus_num)) return -1; i2c->pctrl = devm_pinctrl_get(i2c->adap.dev.parent); if (IS_ERR(i2c->pctrl)) { I2C_ERR("TWI%d devm_pinctrl_get() failed! return %ld\n", i2c->bus_num, PTR_ERR(i2c->pctrl)); return -1; } return twi_select_gpio_state(i2c->pctrl, PINCTRL_STATE_DEFAULT, i2c->bus_num); } ~~~