Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
5408dd8f
Commit
5408dd8f
authored
Nov 04, 2015
by
Mark Brown
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branch 'regulator/topic/list' into regulator-next
parents
ce3c0597
85f3b431
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
164 additions
and
91 deletions
+164
-91
drivers/regulator/core.c
drivers/regulator/core.c
+164
-91
No files found.
drivers/regulator/core.c
View file @
5408dd8f
...
@@ -51,7 +51,6 @@
...
@@ -51,7 +51,6 @@
pr_debug("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__)
pr_debug("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__)
static
DEFINE_MUTEX
(
regulator_list_mutex
);
static
DEFINE_MUTEX
(
regulator_list_mutex
);
static
LIST_HEAD
(
regulator_list
);
static
LIST_HEAD
(
regulator_map_list
);
static
LIST_HEAD
(
regulator_map_list
);
static
LIST_HEAD
(
regulator_ena_gpio_list
);
static
LIST_HEAD
(
regulator_ena_gpio_list
);
static
LIST_HEAD
(
regulator_supply_alias_list
);
static
LIST_HEAD
(
regulator_supply_alias_list
);
...
@@ -59,6 +58,8 @@ static bool has_full_constraints;
...
@@ -59,6 +58,8 @@ static bool has_full_constraints;
static
struct
dentry
*
debugfs_root
;
static
struct
dentry
*
debugfs_root
;
static
struct
class
regulator_class
;
/*
/*
* struct regulator_map
* struct regulator_map
*
*
...
@@ -1325,6 +1326,47 @@ static void regulator_supply_alias(struct device **dev, const char **supply)
...
@@ -1325,6 +1326,47 @@ static void regulator_supply_alias(struct device **dev, const char **supply)
}
}
}
}
static
int
of_node_match
(
struct
device
*
dev
,
const
void
*
data
)
{
return
dev
->
of_node
==
data
;
}
static
struct
regulator_dev
*
of_find_regulator_by_node
(
struct
device_node
*
np
)
{
struct
device
*
dev
;
dev
=
class_find_device
(
&
regulator_class
,
NULL
,
np
,
of_node_match
);
return
dev
?
dev_to_rdev
(
dev
)
:
NULL
;
}
static
int
regulator_match
(
struct
device
*
dev
,
const
void
*
data
)
{
struct
regulator_dev
*
r
=
dev_to_rdev
(
dev
);
return
strcmp
(
rdev_get_name
(
r
),
data
)
==
0
;
}
static
struct
regulator_dev
*
regulator_lookup_by_name
(
const
char
*
name
)
{
struct
device
*
dev
;
dev
=
class_find_device
(
&
regulator_class
,
NULL
,
name
,
regulator_match
);
return
dev
?
dev_to_rdev
(
dev
)
:
NULL
;
}
/**
* regulator_dev_lookup - lookup a regulator device.
* @dev: device for regulator "consumer".
* @supply: Supply name or regulator ID.
* @ret: 0 on success, -ENODEV if lookup fails permanently, -EPROBE_DEFER if
* lookup could succeed in the future.
*
* If successful, returns a struct regulator_dev that corresponds to the name
* @supply and with the embedded struct device refcount incremented by one,
* or NULL on failure. The refcount must be dropped by calling put_device().
*/
static
struct
regulator_dev
*
regulator_dev_lookup
(
struct
device
*
dev
,
static
struct
regulator_dev
*
regulator_dev_lookup
(
struct
device
*
dev
,
const
char
*
supply
,
const
char
*
supply
,
int
*
ret
)
int
*
ret
)
...
@@ -1340,9 +1382,8 @@ static struct regulator_dev *regulator_dev_lookup(struct device *dev,
...
@@ -1340,9 +1382,8 @@ static struct regulator_dev *regulator_dev_lookup(struct device *dev,
if
(
dev
&&
dev
->
of_node
)
{
if
(
dev
&&
dev
->
of_node
)
{
node
=
of_get_regulator
(
dev
,
supply
);
node
=
of_get_regulator
(
dev
,
supply
);
if
(
node
)
{
if
(
node
)
{
list_for_each_entry
(
r
,
&
regulator_list
,
list
)
r
=
of_find_regulator_by_node
(
node
);
if
(
r
->
dev
.
parent
&&
if
(
r
)
node
==
r
->
dev
.
of_node
)
return
r
;
return
r
;
*
ret
=
-
EPROBE_DEFER
;
*
ret
=
-
EPROBE_DEFER
;
return
NULL
;
return
NULL
;
...
@@ -1361,20 +1402,24 @@ static struct regulator_dev *regulator_dev_lookup(struct device *dev,
...
@@ -1361,20 +1402,24 @@ static struct regulator_dev *regulator_dev_lookup(struct device *dev,
if
(
dev
)
if
(
dev
)
devname
=
dev_name
(
dev
);
devname
=
dev_name
(
dev
);
list_for_each_entry
(
r
,
&
regulator_list
,
list
)
r
=
regulator_lookup_by_name
(
supply
);
if
(
strcmp
(
rdev_get_name
(
r
),
supply
)
==
0
)
if
(
r
)
return
r
;
return
r
;
mutex_lock
(
&
regulator_list_mutex
);
list_for_each_entry
(
map
,
&
regulator_map_list
,
list
)
{
list_for_each_entry
(
map
,
&
regulator_map_list
,
list
)
{
/* If the mapping has a device set up it must match */
/* If the mapping has a device set up it must match */
if
(
map
->
dev_name
&&
if
(
map
->
dev_name
&&
(
!
devname
||
strcmp
(
map
->
dev_name
,
devname
)))
(
!
devname
||
strcmp
(
map
->
dev_name
,
devname
)))
continue
;
continue
;
if
(
strcmp
(
map
->
supply
,
supply
)
==
0
)
if
(
strcmp
(
map
->
supply
,
supply
)
==
0
&&
get_device
(
&
map
->
regulator
->
dev
))
{
mutex_unlock
(
&
regulator_list_mutex
);
return
map
->
regulator
;
return
map
->
regulator
;
}
}
}
mutex_unlock
(
&
regulator_list_mutex
);
return
NULL
;
return
NULL
;
}
}
...
@@ -1409,6 +1454,7 @@ static int regulator_resolve_supply(struct regulator_dev *rdev)
...
@@ -1409,6 +1454,7 @@ static int regulator_resolve_supply(struct regulator_dev *rdev)
if
(
have_full_constraints
())
{
if
(
have_full_constraints
())
{
r
=
dummy_regulator_rdev
;
r
=
dummy_regulator_rdev
;
get_device
(
&
r
->
dev
);
}
else
{
}
else
{
dev_err
(
dev
,
"Failed to resolve %s-supply for %s
\n
"
,
dev_err
(
dev
,
"Failed to resolve %s-supply for %s
\n
"
,
rdev
->
supply_name
,
rdev
->
desc
->
name
);
rdev
->
supply_name
,
rdev
->
desc
->
name
);
...
@@ -1418,12 +1464,16 @@ static int regulator_resolve_supply(struct regulator_dev *rdev)
...
@@ -1418,12 +1464,16 @@ static int regulator_resolve_supply(struct regulator_dev *rdev)
/* Recursively resolve the supply of the supply */
/* Recursively resolve the supply of the supply */
ret
=
regulator_resolve_supply
(
r
);
ret
=
regulator_resolve_supply
(
r
);
if
(
ret
<
0
)
if
(
ret
<
0
)
{
put_device
(
&
r
->
dev
);
return
ret
;
return
ret
;
}
ret
=
set_supply
(
rdev
,
r
);
ret
=
set_supply
(
rdev
,
r
);
if
(
ret
<
0
)
if
(
ret
<
0
)
{
put_device
(
&
r
->
dev
);
return
ret
;
return
ret
;
}
/* Cascade always-on state to supply */
/* Cascade always-on state to supply */
if
(
_regulator_is_enabled
(
rdev
)
&&
rdev
->
supply
)
{
if
(
_regulator_is_enabled
(
rdev
)
&&
rdev
->
supply
)
{
...
@@ -1459,8 +1509,6 @@ static struct regulator *_regulator_get(struct device *dev, const char *id,
...
@@ -1459,8 +1509,6 @@ static struct regulator *_regulator_get(struct device *dev, const char *id,
else
else
ret
=
-
EPROBE_DEFER
;
ret
=
-
EPROBE_DEFER
;
mutex_lock
(
&
regulator_list_mutex
);
rdev
=
regulator_dev_lookup
(
dev
,
id
,
&
ret
);
rdev
=
regulator_dev_lookup
(
dev
,
id
,
&
ret
);
if
(
rdev
)
if
(
rdev
)
goto
found
;
goto
found
;
...
@@ -1472,7 +1520,7 @@ static struct regulator *_regulator_get(struct device *dev, const char *id,
...
@@ -1472,7 +1520,7 @@ static struct regulator *_regulator_get(struct device *dev, const char *id,
* succeed, so, quit with appropriate error value
* succeed, so, quit with appropriate error value
*/
*/
if
(
ret
&&
ret
!=
-
ENODEV
)
if
(
ret
&&
ret
!=
-
ENODEV
)
goto
out
;
return
regulator
;
if
(
!
devname
)
if
(
!
devname
)
devname
=
"deviceless"
;
devname
=
"deviceless"
;
...
@@ -1486,40 +1534,46 @@ static struct regulator *_regulator_get(struct device *dev, const char *id,
...
@@ -1486,40 +1534,46 @@ static struct regulator *_regulator_get(struct device *dev, const char *id,
devname
,
id
);
devname
,
id
);
rdev
=
dummy_regulator_rdev
;
rdev
=
dummy_regulator_rdev
;
get_device
(
&
rdev
->
dev
);
goto
found
;
goto
found
;
/* Don't log an error when called from regulator_get_optional() */
/* Don't log an error when called from regulator_get_optional() */
}
else
if
(
!
have_full_constraints
()
||
exclusive
)
{
}
else
if
(
!
have_full_constraints
()
||
exclusive
)
{
dev_warn
(
dev
,
"dummy supplies not allowed
\n
"
);
dev_warn
(
dev
,
"dummy supplies not allowed
\n
"
);
}
}
mutex_unlock
(
&
regulator_list_mutex
);
return
regulator
;
return
regulator
;
found:
found:
if
(
rdev
->
exclusive
)
{
if
(
rdev
->
exclusive
)
{
regulator
=
ERR_PTR
(
-
EPERM
);
regulator
=
ERR_PTR
(
-
EPERM
);
goto
out
;
put_device
(
&
rdev
->
dev
);
return
regulator
;
}
}
if
(
exclusive
&&
rdev
->
open_count
)
{
if
(
exclusive
&&
rdev
->
open_count
)
{
regulator
=
ERR_PTR
(
-
EBUSY
);
regulator
=
ERR_PTR
(
-
EBUSY
);
goto
out
;
put_device
(
&
rdev
->
dev
);
return
regulator
;
}
}
ret
=
regulator_resolve_supply
(
rdev
);
ret
=
regulator_resolve_supply
(
rdev
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
{
regulator
=
ERR_PTR
(
ret
);
regulator
=
ERR_PTR
(
ret
);
goto
out
;
put_device
(
&
rdev
->
dev
);
return
regulator
;
}
}
if
(
!
try_module_get
(
rdev
->
owner
))
if
(
!
try_module_get
(
rdev
->
owner
))
{
goto
out
;
put_device
(
&
rdev
->
dev
);
return
regulator
;
}
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
);
put_device
(
&
rdev
->
dev
);
module_put
(
rdev
->
owner
);
module_put
(
rdev
->
owner
);
goto
out
;
return
regulator
;
}
}
rdev
->
open_count
++
;
rdev
->
open_count
++
;
...
@@ -1533,9 +1587,6 @@ static struct regulator *_regulator_get(struct device *dev, const char *id,
...
@@ -1533,9 +1587,6 @@ static struct regulator *_regulator_get(struct device *dev, const char *id,
rdev
->
use_count
=
0
;
rdev
->
use_count
=
0
;
}
}
out:
mutex_unlock
(
&
regulator_list_mutex
);
return
regulator
;
return
regulator
;
}
}
...
@@ -1633,6 +1684,7 @@ static void _regulator_put(struct regulator *regulator)
...
@@ -1633,6 +1684,7 @@ static void _regulator_put(struct regulator *regulator)
rdev
->
open_count
--
;
rdev
->
open_count
--
;
rdev
->
exclusive
=
0
;
rdev
->
exclusive
=
0
;
put_device
(
&
rdev
->
dev
);
mutex_unlock
(
&
rdev
->
mutex
);
mutex_unlock
(
&
rdev
->
mutex
);
kfree
(
regulator
->
supply_name
);
kfree
(
regulator
->
supply_name
);
...
@@ -3810,8 +3862,6 @@ regulator_register(const struct regulator_desc *regulator_desc,
...
@@ -3810,8 +3862,6 @@ regulator_register(const struct regulator_desc *regulator_desc,
}
}
}
}
list_add
(
&
rdev
->
list
,
&
regulator_list
);
rdev_init_debugfs
(
rdev
);
rdev_init_debugfs
(
rdev
);
out:
out:
mutex_unlock
(
&
regulator_list_mutex
);
mutex_unlock
(
&
regulator_list_mutex
);
...
@@ -3865,6 +3915,19 @@ void regulator_unregister(struct regulator_dev *rdev)
...
@@ -3865,6 +3915,19 @@ void regulator_unregister(struct regulator_dev *rdev)
}
}
EXPORT_SYMBOL_GPL
(
regulator_unregister
);
EXPORT_SYMBOL_GPL
(
regulator_unregister
);
static
int
_regulator_suspend_prepare
(
struct
device
*
dev
,
void
*
data
)
{
struct
regulator_dev
*
rdev
=
dev_to_rdev
(
dev
);
const
suspend_state_t
*
state
=
data
;
int
ret
;
mutex_lock
(
&
rdev
->
mutex
);
ret
=
suspend_prepare
(
rdev
,
*
state
);
mutex_unlock
(
&
rdev
->
mutex
);
return
ret
;
}
/**
/**
* regulator_suspend_prepare - prepare regulators for system wide suspend
* regulator_suspend_prepare - prepare regulators for system wide suspend
* @state: system suspend state
* @state: system suspend state
...
@@ -3874,50 +3937,28 @@ EXPORT_SYMBOL_GPL(regulator_unregister);
...
@@ -3874,50 +3937,28 @@ EXPORT_SYMBOL_GPL(regulator_unregister);
*/
*/
int
regulator_suspend_prepare
(
suspend_state_t
state
)
int
regulator_suspend_prepare
(
suspend_state_t
state
)
{
{
struct
regulator_dev
*
rdev
;
int
ret
=
0
;
/* ON is handled by regulator active state */
/* ON is handled by regulator active state */
if
(
state
==
PM_SUSPEND_ON
)
if
(
state
==
PM_SUSPEND_ON
)
return
-
EINVAL
;
return
-
EINVAL
;
mutex_lock
(
&
regulator_list_mutex
);
return
class_for_each_device
(
&
regulator_class
,
NULL
,
&
state
,
list_for_each_entry
(
rdev
,
&
regulator_list
,
list
)
{
_regulator_suspend_prepare
);
mutex_lock
(
&
rdev
->
mutex
);
ret
=
suspend_prepare
(
rdev
,
state
);
mutex_unlock
(
&
rdev
->
mutex
);
if
(
ret
<
0
)
{
rdev_err
(
rdev
,
"failed to prepare
\n
"
);
goto
out
;
}
}
out:
mutex_unlock
(
&
regulator_list_mutex
);
return
ret
;
}
}
EXPORT_SYMBOL_GPL
(
regulator_suspend_prepare
);
EXPORT_SYMBOL_GPL
(
regulator_suspend_prepare
);
/**
static
int
_regulator_suspend_finish
(
struct
device
*
dev
,
void
*
data
)
* regulator_suspend_finish - resume regulators from system wide suspend
*
* Turn on regulators that might be turned off by regulator_suspend_prepare
* and that should be turned on according to the regulators properties.
*/
int
regulator_suspend_finish
(
void
)
{
{
struct
regulator_dev
*
rdev
;
struct
regulator_dev
*
rdev
=
dev_to_rdev
(
dev
)
;
int
ret
=
0
,
error
;
int
ret
;
mutex_lock
(
&
regulator_list_mutex
);
list_for_each_entry
(
rdev
,
&
regulator_list
,
list
)
{
mutex_lock
(
&
rdev
->
mutex
);
mutex_lock
(
&
rdev
->
mutex
);
if
(
rdev
->
use_count
>
0
||
rdev
->
constraints
->
always_on
)
{
if
(
rdev
->
use_count
>
0
||
rdev
->
constraints
->
always_on
)
{
if
(
!
_regulator_is_enabled
(
rdev
))
{
if
(
!
_regulator_is_enabled
(
rdev
))
{
error
=
_regulator_do_enable
(
rdev
);
ret
=
_regulator_do_enable
(
rdev
);
if
(
error
)
if
(
ret
)
ret
=
error
;
dev_err
(
dev
,
"Failed to resume regulator %d
\n
"
,
ret
);
}
}
}
else
{
}
else
{
if
(
!
have_full_constraints
())
if
(
!
have_full_constraints
())
...
@@ -3925,15 +3966,27 @@ int regulator_suspend_finish(void)
...
@@ -3925,15 +3966,27 @@ int regulator_suspend_finish(void)
if
(
!
_regulator_is_enabled
(
rdev
))
if
(
!
_regulator_is_enabled
(
rdev
))
goto
unlock
;
goto
unlock
;
error
=
_regulator_do_disable
(
rdev
);
ret
=
_regulator_do_disable
(
rdev
);
if
(
error
)
if
(
ret
)
ret
=
error
;
dev_err
(
dev
,
"Failed to suspend regulator %d
\n
"
,
ret
)
;
}
}
unlock:
unlock:
mutex_unlock
(
&
rdev
->
mutex
);
mutex_unlock
(
&
rdev
->
mutex
);
}
mutex_unlock
(
&
regulator_list_mutex
);
/* Keep processing regulators in spite of any errors */
return
ret
;
return
0
;
}
/**
* regulator_suspend_finish - resume regulators from system wide suspend
*
* Turn on regulators that might be turned off by regulator_suspend_prepare
* and that should be turned on according to the regulators properties.
*/
int
regulator_suspend_finish
(
void
)
{
return
class_for_each_device
(
&
regulator_class
,
NULL
,
NULL
,
_regulator_suspend_finish
);
}
}
EXPORT_SYMBOL_GPL
(
regulator_suspend_finish
);
EXPORT_SYMBOL_GPL
(
regulator_suspend_finish
);
...
@@ -4053,14 +4106,35 @@ static const struct file_operations supply_map_fops = {
...
@@ -4053,14 +4106,35 @@ static const struct file_operations supply_map_fops = {
};
};
#ifdef CONFIG_DEBUG_FS
#ifdef CONFIG_DEBUG_FS
struct
summary_data
{
struct
seq_file
*
s
;
struct
regulator_dev
*
parent
;
int
level
;
};
static
void
regulator_summary_show_subtree
(
struct
seq_file
*
s
,
struct
regulator_dev
*
rdev
,
int
level
);
static
int
regulator_summary_show_children
(
struct
device
*
dev
,
void
*
data
)
{
struct
regulator_dev
*
rdev
=
dev_to_rdev
(
dev
);
struct
summary_data
*
summary_data
=
data
;
if
(
rdev
->
supply
&&
rdev
->
supply
->
rdev
==
summary_data
->
parent
)
regulator_summary_show_subtree
(
summary_data
->
s
,
rdev
,
summary_data
->
level
+
1
);
return
0
;
}
static
void
regulator_summary_show_subtree
(
struct
seq_file
*
s
,
static
void
regulator_summary_show_subtree
(
struct
seq_file
*
s
,
struct
regulator_dev
*
rdev
,
struct
regulator_dev
*
rdev
,
int
level
)
int
level
)
{
{
struct
list_head
*
list
=
s
->
private
;
struct
regulator_dev
*
child
;
struct
regulation_constraints
*
c
;
struct
regulation_constraints
*
c
;
struct
regulator
*
consumer
;
struct
regulator
*
consumer
;
struct
summary_data
summary_data
;
if
(
!
rdev
)
if
(
!
rdev
)
return
;
return
;
...
@@ -4110,33 +4184,32 @@ static void regulator_summary_show_subtree(struct seq_file *s,
...
@@ -4110,33 +4184,32 @@ static void regulator_summary_show_subtree(struct seq_file *s,
seq_puts
(
s
,
"
\n
"
);
seq_puts
(
s
,
"
\n
"
);
}
}
list_for_each_entry
(
child
,
list
,
list
)
{
summary_data
.
s
=
s
;
/* handle only non-root regulators supplied by current rdev */
summary_data
.
level
=
level
;
if
(
!
child
->
supply
||
child
->
supply
->
rdev
!=
rdev
)
summary_data
.
parent
=
rdev
;
continue
;
regulator_summary_show_subtree
(
s
,
child
,
level
+
1
);
class_for_each_device
(
&
regulator_class
,
NULL
,
&
summary_data
,
}
regulator_summary_show_children
);
}
}
static
int
regulator_summary_show
(
struct
seq_file
*
s
,
void
*
data
)
static
int
regulator_summary_show
_roots
(
struct
device
*
dev
,
void
*
data
)
{
{
struct
list_head
*
list
=
s
->
private
;
struct
regulator_dev
*
rdev
=
dev_to_rdev
(
dev
);
struct
regulator_dev
*
rdev
;
struct
seq_file
*
s
=
data
;
seq_puts
(
s
,
" regulator use open bypass voltage current min max
\n
"
);
seq_puts
(
s
,
"-------------------------------------------------------------------------------
\n
"
);
mutex_lock
(
&
regulator_list_mutex
);
if
(
!
rdev
->
supply
)
regulator_summary_show_subtree
(
s
,
rdev
,
0
);
list_for_each_entry
(
rdev
,
list
,
list
)
{
return
0
;
if
(
rdev
->
supply
)
}
continue
;
regulator_summary_show_subtree
(
s
,
rdev
,
0
);
static
int
regulator_summary_show
(
struct
seq_file
*
s
,
void
*
data
)
}
{
seq_puts
(
s
,
" regulator use open bypass voltage current min max
\n
"
);
seq_puts
(
s
,
"-------------------------------------------------------------------------------
\n
"
);
mutex_unlock
(
&
regulator_list_mutex
);
class_for_each_device
(
&
regulator_class
,
NULL
,
s
,
regulator_summary_show_roots
);
return
0
;
return
0
;
}
}
...
@@ -4170,7 +4243,7 @@ static int __init regulator_init(void)
...
@@ -4170,7 +4243,7 @@ static int __init regulator_init(void)
&
supply_map_fops
);
&
supply_map_fops
);
debugfs_create_file
(
"regulator_summary"
,
0444
,
debugfs_root
,
debugfs_create_file
(
"regulator_summary"
,
0444
,
debugfs_root
,
&
regulator_list
,
&
regulator_summary_fops
);
NULL
,
&
regulator_summary_fops
);
regulator_dummy_init
();
regulator_dummy_init
();
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment