regulator: framework core
PATCH v3 4/7 regulator: framework core
This patch provides the regulator framework core. The core also provides a sysfs interface for userspace information.
--- drivers/regulator/reg-core.c | 1311 ++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 1311 insertions(+), 0 deletions(-) create mode 100644 drivers/regulator/reg-core.c
drivers/regulator/reg-core.c new file +1311 -0
@@ -0,0 +1,1311 @@ +/* +* regulator.c -- Voltage/Current Regulator framework. +* +* Copyright 2007, 2008 Wolfson Microelectronics PLC. +* +* Author: Liam Girdwood <[email protected]> +* +* This program is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by the +* Free Software Foundation; either version 2 of the License, or (at your +* option) any later version. +* +*/ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/device.h> +#include <linux/err.h> +#include <linux/mutex.h> +#include <linux/regulator/regulator.h> +#include <linux/regulator/regulator-drv.h> +#include <linux/regulator/regulator-platform.h> + +#define REGULATOR_VERSION "0.4" + +static DEFINE_MUTEX (regulator_list_mutex); +static LIST_HEAD (regulator_list); + +/** +* struct regulator_cdev +* +* Voltage / Current regulator class device. One for each regulator. +*/ +struct regulator_cdev { +struct regulator_desc *desc; +int use_count; + +struct list_head list; +struct list_head consumer_list; +struct blocking_notifier_head notifier; +struct mutex mutex;/* consumer lock */ +struct module *owner; +struct class_device cdev; +struct regulation_constraints *constraints; +struct regulator_cdev *parent;/* for tree */ + +void *reg_data;/* regulator_cdev data */ +}; + +static inline struct regulator_cdev *to_rcdev (struct class_device *cd) +{ + return container_of(cd, struct regulator_cdev, cdev); +} + +/* +* struct regulator +* +* One for each consumer device. +*/ +struct regulator { +struct device *dev; +struct list_head list; +int uA_load; +int uV_required; +int enabled;/* client has called enabled */ +struct device_attribute dev_attr; +struct regulator_cdev *rcdev; +}; + +static int _regulator_is_enabled (struct regulator_cdev *rcdev); +static int _regulator_disable (struct regulator_cdev *rcdev); +static int _regulator_get_voltage (struct regulator_cdev *rcdev); +static int _regulator_get_current (struct regulator_cdev *rcdev); +static unsigned int _regulator_get_mode (struct regulator_cdev *rcdev); + +/* gets the regulator for a given consumer device */ +static struct regulator *get_device_regulator (struct device *dev) +{ +struct regulator *regulator =NULL ; +struct regulator_cdev *rcdev; + +mutex_lock (®ulator_list_mutex); +list_for_each_entry (rcdev, ®ulator_list, list) { +mutex_lock (&rcdev->mutex); +list_for_each_entry (regulator, &rcdev->consumer_list, list) { +if (regulator->dev == dev) { +mutex_unlock (&rcdev->mutex); +return regulator; + } + } +mutex_unlock (&rcdev->mutex); + } +mutex_unlock (®ulator_list_mutex); +return NULL ; +} + +/* voltage constraint check */ +static int regulator_check_voltage (struct regulator_cdev *rcdev,int uV) +{ +if (!rcdev->constraints) { +printk (KERN_ERR "%s: no constraints for %s\n" , __func__, + rcdev->desc->name); +return -ENODEV ; + } +if (!(rcdev->constraints->valid_ops_mask ®ULATOR_CHANGE_VOLTAGE )) { +printk (KERN_ERR "%s: operation not allowed for %s\n" , + __func__, rcdev->desc->name); +return -EPERM ; + } +if (uV > rcdev->constraints->max_uV || + uV < rcdev->constraints->min_uV) { +printk (KERN_ERR "%s: invalid voltage %duV for %s\n" , + __func__, uV, rcdev->desc->name); +return -EINVAL ; + } +return 0 ; +} + +/* current constraint check */ +static int regulator_check_current (struct regulator_cdev *rcdev,int uA) +{ +if (!rcdev->constraints) { +printk (KERN_ERR "%s: no constraints for %s\n" , __func__, + rcdev->desc->name); +return -ENODEV ; + } +if (!(rcdev->constraints->valid_ops_mask ®ULATOR_CHANGE_CURRENT )) { +printk (KERN_ERR "%s: operation not allowed for %s\n" , + __func__, rcdev->desc->name); +return -EPERM ; + } +if (uA > rcdev->constraints->max_uA || + uA < rcdev->constraints->min_uA) { +printk (KERN_ERR "%s: invalid current %duA for %s\n" , + __func__, uA, rcdev->desc->name); +return -EINVAL ; + } +return 0 ; +} + +/* operating mode constraint check */ +static int regulator_check_mode (struct regulator_cdev *rcdev,int mode) +{ +if (!rcdev->constraints) { +printk (KERN_ERR "%s: no constraints for %s\n" , __func__, + rcdev->desc->name); +return -ENODEV ; + } +if (!(rcdev->constraints->valid_ops_mask ®ULATOR_CHANGE_MODE )) { +printk (KERN_ERR "%s: operation not allowed for %s\n" , + __func__, rcdev->desc->name); +return -EPERM ; + } +if (!(rcdev->constraints->valid_modes_mask & mode)) { +printk (KERN_ERR "%s: invalid mode %x for %s\n" , + __func__, mode, rcdev->desc->name); +return -EINVAL ; + } +return 0 ; +} + +/* dynamic regulator mode switching constraint check */ +static int regulator_check_drms (struct regulator_cdev *rcdev) +{ +if (!rcdev->constraints) { +printk (KERN_ERR "%s: no constraints for %s\n" , __func__, + rcdev->desc->name); +return -ENODEV ; + } +if (!(rcdev->constraints->valid_ops_mask ®ULATOR_CHANGE_DRMS )) { +printk (KERN_ERR "%s: operation not allowed for %s\n" , + __func__, rcdev->desc->name); +return -EPERM ; + } +return 0 ; +} + +static ssize_t device_requested_uA_show (struct device *dev, +struct device_attribute *attr,char *buf) +{ +struct regulator *regulator; + + regulator =get_device_regulator (dev); +if (regulator ==NULL ) +return 0 ; + +return sprintf (buf,"%d\n" , regulator->uA_load); +} + +static ssize_t regulator_uV_show (struct class_device *cdev,char *buf) +{ +struct regulator_cdev *rcdev =to_rcdev (cdev); + +return sprintf (buf,"%d\n" ,_regulator_get_voltage (rcdev)); +} + +static ssize_t regulator_uA_show (struct class_device *cdev,char *buf) +{ +struct regulator_cdev *rcdev =to_rcdev (cdev); + +return sprintf (buf,"%d\n" ,_regulator_get_current (rcdev)); +} + +static ssize_t regulator_opmode_show (struct class_device *cdev,char *buf) +{ +struct regulator_cdev *rcdev =to_rcdev (cdev); +int mode =_regulator_get_mode (rcdev); + +switch (mode) { +case REGULATOR_MODE_FAST : +return sprintf (buf,"fast\n" ); +case REGULATOR_MODE_NORMAL : +return sprintf (buf,"normal\n" ); +case REGULATOR_MODE_IDLE : +return sprintf (buf,"idle\n" ); +case REGULATOR_MODE_STANDBY : +return sprintf (buf,"standby\n" ); + } +return sprintf (buf,"unknown\n" ); +} + +static ssize_t regulator_state_show (struct class_device *cdev,char *buf) +{ +struct regulator_cdev *rcdev =to_rcdev (cdev); +int state =_regulator_is_enabled (rcdev); + +if (state >0 ) +return sprintf (buf,"enabled\n" ); +else if (state ==0 ) +return sprintf (buf,"disabled\n" ); +else +return sprintf (buf,"unknown\n" ); +} + +static ssize_t regulator_min_uA_show (struct class_device *cdev, +char *buf) +{ +struct regulator_cdev *rcdev =to_rcdev (cdev); + +if (!rcdev->constraints) +return sprintf (buf,"constraint not defined\n" ); + +return sprintf (buf,"%d\n" , rcdev->constraints->min_uA); +} + +static ssize_t regulator_max_uA_show (struct class_device *cdev, +char *buf) +{ +struct regulator_cdev *rcdev =to_rcdev (cdev); + +if (!rcdev->constraints) +return sprintf (buf,"constraint not defined\n" ); + +return sprintf (buf,"%d\n" , rcdev->constraints->max_uA); +} + +static ssize_t regulator_min_uV_show (struct class_device *cdev, +char *buf) +{ +struct regulator_cdev *rcdev =to_rcdev (cdev); + +if (!rcdev->constraints) +return sprintf (buf,"constraint not defined\n" ); + +return sprintf (buf,"%d\n" , rcdev->constraints->min_uV); +} + +static ssize_t regulator_max_uV_show (struct class_device *cdev, +char *buf) +{ +struct regulator_cdev *rcdev =to_rcdev (cdev); + +if (!rcdev->constraints) +return sprintf (buf,"constraint not defined\n" ); + +return sprintf (buf,"%d\n" , rcdev->constraints->max_uV); +} + +static ssize_t regulator_total_uA_show (struct class_device *cdev,char *buf) +{ +struct regulator_cdev *rcdev =to_rcdev (cdev); +struct regulator *regulator; +int uA =0 ; + +mutex_lock (&rcdev->mutex); +list_for_each_entry (regulator, &rcdev->consumer_list, list) + uA += regulator->uA_load; +mutex_unlock (&rcdev->mutex); +return sprintf (buf,"%d\n" , uA); +} + +static ssize_t regulator_num_users_show (struct class_device *cdev,char *buf) +{ +struct regulator_cdev *rcdev =to_rcdev (cdev); +return sprintf (buf,"%d\n" , rcdev->use_count); +} + +static ssize_t regulator_type_show (struct class_device *cdev,char *buf) +{ +struct regulator_cdev *rcdev =to_rcdev (cdev); + +switch (rcdev->desc->type) { +case REGULATOR_VOLTAGE : +return sprintf (buf,"voltage\n" ); +case REGULATOR_CURRENT : +return sprintf (buf,"current\n" ); + } +return sprintf (buf,"unknown\n" ); +} + +static struct class_device_attribute regulator_dev_attrs[] = { +__ATTR (microvolts,0444 , regulator_uV_show,NULL ), +__ATTR (microamps,0444 , regulator_uA_show,NULL ), +__ATTR (opmode,0444 , regulator_opmode_show,NULL ), +__ATTR (state,0444 , regulator_state_show,NULL ), +__ATTR (min_microvolts,0444 , regulator_min_uV_show,NULL ), +__ATTR (min_microamps,0444 , regulator_min_uA_show,NULL ), +__ATTR (max_microvolts,0444 , regulator_max_uV_show,NULL ), +__ATTR (max_microamps,0444 , regulator_max_uA_show,NULL ), +__ATTR (requested_microamps,0444 , regulator_total_uA_show,NULL ), +__ATTR (num_users,0444 , regulator_num_users_show,NULL ), +__ATTR (type,0444 , regulator_type_show,NULL ), + __ATTR_NULL, +}; + +static void regulator_dev_release (struct class_device *cdev) +{ +struct regulator_cdev *rcdev =to_rcdev (cdev); +kfree (rcdev); +} + +struct class regulator_class = { + .name ="regulator" , + .release = regulator_dev_release, + .class_dev_attrs = regulator_dev_attrs, +}; + +/* find the lowest stable voltage that all enabled clients can operate at */ +static inline int get_lowest_stable_voltage (struct regulator_cdev *rcdev) +{ +struct regulator *regulator; +int highest_uV =0 ; + +/* lock is held by caller */ +list_for_each_entry (regulator, &rcdev->consumer_list, list) { +if (regulator->enabled && regulator->uV_required > highest_uV) + highest_uV = regulator->uV_required; + } +return highest_uV; +} + +/* Set the regulator voltage to the lowest possible value that can safely +* support all the client devices */ +static int regulator_set_stable_voltage (struct regulator_cdev *rcdev) +{ +int ret =0 , uV; + +if (rcdev->desc->type ==REGULATOR_VOLTAGE ) { + uV =get_lowest_stable_voltage (rcdev); +if (uV && rcdev->desc->ops->set_voltage) + ret = rcdev->desc->ops->set_voltage (rcdev, uV); + } +return ret; +} + +/* Calculate the new optimum regulator operating mode based on the new total +* consumer load. All locks held by caller */ +static void drms_uA_update (struct regulator_cdev *rcdev) +{ +struct regulator *sibling; +int current_uA =0 , output_uV, input_uV, err; +unsigned int mode; + + err =regulator_check_drms (rcdev); +if (err <0 || !rcdev->desc->ops->get_optimum_mode || + !rcdev->desc->ops->get_voltage || !rcdev->desc->ops->set_mode); +return ; + +/* get output voltage */ + output_uV = rcdev->desc->ops->get_voltage (rcdev); + +/* get input voltage */ +if (rcdev->parent && rcdev->parent->desc->ops->get_voltage) + input_uV = rcdev->parent->desc->ops->get_voltage (rcdev->parent); +else + input_uV = rcdev->constraints->input_uV; + +/* calc total requested load */ +list_for_each_entry (sibling, &rcdev->consumer_list, list) + current_uA += sibling->uA_load; + +/* now get the optimum mode for our new total regulator load */ + mode = rcdev->desc->ops->get_optimum_mode (rcdev, input_uV, + output_uV, current_uA); + +/* check the new mode is allowed */ + err =regulator_check_mode (rcdev, mode); +if (err ==0 ) + rcdev->desc->ops->set_mode (rcdev, mode); +} + +static void print_constraints (struct regulator_cdev *rcdev) +{ +struct regulation_constraints *constraints = rcdev->constraints; +char buf[80 ]; +int count; + +if (rcdev->desc->type ==REGULATOR_VOLTAGE ) { +if (constraints->min_uV == constraints->max_uV) + count =sprintf (buf,"%d mV " , +uV_to_mV (constraints->min_uV)); +else + count =sprintf (buf,"%d <--> %d mV " , +uV_to_mV (constraints->min_uV), +uV_to_mV (constraints->max_uV)); + }else { +if (constraints->min_uA == constraints->max_uA) + count =sprintf (buf,"%d mA " , +uA_to_mA (constraints->min_uA)); +else + count =sprintf (buf,"%d <--> %d mA " , +uA_to_mA (constraints->min_uA), +uA_to_mA (constraints->max_uA)); + } +if (constraints->valid_modes_mask ®ULATOR_MODE_FAST ) + count +=sprintf (buf + count,"fast " ); +if (constraints->valid_modes_mask ®ULATOR_MODE_NORMAL ) + count +=sprintf (buf + count,"normal " ); +if (constraints->valid_modes_mask ®ULATOR_MODE_IDLE ) + count +=sprintf (buf + count,"idle " ); +if (constraints->valid_modes_mask ®ULATOR_MODE_STANDBY ) + count +=sprintf (buf + count,"standby" ); + +printk (KERN_INFO "regulator: %s: %s\n" , rcdev->desc->name, buf); +} + +#define REG_STR_SIZE 32 + +static struct regulator *create_regulator (struct regulator_cdev *rcdev, +struct device *dev) +{ +struct regulator *regulator; +char buf[REG_STR_SIZE ]; +int err, size; + + regulator =kzalloc (sizeof (*regulator),GFP_KERNEL ); +if (regulator ==NULL ) +return NULL ; + +mutex_lock (&rcdev->mutex); + regulator->rcdev = rcdev; +list_add (®ulator->list, &rcdev->consumer_list); + +if (dev) { +/* create a 'requested_microamps_name' sysfs entry */ + size =scnprintf (buf,REG_STR_SIZE ,"microamps_requested_%s" , + regulator->rcdev->desc->name); +if (size >=REG_STR_SIZE ) + goto overflow_err; + + regulator->dev = dev; + regulator->dev_attr.attr.name =kstrdup (buf,GFP_KERNEL ); +if (regulator->dev_attr.attr.name ==NULL ) + goto err_out; + + regulator->dev_attr.attr.owner =THIS_MODULE ; + regulator->dev_attr.attr.mode =0444 ; + regulator->dev_attr.show = device_requested_uA_show; + err =device_create_file (dev, ®ulator->dev_attr); +if (err <0 ) { +printk (KERN_WARNING "%s: could not add regulator_cdev" +" load sysfs\n" , __func__); + goto err_out; + } + +/* also add a link to the device sysfs entry */ + err =sysfs_create_link (&rcdev->cdev.kobj, &dev->kobj, + dev->kobj.name); +if (err) { +printk (KERN_WARNING +"%s: could not add device link %s err %d\n" , + __func__, dev->kobj.name, err); +device_remove_file (dev, ®ulator->dev_attr); + goto err_out; + } + } +mutex_unlock (&rcdev->mutex); +return regulator; +err_out: +kfree (regulator->dev_attr.attr.name); +overflow_err: +list_del (®ulator->list); +kfree (regulator); +mutex_unlock (&rcdev->mutex); +return NULL ; +} + +/** +* regulator_get - lookup and obtain a reference to a regulator. +* @dev: device for regulator "consumer" +* @id: regulator ID +* +* Returns a struct regulator corresponding to the regulator producer, or +* IS_ERR() condition containing errno. +*/ +struct regulator *regulator_get (struct device *dev,const char *id) +{ +struct regulator_cdev *rcdev; +struct regulator *regulator =ERR_PTR (-ENODEV ); + +if (id ==NULL ) +return regulator; + +mutex_lock (®ulator_list_mutex); +list_for_each_entry (rcdev, ®ulator_list, list) { +if (strcmp (id, rcdev->desc->name) ==0 && +try_module_get (rcdev->owner)) { + goto found; + } + } +printk (KERN_ERR "regulator: Unable to get requested regulator: %s\n" , + id); +mutex_unlock (®ulator_list_mutex); +return regulator; + +found: + regulator =create_regulator (rcdev, dev); +if (regulator ==NULL ) { + regulator =ERR_PTR (-ENOMEM ); +module_put (rcdev->owner); + } + +mutex_unlock (®ulator_list_mutex); +return regulator; +} +EXPORT_SYMBOL_GPL (regulator_get); + +/** +* regulator_put - "free" the regulator source +* @regulator: regulator source +* +* Note: drivers must ensure that all regulator_enable calls made on this +* regulator source are balanced by regulator_disable calls prior to calling +* this function. +*/ +void regulator_put (struct regulator *regulator) +{ +struct regulator_cdev *rcdev; + +if (regulator ==NULL ||IS_ERR (regulator)) +return ; + +mutex_lock (®ulator_list_mutex); + rcdev = regulator->rcdev; + +/* remove any sysfs entries */ +if (regulator->dev) { +sysfs_remove_link (&rcdev->cdev.kobj, regulator->dev->kobj.name); +device_remove_file (regulator->dev, ®ulator->dev_attr); +kfree (regulator->dev_attr.attr.name); + } +list_del (®ulator->list); +kfree (regulator); + +module_put (rcdev->owner); +mutex_unlock (®ulator_list_mutex); +} +EXPORT_SYMBOL_GPL (regulator_put); + +/* locks held by regulator_enable() */ +static int _regulator_enable (struct regulator_cdev *rcdev) +{ +int ret = -EINVAL ; + +/* do we need to enable the parent regulator first */ +if (rcdev->parent) { + ret =_regulator_enable (rcdev->parent); +if (ret <0 ) { +printk (KERN_ERR "%s: failed to enable %s\n" , + __func__, rcdev->desc->name); +return ret; + } + } + +/* check voltage and requested load before enabling */ +if (rcdev->desc->ops->enable) { + ret =regulator_set_stable_voltage (rcdev); +if (ret <0 ) { +printk (KERN_ERR "%s: invalid voltage for %s\n" , + __func__, rcdev->desc->name); +return ret; + } + +if (rcdev->constraints && + (rcdev->constraints->valid_ops_mask & +REGULATOR_CHANGE_DRMS )) +drms_uA_update (rcdev); + + ret = rcdev->desc->ops->enable (rcdev); +if (ret <0 ) { +printk (KERN_ERR "%s: failed to enable %s\n" , + __func__, rcdev->desc->name); +return ret; + } + + rcdev->use_count++; +return ret; + } + +return ret; +} + +/** +* regulator_enable - enable regulator output +* @regulator: regulator source +* +* Enable the regulator output at the predefined voltage or current value. +* NOTE: the output value can be set by other drivers, boot loader or may be +* hardwired in the regulator. +* NOTE: calls to regulator_enable() must be balanced with calls to +* regulator_disable(). +*/ +int regulator_enable (struct regulator *regulator) +{ +int ret; + +mutex_lock (®ulator->rcdev->mutex); + regulator->enabled =0 ; + ret =_regulator_enable (regulator->rcdev); +if (ret ==0 ) + regulator->enabled =1 ; +mutex_unlock (®ulator->rcdev->mutex); +return ret; +} +EXPORT_SYMBOL_GPL (regulator_enable); + +/* locks held by regulator_disable() */ +static int _regulator_disable (struct regulator_cdev *rcdev) +{ +int ret =0 ; + +/* are we the last user of this regulator */ +if (rcdev->use_count ==1 ) { + +/* last user - then disable */ +if (rcdev->desc->ops->disable) { + ret = rcdev->desc->ops->disable (rcdev); +if (ret <0 ) { +printk (KERN_ERR "%s: failed to disable %s\n" , + __func__, rcdev->desc->name); +return ret; + } + } + +/* decrease our parents ref count and disable if required */ +if (rcdev->parent) +_regulator_disable (rcdev->parent); + + rcdev->use_count =0 ; + }else if (rcdev->use_count >1 ) { +/* find the most efficient voltage and mode now that we +* have one less consumer device. */ + ret =regulator_set_stable_voltage (rcdev); + +if (rcdev->constraints && + (rcdev->constraints->valid_ops_mask & +REGULATOR_CHANGE_DRMS )) +drms_uA_update (rcdev); + + rcdev->use_count--; + } +return ret; +} + +/** +* regulator_disable - disable regulator output +* @regulator: regulator source +* +* Disable the regulator output voltage or current. +* NOTE: this will only disable the regulator output iff no other consumer +* devices have it enabled. +* NOTE: calls to regulator_enable() must be balanced with calls to +* regulator_disable(). +*/ +int regulator_disable (struct regulator *regulator) +{ +int ret; + +mutex_lock (®ulator->rcdev->mutex); + regulator->enabled =0 ; + regulator->uA_load =0 ; + ret =_regulator_disable (regulator->rcdev); +mutex_unlock (®ulator->rcdev->mutex); +return ret; +} +EXPORT_SYMBOL_GPL (regulator_disable); + +static int _regulator_is_enabled (struct regulator_cdev *rcdev) +{ +int ret; + +mutex_lock (&rcdev->mutex); + +/* sanity check */ +if (!rcdev->desc->ops->is_enabled) { + ret = -EINVAL ; + goto out; + } + + ret = rcdev->desc->ops->is_enabled (rcdev); +out: +mutex_unlock (&rcdev->mutex); +return ret; +} + +/** +* regulator_is_enabled - is the regulator output enabled +* @regulator: regulator source +* +* Returns zero for disabled otherwise return number of enable requests. +*/ +int regulator_is_enabled (struct regulator *regulator) +{ +return _regulator_is_enabled (regulator->rcdev); +} +EXPORT_SYMBOL_GPL (regulator_is_enabled); + +/** +* regulator_set_voltage - set regulator output voltage +* @regulator: regulator source +* @uV: voltage in uV +* +* Sets a voltage regulator to the desired output voltage. This can be set +* during any regulator state. IOW, regulator can be disabled or enabled. +* +* If the regulator is enabled then the voltage will change to the new value +* immediately otherwise if the regulator is disabled the regulator will +* output at the new voltage when enabled. +* +* NOTE: If the regulator is shared between several devices then the lowest +* request voltage that meets the system constraints will be used. +* NOTE: Regulator system constraints must be set for this regulator before +* calling this function otherwise this call will fail. +*/ +int regulator_set_voltage (struct regulator *regulator,int uV) +{ +struct regulator_cdev *rcdev = regulator->rcdev; +int ret; + +mutex_lock (&rcdev->mutex); + +/* sanity check */ +if (!rcdev->desc->ops->set_voltage) { + ret = -EINVAL ; + goto out; + } + +/* constraints check */ + ret =regulator_check_voltage (rcdev, uV); +if (ret <0 ) + goto out; + regulator->uV_required = uV; + +/* only set the new voltage if it's all clients can use it */ + ret =regulator_set_stable_voltage (rcdev); +out: +mutex_unlock (&rcdev->mutex); +return ret; +} +EXPORT_SYMBOL_GPL (regulator_set_voltage); + +static int _regulator_get_voltage (struct regulator_cdev *rcdev) +{ +int ret; + +mutex_lock (&rcdev->mutex); + +/* sanity check */ +if (!rcdev->desc->ops->get_voltage) { + ret = -EINVAL ; + goto out; + } + + ret = rcdev->desc->ops->get_voltage (rcdev); +out: +mutex_unlock (&rcdev->mutex); +return ret; +} + +/** +* regulator_get_voltage - get regulator output voltage +* @regulator: regulator source +* +* This returns the current regulator voltage in uV. +* +* NOTE: If the regulator is disabled it will return the voltage value. This +* function should not be used to determine regulator state. +*/ +int regulator_get_voltage (struct regulator *regulator) +{ +return _regulator_get_voltage (regulator->rcdev); +} +EXPORT_SYMBOL_GPL (regulator_get_voltage); + +/** +* regulator_set_current - set regulator output current for a current sink +* @regulator: regulator source +* @uA: current in uA +* +* Sets current sink to the desired output current. This can be set during +* any regulator state. IOW, regulator can be disabled or enabled. +* +* If the regulator is enabled then the current will change to the new value +* immediately otherwise if the regulator is disabled the regulator will +* output at the new current when enabled. +* +* NOTE: Regulator system constraints must be set for this regulator before +* calling this function otherwise this call will fail. +*/ +int regulator_set_current (struct regulator *regulator,int uA) +{ +struct regulator_cdev *rcdev = regulator->rcdev; +int ret; + +mutex_lock (&rcdev->mutex); + +/* sanity check */ +if (!rcdev->desc->ops->set_current) { + ret = -EINVAL ; + goto out; + } + +/* constraints check */ + ret =regulator_check_current (rcdev, uA); +if (ret <0 ) + goto out; + + ret = rcdev->desc->ops->set_current (rcdev, uA); +out: +mutex_unlock (&rcdev->mutex); +return ret; +} +EXPORT_SYMBOL_GPL (regulator_set_current); + +static int _regulator_get_current (struct regulator_cdev *rcdev) +{ +int ret; + +mutex_lock (&rcdev->mutex); + +/* sanity check */ +if (!rcdev->desc->ops->get_current) { + ret = -EINVAL ; + goto out; + } + + ret = rcdev->desc->ops->get_current (rcdev); +out: +mutex_unlock (&rcdev->mutex); +return ret; +} + +/** +* regulator_get_current - get regulator output current +* @regulator: regulator source +* +* This returns the current supplied by the specified current sink in uA. +* +* NOTE: If the regulator is disabled it will return the current value. This +* function should not be used to determine regulator state. +*/ +int regulator_get_current (struct regulator *regulator) +{ +return _regulator_get_current (regulator->rcdev); +} +EXPORT_SYMBOL_GPL (regulator_get_current); + +/** +* regulator_set_mode - set regulator operating mode +* @regulator: regulator source +* @mode: operating mode - one of the REGULATOR_MODE constants +* +* Set regulator operating mode to increase regulator efficiency or improve +* regulation performance. +* +* NOTE: Regulator system constraints must be set for this regulator before +* calling this function otherwise this call will fail. +*/ +int regulator_set_mode (struct regulator *regulator,unsigned int mode) +{ +struct regulator_cdev *rcdev = regulator->rcdev; +int ret; + +mutex_lock (&rcdev->mutex); + +/* sanity check */ +if (!rcdev->desc->ops->set_mode) { + ret = -EINVAL ; + goto out; + } + +/* constraints check */ + ret =regulator_check_mode (rcdev, mode); +if (ret <0 ) + goto out; + + ret = rcdev->desc->ops->set_mode (rcdev, mode); +out: +mutex_unlock (&rcdev->mutex); +return ret; +} +EXPORT_SYMBOL_GPL (regulator_set_mode); + +static unsigned int _regulator_get_mode (struct regulator_cdev *rcdev) +{ +int ret; + +mutex_lock (&rcdev->mutex); + +/* sanity check */ +if (!rcdev->desc->ops->get_mode) { + ret = -EINVAL ; + goto out; + } + + ret = rcdev->desc->ops->get_mode (rcdev); +out: +mutex_unlock (&rcdev->mutex); +return ret; +} + +/** +* regulator_get_mode - get regulator operating mode +* @regulator: regulator source +* +* Get the current regulator operating mode. +*/ +unsigned int regulator_get_mode (struct regulator *regulator) +{ +return _regulator_get_mode (regulator->rcdev); +} +EXPORT_SYMBOL_GPL (regulator_get_mode); + +static unsigned int _regulator_get_optimum_mode (struct regulator_cdev *rcdev, +int input_uV,int output_uV, +int load_uA) +{ +int ret; + +mutex_lock (&rcdev->mutex); + +/* sanity check */ +if (!rcdev->desc->ops->get_optimum_mode) { + ret = -EINVAL ; + goto out; + } + + ret = rcdev->desc->ops->get_optimum_mode (rcdev, + input_uV, output_uV, load_uA); +out: +mutex_unlock (&rcdev->mutex); +return ret; +} + +/** +* regulator_get_optimum_mode - get regulator optimum operating mode +* @regulator: regulator source +* @input_uV: input voltage +* @output_uV: output voltage +* @load_uV: load current +* +* Get the most efficient regulator operating mode for the given input +* and output voltages at a specific load.. +*/ +unsigned int regulator_get_optimum_mode (struct regulator *regulator, +int input_uV,int output_uV, +int load_uA) +{ +return _regulator_get_optimum_mode (regulator->rcdev, input_uV, + output_uV, load_uA); +} +EXPORT_SYMBOL_GPL (regulator_get_optimum_mode); + +/** +* regulator_register_client - register regulator event notifier +* @regulator: regulator source +* @notifier_block: notifier block +* +* Register notifier block to receive regulator events. +*/ +int regulator_register_client (struct regulator *regulator, +struct notifier_block *nb) +{ +return blocking_notifier_chain_register (®ulator->rcdev->notifier, + nb); +} +EXPORT_SYMBOL_GPL (regulator_register_client); + +/** +* regulator_unregister_client - unregister regulator event notifier +* @regulator: regulator source +* @notifier_block: notifier block +* +* Unregister regulator event notifier block. +*/ +int regulator_unregister_client (struct regulator *regulator, +struct notifier_block *nb) +{ +return blocking_notifier_chain_unregister (®ulator->rcdev->notifier, + nb); +} +EXPORT_SYMBOL_GPL (regulator_unregister_client); + +/** +* regulator_notifier_call_chain - call regulator event notifier +* @regulator: regulator source +* @event: notifier block +* @data: +* +* Called by regulator drivers to notify clients a regulator event has +* occurred. +*/ +int regulator_notifier_call_chain (struct regulator_cdev *rcdev, +unsigned long event,void *data) +{ +return blocking_notifier_call_chain (&rcdev->notifier, event, data); +} +EXPORT_SYMBOL_GPL (regulator_notifier_call_chain); + +/** +* regulator_register - register regulator +* @regulator: regulator source +* @reg_data: private regulator data +* +* Called by regulator drivers to register a regulator. +* Returns 0 on success. +*/ +struct regulator_cdev *regulator_register (struct regulator_desc *regulator_desc, +void *reg_data) +{ +static atomic_t regulator_no =ATOMIC_INIT (0 ); +struct regulator_cdev *rcdev; +int ret; + +if (regulator_desc ==NULL ) +return ERR_PTR (-EINVAL ); + +if (regulator_desc->name ==NULL || regulator_desc->ops ==NULL ) +return ERR_PTR (-EINVAL ); + +if (!regulator_desc->type ==REGULATOR_VOLTAGE && + !regulator_desc->type ==REGULATOR_CURRENT ) +return ERR_PTR (-EINVAL ); + + rcdev =kzalloc (sizeof (struct regulator_cdev ),GFP_KERNEL ); +if (rcdev ==NULL ) +return ERR_PTR (-ENOMEM ); + +mutex_lock (®ulator_list_mutex); + +mutex_init (&rcdev->mutex); + rcdev->reg_data = reg_data; + rcdev->owner = regulator_desc->owner; + rcdev->desc = regulator_desc; +INIT_LIST_HEAD (&rcdev->consumer_list); +INIT_LIST_HEAD (&rcdev->list); +BLOCKING_INIT_NOTIFIER_HEAD (&rcdev->notifier); + + rcdev->cdev.class = ®ulator_class; +class_device_initialize (&rcdev->cdev); +snprintf (rcdev->cdev.class_id,sizeof (rcdev->cdev.class_id), +"regulator_%ld_%s" , + (unsigned long )atomic_inc_return (®ulator_no) -1 , + regulator_desc->name); + + ret =class_device_add (&rcdev->cdev); +if (ret ==0 ) +list_add (&rcdev->list, ®ulator_list); +else { +kfree (rcdev); + rcdev =ERR_PTR (ret); + } +mutex_unlock (®ulator_list_mutex); +return rcdev; +} +EXPORT_SYMBOL_GPL (regulator_register); + +/** +* regulator_unregister - unregister regulator +* @regulator: regulator source +* +* Called by regulator drivers to unregister a regulator. +*/ +void regulator_unregister (struct regulator_cdev *rcdev) +{ +if (rcdev ==NULL ) +return ; + +mutex_lock (®ulator_list_mutex); +list_del (&rcdev->list); +if (rcdev->parent) +sysfs_remove_link (&rcdev->cdev.kobj,"parent" ); +class_device_unregister (&rcdev->cdev); +mutex_unlock (®ulator_list_mutex); +} +EXPORT_SYMBOL_GPL (regulator_unregister); + +/** +* regulator_set_parent - set regulator parent (or supply) regulator +* @regulator: regulator name +* @parent: parent (or supply) regulator name +* +* Called by platform initialisation code to set the parent or "supply" +* regulator for this regulator. This ensures that a regulator parent will +* also be enabled by the core if it's child is enabled. +*/ +int regulator_set_parent (const char *regulator,const char *parent) +{ +struct regulator_cdev *rcdev, *parent_rcdev; +int err; + +if (regulator ==NULL || parent ==NULL ) +return -EINVAL ; + +mutex_lock (®ulator_list_mutex); + +list_for_each_entry (rcdev, ®ulator_list, list) { +if (!strcmp (rcdev->desc->name, regulator)) + goto found_regulator; + } +mutex_unlock (®ulator_list_mutex); +return -ENODEV ; + +found_regulator: +list_for_each_entry (parent_rcdev, ®ulator_list, list) { +if (!strcmp (parent_rcdev->desc->name, parent)) + goto found_parent; + } +mutex_unlock (®ulator_list_mutex); +return -ENODEV ; + +found_parent: + rcdev->parent = parent_rcdev; + err =sysfs_create_link (&rcdev->cdev.kobj, &parent_rcdev->cdev.kobj, +"parent" ); +if (err) { +printk (KERN_ERR +"%s: could not add device link %s err %d\n" , + __func__, parent_rcdev->cdev.kobj.name, err); + rcdev->parent =NULL ; + } +mutex_unlock (®ulator_list_mutex); +return err; +} +EXPORT_SYMBOL_GPL (regulator_set_parent); + +/** +* regulator_get_parent - get regulator parent (or supply) regulator +* @regulator: regulator name +* +* Returns the parent supply regulator name or NULL if no supply regulator +* exists (i.e the regulator is supplied directly from USB, Line, Battery, etc) +*/ +const char *regulator_get_parent (const char *regulator) +{ +struct regulator_cdev *rcdev; + +if (regulator ==NULL ) +return NULL ; + +mutex_lock (®ulator_list_mutex); +list_for_each_entry (rcdev, ®ulator_list, list) { +if (!strcmp (rcdev->desc->name, regulator)) + goto found; + } +mutex_unlock (®ulator_list_mutex); +return NULL ; + +found: +mutex_unlock (®ulator_list_mutex); +if (rcdev->parent) +return rcdev->parent->desc->name; +else +return NULL ; +} +EXPORT_SYMBOL_GPL (regulator_get_parent); + +/** +* regulator_set_platform_constraints - sets regulator constraints +* @regulator: regulator source +* +* Allows platform initialisation code to define and constrain regulator +* circuits e.g. valid voltage/current ranges, etc. +* NOTE: Constraints *must* be set by platform code in order for some +* regulator operations to proceed i.e. set_voltage, set_current, set_mode. +*/ +int regulator_set_platform_constraints (const char *regulator_name, +struct regulation_constraints *constraints) +{ +struct regulator_cdev *rcdev; + +if (regulator_name ==NULL ) +return -EINVAL ; + +mutex_lock (®ulator_list_mutex); +list_for_each_entry (rcdev, ®ulator_list, list) { +if (!strcmp (regulator_name, rcdev->desc->name)) { +mutex_lock (&rcdev->mutex); + rcdev->constraints = constraints; +print_constraints (rcdev); +mutex_unlock (&rcdev->mutex); +mutex_unlock (®ulator_list_mutex); +return 0 ; + } + } +mutex_unlock (®ulator_list_mutex); +return -ENODEV ; +} +EXPORT_SYMBOL_GPL (regulator_set_platform_constraints); + +/** +* regulator_notify_load - notify regulator of new device load +* @regulator: regulator +* @dev: device +* @uA: load +* +* Notifies the regulator core of a new device load. This is then used by +* DRMS (if enabled by constraints) to select the most efficient regulator +* operating mode for the new regulator loading. +* +* Client devices notify their supply regulator of the maximum power +* they will require (can be taken from device datasheet in the power +* consumption tables) when they change operational status and hence power +* state. Examples of operational state changes that can affect power +* consumption are :- +* +* o Device is opened / closed. +* o Device I/O is about to begin or has just finished. +* o Device is idling in between work. +* +* This information is also exported via sysfs to userspace. +* +* DRMS will sum the total requested load on the regulator and change +* to the most efficient operating mode if platform constraints allow. +*/ +void regulator_drms_notify_load (struct regulator *regulator,int uA) +{ +struct regulator_cdev *rcdev = regulator->rcdev; + +mutex_lock (&rcdev->mutex); + regulator->uA_load = uA; +drms_uA_update (rcdev); +mutex_unlock (&rcdev->mutex); +} +EXPORT_SYMBOL_GPL (regulator_drms_notify_load); + +/** +* rcdev_get_drvdata - get rcdev regulator driver data +* @regulator: regulator +* +* Get rcdev regulator driver private data. This call can be used in the +* regulator driver context. +*/ +void *rcdev_get_drvdata (struct regulator_cdev *rcdev) +{ +return rcdev->reg_data; +} +EXPORT_SYMBOL_GPL (rcdev_get_drvdata); + +/** +* regulator_get_drvdata - get regulator driver data +* @regulator: regulator +* +* Get regulator driver private data. This call can be used in the consumer +* driver context when non API regulator specific functions need to be called. +*/ +void *regulator_get_drvdata (struct regulator *regulator) +{ +return regulator->rcdev->reg_data; +} +EXPORT_SYMBOL_GPL (regulator_get_drvdata); + +/** +* regulator_set_drvdata - set regulator driver data +* @regulator: regulator +* @data: data +*/ +void regulator_set_drvdata (struct regulator *regulator,void *data) +{ + regulator->rcdev->reg_data = data; +} +EXPORT_SYMBOL_GPL (regulator_set_drvdata); + +/** +* regulator_get_id - get regulator ID +* @regulator: regulator +*/ +int rcdev_get_id (struct regulator_cdev *rcdev) +{ +return rcdev->desc->id; +} +EXPORT_SYMBOL_GPL (rcdev_get_id); + +static int __init regulator_init (void ) +{ +printk (KERN_INFO "regulator: core version %s\n" ,REGULATOR_VERSION ); +return class_register (®ulator_class); +} + +/* init early to allow our consumers to complete system booting */ +core_initcall (regulator_init);
Signature · 1 line
1.5.4.3
Quoted 13 lines · On Thu, 06 Mar 2008 18:11:54 +0000 Liam Girdwood…
This patch provides the regulator framework core. The core also provides a sysfs interface for userspace information.
drivers/regulator/reg-core.c new file +10
-0+/* gets the regulator for a given consumer device */ +static struct regulator *get_device_regulator (struct device *dev) +{ +struct regulator *regulator =NULL ; +struct regulator_cdev *rcdev; + +mutex_lock (®ulator_list_mutex); +list_for_each_entry (rcdev, ®ulator_list, list) { +mutex_lock (&rcdev->mutex); +list_for_each_entry (regulator, &rcdev->consumer_list, list) {
drivers/regulator/reg-core.c line 95
Quoted 10 lines
drivers/regulator/reg-core.c new file +10
-0+if (regulator->dev == dev) { +mutex_unlock (&rcdev->mutex); +return regulator; + } + } +mutex_unlock (&rcdev->mutex); + } +mutex_unlock (®ulator_list_mutex); +return NULL ; +}
Is this really supposed to return with the list lock held? If so, some comment describing the overall locking design here would be better than having to reverse-engineer it.
drivers/regulator/reg-core.c line 350
Quoted 12 lines
drivers/regulator/reg-core.c new file +12
-0+static inline int get_lowest_stable_voltage (struct regulator_cdev *rcdev) +{ +struct regulator *regulator; +int highest_uV =0 ; + +/* lock is held by caller */ +list_for_each_entry (regulator, &rcdev->consumer_list, list) { +if (regulator->enabled && regulator->uV_required > highest_uV) + highest_uV = regulator->uV_required; + } +return highest_uV; +}
Too large to inline - the compiler will do this for you if it is a benefit to do so.
Quoted 15 lines
drivers/regulator/reg-core.c new file +15
-0+/* Calculate the new optimum regulator operating mode based on the new total +* consumer load. All locks held by caller */ +static void drms_uA_update (struct regulator_cdev *rcdev) +{ +struct regulator *sibling; +int current_uA =0 , output_uV, input_uV, err; +unsigned int mode; + + err =regulator_check_drms (rcdev); +if (err <0 || !rcdev->desc->ops->get_optimum_mode || + !rcdev->desc->ops->get_voltage || !rcdev->desc->ops->set_mode); +return ; + +/* get output voltage */ + output_uV = rcdev->desc->ops->get_voltage (rcdev);
drivers/regulator/reg-core.c line 390
Quoted 10 lines
drivers/regulator/reg-core.c new file +10
-0+ +/* get input voltage */ +if (rcdev->parent && rcdev->parent->desc->ops->get_voltage) + input_uV = rcdev->parent->desc->ops->get_voltage (rcdev->parent); +else + input_uV = rcdev->constraints->input_uV; + +/* calc total requested load */ +list_for_each_entry (sibling, &rcdev->consumer_list, list) + current_uA += sibling->uA_load;
Should be indented with a tab, not spacespacespacespace
Quoted 12 lines
drivers/regulator/reg-core.c new file +12
-0+/* now get the optimum mode for our new total regulator load */ + mode = rcdev->desc->ops->get_optimum_mode (rcdev, input_uV, + output_uV, current_uA); + +/* check the new mode is allowed */ + err =regulator_check_mode (rcdev, mode); +if (err ==0 ) + rcdev->desc->ops->set_mode (rcdev, mode); +} + +#define REG_STR_SIZE 32 +
Quoted 65 lines · Andrew Morton
Quoted 13 lines · On Thu, 06 Mar 2008 18:11:54 +0000 Liam Girdwood…
This patch provides the regulator framework core. The core also provides a sysfs interface for userspace information.
(quoted diff) +10
-0+/* gets the regulator for a given consumer device */ +static struct regulator *get_device_regulator(struct device *dev) +{ + struct regulator *regulator = NULL; + struct regulator_cdev *rcdev; + + mutex_lock(®ulator_list_mutex); + list_for_each_entry(rcdev, ®ulator_list, list) { + mutex_lock(&rcdev->mutex); + list_for_each_entry(regulator, &rcdev->consumer_list, list) {Review
Quoted 10 lines
(quoted diff) +10
-0+ if (regulator->dev == dev) { + mutex_unlock(&rcdev->mutex); + return regulator; + } + } + mutex_unlock(&rcdev->mutex); + } + mutex_unlock(®ulator_list_mutex); + return NULL; +}Is this really supposed to return with the list lock held? If so, some comment describing the overall locking design here would be better than having to reverse-engineer it.
Review
Quoted 12 lines
(quoted diff) +12
-0+static inline int get_lowest_stable_voltage(struct regulator_cdev *rcdev) +{ + struct regulator *regulator; + int highest_uV = 0; + + /* lock is held by caller */ + list_for_each_entry(regulator, &rcdev->consumer_list, list) { + if (regulator->enabled && regulator->uV_required > highest_uV) + highest_uV = regulator->uV_required; + } + return highest_uV; +}Too large to inline - the compiler will do this for you if it is a benefit to do so.
Quoted 19 lines
(quoted diff) +19
-0+/* Calculate the new optimum regulator operating mode based on the new total + * consumer load. All locks held by caller */ +static void drms_uA_update(struct regulator_cdev *rcdev) +{ + struct regulator *sibling; + int current_uA = 0, output_uV, input_uV, err; + unsigned int mode; + + err = regulator_check_drms(rcdev); + if (err < 0 || !rcdev->desc->ops->get_optimum_mode || + !rcdev->desc->ops->get_voltage || !rcdev->desc->ops->set_mode); + return; + + /* get output voltage */ + output_uV = rcdev->desc->ops->get_voltage(rcdev); + + /* get input voltage */ + if (rcdev->parent && rcdev->parent->desc->ops->get_voltage) + input_uV = rcdev->parent->desc->ops->get_voltage(rcdev->parent);
Quoted 8 lines
Review
Quoted 6 lines
(quoted diff) +6
-0+ else + input_uV = rcdev->constraints->input_uV; + + /* calc total requested load */ + list_for_each_entry(sibling, &rcdev->consumer_list, list) + current_uA += sibling->uA_load;Should be indented with a tab, not spacespacespacespace
This patch releases the lock in get_device_regulator(), makes get_lowest_stable_voltage() non inline and fixes a minor indentation issue.
--- drivers/regulator/reg-core.c | 5 +++-- 1 files changed, 3 insertions(+), 2 deletions(-)
drivers/regulator/reg-core.c +3 -2
@@ -85,6 +85,7 @@ static struct regulator *get_device_regulator(struct device *dev)list_for_each_entry (regulator, &rcdev->consumer_list, list) {if (regulator->dev == dev) {mutex_unlock (&rcdev->mutex); +mutex_unlock (®ulator_list_mutex);return regulator; } }
@@ -336,7 +337,7 @@ struct class regulator_class = { };/* find the lowest stable voltage that all enabled clients can operate at */ -static inline int get_lowest_stable_voltage (struct regulator_cdev *rcdev) +static int get_lowest_stable_voltage (struct regulator_cdev *rcdev) {struct regulator *regulator;int highest_uV =0 ;
@@ -387,7 +388,7 @@ static void drms_uA_update(struct regulator_cdev *rcdev)/* calc total requested load */ list_for_each_entry (sibling, &rcdev->consumer_list, list) - current_uA += sibling->uA_load; + current_uA += sibling->uA_load;/* now get the optimum mode for our new total regulator load */ mode = rcdev->desc->ops->get_optimum_mode(rcdev, input_uV,
Signature · 1 line
1.5.4.3
Quoted 5 lines · On Sat, 08 Mar 2008 17:24:46 +0000 Liam Girdwood…
Quoted 1 line
Should be indented with a tab, not spacespacespacespace
This patch releases the lock in
get_device_regulator(), makesget_lowest_stable_voltage()non inline and fixes a minor indentation issue.
OK, I'll toss it in there, thanks.
It sounds like significant changes will be happening and that we can expect to see a new patchset?
I assume you noted my s/get_current/read_current/g fix? It'll be needed for alpha, frv and mn10300. read_current() is a pretty crappy name but I couldn't think of anything better. It would look nicer if we also did s/get_voltage/read_voltage/g - your call.
Quoted 4 lines · Andrew Morton
Quoted 2 lines · On Sat, 08 Mar 2008 17:24:46 +0000 Liam Girdwood…
Quoted 1 line
Should be indented with a tab, not spacespacespacespace
Quoted 9 lines
Quoted 3 lines
This patch releases the lock in
get_device_regulator(), makesget_lowest_stable_voltage()non inline and fixes a minor indentation issue.OK, I'll toss it in there, thanks.
It sounds like significant changes will be happening and that we can expect to see a new patchset?
Yep, I have some customer stuff to do at the start of the week so I'll be able to send some new patches later in the week.
Quoted 4 lines
I assume you noted my s/get_current/read_current/g fix? It'll be needed for alpha, frv and mn10300.
read_current()is a pretty crappy name but I couldn't think of anything better. It would look nicer if we also did s/get_voltage/read_voltage/g - your call.
ok, will do.
Liam
Quoted 48 lines · Liam Girdwood
This patch provides the regulator framework core. The core also provides a sysfs interface for userspace information.
Signed-off-by Liam Girdwood <[email protected]>--- drivers/regulator/reg-core.c | 1311 ++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 1311 insertions(+), 0 deletions(-) create mode 100644 drivers/regulator/reg-core.cdrivers/regulator/reg-core.c new file +33
-0@@ -0,0 +1,1311 @@ +/* +* regulator.c -- Voltage/Current Regulator framework. +* +* Copyright 2007, 2008 Wolfson Microelectronics PLC. +* +* Author: Liam Girdwood <[email protected]> +* +* This program is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by the +* Free Software Foundation; either version 2 of the License, or (at your +* option) any later version. +* +*/ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/device.h> +#include <linux/err.h> +#include <linux/mutex.h> +#include <linux/regulator/regulator.h> +#include <linux/regulator/regulator-drv.h> +#include <linux/regulator/regulator-platform.h> + +#define REGULATOR_VERSION "0.4" + +static DEFINE_MUTEX (regulator_list_mutex); +static LIST_HEAD (regulator_list); + +/** +* struct regulator_cdev +* +* Voltage / Current regulator class device. One for each regulator. +*/
drivers/regulator/reg-core.c line 43
Quoted 10 lines
drivers/regulator/reg-core.c new file +10
-0+struct regulator_cdev { +struct regulator_desc *desc; +int use_count; + +struct list_head list; +struct list_head consumer_list; +struct blocking_notifier_head notifier; +struct mutex mutex;/* consumer lock */ +struct module *owner; +struct class_device cdev;
Can you change this to use a "struct device" instead? We are trying to get rid of class_device, and there are only 3 users of it in the kernel today (memorystick, infiniband, and scsi), and I have patches pending to fix all of these. For 2.6.26 I would like to be rid of it finally.
If you want, I would be glad to fix this up for you, it should be a pretty simple replacement.
drivers/regulator/reg-core.c line 45
Quoted 2 lines
drivers/regulator/reg-core.c new file +2
-0+struct regulation_constraints *constraints; +struct regulator_cdev *parent;/* for tree */
And if when you convert, you can get rid of this pointer, it would not be needed.
drivers/regulator/reg-core.c line 47
Quoted 1 line
drivers/regulator/reg-core.c new file +1
-0+void *reg_data;/* regulator_cdev data */
Nor would this one. Actually I don't think you need this one today anyway...
thanks,
greg k-h
Quoted 23 lines · Greg KH
Quoted 5 lines · Liam Girdwood
drivers/regulator/reg-core.c new file +5
-0+/** +* struct regulator_cdev +* +* Voltage / Current regulator class device. One for each regulator. +*/ drivers/regulator/reg-core.c line 43
Quoted 10 lines
drivers/regulator/reg-core.c new file +10
-0+struct regulator_cdev { +struct regulator_desc *desc; +int use_count; + +struct list_head list; +struct list_head consumer_list; +struct blocking_notifier_head notifier; +struct mutex mutex;/* consumer lock */ +struct module *owner; +struct class_device cdev;Can you change this to use a "struct device" instead? We are trying to get rid of
class_device, and there are only 3 users of it in the kernel today (memorystick, infiniband, and scsi), and I have patches pending to fix all of these. For 2.6.26 I would like to be rid of it finally.
Quoted 3 lines
If you want, I would be glad to fix this up for you, it should be a pretty simple replacement.
Yes please. Much appreciated :)
Quoted 5 lines
drivers/regulator/reg-core.c line 45
Quoted 2 lines
drivers/regulator/reg-core.c new file +2
-0+struct regulation_constraints *constraints; +struct regulator_cdev *parent;/* for tree */ And if when you convert, you can get rid of this pointer, it would not be needed.
Fwiw, the regulator-parent relationship is established by the platform code after the regulator driver has registered all the regulator devices. I assume we can just device_move() to re-parent.
It may also be nice to have a link like /sys/power/regulator -> /sys/devices/.../regulator
Quoted 6 lines
drivers/regulator/reg-core.c line 47
Quoted 2 lines
drivers/regulator/reg-core.c new file +1
-0+void *reg_data;/* regulator_cdev data */ Nor would this one. Actually I don't think you need this one today anyway...
Agreed, this is just driver_data for the regulator driver.
Many Thanks
Liam
Quoted 24 lines · Liam Girdwood
Quoted 23 lines · Greg KH
Quoted 5 lines · Liam Girdwood
(quoted diff) +5
-0+/** + * struct regulator_cdev + * + * Voltage / Current regulator class device. One for each regulator. + */Review
Quoted 10 lines
(quoted diff) +10
-0+struct regulator_cdev { + struct regulator_desc *desc; + int use_count; + + struct list_head list; + struct list_head consumer_list; + struct blocking_notifier_head notifier; + struct mutex mutex; /* consumer lock */ + struct module *owner; + struct class_device cdev;Can you change this to use a "struct device" instead? We are trying to get rid of
class_device, and there are only 3 users of it in the kernel today (memorystick, infiniband, and scsi), and I have patches pending to fix all of these. For 2.6.26 I would like to be rid of it finally.
Quoted 5 lines
Quoted 3 lines
If you want, I would be glad to fix this up for you, it should be a pretty simple replacement.
Yes please. Much appreciated :)
Ok, it's below, on top of your patch series. If you want me to merge it in, I can do that as well. It's a bit big, as I renamed "cdev" to "dev" in your structure names and variable names as it isn't a class device anymore.
Quoted 9 lines
Quoted 5 lines
Review
Quoted 2 lines
(quoted diff) +2
-0+ struct regulation_constraints *constraints; + struct regulator_cdev *parent; /* for tree */And if when you convert, you can get rid of this pointer, it would not be needed.
Fwiw, the regulator-parent relationship is established by the platform code after the regulator driver has registered all the regulator devices. I assume we can just
device_move()to re-parent.
Ick, no, just pass the parent into the regulator_register() function. Otherwise you will get some wierd uevents spit out (run udevmonitor to see what I mean.) You should set up the parent linkage before you register the device with the driver core.
Quoted 2 lines
It may also be nice to have a link like
/sys/power/regulator->/sys/devices/.../regulator
why? You should be able to get there from the /sys/class/regulator/ links now, right?
Quoted 8 lines
Quoted 6 lines
Review
Quoted 2 lines
(quoted diff) +1
-0+ void *reg_data; /* regulator_cdev data */Nor would this one. Actually I don't think you need this one today anyway...
Agreed, this is just
driver_datafor the regulator driver.
I didn't change that in this patch, I'll let you do that :)
If you have any questions about this patch, or need anything else, please let me know.
thanks,
greg k-h
---------------
Subject: regulator: convert class_device to device
We also rename the functions and variables as "cdev" no longer makes any sense.
--- drivers/regulator/reg-core.c | 575 ++++++++++++++++---------------- include/linux/regulator/regulator-drv.h | 32 - 2 files changed, 307 insertions(+), 300 deletions(-)
drivers/regulator/reg-core.c +291 -284
@@ -27,11 +27,11 @@ static DEFINE_MUTEX(regulator_list_mutexstatic LIST_HEAD (regulator_list);/** -* struct regulator_cdev +* struct regulator_dev * * Voltage / Current regulator class device. One for each regulator. */ -struct regulator_cdev { +struct regulator_dev {struct regulator_desc *desc;int use_count;
@@ -40,16 +40,16 @@ struct regulator_cdev {struct blocking_notifier_head notifier;struct mutex mutex;/* consumer lock */ struct module *owner; -struct class_device cdev; +struct device dev;struct regulation_constraints *constraints; -struct regulator_cdev *parent;/* for tree */ +struct regulator_dev *parent;/* for tree */ -void *reg_data;/* regulator_cdev data */ +void *reg_data;/* regulator_dev data */ }; -static inline struct regulator_cdev *to_rcdev (struct class_device *cd) +static inline struct regulator_dev *to_rdev (struct device *d) { - return container_of(cd, struct regulator_cdev, cdev); + return container_of(d, struct regulator_dev, dev); }/*
@@ -64,112 +64,112 @@ struct regulator {int uV_required;int enabled;/* client has called enabled */ struct device_attribute dev_attr; -struct regulator_cdev *rcdev; +struct regulator_dev *rdev; }; -static int _regulator_is_enabled (struct regulator_cdev *rcdev); -static int _regulator_disable (struct regulator_cdev *rcdev); -static int _regulator_get_voltage (struct regulator_cdev *rcdev); -static int _regulator_get_current (struct regulator_cdev *rcdev); -static unsigned int _regulator_get_mode (struct regulator_cdev *rcdev); +static int _regulator_is_enabled (struct regulator_dev *rdev); +static int _regulator_disable (struct regulator_dev *rdev); +static int _regulator_get_voltage (struct regulator_dev *rdev); +static int _regulator_get_current (struct regulator_dev *rdev); +static unsigned int _regulator_get_mode (struct regulator_dev *rdev);/* gets the regulator for a given consumer device */ static struct regulator *get_device_regulator (struct device *dev) {struct regulator *regulator =NULL ; -struct regulator_cdev *rcdev; +struct regulator_dev *rdev;mutex_lock (®ulator_list_mutex); -list_for_each_entry (rcdev, ®ulator_list, list) { -mutex_lock (&rcdev->mutex); -list_for_each_entry (regulator, &rcdev->consumer_list, list) { +list_for_each_entry (rdev, ®ulator_list, list) { +mutex_lock (&rdev->mutex); +list_for_each_entry (regulator, &rdev->consumer_list, list) {if (regulator->dev == dev) { -mutex_unlock (&rcdev->mutex); +mutex_unlock (&rdev->mutex);return regulator; } } -mutex_unlock (&rcdev->mutex); +mutex_unlock (&rdev->mutex); }mutex_unlock (®ulator_list_mutex);return NULL ; }/* voltage constraint check */ -static int regulator_check_voltage (struct regulator_cdev *rcdev,int uV) +static int regulator_check_voltage (struct regulator_dev *rdev,int uV) { -if (!rcdev->constraints) { +if (!rdev->constraints) {printk (KERN_ERR "%s: no constraints for %s\n" , __func__, - rcdev->desc->name); + rdev->desc->name);return -ENODEV ; } -if (!(rcdev->constraints->valid_ops_mask ®ULATOR_CHANGE_VOLTAGE )) { +if (!(rdev->constraints->valid_ops_mask ®ULATOR_CHANGE_VOLTAGE )) {printk (KERN_ERR "%s: operation not allowed for %s\n" , - __func__, rcdev->desc->name); + __func__, rdev->desc->name);return -EPERM ; } -if (uV > rcdev->constraints->max_uV || - uV < rcdev->constraints->min_uV) { +if (uV > rdev->constraints->max_uV || + uV < rdev->constraints->min_uV) {printk (KERN_ERR "%s: invalid voltage %duV for %s\n" , - __func__, uV, rcdev->desc->name); + __func__, uV, rdev->desc->name);return -EINVAL ; }return 0 ; }/* current constraint check */ -static int regulator_check_current (struct regulator_cdev *rcdev,int uA) +static int regulator_check_current (struct regulator_dev *rdev,int uA) { -if (!rcdev->constraints) { +if (!rdev->constraints) {printk (KERN_ERR "%s: no constraints for %s\n" , __func__, - rcdev->desc->name); + rdev->desc->name);return -ENODEV ; } -if (!(rcdev->constraints->valid_ops_mask ®ULATOR_CHANGE_CURRENT )) { +if (!(rdev->constraints->valid_ops_mask ®ULATOR_CHANGE_CURRENT )) {printk (KERN_ERR "%s: operation not allowed for %s\n" , - __func__, rcdev->desc->name); + __func__, rdev->desc->name);return -EPERM ; } -if (uA > rcdev->constraints->max_uA || - uA < rcdev->constraints->min_uA) { +if (uA > rdev->constraints->max_uA || + uA < rdev->constraints->min_uA) {printk (KERN_ERR "%s: invalid current %duA for %s\n" , - __func__, uA, rcdev->desc->name); + __func__, uA, rdev->desc->name);return -EINVAL ; }return 0 ; }/* operating mode constraint check */ -static int regulator_check_mode (struct regulator_cdev *rcdev,int mode) +static int regulator_check_mode (struct regulator_dev *rdev,int mode) { -if (!rcdev->constraints) { +if (!rdev->constraints) {printk (KERN_ERR "%s: no constraints for %s\n" , __func__, - rcdev->desc->name); + rdev->desc->name);return -ENODEV ; } -if (!(rcdev->constraints->valid_ops_mask ®ULATOR_CHANGE_MODE )) { +if (!(rdev->constraints->valid_ops_mask ®ULATOR_CHANGE_MODE )) {printk (KERN_ERR "%s: operation not allowed for %s\n" , - __func__, rcdev->desc->name); + __func__, rdev->desc->name);return -EPERM ; } -if (!(rcdev->constraints->valid_modes_mask & mode)) { +if (!(rdev->constraints->valid_modes_mask & mode)) {printk (KERN_ERR "%s: invalid mode %x for %s\n" , - __func__, mode, rcdev->desc->name); + __func__, mode, rdev->desc->name);return -EINVAL ; }return 0 ; }/* dynamic regulator mode switching constraint check */ -static int regulator_check_drms (struct regulator_cdev *rcdev) +static int regulator_check_drms (struct regulator_dev *rdev) { -if (!rcdev->constraints) { +if (!rdev->constraints) {printk (KERN_ERR "%s: no constraints for %s\n" , __func__, - rcdev->desc->name); + rdev->desc->name);return -ENODEV ; } -if (!(rcdev->constraints->valid_ops_mask ®ULATOR_CHANGE_DRMS )) { +if (!(rdev->constraints->valid_ops_mask ®ULATOR_CHANGE_DRMS )) {printk (KERN_ERR "%s: operation not allowed for %s\n" , - __func__, rcdev->desc->name); + __func__, rdev->desc->name);return -EPERM ; }return 0 ;
@@ -187,24 +187,27 @@ static ssize_t device_requested_uA_show(return sprintf (buf,"%d\n" , regulator->uA_load); } -static ssize_t regulator_uV_show (struct class_device *cdev,char *buf) +static ssize_t regulator_uV_show (struct device *dev, +struct device_attribute *attr,char *buf) { -struct regulator_cdev *rcdev =to_rcdev (cdev); +struct regulator_dev *rdev =to_rdev (dev); -return sprintf (buf,"%d\n" ,_regulator_get_voltage (rcdev)); +return sprintf (buf,"%d\n" ,_regulator_get_voltage (rdev)); } -static ssize_t regulator_uA_show (struct class_device *cdev,char *buf) +static ssize_t regulator_uA_show (struct device *dev, +struct device_attribute *attr,char *buf) { -struct regulator_cdev *rcdev =to_rcdev (cdev); +struct regulator_dev *rdev =to_rdev (dev); -return sprintf (buf,"%d\n" ,_regulator_get_current (rcdev)); +return sprintf (buf,"%d\n" ,_regulator_get_current (rdev)); } -static ssize_t regulator_opmode_show (struct class_device *cdev,char *buf) +static ssize_t regulator_opmode_show (struct device *dev, +struct device_attribute *attr,char *buf) { -struct regulator_cdev *rcdev =to_rcdev (cdev); -int mode =_regulator_get_mode (rcdev); +struct regulator_dev *rdev =to_rdev (dev); +int mode =_regulator_get_mode (rdev);switch (mode) {case REGULATOR_MODE_FAST :
@@ -219,10 +222,11 @@ static ssize_t regulator_opmode_show(strreturn sprintf (buf,"unknown\n" ); } -static ssize_t regulator_state_show (struct class_device *cdev,char *buf) +static ssize_t regulator_state_show (struct device *dev, +struct device_attribute *attr,char *buf) { -struct regulator_cdev *rcdev =to_rcdev (cdev); -int state =_regulator_is_enabled (rcdev); +struct regulator_dev *rdev =to_rdev (dev); +int state =_regulator_is_enabled (rdev);if (state >0 )return sprintf (buf,"enabled\n" );
@@ -232,74 +236,77 @@ static ssize_t regulator_state_show(strureturn sprintf (buf,"unknown\n" ); } -static ssize_t regulator_min_uA_show (struct class_device *cdev, -char *buf) +static ssize_t regulator_min_uA_show (struct device *dev, +struct device_attribute *attr,char *buf) { -struct regulator_cdev *rcdev =to_rcdev (cdev); +struct regulator_dev *rdev =to_rdev (dev); -if (!rcdev->constraints) +if (!rdev->constraints)return sprintf (buf,"constraint not defined\n" ); -return sprintf (buf,"%d\n" , rcdev->constraints->min_uA); +return sprintf (buf,"%d\n" , rdev->constraints->min_uA); } -static ssize_t regulator_max_uA_show (struct class_device *cdev, -char *buf) +static ssize_t regulator_max_uA_show (struct device *dev, +struct device_attribute *attr,char *buf) { -struct regulator_cdev *rcdev =to_rcdev (cdev); +struct regulator_dev *rdev =to_rdev (dev); -if (!rcdev->constraints) +if (!rdev->constraints)return sprintf (buf,"constraint not defined\n" ); -return sprintf (buf,"%d\n" , rcdev->constraints->max_uA); +return sprintf (buf,"%d\n" , rdev->constraints->max_uA); } -static ssize_t regulator_min_uV_show (struct class_device *cdev, -char *buf) +static ssize_t regulator_min_uV_show (struct device *dev, +struct device_attribute *attr,char *buf) { -struct regulator_cdev *rcdev =to_rcdev (cdev); +struct regulator_dev *rdev =to_rdev (dev); -if (!rcdev->constraints) +if (!rdev->constraints)return sprintf (buf,"constraint not defined\n" ); -return sprintf (buf,"%d\n" , rcdev->constraints->min_uV); +return sprintf (buf,"%d\n" , rdev->constraints->min_uV); } -static ssize_t regulator_max_uV_show (struct class_device *cdev, -char *buf) +static ssize_t regulator_max_uV_show (struct device *dev, +struct device_attribute *attr,char *buf) { -struct regulator_cdev *rcdev =to_rcdev (cdev); +struct regulator_dev *rdev =to_rdev (dev); -if (!rcdev->constraints) +if (!rdev->constraints)return sprintf (buf,"constraint not defined\n" ); -return sprintf (buf,"%d\n" , rcdev->constraints->max_uV); +return sprintf (buf,"%d\n" , rdev->constraints->max_uV); } -static ssize_t regulator_total_uA_show (struct class_device *cdev,char *buf) +static ssize_t regulator_total_uA_show (struct device *dev, +struct device_attribute *attr,char *buf) { -struct regulator_cdev *rcdev =to_rcdev (cdev); +struct regulator_dev *rdev =to_rdev (dev);struct regulator *regulator;int uA =0 ; -mutex_lock (&rcdev->mutex); -list_for_each_entry (regulator, &rcdev->consumer_list, list) +mutex_lock (&rdev->mutex); +list_for_each_entry (regulator, &rdev->consumer_list, list) uA += regulator->uA_load; -mutex_unlock (&rcdev->mutex); +mutex_unlock (&rdev->mutex);return sprintf (buf,"%d\n" , uA); } -static ssize_t regulator_num_users_show (struct class_device *cdev,char *buf) +static ssize_t regulator_num_users_show (struct device *dev, +struct device_attribute *att,char *buf) { -struct regulator_cdev *rcdev =to_rcdev (cdev); -return sprintf (buf,"%d\n" , rcdev->use_count); +struct regulator_dev *rdev =to_rdev (dev); +return sprintf (buf,"%d\n" , rdev->use_count); } -static ssize_t regulator_type_show (struct class_device *cdev,char *buf) +static ssize_t regulator_type_show (struct device *dev, +struct device_attribute *attr,char *buf) { -struct regulator_cdev *rcdev =to_rcdev (cdev); +struct regulator_dev *rdev =to_rdev (dev); -switch (rcdev->desc->type) { +switch (rdev->desc->type) {case REGULATOR_VOLTAGE :return sprintf (buf,"voltage\n" );case REGULATOR_CURRENT :
@@ -308,7 +315,7 @@ static ssize_t regulator_type_show(strucreturn sprintf (buf,"unknown\n" ); } -static struct class_device_attribute regulator_dev_attrs[] = { +static struct device_attribute regulator_dev_attrs[] = {__ATTR (microvolts,0444 , regulator_uV_show,NULL ),__ATTR (microamps,0444 , regulator_uA_show,NULL ),__ATTR (opmode,0444 , regulator_opmode_show,NULL ),
@@ -323,26 +330,26 @@ static struct class_device_attribute reg __ATTR_NULL, }; -static void regulator_dev_release (struct class_device *cdev) +static void regulator_dev_release (struct device *dev) { -struct regulator_cdev *rcdev =to_rcdev (cdev); -kfree (rcdev); +struct regulator_dev *rdev =to_rdev (dev); +kfree (rdev); }struct class regulator_class = { .name ="regulator" , - .release = regulator_dev_release, - .class_dev_attrs = regulator_dev_attrs, + .dev_release = regulator_dev_release, + .dev_attrs = regulator_dev_attrs, };/* find the lowest stable voltage that all enabled clients can operate at */ -static inline int get_lowest_stable_voltage (struct regulator_cdev *rcdev) +static inline int get_lowest_stable_voltage (struct regulator_dev *rdev) {struct regulator *regulator;int highest_uV =0 ;/* lock is held by caller */ -list_for_each_entry (regulator, &rcdev->consumer_list, list) { +list_for_each_entry (regulator, &rdev->consumer_list, list) {if (regulator->enabled && regulator->uV_required > highest_uV) highest_uV = regulator->uV_required; }
@@ -351,61 +358,61 @@ static inline int get_lowest_stable_volt/* Set the regulator voltage to the lowest possible value that can safely * support all the client devices */ -static int regulator_set_stable_voltage (struct regulator_cdev *rcdev) +static int regulator_set_stable_voltage (struct regulator_dev *rdev) {int ret =0 , uV; -if (rcdev->desc->type ==REGULATOR_VOLTAGE ) { - uV =get_lowest_stable_voltage (rcdev); -if (uV && rcdev->desc->ops->set_voltage) - ret = rcdev->desc->ops->set_voltage (rcdev, uV); +if (rdev->desc->type ==REGULATOR_VOLTAGE ) { + uV =get_lowest_stable_voltage (rdev); +if (uV && rdev->desc->ops->set_voltage) + ret = rdev->desc->ops->set_voltage (rdev, uV); }return ret; }/* Calculate the new optimum regulator operating mode based on the new total * consumer load. All locks held by caller */ -static void drms_uA_update (struct regulator_cdev *rcdev) +static void drms_uA_update (struct regulator_dev *rdev) {struct regulator *sibling;int current_uA =0 , output_uV, input_uV, err;unsigned int mode; - err =regulator_check_drms (rcdev); -if (err <0 || !rcdev->desc->ops->get_optimum_mode || - !rcdev->desc->ops->get_voltage || !rcdev->desc->ops->set_mode); + err =regulator_check_drms (rdev); +if (err <0 || !rdev->desc->ops->get_optimum_mode || + !rdev->desc->ops->get_voltage || !rdev->desc->ops->set_mode);return ;/* get output voltage */ - output_uV = rcdev->desc->ops->get_voltage (rcdev); + output_uV = rdev->desc->ops->get_voltage (rdev);/* get input voltage */ -if (rcdev->parent && rcdev->parent->desc->ops->get_voltage) - input_uV = rcdev->parent->desc->ops->get_voltage (rcdev->parent); +if (rdev->parent && rdev->parent->desc->ops->get_voltage) + input_uV = rdev->parent->desc->ops->get_voltage (rdev->parent);else - input_uV = rcdev->constraints->input_uV; + input_uV = rdev->constraints->input_uV;/* calc total requested load */ -list_for_each_entry (sibling, &rcdev->consumer_list, list) +list_for_each_entry (sibling, &rdev->consumer_list, list) current_uA += sibling->uA_load;/* now get the optimum mode for our new total regulator load */ - mode = rcdev->desc->ops->get_optimum_mode (rcdev, input_uV, + mode = rdev->desc->ops->get_optimum_mode (rdev, input_uV, output_uV, current_uA);/* check the new mode is allowed */ - err =regulator_check_mode (rcdev, mode); + err =regulator_check_mode (rdev, mode);if (err ==0 ) - rcdev->desc->ops->set_mode (rcdev, mode); + rdev->desc->ops->set_mode (rdev, mode); } -static void print_constraints (struct regulator_cdev *rcdev) +static void print_constraints (struct regulator_dev *rdev) { -struct regulation_constraints *constraints = rcdev->constraints; +struct regulation_constraints *constraints = rdev->constraints;char buf[80 ];int count; -if (rcdev->desc->type ==REGULATOR_VOLTAGE ) { +if (rdev->desc->type ==REGULATOR_VOLTAGE ) {if (constraints->min_uV == constraints->max_uV) count =sprintf (buf,"%d mV " ,uV_to_mV (constraints->min_uV));
@@ -431,12 +438,12 @@ static void print_constraints(struct regif (constraints->valid_modes_mask ®ULATOR_MODE_STANDBY ) count +=sprintf (buf + count,"standby" ); -printk (KERN_INFO "regulator: %s: %s\n" , rcdev->desc->name, buf); +printk (KERN_INFO "regulator: %s: %s\n" , rdev->desc->name, buf); }#define REG_STR_SIZE 32 -static struct regulator *create_regulator (struct regulator_cdev *rcdev, +static struct regulator *create_regulator (struct regulator_dev *rdev,struct device *dev) {struct regulator *regulator;
@@ -447,14 +454,14 @@ static struct regulator *create_regulatoif (regulator ==NULL )return NULL ; -mutex_lock (&rcdev->mutex); - regulator->rcdev = rcdev; -list_add (®ulator->list, &rcdev->consumer_list); +mutex_lock (&rdev->mutex); + regulator->rdev = rdev; +list_add (®ulator->list, &rdev->consumer_list);if (dev) {/* create a 'requested_microamps_name' sysfs entry */ size =scnprintf (buf,REG_STR_SIZE ,"microamps_requested_%s" , - regulator->rcdev->desc->name); + regulator->rdev->desc->name);if (size >=REG_STR_SIZE ) goto overflow_err;
@@ -468,13 +475,13 @@ static struct regulator *create_regulato regulator->dev_attr.show = device_requested_uA_show; err =device_create_file (dev, ®ulator->dev_attr);if (err <0 ) { -printk (KERN_WARNING "%s: could not add regulator_cdev" +printk (KERN_WARNING "%s: could not add regulator_dev" " load sysfs\n" , __func__); goto err_out; }/* also add a link to the device sysfs entry */ - err =sysfs_create_link (&rcdev->cdev.kobj, &dev->kobj, + err =sysfs_create_link (&rdev->dev.kobj, &dev->kobj, dev->kobj.name);if (err) { printk(KERN_WARNING
@@ -484,14 +491,14 @@ static struct regulator *create_regulato goto err_out; } } -mutex_unlock (&rcdev->mutex); +mutex_unlock (&rdev->mutex);return regulator; err_out:kfree (regulator->dev_attr.attr.name); overflow_err:list_del (®ulator->list);kfree (regulator); -mutex_unlock (&rcdev->mutex); +mutex_unlock (&rdev->mutex);return NULL ; }
@@ -505,16 +512,16 @@ overflow_err:*/ struct regulator *regulator_get (struct device *dev,const char *id) { -struct regulator_cdev *rcdev; +struct regulator_dev *rdev;struct regulator *regulator =ERR_PTR (-ENODEV );if (id ==NULL )return regulator;mutex_lock (®ulator_list_mutex); -list_for_each_entry (rcdev, ®ulator_list, list) { -if (strcmp (id, rcdev->desc->name) ==0 && -try_module_get (rcdev->owner)) { +list_for_each_entry (rdev, ®ulator_list, list) { +if (strcmp (id, rdev->desc->name) ==0 && +try_module_get (rdev->owner)) { goto found; } }
@@ -524,10 +531,10 @@ struct regulator *regulator_get(struct dreturn regulator; found: - regulator =create_regulator (rcdev, dev); + regulator =create_regulator (rdev, dev);if (regulator ==NULL ) { regulator =ERR_PTR (-ENOMEM ); -module_put (rcdev->owner); +module_put (rdev->owner); }mutex_unlock (®ulator_list_mutex);
@@ -545,65 +552,65 @@ EXPORT_SYMBOL_GPL(regulator_get);*/ void regulator_put (struct regulator *regulator) { -struct regulator_cdev *rcdev; +struct regulator_dev *rdev;if (regulator ==NULL ||IS_ERR (regulator))return ;mutex_lock (®ulator_list_mutex); - rcdev = regulator->rcdev; + rdev = regulator->rdev;/* remove any sysfs entries */ if (regulator->dev) { -sysfs_remove_link (&rcdev->cdev.kobj, regulator->dev->kobj.name); +sysfs_remove_link (&rdev->dev.kobj, regulator->dev->kobj.name);device_remove_file (regulator->dev, ®ulator->dev_attr);kfree (regulator->dev_attr.attr.name); }list_del (®ulator->list);kfree (regulator); -module_put (rcdev->owner); +module_put (rdev->owner);mutex_unlock (®ulator_list_mutex); }EXPORT_SYMBOL_GPL (regulator_put);/* locks held by regulator_enable() */ -static int _regulator_enable (struct regulator_cdev *rcdev) +static int _regulator_enable (struct regulator_dev *rdev) {int ret = -EINVAL ;/* do we need to enable the parent regulator first */ -if (rcdev->parent) { - ret =_regulator_enable (rcdev->parent); +if (rdev->parent) { + ret =_regulator_enable (rdev->parent);if (ret <0 ) {printk (KERN_ERR "%s: failed to enable %s\n" , - __func__, rcdev->desc->name); + __func__, rdev->desc->name);return ret; } }/* check voltage and requested load before enabling */ -if (rcdev->desc->ops->enable) { - ret =regulator_set_stable_voltage (rcdev); +if (rdev->desc->ops->enable) { + ret =regulator_set_stable_voltage (rdev);if (ret <0 ) {printk (KERN_ERR "%s: invalid voltage for %s\n" , - __func__, rcdev->desc->name); + __func__, rdev->desc->name);return ret; } -if (rcdev->constraints && - (rcdev->constraints->valid_ops_mask & +if (rdev->constraints && + (rdev->constraints->valid_ops_mask ®ULATOR_CHANGE_DRMS )) -drms_uA_update (rcdev); +drms_uA_update (rdev); - ret = rcdev->desc->ops->enable (rcdev); + ret = rdev->desc->ops->enable (rdev);if (ret <0 ) {printk (KERN_ERR "%s: failed to enable %s\n" , - __func__, rcdev->desc->name); + __func__, rdev->desc->name);return ret; } - rcdev->use_count++; + rdev->use_count++;return ret; }
@@ -624,50 +631,50 @@ int regulator_enable(struct regulator *r {int ret; -mutex_lock (®ulator->rcdev->mutex); +mutex_lock (®ulator->rdev->mutex); regulator->enabled =0 ; - ret =_regulator_enable (regulator->rcdev); + ret =_regulator_enable (regulator->rdev);if (ret ==0 ) regulator->enabled =1 ; -mutex_unlock (®ulator->rcdev->mutex); +mutex_unlock (®ulator->rdev->mutex);return ret; }EXPORT_SYMBOL_GPL (regulator_enable);/* locks held by regulator_disable() */ -static int _regulator_disable (struct regulator_cdev *rcdev) +static int _regulator_disable (struct regulator_dev *rdev) {int ret =0 ;/* are we the last user of this regulator */ -if (rcdev->use_count ==1 ) { +if (rdev->use_count ==1 ) {/* last user - then disable */ -if (rcdev->desc->ops->disable) { - ret = rcdev->desc->ops->disable (rcdev); +if (rdev->desc->ops->disable) { + ret = rdev->desc->ops->disable (rdev);if (ret <0 ) {printk (KERN_ERR "%s: failed to disable %s\n" , - __func__, rcdev->desc->name); + __func__, rdev->desc->name);return ret; } }/* decrease our parents ref count and disable if required */ -if (rcdev->parent) -_regulator_disable (rcdev->parent); +if (rdev->parent) +_regulator_disable (rdev->parent); - rcdev->use_count =0 ; - }else if (rcdev->use_count >1 ) { + rdev->use_count =0 ; + }else if (rdev->use_count >1 ) {/* find the most efficient voltage and mode now that we * have one less consumer device. */ - ret =regulator_set_stable_voltage (rcdev); + ret =regulator_set_stable_voltage (rdev); -if (rcdev->constraints && - (rcdev->constraints->valid_ops_mask & +if (rdev->constraints && + (rdev->constraints->valid_ops_mask ®ULATOR_CHANGE_DRMS )) -drms_uA_update (rcdev); +drms_uA_update (rdev); - rcdev->use_count--; + rdev->use_count--; }return ret; }
@@ -686,30 +693,30 @@ int regulator_disable(struct regulator * {int ret; -mutex_lock (®ulator->rcdev->mutex); +mutex_lock (®ulator->rdev->mutex); regulator->enabled =0 ; regulator->uA_load =0 ; - ret =_regulator_disable (regulator->rcdev); -mutex_unlock (®ulator->rcdev->mutex); + ret =_regulator_disable (regulator->rdev); +mutex_unlock (®ulator->rdev->mutex);return ret; }EXPORT_SYMBOL_GPL (regulator_disable); -static int _regulator_is_enabled (struct regulator_cdev *rcdev) +static int _regulator_is_enabled (struct regulator_dev *rdev) {int ret; -mutex_lock (&rcdev->mutex); +mutex_lock (&rdev->mutex);/* sanity check */ -if (!rcdev->desc->ops->is_enabled) { +if (!rdev->desc->ops->is_enabled) { ret = -EINVAL ; goto out; } - ret = rcdev->desc->ops->is_enabled (rcdev); + ret = rdev->desc->ops->is_enabled (rdev); out: -mutex_unlock (&rcdev->mutex); +mutex_unlock (&rdev->mutex);return ret; }
@@ -721,7 +728,7 @@ out:*/ int regulator_is_enabled (struct regulator *regulator) { -return _regulator_is_enabled (regulator->rcdev); +return _regulator_is_enabled (regulator->rdev); }EXPORT_SYMBOL_GPL (regulator_is_enabled);
@@ -744,46 +751,46 @@ EXPORT_SYMBOL_GPL(regulator_is_enabled);*/ int regulator_set_voltage (struct regulator *regulator,int uV) { -struct regulator_cdev *rcdev = regulator->rcdev; +struct regulator_dev *rdev = regulator->rdev;int ret; -mutex_lock (&rcdev->mutex); +mutex_lock (&rdev->mutex);/* sanity check */ -if (!rcdev->desc->ops->set_voltage) { +if (!rdev->desc->ops->set_voltage) { ret = -EINVAL ; goto out; }/* constraints check */ - ret =regulator_check_voltage (rcdev, uV); + ret =regulator_check_voltage (rdev, uV);if (ret <0 ) goto out; regulator->uV_required = uV;/* only set the new voltage if it's all clients can use it */ - ret =regulator_set_stable_voltage (rcdev); + ret =regulator_set_stable_voltage (rdev); out: -mutex_unlock (&rcdev->mutex); +mutex_unlock (&rdev->mutex);return ret; }EXPORT_SYMBOL_GPL (regulator_set_voltage); -static int _regulator_get_voltage (struct regulator_cdev *rcdev) +static int _regulator_get_voltage (struct regulator_dev *rdev) {int ret; -mutex_lock (&rcdev->mutex); +mutex_lock (&rdev->mutex);/* sanity check */ -if (!rcdev->desc->ops->get_voltage) { +if (!rdev->desc->ops->get_voltage) { ret = -EINVAL ; goto out; } - ret = rcdev->desc->ops->get_voltage (rcdev); + ret = rdev->desc->ops->get_voltage (rdev); out: -mutex_unlock (&rcdev->mutex); +mutex_unlock (&rdev->mutex);return ret; }
@@ -798,7 +805,7 @@ out:*/ int regulator_get_voltage (struct regulator *regulator) { -return _regulator_get_voltage (regulator->rcdev); +return _regulator_get_voltage (regulator->rdev); }EXPORT_SYMBOL_GPL (regulator_get_voltage);
@@ -819,44 +826,44 @@ EXPORT_SYMBOL_GPL(regulator_get_voltage)*/ int regulator_set_current (struct regulator *regulator,int uA) { -struct regulator_cdev *rcdev = regulator->rcdev; +struct regulator_dev *rdev = regulator->rdev;int ret; -mutex_lock (&rcdev->mutex); +mutex_lock (&rdev->mutex);/* sanity check */ -if (!rcdev->desc->ops->set_current) { +if (!rdev->desc->ops->set_current) { ret = -EINVAL ; goto out; }/* constraints check */ - ret =regulator_check_current (rcdev, uA); + ret =regulator_check_current (rdev, uA);if (ret <0 ) goto out; - ret = rcdev->desc->ops->set_current (rcdev, uA); + ret = rdev->desc->ops->set_current (rdev, uA); out: -mutex_unlock (&rcdev->mutex); +mutex_unlock (&rdev->mutex);return ret; }EXPORT_SYMBOL_GPL (regulator_set_current); -static int _regulator_get_current (struct regulator_cdev *rcdev) +static int _regulator_get_current (struct regulator_dev *rdev) {int ret; -mutex_lock (&rcdev->mutex); +mutex_lock (&rdev->mutex);/* sanity check */ -if (!rcdev->desc->ops->get_current) { +if (!rdev->desc->ops->get_current) { ret = -EINVAL ; goto out; } - ret = rcdev->desc->ops->get_current (rcdev); + ret = rdev->desc->ops->get_current (rdev); out: -mutex_unlock (&rcdev->mutex); +mutex_unlock (&rdev->mutex);return ret; }
@@ -871,7 +878,7 @@ out:*/ int regulator_get_current (struct regulator *regulator) { -return _regulator_get_current (regulator->rcdev); +return _regulator_get_current (regulator->rdev); }EXPORT_SYMBOL_GPL (regulator_get_current);
@@ -888,44 +895,44 @@ EXPORT_SYMBOL_GPL(regulator_get_current)*/ int regulator_set_mode (struct regulator *regulator,unsigned int mode) { -struct regulator_cdev *rcdev = regulator->rcdev; +struct regulator_dev *rdev = regulator->rdev;int ret; -mutex_lock (&rcdev->mutex); +mutex_lock (&rdev->mutex);/* sanity check */ -if (!rcdev->desc->ops->set_mode) { +if (!rdev->desc->ops->set_mode) { ret = -EINVAL ; goto out; }/* constraints check */ - ret =regulator_check_mode (rcdev, mode); + ret =regulator_check_mode (rdev, mode);if (ret <0 ) goto out; - ret = rcdev->desc->ops->set_mode (rcdev, mode); + ret = rdev->desc->ops->set_mode (rdev, mode); out: -mutex_unlock (&rcdev->mutex); +mutex_unlock (&rdev->mutex);return ret; }EXPORT_SYMBOL_GPL (regulator_set_mode); -static unsigned int _regulator_get_mode (struct regulator_cdev *rcdev) +static unsigned int _regulator_get_mode (struct regulator_dev *rdev) {int ret; -mutex_lock (&rcdev->mutex); +mutex_lock (&rdev->mutex);/* sanity check */ -if (!rcdev->desc->ops->get_mode) { +if (!rdev->desc->ops->get_mode) { ret = -EINVAL ; goto out; } - ret = rcdev->desc->ops->get_mode (rcdev); + ret = rdev->desc->ops->get_mode (rdev); out: -mutex_unlock (&rcdev->mutex); +mutex_unlock (&rdev->mutex);return ret; }
@@ -937,28 +944,28 @@ out:*/ unsigned int regulator_get_mode (struct regulator *regulator) { -return _regulator_get_mode (regulator->rcdev); +return _regulator_get_mode (regulator->rdev); }EXPORT_SYMBOL_GPL (regulator_get_mode); -static unsigned int _regulator_get_optimum_mode (struct regulator_cdev *rcdev, +static unsigned int _regulator_get_optimum_mode (struct regulator_dev *rdev,int input_uV,int output_uV,int load_uA) {int ret; -mutex_lock (&rcdev->mutex); +mutex_lock (&rdev->mutex);/* sanity check */ -if (!rcdev->desc->ops->get_optimum_mode) { +if (!rdev->desc->ops->get_optimum_mode) { ret = -EINVAL ; goto out; } - ret = rcdev->desc->ops->get_optimum_mode (rcdev, + ret = rdev->desc->ops->get_optimum_mode (rdev, input_uV, output_uV, load_uA); out: -mutex_unlock (&rcdev->mutex); +mutex_unlock (&rdev->mutex);return ret; }
@@ -976,7 +983,7 @@ unsigned int regulator_get_optimum_mode( int input_uV, int output_uV, int load_uA) { - return _regulator_get_optimum_mode(regulator->rcdev, input_uV, + return _regulator_get_optimum_mode(regulator->rdev, input_uV,output_uV ,load_uA ); }EXPORT_SYMBOL_GPL (regulator_get_optimum_mode);
@@ -991,7 +998,7 @@ EXPORT_SYMBOL_GPL(regulator_get_optimum_int regulator_register_client (struct regulator *regulator,struct notifier_block *nb) { -return blocking_notifier_chain_register (®ulator->rcdev->notifier, +return blocking_notifier_chain_register (®ulator->rdev->notifier, nb); }EXPORT_SYMBOL_GPL (regulator_register_client);
@@ -1006,7 +1013,7 @@ EXPORT_SYMBOL_GPL(regulator_register_cliint regulator_unregister_client (struct regulator *regulator,struct notifier_block *nb) { -return blocking_notifier_chain_unregister (®ulator->rcdev->notifier, +return blocking_notifier_chain_unregister (®ulator->rdev->notifier, nb); }EXPORT_SYMBOL_GPL (regulator_unregister_client);
@@ -1020,10 +1027,10 @@ EXPORT_SYMBOL_GPL(regulator_unregister_c* Called by regulator drivers to notify clients a regulator event has * occurred. */ -int regulator_notifier_call_chain (struct regulator_cdev *rcdev, +int regulator_notifier_call_chain (struct regulator_dev *rdev,unsigned long event,void *data) { -return blocking_notifier_call_chain (&rcdev->notifier, event, data); +return blocking_notifier_call_chain (&rdev->notifier, event, data); }EXPORT_SYMBOL_GPL (regulator_notifier_call_chain);
@@ -1035,11 +1042,11 @@ EXPORT_SYMBOL_GPL(regulator_notifier_cal* Called by regulator drivers to register a regulator. * Returns 0 on success. */ -struct regulator_cdev *regulator_register (struct regulator_desc *regulator_desc, +struct regulator_dev *regulator_register (struct regulator_desc *regulator_desc,void *reg_data) {static atomic_t regulator_no =ATOMIC_INIT (0 ); -struct regulator_cdev *rcdev; +struct regulator_dev *rdev;int ret;if (regulator_desc ==NULL )
@@ -1052,36 +1059,36 @@ struct regulator_cdev *regulator_registe !regulator_desc->type == REGULATOR_CURRENT)return ERR_PTR (-EINVAL ); - rcdev =kzalloc (sizeof (struct regulator_cdev ),GFP_KERNEL ); -if (rcdev ==NULL ) + rdev =kzalloc (sizeof (struct regulator_dev ),GFP_KERNEL ); +if (rdev ==NULL )return ERR_PTR (-ENOMEM );mutex_lock (®ulator_list_mutex); -mutex_init (&rcdev->mutex); - rcdev->reg_data = reg_data; - rcdev->owner = regulator_desc->owner; - rcdev->desc = regulator_desc; -INIT_LIST_HEAD (&rcdev->consumer_list); -INIT_LIST_HEAD (&rcdev->list); -BLOCKING_INIT_NOTIFIER_HEAD (&rcdev->notifier); - - rcdev->cdev.class = ®ulator_class; -class_device_initialize (&rcdev->cdev); -snprintf (rcdev->cdev.class_id,sizeof (rcdev->cdev.class_id), +mutex_init (&rdev->mutex); + rdev->reg_data = reg_data; + rdev->owner = regulator_desc->owner; + rdev->desc = regulator_desc; +INIT_LIST_HEAD (&rdev->consumer_list); +INIT_LIST_HEAD (&rdev->list); +BLOCKING_INIT_NOTIFIER_HEAD (&rdev->notifier); + + rdev->dev.class = ®ulator_class; +device_initialize (&rdev->dev); +snprintf (rdev->dev.bus_id,sizeof (rdev->dev.bus_id),"regulator_%ld_%s" , (unsigned long )atomic_inc_return (®ulator_no) -1 , regulator_desc->name); - ret =class_device_add (&rcdev->cdev); + ret =device_add (&rdev->dev);if (ret ==0 ) -list_add (&rcdev->list, ®ulator_list); +list_add (&rdev->list, ®ulator_list);else { -kfree (rcdev); - rcdev =ERR_PTR (ret); +kfree (rdev); + rdev =ERR_PTR (ret); }mutex_unlock (®ulator_list_mutex); -return rcdev; +return rdev; }EXPORT_SYMBOL_GPL (regulator_register);
@@ -1091,16 +1098,16 @@ EXPORT_SYMBOL_GPL(regulator_register);* * Called by regulator drivers to unregister a regulator. */ -void regulator_unregister (struct regulator_cdev *rcdev) +void regulator_unregister (struct regulator_dev *rdev) { -if (rcdev ==NULL ) +if (rdev ==NULL )return ;mutex_lock (®ulator_list_mutex); -list_del (&rcdev->list); -if (rcdev->parent) -sysfs_remove_link (&rcdev->cdev.kobj,"parent" ); -class_device_unregister (&rcdev->cdev); +list_del (&rdev->list); +if (rdev->parent) +sysfs_remove_link (&rdev->dev.kobj,"parent" ); +device_unregister (&rdev->dev);mutex_unlock (®ulator_list_mutex); }EXPORT_SYMBOL_GPL (regulator_unregister);
@@ -1116,7 +1123,7 @@ EXPORT_SYMBOL_GPL(regulator_unregister);*/ int regulator_set_parent (const char *regulator,const char *parent) { -struct regulator_cdev *rcdev, *parent_rcdev; +struct regulator_dev *rdev, *parent_rdev;int err;if (regulator ==NULL || parent ==NULL )
@@ -1124,30 +1131,30 @@ int regulator_set_parent(const char *regmutex_lock (®ulator_list_mutex); -list_for_each_entry (rcdev, ®ulator_list, list) { -if (!strcmp (rcdev->desc->name, regulator)) +list_for_each_entry (rdev, ®ulator_list, list) { +if (!strcmp (rdev->desc->name, regulator)) goto found_regulator; }mutex_unlock (®ulator_list_mutex);return -ENODEV ; found_regulator: -list_for_each_entry (parent_rcdev, ®ulator_list, list) { -if (!strcmp (parent_rcdev->desc->name, parent)) +list_for_each_entry (parent_rdev, ®ulator_list, list) { +if (!strcmp (parent_rdev->desc->name, parent)) goto found_parent; }mutex_unlock (®ulator_list_mutex);return -ENODEV ; found_parent: - rcdev->parent = parent_rcdev; - err =sysfs_create_link (&rcdev->cdev.kobj, &parent_rcdev->cdev.kobj, + rdev->parent = parent_rdev; + err =sysfs_create_link (&rdev->dev.kobj, &parent_rdev->dev.kobj,"parent" );if (err) {printk (KERN_ERR "%s: could not add device link %s err %d\n" , - __func__, parent_rcdev->cdev.kobj.name, err); - rcdev->parent =NULL ; + __func__, parent_rdev->dev.kobj.name, err); + rdev->parent =NULL ; }mutex_unlock (®ulator_list_mutex);return err;
@@ -1163,14 +1170,14 @@ EXPORT_SYMBOL_GPL(regulator_set_parent);*/ const char *regulator_get_parent (const char *regulator) { -struct regulator_cdev *rcdev; +struct regulator_dev *rdev;if (regulator ==NULL )return NULL ;mutex_lock (®ulator_list_mutex); -list_for_each_entry (rcdev, ®ulator_list, list) { -if (!strcmp (rcdev->desc->name, regulator)) +list_for_each_entry (rdev, ®ulator_list, list) { +if (!strcmp (rdev->desc->name, regulator)) goto found; }mutex_unlock (®ulator_list_mutex);
@@ -1178,8 +1185,8 @@ const char *regulator_get_parent(const c found:mutex_unlock (®ulator_list_mutex); -if (rcdev->parent) -return rcdev->parent->desc->name; +if (rdev->parent) +return rdev->parent->desc->name;else return NULL ; }
@@ -1197,18 +1204,18 @@ EXPORT_SYMBOL_GPL(regulator_get_parent);int regulator_set_platform_constraints (const char *regulator_name,struct regulation_constraints *constraints) { -struct regulator_cdev *rcdev; +struct regulator_dev *rdev;if (regulator_name ==NULL )return -EINVAL ;mutex_lock (®ulator_list_mutex); -list_for_each_entry (rcdev, ®ulator_list, list) { -if (!strcmp (regulator_name, rcdev->desc->name)) { -mutex_lock (&rcdev->mutex); - rcdev->constraints = constraints; -print_constraints (rcdev); -mutex_unlock (&rcdev->mutex); +list_for_each_entry (rdev, ®ulator_list, list) { +if (!strcmp (regulator_name, rdev->desc->name)) { +mutex_lock (&rdev->mutex); + rdev->constraints = constraints; +print_constraints (rdev); +mutex_unlock (&rdev->mutex);mutex_unlock (®ulator_list_mutex);return 0 ; }
@@ -1245,27 +1252,27 @@ EXPORT_SYMBOL_GPL(regulator_set_platform*/ void regulator_drms_notify_load (struct regulator *regulator,int uA) { -struct regulator_cdev *rcdev = regulator->rcdev; +struct regulator_dev *rdev = regulator->rdev; -mutex_lock (&rcdev->mutex); +mutex_lock (&rdev->mutex); regulator->uA_load = uA; -drms_uA_update (rcdev); -mutex_unlock (&rcdev->mutex); +drms_uA_update (rdev); +mutex_unlock (&rdev->mutex); }EXPORT_SYMBOL_GPL (regulator_drms_notify_load);/** -* rcdev_get_drvdata - get rcdev regulator driver data +* rdev_get_drvdata - get rdev regulator driver data * @regulator: regulator * -* Get rcdev regulator driver private data. This call can be used in the +* Get rdev regulator driver private data. This call can be used in the * regulator driver context. */ -void *rcdev_get_drvdata (struct regulator_cdev *rcdev) +void *rdev_get_drvdata (struct regulator_dev *rdev) { -return rcdev->reg_data; +return rdev->reg_data; } -EXPORT_SYMBOL_GPL (rcdev_get_drvdata); +EXPORT_SYMBOL_GPL (rdev_get_drvdata);/** * regulator_get_drvdata - get regulator driver data
@@ -1276,7 +1283,7 @@ EXPORT_SYMBOL_GPL(rcdev_get_drvdata);*/ void *regulator_get_drvdata (struct regulator *regulator) { -return regulator->rcdev->reg_data; +return regulator->rdev->reg_data; }EXPORT_SYMBOL_GPL (regulator_get_drvdata);
@@ -1287,7 +1294,7 @@ EXPORT_SYMBOL_GPL(regulator_get_drvdata)*/ void regulator_set_drvdata (struct regulator *regulator,void *data) { - regulator->rcdev->reg_data = data; + regulator->rdev->reg_data = data; }EXPORT_SYMBOL_GPL (regulator_set_drvdata);
@@ -1295,11 +1302,11 @@ EXPORT_SYMBOL_GPL(regulator_set_drvdata)* regulator_get_id - get regulator ID * @regulator: regulator */ -int rcdev_get_id (struct regulator_cdev *rcdev) +int rdev_get_id (struct regulator_dev *rdev) { -return rcdev->desc->id; +return rdev->desc->id; } -EXPORT_SYMBOL_GPL (rcdev_get_id); +EXPORT_SYMBOL_GPL (rdev_get_id);static int __init regulator_init (void ) {
include/linux/regulator/regulator-drv.h +16 -16
@@ -19,7 +19,7 @@#include <linux/regulator/regulator.h> struct regulator_constraints ; -struct regulator_cdev ; +struct regulator_dev ;/** * struct regulator_ops - regulator operations.
@@ -29,24 +29,24 @@ struct regulator_cdev;struct regulator_ops {/* get/set regulator voltage */ -int (*set_voltage) (struct regulator_cdev *,int uV); -int (*get_voltage) (struct regulator_cdev *); +int (*set_voltage) (struct regulator_dev *,int uV); +int (*get_voltage) (struct regulator_dev *);/* get/set regulator current */ -int (*set_current) (struct regulator_cdev *,int uA); -int (*get_current) (struct regulator_cdev *); +int (*set_current) (struct regulator_dev *,int uA); +int (*get_current) (struct regulator_dev *);/* enable/disable regulator */ -int (*enable) (struct regulator_cdev *); -int (*disable) (struct regulator_cdev *); -int (*is_enabled) (struct regulator_cdev *); +int (*enable) (struct regulator_dev *); +int (*disable) (struct regulator_dev *); +int (*is_enabled) (struct regulator_dev *);/* get/set regulator operating mode (defined in regulator.h) */ -int (*set_mode) (struct regulator_cdev *,unsigned int mode); -unsigned int (*get_mode) (struct regulator_cdev *); +int (*set_mode) (struct regulator_dev *,unsigned int mode); +unsigned int (*get_mode) (struct regulator_dev *);/* get most efficient regulator operating mode for load */ -unsigned int (*get_optimum_mode) (struct regulator_cdev *,int input_uV, +unsigned int (*get_optimum_mode) (struct regulator_dev *,int input_uV,int output_uV,int load_uA); };
@@ -72,14 +72,14 @@ struct regulator_desc { }; -struct regulator_cdev *regulator_register (struct regulator_desc *regulator_desc, +struct regulator_dev *regulator_register (struct regulator_desc *regulator_desc,void *reg_data); -void regulator_unregister (struct regulator_cdev *rcdev); +void regulator_unregister (struct regulator_dev *rdev); -int regulator_notifier_call_chain (struct regulator_cdev *rcdev, +int regulator_notifier_call_chain (struct regulator_dev *rdev,unsigned long event,void *data); -void *rcdev_get_drvdata (struct regulator_cdev *rcdev); -int rcdev_get_id (struct regulator_cdev *rcdev); +void *rdev_get_drvdata (struct regulator_dev *rdev); +int rdev_get_id (struct regulator_dev *rdev);#endif
Quoted 29 lines · Greg KH
Quoted 28 lines · Liam Girdwood
Quoted 26 lines · Greg KH
Quoted 5 lines · Liam Girdwood
(quoted diff) +5
-0+/** + * struct regulator_cdev + * + * Voltage / Current regulator class device. One for each regulator. + */Review
Quoted 10 lines
(quoted diff) +10
-0+struct regulator_cdev { + struct regulator_desc *desc; + int use_count; + + struct list_head list; + struct list_head consumer_list; + struct blocking_notifier_head notifier; + struct mutex mutex; /* consumer lock */ + struct module *owner; + struct class_device cdev;Can you change this to use a "struct device" instead? We are trying to get rid of
class_device, and there are only 3 users of it in the kernel today (memorystick, infiniband, and scsi), and I have patches pending to fix all of these. For 2.6.26 I would like to be rid of it finally.If you want, I would be glad to fix this up for you, it should be a pretty simple replacement.
Quoted 6 lines
Quoted 1 line
Yes please. Much appreciated :)
Ok, it's below, on top of your patch series. If you want me to merge it in, I can do that as well. It's a bit big, as I renamed "cdev" to "dev" in your structure names and variable names as it isn't a class device anymore.
Thanks. I've now committed into Wolfson git. I'll give it a spin on real hardware early next week and then send to Andrew.
Quoted 7 lines
Quoted 7 lines
Quoted 6 lines
Review
Quoted 3 lines
(quoted diff) +2
-0+ struct regulation_constraints *constraints; + struct regulator_cdev *parent; /* for tree */And if when you convert, you can get rid of this pointer, it would not be needed.
Quoted 8 lines
Quoted 3 lines
Fwiw, the regulator-parent relationship is established by the platform code after the regulator driver has registered all the regulator devices. I assume we can just
device_move()to re-parent.Ick, no, just pass the parent into the
regulator_register()function. Otherwise you will get some wierd uevents spit out (run udevmonitor to see what I mean.) You should set up the parent linkage before you register the device with the driver core.
Sorry, I think the 'parent' naming is a little confusing. The device parent would be set at register time and the 'supply' would be set later during platform power config.
Liam
Quoted 51 lines · Liam Girdwood
Quoted 29 lines · Greg KH
Quoted 28 lines · Liam Girdwood
Quoted 26 lines · Greg KH
Quoted 5 lines · Liam Girdwood
(quoted diff) +5
-0+/** + * struct regulator_cdev + * + * Voltage / Current regulator class device. One for each regulator. + */Review
Quoted 10 lines
(quoted diff) +10
-0+struct regulator_cdev { + struct regulator_desc *desc; + int use_count; + + struct list_head list; + struct list_head consumer_list; + struct blocking_notifier_head notifier; + struct mutex mutex; /* consumer lock */ + struct module *owner; + struct class_device cdev;Can you change this to use a "struct device" instead? We are trying to get rid of
class_device, and there are only 3 users of it in the kernel today (memorystick, infiniband, and scsi), and I have patches pending to fix all of these. For 2.6.26 I would like to be rid of it finally.If you want, I would be glad to fix this up for you, it should be a pretty simple replacement.
Quoted 6 lines
Quoted 1 line
Yes please. Much appreciated :)
Ok, it's below, on top of your patch series. If you want me to merge it in, I can do that as well. It's a bit big, as I renamed "cdev" to "dev" in your structure names and variable names as it isn't a class device anymore.
Thanks. I've now committed into Wolfson git. I'll give it a spin on real hardware early next week and then send to Andrew.
Quoted 11 lines
Quoted 10 lines
Quoted 6 lines
Review
Quoted 3 lines
(quoted diff) +2
-0+ struct regulation_constraints *constraints; + struct regulator_cdev *parent; /* for tree */And if when you convert, you can get rid of this pointer, it would not be needed.
Fwiw, the regulator-parent relationship is established by the platform code after the regulator driver has registered all the regulator devices. I assume we can just
device_move()to re-parent.
Quoted 8 lines
Quoted 4 lines
Ick, no, just pass the parent into the
regulator_register()function. Otherwise you will get some wierd uevents spit out (run udevmonitor to see what I mean.) You should set up the parent linkage before you register the device with the driver core.Sorry, I think the 'parent' naming is a little confusing. The device parent would be set at register time and the 'supply' would be set later during platform power config.
Heh, we both are confused here. Your statement is exactly what I was recommending :)
Feel free to CC: me on your next round of patches if you want me to review them.
thanks,
greg k-h