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