1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (C) 2022-2023, Advanced Micro Devices, Inc.
6 #include <linux/module.h>
9 #include "mcdi_functions.h"
11 int cdx_mcdi_get_num_buses(struct cdx_mcdi
*cdx
)
13 MCDI_DECLARE_BUF(outbuf
, MC_CMD_CDX_BUS_ENUM_BUSES_OUT_LEN
);
17 ret
= cdx_mcdi_rpc(cdx
, MC_CMD_CDX_BUS_ENUM_BUSES
, NULL
, 0,
18 outbuf
, sizeof(outbuf
), &outlen
);
22 if (outlen
!= MC_CMD_CDX_BUS_ENUM_BUSES_OUT_LEN
)
25 return MCDI_DWORD(outbuf
, CDX_BUS_ENUM_BUSES_OUT_BUS_COUNT
);
28 int cdx_mcdi_get_num_devs(struct cdx_mcdi
*cdx
, int bus_num
)
30 MCDI_DECLARE_BUF(outbuf
, MC_CMD_CDX_BUS_ENUM_DEVICES_OUT_LEN
);
31 MCDI_DECLARE_BUF(inbuf
, MC_CMD_CDX_BUS_ENUM_DEVICES_IN_LEN
);
35 MCDI_SET_DWORD(inbuf
, CDX_BUS_ENUM_DEVICES_IN_BUS
, bus_num
);
37 ret
= cdx_mcdi_rpc(cdx
, MC_CMD_CDX_BUS_ENUM_DEVICES
, inbuf
, sizeof(inbuf
),
38 outbuf
, sizeof(outbuf
), &outlen
);
42 if (outlen
!= MC_CMD_CDX_BUS_ENUM_DEVICES_OUT_LEN
)
45 return MCDI_DWORD(outbuf
, CDX_BUS_ENUM_DEVICES_OUT_DEVICE_COUNT
);
48 int cdx_mcdi_get_dev_config(struct cdx_mcdi
*cdx
,
49 u8 bus_num
, u8 dev_num
,
50 struct cdx_dev_params
*dev_params
)
52 MCDI_DECLARE_BUF(outbuf
, MC_CMD_CDX_BUS_GET_DEVICE_CONFIG_OUT_V2_LEN
);
53 MCDI_DECLARE_BUF(inbuf
, MC_CMD_CDX_BUS_GET_DEVICE_CONFIG_IN_LEN
);
54 struct resource
*res
= &dev_params
->res
[0];
59 MCDI_SET_DWORD(inbuf
, CDX_BUS_GET_DEVICE_CONFIG_IN_BUS
, bus_num
);
60 MCDI_SET_DWORD(inbuf
, CDX_BUS_GET_DEVICE_CONFIG_IN_DEVICE
, dev_num
);
62 ret
= cdx_mcdi_rpc(cdx
, MC_CMD_CDX_BUS_GET_DEVICE_CONFIG
, inbuf
, sizeof(inbuf
),
63 outbuf
, sizeof(outbuf
), &outlen
);
67 if (outlen
!= MC_CMD_CDX_BUS_GET_DEVICE_CONFIG_OUT_V2_LEN
)
70 dev_params
->bus_num
= bus_num
;
71 dev_params
->dev_num
= dev_num
;
73 req_id
= MCDI_DWORD(outbuf
, CDX_BUS_GET_DEVICE_CONFIG_OUT_REQUESTER_ID
);
74 dev_params
->req_id
= req_id
;
76 dev_params
->msi_dev_id
= MCDI_DWORD(outbuf
,
77 CDX_BUS_GET_DEVICE_CONFIG_OUT_V2_REQUESTER_DEVICE_ID
);
79 dev_params
->res_count
= 0;
80 if (MCDI_QWORD(outbuf
, CDX_BUS_GET_DEVICE_CONFIG_OUT_MMIO_REGION0_SIZE
) != 0) {
81 res
[dev_params
->res_count
].start
=
82 MCDI_QWORD(outbuf
, CDX_BUS_GET_DEVICE_CONFIG_OUT_MMIO_REGION0_BASE
);
83 res
[dev_params
->res_count
].end
=
84 MCDI_QWORD(outbuf
, CDX_BUS_GET_DEVICE_CONFIG_OUT_MMIO_REGION0_BASE
) +
86 CDX_BUS_GET_DEVICE_CONFIG_OUT_MMIO_REGION0_SIZE
) - 1;
87 res
[dev_params
->res_count
].flags
= IORESOURCE_MEM
;
88 dev_params
->res_count
++;
91 if (MCDI_QWORD(outbuf
, CDX_BUS_GET_DEVICE_CONFIG_OUT_MMIO_REGION1_SIZE
) != 0) {
92 res
[dev_params
->res_count
].start
=
93 MCDI_QWORD(outbuf
, CDX_BUS_GET_DEVICE_CONFIG_OUT_MMIO_REGION1_BASE
);
94 res
[dev_params
->res_count
].end
=
95 MCDI_QWORD(outbuf
, CDX_BUS_GET_DEVICE_CONFIG_OUT_MMIO_REGION1_BASE
) +
97 CDX_BUS_GET_DEVICE_CONFIG_OUT_MMIO_REGION1_SIZE
) - 1;
98 res
[dev_params
->res_count
].flags
= IORESOURCE_MEM
;
99 dev_params
->res_count
++;
102 if (MCDI_QWORD(outbuf
, CDX_BUS_GET_DEVICE_CONFIG_OUT_MMIO_REGION2_SIZE
) != 0) {
103 res
[dev_params
->res_count
].start
=
104 MCDI_QWORD(outbuf
, CDX_BUS_GET_DEVICE_CONFIG_OUT_MMIO_REGION2_BASE
);
105 res
[dev_params
->res_count
].end
=
106 MCDI_QWORD(outbuf
, CDX_BUS_GET_DEVICE_CONFIG_OUT_MMIO_REGION2_BASE
) +
108 CDX_BUS_GET_DEVICE_CONFIG_OUT_MMIO_REGION2_SIZE
) - 1;
109 res
[dev_params
->res_count
].flags
= IORESOURCE_MEM
;
110 dev_params
->res_count
++;
113 if (MCDI_QWORD(outbuf
, CDX_BUS_GET_DEVICE_CONFIG_OUT_MMIO_REGION3_SIZE
) != 0) {
114 res
[dev_params
->res_count
].start
=
115 MCDI_QWORD(outbuf
, CDX_BUS_GET_DEVICE_CONFIG_OUT_MMIO_REGION3_BASE
);
116 res
[dev_params
->res_count
].end
=
117 MCDI_QWORD(outbuf
, CDX_BUS_GET_DEVICE_CONFIG_OUT_MMIO_REGION3_BASE
) +
119 CDX_BUS_GET_DEVICE_CONFIG_OUT_MMIO_REGION3_SIZE
) - 1;
120 res
[dev_params
->res_count
].flags
= IORESOURCE_MEM
;
121 dev_params
->res_count
++;
124 dev_params
->vendor
= MCDI_WORD(outbuf
, CDX_BUS_GET_DEVICE_CONFIG_OUT_VENDOR_ID
);
125 dev_params
->device
= MCDI_WORD(outbuf
, CDX_BUS_GET_DEVICE_CONFIG_OUT_DEVICE_ID
);
126 dev_params
->subsys_vendor
= MCDI_WORD(outbuf
,
127 CDX_BUS_GET_DEVICE_CONFIG_OUT_SUBSYS_VENDOR_ID
);
128 dev_params
->subsys_device
= MCDI_WORD(outbuf
,
129 CDX_BUS_GET_DEVICE_CONFIG_OUT_SUBSYS_DEVICE_ID
);
130 dev_params
->class = MCDI_DWORD(outbuf
,
131 CDX_BUS_GET_DEVICE_CONFIG_OUT_DEVICE_CLASS
) & 0xFFFFFF;
132 dev_params
->revision
= MCDI_BYTE(outbuf
, CDX_BUS_GET_DEVICE_CONFIG_OUT_DEVICE_REVISION
);
133 dev_params
->num_msi
= MCDI_DWORD(outbuf
, CDX_BUS_GET_DEVICE_CONFIG_OUT_MSI_COUNT
);
138 int cdx_mcdi_bus_enable(struct cdx_mcdi
*cdx
, u8 bus_num
)
140 MCDI_DECLARE_BUF(inbuf
, MC_CMD_CDX_BUS_UP_IN_LEN
);
143 MCDI_SET_DWORD(inbuf
, CDX_BUS_UP_IN_BUS
, bus_num
);
144 ret
= cdx_mcdi_rpc(cdx
, MC_CMD_CDX_BUS_UP
, inbuf
, sizeof(inbuf
),
150 int cdx_mcdi_bus_disable(struct cdx_mcdi
*cdx
, u8 bus_num
)
152 MCDI_DECLARE_BUF(inbuf
, MC_CMD_CDX_BUS_DOWN_IN_LEN
);
155 MCDI_SET_DWORD(inbuf
, CDX_BUS_DOWN_IN_BUS
, bus_num
);
156 ret
= cdx_mcdi_rpc(cdx
, MC_CMD_CDX_BUS_DOWN
, inbuf
, sizeof(inbuf
),
162 int cdx_mcdi_write_msi(struct cdx_mcdi
*cdx
, u8 bus_num
, u8 dev_num
,
163 u32 msi_vector
, u64 msi_address
, u32 msi_data
)
165 MCDI_DECLARE_BUF(inbuf
, MC_CMD_CDX_DEVICE_WRITE_MSI_MSG_IN_LEN
);
168 MCDI_SET_DWORD(inbuf
, CDX_DEVICE_WRITE_MSI_MSG_IN_BUS
, bus_num
);
169 MCDI_SET_DWORD(inbuf
, CDX_DEVICE_WRITE_MSI_MSG_IN_DEVICE
, dev_num
);
170 MCDI_SET_DWORD(inbuf
, CDX_DEVICE_WRITE_MSI_MSG_IN_MSI_VECTOR
, msi_vector
);
171 MCDI_SET_QWORD(inbuf
, CDX_DEVICE_WRITE_MSI_MSG_IN_MSI_ADDRESS
, msi_address
);
172 MCDI_SET_DWORD(inbuf
, CDX_DEVICE_WRITE_MSI_MSG_IN_MSI_DATA
, msi_data
);
174 ret
= cdx_mcdi_rpc(cdx
, MC_CMD_CDX_DEVICE_WRITE_MSI_MSG
, inbuf
, sizeof(inbuf
),
180 int cdx_mcdi_reset_device(struct cdx_mcdi
*cdx
, u8 bus_num
, u8 dev_num
)
182 MCDI_DECLARE_BUF(inbuf
, MC_CMD_CDX_DEVICE_RESET_IN_LEN
);
185 MCDI_SET_DWORD(inbuf
, CDX_DEVICE_RESET_IN_BUS
, bus_num
);
186 MCDI_SET_DWORD(inbuf
, CDX_DEVICE_RESET_IN_DEVICE
, dev_num
);
188 ret
= cdx_mcdi_rpc(cdx
, MC_CMD_CDX_DEVICE_RESET
, inbuf
, sizeof(inbuf
),
194 static int cdx_mcdi_ctrl_flag_get(struct cdx_mcdi
*cdx
, u8 bus_num
,
195 u8 dev_num
, u32
*flags
)
197 MCDI_DECLARE_BUF(inbuf
, MC_CMD_CDX_DEVICE_CONTROL_GET_IN_LEN
);
198 MCDI_DECLARE_BUF(outbuf
, MC_CMD_CDX_DEVICE_CONTROL_GET_OUT_LEN
);
202 MCDI_SET_DWORD(inbuf
, CDX_DEVICE_CONTROL_GET_IN_BUS
, bus_num
);
203 MCDI_SET_DWORD(inbuf
, CDX_DEVICE_CONTROL_GET_IN_DEVICE
, dev_num
);
204 ret
= cdx_mcdi_rpc(cdx
, MC_CMD_CDX_DEVICE_CONTROL_GET
, inbuf
,
205 sizeof(inbuf
), outbuf
, sizeof(outbuf
), &outlen
);
209 if (outlen
!= MC_CMD_CDX_DEVICE_CONTROL_GET_OUT_LEN
)
212 *flags
= MCDI_DWORD(outbuf
, CDX_DEVICE_CONTROL_GET_OUT_FLAGS
);
217 static int cdx_mcdi_ctrl_flag_set(struct cdx_mcdi
*cdx
, u8 bus_num
,
218 u8 dev_num
, bool enable
, int bit_pos
)
220 MCDI_DECLARE_BUF(inbuf
, MC_CMD_CDX_DEVICE_CONTROL_SET_IN_LEN
);
225 * Get flags and then set/reset bit at bit_pos according to
228 ret
= cdx_mcdi_ctrl_flag_get(cdx
, bus_num
, dev_num
, &flags
);
232 flags
= flags
& (u32
)(~(BIT(bit_pos
)));
234 flags
|= (1 << bit_pos
);
236 MCDI_SET_DWORD(inbuf
, CDX_DEVICE_CONTROL_SET_IN_BUS
, bus_num
);
237 MCDI_SET_DWORD(inbuf
, CDX_DEVICE_CONTROL_SET_IN_DEVICE
, dev_num
);
238 MCDI_SET_DWORD(inbuf
, CDX_DEVICE_CONTROL_SET_IN_FLAGS
, flags
);
239 ret
= cdx_mcdi_rpc(cdx
, MC_CMD_CDX_DEVICE_CONTROL_SET
, inbuf
,
240 sizeof(inbuf
), NULL
, 0, NULL
);
245 int cdx_mcdi_bus_master_enable(struct cdx_mcdi
*cdx
, u8 bus_num
,
246 u8 dev_num
, bool enable
)
248 return cdx_mcdi_ctrl_flag_set(cdx
, bus_num
, dev_num
, enable
,
249 MC_CMD_CDX_DEVICE_CONTROL_SET_IN_BUS_MASTER_ENABLE_LBN
);
252 int cdx_mcdi_msi_enable(struct cdx_mcdi
*cdx
, u8 bus_num
,
253 u8 dev_num
, bool enable
)
255 return cdx_mcdi_ctrl_flag_set(cdx
, bus_num
, dev_num
, enable
,
256 MC_CMD_CDX_DEVICE_CONTROL_SET_IN_MSI_ENABLE_LBN
);