xref: /optee_os/core/drivers/bnxt/bnxt.c (revision c2e4eb43b7b7211345cd38ceceac97773bd78d2c)
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))
299b726349SSheetal 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 
379b726349SSheetal Tigadoli #define BNXT_HEALTH_CHECK_REG			0x03100008
389b726349SSheetal Tigadoli 
399b726349SSheetal Tigadoli enum bnxt_handshake_sts {
409b726349SSheetal Tigadoli 	BNXT_HANDSHAKE_SUCCESS = 0,
419b726349SSheetal Tigadoli 	BNXT_HANDSHAKE_WAIT_ERROR,
429b726349SSheetal Tigadoli 	BNXT_HANDSHAKE_WAIT_TIMEOUT
439b726349SSheetal Tigadoli };
449b726349SSheetal Tigadoli 
4595bec10aSVikas Gupta static vaddr_t bnxt_access_window_virt_addr;
4695bec10aSVikas Gupta static vaddr_t bnxt_indirect_dest_addr;
4795bec10aSVikas Gupta 
bnxt_prepare_access_window(uint32_t addr)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 
bnxt_indirect_tgt_addr(uint32_t addr)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 
bnxt_write32_multiple(uintptr_t dst,uintptr_t src,uint32_t num_entries,int src_4byte_increment)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 
bnxt_read(uint32_t addr)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 
bnxt_read_ctrl(uint32_t offset)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 
bnxt_write(uint32_t addr,uint32_t value)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 
bnxt_write_ctrl(uint32_t offset,uint32_t value)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 
bnxt_handshake_clear(void)1139b726349SSheetal Tigadoli void bnxt_handshake_clear(void)
1149b726349SSheetal Tigadoli {
1159b726349SSheetal Tigadoli 	uint32_t value = bnxt_read(BNXT_REG_ECO_RESERVED);
1169b726349SSheetal Tigadoli 
1179b726349SSheetal Tigadoli 	value = value & ~BIT(BNXT_FLASH_ACCESS_DONE_BIT);
1189b726349SSheetal Tigadoli 	bnxt_write(BNXT_REG_ECO_RESERVED, value);
1199b726349SSheetal Tigadoli }
1209b726349SSheetal Tigadoli 
bnxt_handshake_done(void)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 
bnxt_wait_handshake(uint32_t max_timeout)1319b726349SSheetal Tigadoli uint32_t bnxt_wait_handshake(uint32_t max_timeout)
13295bec10aSVikas Gupta {
1339b726349SSheetal Tigadoli 	int ret = 0;
13495bec10aSVikas Gupta 	uint32_t status = 0;
1359b726349SSheetal Tigadoli 	uint32_t timeout = 0;
1369b726349SSheetal Tigadoli 
1379b726349SSheetal Tigadoli 	/* If no timeout given we go with max timeout */
1389b726349SSheetal Tigadoli 	if (max_timeout == 0)
1399b726349SSheetal Tigadoli 		max_timeout = BNXT_HANDSHAKE_TIMEOUT_MS;
1409b726349SSheetal Tigadoli 
1419b726349SSheetal Tigadoli 	timeout = max_timeout;
14295bec10aSVikas Gupta 
14395bec10aSVikas Gupta 	DMSG("Waiting for ChiMP handshake...");
14495bec10aSVikas Gupta 	do {
1459b726349SSheetal Tigadoli 		if (bnxt_handshake_done()) {
1469b726349SSheetal Tigadoli 			ret = BNXT_HANDSHAKE_SUCCESS;
14795bec10aSVikas Gupta 			break;
1489b726349SSheetal 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) {
1529b726349SSheetal Tigadoli 			EMSG("ChiMP error 0x%x. Wait aborted", status);
1539b726349SSheetal 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()) {
1609b726349SSheetal Tigadoli 		if (timeout == 0) {
1619b726349SSheetal Tigadoli 			ret = BNXT_HANDSHAKE_WAIT_TIMEOUT;
1629b726349SSheetal Tigadoli 			EMSG("Timeout waiting for ChiMP handshake");
16395bec10aSVikas Gupta 		}
1649b726349SSheetal Tigadoli 	} else {
1659b726349SSheetal Tigadoli 		ret = BNXT_HANDSHAKE_SUCCESS;
1669b726349SSheetal Tigadoli 		DMSG("ChiMP handshake successful");
1679b726349SSheetal Tigadoli 	}
1689b726349SSheetal Tigadoli 
1699b726349SSheetal Tigadoli 	return ret;
17095bec10aSVikas Gupta }
17195bec10aSVikas Gupta 
bnxt_chimp_halt(void)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 
bnxt_kong_halt(void)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 
bnxt_fastboot(uintptr_t addr)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 
bnxt_health_status(void)2109b726349SSheetal Tigadoli uint32_t bnxt_health_status(void)
2119b726349SSheetal Tigadoli {
2129b726349SSheetal Tigadoli 	return bnxt_read(BNXT_HEALTH_CHECK_REG);
2139b726349SSheetal Tigadoli }
2149b726349SSheetal Tigadoli 
bnxt_init(void)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,
219*c2e4eb43SAnton Rybakov 				      MEM_AREA_IO_SEC, sizeof(uint32_t));
22095bec10aSVikas Gupta 	bnxt_indirect_dest_addr =
22195bec10aSVikas Gupta 		(vaddr_t)phys_to_virt(BNXT_INDIRECT_BASE,
222*c2e4eb43SAnton Rybakov 				      MEM_AREA_IO_SEC,
223*c2e4eb43SAnton Rybakov 				      BNXT_INDIRECT_WINDOW_SIZE);
22495bec10aSVikas Gupta 	return TEE_SUCCESS;
22595bec10aSVikas Gupta }
22695bec10aSVikas Gupta driver_init(bnxt_init);
227