完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
【平台信息】
平台:Rockchip CPU:RK3288 PMU:RK808-B 开机流程: 1)当有接适配器时:VDC 电压升高; VSYS 上电; PMIC 上电并输出。 2)当只接电池时,按开机键:PWRON 拉高; PMIC 上电并输出。PMIC 启动,实现 EPROM 中的默认设置,各路上电完成后,发送 reset 信号,芯片上电,系统启动,PMIC 设备挂载,通过I2C 重新配置 PMIC。 【流程梳理】 1、设备树配置 kernel/arch/arm/boot/dts/rk808.dtsi &rk808 { compatible = "rockchip,rk808"; regulators { #address-cells = <1>; #size-cells = <0>; rk808_dcdc1_reg: regulator@0 { reg = <0>; regulator-compatible = "rk_dcdc1"; regulator-min-microvolt = <700000>; regulator-max-microvolt = <1500000>; regulator-initial-mode = <0x2>; regulator-initial-state = <3>; regulator-state-mem { regulator-state-mode = <0x2>; regulator-state-disabled;//disabled regulator-state-uv = <900000>; }; }; ... rk808_ldo1_reg: regulator@4 { reg = <4>; regulator-compatible = "rk_ldo1"; regulator-initial-state = <3>; regulator-state-mem { regulator-state-enabled; regulator-state-uv = <3300000>; }; }; ... kernel/arch/arm/boot/dts/rk3288-n1904.dts &i2c0 { status = "okay"; rk808: rk808@1b { reg = <0x1b>; status = "okay"; }; ... } &rk808 { gpios =<&gpio0 GPIO_A4 GPIO_ACTIVE_HIGH>,<&gpio0 GPIO_A0 GPIO_ACTIVE_HIGH>; rk808,system-power-controller; regulators { rk808_dcdc1_reg: regulator@0{ regulator-name= "vdd_arm"; regulator-min-microvolt = <700000>; regulator-max-microvolt = <1500000>; regulator-always-on; regulator-boot-on; }; ... rk808_ldo1_reg: regulator@4 { regulator-name= "rk_ldo1"; regulator-min-microvolt = <1800000>; regulator-max-microvolt = <1800000>; regulator-always-on; regulator-boot-on; }; ... }; }; 参考文档: Documentation/devicetree/bindings/mfd/rk808.txt Documentation/devicetree/bindings/regulator/regulator.txt 2、驱动代码 kernel/drivers/mfd/rk808.c static struct rk808_board *rk808_parse_dt(struct rk808 *rk808) { struct rk808_board *pdata; struct device_node *regs,*rk808_pmic_np; int i, count; rk808_pmic_np = of_node_get(rk808->dev->of_node); if (!rk808_pmic_np) { printk("could not find pmic sub-noden"); return NULL; } regs = of_find_node_by_name(rk808_pmic_np, "regulators"); if (!regs) return NULL; count = of_regulator_match(rk808->dev, regs, rk808_reg_matches, rk808_NUM_REGULATORS); // 匹配并查找设备树中regulator个数 of_node_put(regs); if ((count < 0) || (count > rk808_NUM_REGULATORS)) return NULL; pdata = devm_kzalloc(rk808->dev, sizeof(*pdata), GFP_KERNEL); if (!pdata) return NULL; for (i = 0; i < count; i++) { if (!rk808_reg_matches.init_data || !rk808_reg_matches.of_node) continue; pdata->rk808_init_data = rk808_reg_matches.init_data; pdata->of_node = rk808_reg_matches.of_node; } pdata->irq = rk808->chip_irq; pdata->irq_base = -1; pdata->irq_gpio = of_get_named_gpio(rk808_pmic_np,"gpios",0); if (!gpio_is_valid(pdata->irq_gpio)) { printk("invalid gpio: %dn", pdata->irq_gpio); return NULL; } pdata->pmic_sleep_gpio = of_get_named_gpio(rk808_pmic_np,"gpios",1); if (!gpio_is_valid(pdata->pmic_sleep_gpio)) { printk("invalid gpio: %dn", pdata->pmic_sleep_gpio); } pdata->pmic_sleep = true; pdata->pm_off = of_property_read_bool(rk808_pmic_np,"rk808,system-power-controller"); return pdata; } static int rk808_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { struct rk808 *rk808; ... rk808 = devm_kzalloc(&i2c->dev,sizeof(struct rk808), GFP_KERNEL); rk808->i2c = i2c; rk808->dev = &i2c->dev; i2c_set_clientdata(i2c, rk808); ... ret = rk808_pre_init(rk808); //rk808工作状态初始化,配置一堆寄存器 if (rk808->dev->of_node) pdev = rk808_parse_dt(rk808); //设备树解析 /******************************set sleep vol & dcdc mode******************/ #ifdef CONFIG_OF rk808->pmic_sleep_gpio = pdev->pmic_sleep_gpio; if (rk808->pmic_sleep_gpio) { ret = gpio_request(rk808->pmic_sleep_gpio, "rk808_pmic_sleep"); if (ret < 0) { dev_err(rk808->dev,"Failed to request gpio %d with ret:""%dn", rk808->pmic_sleep_gpio, ret); return IRQ_NONE; } gpio_direction_output(rk808->pmic_sleep_gpio,0); ret = gpio_get_value(rk808->pmic_sleep_gpio); gpio_free(rk808->pmic_sleep_gpio); pr_info("%s: rk808_pmic_sleep=%xn", __func__, ret); } #endif if (pdev) { rk808->num_regulators = rk808_NUM_REGULATORS; rk808->rdev = kcalloc(rk808_NUM_REGULATORS,sizeof(struct regulator_dev *), GFP_KERNEL); if (!rk808->rdev) { return -ENOMEM; } /* Instantiate the regulators */ for (i = 0; i < rk808_NUM_REGULATORS; i++) { reg_data = pdev->rk808_init_data; if (!reg_data) continue; config.dev = rk808->dev; config.driver_data = rk808; config.regmap = rk808->regmap; if (rk808->dev->of_node) config.of_node = pdev->of_node; if (reg_data && reg_data->constraints.name) rail_name = reg_data->constraints.name; else rail_name = regulators.name; reg_data->supply_regulator = rail_name; config.init_data =reg_data; rk808_rdev = regulator_register(®ulators,&config); if (IS_ERR(rk808_rdev)) { printk("failed to register %d regulatorn",i); goto err; } rk808->rdev = rk808_rdev; } // end for } // end if rk808->irq_gpio = pdev->irq_gpio; ret = rk808_irq_init(rk808, rk808->irq_gpio, pdev); if (ret < 0) goto err; ret = mfd_add_devices(rk808->dev, -1, rk808s, ARRAY_SIZE(rk808s), NULL, 0,NULL); g_rk808 = rk808; if (pdev->pm_off && !pm_power_off) { pm_power_off = rk808_device_shutdown; } #ifdef CONFIG_HAS_EARLYSUSPEND rk808->rk808_suspend.suspend = rk808_early_suspend, rk808->rk808_suspend.resume = rk808_late_resume, rk808->rk808_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB + 1, register_early_suspend(&rk808->rk808_suspend); #endif rk808_kobj = kobject_create_and_add("rk808", NULL); if (!rk808_kobj) return -ENOMEM; for (i = 0; i < ARRAY_SIZE(rk808_attrs); i++) { ret = sysfs_create_file(rk808_kobj, &rk808_attrs.attr); if (ret != 0) { printk("create index %d errorn", i); return ret; } } register_syscore_ops(&rk808_syscore_ops); return 0; } static const struct i2c_device_id rk808_i2c_id[] = { { "rk808", 0 }, { } }; MODULE_DEVICE_TABLE(i2c, rk808_i2c_id); static struct i2c_driver rk808_i2c_driver = { .driver = { .name = "rk808", .owner = THIS_MODULE, #ifdef CONFIG_PM .pm = &rk808_pm_ops, #endif .of_match_table =of_match_ptr(rk808_of_match), }, .probe = rk808_i2c_probe, .remove = rk808_i2c_remove, .id_table = rk808_i2c_id, }; static int __init rk808_module_init(void) { int ret; ret = i2c_add_driver(&rk808_i2c_driver); if (ret != 0) pr_err("Failed to register I2C driver: %dn", ret); return ret; } subsys_initcall_sync(rk808_module_init); 【调试记录】 1、内核加载rk808驱动日志 rk808_i2c_probe,line=1355 rk808_pre_init,line=1224 of_get_named_gpio_flags exited with status 4 of_get_named_gpio_flags exited with status 0 vdd_arm: 712 <--> 1500 mV at 1312 mV vdd_gpu: 712 <--> 1500 mV at 900 mV rk_dcdc3: 1200 mV vccio: 1800 <--> 3300 mV at 3300 mV rk_ldo1: 1800 mV rk_ldo2: 3300 mV rk_ldo3: 1000 mV rk_ldo4: 1800 mV rk_ldo5: 3300 mV rk_ldo6: 1800 mV rk_ldo7: 1800 mV rk_battery_charger_detect_cb , battery_charger_detect 1 rk_ldo8: 1800 mV rk_ldo9: at 3300 mV rk_ldo10: at 3300 mV rk808_irq_init: rk808_pmic_irq=1 rk808_rtc_probe,line=540 rk808-rtc rk808-rtc: rtc core: registered rk808 as rtc0 rk808_rtc_probe:ok |
|
|
|
你正在撰写答案
如果你是对答案或其他答案精选点评或询问,请使用“评论”功能。
rk1126实现BT601输入,输入不带IIC接口的驱动程序
1235 浏览 0 评论
1225 浏览 1 评论
2318 浏览 3 评论
RK3568 Android11让系统ntp校准时间生效,需要设置些什么
3077 浏览 1 评论
5085 浏览 2 评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-8-18 02:18 , Processed in 0.559059 second(s), Total 72, Slave 56 queries .
Powered by 电子发烧友网
© 2015 www.ws-dc.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号