xref: /arm-trusted-firmware/plat/marvell/armada/common/mrvl_sip_svc.c (revision 91f16700b400a8c0651d24a598fc48ee2997a0d7)
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