1818#include <linux/of.h>
1919#include <linux/of_address.h>
2020#include <linux/pm_runtime.h>
21+ #include <linux/of_platform.h>
22+ #include <linux/sched.h>
2123
2224struct exynos_pm_domain_config {
2325 /* Value for LOCAL_PWR_CFG and STATUS fields for each domain */
@@ -73,15 +75,15 @@ static int exynos_pd_power_off(struct generic_pm_domain *domain)
7375 return exynos_pd_power (domain , false);
7476}
7577
76- static const struct exynos_pm_domain_config exynos4210_cfg = {
78+ static const struct exynos_pm_domain_config exynos4210_cfg __initconst = {
7779 .local_pwr_cfg = 0x7 ,
7880};
7981
80- static const struct exynos_pm_domain_config exynos5433_cfg = {
82+ static const struct exynos_pm_domain_config exynos5433_cfg __initconst = {
8183 .local_pwr_cfg = 0xf ,
8284};
8385
84- static const struct of_device_id exynos_pm_domain_of_match [] = {
86+ static const struct of_device_id exynos_pm_domain_of_match [] __initconst = {
8587 {
8688 .compatible = "samsung,exynos4210-pd" ,
8789 .data = & exynos4210_cfg ,
@@ -92,7 +94,7 @@ static const struct of_device_id exynos_pm_domain_of_match[] = {
9294 { },
9395};
9496
95- static const char * exynos_get_domain_name (struct device_node * node )
97+ static __init const char * exynos_get_domain_name (struct device_node * node )
9698{
9799 const char * name ;
98100
@@ -101,44 +103,60 @@ static const char *exynos_get_domain_name(struct device_node *node)
101103 return kstrdup_const (name , GFP_KERNEL );
102104}
103105
104- static int exynos_pd_probe ( struct platform_device * pdev )
106+ static __init int exynos4_pm_init_power_domain ( void )
105107{
106- const struct exynos_pm_domain_config * pm_domain_cfg ;
107- struct device * dev = & pdev -> dev ;
108- struct device_node * np = dev -> of_node ;
109- struct of_phandle_args child , parent ;
110- struct exynos_pm_domain * pd ;
111- int on , ret ;
108+ struct device_node * np ;
109+ const struct of_device_id * match ;
112110
113- pm_domain_cfg = of_device_get_match_data ( dev );
114- pd = devm_kzalloc ( dev , sizeof ( * pd ), GFP_KERNEL ) ;
115- if (! pd )
116- return - ENOMEM ;
111+ for_each_matching_node_and_match ( np , exynos_pm_domain_of_match , & match ) {
112+ const struct exynos_pm_domain_config * pm_domain_cfg ;
113+ struct exynos_pm_domain * pd ;
114+ int on ;
117115
118- pd -> pd .name = exynos_get_domain_name (np );
119- if (!pd -> pd .name )
120- return - ENOMEM ;
116+ pm_domain_cfg = match -> data ;
121117
122- pd -> base = of_iomap (np , 0 );
123- if (!pd -> base ) {
124- kfree_const (pd -> pd .name );
125- return - ENODEV ;
126- }
118+ pd = kzalloc (sizeof (* pd ), GFP_KERNEL );
119+ if (!pd ) {
120+ of_node_put (np );
121+ return - ENOMEM ;
122+ }
123+ pd -> pd .name = exynos_get_domain_name (np );
124+ if (!pd -> pd .name ) {
125+ kfree (pd );
126+ of_node_put (np );
127+ return - ENOMEM ;
128+ }
127129
128- pd -> pd .power_off = exynos_pd_power_off ;
129- pd -> pd .power_on = exynos_pd_power_on ;
130- pd -> local_pwr_cfg = pm_domain_cfg -> local_pwr_cfg ;
130+ pd -> base = of_iomap (np , 0 );
131+ if (!pd -> base ) {
132+ pr_warn ("%s: failed to map memory\n" , __func__ );
133+ kfree_const (pd -> pd .name );
134+ kfree (pd );
135+ continue ;
136+ }
137+
138+ pd -> pd .power_off = exynos_pd_power_off ;
139+ pd -> pd .power_on = exynos_pd_power_on ;
140+ pd -> local_pwr_cfg = pm_domain_cfg -> local_pwr_cfg ;
131141
132- on = readl_relaxed (pd -> base + 0x4 ) & pd -> local_pwr_cfg ;
142+ on = readl_relaxed (pd -> base + 0x4 ) & pd -> local_pwr_cfg ;
143+
144+ pm_genpd_init (& pd -> pd , NULL , !on );
145+ of_genpd_add_provider_simple (np , & pd -> pd );
146+ }
133147
134- pm_genpd_init (& pd -> pd , NULL , !on );
135- ret = of_genpd_add_provider_simple (np , & pd -> pd );
148+ /* Assign the child power domains to their parents */
149+ for_each_matching_node (np , exynos_pm_domain_of_match ) {
150+ struct of_phandle_args child , parent ;
136151
137- if (ret == 0 && of_parse_phandle_with_args (np , "power-domains" ,
138- "#power-domain-cells" , 0 , & parent ) == 0 ) {
139152 child .np = np ;
140153 child .args_count = 0 ;
141154
155+ if (of_parse_phandle_with_args (np , "power-domains" ,
156+ "#power-domain-cells" , 0 ,
157+ & parent ) != 0 )
158+ continue ;
159+
142160 if (of_genpd_add_subdomain (& parent , & child ))
143161 pr_warn ("%pOF failed to add subdomain: %pOF\n" ,
144162 parent .np , child .np );
@@ -147,21 +165,6 @@ static int exynos_pd_probe(struct platform_device *pdev)
147165 parent .np , child .np );
148166 }
149167
150- pm_runtime_enable (dev );
151- return ret ;
152- }
153-
154- static struct platform_driver exynos_pd_driver = {
155- .probe = exynos_pd_probe ,
156- .driver = {
157- .name = "exynos-pd" ,
158- .of_match_table = exynos_pm_domain_of_match ,
159- .suppress_bind_attrs = true,
160- }
161- };
162-
163- static __init int exynos4_pm_init_power_domain (void )
164- {
165- return platform_driver_register (& exynos_pd_driver );
168+ return 0 ;
166169}
167170core_initcall (exynos4_pm_init_power_domain );
0 commit comments