3527 lines · 90.1 KB · C
RawDownload
/* * core.c  --  Voltage/Current Regulator framework. * * Copyright 2007, 2008 Wolfson Microelectronics PLC. * Copyright 2008 SlimLogic Ltd. * * Author: Liam Girdwood <lrg@slimlogic.co.uk> * *  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/debugfs.h>#include <linux/device.h>#include <linux/slab.h>#include <linux/async.h>#include <linux/err.h>#include <linux/mutex.h>#include <linux/suspend.h>#include <linux/delay.h>#include <linux/of.h>#include <linux/regmap.h>#include <linux/regulator/of_regulator.h>#include <linux/regulator/consumer.h>#include <linux/regulator/driver.h>#include <linux/regulator/machine.h>#include <linux/module.h> #define CREATE_TRACE_POINTS#include <trace/events/regulator.h> #include "dummy.h" #define rdev_crit(rdev, fmt, ...)					\	pr_crit("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__)#define rdev_err(rdev, fmt, ...)					\	pr_err("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__)#define rdev_warn(rdev, fmt, ...)					\	pr_warn("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__)#define rdev_info(rdev, fmt, ...)					\	pr_info("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__)#define rdev_dbg(rdev, fmt, ...)					\	pr_debug("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__) static DEFINE_MUTEX(regulator_list_mutex);static LIST_HEAD(regulator_list);static LIST_HEAD(regulator_map_list);static bool has_full_constraints;static bool board_wants_dummy_regulator; static struct dentry *debugfs_root; /* * struct regulator_map * * Used to provide symbolic supply names to devices. */struct regulator_map {	struct list_head list;	const char *dev_name;   /* The dev_name() for the consumer */	const char *supply;	struct regulator_dev *regulator;}; /* * struct regulator * * One for each consumer device. */struct regulator {	struct device *dev;	struct list_head list;	unsigned int always_on:1;	int uA_load;	int min_uV;	int max_uV;	char *supply_name;	struct device_attribute dev_attr;	struct regulator_dev *rdev;	struct dentry *debugfs;}; 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_limit(struct regulator_dev *rdev);static unsigned int _regulator_get_mode(struct regulator_dev *rdev);static void _notifier_call_chain(struct regulator_dev *rdev,				  unsigned long event, void *data);static int _regulator_do_set_voltage(struct regulator_dev *rdev,				     int min_uV, int max_uV);static struct regulator *create_regulator(struct regulator_dev *rdev,					  struct device *dev,					  const char *supply_name); static const char *rdev_get_name(struct regulator_dev *rdev){	if (rdev->constraints && rdev->constraints->name)		return rdev->constraints->name;	else if (rdev->desc->name)		return rdev->desc->name;	else		return "";} /* gets the regulator for a given consumer device */static struct regulator *get_device_regulator(struct device *dev){	struct regulator *regulator = NULL;	struct regulator_dev *rdev; 	mutex_lock(&regulator_list_mutex);	list_for_each_entry(rdev, &regulator_list, list) {		mutex_lock(&rdev->mutex);		list_for_each_entry(regulator, &rdev->consumer_list, list) {			if (regulator->dev == dev) {				mutex_unlock(&rdev->mutex);				mutex_unlock(&regulator_list_mutex);				return regulator;			}		}		mutex_unlock(&rdev->mutex);	}	mutex_unlock(&regulator_list_mutex);	return NULL;} /** * of_get_regulator - get a regulator device node based on supply name * @dev: Device pointer for the consumer (of regulator) device * @supply: regulator supply name * * Extract the regulator device node corresponding to the supply name. * retruns the device node corresponding to the regulator if found, else * returns NULL. */static struct device_node *of_get_regulator(struct device *dev, const char *supply){	struct device_node *regnode = NULL;	char prop_name[32]; /* 32 is max size of property name */ 	dev_dbg(dev, "Looking up %s-supply from device tree\n", supply); 	snprintf(prop_name, 32, "%s-supply", supply);	regnode = of_parse_phandle(dev->of_node, prop_name, 0); 	if (!regnode) {		dev_dbg(dev, "Looking up %s property in node %s failed",				prop_name, dev->of_node->full_name);		return NULL;	}	return regnode;} static int _regulator_can_change_status(struct regulator_dev *rdev){	if (!rdev->constraints)		return 0; 	if (rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_STATUS)		return 1;	else		return 0;} /* Platform voltage constraint check */static int regulator_check_voltage(struct regulator_dev *rdev,				   int *min_uV, int *max_uV){	BUG_ON(*min_uV > *max_uV); 	if (!rdev->constraints) {		rdev_err(rdev, "no constraints\n");		return -ENODEV;	}	if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE)) {		rdev_err(rdev, "operation not allowed\n");		return -EPERM;	} 	if (*max_uV > rdev->constraints->max_uV)		*max_uV = rdev->constraints->max_uV;	if (*min_uV < rdev->constraints->min_uV)		*min_uV = rdev->constraints->min_uV; 	if (*min_uV > *max_uV) {		rdev_err(rdev, "unsupportable voltage range: %d-%duV\n",			 *min_uV, *max_uV);		return -EINVAL;	} 	return 0;} /* Make sure we select a voltage that suits the needs of all * regulator consumers */static int regulator_check_consumers(struct regulator_dev *rdev,				     int *min_uV, int *max_uV){	struct regulator *regulator; 	list_for_each_entry(regulator, &rdev->consumer_list, list) {		/*		 * Assume consumers that didn't say anything are OK		 * with anything in the constraint range.		 */		if (!regulator->min_uV && !regulator->max_uV)			continue; 		if (*max_uV > regulator->max_uV)			*max_uV = regulator->max_uV;		if (*min_uV < regulator->min_uV)			*min_uV = regulator->min_uV;	} 	if (*min_uV > *max_uV)		return -EINVAL; 	return 0;} /* current constraint check */static int regulator_check_current_limit(struct regulator_dev *rdev,					int *min_uA, int *max_uA){	BUG_ON(*min_uA > *max_uA); 	if (!rdev->constraints) {		rdev_err(rdev, "no constraints\n");		return -ENODEV;	}	if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_CURRENT)) {		rdev_err(rdev, "operation not allowed\n");		return -EPERM;	} 	if (*max_uA > rdev->constraints->max_uA)		*max_uA = rdev->constraints->max_uA;	if (*min_uA < rdev->constraints->min_uA)		*min_uA = rdev->constraints->min_uA; 	if (*min_uA > *max_uA) {		rdev_err(rdev, "unsupportable current range: %d-%duA\n",			 *min_uA, *max_uA);		return -EINVAL;	} 	return 0;} /* operating mode constraint check */static int regulator_mode_constrain(struct regulator_dev *rdev, int *mode){	switch (*mode) {	case REGULATOR_MODE_FAST:	case REGULATOR_MODE_NORMAL:	case REGULATOR_MODE_IDLE:	case REGULATOR_MODE_STANDBY:		break;	default:		rdev_err(rdev, "invalid mode %x specified\n", *mode);		return -EINVAL;	} 	if (!rdev->constraints) {		rdev_err(rdev, "no constraints\n");		return -ENODEV;	}	if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_MODE)) {		rdev_err(rdev, "operation not allowed\n");		return -EPERM;	} 	/* The modes are bitmasks, the most power hungry modes having	 * the lowest values. If the requested mode isn't supported	 * try higher modes. */	while (*mode) {		if (rdev->constraints->valid_modes_mask & *mode)			return 0;		*mode /= 2;	} 	return -EINVAL;} /* dynamic regulator mode switching constraint check */static int regulator_check_drms(struct regulator_dev *rdev){	if (!rdev->constraints) {		rdev_err(rdev, "no constraints\n");		return -ENODEV;	}	if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_DRMS)) {		rdev_err(rdev, "operation not allowed\n");		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 device *dev,				struct device_attribute *attr, char *buf){	struct regulator_dev *rdev = dev_get_drvdata(dev);	ssize_t ret; 	mutex_lock(&rdev->mutex);	ret = sprintf(buf, "%d\n", _regulator_get_voltage(rdev));	mutex_unlock(&rdev->mutex); 	return ret;}static DEVICE_ATTR(microvolts, 0444, regulator_uV_show, NULL); static ssize_t regulator_uA_show(struct device *dev,				struct device_attribute *attr, char *buf){	struct regulator_dev *rdev = dev_get_drvdata(dev); 	return sprintf(buf, "%d\n", _regulator_get_current_limit(rdev));}static DEVICE_ATTR(microamps, 0444, regulator_uA_show, NULL); static ssize_t regulator_name_show(struct device *dev,			     struct device_attribute *attr, char *buf){	struct regulator_dev *rdev = dev_get_drvdata(dev); 	return sprintf(buf, "%s\n", rdev_get_name(rdev));} static ssize_t regulator_print_opmode(char *buf, int mode){	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_opmode_show(struct device *dev,				    struct device_attribute *attr, char *buf){	struct regulator_dev *rdev = dev_get_drvdata(dev); 	return regulator_print_opmode(buf, _regulator_get_mode(rdev));}static DEVICE_ATTR(opmode, 0444, regulator_opmode_show, NULL); static ssize_t regulator_print_state(char *buf, int state){	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_state_show(struct device *dev,				   struct device_attribute *attr, char *buf){	struct regulator_dev *rdev = dev_get_drvdata(dev);	ssize_t ret; 	mutex_lock(&rdev->mutex);	ret = regulator_print_state(buf, _regulator_is_enabled(rdev));	mutex_unlock(&rdev->mutex); 	return ret;}static DEVICE_ATTR(state, 0444, regulator_state_show, NULL); static ssize_t regulator_status_show(struct device *dev,				   struct device_attribute *attr, char *buf){	struct regulator_dev *rdev = dev_get_drvdata(dev);	int status;	char *label; 	status = rdev->desc->ops->get_status(rdev);	if (status < 0)		return status; 	switch (status) {	case REGULATOR_STATUS_OFF:		label = "off";		break;	case REGULATOR_STATUS_ON:		label = "on";		break;	case REGULATOR_STATUS_ERROR:		label = "error";		break;	case REGULATOR_STATUS_FAST:		label = "fast";		break;	case REGULATOR_STATUS_NORMAL:		label = "normal";		break;	case REGULATOR_STATUS_IDLE:		label = "idle";		break;	case REGULATOR_STATUS_STANDBY:		label = "standby";		break;	default:		return -ERANGE;	} 	return sprintf(buf, "%s\n", label);}static DEVICE_ATTR(status, 0444, regulator_status_show, NULL); static ssize_t regulator_min_uA_show(struct device *dev,				    struct device_attribute *attr, char *buf){	struct regulator_dev *rdev = dev_get_drvdata(dev); 	if (!rdev->constraints)		return sprintf(buf, "constraint not defined\n"); 	return sprintf(buf, "%d\n", rdev->constraints->min_uA);}static DEVICE_ATTR(min_microamps, 0444, regulator_min_uA_show, NULL); static ssize_t regulator_max_uA_show(struct device *dev,				    struct device_attribute *attr, char *buf){	struct regulator_dev *rdev = dev_get_drvdata(dev); 	if (!rdev->constraints)		return sprintf(buf, "constraint not defined\n"); 	return sprintf(buf, "%d\n", rdev->constraints->max_uA);}static DEVICE_ATTR(max_microamps, 0444, regulator_max_uA_show, NULL); static ssize_t regulator_min_uV_show(struct device *dev,				    struct device_attribute *attr, char *buf){	struct regulator_dev *rdev = dev_get_drvdata(dev); 	if (!rdev->constraints)		return sprintf(buf, "constraint not defined\n"); 	return sprintf(buf, "%d\n", rdev->constraints->min_uV);}static DEVICE_ATTR(min_microvolts, 0444, regulator_min_uV_show, NULL); static ssize_t regulator_max_uV_show(struct device *dev,				    struct device_attribute *attr, char *buf){	struct regulator_dev *rdev = dev_get_drvdata(dev); 	if (!rdev->constraints)		return sprintf(buf, "constraint not defined\n"); 	return sprintf(buf, "%d\n", rdev->constraints->max_uV);}static DEVICE_ATTR(max_microvolts, 0444, regulator_max_uV_show, NULL); static ssize_t regulator_total_uA_show(struct device *dev,				      struct device_attribute *attr, char *buf){	struct regulator_dev *rdev = dev_get_drvdata(dev);	struct regulator *regulator;	int uA = 0; 	mutex_lock(&rdev->mutex);	list_for_each_entry(regulator, &rdev->consumer_list, list)		uA += regulator->uA_load;	mutex_unlock(&rdev->mutex);	return sprintf(buf, "%d\n", uA);}static DEVICE_ATTR(requested_microamps, 0444, regulator_total_uA_show, NULL); 

Lines 1–500 of 3527.