xref: /rk3399_ARM-atf/plat/rockchip/common/plat_pm_helpers.c (revision 44418fce30938ee483fbfc79cc32fde33753d1aa)
1*e3ec6ff4SXiaoDong Huang /*
2*e3ec6ff4SXiaoDong Huang  * Copyright (c) 2024, Rockchip, Inc. All rights reserved.
3*e3ec6ff4SXiaoDong Huang  *
4*e3ec6ff4SXiaoDong Huang  * SPDX-License-Identifier: BSD-3-Clause
5*e3ec6ff4SXiaoDong Huang  */
6*e3ec6ff4SXiaoDong Huang 
7*e3ec6ff4SXiaoDong Huang #include <assert.h>
8*e3ec6ff4SXiaoDong Huang #include <errno.h>
9*e3ec6ff4SXiaoDong Huang 
10*e3ec6ff4SXiaoDong Huang #include <arch_helpers.h>
11*e3ec6ff4SXiaoDong Huang #include <bl31/bl31.h>
12*e3ec6ff4SXiaoDong Huang #include <common/debug.h>
13*e3ec6ff4SXiaoDong Huang #include <drivers/console.h>
14*e3ec6ff4SXiaoDong Huang #include <drivers/delay_timer.h>
15*e3ec6ff4SXiaoDong Huang #include <lib/mmio.h>
16*e3ec6ff4SXiaoDong Huang #include <plat/common/platform.h>
17*e3ec6ff4SXiaoDong Huang #include <platform_def.h>
18*e3ec6ff4SXiaoDong Huang 
19*e3ec6ff4SXiaoDong Huang #include <plat_pm_helpers.h>
20*e3ec6ff4SXiaoDong Huang 
21*e3ec6ff4SXiaoDong Huang #define ROCKCHIP_PM_REG_REGION_MEM_LEN	(ROCKCHIP_PM_REG_REGION_MEM_SIZE / sizeof(uint32_t))
22*e3ec6ff4SXiaoDong Huang 
23*e3ec6ff4SXiaoDong Huang /* REG region */
24*e3ec6ff4SXiaoDong Huang #define RGN_LEN(_rgn)		(((_rgn)->end - (_rgn)->start) / (_rgn)->stride + 1)
25*e3ec6ff4SXiaoDong Huang 
26*e3ec6ff4SXiaoDong Huang #ifndef ROCKCHIP_PM_REG_REGION_MEM_SIZE
27*e3ec6ff4SXiaoDong Huang #define ROCKCHIP_PM_REG_REGION_MEM_SIZE		0
28*e3ec6ff4SXiaoDong Huang #endif
29*e3ec6ff4SXiaoDong Huang 
30*e3ec6ff4SXiaoDong Huang #ifdef ROCKCHIP_REG_RGN_MEM_BASE
31*e3ec6ff4SXiaoDong Huang static uint32_t *region_mem = (uint32_t *)ROCKCHIP_REG_RGN_MEM_BASE;
32*e3ec6ff4SXiaoDong Huang #else
33*e3ec6ff4SXiaoDong Huang static uint32_t region_mem[ROCKCHIP_PM_REG_REGION_MEM_LEN];
34*e3ec6ff4SXiaoDong Huang #endif
35*e3ec6ff4SXiaoDong Huang 
36*e3ec6ff4SXiaoDong Huang static int region_mem_idx;
37*e3ec6ff4SXiaoDong Huang 
alloc_region_mem(uint32_t * buf,int max_len,struct reg_region * rgns,uint32_t rgn_num)38*e3ec6ff4SXiaoDong Huang static int alloc_region_mem(uint32_t *buf, int max_len,
39*e3ec6ff4SXiaoDong Huang 			    struct reg_region *rgns, uint32_t rgn_num)
40*e3ec6ff4SXiaoDong Huang {
41*e3ec6ff4SXiaoDong Huang 	int i;
42*e3ec6ff4SXiaoDong Huang 	int total_len = 0, len = 0;
43*e3ec6ff4SXiaoDong Huang 	struct reg_region *r = rgns;
44*e3ec6ff4SXiaoDong Huang 
45*e3ec6ff4SXiaoDong Huang 	assert(buf && rgns && rgn_num);
46*e3ec6ff4SXiaoDong Huang 
47*e3ec6ff4SXiaoDong Huang 	for (i = 0; i < rgn_num; i++, r++) {
48*e3ec6ff4SXiaoDong Huang 		if (total_len < max_len)
49*e3ec6ff4SXiaoDong Huang 			r->buf = &buf[total_len];
50*e3ec6ff4SXiaoDong Huang 
51*e3ec6ff4SXiaoDong Huang 		len = RGN_LEN(r);
52*e3ec6ff4SXiaoDong Huang 		total_len += len;
53*e3ec6ff4SXiaoDong Huang 	}
54*e3ec6ff4SXiaoDong Huang 
55*e3ec6ff4SXiaoDong Huang 	if (total_len > max_len) {
56*e3ec6ff4SXiaoDong Huang 		ERROR("%s The buffer remain length:%d is too small for region:0x%x, at least %d\n",
57*e3ec6ff4SXiaoDong Huang 		      __func__, max_len, rgns[0].start, total_len);
58*e3ec6ff4SXiaoDong Huang 		panic();
59*e3ec6ff4SXiaoDong Huang 	}
60*e3ec6ff4SXiaoDong Huang 
61*e3ec6ff4SXiaoDong Huang 	return total_len;
62*e3ec6ff4SXiaoDong Huang }
63*e3ec6ff4SXiaoDong Huang 
64*e3ec6ff4SXiaoDong Huang /**
65*e3ec6ff4SXiaoDong Huang  * Alloc memory to reg_region->buf from region_mem.
66*e3ec6ff4SXiaoDong Huang  * @rgns - struct reg_region array.
67*e3ec6ff4SXiaoDong Huang  * @rgn_num - struct reg_region array length.
68*e3ec6ff4SXiaoDong Huang  */
rockchip_alloc_region_mem(struct reg_region * rgns,uint32_t rgn_num)69*e3ec6ff4SXiaoDong Huang void rockchip_alloc_region_mem(struct reg_region *rgns, uint32_t rgn_num)
70*e3ec6ff4SXiaoDong Huang {
71*e3ec6ff4SXiaoDong Huang 	int max_len = 0, len;
72*e3ec6ff4SXiaoDong Huang 
73*e3ec6ff4SXiaoDong Huang 	assert(rgns && rgn_num);
74*e3ec6ff4SXiaoDong Huang 
75*e3ec6ff4SXiaoDong Huang 	max_len = ROCKCHIP_PM_REG_REGION_MEM_LEN - region_mem_idx;
76*e3ec6ff4SXiaoDong Huang 
77*e3ec6ff4SXiaoDong Huang 	len = alloc_region_mem(region_mem + region_mem_idx, max_len,
78*e3ec6ff4SXiaoDong Huang 			       rgns, rgn_num);
79*e3ec6ff4SXiaoDong Huang 
80*e3ec6ff4SXiaoDong Huang 	region_mem_idx += len;
81*e3ec6ff4SXiaoDong Huang }
82*e3ec6ff4SXiaoDong Huang 
83*e3ec6ff4SXiaoDong Huang /**
84*e3ec6ff4SXiaoDong Huang  * Save (reg_region->start ~ reg_region->end) to reg_region->buf.
85*e3ec6ff4SXiaoDong Huang  * @rgns - struct reg_region array.
86*e3ec6ff4SXiaoDong Huang  * @rgn_num - struct reg_region array length.
87*e3ec6ff4SXiaoDong Huang  */
rockchip_reg_rgn_save(struct reg_region * rgns,uint32_t rgn_num)88*e3ec6ff4SXiaoDong Huang void rockchip_reg_rgn_save(struct reg_region *rgns, uint32_t rgn_num)
89*e3ec6ff4SXiaoDong Huang {
90*e3ec6ff4SXiaoDong Huang 	struct reg_region *r;
91*e3ec6ff4SXiaoDong Huang 	uint32_t addr;
92*e3ec6ff4SXiaoDong Huang 	int i, j;
93*e3ec6ff4SXiaoDong Huang 
94*e3ec6ff4SXiaoDong Huang 	assert(rgns && rgn_num);
95*e3ec6ff4SXiaoDong Huang 
96*e3ec6ff4SXiaoDong Huang 	for (i = 0; i < rgn_num; i++) {
97*e3ec6ff4SXiaoDong Huang 		r = &rgns[i];
98*e3ec6ff4SXiaoDong Huang 		for (j = 0, addr = r->start; addr <= r->end; addr += r->stride, j++)
99*e3ec6ff4SXiaoDong Huang 			r->buf[j] = mmio_read_32(addr);
100*e3ec6ff4SXiaoDong Huang 	}
101*e3ec6ff4SXiaoDong Huang }
102*e3ec6ff4SXiaoDong Huang 
103*e3ec6ff4SXiaoDong Huang /**
104*e3ec6ff4SXiaoDong Huang  * Restore reg_region->buf to (reg_region->start ~ reg_region->end).
105*e3ec6ff4SXiaoDong Huang  * @rgns - struct reg_region array.
106*e3ec6ff4SXiaoDong Huang  * @rgn_num - struct reg_region array length.
107*e3ec6ff4SXiaoDong Huang  */
rockchip_reg_rgn_restore(struct reg_region * rgns,uint32_t rgn_num)108*e3ec6ff4SXiaoDong Huang void rockchip_reg_rgn_restore(struct reg_region *rgns, uint32_t rgn_num)
109*e3ec6ff4SXiaoDong Huang {
110*e3ec6ff4SXiaoDong Huang 	struct reg_region *r;
111*e3ec6ff4SXiaoDong Huang 	uint32_t addr;
112*e3ec6ff4SXiaoDong Huang 	int i, j;
113*e3ec6ff4SXiaoDong Huang 
114*e3ec6ff4SXiaoDong Huang 	assert(rgns && rgn_num);
115*e3ec6ff4SXiaoDong Huang 
116*e3ec6ff4SXiaoDong Huang 	for (i = 0; i < rgn_num; i++) {
117*e3ec6ff4SXiaoDong Huang 		r = &rgns[i];
118*e3ec6ff4SXiaoDong Huang 		for (j = 0, addr = r->start; addr <= r->end; addr += r->stride, j++)
119*e3ec6ff4SXiaoDong Huang 			mmio_write_32(addr, r->buf[j] | r->wmsk);
120*e3ec6ff4SXiaoDong Huang 
121*e3ec6ff4SXiaoDong Huang 		dsb();
122*e3ec6ff4SXiaoDong Huang 	}
123*e3ec6ff4SXiaoDong Huang }
124*e3ec6ff4SXiaoDong Huang 
125*e3ec6ff4SXiaoDong Huang /**
126*e3ec6ff4SXiaoDong Huang  * Restore reg_region->buf to (reg_region->start ~ reg_region->end) reversely.
127*e3ec6ff4SXiaoDong Huang  * @rgns - struct reg_region array.
128*e3ec6ff4SXiaoDong Huang  * @rgn_num - struct reg_region array length.
129*e3ec6ff4SXiaoDong Huang  */
rockchip_reg_rgn_restore_reverse(struct reg_region * rgns,uint32_t rgn_num)130*e3ec6ff4SXiaoDong Huang void rockchip_reg_rgn_restore_reverse(struct reg_region *rgns, uint32_t rgn_num)
131*e3ec6ff4SXiaoDong Huang {
132*e3ec6ff4SXiaoDong Huang 	struct reg_region *r;
133*e3ec6ff4SXiaoDong Huang 	uint32_t addr;
134*e3ec6ff4SXiaoDong Huang 	int i, j;
135*e3ec6ff4SXiaoDong Huang 
136*e3ec6ff4SXiaoDong Huang 	assert(rgns && rgn_num);
137*e3ec6ff4SXiaoDong Huang 
138*e3ec6ff4SXiaoDong Huang 	for (i = rgn_num - 1; i >= 0; i--) {
139*e3ec6ff4SXiaoDong Huang 		r = &rgns[i];
140*e3ec6ff4SXiaoDong Huang 		j = RGN_LEN(r) - 1;
141*e3ec6ff4SXiaoDong Huang 		for (addr = r->end; addr >= r->start; addr -= r->stride, j--)
142*e3ec6ff4SXiaoDong Huang 			mmio_write_32(addr, r->buf[j] | r->wmsk);
143*e3ec6ff4SXiaoDong Huang 
144*e3ec6ff4SXiaoDong Huang 		dsb();
145*e3ec6ff4SXiaoDong Huang 	}
146*e3ec6ff4SXiaoDong Huang }
147*e3ec6ff4SXiaoDong Huang 
rockchip_print_hex(uint32_t val)148*e3ec6ff4SXiaoDong Huang static void rockchip_print_hex(uint32_t val)
149*e3ec6ff4SXiaoDong Huang {
150*e3ec6ff4SXiaoDong Huang 	int i;
151*e3ec6ff4SXiaoDong Huang 	unsigned char tmp;
152*e3ec6ff4SXiaoDong Huang 
153*e3ec6ff4SXiaoDong Huang 	putchar('0');
154*e3ec6ff4SXiaoDong Huang 	putchar('x');
155*e3ec6ff4SXiaoDong Huang 	for (i = 0; i < 8; val <<= 4, ++i) {
156*e3ec6ff4SXiaoDong Huang 		tmp = (val & 0xf0000000) >> 28;
157*e3ec6ff4SXiaoDong Huang 		if (tmp < 10)
158*e3ec6ff4SXiaoDong Huang 			putchar('0' + tmp);
159*e3ec6ff4SXiaoDong Huang 		else
160*e3ec6ff4SXiaoDong Huang 			putchar('a' + tmp - 10);
161*e3ec6ff4SXiaoDong Huang 	}
162*e3ec6ff4SXiaoDong Huang }
163*e3ec6ff4SXiaoDong Huang 
164*e3ec6ff4SXiaoDong Huang /**
165*e3ec6ff4SXiaoDong Huang  * Dump registers (base + start_offset ~ base + end_offset)
166*e3ec6ff4SXiaoDong Huang  * @base - the base addr of the register.
167*e3ec6ff4SXiaoDong Huang  * @start_offset - the start offset to dump.
168*e3ec6ff4SXiaoDong Huang  * @end_offset - the end offset to dump.
169*e3ec6ff4SXiaoDong Huang  * @stride - the stride of the registers.
170*e3ec6ff4SXiaoDong Huang  */
rockchip_regs_dump(uint32_t base,uint32_t start_offset,uint32_t end_offset,uint32_t stride)171*e3ec6ff4SXiaoDong Huang void rockchip_regs_dump(uint32_t base,
172*e3ec6ff4SXiaoDong Huang 			uint32_t start_offset,
173*e3ec6ff4SXiaoDong Huang 			uint32_t end_offset,
174*e3ec6ff4SXiaoDong Huang 			uint32_t stride)
175*e3ec6ff4SXiaoDong Huang {
176*e3ec6ff4SXiaoDong Huang 	uint32_t i;
177*e3ec6ff4SXiaoDong Huang 
178*e3ec6ff4SXiaoDong Huang 	for (i = start_offset; i <= end_offset; i += stride) {
179*e3ec6ff4SXiaoDong Huang 		if ((i - start_offset) % 16 == 0) {
180*e3ec6ff4SXiaoDong Huang 			putchar('\n');
181*e3ec6ff4SXiaoDong Huang 			rockchip_print_hex(base + i);
182*e3ec6ff4SXiaoDong Huang 			putchar(':');
183*e3ec6ff4SXiaoDong Huang 			putchar(' ');
184*e3ec6ff4SXiaoDong Huang 			putchar(' ');
185*e3ec6ff4SXiaoDong Huang 			putchar(' ');
186*e3ec6ff4SXiaoDong Huang 			putchar(' ');
187*e3ec6ff4SXiaoDong Huang 		}
188*e3ec6ff4SXiaoDong Huang 		rockchip_print_hex(mmio_read_32(base + i));
189*e3ec6ff4SXiaoDong Huang 		putchar(' ');
190*e3ec6ff4SXiaoDong Huang 		putchar(' ');
191*e3ec6ff4SXiaoDong Huang 		putchar(' ');
192*e3ec6ff4SXiaoDong Huang 		putchar(' ');
193*e3ec6ff4SXiaoDong Huang 	}
194*e3ec6ff4SXiaoDong Huang 	putchar('\n');
195*e3ec6ff4SXiaoDong Huang }
196*e3ec6ff4SXiaoDong Huang 
197*e3ec6ff4SXiaoDong Huang /**
198*e3ec6ff4SXiaoDong Huang  * Dump reg regions
199*e3ec6ff4SXiaoDong Huang  * @rgns - struct reg_region array.
200*e3ec6ff4SXiaoDong Huang  * @rgn_num - struct reg_region array length.
201*e3ec6ff4SXiaoDong Huang  */
rockchip_dump_reg_rgns(struct reg_region * rgns,uint32_t rgn_num)202*e3ec6ff4SXiaoDong Huang void rockchip_dump_reg_rgns(struct reg_region *rgns, uint32_t rgn_num)
203*e3ec6ff4SXiaoDong Huang {
204*e3ec6ff4SXiaoDong Huang 	struct reg_region *r;
205*e3ec6ff4SXiaoDong Huang 	int i;
206*e3ec6ff4SXiaoDong Huang 
207*e3ec6ff4SXiaoDong Huang 	assert(rgns && rgn_num);
208*e3ec6ff4SXiaoDong Huang 
209*e3ec6ff4SXiaoDong Huang 	for (i = 0; i < rgn_num; i++) {
210*e3ec6ff4SXiaoDong Huang 		r = &rgns[i];
211*e3ec6ff4SXiaoDong Huang 		rockchip_regs_dump(0x0, r->start, r->end, r->stride);
212*e3ec6ff4SXiaoDong Huang 	}
213*e3ec6ff4SXiaoDong Huang }
214