1 /* SPDX-License-Identifier: BSD-3-Clause
3 * Copyright(c) 2019-2020 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 */