brintos

brintos / linux-shallow public Read only

0
0
Text · 8.0 KiB · 885c69e Raw
258 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Copyright (C) 2022-2023, Advanced Micro Devices, Inc.4 */5 6#include <linux/module.h>7 8#include "mcdi.h"9#include "mcdi_functions.h"10 11int cdx_mcdi_get_num_buses(struct cdx_mcdi *cdx)12{13	MCDI_DECLARE_BUF(outbuf, MC_CMD_CDX_BUS_ENUM_BUSES_OUT_LEN);14	size_t outlen;15	int ret;16 17	ret = cdx_mcdi_rpc(cdx, MC_CMD_CDX_BUS_ENUM_BUSES, NULL, 0,18			   outbuf, sizeof(outbuf), &outlen);19	if (ret)20		return ret;21 22	if (outlen != MC_CMD_CDX_BUS_ENUM_BUSES_OUT_LEN)23		return -EIO;24 25	return MCDI_DWORD(outbuf, CDX_BUS_ENUM_BUSES_OUT_BUS_COUNT);26}27 28int cdx_mcdi_get_num_devs(struct cdx_mcdi *cdx, int bus_num)29{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);32	size_t outlen;33	int ret;34 35	MCDI_SET_DWORD(inbuf, CDX_BUS_ENUM_DEVICES_IN_BUS, bus_num);36 37	ret = cdx_mcdi_rpc(cdx, MC_CMD_CDX_BUS_ENUM_DEVICES, inbuf, sizeof(inbuf),38			   outbuf, sizeof(outbuf), &outlen);39	if (ret)40		return ret;41 42	if (outlen != MC_CMD_CDX_BUS_ENUM_DEVICES_OUT_LEN)43		return -EIO;44 45	return MCDI_DWORD(outbuf, CDX_BUS_ENUM_DEVICES_OUT_DEVICE_COUNT);46}47 48int cdx_mcdi_get_dev_config(struct cdx_mcdi *cdx,49			    u8 bus_num, u8 dev_num,50			    struct cdx_dev_params *dev_params)51{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];55	size_t outlen;56	u32 req_id;57	int ret;58 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);61 62	ret = cdx_mcdi_rpc(cdx, MC_CMD_CDX_BUS_GET_DEVICE_CONFIG, inbuf, sizeof(inbuf),63			   outbuf, sizeof(outbuf), &outlen);64	if (ret)65		return ret;66 67	if (outlen != MC_CMD_CDX_BUS_GET_DEVICE_CONFIG_OUT_V2_LEN)68		return -EIO;69 70	dev_params->bus_num = bus_num;71	dev_params->dev_num = dev_num;72 73	req_id = MCDI_DWORD(outbuf, CDX_BUS_GET_DEVICE_CONFIG_OUT_REQUESTER_ID);74	dev_params->req_id = req_id;75 76	dev_params->msi_dev_id = MCDI_DWORD(outbuf,77					    CDX_BUS_GET_DEVICE_CONFIG_OUT_V2_REQUESTER_DEVICE_ID);78 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) +85				   MCDI_QWORD(outbuf,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++;89	}90 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) +96				   MCDI_QWORD(outbuf,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++;100	}101 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) +107				   MCDI_QWORD(outbuf,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++;111	}112 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) +118				   MCDI_QWORD(outbuf,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++;122	}123 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);134 135	return 0;136}137 138int cdx_mcdi_bus_enable(struct cdx_mcdi *cdx, u8 bus_num)139{140	MCDI_DECLARE_BUF(inbuf, MC_CMD_CDX_BUS_UP_IN_LEN);141	int ret;142 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),145			   NULL, 0, NULL);146 147	return ret;148}149 150int cdx_mcdi_bus_disable(struct cdx_mcdi *cdx, u8 bus_num)151{152	MCDI_DECLARE_BUF(inbuf, MC_CMD_CDX_BUS_DOWN_IN_LEN);153	int ret;154 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),157			   NULL, 0, NULL);158 159	return ret;160}161 162int cdx_mcdi_write_msi(struct cdx_mcdi *cdx, u8 bus_num, u8 dev_num,163		       u32 msi_vector, u64 msi_address, u32 msi_data)164{165	MCDI_DECLARE_BUF(inbuf, MC_CMD_CDX_DEVICE_WRITE_MSI_MSG_IN_LEN);166	int ret;167 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);173 174	ret = cdx_mcdi_rpc(cdx, MC_CMD_CDX_DEVICE_WRITE_MSI_MSG, inbuf, sizeof(inbuf),175			   NULL, 0, NULL);176 177	return ret;178}179 180int cdx_mcdi_reset_device(struct cdx_mcdi *cdx, u8 bus_num, u8 dev_num)181{182	MCDI_DECLARE_BUF(inbuf, MC_CMD_CDX_DEVICE_RESET_IN_LEN);183	int ret;184 185	MCDI_SET_DWORD(inbuf, CDX_DEVICE_RESET_IN_BUS, bus_num);186	MCDI_SET_DWORD(inbuf, CDX_DEVICE_RESET_IN_DEVICE, dev_num);187 188	ret = cdx_mcdi_rpc(cdx, MC_CMD_CDX_DEVICE_RESET, inbuf, sizeof(inbuf),189			   NULL, 0, NULL);190 191	return ret;192}193 194static int cdx_mcdi_ctrl_flag_get(struct cdx_mcdi *cdx, u8 bus_num,195				  u8 dev_num, u32 *flags)196{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);199	size_t outlen;200	int ret;201 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);206	if (ret)207		return ret;208 209	if (outlen != MC_CMD_CDX_DEVICE_CONTROL_GET_OUT_LEN)210		return -EIO;211 212	*flags = MCDI_DWORD(outbuf, CDX_DEVICE_CONTROL_GET_OUT_FLAGS);213 214	return 0;215}216 217static int cdx_mcdi_ctrl_flag_set(struct cdx_mcdi *cdx, u8 bus_num,218				  u8 dev_num, bool enable, int bit_pos)219{220	MCDI_DECLARE_BUF(inbuf, MC_CMD_CDX_DEVICE_CONTROL_SET_IN_LEN);221	u32 flags;222	int ret;223 224	/*225	 * Get flags and then set/reset bit at bit_pos according to226	 * the input params.227	 */228	ret = cdx_mcdi_ctrl_flag_get(cdx, bus_num, dev_num, &flags);229	if (ret)230		return ret;231 232	flags = flags & (u32)(~(BIT(bit_pos)));233	if (enable)234		flags |= (1 << bit_pos);235 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);241 242	return ret;243}244 245int cdx_mcdi_bus_master_enable(struct cdx_mcdi *cdx, u8 bus_num,246			       u8 dev_num, bool enable)247{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);250}251 252int cdx_mcdi_msi_enable(struct cdx_mcdi *cdx, u8 bus_num,253			u8 dev_num, bool enable)254{255	return cdx_mcdi_ctrl_flag_set(cdx, bus_num, dev_num, enable,256			MC_CMD_CDX_DEVICE_CONTROL_SET_IN_MSI_ENABLE_LBN);257}258