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 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 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 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 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 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 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