1 /*
2  * Copyright (c) 2016 - 2020, Broadcom
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include <string.h>
8 
9 #include <drivers/delay_timer.h>
10 
11 #include <chimp.h>
12 #include <chimp_nv_defs.h>
13 
14 #define CHIMP_DEFAULT_STARTUP_ADDR 0xb4300000
15 
16 /* ChiMP's view of APE scratchpad memory for fastboot */
17 #define CHIMP_FASTBOOT_ADDR 0x61000000
18 
19 #define CHIMP_PREPARE_ACCESS_WINDOW(addr) \
20 	(\
21 		mmio_write_32(\
22 			NIC400_NITRO_CHIMP_S_IDM_IO_CONTROL_DIRECT, \
23 			addr & 0xffc00000)\
24 	)
25 #define CHIMP_INDIRECT_TGT_ADDR(addr) \
26 	(CHIMP_INDIRECT_BASE + (addr & CHIMP_INDIRECT_ADDR_MASK))
27 
28 #define CHIMP_CTRL_ADDR(x) (CHIMP_REG_CTRL_BASE + x)
29 
30 /* For non-PAXC builds */
31 #ifndef CHIMP_FB1_ENTRY
32 #define CHIMP_FB1_ENTRY 0
33 #endif
34 
35 #define CHIMP_DBG	VERBOSE
36 
bcm_chimp_write(uintptr_t addr,uint32_t value)37 void bcm_chimp_write(uintptr_t addr, uint32_t value)
38 {
39 	CHIMP_PREPARE_ACCESS_WINDOW(addr);
40 	mmio_write_32(CHIMP_INDIRECT_TGT_ADDR(addr), value);
41 }
42 
bcm_chimp_read(uintptr_t addr)43 uint32_t bcm_chimp_read(uintptr_t addr)
44 {
45 	CHIMP_PREPARE_ACCESS_WINDOW(addr);
46 	return mmio_read_32(CHIMP_INDIRECT_TGT_ADDR(addr));
47 }
48 
bcm_chimp_clrbits(uintptr_t addr,uint32_t bits)49 void bcm_chimp_clrbits(uintptr_t addr, uint32_t bits)
50 {
51 	CHIMP_PREPARE_ACCESS_WINDOW(addr);
52 	mmio_clrbits_32(CHIMP_INDIRECT_TGT_ADDR(addr), bits);
53 }
54 
bcm_chimp_setbits(uintptr_t addr,uint32_t bits)55 void bcm_chimp_setbits(uintptr_t addr, uint32_t bits)
56 {
57 	CHIMP_PREPARE_ACCESS_WINDOW(addr);
58 	mmio_setbits_32(CHIMP_INDIRECT_TGT_ADDR(addr), bits);
59 }
60 
bcm_chimp_is_nic_mode(void)61 int bcm_chimp_is_nic_mode(void)
62 {
63 	uint32_t val;
64 
65 	/* Check if ChiMP straps are set */
66 	val = mmio_read_32(CDRU_CHIP_STRAP_DATA_LSW);
67 	val &= CDRU_CHIP_STRAP_DATA_LSW__NIC_MODE_MASK;
68 
69 	return val == CDRU_CHIP_STRAP_DATA_LSW__NIC_MODE_MASK;
70 }
71 
bcm_chimp_fru_prog_done(bool is_done)72 void bcm_chimp_fru_prog_done(bool is_done)
73 {
74 	uint32_t val;
75 
76 	val = is_done ? (1 << CHIMP_FRU_PROG_DONE_BIT) : 0;
77 	bcm_chimp_setbits(CHIMP_REG_ECO_RESERVED, val);
78 }
79 
bcm_chimp_handshake_done(void)80 int bcm_chimp_handshake_done(void)
81 {
82 	uint32_t value;
83 
84 	value = bcm_chimp_read(CHIMP_REG_ECO_RESERVED);
85 	value &= (1 << CHIMP_FLASH_ACCESS_DONE_BIT);
86 
87 	return value != 0;
88 }
89 
bcm_chimp_wait_handshake(void)90 int bcm_chimp_wait_handshake(void)
91 {
92 	uint32_t timeout = CHIMP_HANDSHAKE_TIMEOUT_MS;
93 	uint32_t status;
94 
95 	INFO("Waiting for ChiMP handshake...\n");
96 	do {
97 		if (bcm_chimp_handshake_done())
98 			break;
99 		/* No need to wait if ChiMP reported an error */
100 		status = bcm_chimp_read_ctrl(CHIMP_REG_CTRL_BPE_STAT_REG);
101 		if (status & CHIMP_ERROR_MASK) {
102 			ERROR("ChiMP error 0x%x. Wait aborted\n", status);
103 			break;
104 		}
105 		mdelay(1);
106 	} while (--timeout);
107 
108 	if (!bcm_chimp_handshake_done()) {
109 		if (timeout == 0) {
110 			WARN("Timeout waiting for ChiMP handshake\n");
111 		}
112 	} else {
113 		INFO("Got handshake from ChiMP!\n");
114 	}
115 
116 	return bcm_chimp_handshake_done();
117 }
118 
bcm_chimp_read_ctrl(uint32_t offset)119 uint32_t bcm_chimp_read_ctrl(uint32_t offset)
120 {
121 	return bcm_chimp_read(CHIMP_CTRL_ADDR(offset));
122 }
123 
bcm_chimp_nitro_reset(void)124 static int bcm_chimp_nitro_reset(void)
125 {
126 	uint32_t timeout;
127 
128 	/* Perform tasks done by M0 in NIC mode */
129 	CHIMP_DBG("Taking Nitro out of reset\n");
130 	mmio_setbits_32(CDRU_MISC_RESET_CONTROL,
131 		/* MHB_RESET_N */
132 		(1 << CDRU_MISC_RESET_CONTROL__CDRU_MHB_RESET_N_R)  |
133 		/* PCI_RESET_N */
134 		(1 << CDRU_MISC_RESET_CONTROL__CDRU_PCIE_RESET_N_R) |
135 		/* PM_RESET_N */
136 		(1 << CDRU_MISC_RESET_CONTROL__CDRU_PM_RESET_N_R)   |
137 		/* NIC_RESET_N */
138 		(1 << CDRU_MISC_RESET_CONTROL__CDRU_NITRO_RESET_N_R)
139 	);
140 
141 	/* Wait until Nitro is out of reset */
142 	timeout = NIC_RESET_RELEASE_TIMEOUT_US;
143 	do {
144 		uint32_t value;
145 
146 		value = bcm_chimp_read_ctrl(CHIMP_REG_CTRL_BPE_MODE_REG);
147 		if ((value & CHIMP_BPE_MODE_ID_MASK) ==
148 				CHIMP_BPE_MODE_ID_PATTERN)
149 			break;
150 		udelay(1);
151 	} while (--timeout);
152 
153 	if (timeout == 0) {
154 		ERROR("NIC reset release timed out\n");
155 		return -1;
156 	}
157 
158 	return 0;
159 }
160 
bcm_nitro_secure_mode_enable(void)161 static void bcm_nitro_secure_mode_enable(void)
162 {
163 	mmio_setbits_32(CDRU_NITRO_CONTROL,
164 		(1 << CDRU_NITRO_CONTROL__CDRU_NITRO_SEC_MODE_R) |
165 		(1 << CDRU_NITRO_CONTROL__CDRU_NITRO_SEC_OVERRIDE_R));
166 	mmio_write_32(NITRO_TZPC_TZPCDECPROT0clr,
167 		/* NITRO_TZPC */
168 		1 << NITRO_TZPC_TZPCDECPROT0clr__DECPROT0_chimp_m_clr_R);
169 }
170 
bcm_chimp_reset_and_initial_setup(void)171 static int bcm_chimp_reset_and_initial_setup(void)
172 {
173 
174 	int err;
175 	uint32_t handshake_reg;
176 
177 	err = bcm_chimp_nitro_reset();
178 	if (err)
179 		return err;
180 
181 	/* Enable Nitro secure mode */
182 	bcm_nitro_secure_mode_enable();
183 
184 	/* Force ChiMP back into reset */
185 	bcm_chimp_setbits(CHIMP_CTRL_ADDR(CHIMP_REG_CTRL_BPE_MODE_REG),
186 		1 << CHIMP_REG_CHIMP_REG_CTRL_BPE_MODE_REG__cm3_rst_R);
187 
188 	handshake_reg = (1 << SR_IN_SMARTNIC_MODE_BIT);
189 
190 	/* Get OTP secure Chimp boot status */
191 	if (mmio_read_32(CRMU_OTP_STATUS) & (1 << CRMU_OTP_STATUS_BIT))
192 		handshake_reg |= (1 << SR_CHIMP_SECURE_BOOT_BIT);
193 
194 	bcm_chimp_write(CHIMP_REG_ECO_RESERVED, handshake_reg);
195 
196 	CHIMP_DBG("ChiMP reset and initial handshake parameters set\n");
197 
198 	return 0;
199 }
200 
bcm_nitro_chimp_release_reset(void)201 static void bcm_nitro_chimp_release_reset(void)
202 {
203 	bcm_chimp_clrbits(CHIMP_CTRL_ADDR(CHIMP_REG_CTRL_BPE_MODE_REG),
204 		1 << CHIMP_REG_CHIMP_REG_CTRL_BPE_MODE_REG__cm3_rst_R);
205 
206 	CHIMP_DBG("Nitro Reset Released\n");
207 }
208 
bcm_chimp_set_fastboot(int mode)209 static void bcm_chimp_set_fastboot(int mode)
210 {
211 	uint32_t fb_entry;
212 
213 	/* 1. Enable fastboot */
214 	bcm_chimp_setbits(CHIMP_CTRL_ADDR(CHIMP_REG_CTRL_BPE_MODE_REG),
215 			(1 << CHIMP_FAST_BOOT_MODE_BIT));
216 	fb_entry = CHIMP_FASTBOOT_ADDR | mode;
217 	if (mode == CHIMP_FASTBOOT_JUMP_IN_PLACE)
218 		fb_entry = CHIMP_FB1_ENTRY;
219 	/* 2. Write startup address and mode */
220 	INFO("Setting fastboot type %d entry to 0x%x\n", mode, fb_entry);
221 	bcm_chimp_write(
222 			CHIMP_CTRL_ADDR(CHIMP_REG_CTRL_FSTBOOT_PTR_REG),
223 			fb_entry);
224 }
225 
226 #ifndef CHIMPFW_USE_SIDELOAD
bcm_chimp_load_fw_from_spi(uintptr_t spi_addr,size_t size)227 static void bcm_chimp_load_fw_from_spi(uintptr_t spi_addr, size_t size)
228 {
229 	uintptr_t ape_scpad;
230 	uintptr_t dest;
231 	size_t bytes_left;
232 
233 	ape_scpad = CHIMP_REG_CHIMP_APE_SCPAD;
234 	dest = CHIMP_INDIRECT_TGT_ADDR(CHIMP_REG_CHIMP_APE_SCPAD);
235 	bytes_left = size;
236 
237 	while (bytes_left) {
238 		uint32_t delta;
239 
240 		delta = bytes_left > CHIMP_WINDOW_SIZE ?
241 			bytes_left - CHIMP_WINDOW_SIZE : bytes_left;
242 		CHIMP_PREPARE_ACCESS_WINDOW(ape_scpad);
243 		INFO("Transferring %d byte(s) from 0x%lx to 0x%lx\n",
244 			delta, spi_addr, dest);
245 	/*
246 	 * This single memcpy call takes significant amount of time
247 	 * on Palladium. Be patient
248 	 */
249 		memcpy((void *)dest, (void *)spi_addr, delta);
250 		bytes_left -= delta;
251 		INFO("Transferred %d byte(s) from 0x%lx to 0x%lx (%lu%%)\n",
252 			delta, spi_addr, dest,
253 			((size - bytes_left) * 100)/size);
254 		spi_addr += delta;
255 		dest += delta;
256 		ape_scpad += delta;
257 	}
258 }
259 
bcm_chimp_find_fw_in_spi(uintptr_t * addr,size_t * size)260 static int bcm_chimp_find_fw_in_spi(uintptr_t *addr, size_t *size)
261 {
262 	int i;
263 	bnxnvm_master_block_header_t *master_block_hdr;
264 	bnxnvm_directory_block_header_t *dir_block_hdr;
265 	bnxnvm_directory_entry_t *dir_entry;
266 	int found;
267 
268 	found = 0;
269 
270 	/* Read the master block */
271 	master_block_hdr =
272 		(bnxnvm_master_block_header_t *)(uintptr_t)QSPI_BASE_ADDR;
273 	if (master_block_hdr->sig != BNXNVM_MASTER_BLOCK_SIG) {
274 		WARN("Invalid masterblock 0x%x (expected 0x%x)\n",
275 			master_block_hdr->sig,
276 			BNXNVM_MASTER_BLOCK_SIG);
277 		return -NV_NOT_NVRAM;
278 	}
279 	if ((master_block_hdr->block_size > NV_MAX_BLOCK_SIZE) ||
280 		(master_block_hdr->directory_offset >=
281 			master_block_hdr->nvram_size)) {
282 		WARN("Invalid masterblock block size 0x%x or directory offset 0x%x\n",
283 			master_block_hdr->block_size,
284 			master_block_hdr->directory_offset);
285 		return -NV_BAD_MB;
286 	}
287 
288 	/* Skip to the Directory block start */
289 	dir_block_hdr =
290 		(bnxnvm_directory_block_header_t *)
291 			((uintptr_t)QSPI_BASE_ADDR +
292 				master_block_hdr->directory_offset);
293 	if (dir_block_hdr->sig != BNXNVM_DIRECTORY_BLOCK_SIG) {
294 		WARN("Invalid directory header 0x%x (expected 0x%x)\n",
295 			dir_block_hdr->sig,
296 			BNXNVM_DIRECTORY_BLOCK_SIG);
297 		return -NV_BAD_DIR_HEADER;
298 	}
299 
300 	/* Locate the firmware */
301 	for (i = 0; i < dir_block_hdr->entries; i++) {
302 		*addr = ((uintptr_t)dir_block_hdr + dir_block_hdr->length +
303 			i * dir_block_hdr->entry_length);
304 		dir_entry = (bnxnvm_directory_entry_t *)(*addr);
305 		if ((dir_entry->type == BNX_DIR_TYPE_BOOTCODE) ||
306 				(dir_entry->type == BNX_DIR_TYPE_BOOTCODE_2)) {
307 			found = 1;
308 			break;
309 		}
310 	}
311 
312 	if (!found)
313 		return -NV_FW_NOT_FOUND;
314 
315 	*addr = QSPI_BASE_ADDR + dir_entry->item_location;
316 	*size = dir_entry->data_length;
317 
318 	INFO("Found chimp firmware at 0x%lx, size %lu byte(s)\n",
319 			*addr, *size);
320 
321 	return NV_OK;
322 }
323 #endif
324 
bcm_chimp_initiate_fastboot(int fastboot_type)325 int bcm_chimp_initiate_fastboot(int fastboot_type)
326 {
327 	int err;
328 
329 	if ((fastboot_type != CHIMP_FASTBOOT_NITRO_RESET) &&
330 			(fastboot_type <= CHIMP_FASTBOOT_JUMP_DECOMPRESS)) {
331 		CHIMP_DBG("Initiating ChiMP fastboot type %d\n", fastboot_type);
332 	}
333 
334 	/*
335 	 * If we are here, M0 did not setup Nitro because NIC mode
336 	 * strap was not present
337 	 */
338 	err = bcm_chimp_reset_and_initial_setup();
339 	if (err)
340 		return err;
341 
342 	if (fastboot_type > CHIMP_FASTBOOT_JUMP_DECOMPRESS) {
343 		WARN("ChiMP setup deferred\n");
344 		return -1;
345 	}
346 
347 	if (fastboot_type != CHIMP_FASTBOOT_NITRO_RESET) {
348 
349 		if ((fastboot_type == CHIMP_FASTBOOT_JUMP_IN_PLACE) &&
350 			(CHIMP_FB1_ENTRY == 0)) {
351 			ERROR("Missing ESAL entry point for fastboot type 1.\n"
352 			"Fastboot failed\n");
353 			return -1;
354 		}
355 
356 		/*
357 		 * TODO: We need to think of the way to load the ChiMP fw.
358 		 * This could be SPI, NAND, etc.
359 		 * For now we temporarily stick to the SPI load unless
360 		 * CHIMPFW_USE_SIDELOAD is defined. Note that for the SPI NVRAM
361 		 * image we need to parse directory and get the image.
362 		 * When we load image from other media there is no need to
363 		 * parse because fw image can be directly placed into the APE's
364 		 * scratchpad.
365 		 * For sideload method we simply reset the ChiMP, set bpe_reg
366 		 * to do fastboot with the type we define, and release from
367 		 * reset so that ROM loader would initiate fastboot immediately
368 		 */
369 #ifndef CHIMPFW_USE_SIDELOAD
370 		{
371 			uintptr_t spi_addr;
372 			size_t size;
373 
374 			err = bcm_chimp_find_fw_in_spi(&spi_addr, &size);
375 			if (!err) {
376 				INFO("Loading ChiMP firmware, addr 0x%lx, size %lu byte(s)\n",
377 					spi_addr, size);
378 				bcm_chimp_load_fw_from_spi(spi_addr, size);
379 			} else {
380 				ERROR("Error %d ChiMP firmware not in NVRAM directory!\n",
381 					err);
382 			}
383 		}
384 #else
385 		INFO("Skip ChiMP QSPI fastboot type %d due to sideload requested\n",
386 		     fastboot_type);
387 #endif
388 		if (!err) {
389 			INFO("Instruct ChiMP to fastboot\n");
390 			bcm_chimp_set_fastboot(fastboot_type);
391 			INFO("Fastboot mode set\n");
392 		}
393 	}
394 
395 	bcm_nitro_chimp_release_reset();
396 
397 	return err;
398 }
399