Skip to content

Commit 30f6042

Browse files
ilina-linarorafaeljw
authored andcommitted
PM / Domains: Allow domain power states to be read from DT
This patch allows domains to define idle states in the DT. SoC's can define domain idle states in DT using the "domain-idle-states" property of the domain provider. Add API to read the idle states from DT that can be set in the genpd object. This patch is based on the original patch by Marc Titinger. Signed-off-by: Marc Titinger <[email protected]> Signed-off-by: Ulf Hansson <[email protected]> Signed-off-by: Lina Iyer <[email protected]> Reviewed-by: Kevin Hilman <[email protected]> Signed-off-by: Rafael J. Wysocki <[email protected]>
1 parent 405f722 commit 30f6042

File tree

2 files changed

+102
-0
lines changed

2 files changed

+102
-0
lines changed

drivers/base/power/domain.c

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1916,6 +1916,100 @@ int genpd_dev_pm_attach(struct device *dev)
19161916
return ret ? -EPROBE_DEFER : 0;
19171917
}
19181918
EXPORT_SYMBOL_GPL(genpd_dev_pm_attach);
1919+
1920+
static const struct of_device_id idle_state_match[] = {
1921+
{ .compatible = "arm,idle-state", },
1922+
{ }
1923+
};
1924+
1925+
static int genpd_parse_state(struct genpd_power_state *genpd_state,
1926+
struct device_node *state_node)
1927+
{
1928+
int err;
1929+
u32 residency;
1930+
u32 entry_latency, exit_latency;
1931+
const struct of_device_id *match_id;
1932+
1933+
match_id = of_match_node(idle_state_match, state_node);
1934+
if (!match_id)
1935+
return -EINVAL;
1936+
1937+
err = of_property_read_u32(state_node, "entry-latency-us",
1938+
&entry_latency);
1939+
if (err) {
1940+
pr_debug(" * %s missing entry-latency-us property\n",
1941+
state_node->full_name);
1942+
return -EINVAL;
1943+
}
1944+
1945+
err = of_property_read_u32(state_node, "exit-latency-us",
1946+
&exit_latency);
1947+
if (err) {
1948+
pr_debug(" * %s missing exit-latency-us property\n",
1949+
state_node->full_name);
1950+
return -EINVAL;
1951+
}
1952+
1953+
err = of_property_read_u32(state_node, "min-residency-us", &residency);
1954+
if (!err)
1955+
genpd_state->residency_ns = 1000 * residency;
1956+
1957+
genpd_state->power_on_latency_ns = 1000 * exit_latency;
1958+
genpd_state->power_off_latency_ns = 1000 * entry_latency;
1959+
1960+
return 0;
1961+
}
1962+
1963+
/**
1964+
* of_genpd_parse_idle_states: Return array of idle states for the genpd.
1965+
*
1966+
* @dn: The genpd device node
1967+
* @states: The pointer to which the state array will be saved.
1968+
* @n: The count of elements in the array returned from this function.
1969+
*
1970+
* Returns the device states parsed from the OF node. The memory for the states
1971+
* is allocated by this function and is the responsibility of the caller to
1972+
* free the memory after use.
1973+
*/
1974+
int of_genpd_parse_idle_states(struct device_node *dn,
1975+
struct genpd_power_state **states, int *n)
1976+
{
1977+
struct genpd_power_state *st;
1978+
struct device_node *np;
1979+
int i = 0;
1980+
int err, ret;
1981+
int count;
1982+
struct of_phandle_iterator it;
1983+
1984+
count = of_count_phandle_with_args(dn, "domain-idle-states", NULL);
1985+
if (!count)
1986+
return -EINVAL;
1987+
1988+
st = kcalloc(count, sizeof(*st), GFP_KERNEL);
1989+
if (!st)
1990+
return -ENOMEM;
1991+
1992+
/* Loop over the phandles until all the requested entry is found */
1993+
of_for_each_phandle(&it, err, dn, "domain-idle-states", NULL, 0) {
1994+
np = it.node;
1995+
ret = genpd_parse_state(&st[i++], np);
1996+
if (ret) {
1997+
pr_err
1998+
("Parsing idle state node %s failed with err %d\n",
1999+
np->full_name, ret);
2000+
of_node_put(np);
2001+
kfree(st);
2002+
return ret;
2003+
}
2004+
}
2005+
2006+
*n = count;
2007+
*states = st;
2008+
2009+
return 0;
2010+
}
2011+
EXPORT_SYMBOL_GPL(of_genpd_parse_idle_states);
2012+
19192013
#endif /* CONFIG_PM_GENERIC_DOMAINS_OF */
19202014

19212015

include/linux/pm_domain.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,8 @@ extern int of_genpd_add_device(struct of_phandle_args *args,
205205
extern int of_genpd_add_subdomain(struct of_phandle_args *parent,
206206
struct of_phandle_args *new_subdomain);
207207
extern struct generic_pm_domain *of_genpd_remove_last(struct device_node *np);
208+
extern int of_genpd_parse_idle_states(struct device_node *dn,
209+
struct genpd_power_state **states, int *n);
208210

209211
int genpd_dev_pm_attach(struct device *dev);
210212
#else /* !CONFIG_PM_GENERIC_DOMAINS_OF */
@@ -234,6 +236,12 @@ static inline int of_genpd_add_subdomain(struct of_phandle_args *parent,
234236
return -ENODEV;
235237
}
236238

239+
static inline int of_genpd_parse_idle_states(struct device_node *dn,
240+
struct genpd_power_state **states, int *n)
241+
{
242+
return -ENODEV;
243+
}
244+
237245
static inline int genpd_dev_pm_attach(struct device *dev)
238246
{
239247
return -ENODEV;

0 commit comments

Comments
 (0)