1 /*
2 * Copyright (c) 2014-2015, Linaro Ltd and Contributors. All rights reserved.
3 * Copyright (c) 2014-2015, Hisilicon Ltd and Contributors. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * Redistributions of source code must retain the above copyright notice, this
9 * list of conditions and the following disclaimer.
10 *
11 * Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
14 *
15 * Neither the name of ARM nor the names of its contributors may be used
16 * to endorse or promote products derived from this software without specific
17 * prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 #include <arch_helpers.h>
33 #include <assert.h>
34 #include <bl_common.h>
35 #include <console.h>
36 #include <debug.h>
37 #include <partitions.h>
38 #include <platform.h>
39 #include <platform_def.h>
40 #include <string.h>
41 #include <mmio.h>
42 #include <hi6220.h>
43
44 #define MCU_SECTION_MAX 30
45
46 enum MCU_IMAGE_SEC_TYPE_ENUM {
47 MCU_IMAGE_SEC_TYPE_TEXT = 0, /* text section */
48 MCU_IMAGE_SEC_TYPE_DATA, /* data section */
49 MCU_IMAGE_SEC_TYPE_BUTT
50 };
51
52 enum MCU_IMAGE_SEC_LOAD_ENUM {
53 MCU_IMAGE_SEC_LOAD_STATIC = 0,
54 MCU_IMAGE_SEC_LOAD_DYNAMIC,
55 MCU_IMAGE_SEC_LOAD_BUFFER,
56 MCU_IMAGE_SEC_LOAD_MODEM_ENTRY,
57 MCU_IMAGE_SEC_LOAD_BUTT
58 };
59
60 struct mcu_image_sec {
61 unsigned short serial;
62 char type;
63 char load_attr;
64 uint32_t src_offset; /* offset in image */
65 uint32_t dst_offset; /* offset in memory */
66 uint32_t size;
67 };
68
69 struct mcu_image_head {
70 char time_stamp[24];
71 uint32_t image_size;
72 uint32_t secs_num;
73 struct mcu_image_sec secs[MCU_SECTION_MAX];
74 };
75
76 #define SOC_SRAM_M3_BASE_ADDR (0xF6000000)
77
78 #define MCU_SRAM_SIZE (0x0000C000)
79 #define MCU_CACHE_SIZE (0x00004000)
80 #define MCU_CODE_SIZE (MCU_SRAM_SIZE - MCU_CACHE_SIZE)
81
82 #define MCU_SYS_MEM_ADDR (0x05E00000)
83 #define MCU_SYS_MEM_SIZE (0x00100000)
84
85 #if 0
86 static uint32_t ap2mcu_addr(uint32_t ap_addr)
87 {
88 if (ap_addr >= SOC_SRAM_M3_BASE_ADDR &&
89 ap_addr < SOC_SRAM_M3_BASE_ADDR + MCU_SRAM_SIZE)
90 return ap_addr - SOC_SRAM_M3_BASE_ADDR;
91 else if (ap_addr >= MCU_SYS_MEM_ADDR &&
92 ap_addr < MCU_SYS_MEM_ADDR + MCU_SYS_MEM_SIZE )
93 return ap_addr - MCU_SYS_MEM_ADDR + MCU_SRAM_SIZE;
94 else
95 return ap_addr;
96 }
97 #endif
98
mcu2ap_addr(uint32_t mcu_addr)99 static uint32_t mcu2ap_addr(uint32_t mcu_addr)
100 {
101 if (mcu_addr < MCU_CODE_SIZE)
102 return (mcu_addr + SOC_SRAM_M3_BASE_ADDR);
103 else if ((mcu_addr >= MCU_SRAM_SIZE) &&
104 (mcu_addr < MCU_SRAM_SIZE + MCU_SYS_MEM_SIZE))
105 return mcu_addr - MCU_SRAM_SIZE + MCU_SYS_MEM_ADDR;
106 else
107 return mcu_addr;
108 }
109
is_binary_header_invalid(struct mcu_image_head * head,unsigned length)110 static int is_binary_header_invalid(struct mcu_image_head *head,
111 unsigned length)
112 {
113 /* invalid cases */
114 if ((head->image_size == 0) ||
115 (head->image_size > length) ||
116 (head->secs_num > MCU_SECTION_MAX) ||
117 (head->secs_num == 0))
118 return 1;
119
120 return 0;
121 }
122
is_binary_section_invalid(struct mcu_image_sec * sec,struct mcu_image_head * head)123 static int is_binary_section_invalid(struct mcu_image_sec *sec,
124 struct mcu_image_head *head)
125 {
126 unsigned long ap_dst_offset = 0;
127
128 if ((sec->serial >= head->secs_num) ||
129 (sec->src_offset + sec->size > head->image_size))
130 return 1;
131
132 if ((sec->type >= MCU_IMAGE_SEC_TYPE_BUTT) ||
133 (sec->load_attr >= MCU_IMAGE_SEC_LOAD_BUTT))
134 return 1;
135
136 ap_dst_offset = mcu2ap_addr(sec->dst_offset);
137 if ((ap_dst_offset >= SOC_SRAM_M3_BASE_ADDR) &&
138 (ap_dst_offset < SOC_SRAM_M3_BASE_ADDR + 0x20000 - sec->size))
139 return 0;
140 else if ((ap_dst_offset >= MCU_SYS_MEM_ADDR) &&
141 (ap_dst_offset < MCU_SYS_MEM_ADDR + MCU_SYS_MEM_SIZE - sec->size))
142 return 0;
143 else if ((ap_dst_offset >= 0xfff8e000) &&
144 (ap_dst_offset < 0xfff91c00 - sec->size))
145 return 0;
146
147 ERROR("%s: mcu destination address invalid.\n", __func__);
148 ERROR("%s: number=%d, dst offset=%d size=%d\n",
149 __func__, sec->serial, sec->dst_offset, sec->size);
150 return 1;
151 }
152
hisi_mcu_enable_sram(void)153 void hisi_mcu_enable_sram(void)
154 {
155 mmio_write_32(AO_SC_PERIPH_CLKEN4,
156 AO_SC_PERIPH_CLKEN4_HCLK_IPC_S |
157 AO_SC_PERIPH_CLKEN4_HCLK_IPC_NS);
158
159 /* set register to enable dvfs which is used by mcu */
160 mmio_write_32(PERI_SC_RESERVED8_ADDR, 0x0A001022);
161
162 /* mcu mem is powered on, need de-assert reset */
163 mmio_write_32(AO_SC_PERIPH_RSTDIS4,
164 AO_SC_PERIPH_RSTDIS4_RESET_MCU_ECTR_N);
165
166 /* enable mcu hclk */
167 mmio_write_32(AO_SC_PERIPH_CLKEN4,
168 AO_SC_PERIPH_CLKEN4_HCLK_MCU |
169 AO_SC_PERIPH_CLKEN4_CLK_MCU_DAP);
170 }
171
hisi_mcu_start_run(void)172 void hisi_mcu_start_run(void)
173 {
174 unsigned int val;
175
176 #if 0
177 /* set mcu's self loop instruction 0xE7FE at entry point */
178 val = mmio_read_32((SOC_SRAM_M3_BASE_ADDR + 0x200));
179 val &= 0xFFFF0000;
180 val |= 0xE7FE;
181 mmio_write_32((SOC_SRAM_M3_BASE_ADDR + 0x200), val);
182 #endif
183
184 /* set mcu ddr remap configuration */
185 mmio_write_32(AO_SC_MCU_SUBSYS_CTRL2, MCU_SYS_MEM_ADDR);
186
187 /* de-assert reset for mcu and to run */
188 mmio_write_32(AO_SC_PERIPH_RSTDIS4,
189 AO_SC_PERIPH_RSTDIS4_RESET_MCU_ECTR_N |
190 AO_SC_PERIPH_RSTDIS4_RESET_MCU_SYS_N |
191 AO_SC_PERIPH_RSTDIS4_RESET_MCU_POR_N |
192 AO_SC_PERIPH_RSTDIS4_RESET_MCU_DAP_N);
193
194 val = mmio_read_32(AO_SC_SYS_CTRL2);
195 mmio_write_32(AO_SC_SYS_CTRL2,
196 val | AO_SC_SYS_CTRL2_GLB_SRST_STAT_CLEAR);
197
198 INFO("%s: AO_SC_SYS_CTRL2=%x\n", __func__,
199 mmio_read_32(AO_SC_SYS_CTRL2));
200 }
201
hisi_mcu_load_image(uintptr_t image_base,uint32_t image_size)202 int hisi_mcu_load_image(uintptr_t image_base, uint32_t image_size)
203 {
204 unsigned int i;
205 struct mcu_image_head *head;
206 char *buf;
207
208 head = (struct mcu_image_head *)image_base;
209 if (is_binary_header_invalid(head, image_size)) {
210 ERROR("Invalid %s image header.\n", head->time_stamp);
211 return -1;
212 }
213
214 buf = (char *)head;
215 for (i = 0; i < head->secs_num; i++) {
216
217 int *src, *dst;
218
219 /* check the sections */
220 if (is_binary_section_invalid(&head->secs[i], head)) {
221 ERROR("Invalid mcu section.\n");
222 return -1;
223 }
224
225 /* check if the section is static-loaded */
226 if (head->secs[i].load_attr != MCU_IMAGE_SEC_LOAD_STATIC)
227 continue;
228
229 /* copy the sections */
230 src = (int *)(intptr_t)(buf + head->secs[i].src_offset);
231 dst = (int *)(intptr_t)mcu2ap_addr(head->secs[i].dst_offset);
232
233 memcpy((void *)dst, (void *)src, head->secs[i].size);
234
235 INFO("%s: mcu sections %d:\n", __func__, i);
236 INFO("%s: src = 0x%x\n", __func__, src);
237 INFO("%s: dst = 0x%x\n", __func__, dst);
238 INFO("%s: size = %d\n", __func__, head->secs[i].size);
239
240 INFO("%s: [SRC 0x%x] 0x%x 0x%x 0x%x 0x%x\n", __func__,
241 src, src[0], src[1], src[2], src[3]);
242 INFO("%s: [DST 0x%x] 0x%x 0x%x 0x%x 0x%x\n", __func__,
243 dst, dst[0], dst[1], dst[2], dst[3]);
244 }
245
246 return 0;
247 }
248