Loading drivers/regulator/core.c +110 −80 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ #include <linux/debugfs.h> #include <linux/device.h> #include <linux/slab.h> #include <linux/async.h> #include <linux/err.h> #include <linux/mutex.h> #include <linux/suspend.h> Loading @@ -33,6 +34,8 @@ #include "dummy.h" #define rdev_crit(rdev, fmt, ...) \ pr_crit("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__) #define rdev_err(rdev, fmt, ...) \ pr_err("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__) #define rdev_warn(rdev, fmt, ...) \ Loading Loading @@ -78,11 +81,13 @@ struct regulator { char *supply_name; struct device_attribute dev_attr; struct regulator_dev *rdev; #ifdef CONFIG_DEBUG_FS struct dentry *debugfs; #endif }; static int _regulator_is_enabled(struct regulator_dev *rdev); static int _regulator_disable(struct regulator_dev *rdev, struct regulator_dev **supply_rdev_ptr); static int _regulator_disable(struct regulator_dev *rdev); static int _regulator_get_voltage(struct regulator_dev *rdev); static int _regulator_get_current_limit(struct regulator_dev *rdev); static unsigned int _regulator_get_mode(struct regulator_dev *rdev); Loading @@ -90,6 +95,9 @@ static void _notifier_call_chain(struct regulator_dev *rdev, unsigned long event, void *data); static int _regulator_do_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV); static struct regulator *create_regulator(struct regulator_dev *rdev, struct device *dev, const char *supply_name); static const char *rdev_get_name(struct regulator_dev *rdev) { Loading Loading @@ -143,8 +151,11 @@ static int regulator_check_voltage(struct regulator_dev *rdev, if (*min_uV < rdev->constraints->min_uV) *min_uV = rdev->constraints->min_uV; if (*min_uV > *max_uV) if (*min_uV > *max_uV) { rdev_err(rdev, "unsupportable voltage range: %d-%duV\n", *min_uV, *max_uV); return -EINVAL; } return 0; } Loading Loading @@ -197,8 +208,11 @@ static int regulator_check_current_limit(struct regulator_dev *rdev, if (*min_uA < rdev->constraints->min_uA) *min_uA = rdev->constraints->min_uA; if (*min_uA > *max_uA) if (*min_uA > *max_uA) { rdev_err(rdev, "unsupportable current range: %d-%duA\n", *min_uA, *max_uA); return -EINVAL; } return 0; } Loading @@ -213,6 +227,7 @@ static int regulator_mode_constrain(struct regulator_dev *rdev, int *mode) case REGULATOR_MODE_STANDBY: break; default: rdev_err(rdev, "invalid mode %x specified\n", *mode); return -EINVAL; } Loading Loading @@ -779,7 +794,6 @@ static int machine_constraints_voltage(struct regulator_dev *rdev, if (ret < 0) { rdev_err(rdev, "failed to apply %duV constraint\n", rdev->constraints->min_uV); rdev->constraints = NULL; return ret; } } Loading Loading @@ -882,7 +896,6 @@ static int set_machine_constraints(struct regulator_dev *rdev, ret = suspend_prepare(rdev, rdev->constraints->initial_state); if (ret < 0) { rdev_err(rdev, "failed to set suspend state\n"); rdev->constraints = NULL; goto out; } } Loading @@ -909,13 +922,15 @@ static int set_machine_constraints(struct regulator_dev *rdev, ret = ops->enable(rdev); if (ret < 0) { rdev_err(rdev, "failed to enable\n"); rdev->constraints = NULL; goto out; } } print_constraints(rdev); return 0; out: kfree(rdev->constraints); rdev->constraints = NULL; return ret; } Loading @@ -933,19 +948,18 @@ static int set_supply(struct regulator_dev *rdev, { int err; err = sysfs_create_link(&rdev->dev.kobj, &supply_rdev->dev.kobj, "supply"); if (err) { rdev_err(rdev, "could not add device link %s err %d\n", supply_rdev->dev.kobj.name, err); goto out; } rdev->supply = supply_rdev; list_add(&rdev->slist, &supply_rdev->supply_list); out: rdev_info(rdev, "supplied by %s\n", rdev_get_name(supply_rdev)); rdev->supply = create_regulator(supply_rdev, &rdev->dev, "SUPPLY"); if (IS_ERR(rdev->supply)) { err = PTR_ERR(rdev->supply); rdev->supply = NULL; return err; } return 0; } /** * set_consumer_device_supply - Bind a regulator to a symbolic supply * @rdev: regulator source Loading Loading @@ -1032,7 +1046,7 @@ static void unset_regulator_supplies(struct regulator_dev *rdev) } } #define REG_STR_SIZE 32 #define REG_STR_SIZE 64 static struct regulator *create_regulator(struct regulator_dev *rdev, struct device *dev, Loading @@ -1052,8 +1066,9 @@ static struct regulator *create_regulator(struct regulator_dev *rdev, if (dev) { /* create a 'requested_microamps_name' sysfs entry */ size = scnprintf(buf, REG_STR_SIZE, "microamps_requested_%s", supply_name); size = scnprintf(buf, REG_STR_SIZE, "microamps_requested_%s-%s", dev_name(dev), supply_name); if (size >= REG_STR_SIZE) goto overflow_err; Loading Loading @@ -1088,7 +1103,28 @@ static struct regulator *create_regulator(struct regulator_dev *rdev, dev->kobj.name, err); goto link_name_err; } } else { regulator->supply_name = kstrdup(supply_name, GFP_KERNEL); if (regulator->supply_name == NULL) goto attr_err; } #ifdef CONFIG_DEBUG_FS regulator->debugfs = debugfs_create_dir(regulator->supply_name, rdev->debugfs); if (IS_ERR_OR_NULL(regulator->debugfs)) { rdev_warn(rdev, "Failed to create debugfs directory\n"); regulator->debugfs = NULL; } else { debugfs_create_u32("uA_load", 0444, regulator->debugfs, ®ulator->uA_load); debugfs_create_u32("min_uV", 0444, regulator->debugfs, ®ulator->min_uV); debugfs_create_u32("max_uV", 0444, regulator->debugfs, ®ulator->max_uV); } #endif mutex_unlock(&rdev->mutex); return regulator; link_name_err: Loading Loading @@ -1267,13 +1303,17 @@ void regulator_put(struct regulator *regulator) mutex_lock(®ulator_list_mutex); rdev = regulator->rdev; #ifdef CONFIG_DEBUG_FS debugfs_remove_recursive(regulator->debugfs); #endif /* remove any sysfs entries */ if (regulator->dev) { sysfs_remove_link(&rdev->dev.kobj, regulator->supply_name); kfree(regulator->supply_name); device_remove_file(regulator->dev, ®ulator->dev_attr); kfree(regulator->dev_attr.attr.name); } kfree(regulator->supply_name); list_del(®ulator->list); kfree(regulator); Loading Loading @@ -1301,19 +1341,6 @@ static int _regulator_enable(struct regulator_dev *rdev) { int ret, delay; if (rdev->use_count == 0) { /* do we need to enable the supply regulator first */ if (rdev->supply) { mutex_lock(&rdev->supply->mutex); ret = _regulator_enable(rdev->supply); mutex_unlock(&rdev->supply->mutex); if (ret < 0) { rdev_err(rdev, "failed to enable: %d\n", ret); return ret; } } } /* check voltage and requested load before enabling */ if (rdev->constraints && (rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_DRMS)) Loading Loading @@ -1388,19 +1415,27 @@ int regulator_enable(struct regulator *regulator) struct regulator_dev *rdev = regulator->rdev; int ret = 0; if (rdev->supply) { ret = regulator_enable(rdev->supply); if (ret != 0) return ret; } mutex_lock(&rdev->mutex); ret = _regulator_enable(rdev); mutex_unlock(&rdev->mutex); if (ret != 0) regulator_disable(rdev->supply); return ret; } EXPORT_SYMBOL_GPL(regulator_enable); /* locks held by regulator_disable() */ static int _regulator_disable(struct regulator_dev *rdev, struct regulator_dev **supply_rdev_ptr) static int _regulator_disable(struct regulator_dev *rdev) { int ret = 0; *supply_rdev_ptr = NULL; if (WARN(rdev->use_count <= 0, "unbalanced disables for %s\n", rdev_get_name(rdev))) Loading @@ -1427,9 +1462,6 @@ static int _regulator_disable(struct regulator_dev *rdev, NULL); } /* decrease our supplies ref count and disable if required */ *supply_rdev_ptr = rdev->supply; rdev->use_count = 0; } else if (rdev->use_count > 1) { Loading @@ -1440,6 +1472,7 @@ static int _regulator_disable(struct regulator_dev *rdev, rdev->use_count--; } return ret; } Loading @@ -1458,29 +1491,21 @@ static int _regulator_disable(struct regulator_dev *rdev, int regulator_disable(struct regulator *regulator) { struct regulator_dev *rdev = regulator->rdev; struct regulator_dev *supply_rdev = NULL; int ret = 0; mutex_lock(&rdev->mutex); ret = _regulator_disable(rdev, &supply_rdev); ret = _regulator_disable(rdev); mutex_unlock(&rdev->mutex); /* decrease our supplies ref count and disable if required */ while (supply_rdev != NULL) { rdev = supply_rdev; mutex_lock(&rdev->mutex); _regulator_disable(rdev, &supply_rdev); mutex_unlock(&rdev->mutex); } if (ret == 0 && rdev->supply) regulator_disable(rdev->supply); return ret; } EXPORT_SYMBOL_GPL(regulator_disable); /* locks held by regulator_force_disable() */ static int _regulator_force_disable(struct regulator_dev *rdev, struct regulator_dev **supply_rdev_ptr) static int _regulator_force_disable(struct regulator_dev *rdev) { int ret = 0; Loading @@ -1497,10 +1522,6 @@ static int _regulator_force_disable(struct regulator_dev *rdev, REGULATOR_EVENT_DISABLE, NULL); } /* decrease our supplies ref count and disable if required */ *supply_rdev_ptr = rdev->supply; rdev->use_count = 0; return ret; } Loading @@ -1516,16 +1537,16 @@ static int _regulator_force_disable(struct regulator_dev *rdev, int regulator_force_disable(struct regulator *regulator) { struct regulator_dev *rdev = regulator->rdev; struct regulator_dev *supply_rdev = NULL; int ret; mutex_lock(&rdev->mutex); regulator->uA_load = 0; ret = _regulator_force_disable(rdev, &supply_rdev); ret = _regulator_force_disable(regulator->rdev); mutex_unlock(&rdev->mutex); if (supply_rdev) regulator_disable(get_device_regulator(rdev_get_dev(supply_rdev))); if (rdev->supply) while (rdev->open_count--) regulator_disable(rdev->supply); return ret; } Loading Loading @@ -2136,7 +2157,7 @@ int regulator_set_optimum_mode(struct regulator *regulator, int uA_load) /* get input voltage */ input_uV = 0; if (rdev->supply) input_uV = _regulator_get_voltage(rdev->supply); input_uV = regulator_get_voltage(rdev->supply); if (input_uV <= 0) input_uV = rdev->constraints->input_uV; if (input_uV <= 0) { Loading Loading @@ -2206,17 +2227,8 @@ EXPORT_SYMBOL_GPL(regulator_unregister_notifier); static void _notifier_call_chain(struct regulator_dev *rdev, unsigned long event, void *data) { struct regulator_dev *_rdev; /* call rdev chain first */ blocking_notifier_call_chain(&rdev->notifier, event, NULL); /* now notify regulator we supply */ list_for_each_entry(_rdev, &rdev->supply_list, slist) { mutex_lock(&_rdev->mutex); _notifier_call_chain(_rdev, event, data); mutex_unlock(&_rdev->mutex); } } /** Loading Loading @@ -2264,6 +2276,13 @@ err: } EXPORT_SYMBOL_GPL(regulator_bulk_get); static void regulator_bulk_enable_async(void *data, async_cookie_t cookie) { struct regulator_bulk_data *bulk = data; bulk->ret = regulator_enable(bulk->consumer); } /** * regulator_bulk_enable - enable multiple regulator consumers * Loading @@ -2279,21 +2298,33 @@ EXPORT_SYMBOL_GPL(regulator_bulk_get); int regulator_bulk_enable(int num_consumers, struct regulator_bulk_data *consumers) { LIST_HEAD(async_domain); int i; int ret; int ret = 0; for (i = 0; i < num_consumers; i++) async_schedule_domain(regulator_bulk_enable_async, &consumers[i], &async_domain); async_synchronize_full_domain(&async_domain); /* If any consumer failed we need to unwind any that succeeded */ for (i = 0; i < num_consumers; i++) { ret = regulator_enable(consumers[i].consumer); if (ret != 0) if (consumers[i].ret != 0) { ret = consumers[i].ret; goto err; } } return 0; err: pr_err("Failed to enable %s: %d\n", consumers[i].supply, ret); for (--i; i >= 0; --i) for (i = 0; i < num_consumers; i++) if (consumers[i].ret == 0) regulator_disable(consumers[i].consumer); else pr_err("Failed to enable %s: %d\n", consumers[i].supply, consumers[i].ret); return ret; } Loading Loading @@ -2589,9 +2620,7 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc, rdev->owner = regulator_desc->owner; rdev->desc = regulator_desc; INIT_LIST_HEAD(&rdev->consumer_list); INIT_LIST_HEAD(&rdev->supply_list); INIT_LIST_HEAD(&rdev->list); INIT_LIST_HEAD(&rdev->slist); BLOCKING_INIT_NOTIFIER_HEAD(&rdev->notifier); /* preform any regulator specific init */ Loading Loading @@ -2672,6 +2701,7 @@ unset_supplies: unset_regulator_supplies(rdev); scrub: kfree(rdev->constraints); device_unregister(&rdev->dev); /* device core frees rdev */ rdev = ERR_PTR(ret); Loading Loading @@ -2703,7 +2733,7 @@ void regulator_unregister(struct regulator_dev *rdev) unset_regulator_supplies(rdev); list_del(&rdev->list); if (rdev->supply) sysfs_remove_link(&rdev->dev.kobj, "supply"); regulator_put(rdev->supply); device_unregister(&rdev->dev); kfree(rdev->constraints); mutex_unlock(®ulator_list_mutex); Loading drivers/regulator/dummy.c +26 −6 Original line number Diff line number Diff line Loading @@ -36,6 +36,29 @@ static struct regulator_desc dummy_desc = { .ops = &dummy_ops, }; static int __devinit dummy_regulator_probe(struct platform_device *pdev) { int ret; dummy_regulator_rdev = regulator_register(&dummy_desc, NULL, &dummy_initdata, NULL); if (IS_ERR(dummy_regulator_rdev)) { ret = PTR_ERR(dummy_regulator_rdev); pr_err("Failed to register regulator: %d\n", ret); return ret; } return 0; } static struct platform_driver dummy_regulator_driver = { .probe = dummy_regulator_probe, .driver = { .name = "reg-dummy", .owner = THIS_MODULE, }, }; static struct platform_device *dummy_pdev; void __init regulator_dummy_init(void) Loading @@ -55,12 +78,9 @@ void __init regulator_dummy_init(void) return; } dummy_regulator_rdev = regulator_register(&dummy_desc, NULL, &dummy_initdata, NULL); if (IS_ERR(dummy_regulator_rdev)) { ret = PTR_ERR(dummy_regulator_rdev); pr_err("Failed to register regulator: %d\n", ret); ret = platform_driver_register(&dummy_regulator_driver); if (ret != 0) { pr_err("Failed to register dummy regulator driver: %d\n", ret); platform_device_unregister(dummy_pdev); return; } } drivers/regulator/tps65910-regulator.c +51 −12 Original line number Diff line number Diff line Loading @@ -49,7 +49,6 @@ #define TPS65911_REG_LDO7 11 #define TPS65911_REG_LDO8 12 #define TPS65910_NUM_REGULATOR 13 #define TPS65910_SUPPLY_STATE_ENABLED 0x1 /* supported VIO voltages in milivolts */ Loading Loading @@ -264,11 +263,12 @@ static struct tps_info tps65911_regs[] = { }; struct tps65910_reg { struct regulator_desc desc[TPS65910_NUM_REGULATOR]; struct regulator_desc *desc; struct tps65910 *mfd; struct regulator_dev *rdev[TPS65910_NUM_REGULATOR]; struct tps_info *info[TPS65910_NUM_REGULATOR]; struct regulator_dev **rdev; struct tps_info **info; struct mutex mutex; int num_regulators; int mode; int (*get_ctrl_reg)(int); }; Loading Loading @@ -759,8 +759,13 @@ static int tps65910_list_voltage_dcdc(struct regulator_dev *dev, mult = (selector / VDD1_2_NUM_VOLTS) + 1; volt = VDD1_2_MIN_VOLT + (selector % VDD1_2_NUM_VOLTS) * VDD1_2_OFFSET; break; case TPS65911_REG_VDDCTRL: volt = VDDCTRL_MIN_VOLT + (selector * VDDCTRL_OFFSET); break; default: BUG(); return -EINVAL; } return volt * 100 * mult; Loading Loading @@ -897,16 +902,42 @@ static __devinit int tps65910_probe(struct platform_device *pdev) switch(tps65910_chip_id(tps65910)) { case TPS65910: pmic->get_ctrl_reg = &tps65910_get_ctrl_register; pmic->num_regulators = ARRAY_SIZE(tps65910_regs); info = tps65910_regs; break; case TPS65911: pmic->get_ctrl_reg = &tps65911_get_ctrl_register; pmic->num_regulators = ARRAY_SIZE(tps65911_regs); info = tps65911_regs; break; default: pr_err("Invalid tps chip version\n"); kfree(pmic); return -ENODEV; } for (i = 0; i < TPS65910_NUM_REGULATOR; i++, info++, reg_data++) { pmic->desc = kcalloc(pmic->num_regulators, sizeof(struct regulator_desc), GFP_KERNEL); if (!pmic->desc) { err = -ENOMEM; goto err_free_pmic; } pmic->info = kcalloc(pmic->num_regulators, sizeof(struct tps_info *), GFP_KERNEL); if (!pmic->info) { err = -ENOMEM; goto err_free_desc; } pmic->rdev = kcalloc(pmic->num_regulators, sizeof(struct regulator_dev *), GFP_KERNEL); if (!pmic->rdev) { err = -ENOMEM; goto err_free_info; } for (i = 0; i < pmic->num_regulators; i++, info++, reg_data++) { /* Register the regulators */ pmic->info[i] = info; Loading Loading @@ -938,7 +969,7 @@ static __devinit int tps65910_probe(struct platform_device *pdev) "failed to register %s regulator\n", pdev->name); err = PTR_ERR(rdev); goto err; goto err_unregister_regulator; } /* Save regulator for cleanup */ Loading @@ -946,23 +977,31 @@ static __devinit int tps65910_probe(struct platform_device *pdev) } return 0; err: err_unregister_regulator: while (--i >= 0) regulator_unregister(pmic->rdev[i]); kfree(pmic->rdev); err_free_info: kfree(pmic->info); err_free_desc: kfree(pmic->desc); err_free_pmic: kfree(pmic); return err; } static int __devexit tps65910_remove(struct platform_device *pdev) { struct tps65910_reg *tps65910_reg = platform_get_drvdata(pdev); struct tps65910_reg *pmic = platform_get_drvdata(pdev); int i; for (i = 0; i < TPS65910_NUM_REGULATOR; i++) regulator_unregister(tps65910_reg->rdev[i]); for (i = 0; i < pmic->num_regulators; i++) regulator_unregister(pmic->rdev[i]); kfree(tps65910_reg); kfree(pmic->rdev); kfree(pmic->info); kfree(pmic->desc); kfree(pmic); return 0; } Loading drivers/regulator/twl-regulator.c +31 −35 Original line number Diff line number Diff line Loading @@ -835,8 +835,8 @@ static struct regulator_ops twlsmps_ops = { remap_conf) \ TWL_FIXED_LDO(label, offset, mVolts, num, turnon_delay, \ remap_conf, TWL4030, twl4030fixed_ops) #define TWL6030_FIXED_LDO(label, offset, mVolts, num, turnon_delay) \ TWL_FIXED_LDO(label, offset, mVolts, num, turnon_delay, \ #define TWL6030_FIXED_LDO(label, offset, mVolts, turnon_delay) \ TWL_FIXED_LDO(label, offset, mVolts, 0x0, turnon_delay, \ 0x0, TWL6030, twl6030fixed_ops) #define TWL4030_ADJUSTABLE_LDO(label, offset, num, turnon_delay, remap_conf) { \ Loading @@ -856,24 +856,22 @@ static struct regulator_ops twlsmps_ops = { }, \ } #define TWL6030_ADJUSTABLE_LDO(label, offset, min_mVolts, max_mVolts, num) { \ #define TWL6030_ADJUSTABLE_LDO(label, offset, min_mVolts, max_mVolts) { \ .base = offset, \ .id = num, \ .min_mV = min_mVolts, \ .max_mV = max_mVolts, \ .desc = { \ .name = #label, \ .id = TWL6030_REG_##label, \ .n_voltages = (max_mVolts - min_mVolts)/100, \ .n_voltages = (max_mVolts - min_mVolts)/100 + 1, \ .ops = &twl6030ldo_ops, \ .type = REGULATOR_VOLTAGE, \ .owner = THIS_MODULE, \ }, \ } #define TWL6025_ADJUSTABLE_LDO(label, offset, min_mVolts, max_mVolts, num) { \ #define TWL6025_ADJUSTABLE_LDO(label, offset, min_mVolts, max_mVolts) { \ .base = offset, \ .id = num, \ .min_mV = min_mVolts, \ .max_mV = max_mVolts, \ .desc = { \ Loading Loading @@ -903,9 +901,8 @@ static struct regulator_ops twlsmps_ops = { }, \ } #define TWL6030_FIXED_RESOURCE(label, offset, num, turnon_delay) { \ #define TWL6030_FIXED_RESOURCE(label, offset, turnon_delay) { \ .base = offset, \ .id = num, \ .delay = turnon_delay, \ .desc = { \ .name = #label, \ Loading @@ -916,9 +913,8 @@ static struct regulator_ops twlsmps_ops = { }, \ } #define TWL6025_ADJUSTABLE_SMPS(label, offset, num) { \ #define TWL6025_ADJUSTABLE_SMPS(label, offset) { \ .base = offset, \ .id = num, \ .min_mV = 600, \ .max_mV = 2100, \ .desc = { \ Loading Loading @@ -961,32 +957,32 @@ static struct twlreg_info twl_regs[] = { /* 6030 REG with base as PMC Slave Misc : 0x0030 */ /* Turnon-delay and remap configuration values for 6030 are not verified since the specification is not public */ TWL6030_ADJUSTABLE_LDO(VAUX1_6030, 0x54, 1000, 3300, 1), TWL6030_ADJUSTABLE_LDO(VAUX2_6030, 0x58, 1000, 3300, 2), TWL6030_ADJUSTABLE_LDO(VAUX3_6030, 0x5c, 1000, 3300, 3), TWL6030_ADJUSTABLE_LDO(VMMC, 0x68, 1000, 3300, 4), TWL6030_ADJUSTABLE_LDO(VPP, 0x6c, 1000, 3300, 5), TWL6030_ADJUSTABLE_LDO(VUSIM, 0x74, 1000, 3300, 7), TWL6030_FIXED_LDO(VANA, 0x50, 2100, 15, 0), TWL6030_FIXED_LDO(VCXIO, 0x60, 1800, 16, 0), TWL6030_FIXED_LDO(VDAC, 0x64, 1800, 17, 0), TWL6030_FIXED_LDO(VUSB, 0x70, 3300, 18, 0), TWL6030_FIXED_RESOURCE(CLK32KG, 0x8C, 48, 0), TWL6030_ADJUSTABLE_LDO(VAUX1_6030, 0x54, 1000, 3300), TWL6030_ADJUSTABLE_LDO(VAUX2_6030, 0x58, 1000, 3300), TWL6030_ADJUSTABLE_LDO(VAUX3_6030, 0x5c, 1000, 3300), TWL6030_ADJUSTABLE_LDO(VMMC, 0x68, 1000, 3300), TWL6030_ADJUSTABLE_LDO(VPP, 0x6c, 1000, 3300), TWL6030_ADJUSTABLE_LDO(VUSIM, 0x74, 1000, 3300), TWL6030_FIXED_LDO(VANA, 0x50, 2100, 0), TWL6030_FIXED_LDO(VCXIO, 0x60, 1800, 0), TWL6030_FIXED_LDO(VDAC, 0x64, 1800, 0), TWL6030_FIXED_LDO(VUSB, 0x70, 3300, 0), TWL6030_FIXED_RESOURCE(CLK32KG, 0x8C, 0), /* 6025 are renamed compared to 6030 versions */ TWL6025_ADJUSTABLE_LDO(LDO2, 0x54, 1000, 3300, 1), TWL6025_ADJUSTABLE_LDO(LDO4, 0x58, 1000, 3300, 2), TWL6025_ADJUSTABLE_LDO(LDO3, 0x5c, 1000, 3300, 3), TWL6025_ADJUSTABLE_LDO(LDO5, 0x68, 1000, 3300, 4), TWL6025_ADJUSTABLE_LDO(LDO1, 0x6c, 1000, 3300, 5), TWL6025_ADJUSTABLE_LDO(LDO7, 0x74, 1000, 3300, 7), TWL6025_ADJUSTABLE_LDO(LDO6, 0x60, 1000, 3300, 16), TWL6025_ADJUSTABLE_LDO(LDOLN, 0x64, 1000, 3300, 17), TWL6025_ADJUSTABLE_LDO(LDOUSB, 0x70, 1000, 3300, 18), TWL6025_ADJUSTABLE_SMPS(SMPS3, 0x34, 1), TWL6025_ADJUSTABLE_SMPS(SMPS4, 0x10, 2), TWL6025_ADJUSTABLE_SMPS(VIO, 0x16, 3), TWL6025_ADJUSTABLE_LDO(LDO2, 0x54, 1000, 3300), TWL6025_ADJUSTABLE_LDO(LDO4, 0x58, 1000, 3300), TWL6025_ADJUSTABLE_LDO(LDO3, 0x5c, 1000, 3300), TWL6025_ADJUSTABLE_LDO(LDO5, 0x68, 1000, 3300), TWL6025_ADJUSTABLE_LDO(LDO1, 0x6c, 1000, 3300), TWL6025_ADJUSTABLE_LDO(LDO7, 0x74, 1000, 3300), TWL6025_ADJUSTABLE_LDO(LDO6, 0x60, 1000, 3300), TWL6025_ADJUSTABLE_LDO(LDOLN, 0x64, 1000, 3300), TWL6025_ADJUSTABLE_LDO(LDOUSB, 0x70, 1000, 3300), TWL6025_ADJUSTABLE_SMPS(SMPS3, 0x34), TWL6025_ADJUSTABLE_SMPS(SMPS4, 0x10), TWL6025_ADJUSTABLE_SMPS(VIO, 0x16), }; static u8 twl_get_smps_offset(void) Loading drivers/regulator/wm831x-dcdc.c +65 −61 Original line number Diff line number Diff line Loading @@ -267,23 +267,6 @@ static int wm831x_buckv_select_min_voltage(struct regulator_dev *rdev, return vsel; } static int wm831x_buckv_select_max_voltage(struct regulator_dev *rdev, int min_uV, int max_uV) { u16 vsel; if (max_uV < 600000 || max_uV > 1800000) return -EINVAL; vsel = ((max_uV - 600000) / 12500) + 8; if (wm831x_buckv_list_voltage(rdev, vsel) < min_uV || wm831x_buckv_list_voltage(rdev, vsel) < max_uV) return -EINVAL; return vsel; } static int wm831x_buckv_set_dvs(struct regulator_dev *rdev, int state) { struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev); Loading Loading @@ -338,27 +321,22 @@ static int wm831x_buckv_set_voltage(struct regulator_dev *rdev, if (ret < 0) return ret; /* Set the high voltage as the DVS voltage. This is optimised * for CPUfreq usage, most processors will keep the maximum * voltage constant and lower the minimum with the frequency. */ vsel = wm831x_buckv_select_max_voltage(rdev, min_uV, max_uV); if (vsel < 0) { /* This should never happen - at worst the same vsel * should be chosen */ WARN_ON(vsel < 0); return 0; } /* Don't bother if it's the same VSEL we're already using */ if (vsel == dcdc->on_vsel) return 0; ret = wm831x_set_bits(wm831x, dvs_reg, WM831X_DC1_DVS_VSEL_MASK, vsel); /* * If this VSEL is higher than the last one we've seen then * remember it as the DVS VSEL. This is optimised for CPUfreq * usage where we want to get to the highest voltage very * quickly. */ if (vsel > dcdc->dvs_vsel) { ret = wm831x_set_bits(wm831x, dvs_reg, WM831X_DC1_DVS_VSEL_MASK, dcdc->dvs_vsel); if (ret == 0) dcdc->dvs_vsel = vsel; else dev_warn(wm831x->dev, "Failed to set DCDC DVS VSEL: %d\n", ret); dev_warn(wm831x->dev, "Failed to set DCDC DVS VSEL: %d\n", ret); } return 0; } Loading Loading @@ -456,27 +434,6 @@ static __devinit void wm831x_buckv_dvs_init(struct wm831x_dcdc *dcdc, if (!pdata || !pdata->dvs_gpio) return; switch (pdata->dvs_control_src) { case 1: ctrl = 2 << WM831X_DC1_DVS_SRC_SHIFT; break; case 2: ctrl = 3 << WM831X_DC1_DVS_SRC_SHIFT; break; default: dev_err(wm831x->dev, "Invalid DVS control source %d for %s\n", pdata->dvs_control_src, dcdc->name); return; } ret = wm831x_set_bits(wm831x, dcdc->base + WM831X_DCDC_DVS_CONTROL, WM831X_DC1_DVS_SRC_MASK, ctrl); if (ret < 0) { dev_err(wm831x->dev, "Failed to set %s DVS source: %d\n", dcdc->name, ret); return; } ret = gpio_request(pdata->dvs_gpio, "DCDC DVS"); if (ret < 0) { dev_err(wm831x->dev, "Failed to get %s DVS GPIO: %d\n", Loading @@ -498,17 +455,57 @@ static __devinit void wm831x_buckv_dvs_init(struct wm831x_dcdc *dcdc, } dcdc->dvs_gpio = pdata->dvs_gpio; switch (pdata->dvs_control_src) { case 1: ctrl = 2 << WM831X_DC1_DVS_SRC_SHIFT; break; case 2: ctrl = 3 << WM831X_DC1_DVS_SRC_SHIFT; break; default: dev_err(wm831x->dev, "Invalid DVS control source %d for %s\n", pdata->dvs_control_src, dcdc->name); return; } /* If DVS_VSEL is set to the minimum value then raise it to ON_VSEL * to make bootstrapping a bit smoother. */ if (!dcdc->dvs_vsel) { ret = wm831x_set_bits(wm831x, dcdc->base + WM831X_DCDC_DVS_CONTROL, WM831X_DC1_DVS_VSEL_MASK, dcdc->on_vsel); if (ret == 0) dcdc->dvs_vsel = dcdc->on_vsel; else dev_warn(wm831x->dev, "Failed to set DVS_VSEL: %d\n", ret); } ret = wm831x_set_bits(wm831x, dcdc->base + WM831X_DCDC_DVS_CONTROL, WM831X_DC1_DVS_SRC_MASK, ctrl); if (ret < 0) { dev_err(wm831x->dev, "Failed to set %s DVS source: %d\n", dcdc->name, ret); } } static __devinit int wm831x_buckv_probe(struct platform_device *pdev) { struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent); struct wm831x_pdata *pdata = wm831x->dev->platform_data; int id = pdev->id % ARRAY_SIZE(pdata->dcdc); int id; struct wm831x_dcdc *dcdc; struct resource *res; int ret, irq; if (pdata && pdata->wm831x_num) id = (pdata->wm831x_num * 10) + 1; else id = 0; id = pdev->id - id; dev_dbg(&pdev->dev, "Probing DCDC%d\n", id + 1); if (pdata == NULL || pdata->dcdc[id] == NULL) Loading Loading @@ -545,7 +542,7 @@ static __devinit int wm831x_buckv_probe(struct platform_device *pdev) } dcdc->on_vsel = ret & WM831X_DC1_ON_VSEL_MASK; ret = wm831x_reg_read(wm831x, dcdc->base + WM831X_DCDC_ON_CONFIG); ret = wm831x_reg_read(wm831x, dcdc->base + WM831X_DCDC_DVS_CONTROL); if (ret < 0) { dev_err(wm831x->dev, "Failed to read DVS VSEL: %d\n", ret); goto err; Loading Loading @@ -709,11 +706,17 @@ static __devinit int wm831x_buckp_probe(struct platform_device *pdev) { struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent); struct wm831x_pdata *pdata = wm831x->dev->platform_data; int id = pdev->id % ARRAY_SIZE(pdata->dcdc); int id; struct wm831x_dcdc *dcdc; struct resource *res; int ret, irq; if (pdata && pdata->wm831x_num) id = (pdata->wm831x_num * 10) + 1; else id = 0; id = pdev->id - id; dev_dbg(&pdev->dev, "Probing DCDC%d\n", id + 1); if (pdata == NULL || pdata->dcdc[id] == NULL) Loading Loading @@ -1046,3 +1049,4 @@ MODULE_DESCRIPTION("WM831x DC-DC convertor driver"); MODULE_LICENSE("GPL"); MODULE_ALIAS("platform:wm831x-buckv"); MODULE_ALIAS("platform:wm831x-buckp"); MODULE_ALIAS("platform:wm831x-epe"); Loading
drivers/regulator/core.c +110 −80 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ #include <linux/debugfs.h> #include <linux/device.h> #include <linux/slab.h> #include <linux/async.h> #include <linux/err.h> #include <linux/mutex.h> #include <linux/suspend.h> Loading @@ -33,6 +34,8 @@ #include "dummy.h" #define rdev_crit(rdev, fmt, ...) \ pr_crit("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__) #define rdev_err(rdev, fmt, ...) \ pr_err("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__) #define rdev_warn(rdev, fmt, ...) \ Loading Loading @@ -78,11 +81,13 @@ struct regulator { char *supply_name; struct device_attribute dev_attr; struct regulator_dev *rdev; #ifdef CONFIG_DEBUG_FS struct dentry *debugfs; #endif }; static int _regulator_is_enabled(struct regulator_dev *rdev); static int _regulator_disable(struct regulator_dev *rdev, struct regulator_dev **supply_rdev_ptr); static int _regulator_disable(struct regulator_dev *rdev); static int _regulator_get_voltage(struct regulator_dev *rdev); static int _regulator_get_current_limit(struct regulator_dev *rdev); static unsigned int _regulator_get_mode(struct regulator_dev *rdev); Loading @@ -90,6 +95,9 @@ static void _notifier_call_chain(struct regulator_dev *rdev, unsigned long event, void *data); static int _regulator_do_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV); static struct regulator *create_regulator(struct regulator_dev *rdev, struct device *dev, const char *supply_name); static const char *rdev_get_name(struct regulator_dev *rdev) { Loading Loading @@ -143,8 +151,11 @@ static int regulator_check_voltage(struct regulator_dev *rdev, if (*min_uV < rdev->constraints->min_uV) *min_uV = rdev->constraints->min_uV; if (*min_uV > *max_uV) if (*min_uV > *max_uV) { rdev_err(rdev, "unsupportable voltage range: %d-%duV\n", *min_uV, *max_uV); return -EINVAL; } return 0; } Loading Loading @@ -197,8 +208,11 @@ static int regulator_check_current_limit(struct regulator_dev *rdev, if (*min_uA < rdev->constraints->min_uA) *min_uA = rdev->constraints->min_uA; if (*min_uA > *max_uA) if (*min_uA > *max_uA) { rdev_err(rdev, "unsupportable current range: %d-%duA\n", *min_uA, *max_uA); return -EINVAL; } return 0; } Loading @@ -213,6 +227,7 @@ static int regulator_mode_constrain(struct regulator_dev *rdev, int *mode) case REGULATOR_MODE_STANDBY: break; default: rdev_err(rdev, "invalid mode %x specified\n", *mode); return -EINVAL; } Loading Loading @@ -779,7 +794,6 @@ static int machine_constraints_voltage(struct regulator_dev *rdev, if (ret < 0) { rdev_err(rdev, "failed to apply %duV constraint\n", rdev->constraints->min_uV); rdev->constraints = NULL; return ret; } } Loading Loading @@ -882,7 +896,6 @@ static int set_machine_constraints(struct regulator_dev *rdev, ret = suspend_prepare(rdev, rdev->constraints->initial_state); if (ret < 0) { rdev_err(rdev, "failed to set suspend state\n"); rdev->constraints = NULL; goto out; } } Loading @@ -909,13 +922,15 @@ static int set_machine_constraints(struct regulator_dev *rdev, ret = ops->enable(rdev); if (ret < 0) { rdev_err(rdev, "failed to enable\n"); rdev->constraints = NULL; goto out; } } print_constraints(rdev); return 0; out: kfree(rdev->constraints); rdev->constraints = NULL; return ret; } Loading @@ -933,19 +948,18 @@ static int set_supply(struct regulator_dev *rdev, { int err; err = sysfs_create_link(&rdev->dev.kobj, &supply_rdev->dev.kobj, "supply"); if (err) { rdev_err(rdev, "could not add device link %s err %d\n", supply_rdev->dev.kobj.name, err); goto out; } rdev->supply = supply_rdev; list_add(&rdev->slist, &supply_rdev->supply_list); out: rdev_info(rdev, "supplied by %s\n", rdev_get_name(supply_rdev)); rdev->supply = create_regulator(supply_rdev, &rdev->dev, "SUPPLY"); if (IS_ERR(rdev->supply)) { err = PTR_ERR(rdev->supply); rdev->supply = NULL; return err; } return 0; } /** * set_consumer_device_supply - Bind a regulator to a symbolic supply * @rdev: regulator source Loading Loading @@ -1032,7 +1046,7 @@ static void unset_regulator_supplies(struct regulator_dev *rdev) } } #define REG_STR_SIZE 32 #define REG_STR_SIZE 64 static struct regulator *create_regulator(struct regulator_dev *rdev, struct device *dev, Loading @@ -1052,8 +1066,9 @@ static struct regulator *create_regulator(struct regulator_dev *rdev, if (dev) { /* create a 'requested_microamps_name' sysfs entry */ size = scnprintf(buf, REG_STR_SIZE, "microamps_requested_%s", supply_name); size = scnprintf(buf, REG_STR_SIZE, "microamps_requested_%s-%s", dev_name(dev), supply_name); if (size >= REG_STR_SIZE) goto overflow_err; Loading Loading @@ -1088,7 +1103,28 @@ static struct regulator *create_regulator(struct regulator_dev *rdev, dev->kobj.name, err); goto link_name_err; } } else { regulator->supply_name = kstrdup(supply_name, GFP_KERNEL); if (regulator->supply_name == NULL) goto attr_err; } #ifdef CONFIG_DEBUG_FS regulator->debugfs = debugfs_create_dir(regulator->supply_name, rdev->debugfs); if (IS_ERR_OR_NULL(regulator->debugfs)) { rdev_warn(rdev, "Failed to create debugfs directory\n"); regulator->debugfs = NULL; } else { debugfs_create_u32("uA_load", 0444, regulator->debugfs, ®ulator->uA_load); debugfs_create_u32("min_uV", 0444, regulator->debugfs, ®ulator->min_uV); debugfs_create_u32("max_uV", 0444, regulator->debugfs, ®ulator->max_uV); } #endif mutex_unlock(&rdev->mutex); return regulator; link_name_err: Loading Loading @@ -1267,13 +1303,17 @@ void regulator_put(struct regulator *regulator) mutex_lock(®ulator_list_mutex); rdev = regulator->rdev; #ifdef CONFIG_DEBUG_FS debugfs_remove_recursive(regulator->debugfs); #endif /* remove any sysfs entries */ if (regulator->dev) { sysfs_remove_link(&rdev->dev.kobj, regulator->supply_name); kfree(regulator->supply_name); device_remove_file(regulator->dev, ®ulator->dev_attr); kfree(regulator->dev_attr.attr.name); } kfree(regulator->supply_name); list_del(®ulator->list); kfree(regulator); Loading Loading @@ -1301,19 +1341,6 @@ static int _regulator_enable(struct regulator_dev *rdev) { int ret, delay; if (rdev->use_count == 0) { /* do we need to enable the supply regulator first */ if (rdev->supply) { mutex_lock(&rdev->supply->mutex); ret = _regulator_enable(rdev->supply); mutex_unlock(&rdev->supply->mutex); if (ret < 0) { rdev_err(rdev, "failed to enable: %d\n", ret); return ret; } } } /* check voltage and requested load before enabling */ if (rdev->constraints && (rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_DRMS)) Loading Loading @@ -1388,19 +1415,27 @@ int regulator_enable(struct regulator *regulator) struct regulator_dev *rdev = regulator->rdev; int ret = 0; if (rdev->supply) { ret = regulator_enable(rdev->supply); if (ret != 0) return ret; } mutex_lock(&rdev->mutex); ret = _regulator_enable(rdev); mutex_unlock(&rdev->mutex); if (ret != 0) regulator_disable(rdev->supply); return ret; } EXPORT_SYMBOL_GPL(regulator_enable); /* locks held by regulator_disable() */ static int _regulator_disable(struct regulator_dev *rdev, struct regulator_dev **supply_rdev_ptr) static int _regulator_disable(struct regulator_dev *rdev) { int ret = 0; *supply_rdev_ptr = NULL; if (WARN(rdev->use_count <= 0, "unbalanced disables for %s\n", rdev_get_name(rdev))) Loading @@ -1427,9 +1462,6 @@ static int _regulator_disable(struct regulator_dev *rdev, NULL); } /* decrease our supplies ref count and disable if required */ *supply_rdev_ptr = rdev->supply; rdev->use_count = 0; } else if (rdev->use_count > 1) { Loading @@ -1440,6 +1472,7 @@ static int _regulator_disable(struct regulator_dev *rdev, rdev->use_count--; } return ret; } Loading @@ -1458,29 +1491,21 @@ static int _regulator_disable(struct regulator_dev *rdev, int regulator_disable(struct regulator *regulator) { struct regulator_dev *rdev = regulator->rdev; struct regulator_dev *supply_rdev = NULL; int ret = 0; mutex_lock(&rdev->mutex); ret = _regulator_disable(rdev, &supply_rdev); ret = _regulator_disable(rdev); mutex_unlock(&rdev->mutex); /* decrease our supplies ref count and disable if required */ while (supply_rdev != NULL) { rdev = supply_rdev; mutex_lock(&rdev->mutex); _regulator_disable(rdev, &supply_rdev); mutex_unlock(&rdev->mutex); } if (ret == 0 && rdev->supply) regulator_disable(rdev->supply); return ret; } EXPORT_SYMBOL_GPL(regulator_disable); /* locks held by regulator_force_disable() */ static int _regulator_force_disable(struct regulator_dev *rdev, struct regulator_dev **supply_rdev_ptr) static int _regulator_force_disable(struct regulator_dev *rdev) { int ret = 0; Loading @@ -1497,10 +1522,6 @@ static int _regulator_force_disable(struct regulator_dev *rdev, REGULATOR_EVENT_DISABLE, NULL); } /* decrease our supplies ref count and disable if required */ *supply_rdev_ptr = rdev->supply; rdev->use_count = 0; return ret; } Loading @@ -1516,16 +1537,16 @@ static int _regulator_force_disable(struct regulator_dev *rdev, int regulator_force_disable(struct regulator *regulator) { struct regulator_dev *rdev = regulator->rdev; struct regulator_dev *supply_rdev = NULL; int ret; mutex_lock(&rdev->mutex); regulator->uA_load = 0; ret = _regulator_force_disable(rdev, &supply_rdev); ret = _regulator_force_disable(regulator->rdev); mutex_unlock(&rdev->mutex); if (supply_rdev) regulator_disable(get_device_regulator(rdev_get_dev(supply_rdev))); if (rdev->supply) while (rdev->open_count--) regulator_disable(rdev->supply); return ret; } Loading Loading @@ -2136,7 +2157,7 @@ int regulator_set_optimum_mode(struct regulator *regulator, int uA_load) /* get input voltage */ input_uV = 0; if (rdev->supply) input_uV = _regulator_get_voltage(rdev->supply); input_uV = regulator_get_voltage(rdev->supply); if (input_uV <= 0) input_uV = rdev->constraints->input_uV; if (input_uV <= 0) { Loading Loading @@ -2206,17 +2227,8 @@ EXPORT_SYMBOL_GPL(regulator_unregister_notifier); static void _notifier_call_chain(struct regulator_dev *rdev, unsigned long event, void *data) { struct regulator_dev *_rdev; /* call rdev chain first */ blocking_notifier_call_chain(&rdev->notifier, event, NULL); /* now notify regulator we supply */ list_for_each_entry(_rdev, &rdev->supply_list, slist) { mutex_lock(&_rdev->mutex); _notifier_call_chain(_rdev, event, data); mutex_unlock(&_rdev->mutex); } } /** Loading Loading @@ -2264,6 +2276,13 @@ err: } EXPORT_SYMBOL_GPL(regulator_bulk_get); static void regulator_bulk_enable_async(void *data, async_cookie_t cookie) { struct regulator_bulk_data *bulk = data; bulk->ret = regulator_enable(bulk->consumer); } /** * regulator_bulk_enable - enable multiple regulator consumers * Loading @@ -2279,21 +2298,33 @@ EXPORT_SYMBOL_GPL(regulator_bulk_get); int regulator_bulk_enable(int num_consumers, struct regulator_bulk_data *consumers) { LIST_HEAD(async_domain); int i; int ret; int ret = 0; for (i = 0; i < num_consumers; i++) async_schedule_domain(regulator_bulk_enable_async, &consumers[i], &async_domain); async_synchronize_full_domain(&async_domain); /* If any consumer failed we need to unwind any that succeeded */ for (i = 0; i < num_consumers; i++) { ret = regulator_enable(consumers[i].consumer); if (ret != 0) if (consumers[i].ret != 0) { ret = consumers[i].ret; goto err; } } return 0; err: pr_err("Failed to enable %s: %d\n", consumers[i].supply, ret); for (--i; i >= 0; --i) for (i = 0; i < num_consumers; i++) if (consumers[i].ret == 0) regulator_disable(consumers[i].consumer); else pr_err("Failed to enable %s: %d\n", consumers[i].supply, consumers[i].ret); return ret; } Loading Loading @@ -2589,9 +2620,7 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc, rdev->owner = regulator_desc->owner; rdev->desc = regulator_desc; INIT_LIST_HEAD(&rdev->consumer_list); INIT_LIST_HEAD(&rdev->supply_list); INIT_LIST_HEAD(&rdev->list); INIT_LIST_HEAD(&rdev->slist); BLOCKING_INIT_NOTIFIER_HEAD(&rdev->notifier); /* preform any regulator specific init */ Loading Loading @@ -2672,6 +2701,7 @@ unset_supplies: unset_regulator_supplies(rdev); scrub: kfree(rdev->constraints); device_unregister(&rdev->dev); /* device core frees rdev */ rdev = ERR_PTR(ret); Loading Loading @@ -2703,7 +2733,7 @@ void regulator_unregister(struct regulator_dev *rdev) unset_regulator_supplies(rdev); list_del(&rdev->list); if (rdev->supply) sysfs_remove_link(&rdev->dev.kobj, "supply"); regulator_put(rdev->supply); device_unregister(&rdev->dev); kfree(rdev->constraints); mutex_unlock(®ulator_list_mutex); Loading
drivers/regulator/dummy.c +26 −6 Original line number Diff line number Diff line Loading @@ -36,6 +36,29 @@ static struct regulator_desc dummy_desc = { .ops = &dummy_ops, }; static int __devinit dummy_regulator_probe(struct platform_device *pdev) { int ret; dummy_regulator_rdev = regulator_register(&dummy_desc, NULL, &dummy_initdata, NULL); if (IS_ERR(dummy_regulator_rdev)) { ret = PTR_ERR(dummy_regulator_rdev); pr_err("Failed to register regulator: %d\n", ret); return ret; } return 0; } static struct platform_driver dummy_regulator_driver = { .probe = dummy_regulator_probe, .driver = { .name = "reg-dummy", .owner = THIS_MODULE, }, }; static struct platform_device *dummy_pdev; void __init regulator_dummy_init(void) Loading @@ -55,12 +78,9 @@ void __init regulator_dummy_init(void) return; } dummy_regulator_rdev = regulator_register(&dummy_desc, NULL, &dummy_initdata, NULL); if (IS_ERR(dummy_regulator_rdev)) { ret = PTR_ERR(dummy_regulator_rdev); pr_err("Failed to register regulator: %d\n", ret); ret = platform_driver_register(&dummy_regulator_driver); if (ret != 0) { pr_err("Failed to register dummy regulator driver: %d\n", ret); platform_device_unregister(dummy_pdev); return; } }
drivers/regulator/tps65910-regulator.c +51 −12 Original line number Diff line number Diff line Loading @@ -49,7 +49,6 @@ #define TPS65911_REG_LDO7 11 #define TPS65911_REG_LDO8 12 #define TPS65910_NUM_REGULATOR 13 #define TPS65910_SUPPLY_STATE_ENABLED 0x1 /* supported VIO voltages in milivolts */ Loading Loading @@ -264,11 +263,12 @@ static struct tps_info tps65911_regs[] = { }; struct tps65910_reg { struct regulator_desc desc[TPS65910_NUM_REGULATOR]; struct regulator_desc *desc; struct tps65910 *mfd; struct regulator_dev *rdev[TPS65910_NUM_REGULATOR]; struct tps_info *info[TPS65910_NUM_REGULATOR]; struct regulator_dev **rdev; struct tps_info **info; struct mutex mutex; int num_regulators; int mode; int (*get_ctrl_reg)(int); }; Loading Loading @@ -759,8 +759,13 @@ static int tps65910_list_voltage_dcdc(struct regulator_dev *dev, mult = (selector / VDD1_2_NUM_VOLTS) + 1; volt = VDD1_2_MIN_VOLT + (selector % VDD1_2_NUM_VOLTS) * VDD1_2_OFFSET; break; case TPS65911_REG_VDDCTRL: volt = VDDCTRL_MIN_VOLT + (selector * VDDCTRL_OFFSET); break; default: BUG(); return -EINVAL; } return volt * 100 * mult; Loading Loading @@ -897,16 +902,42 @@ static __devinit int tps65910_probe(struct platform_device *pdev) switch(tps65910_chip_id(tps65910)) { case TPS65910: pmic->get_ctrl_reg = &tps65910_get_ctrl_register; pmic->num_regulators = ARRAY_SIZE(tps65910_regs); info = tps65910_regs; break; case TPS65911: pmic->get_ctrl_reg = &tps65911_get_ctrl_register; pmic->num_regulators = ARRAY_SIZE(tps65911_regs); info = tps65911_regs; break; default: pr_err("Invalid tps chip version\n"); kfree(pmic); return -ENODEV; } for (i = 0; i < TPS65910_NUM_REGULATOR; i++, info++, reg_data++) { pmic->desc = kcalloc(pmic->num_regulators, sizeof(struct regulator_desc), GFP_KERNEL); if (!pmic->desc) { err = -ENOMEM; goto err_free_pmic; } pmic->info = kcalloc(pmic->num_regulators, sizeof(struct tps_info *), GFP_KERNEL); if (!pmic->info) { err = -ENOMEM; goto err_free_desc; } pmic->rdev = kcalloc(pmic->num_regulators, sizeof(struct regulator_dev *), GFP_KERNEL); if (!pmic->rdev) { err = -ENOMEM; goto err_free_info; } for (i = 0; i < pmic->num_regulators; i++, info++, reg_data++) { /* Register the regulators */ pmic->info[i] = info; Loading Loading @@ -938,7 +969,7 @@ static __devinit int tps65910_probe(struct platform_device *pdev) "failed to register %s regulator\n", pdev->name); err = PTR_ERR(rdev); goto err; goto err_unregister_regulator; } /* Save regulator for cleanup */ Loading @@ -946,23 +977,31 @@ static __devinit int tps65910_probe(struct platform_device *pdev) } return 0; err: err_unregister_regulator: while (--i >= 0) regulator_unregister(pmic->rdev[i]); kfree(pmic->rdev); err_free_info: kfree(pmic->info); err_free_desc: kfree(pmic->desc); err_free_pmic: kfree(pmic); return err; } static int __devexit tps65910_remove(struct platform_device *pdev) { struct tps65910_reg *tps65910_reg = platform_get_drvdata(pdev); struct tps65910_reg *pmic = platform_get_drvdata(pdev); int i; for (i = 0; i < TPS65910_NUM_REGULATOR; i++) regulator_unregister(tps65910_reg->rdev[i]); for (i = 0; i < pmic->num_regulators; i++) regulator_unregister(pmic->rdev[i]); kfree(tps65910_reg); kfree(pmic->rdev); kfree(pmic->info); kfree(pmic->desc); kfree(pmic); return 0; } Loading
drivers/regulator/twl-regulator.c +31 −35 Original line number Diff line number Diff line Loading @@ -835,8 +835,8 @@ static struct regulator_ops twlsmps_ops = { remap_conf) \ TWL_FIXED_LDO(label, offset, mVolts, num, turnon_delay, \ remap_conf, TWL4030, twl4030fixed_ops) #define TWL6030_FIXED_LDO(label, offset, mVolts, num, turnon_delay) \ TWL_FIXED_LDO(label, offset, mVolts, num, turnon_delay, \ #define TWL6030_FIXED_LDO(label, offset, mVolts, turnon_delay) \ TWL_FIXED_LDO(label, offset, mVolts, 0x0, turnon_delay, \ 0x0, TWL6030, twl6030fixed_ops) #define TWL4030_ADJUSTABLE_LDO(label, offset, num, turnon_delay, remap_conf) { \ Loading @@ -856,24 +856,22 @@ static struct regulator_ops twlsmps_ops = { }, \ } #define TWL6030_ADJUSTABLE_LDO(label, offset, min_mVolts, max_mVolts, num) { \ #define TWL6030_ADJUSTABLE_LDO(label, offset, min_mVolts, max_mVolts) { \ .base = offset, \ .id = num, \ .min_mV = min_mVolts, \ .max_mV = max_mVolts, \ .desc = { \ .name = #label, \ .id = TWL6030_REG_##label, \ .n_voltages = (max_mVolts - min_mVolts)/100, \ .n_voltages = (max_mVolts - min_mVolts)/100 + 1, \ .ops = &twl6030ldo_ops, \ .type = REGULATOR_VOLTAGE, \ .owner = THIS_MODULE, \ }, \ } #define TWL6025_ADJUSTABLE_LDO(label, offset, min_mVolts, max_mVolts, num) { \ #define TWL6025_ADJUSTABLE_LDO(label, offset, min_mVolts, max_mVolts) { \ .base = offset, \ .id = num, \ .min_mV = min_mVolts, \ .max_mV = max_mVolts, \ .desc = { \ Loading Loading @@ -903,9 +901,8 @@ static struct regulator_ops twlsmps_ops = { }, \ } #define TWL6030_FIXED_RESOURCE(label, offset, num, turnon_delay) { \ #define TWL6030_FIXED_RESOURCE(label, offset, turnon_delay) { \ .base = offset, \ .id = num, \ .delay = turnon_delay, \ .desc = { \ .name = #label, \ Loading @@ -916,9 +913,8 @@ static struct regulator_ops twlsmps_ops = { }, \ } #define TWL6025_ADJUSTABLE_SMPS(label, offset, num) { \ #define TWL6025_ADJUSTABLE_SMPS(label, offset) { \ .base = offset, \ .id = num, \ .min_mV = 600, \ .max_mV = 2100, \ .desc = { \ Loading Loading @@ -961,32 +957,32 @@ static struct twlreg_info twl_regs[] = { /* 6030 REG with base as PMC Slave Misc : 0x0030 */ /* Turnon-delay and remap configuration values for 6030 are not verified since the specification is not public */ TWL6030_ADJUSTABLE_LDO(VAUX1_6030, 0x54, 1000, 3300, 1), TWL6030_ADJUSTABLE_LDO(VAUX2_6030, 0x58, 1000, 3300, 2), TWL6030_ADJUSTABLE_LDO(VAUX3_6030, 0x5c, 1000, 3300, 3), TWL6030_ADJUSTABLE_LDO(VMMC, 0x68, 1000, 3300, 4), TWL6030_ADJUSTABLE_LDO(VPP, 0x6c, 1000, 3300, 5), TWL6030_ADJUSTABLE_LDO(VUSIM, 0x74, 1000, 3300, 7), TWL6030_FIXED_LDO(VANA, 0x50, 2100, 15, 0), TWL6030_FIXED_LDO(VCXIO, 0x60, 1800, 16, 0), TWL6030_FIXED_LDO(VDAC, 0x64, 1800, 17, 0), TWL6030_FIXED_LDO(VUSB, 0x70, 3300, 18, 0), TWL6030_FIXED_RESOURCE(CLK32KG, 0x8C, 48, 0), TWL6030_ADJUSTABLE_LDO(VAUX1_6030, 0x54, 1000, 3300), TWL6030_ADJUSTABLE_LDO(VAUX2_6030, 0x58, 1000, 3300), TWL6030_ADJUSTABLE_LDO(VAUX3_6030, 0x5c, 1000, 3300), TWL6030_ADJUSTABLE_LDO(VMMC, 0x68, 1000, 3300), TWL6030_ADJUSTABLE_LDO(VPP, 0x6c, 1000, 3300), TWL6030_ADJUSTABLE_LDO(VUSIM, 0x74, 1000, 3300), TWL6030_FIXED_LDO(VANA, 0x50, 2100, 0), TWL6030_FIXED_LDO(VCXIO, 0x60, 1800, 0), TWL6030_FIXED_LDO(VDAC, 0x64, 1800, 0), TWL6030_FIXED_LDO(VUSB, 0x70, 3300, 0), TWL6030_FIXED_RESOURCE(CLK32KG, 0x8C, 0), /* 6025 are renamed compared to 6030 versions */ TWL6025_ADJUSTABLE_LDO(LDO2, 0x54, 1000, 3300, 1), TWL6025_ADJUSTABLE_LDO(LDO4, 0x58, 1000, 3300, 2), TWL6025_ADJUSTABLE_LDO(LDO3, 0x5c, 1000, 3300, 3), TWL6025_ADJUSTABLE_LDO(LDO5, 0x68, 1000, 3300, 4), TWL6025_ADJUSTABLE_LDO(LDO1, 0x6c, 1000, 3300, 5), TWL6025_ADJUSTABLE_LDO(LDO7, 0x74, 1000, 3300, 7), TWL6025_ADJUSTABLE_LDO(LDO6, 0x60, 1000, 3300, 16), TWL6025_ADJUSTABLE_LDO(LDOLN, 0x64, 1000, 3300, 17), TWL6025_ADJUSTABLE_LDO(LDOUSB, 0x70, 1000, 3300, 18), TWL6025_ADJUSTABLE_SMPS(SMPS3, 0x34, 1), TWL6025_ADJUSTABLE_SMPS(SMPS4, 0x10, 2), TWL6025_ADJUSTABLE_SMPS(VIO, 0x16, 3), TWL6025_ADJUSTABLE_LDO(LDO2, 0x54, 1000, 3300), TWL6025_ADJUSTABLE_LDO(LDO4, 0x58, 1000, 3300), TWL6025_ADJUSTABLE_LDO(LDO3, 0x5c, 1000, 3300), TWL6025_ADJUSTABLE_LDO(LDO5, 0x68, 1000, 3300), TWL6025_ADJUSTABLE_LDO(LDO1, 0x6c, 1000, 3300), TWL6025_ADJUSTABLE_LDO(LDO7, 0x74, 1000, 3300), TWL6025_ADJUSTABLE_LDO(LDO6, 0x60, 1000, 3300), TWL6025_ADJUSTABLE_LDO(LDOLN, 0x64, 1000, 3300), TWL6025_ADJUSTABLE_LDO(LDOUSB, 0x70, 1000, 3300), TWL6025_ADJUSTABLE_SMPS(SMPS3, 0x34), TWL6025_ADJUSTABLE_SMPS(SMPS4, 0x10), TWL6025_ADJUSTABLE_SMPS(VIO, 0x16), }; static u8 twl_get_smps_offset(void) Loading
drivers/regulator/wm831x-dcdc.c +65 −61 Original line number Diff line number Diff line Loading @@ -267,23 +267,6 @@ static int wm831x_buckv_select_min_voltage(struct regulator_dev *rdev, return vsel; } static int wm831x_buckv_select_max_voltage(struct regulator_dev *rdev, int min_uV, int max_uV) { u16 vsel; if (max_uV < 600000 || max_uV > 1800000) return -EINVAL; vsel = ((max_uV - 600000) / 12500) + 8; if (wm831x_buckv_list_voltage(rdev, vsel) < min_uV || wm831x_buckv_list_voltage(rdev, vsel) < max_uV) return -EINVAL; return vsel; } static int wm831x_buckv_set_dvs(struct regulator_dev *rdev, int state) { struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev); Loading Loading @@ -338,27 +321,22 @@ static int wm831x_buckv_set_voltage(struct regulator_dev *rdev, if (ret < 0) return ret; /* Set the high voltage as the DVS voltage. This is optimised * for CPUfreq usage, most processors will keep the maximum * voltage constant and lower the minimum with the frequency. */ vsel = wm831x_buckv_select_max_voltage(rdev, min_uV, max_uV); if (vsel < 0) { /* This should never happen - at worst the same vsel * should be chosen */ WARN_ON(vsel < 0); return 0; } /* Don't bother if it's the same VSEL we're already using */ if (vsel == dcdc->on_vsel) return 0; ret = wm831x_set_bits(wm831x, dvs_reg, WM831X_DC1_DVS_VSEL_MASK, vsel); /* * If this VSEL is higher than the last one we've seen then * remember it as the DVS VSEL. This is optimised for CPUfreq * usage where we want to get to the highest voltage very * quickly. */ if (vsel > dcdc->dvs_vsel) { ret = wm831x_set_bits(wm831x, dvs_reg, WM831X_DC1_DVS_VSEL_MASK, dcdc->dvs_vsel); if (ret == 0) dcdc->dvs_vsel = vsel; else dev_warn(wm831x->dev, "Failed to set DCDC DVS VSEL: %d\n", ret); dev_warn(wm831x->dev, "Failed to set DCDC DVS VSEL: %d\n", ret); } return 0; } Loading Loading @@ -456,27 +434,6 @@ static __devinit void wm831x_buckv_dvs_init(struct wm831x_dcdc *dcdc, if (!pdata || !pdata->dvs_gpio) return; switch (pdata->dvs_control_src) { case 1: ctrl = 2 << WM831X_DC1_DVS_SRC_SHIFT; break; case 2: ctrl = 3 << WM831X_DC1_DVS_SRC_SHIFT; break; default: dev_err(wm831x->dev, "Invalid DVS control source %d for %s\n", pdata->dvs_control_src, dcdc->name); return; } ret = wm831x_set_bits(wm831x, dcdc->base + WM831X_DCDC_DVS_CONTROL, WM831X_DC1_DVS_SRC_MASK, ctrl); if (ret < 0) { dev_err(wm831x->dev, "Failed to set %s DVS source: %d\n", dcdc->name, ret); return; } ret = gpio_request(pdata->dvs_gpio, "DCDC DVS"); if (ret < 0) { dev_err(wm831x->dev, "Failed to get %s DVS GPIO: %d\n", Loading @@ -498,17 +455,57 @@ static __devinit void wm831x_buckv_dvs_init(struct wm831x_dcdc *dcdc, } dcdc->dvs_gpio = pdata->dvs_gpio; switch (pdata->dvs_control_src) { case 1: ctrl = 2 << WM831X_DC1_DVS_SRC_SHIFT; break; case 2: ctrl = 3 << WM831X_DC1_DVS_SRC_SHIFT; break; default: dev_err(wm831x->dev, "Invalid DVS control source %d for %s\n", pdata->dvs_control_src, dcdc->name); return; } /* If DVS_VSEL is set to the minimum value then raise it to ON_VSEL * to make bootstrapping a bit smoother. */ if (!dcdc->dvs_vsel) { ret = wm831x_set_bits(wm831x, dcdc->base + WM831X_DCDC_DVS_CONTROL, WM831X_DC1_DVS_VSEL_MASK, dcdc->on_vsel); if (ret == 0) dcdc->dvs_vsel = dcdc->on_vsel; else dev_warn(wm831x->dev, "Failed to set DVS_VSEL: %d\n", ret); } ret = wm831x_set_bits(wm831x, dcdc->base + WM831X_DCDC_DVS_CONTROL, WM831X_DC1_DVS_SRC_MASK, ctrl); if (ret < 0) { dev_err(wm831x->dev, "Failed to set %s DVS source: %d\n", dcdc->name, ret); } } static __devinit int wm831x_buckv_probe(struct platform_device *pdev) { struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent); struct wm831x_pdata *pdata = wm831x->dev->platform_data; int id = pdev->id % ARRAY_SIZE(pdata->dcdc); int id; struct wm831x_dcdc *dcdc; struct resource *res; int ret, irq; if (pdata && pdata->wm831x_num) id = (pdata->wm831x_num * 10) + 1; else id = 0; id = pdev->id - id; dev_dbg(&pdev->dev, "Probing DCDC%d\n", id + 1); if (pdata == NULL || pdata->dcdc[id] == NULL) Loading Loading @@ -545,7 +542,7 @@ static __devinit int wm831x_buckv_probe(struct platform_device *pdev) } dcdc->on_vsel = ret & WM831X_DC1_ON_VSEL_MASK; ret = wm831x_reg_read(wm831x, dcdc->base + WM831X_DCDC_ON_CONFIG); ret = wm831x_reg_read(wm831x, dcdc->base + WM831X_DCDC_DVS_CONTROL); if (ret < 0) { dev_err(wm831x->dev, "Failed to read DVS VSEL: %d\n", ret); goto err; Loading Loading @@ -709,11 +706,17 @@ static __devinit int wm831x_buckp_probe(struct platform_device *pdev) { struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent); struct wm831x_pdata *pdata = wm831x->dev->platform_data; int id = pdev->id % ARRAY_SIZE(pdata->dcdc); int id; struct wm831x_dcdc *dcdc; struct resource *res; int ret, irq; if (pdata && pdata->wm831x_num) id = (pdata->wm831x_num * 10) + 1; else id = 0; id = pdev->id - id; dev_dbg(&pdev->dev, "Probing DCDC%d\n", id + 1); if (pdata == NULL || pdata->dcdc[id] == NULL) Loading Loading @@ -1046,3 +1049,4 @@ MODULE_DESCRIPTION("WM831x DC-DC convertor driver"); MODULE_LICENSE("GPL"); MODULE_ALIAS("platform:wm831x-buckv"); MODULE_ALIAS("platform:wm831x-buckp"); MODULE_ALIAS("platform:wm831x-epe");