Commit a5766f11 authored by Liam Girdwood's avatar Liam Girdwood

regulator: core - Rework machine API to remove string based functions.

This improves the machine level API in order to configure
regulator constraints and consumers as platform data and removes the
old string based API that required several calls to set up each regulator.

The intention is to create a struct regulator_init_data, populate
it's fields with constraints, consumers devices, etc and then register
the regulator device from board.c in the standard Linux way.

e.g. regulator LDO2 (supplying codec and sim) platform data.

/* regulator LDO2 consumer devices */
static struct regulator_consumer_supply ldo2_consumers[] = {
{
	.dev	= &platform_audio_device.dev,
	.supply	= "codec_avdd",
},
{
	.dev	= &platform_sim_device.dev,
	.supply	= "sim_vcc",
}
};

/* regulator LDO2 constraints  */
static struct regulator_init_data ldo2_data = {
	.constraints = {
		.min_uV = 3300000,
		.max_uV = 3300000,
		.valid_modes_mask = REGULATOR_MODE_NORMAL,
		.apply_uV = 1,
	},
	.num_consumer_supplies = ARRAY_SIZE(ldo2_consumers),
	.consumer_supplies = ldo2_consumers,
};

/* machine regulator devices with thier consumers and constraints */
static struct platform_device wm8350_regulator_devices[] = {
{
	.name = "wm8350-regulator",
	.id = WM8350_LDO_2,
	.dev = {
		.platform_data = &ldo2_data,
	},
},
};

Changes in detail:-

  o Removed all const char* regulator config functions in machine API.
  o Created new struct regulator_init_data to contain regulator
    machine configuration constraints and consmuers.
  o Changed set_supply(), set_machine_constraints(),
    set_consumer_device_supply() to remove their string identifier
    parameters. Also made them static and moved functions nearer top of
    core.c.
  o Removed no longer used inline func to_rdev()
  o Added regulator_get_init_drvdata() to retrieve init data.
  o Added struct device* as parameter to regulator_register().
  o Changed my email address.
Signed-off-by: default avatarEric Miao <eric.miao@marvell.com>
Signed-off-by: default avatarMark Brown <broonie@opensource.wolfsonmicro.com>
Signed-off-by: default avatarLiam Girdwood <lrg@slimlogic.co.uk>
parent a447c093
...@@ -2,17 +2,8 @@ Regulator Machine Driver Interface ...@@ -2,17 +2,8 @@ Regulator Machine Driver Interface
=================================== ===================================
The regulator machine driver interface is intended for board/machine specific The regulator machine driver interface is intended for board/machine specific
initialisation code to configure the regulator subsystem. Typical things that initialisation code to configure the regulator subsystem.
machine drivers would do are :-
1. Regulator -> Device mapping.
2. Regulator supply configuration.
3. Power Domain constraint setting.
1. Regulator -> device mapping
==============================
Consider the following machine :- Consider the following machine :-
Regulator-1 -+-> Regulator-2 --> [Consumer A @ 1.8 - 2.0V] Regulator-1 -+-> Regulator-2 --> [Consumer A @ 1.8 - 2.0V]
...@@ -21,81 +12,82 @@ Consider the following machine :- ...@@ -21,81 +12,82 @@ Consider the following machine :-
The drivers for consumers A & B must be mapped to the correct regulator in The drivers for consumers A & B must be mapped to the correct regulator in
order to control their power supply. This mapping can be achieved in machine order to control their power supply. This mapping can be achieved in machine
initialisation code by calling :- initialisation code by creating a struct regulator_consumer_supply for
each regulator.
struct regulator_consumer_supply {
struct device *dev; /* consumer */
const char *supply; /* consumer supply - e.g. "vcc" */
};
int regulator_set_device_supply(const char *regulator, struct device *dev, e.g. for the machine above
const char *supply);
and is shown with the following code :- static struct regulator_consumer_supply regulator1_consumers[] = {
{
.dev = &platform_consumerB_device.dev,
.supply = "Vcc",
},};
regulator_set_device_supply("Regulator-1", devB, "Vcc"); static struct regulator_consumer_supply regulator2_consumers[] = {
regulator_set_device_supply("Regulator-2", devA, "Vcc"); {
.dev = &platform_consumerA_device.dev,
.supply = "Vcc",
},};
This maps Regulator-1 to the 'Vcc' supply for Consumer B and maps Regulator-2 This maps Regulator-1 to the 'Vcc' supply for Consumer B and maps Regulator-2
to the 'Vcc' supply for Consumer A. to the 'Vcc' supply for Consumer A.
Constraints can now be registered by defining a struct regulator_init_data
for each regulator power domain. This structure also maps the consumers
to their supply regulator :-
2. Regulator supply configuration. static struct regulator_init_data regulator1_data = {
================================== .constraints = {
Consider the following machine (again) :-
Regulator-1 -+-> Regulator-2 --> [Consumer A @ 1.8 - 2.0V]
|
+-> [Consumer B @ 3.3V]
Regulator-1 supplies power to Regulator-2. This relationship must be registered
with the core so that Regulator-1 is also enabled when Consumer A enables it's
supply (Regulator-2).
This relationship can be register with the core via :-
int regulator_set_supply(const char *regulator, const char *regulator_supply);
In this example we would use the following code :-
regulator_set_supply("Regulator-2", "Regulator-1");
Relationships can be queried by calling :-
const char *regulator_get_supply(const char *regulator);
3. Power Domain constraint setting.
===================================
Each power domain within a system has physical constraints on voltage and
current. This must be defined in software so that the power domain is always
operated within specifications.
Consider the following machine (again) :-
Regulator-1 -+-> Regulator-2 --> [Consumer A @ 1.8 - 2.0V]
|
+-> [Consumer B @ 3.3V]
This gives us two regulators and two power domains:
Domain 1: Regulator-2, Consumer B.
Domain 2: Consumer A.
Constraints can be registered by calling :-
int regulator_set_platform_constraints(const char *regulator,
struct regulation_constraints *constraints);
The example is defined as follows :-
struct regulation_constraints domain_1 = {
.min_uV = 3300000, .min_uV = 3300000,
.max_uV = 3300000, .max_uV = 3300000,
.valid_modes_mask = REGULATOR_MODE_NORMAL, .valid_modes_mask = REGULATOR_MODE_NORMAL,
},
.num_consumer_supplies = ARRAY_SIZE(regulator1_consumers),
.consumer_supplies = regulator1_consumers,
}; };
struct regulation_constraints domain_2 = { Regulator-1 supplies power to Regulator-2. This relationship must be registered
with the core so that Regulator-1 is also enabled when Consumer A enables it's
supply (Regulator-2). The supply regulator is set by the supply_regulator_dev
field below:-
static struct regulator_init_data regulator2_data = {
.supply_regulator_dev = &platform_regulator1_device.dev,
.constraints = {
.min_uV = 1800000, .min_uV = 1800000,
.max_uV = 2000000, .max_uV = 2000000,
.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE, .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
.valid_modes_mask = REGULATOR_MODE_NORMAL, .valid_modes_mask = REGULATOR_MODE_NORMAL,
},
.num_consumer_supplies = ARRAY_SIZE(regulator2_consumers),
.consumer_supplies = regulator2_consumers,
};
Finally the regulator devices must be registered in the usual manner.
static struct platform_device regulator_devices[] = {
{
.name = "regulator",
.id = DCDC_1,
.dev = {
.platform_data = &regulator1_data,
},
},
{
.name = "regulator",
.id = DCDC_2,
.dev = {
.platform_data = &regulator2_data,
},
},
}; };
/* register regulator 1 device */
platform_device_register(&wm8350_regulator_devices[0]);
regulator_set_platform_constraints("Regulator-1", &domain_1); /* register regulator 2 device */
regulator_set_platform_constraints("Regulator-2", &domain_2); platform_device_register(&wm8350_regulator_devices[1]);
...@@ -10,11 +10,11 @@ Registration ...@@ -10,11 +10,11 @@ Registration
Drivers can register a regulator by calling :- Drivers can register a regulator by calling :-
struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc, struct regulator_dev *regulator_register(struct device *dev,
void *reg_data); struct regulator_desc *regulator_desc);
This will register the regulators capabilities and operations the regulator This will register the regulators capabilities and operations to the regulator
core. The core does not touch reg_data (private to regulator driver). core.
Regulators can be unregistered by calling :- Regulators can be unregistered by calling :-
......
...@@ -18,13 +18,13 @@ ...@@ -18,13 +18,13 @@
#include <linux/regulator/bq24022.h> #include <linux/regulator/bq24022.h>
#include <linux/regulator/driver.h> #include <linux/regulator/driver.h>
static int bq24022_set_current_limit(struct regulator_dev *rdev, static int bq24022_set_current_limit(struct regulator_dev *rdev,
int min_uA, int max_uA) int min_uA, int max_uA)
{ {
struct platform_device *pdev = rdev_get_drvdata(rdev); struct bq24022_mach_info *pdata = rdev_get_drvdata(rdev);
struct bq24022_mach_info *pdata = pdev->dev.platform_data;
dev_dbg(&pdev->dev, "setting current limit to %s mA\n", dev_dbg(rdev_get_dev(rdev), "setting current limit to %s mA\n",
max_uA >= 500000 ? "500" : "100"); max_uA >= 500000 ? "500" : "100");
/* REVISIT: maybe return error if min_uA != 0 ? */ /* REVISIT: maybe return error if min_uA != 0 ? */
...@@ -34,18 +34,16 @@ static int bq24022_set_current_limit(struct regulator_dev *rdev, ...@@ -34,18 +34,16 @@ static int bq24022_set_current_limit(struct regulator_dev *rdev,
static int bq24022_get_current_limit(struct regulator_dev *rdev) static int bq24022_get_current_limit(struct regulator_dev *rdev)
{ {
struct platform_device *pdev = rdev_get_drvdata(rdev); struct bq24022_mach_info *pdata = rdev_get_drvdata(rdev);
struct bq24022_mach_info *pdata = pdev->dev.platform_data;
return gpio_get_value(pdata->gpio_iset2) ? 500000 : 100000; return gpio_get_value(pdata->gpio_iset2) ? 500000 : 100000;
} }
static int bq24022_enable(struct regulator_dev *rdev) static int bq24022_enable(struct regulator_dev *rdev)
{ {
struct platform_device *pdev = rdev_get_drvdata(rdev); struct bq24022_mach_info *pdata = rdev_get_drvdata(rdev);
struct bq24022_mach_info *pdata = pdev->dev.platform_data;
dev_dbg(&pdev->dev, "enabling charger\n"); dev_dbg(rdev_get_dev(rdev), "enabling charger\n");
gpio_set_value(pdata->gpio_nce, 0); gpio_set_value(pdata->gpio_nce, 0);
return 0; return 0;
...@@ -53,10 +51,9 @@ static int bq24022_enable(struct regulator_dev *rdev) ...@@ -53,10 +51,9 @@ static int bq24022_enable(struct regulator_dev *rdev)
static int bq24022_disable(struct regulator_dev *rdev) static int bq24022_disable(struct regulator_dev *rdev)
{ {
struct platform_device *pdev = rdev_get_drvdata(rdev); struct bq24022_mach_info *pdata = rdev_get_drvdata(rdev);
struct bq24022_mach_info *pdata = pdev->dev.platform_data;
dev_dbg(&pdev->dev, "disabling charger\n"); dev_dbg(rdev_get_dev(rdev), "disabling charger\n");
gpio_set_value(pdata->gpio_nce, 1); gpio_set_value(pdata->gpio_nce, 1);
return 0; return 0;
...@@ -108,7 +105,7 @@ static int __init bq24022_probe(struct platform_device *pdev) ...@@ -108,7 +105,7 @@ static int __init bq24022_probe(struct platform_device *pdev)
ret = gpio_direction_output(pdata->gpio_iset2, 0); ret = gpio_direction_output(pdata->gpio_iset2, 0);
ret = gpio_direction_output(pdata->gpio_nce, 1); ret = gpio_direction_output(pdata->gpio_nce, 1);
bq24022 = regulator_register(&bq24022_desc, pdev); bq24022 = regulator_register(&bq24022_desc, &pdev->dev, pdata);
if (IS_ERR(bq24022)) { if (IS_ERR(bq24022)) {
dev_dbg(&pdev->dev, "couldn't register regulator\n"); dev_dbg(&pdev->dev, "couldn't register regulator\n");
ret = PTR_ERR(bq24022); ret = PTR_ERR(bq24022);
......
...@@ -2,8 +2,9 @@ ...@@ -2,8 +2,9 @@
* core.c -- Voltage/Current Regulator framework. * core.c -- Voltage/Current Regulator framework.
* *
* Copyright 2007, 2008 Wolfson Microelectronics PLC. * Copyright 2007, 2008 Wolfson Microelectronics PLC.
* Copyright 2008 SlimLogic Ltd.
* *
* Author: Liam Girdwood <liam.girdwood@wolfsonmicro.com> * Author: Liam Girdwood <lrg@slimlogic.co.uk>
* *
* This program is free software; you can redistribute it and/or modify it * 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 * under the terms of the GNU General Public License as published by the
...@@ -64,14 +65,9 @@ struct regulator_map { ...@@ -64,14 +65,9 @@ struct regulator_map {
struct list_head list; struct list_head list;
struct device *dev; struct device *dev;
const char *supply; const char *supply;
const char *regulator; struct regulator_dev *regulator;
}; };
static inline struct regulator_dev *to_rdev(struct device *d)
{
return container_of(d, struct regulator_dev, dev);
}
/* /*
* struct regulator * struct regulator
* *
...@@ -227,7 +223,7 @@ static ssize_t device_requested_uA_show(struct device *dev, ...@@ -227,7 +223,7 @@ static ssize_t device_requested_uA_show(struct device *dev,
static ssize_t regulator_uV_show(struct device *dev, static ssize_t regulator_uV_show(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
struct regulator_dev *rdev = to_rdev(dev); struct regulator_dev *rdev = dev_get_drvdata(dev);
ssize_t ret; ssize_t ret;
mutex_lock(&rdev->mutex); mutex_lock(&rdev->mutex);
...@@ -240,7 +236,7 @@ static ssize_t regulator_uV_show(struct device *dev, ...@@ -240,7 +236,7 @@ static ssize_t regulator_uV_show(struct device *dev,
static ssize_t regulator_uA_show(struct device *dev, static ssize_t regulator_uA_show(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
struct regulator_dev *rdev = to_rdev(dev); struct regulator_dev *rdev = dev_get_drvdata(dev);
return sprintf(buf, "%d\n", _regulator_get_current_limit(rdev)); return sprintf(buf, "%d\n", _regulator_get_current_limit(rdev));
} }
...@@ -248,7 +244,7 @@ static ssize_t regulator_uA_show(struct device *dev, ...@@ -248,7 +244,7 @@ static ssize_t regulator_uA_show(struct device *dev,
static ssize_t regulator_opmode_show(struct device *dev, static ssize_t regulator_opmode_show(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
struct regulator_dev *rdev = to_rdev(dev); struct regulator_dev *rdev = dev_get_drvdata(dev);
int mode = _regulator_get_mode(rdev); int mode = _regulator_get_mode(rdev);
switch (mode) { switch (mode) {
...@@ -267,7 +263,7 @@ static ssize_t regulator_opmode_show(struct device *dev, ...@@ -267,7 +263,7 @@ static ssize_t regulator_opmode_show(struct device *dev,
static ssize_t regulator_state_show(struct device *dev, static ssize_t regulator_state_show(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
struct regulator_dev *rdev = to_rdev(dev); struct regulator_dev *rdev = dev_get_drvdata(dev);
int state = _regulator_is_enabled(rdev); int state = _regulator_is_enabled(rdev);
if (state > 0) if (state > 0)
...@@ -281,7 +277,7 @@ static ssize_t regulator_state_show(struct device *dev, ...@@ -281,7 +277,7 @@ static ssize_t regulator_state_show(struct device *dev,
static ssize_t regulator_min_uA_show(struct device *dev, static ssize_t regulator_min_uA_show(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
struct regulator_dev *rdev = to_rdev(dev); struct regulator_dev *rdev = dev_get_drvdata(dev);
if (!rdev->constraints) if (!rdev->constraints)
return sprintf(buf, "constraint not defined\n"); return sprintf(buf, "constraint not defined\n");
...@@ -292,7 +288,7 @@ static ssize_t regulator_min_uA_show(struct device *dev, ...@@ -292,7 +288,7 @@ static ssize_t regulator_min_uA_show(struct device *dev,
static ssize_t regulator_max_uA_show(struct device *dev, static ssize_t regulator_max_uA_show(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
struct regulator_dev *rdev = to_rdev(dev); struct regulator_dev *rdev = dev_get_drvdata(dev);
if (!rdev->constraints) if (!rdev->constraints)
return sprintf(buf, "constraint not defined\n"); return sprintf(buf, "constraint not defined\n");
...@@ -303,7 +299,7 @@ static ssize_t regulator_max_uA_show(struct device *dev, ...@@ -303,7 +299,7 @@ static ssize_t regulator_max_uA_show(struct device *dev,
static ssize_t regulator_min_uV_show(struct device *dev, static ssize_t regulator_min_uV_show(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
struct regulator_dev *rdev = to_rdev(dev); struct regulator_dev *rdev = dev_get_drvdata(dev);
if (!rdev->constraints) if (!rdev->constraints)
return sprintf(buf, "constraint not defined\n"); return sprintf(buf, "constraint not defined\n");
...@@ -314,7 +310,7 @@ static ssize_t regulator_min_uV_show(struct device *dev, ...@@ -314,7 +310,7 @@ static ssize_t regulator_min_uV_show(struct device *dev,
static ssize_t regulator_max_uV_show(struct device *dev, static ssize_t regulator_max_uV_show(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
struct regulator_dev *rdev = to_rdev(dev); struct regulator_dev *rdev = dev_get_drvdata(dev);
if (!rdev->constraints) if (!rdev->constraints)
return sprintf(buf, "constraint not defined\n"); return sprintf(buf, "constraint not defined\n");
...@@ -325,7 +321,7 @@ static ssize_t regulator_max_uV_show(struct device *dev, ...@@ -325,7 +321,7 @@ static ssize_t regulator_max_uV_show(struct device *dev,
static ssize_t regulator_total_uA_show(struct device *dev, static ssize_t regulator_total_uA_show(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
struct regulator_dev *rdev = to_rdev(dev); struct regulator_dev *rdev = dev_get_drvdata(dev);
struct regulator *regulator; struct regulator *regulator;
int uA = 0; int uA = 0;
...@@ -339,14 +335,14 @@ static ssize_t regulator_total_uA_show(struct device *dev, ...@@ -339,14 +335,14 @@ static ssize_t regulator_total_uA_show(struct device *dev,
static ssize_t regulator_num_users_show(struct device *dev, static ssize_t regulator_num_users_show(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
struct regulator_dev *rdev = to_rdev(dev); struct regulator_dev *rdev = dev_get_drvdata(dev);
return sprintf(buf, "%d\n", rdev->use_count); return sprintf(buf, "%d\n", rdev->use_count);
} }
static ssize_t regulator_type_show(struct device *dev, static ssize_t regulator_type_show(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
struct regulator_dev *rdev = to_rdev(dev); struct regulator_dev *rdev = dev_get_drvdata(dev);
switch (rdev->desc->type) { switch (rdev->desc->type) {
case REGULATOR_VOLTAGE: case REGULATOR_VOLTAGE:
...@@ -360,7 +356,7 @@ static ssize_t regulator_type_show(struct device *dev, ...@@ -360,7 +356,7 @@ static ssize_t regulator_type_show(struct device *dev,
static ssize_t regulator_suspend_mem_uV_show(struct device *dev, static ssize_t regulator_suspend_mem_uV_show(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
struct regulator_dev *rdev = to_rdev(dev); struct regulator_dev *rdev = dev_get_drvdata(dev);
if (!rdev->constraints) if (!rdev->constraints)
return sprintf(buf, "not defined\n"); return sprintf(buf, "not defined\n");
...@@ -370,7 +366,7 @@ static ssize_t regulator_suspend_mem_uV_show(struct device *dev, ...@@ -370,7 +366,7 @@ static ssize_t regulator_suspend_mem_uV_show(struct device *dev,
static ssize_t regulator_suspend_disk_uV_show(struct device *dev, static ssize_t regulator_suspend_disk_uV_show(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
struct regulator_dev *rdev = to_rdev(dev); struct regulator_dev *rdev = dev_get_drvdata(dev);
if (!rdev->constraints) if (!rdev->constraints)
return sprintf(buf, "not defined\n"); return sprintf(buf, "not defined\n");
...@@ -380,7 +376,7 @@ static ssize_t regulator_suspend_disk_uV_show(struct device *dev, ...@@ -380,7 +376,7 @@ static ssize_t regulator_suspend_disk_uV_show(struct device *dev,
static ssize_t regulator_suspend_standby_uV_show(struct device *dev, static ssize_t regulator_suspend_standby_uV_show(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
struct regulator_dev *rdev = to_rdev(dev); struct regulator_dev *rdev = dev_get_drvdata(dev);
if (!rdev->constraints) if (!rdev->constraints)
return sprintf(buf, "not defined\n"); return sprintf(buf, "not defined\n");
...@@ -406,7 +402,7 @@ static ssize_t suspend_opmode_show(struct regulator_dev *rdev, ...@@ -406,7 +402,7 @@ static ssize_t suspend_opmode_show(struct regulator_dev *rdev,
static ssize_t regulator_suspend_mem_mode_show(struct device *dev, static ssize_t regulator_suspend_mem_mode_show(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
struct regulator_dev *rdev = to_rdev(dev); struct regulator_dev *rdev = dev_get_drvdata(dev);
if (!rdev->constraints) if (!rdev->constraints)
return sprintf(buf, "not defined\n"); return sprintf(buf, "not defined\n");
...@@ -417,7 +413,7 @@ static ssize_t regulator_suspend_mem_mode_show(struct device *dev, ...@@ -417,7 +413,7 @@ static ssize_t regulator_suspend_mem_mode_show(struct device *dev,
static ssize_t regulator_suspend_disk_mode_show(struct device *dev, static ssize_t regulator_suspend_disk_mode_show(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
struct regulator_dev *rdev = to_rdev(dev); struct regulator_dev *rdev = dev_get_drvdata(dev);
if (!rdev->constraints) if (!rdev->constraints)
return sprintf(buf, "not defined\n"); return sprintf(buf, "not defined\n");
...@@ -428,7 +424,7 @@ static ssize_t regulator_suspend_disk_mode_show(struct device *dev, ...@@ -428,7 +424,7 @@ static ssize_t regulator_suspend_disk_mode_show(struct device *dev,
static ssize_t regulator_suspend_standby_mode_show(struct device *dev, static ssize_t regulator_suspend_standby_mode_show(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
struct regulator_dev *rdev = to_rdev(dev); struct regulator_dev *rdev = dev_get_drvdata(dev);
if (!rdev->constraints) if (!rdev->constraints)
return sprintf(buf, "not defined\n"); return sprintf(buf, "not defined\n");
...@@ -439,7 +435,7 @@ static ssize_t regulator_suspend_standby_mode_show(struct device *dev, ...@@ -439,7 +435,7 @@ static ssize_t regulator_suspend_standby_mode_show(struct device *dev,
static ssize_t regulator_suspend_mem_state_show(struct device *dev, static ssize_t regulator_suspend_mem_state_show(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
struct regulator_dev *rdev = to_rdev(dev); struct regulator_dev *rdev = dev_get_drvdata(dev);
if (!rdev->constraints) if (!rdev->constraints)
return sprintf(buf, "not defined\n"); return sprintf(buf, "not defined\n");
...@@ -453,7 +449,7 @@ static ssize_t regulator_suspend_mem_state_show(struct device *dev, ...@@ -453,7 +449,7 @@ static ssize_t regulator_suspend_mem_state_show(struct device *dev,
static ssize_t regulator_suspend_disk_state_show(struct device *dev, static ssize_t regulator_suspend_disk_state_show(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
struct regulator_dev *rdev = to_rdev(dev); struct regulator_dev *rdev = dev_get_drvdata(dev);
if (!rdev->constraints) if (!rdev->constraints)
return sprintf(buf, "not defined\n"); return sprintf(buf, "not defined\n");
...@@ -467,7 +463,7 @@ static ssize_t regulator_suspend_disk_state_show(struct device *dev, ...@@ -467,7 +463,7 @@ static ssize_t regulator_suspend_disk_state_show(struct device *dev,
static ssize_t regulator_suspend_standby_state_show(struct device *dev, static ssize_t regulator_suspend_standby_state_show(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
struct regulator_dev *rdev = to_rdev(dev); struct regulator_dev *rdev = dev_get_drvdata(dev);
if (!rdev->constraints) if (!rdev->constraints)
return sprintf(buf, "not defined\n"); return sprintf(buf, "not defined\n");
...@@ -512,7 +508,7 @@ static struct device_attribute regulator_dev_attrs[] = { ...@@ -512,7 +508,7 @@ static struct device_attribute regulator_dev_attrs[] = {
static void regulator_dev_release(struct device *dev) static void regulator_dev_release(struct device *dev)
{ {
struct regulator_dev *rdev = to_rdev(dev); struct regulator_dev *rdev = dev_get_drvdata(dev);
kfree(rdev); kfree(rdev);
} }
...@@ -569,8 +565,11 @@ static int suspend_set_state(struct regulator_dev *rdev, ...@@ -569,8 +565,11 @@ static int suspend_set_state(struct regulator_dev *rdev,
/* enable & disable are mandatory for suspend control */ /* enable & disable are mandatory for suspend control */
if (!rdev->desc->ops->set_suspend_enable || if (!rdev->desc->ops->set_suspend_enable ||
!rdev->desc->ops->set_suspend_disable) !rdev->desc->ops->set_suspend_disable) {
printk(KERN_ERR "%s: no way to set suspend state\n",
__func__);
return -EINVAL; return -EINVAL;
}
if (rstate->enabled) if (rstate->enabled)
ret = rdev->desc->ops->set_suspend_enable(rdev); ret = rdev->desc->ops->set_suspend_enable(rdev);
...@@ -656,6 +655,125 @@ static void print_constraints(struct regulator_dev *rdev) ...@@ -656,6 +655,125 @@ static void print_constraints(struct regulator_dev *rdev)
printk(KERN_INFO "regulator: %s: %s\n", rdev->desc->name, buf); printk(KERN_INFO "regulator: %s: %s\n", rdev->desc->name, buf);
} }
/**
* set_machine_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_limit,
* set_mode.
*/
static int set_machine_constraints(struct regulator_dev *rdev,
struct regulation_constraints *constraints)
{
int ret = 0;
rdev->constraints = constraints;
/* do we need to apply the constraint voltage */
if (rdev->constraints->apply_uV &&
rdev->constraints->min_uV == rdev->constraints->max_uV &&
rdev->desc->ops->set_voltage) {
ret = rdev->desc->ops->set_voltage(rdev,
rdev->constraints->min_uV, rdev->constraints->max_uV);
if (ret < 0) {
printk(KERN_ERR "%s: failed to apply %duV"
" constraint\n", __func__,
rdev->constraints->min_uV);
rdev->constraints = NULL;
goto out;
}
}
/* are we enabled at boot time by firmware / bootloader */
if (rdev->constraints->boot_on)
rdev->use_count = 1;
/* do we need to setup our suspend state */
if (constraints->initial_state)
ret = suspend_prepare(rdev, constraints->initial_state);
print_constraints(rdev);
out:
return ret;
}
/**
* set_supply - set regulator supply regulator
* @regulator: regulator name
* @supply: supply regulator name
*
* Called by platform initialisation code to set the supply regulator for this
* regulator. This ensures that a regulators supply will also be enabled by the
* core if it's child is enabled.
*/
static int set_supply(struct regulator_dev *rdev,
struct regulator_dev *supply_rdev)
{
int err;
err = sysfs_create_link(&rdev->dev.kobj, &supply_rdev->dev.kobj,
"supply");
if (err) {
printk(KERN_ERR
"%s: could not add device link %s err %d\n",
__func__, supply_rdev->dev.kobj.name, err);
goto out;
}
rdev->supply = supply_rdev;
list_add(&rdev->slist, &supply_rdev->supply_list);
out:
return err;
}
/**
* set_consumer_device_supply: Bind a regulator to a symbolic supply
* @regulator: regulator source
* @dev: device the supply applies to
* @supply: symbolic name for supply
*
* Allows platform initialisation code to map physical regulator
* sources to symbolic names for supplies for use by devices. Devices
* should use these symbolic names to request regulators, avoiding the
* need to provide board-specific regulator names as platform data.
*/
static int set_consumer_device_supply(struct regulator_dev *rdev,
struct device *consumer_dev, const char *supply)
{
struct regulator_map *node;
if (supply == NULL)
return -EINVAL;
node = kmalloc(sizeof(struct regulator_map), GFP_KERNEL);
if (node == NULL)
return -ENOMEM;
node->regulator = rdev;
node->dev = consumer_dev;
node->supply = supply;
list_add(&node->list, &regulator_map_list);
return 0;
}
static void unset_consumer_device_supply(struct regulator_dev *rdev,
struct device *consumer_dev)
{
struct regulator_map *node, *n;
list_for_each_entry_safe(node, n, &regulator_map_list, list) {
if (rdev == node->regulator &&
consumer_dev == node->dev) {
list_del(&node->list);
kfree(node);
return;
}
}
}
#define REG_STR_SIZE 32 #define REG_STR_SIZE 32
static struct regulator *create_regulator(struct regulator_dev *rdev, static struct regulator *create_regulator(struct regulator_dev *rdev,
...@@ -746,7 +864,6 @@ struct regulator *regulator_get(struct device *dev, const char *id) ...@@ -746,7 +864,6 @@ struct regulator *regulator_get(struct device *dev, const char *id)
struct regulator_dev *rdev; struct regulator_dev *rdev;
struct regulator_map *map; struct regulator_map *map;
struct regulator *regulator = ERR_PTR(-ENODEV); struct regulator *regulator = ERR_PTR(-ENODEV);
const char *supply = id;
if (id == NULL) { if (id == NULL) {
printk(KERN_ERR "regulator: get() with no identifier\n"); printk(KERN_ERR "regulator: get() with no identifier\n");
...@@ -758,28 +875,26 @@ struct regulator *regulator_get(struct device *dev, const char *id) ...@@ -758,28 +875,26 @@ struct regulator *regulator_get(struct device *dev, const char *id)
list_for_each_entry(map, &regulator_map_list, list) { list_for_each_entry(map, &regulator_map_list, list) {
if (dev == map->dev && if (dev == map->dev &&
strcmp(map->supply, id) == 0) { strcmp(map->supply, id) == 0) {
supply = map->regulator; rdev = map->regulator;
break;
}
}
list_for_each_entry(rdev, &regulator_list, list) {
if (strcmp(supply, rdev->desc->name) == 0 &&
try_module_get(rdev->owner))
goto found; goto found;
} }
}
printk(KERN_ERR "regulator: Unable to get requested regulator: %s\n", printk(KERN_ERR "regulator: Unable to get requested regulator: %s\n",
id); id);
mutex_unlock(&regulator_list_mutex); mutex_unlock(&regulator_list_mutex);
return regulator; return regulator;
found: found:
if (!try_module_get(rdev->owner))
goto out;
regulator = create_regulator(rdev, dev, id); regulator = create_regulator(rdev, dev, id);
if (regulator == NULL) { if (regulator == NULL) {
regulator = ERR_PTR(-ENOMEM); regulator = ERR_PTR(-ENOMEM);
module_put(rdev->owner); module_put(rdev->owner);
} }
out:
mutex_unlock(&regulator_list_mutex); mutex_unlock(&regulator_list_mutex);
return regulator; return regulator;
} }
...@@ -1559,11 +1674,12 @@ EXPORT_SYMBOL_GPL(regulator_notifier_call_chain); ...@@ -1559,11 +1674,12 @@ EXPORT_SYMBOL_GPL(regulator_notifier_call_chain);
* Returns 0 on success. * Returns 0 on success.
*/ */
struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc, struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc,
void *reg_data) struct device *dev, void *driver_data)
{ {
static atomic_t regulator_no = ATOMIC_INIT(0); static atomic_t regulator_no = ATOMIC_INIT(0);
struct regulator_dev *rdev; struct regulator_dev *rdev;
int ret; struct regulator_init_data *init_data = dev->platform_data;
int ret, i;
if (regulator_desc == NULL) if (regulator_desc == NULL)
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
...@@ -1582,7 +1698,7 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc, ...@@ -1582,7 +1698,7 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc,
mutex_lock(&regulator_list_mutex); mutex_lock(&regulator_list_mutex);
mutex_init(&rdev->mutex); mutex_init(&rdev->mutex);
rdev->reg_data = reg_data; rdev->reg_data = driver_data;
rdev->owner = regulator_desc->owner; rdev->owner = regulator_desc->owner;
rdev->desc = regulator_desc; rdev->desc = regulator_desc;
INIT_LIST_HEAD(&rdev->consumer_list); INIT_LIST_HEAD(&rdev->consumer_list);
...@@ -1591,225 +1707,92 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc, ...@@ -1591,225 +1707,92 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc,
INIT_LIST_HEAD(&rdev->slist); INIT_LIST_HEAD(&rdev->slist);
BLOCKING_INIT_NOTIFIER_HEAD(&rdev->notifier); BLOCKING_INIT_NOTIFIER_HEAD(&rdev->notifier);
rdev->dev.class = &regulator_class; /* preform any regulator specific init */
device_initialize(&rdev->dev); if (init_data->regulator_init) {
snprintf(rdev->dev.bus_id, sizeof(rdev->dev.bus_id), ret = init_data->regulator_init(rdev->reg_data);
"regulator_%ld_%s", if (ret < 0) {
(unsigned long)atomic_inc_return(&regulator_no) - 1,
regulator_desc->name);
ret = device_add(&rdev->dev);
if (ret == 0)
list_add(&rdev->list, &regulator_list);
else {
kfree(rdev); kfree(rdev);
rdev = ERR_PTR(ret); rdev = ERR_PTR(ret);
goto out;
} }
mutex_unlock(&regulator_list_mutex);
return rdev;
}
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_dev *rdev)
{
if (rdev == NULL)
return;
mutex_lock(&regulator_list_mutex);
list_del(&rdev->list);
if (rdev->supply)
sysfs_remove_link(&rdev->dev.kobj, "supply");
device_unregister(&rdev->dev);
mutex_unlock(&regulator_list_mutex);
}
EXPORT_SYMBOL_GPL(regulator_unregister);
/**
* regulator_set_supply - set regulator supply regulator
* @regulator: regulator name
* @supply: supply regulator name
*
* Called by platform initialisation code to set the supply regulator for this
* regulator. This ensures that a regulators supply will also be enabled by the
* core if it's child is enabled.
*/
int regulator_set_supply(const char *regulator, const char *supply)
{
struct regulator_dev *rdev, *supply_rdev;
int err;
if (regulator == NULL || supply == NULL)
return -EINVAL;
mutex_lock(&regulator_list_mutex);
list_for_each_entry(rdev, &regulator_list, list) {
if (!strcmp(rdev->desc->name, regulator))
goto found_regulator;
} }
mutex_unlock(&regulator_list_mutex);
return -ENODEV;
found_regulator: /* set regulator constraints */
list_for_each_entry(supply_rdev, &regulator_list, list) { ret = set_machine_constraints(rdev, &init_data->constraints);
if (!strcmp(supply_rdev->desc->name, supply)) if (ret < 0) {
goto found_supply; kfree(rdev);
rdev = ERR_PTR(ret);
goto out;
} }
mutex_unlock(&regulator_list_mutex);
return -ENODEV;
found_supply: /* register with sysfs */
err = sysfs_create_link(&rdev->dev.kobj, &supply_rdev->dev.kobj, rdev->dev.class = &regulator_class;
"supply"); rdev->dev.parent = dev;
if (err) { snprintf(rdev->dev.bus_id, sizeof(rdev->dev.bus_id),
printk(KERN_ERR "regulator.%d", atomic_inc_return(&regulator_no) - 1);
"%s: could not add device link %s err %d\n", ret = device_register(&rdev->dev);
__func__, supply_rdev->dev.kobj.name, err); if (ret != 0) {
kfree(rdev);
rdev = ERR_PTR(ret);
goto out; goto out;
} }
rdev->supply = supply_rdev;
list_add(&rdev->slist, &supply_rdev->supply_list);
out:
mutex_unlock(&regulator_list_mutex);
return err;
}
EXPORT_SYMBOL_GPL(regulator_set_supply);
/** dev_set_drvdata(&rdev->dev, rdev);
* regulator_get_supply - get regulator supply regulator
* @regulator: regulator name
*
* Returns the supply 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_supply(const char *regulator)
{
struct regulator_dev *rdev;
if (regulator == NULL)
return NULL;
mutex_lock(&regulator_list_mutex); /* set supply regulator if it exists */
list_for_each_entry(rdev, &regulator_list, list) { if (init_data->supply_regulator_dev) {
if (!strcmp(rdev->desc->name, regulator)) ret = set_supply(rdev,
goto found; dev_get_drvdata(init_data->supply_regulator_dev));
if (ret < 0) {
device_unregister(&rdev->dev);
kfree(rdev);
rdev = ERR_PTR(ret);
goto out;
} }
mutex_unlock(&regulator_list_mutex);
return NULL;
found:
mutex_unlock(&regulator_list_mutex);
if (rdev->supply)
return rdev->supply->desc->name;
else
return NULL;
}
EXPORT_SYMBOL_GPL(regulator_get_supply);
/**
* regulator_set_machine_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_limit,
* set_mode.
*/
int regulator_set_machine_constraints(const char *regulator_name,
struct regulation_constraints *constraints)
{
struct regulator_dev *rdev;
int ret = 0;
if (regulator_name == NULL)
return -EINVAL;
mutex_lock(&regulator_list_mutex);
list_for_each_entry(rdev, &regulator_list, list) {
if (!strcmp(regulator_name, rdev->desc->name))
goto found;
} }
ret = -ENODEV;
goto out;
found: /* add consumers devices */
mutex_lock(&rdev->mutex); for (i = 0; i < init_data->num_consumer_supplies; i++) {
rdev->constraints = constraints; ret = set_consumer_device_supply(rdev,
init_data->consumer_supplies[i].dev,
/* do we need to apply the constraint voltage */ init_data->consumer_supplies[i].supply);
if (rdev->constraints->apply_uV &&
rdev->constraints->min_uV == rdev->constraints->max_uV &&
rdev->desc->ops->set_voltage) {
ret = rdev->desc->ops->set_voltage(rdev,
rdev->constraints->min_uV, rdev->constraints->max_uV);
if (ret < 0) { if (ret < 0) {
printk(KERN_ERR "%s: failed to apply %duV" for (--i; i >= 0; i--)
" constraint\n", __func__, unset_consumer_device_supply(rdev,
rdev->constraints->min_uV); init_data->consumer_supplies[i].dev);
rdev->constraints = NULL; device_unregister(&rdev->dev);
kfree(rdev);
rdev = ERR_PTR(ret);
goto out; goto out;
} }
} }
/* are we enabled at boot time by firmware / bootloader */ list_add(&rdev->list, &regulator_list);
if (rdev->constraints->boot_on)
rdev->use_count = 1;
/* do we need to setup our suspend state */
if (constraints->initial_state)
ret = suspend_prepare(rdev, constraints->initial_state);
print_constraints(rdev);
mutex_unlock(&rdev->mutex);
out: out:
mutex_unlock(&regulator_list_mutex); mutex_unlock(&regulator_list_mutex);
return ret; return rdev;
} }
EXPORT_SYMBOL_GPL(regulator_set_machine_constraints); EXPORT_SYMBOL_GPL(regulator_register);
/** /**
* regulator_set_device_supply: Bind a regulator to a symbolic supply * regulator_unregister - unregister regulator
* @regulator: regulator source * @regulator: regulator source
* @dev: device the supply applies to
* @supply: symbolic name for supply
* *
* Allows platform initialisation code to map physical regulator * Called by regulator drivers to unregister a regulator.
* sources to symbolic names for supplies for use by devices. Devices
* should use these symbolic names to request regulators, avoiding the
* need to provide board-specific regulator names as platform data.
*/ */
int regulator_set_device_supply(const char *regulator, struct device *dev, void regulator_unregister(struct regulator_dev *rdev)
const char *supply)
{ {
struct regulator_map *node; if (rdev == NULL)
return;
if (regulator == NULL || supply == NULL)
return -EINVAL;
node = kmalloc(sizeof(struct regulator_map), GFP_KERNEL);
if (node == NULL)
return -ENOMEM;
node->regulator = regulator;
node->dev = dev;
node->supply = supply;
mutex_lock(&regulator_list_mutex); mutex_lock(&regulator_list_mutex);
list_add(&node->list, &regulator_map_list); list_del(&rdev->list);
if (rdev->supply)
sysfs_remove_link(&rdev->dev.kobj, "supply");
device_unregister(&rdev->dev);
mutex_unlock(&regulator_list_mutex); mutex_unlock(&regulator_list_mutex);
return 0;
} }
EXPORT_SYMBOL_GPL(regulator_set_device_supply); EXPORT_SYMBOL_GPL(regulator_unregister);
/** /**
* regulator_suspend_prepare: prepare regulators for system wide suspend * regulator_suspend_prepare: prepare regulators for system wide suspend
...@@ -1893,6 +1876,18 @@ int rdev_get_id(struct regulator_dev *rdev) ...@@ -1893,6 +1876,18 @@ int rdev_get_id(struct regulator_dev *rdev)
} }
EXPORT_SYMBOL_GPL(rdev_get_id); EXPORT_SYMBOL_GPL(rdev_get_id);
struct device *rdev_get_dev(struct regulator_dev *rdev)
{
return &rdev->dev;
}
EXPORT_SYMBOL_GPL(rdev_get_dev);
void *regulator_get_init_drvdata(struct regulator_init_data *reg_init_data)
{
return reg_init_data->driver_data;
}
EXPORT_SYMBOL_GPL(regulator_get_init_drvdata);
static int __init regulator_init(void) static int __init regulator_init(void)
{ {
printk(KERN_INFO "regulator: core version %s\n", REGULATOR_VERSION); printk(KERN_INFO "regulator: core version %s\n", REGULATOR_VERSION);
......
...@@ -18,8 +18,8 @@ ...@@ -18,8 +18,8 @@
#include <linux/device.h> #include <linux/device.h>
#include <linux/regulator/consumer.h> #include <linux/regulator/consumer.h>
struct regulator_constraints;
struct regulator_dev; struct regulator_dev;
struct regulator_init_data;
/** /**
* struct regulator_ops - regulator operations. * struct regulator_ops - regulator operations.
...@@ -85,15 +85,17 @@ struct regulator_desc { ...@@ -85,15 +85,17 @@ struct regulator_desc {
struct module *owner; struct module *owner;
}; };
struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc, struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc,
void *reg_data); struct device *dev, void *driver_data);
void regulator_unregister(struct regulator_dev *rdev); void regulator_unregister(struct regulator_dev *rdev);
int regulator_notifier_call_chain(struct regulator_dev *rdev, int regulator_notifier_call_chain(struct regulator_dev *rdev,
unsigned long event, void *data); unsigned long event, void *data);
void *rdev_get_drvdata(struct regulator_dev *rdev); void *rdev_get_drvdata(struct regulator_dev *rdev);
struct device *rdev_get_dev(struct regulator_dev *rdev);
int rdev_get_id(struct regulator_dev *rdev); int rdev_get_id(struct regulator_dev *rdev);
void *regulator_get_init_drvdata(struct regulator_init_data *reg_init_data);
#endif #endif
...@@ -89,15 +89,33 @@ struct regulation_constraints { ...@@ -89,15 +89,33 @@ struct regulation_constraints {
unsigned apply_uV:1; /* apply uV constraint iff min == max */ unsigned apply_uV:1; /* apply uV constraint iff min == max */
}; };
int regulator_set_supply(const char *regulator, const char *regulator_supply); /**
* struct regulator_consumer_supply - supply -> device mapping
*
* This maps a supply name to a device.
*/
struct regulator_consumer_supply {
struct device *dev; /* consumer */
const char *supply; /* consumer supply - e.g. "vcc" */
};
const char *regulator_get_supply(const char *regulator); /**
* struct regulator_init_data - regulator platform initialisation data.
*
* Initialisation constraints, our supply and consumers supplies.
*/
struct regulator_init_data {
struct device *supply_regulator_dev; /* or NULL for LINE */
int regulator_set_machine_constraints(const char *regulator, struct regulation_constraints constraints;
struct regulation_constraints *constraints);
int regulator_set_device_supply(const char *regulator, struct device *dev, int num_consumer_supplies;
const char *supply); struct regulator_consumer_supply *consumer_supplies;
/* optional regulator machine specific init */
int (*regulator_init)(void *driver_data);
void *driver_data; /* core does not touch this */
};
int regulator_suspend_prepare(suspend_state_t state); int regulator_suspend_prepare(suspend_state_t state);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment