linux下regulator的应用
备注:下面提到的充电IC 用charger表示
1. OTG VBUS 5V供电
接入OTG设备,比如U盘,具体是怎么通过charger驱动来给U盘供电5V的
2. 设备树
charger:xxx@6B{ regulator-name = " xxx_otg_vreg"; … }; &usb_otg { … vbus_otg-supply = <& charger >; };
3. 调用流程
3.1 usb otg驱动
对应phy-msm-usb.c文件,usb otg驱动加载的时候,调用msm_otg_set_host(),此函数通过:
vbus_otg =devm_regulator_get(motg->phy.dev, "vbus_otg");
通过supply name,这里是vbus_otg-supply,找到regulator设备节点,这里是xxx_otg_supply,调用之后让vbus_otg指向给otg vbus供电的regulator,
devm_regulator_get的调用流程:
devm_regulator_get(motg->phy.dev,"vbus_otg")--->regulator_get() --->_regulator_get()--->regulator_dev_lookup()--->of_get_regulator() /** *of_get_regulator - get a regulator device node based on supply name *@dev: Device pointer for the consumer (of regulator) device *@supply: regulator supply name * *Extract the regulator device node corresponding to the supply name. *returns the device node corresponding to the regulator if found, else *returns NULL. */ static struct device_node*of_get_regulator(struct device *dev, const char *supply) { structdevice_node *regnode = NULL; charprop_name[32]; /* 32 is max size of property name */ dev_dbg(dev,"Looking up %s-supply from device tree\n", supply); snprintf(prop_name,32, "%s-supply", supply); regnode= of_parse_phandle(dev->of_node, prop_name, 0); if(!regnode) { dev_dbg(dev,"Looking up %s property in node %s failed", prop_name,dev->of_node->full_name); returnNULL; } returnregnode; }
通过节点xxx下的regulator-name找到regulator的名字为xxx_otg_vreg,
Usb otg驱动找到xxx_otg_vreg这个regulator后,在接入OTG设备时,会调用其对应的regulator_desc(描述regulator的静态信息,包括:名字、supply regulator的名字、中断号、操作函数集(structregulator_ops))下的操作表ops下的enable(),拔出OTG设备时调用disable()
msm_hsusb_vbus_power()--->regulator_enable(vbus_otg)
那enable()和disable()具体在charger驱动中实现。
3.2 charger驱动
(1) 驱动初始化
调用regulator_register()向regulator框架层注册一个regulator设备,用regulator_dev结构体表示。
struct regulator_ops xxx_otg_reg_ops = { .enable = xxx_otg_regulator_enable, .disable = xxx_otg_regulator_disable, .is_enabled = xxx_otg_regulator_is_enable, }; static int xxx_regulator_init(struct xxx_device_info*chip) { intrc = 0; structregulator_init_data *init_data; structregulator_config cfg = {}; init_data= of_get_regulator_init_data(chip->dev, chip->dev->of_node); if(!init_data) { dev_err(chip->dev,"Unable to allocate memory\n"); return-ENOMEM; } if(init_data->constraints.name) { chip->otg_vreg.rdesc.owner= THIS_MODULE; chip->otg_vreg.rdesc.type= REGULATOR_VOLTAGE; chip->otg_vreg.rdesc.ops= &xxx_otg_reg_ops; chip->otg_vreg.rdesc.name= init_data->constraints.name; cfg.dev= chip->dev; cfg.init_data= init_data; cfg.driver_data= chip; cfg.of_node= chip->dev->of_node; init_data->constraints.valid_ops_mask |=REGULATOR_CHANGE_STATUS; chip->otg_vreg.rdev= regulator_register( &chip->otg_vreg.rdesc,&cfg); if(IS_ERR(chip->otg_vreg.rdev)) { rc= PTR_ERR(chip->otg_vreg.rdev); chip->otg_vreg.rdev= NULL; if(rc != -EPROBE_DEFER) dev_err(chip->dev, "OTGreg failed, rc=%d\n", rc); } } returnrc; }
(2) 插拔OTG设备
比如插入OTG设备时,usb otg驱动通过调用名为xxx_otg_vreg的regulator的enable,来实现otg vbus的供电,对应调用xxx_otg_regulator_enable()。