Regulator相关GPIO控制使用流程简析
转载请注明出处,亲
1,注册到平台 举例:
extern struct gpio_regulator_platform_data v210_gpio_regs_platform_data; static struct platform_device v210_gpio_regulators_dev = { .name = "gpio-regulators", .id = -1, .dev = { .platform_data = &v210_gpio_regs_platform_data }, };
2,注册设备初始化接口
static struct regulator_consumer_supply gpio_reg_gpa07_consumers[] = { { .supply = "vdd_gps", }, }; static struct regulator_init_data gpio_reg_gpa07 = { .constraints = { .name = "VDD_GPS12/VDD_GPS28", .valid_ops_mask = REGULATOR_CHANGE_STATUS, .state_mem = { .mode = REGULATOR_MODE_NORMAL, .enabled = 0, }, }, .num_consumer_supplies = ARRAY_SIZE(gpio_reg_gpa07_consumers), .consumer_supplies = gpio_reg_gpa07_consumers, }; static struct regulator_consumer_supply gpio_reg_gpb3_consumers[] = { { .supply = "vdd_camb", }, }; static struct gpio_regulator v210_gpio_regulators [] = { [0] = { /*"VDD_GPS",*/ .gpio = S5PV210_GPA0(7), .name = "LDO_GPA0(7)", .type = GPIO_REGULATOR_VOLTAGE, .initdata = &gpio_reg_gpa07, }, [1] = { /*"VDD_CAMA",*/ .gpio = S5PV210_GPB(0), .name = "LDO_GPB(0)", .type = GPIO_REGULATOR_VOLTAGE, .initdata = &gpio_reg_gpb0, }, [2] = { /*"VDD_CAMB",*/ .gpio = S5PV210_GPB(3), .name = "LDO_GPB(3)", .type = GPIO_REGULATOR_VOLTAGE, .initdata = &gpio_reg_gpb3, }
。。。。。
。。。。。
}; struct gpio_regulator_platform_data v210_gpio_regs_platform_data = { .num_regulators = ARRAY_SIZE(v210_gpio_regulators), .regulators = v210_gpio_regulators, };
3,Regulator设备驱动加载的时候初始化,下面的驱动的一般流程和LINUX下的流驱动 字符设备等基本没区别
#include <linux/module.h> #include <linux/err.h> #include <linux/platform_device.h> #include <linux/regulator/driver.h> #include <linux/mutex.h> #include <linux/gpio.h> #include <plat/gpio-cfg.h> #include <plat/gpio_regulator.h> #include <linux/slab.h> struct gpio_regulator_device_data { struct device *dev; struct gpio_regulator_platform_data *pdata; int num_regulators; struct regulator_dev **rdev; struct XXX_gpio_regulator_data *pregdata; }; struct XXX_gpio_regulator_data{ struct regulator_desc reg_desc; int gpio_pin; int active_low; enum gpio_pull_mode pull; int gpio_sleep; /*sleep mode. */ }; static int XXX_gpio_reg_is_enabled(struct regulator_dev *rdev) { struct gpio_regulator_device_data *pddata = rdev_get_drvdata(rdev); struct XXX_gpio_regulator_data *pregdata; int id, ret; id = rdev_get_id(rdev); pregdata = &pddata->pregdata[id]; ret = (gpio_get_value(pregdata->gpio_pin))?1:0; if(pregdata->active_low) ret = !ret; printk("XXX_gpio_reg_is_enabled, regulator:[%s] is %d\n", pregdata->reg_desc.name, ret); printk("gpio_pin: 0x%0x\n", pregdata->gpio_pin); return ret; } static int XXX_gpio_reg_enable(struct regulator_dev *rdev) { struct gpio_regulator_device_data *pddata = rdev_get_drvdata(rdev); struct XXX_gpio_regulator_data *pregdata; int id, value, ret; id = rdev_get_id(rdev); pregdata = &pddata->pregdata[id]; printk("XXX_gpio_reg_enable, regulator: %s\n", pregdata->reg_desc.name); printk("gpio_pin: 0x%0x\n", pregdata->gpio_pin); s3c_gpio_cfgpin(pregdata->gpio_pin,S3C_GPIO_OUTPUT); s3c_gpio_setpull(pregdata->gpio_pin,((__force s3c_gpio_pull_t)pregdata->pull)); gpio_set_value(pregdata->gpio_pin, (pregdata->active_low?0:1)); return 0; } static int XXX_gpio_reg_disable(struct regulator_dev *rdev) { struct gpio_regulator_device_data *pddata = rdev_get_drvdata(rdev); struct XXX_gpio_regulator_data *pregdata; int id, value, ret; id = rdev_get_id(rdev); pregdata = &pddata->pregdata[id]; printk("XXX_gpio_reg_disable, regulator: %s\n", pregdata->reg_desc.name ); printk("gpio_pin: 0x%0x\n", pregdata->gpio_pin); s3c_gpio_cfgpin(pregdata->gpio_pin,S3C_GPIO_OUTPUT); s3c_gpio_setpull(pregdata->gpio_pin,((__force s3c_gpio_pull_t)pregdata->pull)); gpio_set_value(pregdata->gpio_pin, (pregdata->active_low?1:0)); return 0; } static int XXX_gpio_reg_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV) { return 0; } static int XXX_gpio_reg_get_voltage(struct regulator_dev *rdev) { return 0; } static int XXX_gpio_reg_suspend_enable(struct regulator_dev *rdev) { return 0; } static int XXX_gpio_reg_suspend_disable(struct regulator_dev *rdev) { return 0; } static int XXX_gpio_reg_set_suspend_voltage(struct regulator_dev *rdev, int uV) { return 0; } static struct regulator_ops XXX_gpio_reg_ops = { .list_voltage = NULL, //XXX_gpio_reg_list_voltage, .is_enabled = XXX_gpio_reg_is_enabled, .enable = XXX_gpio_reg_enable, .disable = XXX_gpio_reg_disable, .get_voltage = XXX_gpio_reg_get_voltage, .set_voltage = NULL, .set_suspend_enable = XXX_gpio_reg_suspend_enable, .set_suspend_disable = XXX_gpio_reg_suspend_disable, .set_suspend_voltage = NULL, }; static int __devinit XXX_gpio_regulators_probe(struct platform_device *pdev) { int i, error; int id, ret; //jeff, struct gpio_regulator_platform_data *pdata = pdev->dev.platform_data; struct gpio_regulator_device_data *ddata; struct regulator_desc *gpio_reg_desc; printk("XXX_gpio_regulators_probe\n"); ddata = kzalloc(sizeof(struct gpio_regulator_device_data),GFP_KERNEL); if (!ddata) return -ENOMEM; ddata->rdev = kzalloc(sizeof(struct regulator_dev *) * (pdata->num_regulators + 1), GFP_KERNEL); if (!ddata->rdev) { kfree(ddata); return -ENOMEM; } ddata->pregdata = kzalloc(sizeof(struct XXX_gpio_regulator_data) * (pdata->num_regulators + 1), GFP_KERNEL); if (!ddata->pregdata) { kfree(ddata->rdev); kfree(ddata); return -ENOMEM; } ddata->num_regulators = pdata->num_regulators; for (i = 0; i < ddata->num_regulators; i++) { gpio_reg_desc = &(ddata->pregdata[i].reg_desc); gpio_reg_desc->id = i; gpio_reg_desc->name = pdata->regulators[i].name; gpio_reg_desc->type = pdata->regulators[i].type; gpio_reg_desc->ops = &XXX_gpio_reg_ops; gpio_reg_desc->n_voltages = 1; gpio_reg_desc->owner = THIS_MODULE, /*add regulator pin configure*/ ddata->pregdata[i].gpio_pin = pdata->regulators[i].gpio; ddata->pregdata[i].active_low= pdata->regulators[i].active_low; ddata->pregdata[i].pull = pdata->regulators[i].pull; /**/ ddata->rdev[i] = regulator_register(gpio_reg_desc, ddata->dev,pdata->regulators[i].initdata, ddata); ret = IS_ERR(ddata->rdev[i]); if (ret) printk("[gpio_regulator] regulator:\"%s\" init failed\n", gpio_reg_desc->name); else printk("[gpio_regulator] regulator:\"%s\" init success\n", gpio_reg_desc->name); } return ret; } static int __devexit XXX_gpio_regulators_remove(struct platform_device *pdev) { printk("XXX_gpio_regulators_remove\n"); return 0; } static struct platform_driver gpio_regulators_driver = { .probe = XXX_gpio_regulators_probe, .remove = __devexit_p(XXX_gpio_regulators_remove), .driver = { .name = "gpio-regulators", .owner = THIS_MODULE, #if 0 .pm = &gpio_regulators_pm_ops, #endif } }; static int __init XXX_gpio_regulator_init(void) { printk("XXX_gpio_regulator_init\n"); return platform_driver_register(&gpio_regulators_driver); } static void __exit XXX_gpio_regulator_exit(void) { platform_driver_unregister(&gpio_regulators_driver); } subsys_initcall(XXX_gpio_regulator_init); //subsys_initcall_sync(XXX_gpio_regulator_init); module_exit(XXX_gpio_regulator_exit); MODULE_DESCRIPTION("XXX gpio controlled regulator driver"); MODULE_AUTHOR("SSCR jeff "); MODULE_LICENSE("GPL");
4,使用方式
首先,
static struct regulator *xxx_reg; 定义一个regulator结构体指针;
其次,
xxx_reg = regulator_get(NULL, "vdd_gps");获取这个指针
最后操作
if (IS_ERR(xxx_reg)) {
printk(KERN_ERR "failed to get resource %s\n", "xxx_reg");
}else{
regulator_enable(wifi_reg);//通过此来操作I/O控制I/O
}
好处是,方便LINUX各个驱动内部之间的控制。当然也可以用一般的GPIO流驱动替换