lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20250313183440.261872-9-Raju.Rangoju@amd.com>
Date: Fri, 14 Mar 2025 00:04:38 +0530
From: Raju Rangoju <Raju.Rangoju@....com>
To: <broonie@...nel.org>, <linux-spi@...r.kernel.org>,
	<linux-kernel@...r.kernel.org>
CC: <Raju.Rangoju@....com>, <krishnamoorthi.m@....com>,
	<akshata.mukundshetty@....com>
Subject: [PATCH 08/10] spi: espi_amd: Add support for IO/MMIO configuration

Add support to configure the eSPI slave0 IO/MMIO address before
initiating the peripheral channel IO/MMIO read and write operations.
This patch introduces new IOCTLs to enable, disable and read IO/MMIO
configurations.

Co-developed-by: Krishnamoorthi M <krishnamoorthi.m@....com>
Signed-off-by: Krishnamoorthi M <krishnamoorthi.m@....com>
Co-developed-by: Akshata MukundShetty <akshata.mukundshetty@....com>
Signed-off-by: Akshata MukundShetty <akshata.mukundshetty@....com>
Signed-off-by: Raju Rangoju <Raju.Rangoju@....com>
---
 drivers/spi/espi-amd-core.c | 157 ++++++++++++++++++++++++++++++++++++
 drivers/spi/espi-amd-dev.c  |  53 ++++++++++++
 drivers/spi/espi-amd.h      |  91 +++++++++++++++++++++
 3 files changed, 301 insertions(+)

diff --git a/drivers/spi/espi-amd-core.c b/drivers/spi/espi-amd-core.c
index 72a625b8b16d..3704cbd816ae 100644
--- a/drivers/spi/espi-amd-core.c
+++ b/drivers/spi/espi-amd-core.c
@@ -553,6 +553,163 @@ int amd_espi_setup_vw_channel(struct amd_espi *amd_espi, u32 slave_caps)
 			CHANNEL_MODE_VW);
 }
 
+void amd_espi_get_io_mmio_decode_info(struct amd_espi *amd_espi,
+				      struct io_mmio_decode_config *config)
+{
+	config->io_mmio_dc_enable = readl(ESPI_BASE + AMD_ESPI_SLAVE0_DECODE_EN_REG);
+	config->range0.val = readl(ESPI_BASE + AMD_ESPI_SLAVE0_IO_BASE_REG0_REG);
+	config->range1.val = readl(ESPI_BASE + AMD_ESPI_SLAVE0_IO_BASE_REG1_REG);
+	config->range2.val = readl(ESPI_BASE + AMD_ESPI_SLAVE0_IO_SIZE_REG);
+	config->mmio_target_range0 = readl(ESPI_BASE + AMD_ESPI_SLAVE0_MMIO_BASE_REG0);
+	config->mmio_target_range1 = readl(ESPI_BASE + AMD_ESPI_SLAVE0_MMIO_BASE_REG1);
+	config->mmio_target_range2 = readl(ESPI_BASE + AMD_ESPI_SLAVE0_MMIO_BASE_REG2);
+	config->mmio_target_range3 = readl(ESPI_BASE + AMD_ESPI_SLAVE0_MMIO_BASE_REG3);
+	config->mmio_range4.val = readl(ESPI_BASE + AMD_ESPI_SLAVE0_MMIO_SIZE_REG0);
+	config->mmio_range5.val = readl(ESPI_BASE + AMD_ESPI_SLAVE0_MMIO_SIZE_REG1);
+}
+
+void amd_espi_set_io_mmio_decode_config(struct amd_espi *amd_espi,
+					struct io_mmio_decode_config *config)
+{
+	struct io_mmio_decode_config io_dc_conf;
+
+	amd_espi_get_io_mmio_decode_info(amd_espi, &io_dc_conf);
+	writel(((~(config->io_mmio_dc_enable) & io_dc_conf.io_mmio_dc_enable) |
+		config->io_mmio_dc_enable), (ESPI_BASE + AMD_ESPI_SLAVE0_DECODE_EN_REG));
+
+	/* IO RANGE-0 configuration */
+	if (config->io_mmio_dc_enable & IO_DECODE_RANGE0) {
+		if (config->range0.base_addr_range0 != io_dc_conf.range0.base_addr_range0) {
+			writel(((io_dc_conf.range0.val & CNTRL_IO_DECODE_ADDR_MASK(0)) |
+				config->range0.val),
+				(ESPI_BASE + AMD_ESPI_SLAVE0_IO_BASE_REG0_REG));
+			writel(((io_dc_conf.range2.val & CNTRL_IO_DECODE_SIZE_MASK(0)) |
+				config->range2.val), (ESPI_BASE + AMD_ESPI_SLAVE0_IO_SIZE_REG));
+		}
+	}
+
+	/* IO RANGE-1 configuration */
+	if (config->io_mmio_dc_enable & IO_DECODE_RANGE1) {
+		if (config->range0.base_addr_range1 != io_dc_conf.range0.base_addr_range1) {
+			writel(((io_dc_conf.range0.val & CNTRL_IO_DECODE_ADDR_MASK(16)) |
+				config->range0.val),
+				(ESPI_BASE + AMD_ESPI_SLAVE0_IO_BASE_REG0_REG));
+			writel(((io_dc_conf.range2.val & CNTRL_IO_DECODE_SIZE_MASK(8)) |
+				config->range2.val), (ESPI_BASE + AMD_ESPI_SLAVE0_IO_SIZE_REG));
+		}
+	}
+
+	/* IO RANGE-2 configuration */
+	if (config->io_mmio_dc_enable & IO_DECODE_RANGE2) {
+		if (config->range1.base_addr_range2 != io_dc_conf.range1.base_addr_range2) {
+			writel(((io_dc_conf.range1.val & CNTRL_IO_DECODE_ADDR_MASK(0)) |
+				config->range1.val),
+				(ESPI_BASE + AMD_ESPI_SLAVE0_IO_BASE_REG1_REG));
+			writel(((io_dc_conf.range2.val & CNTRL_IO_DECODE_SIZE_MASK(16)) |
+				config->range2.val), (ESPI_BASE + AMD_ESPI_SLAVE0_IO_SIZE_REG));
+		}
+	}
+
+	/* IO RANGE-3 configuration */
+	if (config->io_mmio_dc_enable & IO_DECODE_RANGE3) {
+		if (config->range1.base_addr_range3 != io_dc_conf.range1.base_addr_range3) {
+			writel(((io_dc_conf.range1.val & CNTRL_IO_DECODE_ADDR_MASK(16)) |
+				config->range1.val),
+				(ESPI_BASE + AMD_ESPI_SLAVE0_IO_BASE_REG1_REG));
+			writel(((io_dc_conf.range2.val & CNTRL_IO_DECODE_SIZE_MASK(24)) |
+				config->range2.val), (ESPI_BASE + AMD_ESPI_SLAVE0_IO_SIZE_REG));
+		}
+	}
+
+	/* MMIO RANGE-0 configure */
+	if (config->io_mmio_dc_enable & MMIO_DECODE_RANGE0) {
+		if (config->mmio_target_range0 != io_dc_conf.mmio_target_range0) {
+			writel(config->mmio_target_range0,
+			       (ESPI_BASE + AMD_ESPI_SLAVE0_MMIO_BASE_REG0));
+			writel(((io_dc_conf.mmio_range4.val & CNTRL_MMIO_DECODE_SIZE_MASK(0)) |
+				config->mmio_range4.val),
+				(ESPI_BASE + AMD_ESPI_SLAVE0_MMIO_SIZE_REG0));
+		}
+	}
+
+	/* MMIO RANGE-1 configure */
+	if (config->io_mmio_dc_enable & MMIO_DECODE_RANGE1) {
+		if (config->mmio_target_range1 != io_dc_conf.mmio_target_range1) {
+			writel(config->mmio_target_range1,
+			       (ESPI_BASE + AMD_ESPI_SLAVE0_MMIO_BASE_REG1));
+			writel(((io_dc_conf.mmio_range4.val & CNTRL_MMIO_DECODE_SIZE_MASK(16)) |
+				config->mmio_range4.val),
+				(ESPI_BASE + AMD_ESPI_SLAVE0_MMIO_SIZE_REG0));
+		}
+	}
+
+	/* MMIO RANGE-2 configure */
+	if (config->io_mmio_dc_enable & MMIO_DECODE_RANGE2) {
+		if (config->mmio_target_range2 != io_dc_conf.mmio_target_range2) {
+			writel(config->mmio_target_range2,
+			       (ESPI_BASE + AMD_ESPI_SLAVE0_MMIO_BASE_REG2));
+			writel(((io_dc_conf.mmio_range5.val & CNTRL_MMIO_DECODE_SIZE_MASK(0)) |
+				config->mmio_range5.val),
+				(ESPI_BASE + AMD_ESPI_SLAVE0_MMIO_SIZE_REG1));
+		}
+	}
+
+	/* MMIO RANGE-3 configure */
+	if (config->io_mmio_dc_enable & MMIO_DECODE_RANGE3) {
+		if (config->mmio_target_range3 != io_dc_conf.mmio_target_range3) {
+			writel(config->mmio_target_range3,
+			       (ESPI_BASE + AMD_ESPI_SLAVE0_MMIO_BASE_REG3));
+			writel(((io_dc_conf.mmio_range5.val & CNTRL_MMIO_DECODE_SIZE_MASK(16)) |
+				config->mmio_range5.val),
+				(ESPI_BASE + AMD_ESPI_SLAVE0_MMIO_SIZE_REG1));
+		}
+	}
+}
+
+void amd_espi_disable_io_decode_range(struct amd_espi *amd_espi, u32 io_range)
+{
+	u32 io_mmio_dc_enable = readl(ESPI_BASE + AMD_ESPI_SLAVE0_DECODE_EN_REG);
+
+	switch (io_range) {
+	case 1:
+		if (io_mmio_dc_enable & IO_DECODE_RANGE0)
+			io_mmio_dc_enable = io_mmio_dc_enable ^ IO_DECODE_RANGE0;
+		break;
+	case 2:
+		if (io_mmio_dc_enable & IO_DECODE_RANGE1)
+			io_mmio_dc_enable = io_mmio_dc_enable ^ IO_DECODE_RANGE1;
+		break;
+	case 3:
+		if (io_mmio_dc_enable & IO_DECODE_RANGE2)
+			io_mmio_dc_enable = io_mmio_dc_enable ^ IO_DECODE_RANGE2;
+		break;
+	case 4:
+		if (io_mmio_dc_enable & IO_DECODE_RANGE3)
+			io_mmio_dc_enable = io_mmio_dc_enable ^ IO_DECODE_RANGE3;
+		break;
+	case 5:
+		if (io_mmio_dc_enable & MMIO_DECODE_RANGE0)
+			io_mmio_dc_enable = io_mmio_dc_enable ^ MMIO_DECODE_RANGE0;
+		break;
+	case 6:
+		if (io_mmio_dc_enable & MMIO_DECODE_RANGE1)
+			io_mmio_dc_enable = io_mmio_dc_enable ^ MMIO_DECODE_RANGE1;
+		break;
+	case 7:
+		if (io_mmio_dc_enable & MMIO_DECODE_RANGE2)
+			io_mmio_dc_enable = io_mmio_dc_enable ^ MMIO_DECODE_RANGE2;
+		break;
+	case 8:
+		if (io_mmio_dc_enable & MMIO_DECODE_RANGE3)
+			io_mmio_dc_enable = io_mmio_dc_enable ^ MMIO_DECODE_RANGE3;
+		break;
+	default:
+		break;
+	}
+
+	writel(io_mmio_dc_enable, (ESPI_BASE + AMD_ESPI_SLAVE0_DECODE_EN_REG));
+}
+
 static int amd_espi_get_master_cap(struct amd_espi *amd_espi, struct espi_master *master)
 {
 	u32 master_cap_reg, info;
diff --git a/drivers/spi/espi-amd-dev.c b/drivers/spi/espi-amd-dev.c
index 9f1968566980..31fb06f4a3ff 100644
--- a/drivers/spi/espi-amd-dev.c
+++ b/drivers/spi/espi-amd-dev.c
@@ -286,9 +286,49 @@ static int amd_espi_ioctl_set_freq(struct amd_espi *amd_espi, unsigned long arg)
 	return ret;
 }
 
+static int amd_espi_ioctl_get_io_decode_conf(struct amd_espi *amd_espi, unsigned long arg)
+{
+	struct io_mmio_decode_config *io_dc_config;
+	int ret = 0;
+
+	io_dc_config = kzalloc(sizeof(*io_dc_config), GFP_KERNEL);
+	if (!io_dc_config)
+		return -ENOMEM;
+
+	amd_espi_get_io_mmio_decode_info(amd_espi, io_dc_config);
+
+	if (copy_to_user((void __user *)arg, io_dc_config, sizeof(struct io_mmio_decode_config)))
+		ret = -EFAULT;
+
+	kfree(io_dc_config);
+	return ret;
+}
+
+static int amd_espi_ioctl_enable_io_decode_conf(struct amd_espi *amd_espi, unsigned long arg)
+{
+	struct io_mmio_decode_config *io_dc_config;
+	int ret = 0;
+
+	io_dc_config = kzalloc(sizeof(*io_dc_config), GFP_KERNEL);
+	if (!io_dc_config)
+		return -ENOMEM;
+
+	if (copy_from_user(io_dc_config, (void __user *)arg,
+			   sizeof(struct io_mmio_decode_config))) {
+		ret = -EFAULT;
+		goto decode_config_free;
+	}
+	amd_espi_set_io_mmio_decode_config(amd_espi, io_dc_config);
+
+decode_config_free:
+	kfree(io_dc_config);
+	return ret;
+}
+
 static long amd_espi_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 {
 	struct amd_espi *amd_espi = filp->private_data;
+	u32 io_range = 0;
 	int ret = 0;
 
 	/* Check type and command number */
@@ -316,6 +356,19 @@ static long amd_espi_ioctl(struct file *filp, unsigned int cmd, unsigned long ar
 	case  ESPI_SET_FREQ:
 		ret = amd_espi_ioctl_set_freq(amd_espi, arg);
 		break;
+	case ESPI_GET_IODECODE_CONFIG:
+		ret = amd_espi_ioctl_get_io_decode_conf(amd_espi, arg);
+		break;
+	case ESPI_EN_IODECODE_CONFIG:
+		ret = amd_espi_ioctl_enable_io_decode_conf(amd_espi, arg);
+		break;
+	case ESPI_DS_IODECODE_CONFIG:
+		if (copy_from_user(&io_range, (void __user *)arg, sizeof(unsigned int))) {
+			ret = -EFAULT;
+			break;
+		}
+		amd_espi_disable_io_decode_range(amd_espi, io_range);
+		break;
 	default:
 		dev_err(amd_espi->dev, "ESPI command not found, returning error\n");
 		ret = -EINVAL;
diff --git a/drivers/spi/espi-amd.h b/drivers/spi/espi-amd.h
index e5760db7c1d3..ae76243786f0 100644
--- a/drivers/spi/espi-amd.h
+++ b/drivers/spi/espi-amd.h
@@ -33,6 +33,19 @@
 #define AMD_ESPI_MISC_CNTRL_REG0	0x38
 #define AMD_ESPI_MISC_CNTRL_REG1	0x3c
 
+/* Slave-0 registers IO and MMIO config registers */
+#define AMD_ESPI_SLAVE0_DECODE_EN_REG		0x40
+#define AMD_ESPI_SLAVE0_IO_BASE_REG0_REG	0x44
+#define AMD_ESPI_SLAVE0_IO_BASE_REG1_REG	0x48
+#define AMD_ESPI_SLAVE0_IO_SIZE_REG		0x4C
+#define AMD_ESPI_SLAVE0_MMIO_BASE_REG0		0x50
+#define AMD_ESPI_SLAVE0_MMIO_BASE_REG1		0x54
+#define AMD_ESPI_SLAVE0_MMIO_BASE_REG2		0x58
+#define AMD_ESPI_SLAVE0_MMIO_BASE_REG3		0x5C
+#define AMD_ESPI_SLAVE0_MMIO_SIZE_REG0		0x60
+#define AMD_ESPI_SLAVE0_MMIO_SIZE_REG1		0x64
+#define AMD_ESPI_MMIO_ADDR_LEN			4
+
 /* Slave-0 configuration and interrupt registers */
 #define AMD_ESPI_SLAVE0_CONFIG_REG		0x68
 #define AMD_ESPI_SLAVE0_INT_EN_REG		0x6C
@@ -136,6 +149,20 @@
 #define ESPI_CNTRL_SET_OP_FREQ(conf, freq) (((conf) & ESPI_CNTRL_OP_MODE_MASK) |\
 					    ((freq) << ESPI_CNTRL_SLAVE0_FREQ_SHIFT))
 
+/* Slave-0 IO and MMIO decode enable configurations */
+#define IO_DECODE_RANGE0	BIT(8)
+#define IO_DECODE_RANGE1	BIT(9)
+#define IO_DECODE_RANGE2	BIT(10)
+#define IO_DECODE_RANGE3	BIT(11)
+#define MMIO_DECODE_RANGE0	BIT(12)
+#define MMIO_DECODE_RANGE1	BIT(13)
+#define MMIO_DECODE_RANGE2	BIT(14)
+#define MMIO_DECODE_RANGE3	BIT(15)
+
+#define CNTRL_IO_DECODE_ADDR_MASK(val)   (~(GENMASK(15, 0) << (val)))
+#define CNTRL_IO_DECODE_SIZE_MASK(val)   (~(GENMASK(3, 0) << (val)))
+#define CNTRL_MMIO_DECODE_SIZE_MASK(val) (~(GENMASK(15, 0) << (val)))
+
 #define ESPI_BASE		((u8 __iomem *)amd_espi->io_remap_addr)
 
 /* IOCTL calls */
@@ -146,6 +173,9 @@
 #define ESPI_SET_IO_MODE             _IOW(ESPI_MAGIC_NUMBER, 0x4, struct config)
 #define ESPI_SET_CHAN_MODE           _IOW(ESPI_MAGIC_NUMBER, 0x5, struct config)
 #define ESPI_SET_FREQ                _IOW(ESPI_MAGIC_NUMBER, 0x6, struct config)
+#define ESPI_GET_IODECODE_CONFIG     _IOWR(ESPI_MAGIC_NUMBER, 0x7, struct io_mmio_decode_config)
+#define ESPI_EN_IODECODE_CONFIG      _IOWR(ESPI_MAGIC_NUMBER, 0x8, struct io_mmio_decode_config)
+#define ESPI_DS_IODECODE_CONFIG      _IOWR(ESPI_MAGIC_NUMBER, 0x9, u32)
 
 /*
  * enum amd_espi_versions - eSPI controller versions
@@ -282,6 +312,62 @@ struct espi_txcmd {
 	u32 expected_status_codes;
 };
 
+/* IO/MMIO decode configuartions */
+union io_target_range0 {
+	u32 val;
+	struct {
+		u16 base_addr_range0;
+		u16 base_addr_range1;
+	};
+};
+
+union io_target_range1 {
+	u32 val;
+	struct {
+		u16 base_addr_range2;
+		u16 base_addr_range3;
+	};
+};
+
+union io_target_range2 {
+	u32 val;
+	struct {
+		u32 io_range0_size:8;
+		u32 io_range1_size:8;
+		u32 io_range2_size:8;
+		u32 io_range3_size:8;
+	};
+};
+
+union mmio_target_range4 {
+	u32 val;
+	struct {
+		u32 mmio_range0_size : 16;
+		u32 mmio_range1_size : 16;
+	};
+};
+
+union mmio_target_range5 {
+	u32 val;
+	struct {
+		u32 mmio_range2_size : 16;
+		u32 mmio_range3_size : 16;
+	};
+};
+
+struct io_mmio_decode_config {
+	u32 io_mmio_dc_enable;
+	union io_target_range0 range0;
+	union io_target_range1 range1;
+	union io_target_range2 range2;
+	u32 mmio_target_range0;
+	u32 mmio_target_range1;
+	u32 mmio_target_range2;
+	u32 mmio_target_range3;
+	union mmio_target_range4 mmio_range4;
+	union mmio_target_range5 mmio_range5;
+};
+
 /* Function prototypes */
 int amd_espi_device_create(struct amd_espi *amd_espi, struct device *dev);
 void amd_espi_device_remove(struct amd_espi *amd_espi);
@@ -297,4 +383,9 @@ int amd_espi_get_channel_config(struct amd_espi *amd_espi);
 int amd_espi_setup_periph_channel(struct amd_espi *amd_espi, u32 slave_caps);
 int amd_espi_setup_vw_channel(struct amd_espi *amd_espi, u32 slave_caps);
 void amd_espi_clr_all_intr(struct amd_espi *amd_espi);
+void amd_espi_get_io_mmio_decode_info(struct amd_espi *amd_espi,
+				      struct io_mmio_decode_config *config);
+void amd_espi_set_io_mmio_decode_config(struct amd_espi *amd_espi,
+					struct io_mmio_decode_config *config);
+void amd_espi_disable_io_decode_range(struct amd_espi *amd_espi, u32 io_range);
 #endif
-- 
2.34.1


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ