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