1 /* SPDX-License-Identifier: BSD-3-Clause
3 * Copyright(c) 2019-2021 Xilinx, Inc.
4 * Copyright(c) 2012-2019 Solarflare Communications Inc.
10 #if EFSYS_OPT_SIENA && EFSYS_OPT_MCDI
12 #define SIENA_MCDI_PDU(_emip) \
13 (((emip)->emi_port == 1) \
14 ? MC_SMEM_P0_PDU_OFST >> 2 \
15 : MC_SMEM_P1_PDU_OFST >> 2)
17 #define SIENA_MCDI_DOORBELL(_emip) \
18 (((emip)->emi_port == 1) \
19 ? MC_SMEM_P0_DOORBELL_OFST >> 2 \
20 : MC_SMEM_P1_DOORBELL_OFST >> 2)
22 #define SIENA_MCDI_STATUS(_emip) \
23 (((emip)->emi_port == 1) \
24 ? MC_SMEM_P0_STATUS_OFST >> 2 \
25 : MC_SMEM_P1_STATUS_OFST >> 2)
29 siena_mcdi_send_request(
31 __in_bcount(hdr_len) void *hdrp,
33 __in_bcount(sdu_len) void *sdup,
36 efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip);
42 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);
44 EFSYS_ASSERT(emip->emi_port == 1 || emip->emi_port == 2);
45 pdur = SIENA_MCDI_PDU(emip);
46 dbr = SIENA_MCDI_DOORBELL(emip);
48 /* Write the header */
49 EFSYS_ASSERT3U(hdr_len, ==, sizeof (efx_dword_t));
50 dword = *(efx_dword_t *)hdrp;
51 EFX_BAR_TBL_WRITED(enp, FR_CZ_MC_TREG_SMEM, pdur, &dword, B_TRUE);
53 /* Write the payload */
54 for (pos = 0; pos < sdu_len; pos += sizeof (efx_dword_t)) {
55 dword = *(efx_dword_t *)((uint8_t *)sdup + pos);
56 EFX_BAR_TBL_WRITED(enp, FR_CZ_MC_TREG_SMEM,
57 pdur + 1 + (pos >> 2), &dword, B_FALSE);
60 /* Ring the doorbell */
61 EFX_POPULATE_DWORD_1(dword, EFX_DWORD_0, 0xd004be11);
62 EFX_BAR_TBL_WRITED(enp, FR_CZ_MC_TREG_SMEM, dbr, &dword, B_FALSE);
66 siena_mcdi_poll_reboot(
71 * XXX Bug 25922, bug 26099: This function is not being used
72 * properly. Until its callers are fixed, it should always
78 efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip);
83 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);
84 EFSYS_ASSERT(emip->emi_port == 1 || emip->emi_port == 2);
85 rebootr = SIENA_MCDI_STATUS(emip);
87 EFX_BAR_TBL_READD(enp, FR_CZ_MC_TREG_SMEM, rebootr, &dword, B_FALSE);
88 value = EFX_DWORD_FIELD(dword, EFX_DWORD_0);
93 EFX_ZERO_DWORD(dword);
94 EFX_BAR_TBL_WRITED(enp, FR_CZ_MC_TREG_SMEM, rebootr, &dword, B_FALSE);
96 if (value == MC_STATUS_DWORD_ASSERT)
103 extern __checkReturn boolean_t
104 siena_mcdi_poll_response(
107 efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip);
111 EFSYS_ASSERT(emip->emi_port == 1 || emip->emi_port == 2);
112 pdur = SIENA_MCDI_PDU(emip);
114 EFX_BAR_TBL_READD(enp, FR_CZ_MC_TREG_SMEM, pdur, &hdr, B_FALSE);
115 return (EFX_DWORD_FIELD(hdr, MCDI_HEADER_RESPONSE) ? B_TRUE : B_FALSE);
119 siena_mcdi_read_response(
121 __out_bcount(length) void *bufferp,
125 efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip);
127 unsigned int pos = 0;
129 size_t remaining = length;
131 EFSYS_ASSERT(emip->emi_port == 1 || emip->emi_port == 2);
132 pdur = SIENA_MCDI_PDU(emip);
134 while (remaining > 0) {
135 size_t chunk = MIN(remaining, sizeof (data));
137 EFX_BAR_TBL_READD(enp, FR_CZ_MC_TREG_SMEM,
138 pdur + ((offset + pos) >> 2), &data, B_FALSE);
139 memcpy((uint8_t *)bufferp + pos, &data, chunk);
145 __checkReturn efx_rc_t
148 __in const efx_mcdi_transport_t *mtp)
150 efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip);
152 unsigned int portnum;
155 _NOTE(ARGUNUSED(mtp))
157 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);
159 /* Determine the port number to use for MCDI */
160 EFX_BAR_READO(enp, FR_AZ_CS_DEBUG_REG, &oword);
161 portnum = EFX_OWORD_FIELD(oword, FRF_CZ_CS_PORT_NUM);
164 /* Presumably booted from ROM; only MCDI port 1 will work */
166 } else if (portnum <= 2) {
167 emip->emi_port = portnum;
173 /* Siena BootROM and firmware only support MCDIv1 */
174 emip->emi_max_version = 1;
177 * Wipe the atomic reboot status so subsequent MCDI requests succeed.
178 * BOOT_STATUS is preserved so eno_nic_probe() can boot out of the
181 (void) siena_mcdi_poll_reboot(enp);
186 EFSYS_PROBE1(fail1, efx_rc_t, rc);
195 _NOTE(ARGUNUSED(enp))
198 __checkReturn efx_rc_t
199 siena_mcdi_feature_supported(
201 __in efx_mcdi_feature_id_t id,
202 __out boolean_t *supportedp)
206 EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA);
209 case EFX_MCDI_FEATURE_FW_UPDATE:
210 case EFX_MCDI_FEATURE_LINK_CONTROL:
211 case EFX_MCDI_FEATURE_MACADDR_CHANGE:
212 case EFX_MCDI_FEATURE_MAC_SPOOFING:
213 *supportedp = B_TRUE;
223 EFSYS_PROBE1(fail1, efx_rc_t, rc);
228 /* Default timeout for MCDI command processing. */
229 #define SIENA_MCDI_CMD_TIMEOUT_US (10 * 1000 * 1000)
232 siena_mcdi_get_timeout(
234 __in efx_mcdi_req_t *emrp,
235 __out uint32_t *timeoutp)
237 _NOTE(ARGUNUSED(enp, emrp))
239 *timeoutp = SIENA_MCDI_CMD_TIMEOUT_US;
243 #endif /* EFSYS_OPT_SIENA && EFSYS_OPT_MCDI */