1*91f16700Schasinglulu /* 2*91f16700Schasinglulu * Copyright (C) 2018 Marvell International Ltd. 3*91f16700Schasinglulu * 4*91f16700Schasinglulu * SPDX-License-Identifier: BSD-3-Clause 5*91f16700Schasinglulu * https://spdx.org/licenses 6*91f16700Schasinglulu */ 7*91f16700Schasinglulu 8*91f16700Schasinglulu #include <common/debug.h> 9*91f16700Schasinglulu #include <common/runtime_svc.h> 10*91f16700Schasinglulu #include <drivers/marvell/cache_llc.h> 11*91f16700Schasinglulu #include <drivers/marvell/mochi/ap_setup.h> 12*91f16700Schasinglulu #include <drivers/rambus/trng_ip_76.h> 13*91f16700Schasinglulu #include <lib/smccc.h> 14*91f16700Schasinglulu 15*91f16700Schasinglulu #include <marvell_plat_priv.h> 16*91f16700Schasinglulu #include <plat_marvell.h> 17*91f16700Schasinglulu 18*91f16700Schasinglulu #include "comphy/phy-comphy-cp110.h" 19*91f16700Schasinglulu #include "secure_dfx_access/dfx.h" 20*91f16700Schasinglulu #include "ddr_phy_access.h" 21*91f16700Schasinglulu #include <stdbool.h> 22*91f16700Schasinglulu 23*91f16700Schasinglulu /* #define DEBUG_COMPHY */ 24*91f16700Schasinglulu #ifdef DEBUG_COMPHY 25*91f16700Schasinglulu #define debug(format...) NOTICE(format) 26*91f16700Schasinglulu #else 27*91f16700Schasinglulu #define debug(format, arg...) 28*91f16700Schasinglulu #endif 29*91f16700Schasinglulu 30*91f16700Schasinglulu /* Comphy related FID's */ 31*91f16700Schasinglulu #define MV_SIP_COMPHY_POWER_ON 0x82000001 32*91f16700Schasinglulu #define MV_SIP_COMPHY_POWER_OFF 0x82000002 33*91f16700Schasinglulu #define MV_SIP_COMPHY_PLL_LOCK 0x82000003 34*91f16700Schasinglulu #define MV_SIP_COMPHY_XFI_TRAIN 0x82000004 35*91f16700Schasinglulu #define MV_SIP_COMPHY_DIG_RESET 0x82000005 36*91f16700Schasinglulu 37*91f16700Schasinglulu /* Miscellaneous FID's' */ 38*91f16700Schasinglulu #define MV_SIP_DRAM_SIZE 0x82000010 39*91f16700Schasinglulu #define MV_SIP_LLC_ENABLE 0x82000011 40*91f16700Schasinglulu #define MV_SIP_PMU_IRQ_ENABLE 0x82000012 41*91f16700Schasinglulu #define MV_SIP_PMU_IRQ_DISABLE 0x82000013 42*91f16700Schasinglulu #define MV_SIP_DFX 0x82000014 43*91f16700Schasinglulu #define MV_SIP_DDR_PHY_WRITE 0x82000015 44*91f16700Schasinglulu #define MV_SIP_DDR_PHY_READ 0x82000016 45*91f16700Schasinglulu 46*91f16700Schasinglulu /* TRNG */ 47*91f16700Schasinglulu #define MV_SIP_RNG_64 0xC200FF11 48*91f16700Schasinglulu 49*91f16700Schasinglulu #define MAX_LANE_NR 6 50*91f16700Schasinglulu #define MVEBU_COMPHY_OFFSET 0x441000 51*91f16700Schasinglulu #define MVEBU_CP_BASE_MASK (~0xffffff) 52*91f16700Schasinglulu 53*91f16700Schasinglulu /* Common PHY register */ 54*91f16700Schasinglulu #define COMPHY_TRX_TRAIN_CTRL_REG_0_OFFS 0x120a2c 55*91f16700Schasinglulu 56*91f16700Schasinglulu /* This macro is used to identify COMPHY related calls from SMC function ID */ 57*91f16700Schasinglulu #define is_comphy_fid(fid) \ 58*91f16700Schasinglulu ((fid) >= MV_SIP_COMPHY_POWER_ON && (fid) <= MV_SIP_COMPHY_DIG_RESET) 59*91f16700Schasinglulu 60*91f16700Schasinglulu _Bool is_cp_range_valid(u_register_t *addr) 61*91f16700Schasinglulu { 62*91f16700Schasinglulu int cp_nr; 63*91f16700Schasinglulu 64*91f16700Schasinglulu *addr &= MVEBU_CP_BASE_MASK; 65*91f16700Schasinglulu for (cp_nr = 0; cp_nr < CP_NUM; cp_nr++) { 66*91f16700Schasinglulu if (*addr == MVEBU_CP_REGS_BASE(cp_nr)) 67*91f16700Schasinglulu return true; 68*91f16700Schasinglulu } 69*91f16700Schasinglulu 70*91f16700Schasinglulu return false; 71*91f16700Schasinglulu } 72*91f16700Schasinglulu 73*91f16700Schasinglulu uintptr_t mrvl_sip_smc_handler(uint32_t smc_fid, 74*91f16700Schasinglulu u_register_t x1, 75*91f16700Schasinglulu u_register_t x2, 76*91f16700Schasinglulu u_register_t x3, 77*91f16700Schasinglulu u_register_t x4, 78*91f16700Schasinglulu void *cookie, 79*91f16700Schasinglulu void *handle, 80*91f16700Schasinglulu u_register_t flags) 81*91f16700Schasinglulu { 82*91f16700Schasinglulu u_register_t ret, read, x5 = x1; 83*91f16700Schasinglulu int i; 84*91f16700Schasinglulu 85*91f16700Schasinglulu debug("%s: got SMC (0x%x) x1 0x%lx, x2 0x%lx, x3 0x%lx\n", 86*91f16700Schasinglulu __func__, smc_fid, x1, x2, x3); 87*91f16700Schasinglulu 88*91f16700Schasinglulu if (is_comphy_fid(smc_fid)) { 89*91f16700Schasinglulu /* validate address passed via x1 */ 90*91f16700Schasinglulu if (!is_cp_range_valid(&x1)) { 91*91f16700Schasinglulu ERROR("%s: Wrong smc (0x%x) address: %lx\n", 92*91f16700Schasinglulu __func__, smc_fid, x1); 93*91f16700Schasinglulu SMC_RET1(handle, SMC_UNK); 94*91f16700Schasinglulu } 95*91f16700Schasinglulu 96*91f16700Schasinglulu x5 = x1 + COMPHY_TRX_TRAIN_CTRL_REG_0_OFFS; 97*91f16700Schasinglulu x1 += MVEBU_COMPHY_OFFSET; 98*91f16700Schasinglulu 99*91f16700Schasinglulu if (x2 >= MAX_LANE_NR) { 100*91f16700Schasinglulu ERROR("%s: Wrong smc (0x%x) lane nr: %lx\n", 101*91f16700Schasinglulu __func__, smc_fid, x2); 102*91f16700Schasinglulu SMC_RET1(handle, SMC_UNK); 103*91f16700Schasinglulu } 104*91f16700Schasinglulu } 105*91f16700Schasinglulu 106*91f16700Schasinglulu switch (smc_fid) { 107*91f16700Schasinglulu 108*91f16700Schasinglulu /* Comphy related FID's */ 109*91f16700Schasinglulu case MV_SIP_COMPHY_POWER_ON: 110*91f16700Schasinglulu /* x1: comphy_base, x2: comphy_index, x3: comphy_mode */ 111*91f16700Schasinglulu ret = mvebu_cp110_comphy_power_on(x1, x2, x3, x5); 112*91f16700Schasinglulu SMC_RET1(handle, ret); 113*91f16700Schasinglulu case MV_SIP_COMPHY_POWER_OFF: 114*91f16700Schasinglulu /* x1: comphy_base, x2: comphy_index */ 115*91f16700Schasinglulu ret = mvebu_cp110_comphy_power_off(x1, x2, x3); 116*91f16700Schasinglulu SMC_RET1(handle, ret); 117*91f16700Schasinglulu case MV_SIP_COMPHY_PLL_LOCK: 118*91f16700Schasinglulu /* x1: comphy_base, x2: comphy_index */ 119*91f16700Schasinglulu ret = mvebu_cp110_comphy_is_pll_locked(x1, x2); 120*91f16700Schasinglulu SMC_RET1(handle, ret); 121*91f16700Schasinglulu case MV_SIP_COMPHY_XFI_TRAIN: 122*91f16700Schasinglulu /* x1: comphy_base, x2: comphy_index */ 123*91f16700Schasinglulu ret = mvebu_cp110_comphy_xfi_rx_training(x1, x2); 124*91f16700Schasinglulu SMC_RET1(handle, ret); 125*91f16700Schasinglulu case MV_SIP_COMPHY_DIG_RESET: 126*91f16700Schasinglulu /* x1: comphy_base, x2: comphy_index, x3: mode, x4: command */ 127*91f16700Schasinglulu ret = mvebu_cp110_comphy_digital_reset(x1, x2, x3, x4); 128*91f16700Schasinglulu SMC_RET1(handle, ret); 129*91f16700Schasinglulu 130*91f16700Schasinglulu /* Miscellaneous FID's' */ 131*91f16700Schasinglulu case MV_SIP_DRAM_SIZE: 132*91f16700Schasinglulu ret = mvebu_get_dram_size(MVEBU_REGS_BASE); 133*91f16700Schasinglulu SMC_RET1(handle, ret); 134*91f16700Schasinglulu case MV_SIP_LLC_ENABLE: 135*91f16700Schasinglulu for (i = 0; i < ap_get_count(); i++) 136*91f16700Schasinglulu llc_runtime_enable(i); 137*91f16700Schasinglulu 138*91f16700Schasinglulu SMC_RET1(handle, 0); 139*91f16700Schasinglulu #ifdef MVEBU_PMU_IRQ_WA 140*91f16700Schasinglulu case MV_SIP_PMU_IRQ_ENABLE: 141*91f16700Schasinglulu mvebu_pmu_interrupt_enable(); 142*91f16700Schasinglulu SMC_RET1(handle, 0); 143*91f16700Schasinglulu case MV_SIP_PMU_IRQ_DISABLE: 144*91f16700Schasinglulu mvebu_pmu_interrupt_disable(); 145*91f16700Schasinglulu SMC_RET1(handle, 0); 146*91f16700Schasinglulu #endif 147*91f16700Schasinglulu case MV_SIP_DFX: 148*91f16700Schasinglulu if (x1 >= MV_SIP_DFX_THERMAL_INIT && 149*91f16700Schasinglulu x1 <= MV_SIP_DFX_THERMAL_SEL_CHANNEL) { 150*91f16700Schasinglulu ret = mvebu_dfx_thermal_handle(x1, &read, x2, x3); 151*91f16700Schasinglulu SMC_RET2(handle, ret, read); 152*91f16700Schasinglulu } 153*91f16700Schasinglulu if (x1 >= MV_SIP_DFX_SREAD && x1 <= MV_SIP_DFX_SWRITE) { 154*91f16700Schasinglulu ret = mvebu_dfx_misc_handle(x1, &read, x2, x3); 155*91f16700Schasinglulu SMC_RET2(handle, ret, read); 156*91f16700Schasinglulu } 157*91f16700Schasinglulu 158*91f16700Schasinglulu SMC_RET1(handle, SMC_UNK); 159*91f16700Schasinglulu case MV_SIP_DDR_PHY_WRITE: 160*91f16700Schasinglulu ret = mvebu_ddr_phy_write(x1, x2); 161*91f16700Schasinglulu SMC_RET1(handle, ret); 162*91f16700Schasinglulu case MV_SIP_DDR_PHY_READ: 163*91f16700Schasinglulu read = 0; 164*91f16700Schasinglulu ret = mvebu_ddr_phy_read(x1, (uint16_t *)&read); 165*91f16700Schasinglulu SMC_RET2(handle, ret, read); 166*91f16700Schasinglulu case MV_SIP_RNG_64: 167*91f16700Schasinglulu if ((x1 % 2 + 1) > sizeof(read)/4) { 168*91f16700Schasinglulu ERROR("%s: Maximum %ld random bytes per SMC call\n", 169*91f16700Schasinglulu __func__, sizeof(read)); 170*91f16700Schasinglulu SMC_RET1(handle, SMC_UNK); 171*91f16700Schasinglulu } 172*91f16700Schasinglulu ret = eip76_rng_get_random((uint8_t *)&read, 4 * (x1 % 2 + 1)); 173*91f16700Schasinglulu SMC_RET2(handle, ret, read); 174*91f16700Schasinglulu default: 175*91f16700Schasinglulu ERROR("%s: unhandled SMC (0x%x)\n", __func__, smc_fid); 176*91f16700Schasinglulu SMC_RET1(handle, SMC_UNK); 177*91f16700Schasinglulu } 178*91f16700Schasinglulu } 179*91f16700Schasinglulu 180*91f16700Schasinglulu /* Define a runtime service descriptor for fast SMC calls */ 181*91f16700Schasinglulu DECLARE_RT_SVC( 182*91f16700Schasinglulu marvell_sip_svc, 183*91f16700Schasinglulu OEN_SIP_START, 184*91f16700Schasinglulu OEN_SIP_END, 185*91f16700Schasinglulu SMC_TYPE_FAST, 186*91f16700Schasinglulu NULL, 187*91f16700Schasinglulu mrvl_sip_smc_handler 188*91f16700Schasinglulu ); 189