xref: /optee_os/core/drivers/bnxt/bnxt.c (revision 0d77037f5943c86560dd7c8f473fbc6a55d60a34)
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		10000
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 static vaddr_t bnxt_access_window_virt_addr;
38 static vaddr_t bnxt_indirect_dest_addr;
39 
40 static void bnxt_prepare_access_window(uint32_t addr)
41 {
42 	addr &= BNXT_INDIRECT_BASE_MASK;
43 	io_write32(bnxt_access_window_virt_addr, addr);
44 }
45 
46 static vaddr_t bnxt_indirect_tgt_addr(uint32_t addr)
47 {
48 	addr &= BNXT_INDIRECT_ADDR_MASK;
49 	return (vaddr_t)(bnxt_indirect_dest_addr + addr);
50 }
51 
52 uint32_t bnxt_write32_multiple(uintptr_t dst,
53 			       uintptr_t src,
54 			       uint32_t num_entries,
55 			       int src_4byte_increment)
56 {
57 	uint32_t i = 0;
58 	vaddr_t target = 0;
59 
60 	if (num_entries == 0)
61 		return 0;
62 
63 	/* Only write up to the next window boundary */
64 	if ((dst & BNXT_INDIRECT_BASE_MASK) !=
65 	    ((dst + num_entries * sizeof(uint32_t)) & BNXT_INDIRECT_BASE_MASK))
66 		num_entries = (((dst + BNXT_INDIRECT_WINDOW_SIZE) &
67 				BNXT_INDIRECT_BASE_MASK) -
68 			       dst) /
69 			      sizeof(uint32_t);
70 
71 	bnxt_prepare_access_window(dst);
72 	target = bnxt_indirect_tgt_addr(dst);
73 	for (i = 0; i < num_entries; i++) {
74 		io_write32(target, *(uint32_t *)src);
75 		target += sizeof(uint32_t);
76 		if (src_4byte_increment)
77 			src += sizeof(uint32_t);
78 	}
79 
80 	return num_entries;
81 }
82 
83 static uint32_t bnxt_read(uint32_t addr)
84 {
85 	bnxt_prepare_access_window(addr);
86 	return io_read32(bnxt_indirect_tgt_addr(addr));
87 }
88 
89 static uint32_t bnxt_read_ctrl(uint32_t offset)
90 {
91 	return bnxt_read(BNXT_CTRL_ADDR(offset));
92 }
93 
94 static void bnxt_write(uint32_t addr, uint32_t value)
95 {
96 	bnxt_prepare_access_window(addr);
97 	io_write32(bnxt_indirect_tgt_addr(addr), value);
98 }
99 
100 static void bnxt_write_ctrl(uint32_t offset, uint32_t value)
101 {
102 	bnxt_write(BNXT_CTRL_ADDR(offset), value);
103 }
104 
105 static int bnxt_handshake_done(void)
106 {
107 	uint32_t value = 0;
108 
109 	value = bnxt_read(BNXT_REG_ECO_RESERVED);
110 	value &= BIT(BNXT_FLASH_ACCESS_DONE_BIT);
111 
112 	return value != 0;
113 }
114 
115 int bnxt_wait_handshake(void)
116 {
117 	uint32_t timeout = BNXT_HANDSHAKE_TIMEOUT_MS;
118 	uint32_t status = 0;
119 
120 	DMSG("Waiting for ChiMP handshake...");
121 	do {
122 		if (bnxt_handshake_done())
123 			break;
124 		/* No need to wait if ChiMP reported an error */
125 		status = bnxt_read_ctrl(BNXT_REG_CTRL_BPE_STAT_REG);
126 		if (status & BNXT_ERROR_MASK) {
127 			DMSG("ChiMP error 0x%x. Wait aborted", status);
128 			break;
129 		}
130 		mdelay(1);
131 	} while (--timeout);
132 
133 	if (!bnxt_handshake_done()) {
134 		if (timeout == 0)
135 			DMSG("Timeout waiting for ChiMP handshake");
136 	} else {
137 		DMSG("Got handshake from ChiMP!");
138 	}
139 	return bnxt_handshake_done();
140 }
141 
142 void bnxt_chimp_halt(void)
143 {
144 	uint32_t value = 0;
145 
146 	value = bnxt_read_ctrl(BNXT_REG_CTRL_BPE_MODE_REG);
147 	value |= BIT(BNXT_REG_CTRL_BPE_MODE_CM3_RST_BIT);
148 	bnxt_write_ctrl(BNXT_REG_CTRL_BPE_MODE_REG, value);
149 }
150 
151 void bnxt_kong_halt(void)
152 {
153 	uint32_t value = 0;
154 
155 	value = bnxt_read(KONG_REG_CTRL_MODE_REG);
156 	value &= ~BIT(KONG_REG_CTRL_MODE_CPUHALT_N_BIT);
157 	bnxt_write(KONG_REG_CTRL_MODE_REG, value);
158 }
159 
160 int bnxt_fastboot(uintptr_t addr)
161 {
162 	uint32_t value = 0;
163 
164 	value = bnxt_read(BNXT_STICKY_BYTE_POR);
165 	value |= BIT(BNXT_STICKY_BYTE_POR_MHB_BIT);
166 	bnxt_write(BNXT_STICKY_BYTE_POR, value);
167 
168 	/* Set the fastboot address and type */
169 	bnxt_write_ctrl(BNXT_REG_CTRL_FSTBOOT_PTR_REG, addr);
170 
171 	/* Set fastboot mode & take BNXT CPU1 out of reset */
172 	value = bnxt_read_ctrl(BNXT_REG_CTRL_BPE_MODE_REG);
173 	value |= BIT(BNXT_REG_CTRL_BPE_MODE_FASTBOOT_MODE_BIT);
174 	value &= ~BIT(BNXT_REG_CTRL_BPE_MODE_CM3_RST_BIT);
175 	bnxt_write_ctrl(BNXT_REG_CTRL_BPE_MODE_REG, value);
176 
177 	return 0;
178 }
179 
180 static TEE_Result bnxt_init(void)
181 {
182 	bnxt_access_window_virt_addr =
183 		(vaddr_t)phys_to_virt(NIC400_BNXT_IDM_IO_CONTROL_DIRECT,
184 				      MEM_AREA_IO_SEC);
185 	bnxt_indirect_dest_addr =
186 		(vaddr_t)phys_to_virt(BNXT_INDIRECT_BASE,
187 				      MEM_AREA_IO_SEC);
188 	return TEE_SUCCESS;
189 }
190 driver_init(bnxt_init);
191