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