53fb60db62ad4b400b42ad7045ab965d3c221601
[firefly-linux-kernel-4.4.55.git] / drivers / clk / rk / pd-rk3368.c
1 /*
2  * Power domain support for Rockchip RK3368
3  *
4  * Copyright (C) 2014-2015 ROCKCHIP, Inc.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  */
16
17 #include <linux/of.h>
18 #include <linux/of_address.h>
19 #include <linux/rockchip/pmu.h>
20 #include <linux/rockchip/cru.h>
21 #include <linux/rockchip/cpu_axi.h>
22
23 #include "clk-ops.h"
24
25 static void __iomem *rk_pmu_base;
26
27 static u32 pmu_readl(u32 offset)
28 {
29         return readl_relaxed(rk_pmu_base + (offset));
30 }
31
32 static void pmu_writel(u32 val, u32 offset)
33 {
34         writel_relaxed(val, rk_pmu_base + (offset));
35         dsb(sy);
36 }
37
38 static const u8 pmu_pd_map[] = {
39         [PD_PERI] = 13,
40         [PD_VIDEO] = 14,
41         [PD_VIO] = 15,
42         [PD_GPU_0] = 16,
43         [PD_GPU_1] = 17,
44 };
45
46 static const u8 pmu_st_map[] = {
47         [PD_PERI] = 12,
48         [PD_VIDEO] = 13,
49         [PD_VIO] = 14,
50         [PD_GPU_0] = 15,
51         [PD_GPU_1] = 16,
52 };
53
54 static bool rk3368_pmu_power_domain_is_on(enum pmu_power_domain pd)
55 {
56         /* 1'b0: power on, 1'b1: power off */
57         return !(pmu_readl(RK3368_PMU_PWRDN_ST) & BIT(pmu_st_map[pd]));
58 }
59
60 static DEFINE_SPINLOCK(pmu_idle_lock);
61
62 static const u8 pmu_idle_map[] = {
63         [IDLE_REQ_GPU] = 2,
64         [IDLE_REQ_BUS] = 4,
65         [IDLE_REQ_PERI] = 6,
66         [IDLE_REQ_VIDEO] = 7,
67         [IDLE_REQ_VIO] = 8,
68 };
69
70 static int rk3368_pmu_set_idle_request(enum pmu_idle_req req, bool idle)
71 {
72         u32 bit = pmu_idle_map[req];
73         u32 idle_mask = BIT(bit) | BIT(bit + 16);
74         u32 idle_target = (idle << bit) | (idle << (bit + 16));
75         u32 mask = BIT(bit);
76         u32 val;
77         unsigned long flags;
78
79         spin_lock_irqsave(&pmu_idle_lock, flags);
80
81         val = pmu_readl(RK3368_PMU_IDLE_REQ);
82         if (idle)
83                 val |=  mask;
84         else
85                 val &= ~mask;
86         pmu_writel(val, RK3368_PMU_IDLE_REQ);
87         dsb(sy);
88
89         while ((pmu_readl(RK3368_PMU_IDLE_ST) & idle_mask) != idle_target)
90                 ;
91
92         spin_unlock_irqrestore(&pmu_idle_lock, flags);
93
94         return 0;
95 }
96
97 static DEFINE_SPINLOCK(pmu_pd_lock);
98
99 static noinline void rk3368_do_pmu_set_power_domain
100                                         (enum pmu_power_domain domain, bool on)
101 {
102         u8 pd = pmu_pd_map[domain];
103         u32 val = pmu_readl(RK3368_PMU_PWRDN_CON);
104
105         if (on)
106                 val &= ~BIT(pd);
107         else
108                 val |=  BIT(pd);
109
110         pmu_writel(val, RK3368_PMU_PWRDN_CON);
111         dsb(sy);
112
113         while ((pmu_readl(RK3368_PMU_PWRDN_ST) & BIT(pmu_st_map[domain])) == on)
114                 ;
115 }
116
117 /* PD_VIO */
118 static void __iomem *iep_qos_base;
119 static u32 iep_qos[CPU_AXI_QOS_NUM_REGS];
120 static void __iomem *isp_r0_qos_base;
121 static u32 isp_r0_qos[CPU_AXI_QOS_NUM_REGS];
122 static void __iomem *isp_r1_qos_base;
123 static u32 isp_r1_qos[CPU_AXI_QOS_NUM_REGS];
124 static void __iomem *isp_w0_qos_base;
125 static u32 isp_w0_qos[CPU_AXI_QOS_NUM_REGS];
126 static void __iomem *isp_w1_qos_base;
127 static u32 isp_w1_qos[CPU_AXI_QOS_NUM_REGS];
128 static void __iomem *vip_qos_base;
129 static u32 vip_qos[CPU_AXI_QOS_NUM_REGS];
130 static void __iomem *vop_qos_base;
131 static u32 vop_qos[CPU_AXI_QOS_NUM_REGS];
132 static void __iomem *rga_r_qos_base;
133 static u32 rga_r_qos[CPU_AXI_QOS_NUM_REGS];
134 static void __iomem *rga_w_qos_base;
135 static u32 rga_w_qos[CPU_AXI_QOS_NUM_REGS];
136 /* PD_VIDEO */
137 static void __iomem *hevc_r_qos_base;
138 static u32 hevc_r_qos[CPU_AXI_QOS_NUM_REGS];
139 static void __iomem *vpu_r_qos_base;
140 static u32 vpu_r_qos[CPU_AXI_QOS_NUM_REGS];
141 static void __iomem *vpu_w_qos_base;
142 static u32 vpu_w_qos[CPU_AXI_QOS_NUM_REGS];
143 /* PD_GPU_0 */
144 static void __iomem *gpu_qos_base;
145 static u32 gpu_qos[CPU_AXI_QOS_NUM_REGS];
146 /* PD_PERI */
147 static void __iomem *peri_qos_base;
148 static u32 peri_qos[CPU_AXI_QOS_NUM_REGS];
149
150 #define PD_SAVE_QOS(name) CPU_AXI_SAVE_QOS(name##_qos, name##_qos_base)
151 #define PD_RESTORE_QOS(name) CPU_AXI_RESTORE_QOS(name##_qos, name##_qos_base)
152
153 static int rk3368_pmu_set_power_domain(enum pmu_power_domain pd, bool on)
154 {
155         unsigned long flags;
156
157         spin_lock_irqsave(&pmu_pd_lock, flags);
158
159         if (rk3368_pmu_power_domain_is_on(pd) == on)
160                 goto out;
161
162         if (!on) {
163                 /* if power down, idle request to NIU first */
164                 if (pd == PD_VIO) {
165                         PD_SAVE_QOS(iep);
166                         PD_SAVE_QOS(isp_r0);
167                         PD_SAVE_QOS(isp_r1);
168                         PD_SAVE_QOS(isp_w0);
169                         PD_SAVE_QOS(isp_w1);
170                         PD_SAVE_QOS(vip);
171                         PD_SAVE_QOS(vop);
172                         PD_SAVE_QOS(rga_r);
173                         PD_SAVE_QOS(rga_w);
174                         rk3368_pmu_set_idle_request(IDLE_REQ_VIO, true);
175                 } else if (pd == PD_VIDEO) {
176                         PD_SAVE_QOS(hevc_r);
177                         PD_SAVE_QOS(vpu_r);
178                         PD_SAVE_QOS(vpu_w);
179                         rk3368_pmu_set_idle_request(IDLE_REQ_VIDEO, true);
180                 } else if (pd == PD_GPU_0) {
181                         PD_SAVE_QOS(gpu);
182                         rk3368_pmu_set_idle_request(IDLE_REQ_GPU, true);
183                 } else if (pd == PD_PERI) {
184                         PD_SAVE_QOS(peri);
185                         rk3368_pmu_set_idle_request(IDLE_REQ_PERI, true);
186                 }
187         }
188
189         rk3368_do_pmu_set_power_domain(pd, on);
190
191         if (on) {
192                 /* if power up, idle request release to NIU */
193                 if (pd == PD_VIO) {
194                         rk3368_pmu_set_idle_request(IDLE_REQ_VIO, false);
195                         PD_RESTORE_QOS(iep);
196                         PD_RESTORE_QOS(isp_r0);
197                         PD_RESTORE_QOS(isp_r1);
198                         PD_RESTORE_QOS(isp_w0);
199                         PD_RESTORE_QOS(isp_w1);
200                         PD_RESTORE_QOS(vip);
201                         PD_RESTORE_QOS(vop);
202                         PD_RESTORE_QOS(rga_r);
203                         PD_RESTORE_QOS(rga_w);
204                 } else if (pd == PD_VIDEO) {
205                         rk3368_pmu_set_idle_request(IDLE_REQ_VIDEO, false);
206                         PD_RESTORE_QOS(hevc_r);
207                         PD_RESTORE_QOS(vpu_r);
208                         PD_RESTORE_QOS(vpu_w);
209                 } else if (pd == PD_GPU_0) {
210                         rk3368_pmu_set_idle_request(IDLE_REQ_GPU, false);
211                         PD_RESTORE_QOS(gpu);
212                 } else if (pd == PD_PERI) {
213                         rk3368_pmu_set_idle_request(IDLE_REQ_PERI, false);
214                         PD_RESTORE_QOS(peri);
215                 }
216         }
217
218 out:
219         spin_unlock_irqrestore(&pmu_pd_lock, flags);
220         return 0;
221 }
222
223 static int rk3368_sys_set_power_domain(enum pmu_power_domain pd, bool on)
224 {
225         u32 clks_ungating[RK3368_CRU_CLKGATES_CON_CNT];
226         u32 clks_save[RK3368_CRU_CLKGATES_CON_CNT];
227         u32 i, ret;
228
229         for (i = 0; i < RK3368_CRU_CLKGATES_CON_CNT; i++) {
230                 clks_save[i] = cru_readl(RK3368_CRU_CLKGATES_CON(i));
231                 clks_ungating[i] = 0;
232         }
233
234         for (i = 0; i < RK3368_CRU_CLKGATES_CON_CNT; i++)
235                 cru_writel(0xffff0000, RK3368_CRU_CLKGATES_CON(i));
236
237         ret = rk3368_pmu_set_power_domain(pd, on);
238
239         for (i = 0; i < RK3368_CRU_CLKGATES_CON_CNT; i++)
240                 cru_writel(clks_save[i] | 0xffff0000,
241                            RK3368_CRU_CLKGATES_CON(i));
242
243         return ret;
244 }
245
246 static int __init rk3368_init_rockchip_pmu_ops(void)
247 {
248         struct device_node *node, *gp, *cp;
249
250         node = of_find_compatible_node(NULL, NULL, "rockchip,rk3368-pmu");
251         if (!node) {
252                 pr_err("%s: could not find pmu dt node\n", __func__);
253                 return -ENODEV;
254         }
255
256         rk_pmu_base = of_iomap(node, 0);
257         if (!rk_pmu_base) {
258                 pr_err("%s: could not map pmu registers\n", __func__);
259                 return -ENXIO;
260         }
261
262         node = of_find_compatible_node(NULL, NULL, "rockchip,cpu_axi_bus");
263         if (!node)
264                 return -ENODEV;
265
266 #define MAP(name)                                                       \
267         do {                                                            \
268                 cp = of_get_child_by_name(gp, #name);                   \
269                 if (cp)                                                 \
270                         name##_qos_base = of_iomap(cp, 0);              \
271                 if (!name##_qos_base)                                   \
272                         pr_err("%s: could not map qos %s register\n",   \
273                                __func__, #name);                        \
274         } while (0)
275
276         gp = of_get_child_by_name(node, "qos");
277         if (gp) {
278                 MAP(peri);
279                 MAP(iep);
280                 MAP(isp_r0);
281                 MAP(isp_r1);
282                 MAP(isp_w0);
283                 MAP(isp_w1);
284                 MAP(vip);
285                 MAP(vop);
286                 MAP(rga_r);
287                 MAP(rga_w);
288                 MAP(hevc_r);
289                 MAP(vpu_r);
290                 MAP(vpu_w);
291                 MAP(gpu);
292         }
293
294 #undef MAP
295
296         rockchip_pmu_ops.set_power_domain = rk3368_sys_set_power_domain;
297         rockchip_pmu_ops.power_domain_is_on = rk3368_pmu_power_domain_is_on;
298
299         return 0;
300 }
301
302 arch_initcall(rk3368_init_rockchip_pmu_ops);