195bec10aSVikas Gupta // SPDX-License-Identifier: BSD-2-Clause 295bec10aSVikas Gupta /* 395bec10aSVikas Gupta * Copyright 2019 Broadcom. 495bec10aSVikas Gupta */ 595bec10aSVikas Gupta 695bec10aSVikas Gupta #include <drivers/bcm/bnxt.h> 795bec10aSVikas Gupta #include <initcall.h> 895bec10aSVikas Gupta #include <io.h> 995bec10aSVikas Gupta #include <kernel/delay.h> 1095bec10aSVikas Gupta #include <stdint.h> 1195bec10aSVikas Gupta #include <stdlib.h> 1295bec10aSVikas Gupta #include <string.h> 1395bec10aSVikas Gupta 1495bec10aSVikas Gupta #define BNXT_REG_CTRL_BASE 0x3040000 1595bec10aSVikas Gupta #define BNXT_REG_ECO_RESERVED 0x3042400 1695bec10aSVikas Gupta #define BNXT_FLASH_ACCESS_DONE_BIT 2 1795bec10aSVikas Gupta #define NIC400_BNXT_IDM_IO_CONTROL_DIRECT 0x60e00408 1895bec10aSVikas Gupta #define BNXT_INDIRECT_BASE 0x60800000 1995bec10aSVikas Gupta #define BNXT_INDIRECT_ADDR_MASK 0x3fffffu 2095bec10aSVikas Gupta #define BNXT_INDIRECT_BASE_MASK (~BNXT_INDIRECT_ADDR_MASK) 2195bec10aSVikas Gupta #define BNXT_INDIRECT_WINDOW_SIZE (BNXT_INDIRECT_ADDR_MASK + 1) 2295bec10aSVikas Gupta #define BNXT_REG_CTRL_BPE_MODE_REG 0x0 2395bec10aSVikas Gupta #define BNXT_REG_CTRL_BPE_MODE_FASTBOOT_MODE_BIT 2 2495bec10aSVikas Gupta #define BNXT_REG_CTRL_BPE_MODE_CM3_RST_BIT 1 2595bec10aSVikas Gupta #define BNXT_REG_CTRL_BPE_STAT_REG 0x4 2695bec10aSVikas Gupta #define BNXT_REG_CTRL_FSTBOOT_PTR_REG 0x8 2795bec10aSVikas Gupta #define BNXT_ERROR_MASK 0xf0000000 2895bec10aSVikas Gupta #define BNXT_CTRL_ADDR(x) (BNXT_REG_CTRL_BASE + (x)) 29*9b726349SSheetal Tigadoli #define BNXT_HANDSHAKE_TIMEOUT_MS 1000 3095bec10aSVikas Gupta 3195bec10aSVikas Gupta #define KONG_REG_CTRL_MODE_REG 0x03900000 3295bec10aSVikas Gupta #define KONG_REG_CTRL_MODE_CPUHALT_N_BIT 0 3395bec10aSVikas Gupta 3495bec10aSVikas Gupta #define BNXT_STICKY_BYTE_POR 0x04030088 3595bec10aSVikas Gupta #define BNXT_STICKY_BYTE_POR_MHB_BIT 4 3695bec10aSVikas Gupta 37*9b726349SSheetal Tigadoli #define BNXT_HEALTH_CHECK_REG 0x03100008 38*9b726349SSheetal Tigadoli 39*9b726349SSheetal Tigadoli enum bnxt_handshake_sts { 40*9b726349SSheetal Tigadoli BNXT_HANDSHAKE_SUCCESS = 0, 41*9b726349SSheetal Tigadoli BNXT_HANDSHAKE_WAIT_ERROR, 42*9b726349SSheetal Tigadoli BNXT_HANDSHAKE_WAIT_TIMEOUT 43*9b726349SSheetal Tigadoli }; 44*9b726349SSheetal Tigadoli 4595bec10aSVikas Gupta static vaddr_t bnxt_access_window_virt_addr; 4695bec10aSVikas Gupta static vaddr_t bnxt_indirect_dest_addr; 4795bec10aSVikas Gupta 4895bec10aSVikas Gupta static void bnxt_prepare_access_window(uint32_t addr) 4995bec10aSVikas Gupta { 5095bec10aSVikas Gupta addr &= BNXT_INDIRECT_BASE_MASK; 5195bec10aSVikas Gupta io_write32(bnxt_access_window_virt_addr, addr); 5295bec10aSVikas Gupta } 5395bec10aSVikas Gupta 5495bec10aSVikas Gupta static vaddr_t bnxt_indirect_tgt_addr(uint32_t addr) 5595bec10aSVikas Gupta { 5695bec10aSVikas Gupta addr &= BNXT_INDIRECT_ADDR_MASK; 5795bec10aSVikas Gupta return (vaddr_t)(bnxt_indirect_dest_addr + addr); 5895bec10aSVikas Gupta } 5995bec10aSVikas Gupta 6095bec10aSVikas Gupta uint32_t bnxt_write32_multiple(uintptr_t dst, 6195bec10aSVikas Gupta uintptr_t src, 6295bec10aSVikas Gupta uint32_t num_entries, 6395bec10aSVikas Gupta int src_4byte_increment) 6495bec10aSVikas Gupta { 6595bec10aSVikas Gupta uint32_t i = 0; 6695bec10aSVikas Gupta vaddr_t target = 0; 6795bec10aSVikas Gupta 6895bec10aSVikas Gupta if (num_entries == 0) 6995bec10aSVikas Gupta return 0; 7095bec10aSVikas Gupta 7195bec10aSVikas Gupta /* Only write up to the next window boundary */ 7295bec10aSVikas Gupta if ((dst & BNXT_INDIRECT_BASE_MASK) != 7395bec10aSVikas Gupta ((dst + num_entries * sizeof(uint32_t)) & BNXT_INDIRECT_BASE_MASK)) 7495bec10aSVikas Gupta num_entries = (((dst + BNXT_INDIRECT_WINDOW_SIZE) & 7595bec10aSVikas Gupta BNXT_INDIRECT_BASE_MASK) - 7695bec10aSVikas Gupta dst) / 7795bec10aSVikas Gupta sizeof(uint32_t); 7895bec10aSVikas Gupta 7995bec10aSVikas Gupta bnxt_prepare_access_window(dst); 8095bec10aSVikas Gupta target = bnxt_indirect_tgt_addr(dst); 8195bec10aSVikas Gupta for (i = 0; i < num_entries; i++) { 8295bec10aSVikas Gupta io_write32(target, *(uint32_t *)src); 8395bec10aSVikas Gupta target += sizeof(uint32_t); 8495bec10aSVikas Gupta if (src_4byte_increment) 8595bec10aSVikas Gupta src += sizeof(uint32_t); 8695bec10aSVikas Gupta } 8795bec10aSVikas Gupta 8895bec10aSVikas Gupta return num_entries; 8995bec10aSVikas Gupta } 9095bec10aSVikas Gupta 9195bec10aSVikas Gupta static uint32_t bnxt_read(uint32_t addr) 9295bec10aSVikas Gupta { 9395bec10aSVikas Gupta bnxt_prepare_access_window(addr); 9495bec10aSVikas Gupta return io_read32(bnxt_indirect_tgt_addr(addr)); 9595bec10aSVikas Gupta } 9695bec10aSVikas Gupta 9795bec10aSVikas Gupta static uint32_t bnxt_read_ctrl(uint32_t offset) 9895bec10aSVikas Gupta { 9995bec10aSVikas Gupta return bnxt_read(BNXT_CTRL_ADDR(offset)); 10095bec10aSVikas Gupta } 10195bec10aSVikas Gupta 10295bec10aSVikas Gupta static void bnxt_write(uint32_t addr, uint32_t value) 10395bec10aSVikas Gupta { 10495bec10aSVikas Gupta bnxt_prepare_access_window(addr); 10595bec10aSVikas Gupta io_write32(bnxt_indirect_tgt_addr(addr), value); 10695bec10aSVikas Gupta } 10795bec10aSVikas Gupta 10895bec10aSVikas Gupta static void bnxt_write_ctrl(uint32_t offset, uint32_t value) 10995bec10aSVikas Gupta { 11095bec10aSVikas Gupta bnxt_write(BNXT_CTRL_ADDR(offset), value); 11195bec10aSVikas Gupta } 11295bec10aSVikas Gupta 113*9b726349SSheetal Tigadoli void bnxt_handshake_clear(void) 114*9b726349SSheetal Tigadoli { 115*9b726349SSheetal Tigadoli uint32_t value = bnxt_read(BNXT_REG_ECO_RESERVED); 116*9b726349SSheetal Tigadoli 117*9b726349SSheetal Tigadoli value = value & ~BIT(BNXT_FLASH_ACCESS_DONE_BIT); 118*9b726349SSheetal Tigadoli bnxt_write(BNXT_REG_ECO_RESERVED, value); 119*9b726349SSheetal Tigadoli } 120*9b726349SSheetal Tigadoli 12195bec10aSVikas Gupta static int bnxt_handshake_done(void) 12295bec10aSVikas Gupta { 12395bec10aSVikas Gupta uint32_t value = 0; 12495bec10aSVikas Gupta 12595bec10aSVikas Gupta value = bnxt_read(BNXT_REG_ECO_RESERVED); 12695bec10aSVikas Gupta value &= BIT(BNXT_FLASH_ACCESS_DONE_BIT); 12795bec10aSVikas Gupta 12895bec10aSVikas Gupta return value != 0; 12995bec10aSVikas Gupta } 13095bec10aSVikas Gupta 131*9b726349SSheetal Tigadoli uint32_t bnxt_wait_handshake(uint32_t max_timeout) 13295bec10aSVikas Gupta { 133*9b726349SSheetal Tigadoli int ret = 0; 13495bec10aSVikas Gupta uint32_t status = 0; 135*9b726349SSheetal Tigadoli uint32_t timeout = 0; 136*9b726349SSheetal Tigadoli 137*9b726349SSheetal Tigadoli /* If no timeout given we go with max timeout */ 138*9b726349SSheetal Tigadoli if (max_timeout == 0) 139*9b726349SSheetal Tigadoli max_timeout = BNXT_HANDSHAKE_TIMEOUT_MS; 140*9b726349SSheetal Tigadoli 141*9b726349SSheetal Tigadoli timeout = max_timeout; 14295bec10aSVikas Gupta 14395bec10aSVikas Gupta DMSG("Waiting for ChiMP handshake..."); 14495bec10aSVikas Gupta do { 145*9b726349SSheetal Tigadoli if (bnxt_handshake_done()) { 146*9b726349SSheetal Tigadoli ret = BNXT_HANDSHAKE_SUCCESS; 14795bec10aSVikas Gupta break; 148*9b726349SSheetal Tigadoli } 14995bec10aSVikas Gupta /* No need to wait if ChiMP reported an error */ 15095bec10aSVikas Gupta status = bnxt_read_ctrl(BNXT_REG_CTRL_BPE_STAT_REG); 15195bec10aSVikas Gupta if (status & BNXT_ERROR_MASK) { 152*9b726349SSheetal Tigadoli EMSG("ChiMP error 0x%x. Wait aborted", status); 153*9b726349SSheetal Tigadoli ret = BNXT_HANDSHAKE_WAIT_ERROR; 15495bec10aSVikas Gupta break; 15595bec10aSVikas Gupta } 15695bec10aSVikas Gupta mdelay(1); 15795bec10aSVikas Gupta } while (--timeout); 15895bec10aSVikas Gupta 15995bec10aSVikas Gupta if (!bnxt_handshake_done()) { 160*9b726349SSheetal Tigadoli if (timeout == 0) { 161*9b726349SSheetal Tigadoli ret = BNXT_HANDSHAKE_WAIT_TIMEOUT; 162*9b726349SSheetal Tigadoli EMSG("Timeout waiting for ChiMP handshake"); 16395bec10aSVikas Gupta } 164*9b726349SSheetal Tigadoli } else { 165*9b726349SSheetal Tigadoli ret = BNXT_HANDSHAKE_SUCCESS; 166*9b726349SSheetal Tigadoli DMSG("ChiMP handshake successful"); 167*9b726349SSheetal Tigadoli } 168*9b726349SSheetal Tigadoli 169*9b726349SSheetal Tigadoli return ret; 17095bec10aSVikas Gupta } 17195bec10aSVikas Gupta 17295bec10aSVikas Gupta void bnxt_chimp_halt(void) 17395bec10aSVikas Gupta { 17495bec10aSVikas Gupta uint32_t value = 0; 17595bec10aSVikas Gupta 17695bec10aSVikas Gupta value = bnxt_read_ctrl(BNXT_REG_CTRL_BPE_MODE_REG); 17795bec10aSVikas Gupta value |= BIT(BNXT_REG_CTRL_BPE_MODE_CM3_RST_BIT); 17895bec10aSVikas Gupta bnxt_write_ctrl(BNXT_REG_CTRL_BPE_MODE_REG, value); 17995bec10aSVikas Gupta } 18095bec10aSVikas Gupta 18195bec10aSVikas Gupta void bnxt_kong_halt(void) 18295bec10aSVikas Gupta { 18395bec10aSVikas Gupta uint32_t value = 0; 18495bec10aSVikas Gupta 18595bec10aSVikas Gupta value = bnxt_read(KONG_REG_CTRL_MODE_REG); 18695bec10aSVikas Gupta value &= ~BIT(KONG_REG_CTRL_MODE_CPUHALT_N_BIT); 18795bec10aSVikas Gupta bnxt_write(KONG_REG_CTRL_MODE_REG, value); 18895bec10aSVikas Gupta } 18995bec10aSVikas Gupta 19095bec10aSVikas Gupta int bnxt_fastboot(uintptr_t addr) 19195bec10aSVikas Gupta { 19295bec10aSVikas Gupta uint32_t value = 0; 19395bec10aSVikas Gupta 19495bec10aSVikas Gupta value = bnxt_read(BNXT_STICKY_BYTE_POR); 19595bec10aSVikas Gupta value |= BIT(BNXT_STICKY_BYTE_POR_MHB_BIT); 19695bec10aSVikas Gupta bnxt_write(BNXT_STICKY_BYTE_POR, value); 19795bec10aSVikas Gupta 19895bec10aSVikas Gupta /* Set the fastboot address and type */ 19995bec10aSVikas Gupta bnxt_write_ctrl(BNXT_REG_CTRL_FSTBOOT_PTR_REG, addr); 20095bec10aSVikas Gupta 20195bec10aSVikas Gupta /* Set fastboot mode & take BNXT CPU1 out of reset */ 20295bec10aSVikas Gupta value = bnxt_read_ctrl(BNXT_REG_CTRL_BPE_MODE_REG); 20395bec10aSVikas Gupta value |= BIT(BNXT_REG_CTRL_BPE_MODE_FASTBOOT_MODE_BIT); 20495bec10aSVikas Gupta value &= ~BIT(BNXT_REG_CTRL_BPE_MODE_CM3_RST_BIT); 20595bec10aSVikas Gupta bnxt_write_ctrl(BNXT_REG_CTRL_BPE_MODE_REG, value); 20695bec10aSVikas Gupta 20795bec10aSVikas Gupta return 0; 20895bec10aSVikas Gupta } 20995bec10aSVikas Gupta 210*9b726349SSheetal Tigadoli uint32_t bnxt_health_status(void) 211*9b726349SSheetal Tigadoli { 212*9b726349SSheetal Tigadoli return bnxt_read(BNXT_HEALTH_CHECK_REG); 213*9b726349SSheetal Tigadoli } 214*9b726349SSheetal Tigadoli 21595bec10aSVikas Gupta static TEE_Result bnxt_init(void) 21695bec10aSVikas Gupta { 21795bec10aSVikas Gupta bnxt_access_window_virt_addr = 21895bec10aSVikas Gupta (vaddr_t)phys_to_virt(NIC400_BNXT_IDM_IO_CONTROL_DIRECT, 21995bec10aSVikas Gupta MEM_AREA_IO_SEC); 22095bec10aSVikas Gupta bnxt_indirect_dest_addr = 22195bec10aSVikas Gupta (vaddr_t)phys_to_virt(BNXT_INDIRECT_BASE, 22295bec10aSVikas Gupta MEM_AREA_IO_SEC); 22395bec10aSVikas Gupta return TEE_SUCCESS; 22495bec10aSVikas Gupta } 22595bec10aSVikas Gupta driver_init(bnxt_init); 226