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