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 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 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 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 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 97 static uint32_t bnxt_read_ctrl(uint32_t offset) 98 { 99 return bnxt_read(BNXT_CTRL_ADDR(offset)); 100 } 101 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 108 static void bnxt_write_ctrl(uint32_t offset, uint32_t value) 109 { 110 bnxt_write(BNXT_CTRL_ADDR(offset), value); 111 } 112 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 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 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 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 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 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 210 uint32_t bnxt_health_status(void) 211 { 212 return bnxt_read(BNXT_HEALTH_CHECK_REG); 213 } 214 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