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