xref: /optee_os/core/drivers/bnxt/bnxt.c (revision 9b726349837101194057972c7c6348ed3298c1d5)
195bec10aSVikas Gupta // SPDX-License-Identifier: BSD-2-Clause
295bec10aSVikas Gupta /*
395bec10aSVikas Gupta  * Copyright 2019 Broadcom.
495bec10aSVikas Gupta  */
595bec10aSVikas Gupta 
695bec10aSVikas Gupta #include <drivers/bcm/bnxt.h>
795bec10aSVikas Gupta #include <initcall.h>
895bec10aSVikas Gupta #include <io.h>
995bec10aSVikas Gupta #include <kernel/delay.h>
1095bec10aSVikas Gupta #include <stdint.h>
1195bec10aSVikas Gupta #include <stdlib.h>
1295bec10aSVikas Gupta #include <string.h>
1395bec10aSVikas Gupta 
1495bec10aSVikas Gupta #define BNXT_REG_CTRL_BASE			0x3040000
1595bec10aSVikas Gupta #define BNXT_REG_ECO_RESERVED			0x3042400
1695bec10aSVikas Gupta #define BNXT_FLASH_ACCESS_DONE_BIT		2
1795bec10aSVikas Gupta #define NIC400_BNXT_IDM_IO_CONTROL_DIRECT	0x60e00408
1895bec10aSVikas Gupta #define BNXT_INDIRECT_BASE			0x60800000
1995bec10aSVikas Gupta #define BNXT_INDIRECT_ADDR_MASK			0x3fffffu
2095bec10aSVikas Gupta #define BNXT_INDIRECT_BASE_MASK			(~BNXT_INDIRECT_ADDR_MASK)
2195bec10aSVikas Gupta #define BNXT_INDIRECT_WINDOW_SIZE		(BNXT_INDIRECT_ADDR_MASK + 1)
2295bec10aSVikas Gupta #define BNXT_REG_CTRL_BPE_MODE_REG		0x0
2395bec10aSVikas Gupta #define BNXT_REG_CTRL_BPE_MODE_FASTBOOT_MODE_BIT	2
2495bec10aSVikas Gupta #define BNXT_REG_CTRL_BPE_MODE_CM3_RST_BIT	1
2595bec10aSVikas Gupta #define BNXT_REG_CTRL_BPE_STAT_REG		0x4
2695bec10aSVikas Gupta #define BNXT_REG_CTRL_FSTBOOT_PTR_REG		0x8
2795bec10aSVikas Gupta #define BNXT_ERROR_MASK				0xf0000000
2895bec10aSVikas Gupta #define BNXT_CTRL_ADDR(x)			(BNXT_REG_CTRL_BASE + (x))
29*9b726349SSheetal Tigadoli #define BNXT_HANDSHAKE_TIMEOUT_MS		1000
3095bec10aSVikas Gupta 
3195bec10aSVikas Gupta #define KONG_REG_CTRL_MODE_REG			0x03900000
3295bec10aSVikas Gupta #define KONG_REG_CTRL_MODE_CPUHALT_N_BIT	0
3395bec10aSVikas Gupta 
3495bec10aSVikas Gupta #define BNXT_STICKY_BYTE_POR			0x04030088
3595bec10aSVikas Gupta #define BNXT_STICKY_BYTE_POR_MHB_BIT		4
3695bec10aSVikas Gupta 
37*9b726349SSheetal Tigadoli #define BNXT_HEALTH_CHECK_REG			0x03100008
38*9b726349SSheetal Tigadoli 
39*9b726349SSheetal Tigadoli enum bnxt_handshake_sts {
40*9b726349SSheetal Tigadoli 	BNXT_HANDSHAKE_SUCCESS = 0,
41*9b726349SSheetal Tigadoli 	BNXT_HANDSHAKE_WAIT_ERROR,
42*9b726349SSheetal Tigadoli 	BNXT_HANDSHAKE_WAIT_TIMEOUT
43*9b726349SSheetal Tigadoli };
44*9b726349SSheetal Tigadoli 
4595bec10aSVikas Gupta static vaddr_t bnxt_access_window_virt_addr;
4695bec10aSVikas Gupta static vaddr_t bnxt_indirect_dest_addr;
4795bec10aSVikas Gupta 
4895bec10aSVikas Gupta static void bnxt_prepare_access_window(uint32_t addr)
4995bec10aSVikas Gupta {
5095bec10aSVikas Gupta 	addr &= BNXT_INDIRECT_BASE_MASK;
5195bec10aSVikas Gupta 	io_write32(bnxt_access_window_virt_addr, addr);
5295bec10aSVikas Gupta }
5395bec10aSVikas Gupta 
5495bec10aSVikas Gupta static vaddr_t bnxt_indirect_tgt_addr(uint32_t addr)
5595bec10aSVikas Gupta {
5695bec10aSVikas Gupta 	addr &= BNXT_INDIRECT_ADDR_MASK;
5795bec10aSVikas Gupta 	return (vaddr_t)(bnxt_indirect_dest_addr + addr);
5895bec10aSVikas Gupta }
5995bec10aSVikas Gupta 
6095bec10aSVikas Gupta uint32_t bnxt_write32_multiple(uintptr_t dst,
6195bec10aSVikas Gupta 			       uintptr_t src,
6295bec10aSVikas Gupta 			       uint32_t num_entries,
6395bec10aSVikas Gupta 			       int src_4byte_increment)
6495bec10aSVikas Gupta {
6595bec10aSVikas Gupta 	uint32_t i = 0;
6695bec10aSVikas Gupta 	vaddr_t target = 0;
6795bec10aSVikas Gupta 
6895bec10aSVikas Gupta 	if (num_entries == 0)
6995bec10aSVikas Gupta 		return 0;
7095bec10aSVikas Gupta 
7195bec10aSVikas Gupta 	/* Only write up to the next window boundary */
7295bec10aSVikas Gupta 	if ((dst & BNXT_INDIRECT_BASE_MASK) !=
7395bec10aSVikas Gupta 	    ((dst + num_entries * sizeof(uint32_t)) & BNXT_INDIRECT_BASE_MASK))
7495bec10aSVikas Gupta 		num_entries = (((dst + BNXT_INDIRECT_WINDOW_SIZE) &
7595bec10aSVikas Gupta 				BNXT_INDIRECT_BASE_MASK) -
7695bec10aSVikas Gupta 			       dst) /
7795bec10aSVikas Gupta 			      sizeof(uint32_t);
7895bec10aSVikas Gupta 
7995bec10aSVikas Gupta 	bnxt_prepare_access_window(dst);
8095bec10aSVikas Gupta 	target = bnxt_indirect_tgt_addr(dst);
8195bec10aSVikas Gupta 	for (i = 0; i < num_entries; i++) {
8295bec10aSVikas Gupta 		io_write32(target, *(uint32_t *)src);
8395bec10aSVikas Gupta 		target += sizeof(uint32_t);
8495bec10aSVikas Gupta 		if (src_4byte_increment)
8595bec10aSVikas Gupta 			src += sizeof(uint32_t);
8695bec10aSVikas Gupta 	}
8795bec10aSVikas Gupta 
8895bec10aSVikas Gupta 	return num_entries;
8995bec10aSVikas Gupta }
9095bec10aSVikas Gupta 
9195bec10aSVikas Gupta static uint32_t bnxt_read(uint32_t addr)
9295bec10aSVikas Gupta {
9395bec10aSVikas Gupta 	bnxt_prepare_access_window(addr);
9495bec10aSVikas Gupta 	return io_read32(bnxt_indirect_tgt_addr(addr));
9595bec10aSVikas Gupta }
9695bec10aSVikas Gupta 
9795bec10aSVikas Gupta static uint32_t bnxt_read_ctrl(uint32_t offset)
9895bec10aSVikas Gupta {
9995bec10aSVikas Gupta 	return bnxt_read(BNXT_CTRL_ADDR(offset));
10095bec10aSVikas Gupta }
10195bec10aSVikas Gupta 
10295bec10aSVikas Gupta static void bnxt_write(uint32_t addr, uint32_t value)
10395bec10aSVikas Gupta {
10495bec10aSVikas Gupta 	bnxt_prepare_access_window(addr);
10595bec10aSVikas Gupta 	io_write32(bnxt_indirect_tgt_addr(addr), value);
10695bec10aSVikas Gupta }
10795bec10aSVikas Gupta 
10895bec10aSVikas Gupta static void bnxt_write_ctrl(uint32_t offset, uint32_t value)
10995bec10aSVikas Gupta {
11095bec10aSVikas Gupta 	bnxt_write(BNXT_CTRL_ADDR(offset), value);
11195bec10aSVikas Gupta }
11295bec10aSVikas Gupta 
113*9b726349SSheetal Tigadoli void bnxt_handshake_clear(void)
114*9b726349SSheetal Tigadoli {
115*9b726349SSheetal Tigadoli 	uint32_t value = bnxt_read(BNXT_REG_ECO_RESERVED);
116*9b726349SSheetal Tigadoli 
117*9b726349SSheetal Tigadoli 	value = value & ~BIT(BNXT_FLASH_ACCESS_DONE_BIT);
118*9b726349SSheetal Tigadoli 	bnxt_write(BNXT_REG_ECO_RESERVED, value);
119*9b726349SSheetal Tigadoli }
120*9b726349SSheetal Tigadoli 
12195bec10aSVikas Gupta static int bnxt_handshake_done(void)
12295bec10aSVikas Gupta {
12395bec10aSVikas Gupta 	uint32_t value = 0;
12495bec10aSVikas Gupta 
12595bec10aSVikas Gupta 	value = bnxt_read(BNXT_REG_ECO_RESERVED);
12695bec10aSVikas Gupta 	value &= BIT(BNXT_FLASH_ACCESS_DONE_BIT);
12795bec10aSVikas Gupta 
12895bec10aSVikas Gupta 	return value != 0;
12995bec10aSVikas Gupta }
13095bec10aSVikas Gupta 
131*9b726349SSheetal Tigadoli uint32_t bnxt_wait_handshake(uint32_t max_timeout)
13295bec10aSVikas Gupta {
133*9b726349SSheetal Tigadoli 	int ret = 0;
13495bec10aSVikas Gupta 	uint32_t status = 0;
135*9b726349SSheetal Tigadoli 	uint32_t timeout = 0;
136*9b726349SSheetal Tigadoli 
137*9b726349SSheetal Tigadoli 	/* If no timeout given we go with max timeout */
138*9b726349SSheetal Tigadoli 	if (max_timeout == 0)
139*9b726349SSheetal Tigadoli 		max_timeout = BNXT_HANDSHAKE_TIMEOUT_MS;
140*9b726349SSheetal Tigadoli 
141*9b726349SSheetal Tigadoli 	timeout = max_timeout;
14295bec10aSVikas Gupta 
14395bec10aSVikas Gupta 	DMSG("Waiting for ChiMP handshake...");
14495bec10aSVikas Gupta 	do {
145*9b726349SSheetal Tigadoli 		if (bnxt_handshake_done()) {
146*9b726349SSheetal Tigadoli 			ret = BNXT_HANDSHAKE_SUCCESS;
14795bec10aSVikas Gupta 			break;
148*9b726349SSheetal Tigadoli 		}
14995bec10aSVikas Gupta 		/* No need to wait if ChiMP reported an error */
15095bec10aSVikas Gupta 		status = bnxt_read_ctrl(BNXT_REG_CTRL_BPE_STAT_REG);
15195bec10aSVikas Gupta 		if (status & BNXT_ERROR_MASK) {
152*9b726349SSheetal Tigadoli 			EMSG("ChiMP error 0x%x. Wait aborted", status);
153*9b726349SSheetal Tigadoli 			ret = BNXT_HANDSHAKE_WAIT_ERROR;
15495bec10aSVikas Gupta 			break;
15595bec10aSVikas Gupta 		}
15695bec10aSVikas Gupta 		mdelay(1);
15795bec10aSVikas Gupta 	} while (--timeout);
15895bec10aSVikas Gupta 
15995bec10aSVikas Gupta 	if (!bnxt_handshake_done()) {
160*9b726349SSheetal Tigadoli 		if (timeout == 0) {
161*9b726349SSheetal Tigadoli 			ret = BNXT_HANDSHAKE_WAIT_TIMEOUT;
162*9b726349SSheetal Tigadoli 			EMSG("Timeout waiting for ChiMP handshake");
16395bec10aSVikas Gupta 		}
164*9b726349SSheetal Tigadoli 	} else {
165*9b726349SSheetal Tigadoli 		ret = BNXT_HANDSHAKE_SUCCESS;
166*9b726349SSheetal Tigadoli 		DMSG("ChiMP handshake successful");
167*9b726349SSheetal Tigadoli 	}
168*9b726349SSheetal Tigadoli 
169*9b726349SSheetal Tigadoli 	return ret;
17095bec10aSVikas Gupta }
17195bec10aSVikas Gupta 
17295bec10aSVikas Gupta void bnxt_chimp_halt(void)
17395bec10aSVikas Gupta {
17495bec10aSVikas Gupta 	uint32_t value = 0;
17595bec10aSVikas Gupta 
17695bec10aSVikas Gupta 	value = bnxt_read_ctrl(BNXT_REG_CTRL_BPE_MODE_REG);
17795bec10aSVikas Gupta 	value |= BIT(BNXT_REG_CTRL_BPE_MODE_CM3_RST_BIT);
17895bec10aSVikas Gupta 	bnxt_write_ctrl(BNXT_REG_CTRL_BPE_MODE_REG, value);
17995bec10aSVikas Gupta }
18095bec10aSVikas Gupta 
18195bec10aSVikas Gupta void bnxt_kong_halt(void)
18295bec10aSVikas Gupta {
18395bec10aSVikas Gupta 	uint32_t value = 0;
18495bec10aSVikas Gupta 
18595bec10aSVikas Gupta 	value = bnxt_read(KONG_REG_CTRL_MODE_REG);
18695bec10aSVikas Gupta 	value &= ~BIT(KONG_REG_CTRL_MODE_CPUHALT_N_BIT);
18795bec10aSVikas Gupta 	bnxt_write(KONG_REG_CTRL_MODE_REG, value);
18895bec10aSVikas Gupta }
18995bec10aSVikas Gupta 
19095bec10aSVikas Gupta int bnxt_fastboot(uintptr_t addr)
19195bec10aSVikas Gupta {
19295bec10aSVikas Gupta 	uint32_t value = 0;
19395bec10aSVikas Gupta 
19495bec10aSVikas Gupta 	value = bnxt_read(BNXT_STICKY_BYTE_POR);
19595bec10aSVikas Gupta 	value |= BIT(BNXT_STICKY_BYTE_POR_MHB_BIT);
19695bec10aSVikas Gupta 	bnxt_write(BNXT_STICKY_BYTE_POR, value);
19795bec10aSVikas Gupta 
19895bec10aSVikas Gupta 	/* Set the fastboot address and type */
19995bec10aSVikas Gupta 	bnxt_write_ctrl(BNXT_REG_CTRL_FSTBOOT_PTR_REG, addr);
20095bec10aSVikas Gupta 
20195bec10aSVikas Gupta 	/* Set fastboot mode & take BNXT CPU1 out of reset */
20295bec10aSVikas Gupta 	value = bnxt_read_ctrl(BNXT_REG_CTRL_BPE_MODE_REG);
20395bec10aSVikas Gupta 	value |= BIT(BNXT_REG_CTRL_BPE_MODE_FASTBOOT_MODE_BIT);
20495bec10aSVikas Gupta 	value &= ~BIT(BNXT_REG_CTRL_BPE_MODE_CM3_RST_BIT);
20595bec10aSVikas Gupta 	bnxt_write_ctrl(BNXT_REG_CTRL_BPE_MODE_REG, value);
20695bec10aSVikas Gupta 
20795bec10aSVikas Gupta 	return 0;
20895bec10aSVikas Gupta }
20995bec10aSVikas Gupta 
210*9b726349SSheetal Tigadoli uint32_t bnxt_health_status(void)
211*9b726349SSheetal Tigadoli {
212*9b726349SSheetal Tigadoli 	return bnxt_read(BNXT_HEALTH_CHECK_REG);
213*9b726349SSheetal Tigadoli }
214*9b726349SSheetal Tigadoli 
21595bec10aSVikas Gupta static TEE_Result bnxt_init(void)
21695bec10aSVikas Gupta {
21795bec10aSVikas Gupta 	bnxt_access_window_virt_addr =
21895bec10aSVikas Gupta 		(vaddr_t)phys_to_virt(NIC400_BNXT_IDM_IO_CONTROL_DIRECT,
21995bec10aSVikas Gupta 				      MEM_AREA_IO_SEC);
22095bec10aSVikas Gupta 	bnxt_indirect_dest_addr =
22195bec10aSVikas Gupta 		(vaddr_t)phys_to_virt(BNXT_INDIRECT_BASE,
22295bec10aSVikas Gupta 				      MEM_AREA_IO_SEC);
22395bec10aSVikas Gupta 	return TEE_SUCCESS;
22495bec10aSVikas Gupta }
22595bec10aSVikas Gupta driver_init(bnxt_init);
226