aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/regulator
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2015-01-30 14:29:31 -0500
committerMark Brown <broonie@kernel.org>2015-02-02 15:01:51 -0500
commit39f802d6b6d9a922f2c7a9165f0a7a5b819a1e3f (patch)
tree3d98fc2cefaeb33c3208813e64765204d26b6ab8 /drivers/regulator
parent39138818a4f5c62d70f35504477c2509f982f211 (diff)
regulator: Build sysfs entries with static attribute groups
Instead of calling device_create_file() manually after the device registration, put all in attribute groups and filter the unwanted ones via is_visible callback. This not only simplifies the code but also avoids the possible race between the device registration and sysfs registration. Signed-off-by: Takashi Iwai <tiwai@suse.de> Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'drivers/regulator')
-rw-r--r--drivers/regulator/core.c235
1 files changed, 108 insertions, 127 deletions
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index c2554d89d472..91d79b84358b 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -632,30 +632,6 @@ static ssize_t regulator_bypass_show(struct device *dev,
632static DEVICE_ATTR(bypass, 0444, 632static DEVICE_ATTR(bypass, 0444,
633 regulator_bypass_show, NULL); 633 regulator_bypass_show, NULL);
634 634
635/*
636 * These are the only attributes are present for all regulators.
637 * Other attributes are a function of regulator functionality.
638 */
639static struct attribute *regulator_dev_attrs[] = {
640 &dev_attr_name.attr,
641 &dev_attr_num_users.attr,
642 &dev_attr_type.attr,
643 NULL,
644};
645ATTRIBUTE_GROUPS(regulator_dev);
646
647static void regulator_dev_release(struct device *dev)
648{
649 struct regulator_dev *rdev = dev_get_drvdata(dev);
650 kfree(rdev);
651}
652
653static struct class regulator_class = {
654 .name = "regulator",
655 .dev_release = regulator_dev_release,
656 .dev_groups = regulator_dev_groups,
657};
658
659/* Calculate the new optimum regulator operating mode based on the new total 635/* Calculate the new optimum regulator operating mode based on the new total
660 * consumer load. All locks held by caller */ 636 * consumer load. All locks held by caller */
661static void drms_uA_update(struct regulator_dev *rdev) 637static void drms_uA_update(struct regulator_dev *rdev)
@@ -3434,126 +3410,136 @@ int regulator_mode_to_status(unsigned int mode)
3434} 3410}
3435EXPORT_SYMBOL_GPL(regulator_mode_to_status); 3411EXPORT_SYMBOL_GPL(regulator_mode_to_status);
3436 3412
3413static struct attribute *regulator_dev_attrs[] = {
3414 &dev_attr_name.attr,
3415 &dev_attr_num_users.attr,
3416 &dev_attr_type.attr,
3417 &dev_attr_microvolts.attr,
3418 &dev_attr_microamps.attr,
3419 &dev_attr_opmode.attr,
3420 &dev_attr_state.attr,
3421 &dev_attr_status.attr,
3422 &dev_attr_bypass.attr,
3423 &dev_attr_requested_microamps.attr,
3424 &dev_attr_min_microvolts.attr,
3425 &dev_attr_max_microvolts.attr,
3426 &dev_attr_min_microamps.attr,
3427 &dev_attr_max_microamps.attr,
3428 &dev_attr_suspend_standby_state.attr,
3429 &dev_attr_suspend_mem_state.attr,
3430 &dev_attr_suspend_disk_state.attr,
3431 &dev_attr_suspend_standby_microvolts.attr,
3432 &dev_attr_suspend_mem_microvolts.attr,
3433 &dev_attr_suspend_disk_microvolts.attr,
3434 &dev_attr_suspend_standby_mode.attr,
3435 &dev_attr_suspend_mem_mode.attr,
3436 &dev_attr_suspend_disk_mode.attr,
3437 NULL
3438};
3439
3437/* 3440/*
3438 * To avoid cluttering sysfs (and memory) with useless state, only 3441 * To avoid cluttering sysfs (and memory) with useless state, only
3439 * create attributes that can be meaningfully displayed. 3442 * create attributes that can be meaningfully displayed.
3440 */ 3443 */
3441static int add_regulator_attributes(struct regulator_dev *rdev) 3444static umode_t regulator_attr_is_visible(struct kobject *kobj,
3445 struct attribute *attr, int idx)
3442{ 3446{
3443 struct device *dev = &rdev->dev; 3447 struct device *dev = kobj_to_dev(kobj);
3448 struct regulator_dev *rdev = container_of(dev, struct regulator_dev, dev);
3444 const struct regulator_ops *ops = rdev->desc->ops; 3449 const struct regulator_ops *ops = rdev->desc->ops;
3445 int status = 0; 3450 umode_t mode = attr->mode;
3451
3452 /* these three are always present */
3453 if (attr == &dev_attr_name.attr ||
3454 attr == &dev_attr_num_users.attr ||
3455 attr == &dev_attr_type.attr)
3456 return mode;
3446 3457
3447 /* some attributes need specific methods to be displayed */ 3458 /* some attributes need specific methods to be displayed */
3448 if ((ops->get_voltage && ops->get_voltage(rdev) >= 0) || 3459 if (attr == &dev_attr_microvolts.attr) {
3449 (ops->get_voltage_sel && ops->get_voltage_sel(rdev) >= 0) || 3460 if ((ops->get_voltage && ops->get_voltage(rdev) >= 0) ||
3450 (ops->list_voltage && ops->list_voltage(rdev, 0) >= 0) || 3461 (ops->get_voltage_sel && ops->get_voltage_sel(rdev) >= 0) ||
3451 (rdev->desc->fixed_uV && (rdev->desc->n_voltages == 1))) { 3462 (ops->list_voltage && ops->list_voltage(rdev, 0) >= 0) ||
3452 status = device_create_file(dev, &dev_attr_microvolts); 3463 (rdev->desc->fixed_uV && rdev->desc->n_voltages == 1))
3453 if (status < 0) 3464 return mode;
3454 return status; 3465 return 0;
3455 }
3456 if (ops->get_current_limit) {
3457 status = device_create_file(dev, &dev_attr_microamps);
3458 if (status < 0)
3459 return status;
3460 }
3461 if (ops->get_mode) {
3462 status = device_create_file(dev, &dev_attr_opmode);
3463 if (status < 0)
3464 return status;
3465 }
3466 if (rdev->ena_pin || ops->is_enabled) {
3467 status = device_create_file(dev, &dev_attr_state);
3468 if (status < 0)
3469 return status;
3470 }
3471 if (ops->get_status) {
3472 status = device_create_file(dev, &dev_attr_status);
3473 if (status < 0)
3474 return status;
3475 }
3476 if (ops->get_bypass) {
3477 status = device_create_file(dev, &dev_attr_bypass);
3478 if (status < 0)
3479 return status;
3480 } 3466 }
3481 3467
3468 if (attr == &dev_attr_microamps.attr)
3469 return ops->get_current_limit ? mode : 0;
3470
3471 if (attr == &dev_attr_opmode.attr)
3472 return ops->get_mode ? mode : 0;
3473
3474 if (attr == &dev_attr_state.attr)
3475 return (rdev->ena_pin || ops->is_enabled) ? mode : 0;
3476
3477 if (attr == &dev_attr_status.attr)
3478 return ops->get_status ? mode : 0;
3479
3480 if (attr == &dev_attr_bypass.attr)
3481 return ops->get_bypass ? mode : 0;
3482
3482 /* some attributes are type-specific */ 3483 /* some attributes are type-specific */
3483 if (rdev->desc->type == REGULATOR_CURRENT) { 3484 if (attr == &dev_attr_requested_microamps.attr)
3484 status = device_create_file(dev, &dev_attr_requested_microamps); 3485 return rdev->desc->type == REGULATOR_CURRENT ? mode : 0;
3485 if (status < 0)
3486 return status;
3487 }
3488 3486
3489 /* all the other attributes exist to support constraints; 3487 /* all the other attributes exist to support constraints;
3490 * don't show them if there are no constraints, or if the 3488 * don't show them if there are no constraints, or if the
3491 * relevant supporting methods are missing. 3489 * relevant supporting methods are missing.
3492 */ 3490 */
3493 if (!rdev->constraints) 3491 if (!rdev->constraints)
3494 return status; 3492 return 0;
3495 3493
3496 /* constraints need specific supporting methods */ 3494 /* constraints need specific supporting methods */
3497 if (ops->set_voltage || ops->set_voltage_sel) { 3495 if (attr == &dev_attr_min_microvolts.attr ||
3498 status = device_create_file(dev, &dev_attr_min_microvolts); 3496 attr == &dev_attr_max_microvolts.attr)
3499 if (status < 0) 3497 return (ops->set_voltage || ops->set_voltage_sel) ? mode : 0;
3500 return status; 3498
3501 status = device_create_file(dev, &dev_attr_max_microvolts); 3499 if (attr == &dev_attr_min_microamps.attr ||
3502 if (status < 0) 3500 attr == &dev_attr_max_microamps.attr)
3503 return status; 3501 return ops->set_current_limit ? mode : 0;
3504 } 3502
3505 if (ops->set_current_limit) { 3503 if (attr == &dev_attr_suspend_standby_state.attr ||
3506 status = device_create_file(dev, &dev_attr_min_microamps); 3504 attr == &dev_attr_suspend_mem_state.attr ||
3507 if (status < 0) 3505 attr == &dev_attr_suspend_disk_state.attr)
3508 return status; 3506 return mode;
3509 status = device_create_file(dev, &dev_attr_max_microamps); 3507
3510 if (status < 0) 3508 if (attr == &dev_attr_suspend_standby_microvolts.attr ||
3511 return status; 3509 attr == &dev_attr_suspend_mem_microvolts.attr ||
3512 } 3510 attr == &dev_attr_suspend_disk_microvolts.attr)
3513 3511 return ops->set_suspend_voltage ? mode : 0;
3514 status = device_create_file(dev, &dev_attr_suspend_standby_state); 3512
3515 if (status < 0) 3513 if (attr == &dev_attr_suspend_standby_mode.attr ||
3516 return status; 3514 attr == &dev_attr_suspend_mem_mode.attr ||
3517 status = device_create_file(dev, &dev_attr_suspend_mem_state); 3515 attr == &dev_attr_suspend_disk_mode.attr)
3518 if (status < 0) 3516 return ops->set_suspend_mode ? mode : 0;
3519 return status; 3517
3520 status = device_create_file(dev, &dev_attr_suspend_disk_state); 3518 return mode;
3521 if (status < 0) 3519}
3522 return status; 3520
3521static const struct attribute_group regulator_dev_group = {
3522 .attrs = regulator_dev_attrs,
3523 .is_visible = regulator_attr_is_visible,
3524};
3525
3526static const struct attribute_group *regulator_dev_groups[] = {
3527 &regulator_dev_group,
3528 NULL
3529};
3523 3530
3524 if (ops->set_suspend_voltage) { 3531static void regulator_dev_release(struct device *dev)
3525 status = device_create_file(dev, 3532{
3526 &dev_attr_suspend_standby_microvolts); 3533 struct regulator_dev *rdev = dev_get_drvdata(dev);
3527 if (status < 0) 3534 kfree(rdev);
3528 return status;
3529 status = device_create_file(dev,
3530 &dev_attr_suspend_mem_microvolts);
3531 if (status < 0)
3532 return status;
3533 status = device_create_file(dev,
3534 &dev_attr_suspend_disk_microvolts);
3535 if (status < 0)
3536 return status;
3537 }
3538
3539 if (ops->set_suspend_mode) {
3540 status = device_create_file(dev,
3541 &dev_attr_suspend_standby_mode);
3542 if (status < 0)
3543 return status;
3544 status = device_create_file(dev,
3545 &dev_attr_suspend_mem_mode);
3546 if (status < 0)
3547 return status;
3548 status = device_create_file(dev,
3549 &dev_attr_suspend_disk_mode);
3550 if (status < 0)
3551 return status;
3552 }
3553
3554 return status;
3555} 3535}
3556 3536
3537static struct class regulator_class = {
3538 .name = "regulator",
3539 .dev_release = regulator_dev_release,
3540 .dev_groups = regulator_dev_groups,
3541};
3542
3557static void rdev_init_debugfs(struct regulator_dev *rdev) 3543static void rdev_init_debugfs(struct regulator_dev *rdev)
3558{ 3544{
3559 rdev->debugfs = debugfs_create_dir(rdev_get_name(rdev), debugfs_root); 3545 rdev->debugfs = debugfs_create_dir(rdev_get_name(rdev), debugfs_root);
@@ -3692,11 +3678,6 @@ regulator_register(const struct regulator_desc *regulator_desc,
3692 if (ret < 0) 3678 if (ret < 0)
3693 goto scrub; 3679 goto scrub;
3694 3680
3695 /* add attributes supported by this regulator */
3696 ret = add_regulator_attributes(rdev);
3697 if (ret < 0)
3698 goto scrub;
3699
3700 if (init_data && init_data->supply_regulator) 3681 if (init_data && init_data->supply_regulator)
3701 supply = init_data->supply_regulator; 3682 supply = init_data->supply_regulator;
3702 else if (regulator_desc->supply_name) 3683 else if (regulator_desc->supply_name)