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