1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (C) 2017 ZTE Ltd.
5 * Author: Baoyou Xie <baoyou.xie@linaro.org>
8 #include <linux/delay.h>
13 #include "zx2967_pm_domains.h"
15 #define PCU_DM_CLKEN(zpd) ((zpd)->reg_offset[REG_CLKEN])
16 #define PCU_DM_ISOEN(zpd) ((zpd)->reg_offset[REG_ISOEN])
17 #define PCU_DM_RSTEN(zpd) ((zpd)->reg_offset[REG_RSTEN])
18 #define PCU_DM_PWREN(zpd) ((zpd)->reg_offset[REG_PWREN])
19 #define PCU_DM_ACK_SYNC(zpd) ((zpd)->reg_offset[REG_ACK_SYNC])
21 static void __iomem
*pcubase
;
23 static int zx2967_power_on(struct generic_pm_domain
*domain
)
25 struct zx2967_pm_domain
*zpd
= (struct zx2967_pm_domain
*)domain
;
26 unsigned long loop
= 1000;
29 val
= readl_relaxed(pcubase
+ PCU_DM_PWREN(zpd
));
30 if (zpd
->polarity
== PWREN
)
33 val
&= ~BIT(zpd
->bit
);
34 writel_relaxed(val
, pcubase
+ PCU_DM_PWREN(zpd
));
38 val
= readl_relaxed(pcubase
+ PCU_DM_ACK_SYNC(zpd
))
40 } while (--loop
&& !val
);
43 pr_err("Error: %s %s fail\n", __func__
, domain
->name
);
47 val
= readl_relaxed(pcubase
+ PCU_DM_RSTEN(zpd
));
49 writel_relaxed(val
, pcubase
+ PCU_DM_RSTEN(zpd
));
52 val
= readl_relaxed(pcubase
+ PCU_DM_ISOEN(zpd
));
53 val
&= ~BIT(zpd
->bit
);
54 writel_relaxed(val
, pcubase
+ PCU_DM_ISOEN(zpd
));
57 val
= readl_relaxed(pcubase
+ PCU_DM_CLKEN(zpd
));
59 writel_relaxed(val
, pcubase
+ PCU_DM_CLKEN(zpd
));
62 pr_debug("poweron %s\n", domain
->name
);
67 static int zx2967_power_off(struct generic_pm_domain
*domain
)
69 struct zx2967_pm_domain
*zpd
= (struct zx2967_pm_domain
*)domain
;
70 unsigned long loop
= 1000;
73 val
= readl_relaxed(pcubase
+ PCU_DM_CLKEN(zpd
));
74 val
&= ~BIT(zpd
->bit
);
75 writel_relaxed(val
, pcubase
+ PCU_DM_CLKEN(zpd
));
78 val
= readl_relaxed(pcubase
+ PCU_DM_ISOEN(zpd
));
80 writel_relaxed(val
, pcubase
+ PCU_DM_ISOEN(zpd
));
83 val
= readl_relaxed(pcubase
+ PCU_DM_RSTEN(zpd
));
84 val
&= ~BIT(zpd
->bit
);
85 writel_relaxed(val
, pcubase
+ PCU_DM_RSTEN(zpd
));
88 val
= readl_relaxed(pcubase
+ PCU_DM_PWREN(zpd
));
89 if (zpd
->polarity
== PWREN
)
90 val
&= ~BIT(zpd
->bit
);
93 writel_relaxed(val
, pcubase
+ PCU_DM_PWREN(zpd
));
97 val
= readl_relaxed(pcubase
+ PCU_DM_ACK_SYNC(zpd
))
99 } while (--loop
&& val
);
102 pr_err("Error: %s %s fail\n", __func__
, domain
->name
);
106 pr_debug("poweroff %s\n", domain
->name
);
111 int zx2967_pd_probe(struct platform_device
*pdev
,
112 struct generic_pm_domain
**zx_pm_domains
,
115 struct genpd_onecell_data
*genpd_data
;
116 struct resource
*res
;
119 genpd_data
= devm_kzalloc(&pdev
->dev
, sizeof(*genpd_data
), GFP_KERNEL
);
123 genpd_data
->domains
= zx_pm_domains
;
124 genpd_data
->num_domains
= domain_num
;
126 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
127 pcubase
= devm_ioremap_resource(&pdev
->dev
, res
);
129 return PTR_ERR(pcubase
);
131 for (i
= 0; i
< domain_num
; ++i
) {
132 zx_pm_domains
[i
]->power_on
= zx2967_power_on
;
133 zx_pm_domains
[i
]->power_off
= zx2967_power_off
;
135 pm_genpd_init(zx_pm_domains
[i
], NULL
, false);
138 of_genpd_add_provider_onecell(pdev
->dev
.of_node
, genpd_data
);
139 dev_info(&pdev
->dev
, "powerdomain init ok\n");