xref: /optee_os/core/drivers/bnxt/bnxt.c (revision 95bec10a7d4de4bf8d7cb6c535b80ec76f2b3c94)
1*95bec10aSVikas Gupta // SPDX-License-Identifier: BSD-2-Clause
2*95bec10aSVikas Gupta /*
3*95bec10aSVikas Gupta  * Copyright 2019 Broadcom.
4*95bec10aSVikas Gupta  */
5*95bec10aSVikas Gupta 
6*95bec10aSVikas Gupta #include <drivers/bcm/bnxt.h>
7*95bec10aSVikas Gupta #include <initcall.h>
8*95bec10aSVikas Gupta #include <io.h>
9*95bec10aSVikas Gupta #include <kernel/delay.h>
10*95bec10aSVikas Gupta #include <stdint.h>
11*95bec10aSVikas Gupta #include <stdlib.h>
12*95bec10aSVikas Gupta #include <string.h>
13*95bec10aSVikas Gupta 
14*95bec10aSVikas Gupta #define BNXT_REG_CTRL_BASE			0x3040000
15*95bec10aSVikas Gupta #define BNXT_REG_ECO_RESERVED			0x3042400
16*95bec10aSVikas Gupta #define BNXT_FLASH_ACCESS_DONE_BIT		2
17*95bec10aSVikas Gupta #define NIC400_BNXT_IDM_IO_CONTROL_DIRECT	0x60e00408
18*95bec10aSVikas Gupta #define BNXT_INDIRECT_BASE			0x60800000
19*95bec10aSVikas Gupta #define BNXT_INDIRECT_ADDR_MASK			0x3fffffu
20*95bec10aSVikas Gupta #define BNXT_INDIRECT_BASE_MASK			(~BNXT_INDIRECT_ADDR_MASK)
21*95bec10aSVikas Gupta #define BNXT_INDIRECT_WINDOW_SIZE		(BNXT_INDIRECT_ADDR_MASK + 1)
22*95bec10aSVikas Gupta #define BNXT_REG_CTRL_BPE_MODE_REG		0x0
23*95bec10aSVikas Gupta #define BNXT_REG_CTRL_BPE_MODE_FASTBOOT_MODE_BIT	2
24*95bec10aSVikas Gupta #define BNXT_REG_CTRL_BPE_MODE_CM3_RST_BIT	1
25*95bec10aSVikas Gupta #define BNXT_REG_CTRL_BPE_STAT_REG		0x4
26*95bec10aSVikas Gupta #define BNXT_REG_CTRL_FSTBOOT_PTR_REG		0x8
27*95bec10aSVikas Gupta #define BNXT_ERROR_MASK				0xf0000000
28*95bec10aSVikas Gupta #define BNXT_CTRL_ADDR(x)			(BNXT_REG_CTRL_BASE + (x))
29*95bec10aSVikas Gupta #define BNXT_HANDSHAKE_TIMEOUT_MS		10000
30*95bec10aSVikas Gupta 
31*95bec10aSVikas Gupta #define KONG_REG_CTRL_MODE_REG			0x03900000
32*95bec10aSVikas Gupta #define KONG_REG_CTRL_MODE_CPUHALT_N_BIT	0
33*95bec10aSVikas Gupta 
34*95bec10aSVikas Gupta #define BNXT_STICKY_BYTE_POR			0x04030088
35*95bec10aSVikas Gupta #define BNXT_STICKY_BYTE_POR_MHB_BIT		4
36*95bec10aSVikas Gupta 
37*95bec10aSVikas Gupta static vaddr_t bnxt_access_window_virt_addr;
38*95bec10aSVikas Gupta static vaddr_t bnxt_indirect_dest_addr;
39*95bec10aSVikas Gupta 
40*95bec10aSVikas Gupta static void bnxt_prepare_access_window(uint32_t addr)
41*95bec10aSVikas Gupta {
42*95bec10aSVikas Gupta 	addr &= BNXT_INDIRECT_BASE_MASK;
43*95bec10aSVikas Gupta 	io_write32(bnxt_access_window_virt_addr, addr);
44*95bec10aSVikas Gupta }
45*95bec10aSVikas Gupta 
46*95bec10aSVikas Gupta static vaddr_t bnxt_indirect_tgt_addr(uint32_t addr)
47*95bec10aSVikas Gupta {
48*95bec10aSVikas Gupta 	addr &= BNXT_INDIRECT_ADDR_MASK;
49*95bec10aSVikas Gupta 	return (vaddr_t)(bnxt_indirect_dest_addr + addr);
50*95bec10aSVikas Gupta }
51*95bec10aSVikas Gupta 
52*95bec10aSVikas Gupta uint32_t bnxt_write32_multiple(uintptr_t dst,
53*95bec10aSVikas Gupta 			       uintptr_t src,
54*95bec10aSVikas Gupta 			       uint32_t num_entries,
55*95bec10aSVikas Gupta 			       int src_4byte_increment)
56*95bec10aSVikas Gupta {
57*95bec10aSVikas Gupta 	uint32_t i = 0;
58*95bec10aSVikas Gupta 	vaddr_t target = 0;
59*95bec10aSVikas Gupta 
60*95bec10aSVikas Gupta 	if (num_entries == 0)
61*95bec10aSVikas Gupta 		return 0;
62*95bec10aSVikas Gupta 
63*95bec10aSVikas Gupta 	/* Only write up to the next window boundary */
64*95bec10aSVikas Gupta 	if ((dst & BNXT_INDIRECT_BASE_MASK) !=
65*95bec10aSVikas Gupta 	    ((dst + num_entries * sizeof(uint32_t)) & BNXT_INDIRECT_BASE_MASK))
66*95bec10aSVikas Gupta 		num_entries = (((dst + BNXT_INDIRECT_WINDOW_SIZE) &
67*95bec10aSVikas Gupta 				BNXT_INDIRECT_BASE_MASK) -
68*95bec10aSVikas Gupta 			       dst) /
69*95bec10aSVikas Gupta 			      sizeof(uint32_t);
70*95bec10aSVikas Gupta 
71*95bec10aSVikas Gupta 	bnxt_prepare_access_window(dst);
72*95bec10aSVikas Gupta 	target = bnxt_indirect_tgt_addr(dst);
73*95bec10aSVikas Gupta 	for (i = 0; i < num_entries; i++) {
74*95bec10aSVikas Gupta 		io_write32(target, *(uint32_t *)src);
75*95bec10aSVikas Gupta 		target += sizeof(uint32_t);
76*95bec10aSVikas Gupta 		if (src_4byte_increment)
77*95bec10aSVikas Gupta 			src += sizeof(uint32_t);
78*95bec10aSVikas Gupta 	}
79*95bec10aSVikas Gupta 
80*95bec10aSVikas Gupta 	return num_entries;
81*95bec10aSVikas Gupta }
82*95bec10aSVikas Gupta 
83*95bec10aSVikas Gupta static uint32_t bnxt_read(uint32_t addr)
84*95bec10aSVikas Gupta {
85*95bec10aSVikas Gupta 	bnxt_prepare_access_window(addr);
86*95bec10aSVikas Gupta 	return io_read32(bnxt_indirect_tgt_addr(addr));
87*95bec10aSVikas Gupta }
88*95bec10aSVikas Gupta 
89*95bec10aSVikas Gupta static uint32_t bnxt_read_ctrl(uint32_t offset)
90*95bec10aSVikas Gupta {
91*95bec10aSVikas Gupta 	return bnxt_read(BNXT_CTRL_ADDR(offset));
92*95bec10aSVikas Gupta }
93*95bec10aSVikas Gupta 
94*95bec10aSVikas Gupta static void bnxt_write(uint32_t addr, uint32_t value)
95*95bec10aSVikas Gupta {
96*95bec10aSVikas Gupta 	bnxt_prepare_access_window(addr);
97*95bec10aSVikas Gupta 	io_write32(bnxt_indirect_tgt_addr(addr), value);
98*95bec10aSVikas Gupta }
99*95bec10aSVikas Gupta 
100*95bec10aSVikas Gupta static void bnxt_write_ctrl(uint32_t offset, uint32_t value)
101*95bec10aSVikas Gupta {
102*95bec10aSVikas Gupta 	bnxt_write(BNXT_CTRL_ADDR(offset), value);
103*95bec10aSVikas Gupta }
104*95bec10aSVikas Gupta 
105*95bec10aSVikas Gupta static int bnxt_handshake_done(void)
106*95bec10aSVikas Gupta {
107*95bec10aSVikas Gupta 	uint32_t value = 0;
108*95bec10aSVikas Gupta 
109*95bec10aSVikas Gupta 	value = bnxt_read(BNXT_REG_ECO_RESERVED);
110*95bec10aSVikas Gupta 	value &= BIT(BNXT_FLASH_ACCESS_DONE_BIT);
111*95bec10aSVikas Gupta 
112*95bec10aSVikas Gupta 	return value != 0;
113*95bec10aSVikas Gupta }
114*95bec10aSVikas Gupta 
115*95bec10aSVikas Gupta int bnxt_wait_handshake(void)
116*95bec10aSVikas Gupta {
117*95bec10aSVikas Gupta 	uint32_t timeout = BNXT_HANDSHAKE_TIMEOUT_MS;
118*95bec10aSVikas Gupta 	uint32_t status = 0;
119*95bec10aSVikas Gupta 
120*95bec10aSVikas Gupta 	DMSG("Waiting for ChiMP handshake...");
121*95bec10aSVikas Gupta 	do {
122*95bec10aSVikas Gupta 		if (bnxt_handshake_done())
123*95bec10aSVikas Gupta 			break;
124*95bec10aSVikas Gupta 		/* No need to wait if ChiMP reported an error */
125*95bec10aSVikas Gupta 		status = bnxt_read_ctrl(BNXT_REG_CTRL_BPE_STAT_REG);
126*95bec10aSVikas Gupta 		if (status & BNXT_ERROR_MASK) {
127*95bec10aSVikas Gupta 			DMSG("ChiMP error 0x%x. Wait aborted", status);
128*95bec10aSVikas Gupta 			break;
129*95bec10aSVikas Gupta 		}
130*95bec10aSVikas Gupta 		mdelay(1);
131*95bec10aSVikas Gupta 	} while (--timeout);
132*95bec10aSVikas Gupta 
133*95bec10aSVikas Gupta 	if (!bnxt_handshake_done()) {
134*95bec10aSVikas Gupta 		if (timeout == 0)
135*95bec10aSVikas Gupta 			DMSG("Timeout waiting for ChiMP handshake");
136*95bec10aSVikas Gupta 	} else {
137*95bec10aSVikas Gupta 		DMSG("Got handshake from ChiMP!");
138*95bec10aSVikas Gupta 	}
139*95bec10aSVikas Gupta 	return bnxt_handshake_done();
140*95bec10aSVikas Gupta }
141*95bec10aSVikas Gupta 
142*95bec10aSVikas Gupta void bnxt_chimp_halt(void)
143*95bec10aSVikas Gupta {
144*95bec10aSVikas Gupta 	uint32_t value = 0;
145*95bec10aSVikas Gupta 
146*95bec10aSVikas Gupta 	value = bnxt_read_ctrl(BNXT_REG_CTRL_BPE_MODE_REG);
147*95bec10aSVikas Gupta 	value |= BIT(BNXT_REG_CTRL_BPE_MODE_CM3_RST_BIT);
148*95bec10aSVikas Gupta 	bnxt_write_ctrl(BNXT_REG_CTRL_BPE_MODE_REG, value);
149*95bec10aSVikas Gupta }
150*95bec10aSVikas Gupta 
151*95bec10aSVikas Gupta void bnxt_kong_halt(void)
152*95bec10aSVikas Gupta {
153*95bec10aSVikas Gupta 	uint32_t value = 0;
154*95bec10aSVikas Gupta 
155*95bec10aSVikas Gupta 	value = bnxt_read(KONG_REG_CTRL_MODE_REG);
156*95bec10aSVikas Gupta 	value &= ~BIT(KONG_REG_CTRL_MODE_CPUHALT_N_BIT);
157*95bec10aSVikas Gupta 	bnxt_write(KONG_REG_CTRL_MODE_REG, value);
158*95bec10aSVikas Gupta }
159*95bec10aSVikas Gupta 
160*95bec10aSVikas Gupta int bnxt_fastboot(uintptr_t addr)
161*95bec10aSVikas Gupta {
162*95bec10aSVikas Gupta 	uint32_t value = 0;
163*95bec10aSVikas Gupta 
164*95bec10aSVikas Gupta 	value = bnxt_read(BNXT_STICKY_BYTE_POR);
165*95bec10aSVikas Gupta 	value |= BIT(BNXT_STICKY_BYTE_POR_MHB_BIT);
166*95bec10aSVikas Gupta 	bnxt_write(BNXT_STICKY_BYTE_POR, value);
167*95bec10aSVikas Gupta 
168*95bec10aSVikas Gupta 	/* Set the fastboot address and type */
169*95bec10aSVikas Gupta 	bnxt_write_ctrl(BNXT_REG_CTRL_FSTBOOT_PTR_REG, addr);
170*95bec10aSVikas Gupta 
171*95bec10aSVikas Gupta 	/* Set fastboot mode & take BNXT CPU1 out of reset */
172*95bec10aSVikas Gupta 	value = bnxt_read_ctrl(BNXT_REG_CTRL_BPE_MODE_REG);
173*95bec10aSVikas Gupta 	value |= BIT(BNXT_REG_CTRL_BPE_MODE_FASTBOOT_MODE_BIT);
174*95bec10aSVikas Gupta 	value &= ~BIT(BNXT_REG_CTRL_BPE_MODE_CM3_RST_BIT);
175*95bec10aSVikas Gupta 	bnxt_write_ctrl(BNXT_REG_CTRL_BPE_MODE_REG, value);
176*95bec10aSVikas Gupta 
177*95bec10aSVikas Gupta 	return 0;
178*95bec10aSVikas Gupta }
179*95bec10aSVikas Gupta 
180*95bec10aSVikas Gupta static TEE_Result bnxt_init(void)
181*95bec10aSVikas Gupta {
182*95bec10aSVikas Gupta 	bnxt_access_window_virt_addr =
183*95bec10aSVikas Gupta 		(vaddr_t)phys_to_virt(NIC400_BNXT_IDM_IO_CONTROL_DIRECT,
184*95bec10aSVikas Gupta 				      MEM_AREA_IO_SEC);
185*95bec10aSVikas Gupta 	bnxt_indirect_dest_addr =
186*95bec10aSVikas Gupta 		(vaddr_t)phys_to_virt(BNXT_INDIRECT_BASE,
187*95bec10aSVikas Gupta 				      MEM_AREA_IO_SEC);
188*95bec10aSVikas Gupta 	return TEE_SUCCESS;
189*95bec10aSVikas Gupta }
190*95bec10aSVikas Gupta driver_init(bnxt_init);
191