分类: LINUX
2011-12-19 08:20:18
关于fixed regulator 的使用:
1. 提供一组,消耗和供电的maps
比如模块电源使能:
static struct regulator_consumer_supply omap3evm_vmmc2_supply =
REGULATOR_SUPPLY("vmmc", "mmci-omap-hs.1");
vmmc 表示supply 的名字
mmci-omap-hs.1 dev 名字
他们的map关系名字为vmmc 的regulator 给名字为mmci-omap-hs.1供电
2. 设置regulator_init_data ,该结构,是用来register regulator class
device,包含上面的maps,和约束等数据
比如:
static struct regulator_init_data omap3evm_vmmc2 = {
num_consumer_supplies 指定上面 regulator_consumer_supply maps 有几组
constraints
中valid_ops_mask 包含regulator 操作的能力
#define REGULATOR_CHANGE_VOLTAGE 电压调节
#define REGULATOR_CHANGE_CURRENT 电流调节
#define REGULATOR_CHANGE_MODE
#define REGULATOR_CHANGE_STATUS 开关
#define REGULATOR_CHANGE_DRMS
valid_modes_mask 包含操作mode:
#define REGULATOR_MODE_FAST 0x1 电压可以快速调
#define REGULATOR_MODE_NORMAL 0x2 正常模式
#define REGULATOR_MODE_IDLE 0x4 低负载(loading小)
#define REGULATOR_MODE_STANDBY 0x8 sleep standby 状态下低功耗
3. 声明fixed regulator 所需要的fixed_voltage_config 数据结构
其中包括supply 名字,电压mv,开关gpio,使能电平等,并包含上面的initdata
static struct fixed_voltage_config omap3evm_vwlan = {
.supply_name = "vwl1271",
.microvolts = 1800000, /* 1.80V */
.gpio = OMAP3EVM_WLAN_PMENA_GPIO,
.startup_delay = 70000, /* 70ms */
.enable_high = 1,
.enabled_at_boot = 0,
.init_data = &omap3evm_vmmc2,
};
4. 声明一个reg-fixed-voltage 名字的platform device
和fixed.c中reg-fixed-voltage名字的driver 匹配,
在platform bus 上执行 fixed regulator driver 的probe
比如:
其中fixed_voltage_config 做为platform data 传入probe
static struct platform_device omap3evm_wlan_regulator = {
.name = "reg-fixed-voltage",
.id = 1,
.dev = {
.platform_data = &omap3evm_vwlan,
},
};
最后注册 该platform device
platform_device_register(&omap3evm_wlan_regulator);
关于fixed regulator init
1. fixed regulator driver (fixed.c) 会probe reg-fixed-voltage1
static struct platform_driver regulator_fixed_voltage_driver = {
.probe = reg_fixed_voltage_probe,
.remove = __devexit_p(reg_fixed_voltage_remove),
.driver = {
.name = "reg-fixed-voltage",
.owner = THIS_MODULE,
},
};
2. probe 中,通过struct fixed_voltage_config *config
(regulator platformdevice 的platformdata传入)
获得信息来产生下面结构:
struct fixed_voltage_data {
struct regulator_desc desc;
struct regulator_dev *dev;
int microvolts;
int gpio;
unsigned startup_delay;
bool enable_high;
bool is_enabled;
};
并通过struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc,
struct device *dev, struct regulator_init_data *init_data,
void *driver_data)
注册regulator_dev (class device) 到kernel,
这样/sys/class/regulator 下面 就包含regulator.1 实际link到
/sys/devices/platform/reg-fixed-voltage.1/regulator/regulator.1
这个platform device!
在注册过程中主要进行struct regulator_dev (class device)的初始化
struct regulator_dev {
struct regulator_desc *desc;
int use_count;
int open_count;
int exclusive;
/* lists we belong to */
struct list_head list; /* list of all regulators */
struct list_head slist; /* list of supplied regulators */
/* slist 用来link 到susply 给该reg dev 的supply_list 上*/
/* lists we own */
struct list_head consumer_list; /* consumers we supply */
struct list_head supply_list; /* regulators we supply */
/* supply_list link 子regulator list 用*/
struct blocking_notifier_head notifier;
struct mutex mutex; /* consumer lock */
struct module *owner;
struct device dev;
struct regulation_constraints *constraints;
struct regulator_dev *supply; /* for tree */
void *reg_data; /* regulator_dev data */
/* 私有数据,c 实现多态性的套路*/
};
上面注册成功regulator class dev 后,赋给 fixed_voltage_data
的struct regulator_dev *dev
最后通过platform_set_drvdata(pdev, drvdata);
这样可以方便的使用platform_get_drvdata 来通过
regulator platform device 来获其对应的fixed_voltage_data
在probe中,主要完成
* fixed_voltage_ops 操作函数组设置
不同的regulator 有不同ops
* regulator class device 注册
* 约束设置
比如有电压约束(min ,max)
则ops->set_voltage(min,max)
* 父rugulator dev 关联
这样可以把LDO 串成1棵树
* set_consumer_device_supply
通过该函数建立 consummer supply ,regulator dev 的map
并link 到regulator_map_list
这是regulator get 所需要查找的list
* 最后所有regulator 都挂到全局regulator_list
关于fixed regulator 的调用
在其他driver 中需要通过fixed regulator 上电时:
regulator_get(dev,supply name) 来获得
struct regulator {
struct device *dev;
struct list_head list;
int uA_load;
int min_uV;
int max_uV;
char *supply_name;
struct device_attribute dev_attr;
struct regulator_dev *rdev;
};
这个结构是通用的结构,对不同的regulator 通过
rdev_get_drvdata(rdev) 来获得不同子类型来进行操作
对于fixed regulator 比较简单
在获得regulator 后可以在poweron ,off时
调用regulator_enable(reg) 或
regulator_disable(reg)
比如:sdio 2的vmmc
omap_hsmmc_probe =>
omap_hsmmc_reg_get => host=>vcc 获得regulator结构
omap_hsmmc_23_set_power =>
=>mmc_regulator_set_ocr
=> regulator_enable(supply);
去enable
core.c 应该看做为1个接口,或者抽象类
fixed ,或其他regulator 是对core 接口的具体实现
对外统一使用core.c 中提供的接口函数