Commit 342e4c7e authored by Tomas Winkler's avatar Tomas Winkler Committed by Joonas Lahtinen
Browse files

mei: gsc: setup gsc extended operational memory



1. Retrieve extended operational memory physical pointers from the
   auxiliary device info.
2. Setup memory registers.
3. Notify firmware that the memory is ready by sending the memory
   ready command.
4. Disable PXP device if GSC is not in PXP mode.

CC: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
Signed-off-by: default avatarTomas Winkler <tomas.winkler@intel.com>
Signed-off-by: default avatarAlexander Usyskin <alexander.usyskin@intel.com>
Reviewed-by: default avatarDaniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
Signed-off-by: default avatarDaniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20220907215113.1596567-12-tomas.winkler@intel.com


Acked-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: default avatarJoonas Lahtinen <joonas.lahtinen@linux.intel.com>
Acked-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: default avatarJoonas Lahtinen <joonas.lahtinen@linux.intel.com>
parent fa313ede
Loading
Loading
Loading
Loading
+68 −2
Original line number Diff line number Diff line
@@ -188,6 +188,19 @@ static int mei_fwver(struct mei_cl_device *cldev)
	return ret;
}

static int mei_gfx_memory_ready(struct mei_cl_device *cldev)
{
	struct mkhi_gfx_mem_ready req = {0};
	unsigned int mode = MEI_CL_IO_TX_INTERNAL;

	req.hdr.group_id = MKHI_GROUP_ID_GFX;
	req.hdr.command = MKHI_GFX_MEMORY_READY_CMD_REQ;
	req.flags = MKHI_GFX_MEM_READY_PXP_ALLOWED;

	dev_dbg(&cldev->dev, "Sending memory ready command\n");
	return __mei_cl_send(cldev->cl, (u8 *)&req, sizeof(req), 0, mode);
}

static void mei_mkhi_fix(struct mei_cl_device *cldev)
{
	int ret;
@@ -234,6 +247,39 @@ static void mei_gsc_mkhi_ver(struct mei_cl_device *cldev)
		dev_err(&cldev->dev, "FW version command failed %d\n", ret);
	mei_cldev_disable(cldev);
}

static void mei_gsc_mkhi_fix_ver(struct mei_cl_device *cldev)
{
	int ret;

	/* No need to enable the client if nothing is needed from it */
	if (!cldev->bus->fw_f_fw_ver_supported &&
	    cldev->bus->pxp_mode != MEI_DEV_PXP_INIT)
		return;

	ret = mei_cldev_enable(cldev);
	if (ret)
		return;

	if (cldev->bus->pxp_mode == MEI_DEV_PXP_INIT) {
		ret = mei_gfx_memory_ready(cldev);
		if (ret < 0)
			dev_err(&cldev->dev, "memory ready command failed %d\n", ret);
		else
			dev_dbg(&cldev->dev, "memory ready command sent\n");
		/* we go to reset after that */
		cldev->bus->pxp_mode = MEI_DEV_PXP_SETUP;
		goto out;
	}

	ret = mei_fwver(cldev);
	if (ret < 0)
		dev_err(&cldev->dev, "FW version command failed %d\n",
			ret);
out:
	mei_cldev_disable(cldev);
}

/**
 * mei_wd - wd client on the bus, change protocol version
 *   as the API has changed.
@@ -473,6 +519,26 @@ static void vt_support(struct mei_cl_device *cldev)
		cldev->do_match = 1;
}

/**
 * pxp_is_ready - enable bus client if pxp is ready
 *
 * @cldev: me clients device
 */
static void pxp_is_ready(struct mei_cl_device *cldev)
{
	struct mei_device *bus = cldev->bus;

	switch (bus->pxp_mode) {
	case MEI_DEV_PXP_READY:
	case MEI_DEV_PXP_DEFAULT:
		cldev->do_match = 1;
	break;
	default:
		cldev->do_match = 0;
	break;
	}
}

#define MEI_FIXUP(_uuid, _hook) { _uuid, _hook }

static struct mei_fixup {
@@ -486,10 +552,10 @@ static struct mei_fixup {
	MEI_FIXUP(MEI_UUID_WD, mei_wd),
	MEI_FIXUP(MEI_UUID_MKHIF_FIX, mei_mkhi_fix),
	MEI_FIXUP(MEI_UUID_IGSC_MKHI, mei_gsc_mkhi_ver),
	MEI_FIXUP(MEI_UUID_IGSC_MKHI_FIX, mei_gsc_mkhi_ver),
	MEI_FIXUP(MEI_UUID_IGSC_MKHI_FIX, mei_gsc_mkhi_fix_ver),
	MEI_FIXUP(MEI_UUID_HDCP, whitelist),
	MEI_FIXUP(MEI_UUID_ANY, vt_support),
	MEI_FIXUP(MEI_UUID_PAVP, whitelist),
	MEI_FIXUP(MEI_UUID_PAVP, pxp_is_ready),
};

/**
+16 −0
Original line number Diff line number Diff line
@@ -32,6 +32,17 @@ static int mei_gsc_read_hfs(const struct mei_device *dev, int where, u32 *val)
	return 0;
}

static void mei_gsc_set_ext_op_mem(const struct mei_me_hw *hw, struct resource *mem)
{
	u32 low = lower_32_bits(mem->start);
	u32 hi  = upper_32_bits(mem->start);
	u32 limit = (resource_size(mem) / SZ_4K) | GSC_EXT_OP_MEM_VALID;

	iowrite32(low, hw->mem_addr + H_GSC_EXT_OP_MEM_BASE_ADDR_LO_REG);
	iowrite32(hi, hw->mem_addr + H_GSC_EXT_OP_MEM_BASE_ADDR_HI_REG);
	iowrite32(limit, hw->mem_addr + H_GSC_EXT_OP_MEM_LIMIT_REG);
}

static int mei_gsc_probe(struct auxiliary_device *aux_dev,
			 const struct auxiliary_device_id *aux_dev_id)
{
@@ -67,6 +78,11 @@ static int mei_gsc_probe(struct auxiliary_device *aux_dev,

	dev_set_drvdata(device, dev);

	if (adev->ext_op_mem.start) {
		mei_gsc_set_ext_op_mem(hw, &adev->ext_op_mem);
		dev->pxp_mode = MEI_DEV_PXP_INIT;
	}

	/* use polling */
	if (mei_me_hw_use_polling(hw)) {
		mei_disable_interrupts(dev);
+8 −1
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
 * Copyright (c) 2003-2019, Intel Corporation. All rights reserved.
 * Copyright (c) 2003-2022, Intel Corporation. All rights reserved.
 * Intel Management Engine Interface (Intel MEI) Linux driver
 */
#ifndef _MEI_HW_MEI_REGS_H_
@@ -125,6 +125,8 @@
#  define PCI_CFG_HFS_3_FW_SKU_SPS   0x00000060
#define PCI_CFG_HFS_4         0x64
#define PCI_CFG_HFS_5         0x68
#  define GSC_CFG_HFS_5_BOOT_TYPE_MSK      0x00000003
#  define GSC_CFG_HFS_5_BOOT_TYPE_PXP               3
#define PCI_CFG_HFS_6         0x6C

/* MEI registers */
@@ -141,6 +143,11 @@
/* H_D0I3C - D0I3 Control  */
#define H_D0I3C    0x800

#define H_GSC_EXT_OP_MEM_BASE_ADDR_LO_REG 0x100
#define H_GSC_EXT_OP_MEM_BASE_ADDR_HI_REG 0x104
#define H_GSC_EXT_OP_MEM_LIMIT_REG        0x108
#define GSC_EXT_OP_MEM_VALID              BIT(31)

/* register bits of H_CSR (Host Control Status register) */
/* Host Circular Buffer Depth - maximum number of 32-bit entries in CB */
#define H_CBD             0xFF000000
+27 −1
Original line number Diff line number Diff line
@@ -433,6 +433,29 @@ static bool mei_me_hw_is_resetting(struct mei_device *dev)
	return (mecsr & ME_RST_HRA) == ME_RST_HRA;
}

/**
 * mei_gsc_pxp_check - check for gsc firmware entering pxp mode
 *
 * @dev: the device structure
 */
static void mei_gsc_pxp_check(struct mei_device *dev)
{
	struct mei_me_hw *hw = to_me_hw(dev);
	u32 fwsts5 = 0;

	if (dev->pxp_mode == MEI_DEV_PXP_DEFAULT)
		return;

	hw->read_fws(dev, PCI_CFG_HFS_5, &fwsts5);
	trace_mei_pci_cfg_read(dev->dev, "PCI_CFG_HFS_5", PCI_CFG_HFS_5, fwsts5);
	if ((fwsts5 & GSC_CFG_HFS_5_BOOT_TYPE_MSK) == GSC_CFG_HFS_5_BOOT_TYPE_PXP) {
		dev_dbg(dev->dev, "pxp mode is ready 0x%08x\n", fwsts5);
		dev->pxp_mode = MEI_DEV_PXP_READY;
	} else {
		dev_dbg(dev->dev, "pxp mode is not ready 0x%08x\n", fwsts5);
	}
}

/**
 * mei_me_hw_ready_wait - wait until the me(hw) has turned ready
 *  or timeout is reached
@@ -452,6 +475,8 @@ static int mei_me_hw_ready_wait(struct mei_device *dev)
		return -ETIME;
	}

	mei_gsc_pxp_check(dev);

	mei_me_hw_reset_release(dev);
	dev->recvd_hw_ready = false;
	return 0;
@@ -1268,7 +1293,8 @@ irqreturn_t mei_me_irq_thread_handler(int irq, void *dev_id)

	/* check if ME wants a reset */
	if (!mei_hw_is_ready(dev) && dev->dev_state != MEI_DEV_RESETTING) {
		dev_warn(dev->dev, "FW not ready: resetting.\n");
		dev_warn(dev->dev, "FW not ready: resetting: dev_state = %d pxp = %d\n",
			 dev->dev_state, dev->pxp_mode);
		if (dev->dev_state == MEI_DEV_POWERING_DOWN ||
		    dev->dev_state == MEI_DEV_POWER_DOWN)
			mei_cl_all_disconnect(dev);
+2 −0
Original line number Diff line number Diff line
@@ -397,6 +397,8 @@ void mei_device_init(struct mei_device *dev,
	bitmap_zero(dev->host_clients_map, MEI_CLIENTS_MAX);
	dev->open_handle_count = 0;

	dev->pxp_mode = MEI_DEV_PXP_DEFAULT;

	/*
	 * Reserving the first client ID
	 * 0: Reserved for MEI Bus Message communications
Loading