Path: blob/master/drivers/cdx/controller/mcdi_functions.c
26444 views
// SPDX-License-Identifier: GPL-2.01/*2* Copyright (C) 2022-2023, Advanced Micro Devices, Inc.3*/45#include <linux/module.h>67#include "mcdi.h"8#include "mcdi_functions.h"910int cdx_mcdi_get_num_buses(struct cdx_mcdi *cdx)11{12MCDI_DECLARE_BUF(outbuf, MC_CMD_CDX_BUS_ENUM_BUSES_OUT_LEN);13size_t outlen;14int ret;1516ret = cdx_mcdi_rpc(cdx, MC_CMD_CDX_BUS_ENUM_BUSES, NULL, 0,17outbuf, sizeof(outbuf), &outlen);18if (ret)19return ret;2021if (outlen != MC_CMD_CDX_BUS_ENUM_BUSES_OUT_LEN)22return -EIO;2324return MCDI_DWORD(outbuf, CDX_BUS_ENUM_BUSES_OUT_BUS_COUNT);25}2627int cdx_mcdi_get_num_devs(struct cdx_mcdi *cdx, int bus_num)28{29MCDI_DECLARE_BUF(outbuf, MC_CMD_CDX_BUS_ENUM_DEVICES_OUT_LEN);30MCDI_DECLARE_BUF(inbuf, MC_CMD_CDX_BUS_ENUM_DEVICES_IN_LEN);31size_t outlen;32int ret;3334MCDI_SET_DWORD(inbuf, CDX_BUS_ENUM_DEVICES_IN_BUS, bus_num);3536ret = cdx_mcdi_rpc(cdx, MC_CMD_CDX_BUS_ENUM_DEVICES, inbuf, sizeof(inbuf),37outbuf, sizeof(outbuf), &outlen);38if (ret)39return ret;4041if (outlen != MC_CMD_CDX_BUS_ENUM_DEVICES_OUT_LEN)42return -EIO;4344return MCDI_DWORD(outbuf, CDX_BUS_ENUM_DEVICES_OUT_DEVICE_COUNT);45}4647int cdx_mcdi_get_dev_config(struct cdx_mcdi *cdx,48u8 bus_num, u8 dev_num,49struct cdx_dev_params *dev_params)50{51MCDI_DECLARE_BUF(outbuf, MC_CMD_CDX_BUS_GET_DEVICE_CONFIG_OUT_V2_LEN);52MCDI_DECLARE_BUF(inbuf, MC_CMD_CDX_BUS_GET_DEVICE_CONFIG_IN_LEN);53struct resource *res = &dev_params->res[0];54size_t outlen;55u32 req_id;56int ret;5758MCDI_SET_DWORD(inbuf, CDX_BUS_GET_DEVICE_CONFIG_IN_BUS, bus_num);59MCDI_SET_DWORD(inbuf, CDX_BUS_GET_DEVICE_CONFIG_IN_DEVICE, dev_num);6061ret = cdx_mcdi_rpc(cdx, MC_CMD_CDX_BUS_GET_DEVICE_CONFIG, inbuf, sizeof(inbuf),62outbuf, sizeof(outbuf), &outlen);63if (ret)64return ret;6566if (outlen != MC_CMD_CDX_BUS_GET_DEVICE_CONFIG_OUT_V2_LEN)67return -EIO;6869dev_params->bus_num = bus_num;70dev_params->dev_num = dev_num;7172req_id = MCDI_DWORD(outbuf, CDX_BUS_GET_DEVICE_CONFIG_OUT_REQUESTER_ID);73dev_params->req_id = req_id;7475dev_params->msi_dev_id = MCDI_DWORD(outbuf,76CDX_BUS_GET_DEVICE_CONFIG_OUT_V2_REQUESTER_DEVICE_ID);7778dev_params->res_count = 0;79if (MCDI_QWORD(outbuf, CDX_BUS_GET_DEVICE_CONFIG_OUT_MMIO_REGION0_SIZE) != 0) {80res[dev_params->res_count].start =81MCDI_QWORD(outbuf, CDX_BUS_GET_DEVICE_CONFIG_OUT_MMIO_REGION0_BASE);82res[dev_params->res_count].end =83MCDI_QWORD(outbuf, CDX_BUS_GET_DEVICE_CONFIG_OUT_MMIO_REGION0_BASE) +84MCDI_QWORD(outbuf,85CDX_BUS_GET_DEVICE_CONFIG_OUT_MMIO_REGION0_SIZE) - 1;86res[dev_params->res_count].flags = IORESOURCE_MEM;87dev_params->res_count++;88}8990if (MCDI_QWORD(outbuf, CDX_BUS_GET_DEVICE_CONFIG_OUT_MMIO_REGION1_SIZE) != 0) {91res[dev_params->res_count].start =92MCDI_QWORD(outbuf, CDX_BUS_GET_DEVICE_CONFIG_OUT_MMIO_REGION1_BASE);93res[dev_params->res_count].end =94MCDI_QWORD(outbuf, CDX_BUS_GET_DEVICE_CONFIG_OUT_MMIO_REGION1_BASE) +95MCDI_QWORD(outbuf,96CDX_BUS_GET_DEVICE_CONFIG_OUT_MMIO_REGION1_SIZE) - 1;97res[dev_params->res_count].flags = IORESOURCE_MEM;98dev_params->res_count++;99}100101if (MCDI_QWORD(outbuf, CDX_BUS_GET_DEVICE_CONFIG_OUT_MMIO_REGION2_SIZE) != 0) {102res[dev_params->res_count].start =103MCDI_QWORD(outbuf, CDX_BUS_GET_DEVICE_CONFIG_OUT_MMIO_REGION2_BASE);104res[dev_params->res_count].end =105MCDI_QWORD(outbuf, CDX_BUS_GET_DEVICE_CONFIG_OUT_MMIO_REGION2_BASE) +106MCDI_QWORD(outbuf,107CDX_BUS_GET_DEVICE_CONFIG_OUT_MMIO_REGION2_SIZE) - 1;108res[dev_params->res_count].flags = IORESOURCE_MEM;109dev_params->res_count++;110}111112if (MCDI_QWORD(outbuf, CDX_BUS_GET_DEVICE_CONFIG_OUT_MMIO_REGION3_SIZE) != 0) {113res[dev_params->res_count].start =114MCDI_QWORD(outbuf, CDX_BUS_GET_DEVICE_CONFIG_OUT_MMIO_REGION3_BASE);115res[dev_params->res_count].end =116MCDI_QWORD(outbuf, CDX_BUS_GET_DEVICE_CONFIG_OUT_MMIO_REGION3_BASE) +117MCDI_QWORD(outbuf,118CDX_BUS_GET_DEVICE_CONFIG_OUT_MMIO_REGION3_SIZE) - 1;119res[dev_params->res_count].flags = IORESOURCE_MEM;120dev_params->res_count++;121}122123dev_params->vendor = MCDI_WORD(outbuf, CDX_BUS_GET_DEVICE_CONFIG_OUT_VENDOR_ID);124dev_params->device = MCDI_WORD(outbuf, CDX_BUS_GET_DEVICE_CONFIG_OUT_DEVICE_ID);125dev_params->subsys_vendor = MCDI_WORD(outbuf,126CDX_BUS_GET_DEVICE_CONFIG_OUT_SUBSYS_VENDOR_ID);127dev_params->subsys_device = MCDI_WORD(outbuf,128CDX_BUS_GET_DEVICE_CONFIG_OUT_SUBSYS_DEVICE_ID);129dev_params->class = MCDI_DWORD(outbuf,130CDX_BUS_GET_DEVICE_CONFIG_OUT_DEVICE_CLASS) & 0xFFFFFF;131dev_params->revision = MCDI_BYTE(outbuf, CDX_BUS_GET_DEVICE_CONFIG_OUT_DEVICE_REVISION);132dev_params->num_msi = MCDI_DWORD(outbuf, CDX_BUS_GET_DEVICE_CONFIG_OUT_MSI_COUNT);133134return 0;135}136137int cdx_mcdi_bus_enable(struct cdx_mcdi *cdx, u8 bus_num)138{139MCDI_DECLARE_BUF(inbuf, MC_CMD_CDX_BUS_UP_IN_LEN);140int ret;141142MCDI_SET_DWORD(inbuf, CDX_BUS_UP_IN_BUS, bus_num);143ret = cdx_mcdi_rpc(cdx, MC_CMD_CDX_BUS_UP, inbuf, sizeof(inbuf),144NULL, 0, NULL);145146return ret;147}148149int cdx_mcdi_bus_disable(struct cdx_mcdi *cdx, u8 bus_num)150{151MCDI_DECLARE_BUF(inbuf, MC_CMD_CDX_BUS_DOWN_IN_LEN);152int ret;153154MCDI_SET_DWORD(inbuf, CDX_BUS_DOWN_IN_BUS, bus_num);155ret = cdx_mcdi_rpc(cdx, MC_CMD_CDX_BUS_DOWN, inbuf, sizeof(inbuf),156NULL, 0, NULL);157158return ret;159}160161int cdx_mcdi_write_msi(struct cdx_mcdi *cdx, u8 bus_num, u8 dev_num,162u32 msi_vector, u64 msi_address, u32 msi_data)163{164MCDI_DECLARE_BUF(inbuf, MC_CMD_CDX_DEVICE_WRITE_MSI_MSG_IN_LEN);165int ret;166167MCDI_SET_DWORD(inbuf, CDX_DEVICE_WRITE_MSI_MSG_IN_BUS, bus_num);168MCDI_SET_DWORD(inbuf, CDX_DEVICE_WRITE_MSI_MSG_IN_DEVICE, dev_num);169MCDI_SET_DWORD(inbuf, CDX_DEVICE_WRITE_MSI_MSG_IN_MSI_VECTOR, msi_vector);170MCDI_SET_QWORD(inbuf, CDX_DEVICE_WRITE_MSI_MSG_IN_MSI_ADDRESS, msi_address);171MCDI_SET_DWORD(inbuf, CDX_DEVICE_WRITE_MSI_MSG_IN_MSI_DATA, msi_data);172173ret = cdx_mcdi_rpc(cdx, MC_CMD_CDX_DEVICE_WRITE_MSI_MSG, inbuf, sizeof(inbuf),174NULL, 0, NULL);175176return ret;177}178179int cdx_mcdi_reset_device(struct cdx_mcdi *cdx, u8 bus_num, u8 dev_num)180{181MCDI_DECLARE_BUF(inbuf, MC_CMD_CDX_DEVICE_RESET_IN_LEN);182int ret;183184MCDI_SET_DWORD(inbuf, CDX_DEVICE_RESET_IN_BUS, bus_num);185MCDI_SET_DWORD(inbuf, CDX_DEVICE_RESET_IN_DEVICE, dev_num);186187ret = cdx_mcdi_rpc(cdx, MC_CMD_CDX_DEVICE_RESET, inbuf, sizeof(inbuf),188NULL, 0, NULL);189190return ret;191}192193static int cdx_mcdi_ctrl_flag_get(struct cdx_mcdi *cdx, u8 bus_num,194u8 dev_num, u32 *flags)195{196MCDI_DECLARE_BUF(inbuf, MC_CMD_CDX_DEVICE_CONTROL_GET_IN_LEN);197MCDI_DECLARE_BUF(outbuf, MC_CMD_CDX_DEVICE_CONTROL_GET_OUT_LEN);198size_t outlen;199int ret;200201MCDI_SET_DWORD(inbuf, CDX_DEVICE_CONTROL_GET_IN_BUS, bus_num);202MCDI_SET_DWORD(inbuf, CDX_DEVICE_CONTROL_GET_IN_DEVICE, dev_num);203ret = cdx_mcdi_rpc(cdx, MC_CMD_CDX_DEVICE_CONTROL_GET, inbuf,204sizeof(inbuf), outbuf, sizeof(outbuf), &outlen);205if (ret)206return ret;207208if (outlen != MC_CMD_CDX_DEVICE_CONTROL_GET_OUT_LEN)209return -EIO;210211*flags = MCDI_DWORD(outbuf, CDX_DEVICE_CONTROL_GET_OUT_FLAGS);212213return 0;214}215216static int cdx_mcdi_ctrl_flag_set(struct cdx_mcdi *cdx, u8 bus_num,217u8 dev_num, bool enable, int bit_pos)218{219MCDI_DECLARE_BUF(inbuf, MC_CMD_CDX_DEVICE_CONTROL_SET_IN_LEN);220u32 flags;221int ret;222223/*224* Get flags and then set/reset bit at bit_pos according to225* the input params.226*/227ret = cdx_mcdi_ctrl_flag_get(cdx, bus_num, dev_num, &flags);228if (ret)229return ret;230231flags = flags & (u32)(~(BIT(bit_pos)));232if (enable)233flags |= (1 << bit_pos);234235MCDI_SET_DWORD(inbuf, CDX_DEVICE_CONTROL_SET_IN_BUS, bus_num);236MCDI_SET_DWORD(inbuf, CDX_DEVICE_CONTROL_SET_IN_DEVICE, dev_num);237MCDI_SET_DWORD(inbuf, CDX_DEVICE_CONTROL_SET_IN_FLAGS, flags);238ret = cdx_mcdi_rpc(cdx, MC_CMD_CDX_DEVICE_CONTROL_SET, inbuf,239sizeof(inbuf), NULL, 0, NULL);240241return ret;242}243244int cdx_mcdi_bus_master_enable(struct cdx_mcdi *cdx, u8 bus_num,245u8 dev_num, bool enable)246{247return cdx_mcdi_ctrl_flag_set(cdx, bus_num, dev_num, enable,248MC_CMD_CDX_DEVICE_CONTROL_SET_IN_BUS_MASTER_ENABLE_LBN);249}250251int cdx_mcdi_msi_enable(struct cdx_mcdi *cdx, u8 bus_num,252u8 dev_num, bool enable)253{254return cdx_mcdi_ctrl_flag_set(cdx, bus_num, dev_num, enable,255MC_CMD_CDX_DEVICE_CONTROL_SET_IN_MSI_ENABLE_LBN);256}257258259