2022-06-17 02:22:27

by Zhang, Tianfei

[permalink] [raw]
Subject: [PATCH v2 0/4] add PMCI driver support

PMCI(Platform Management Control Interface) is a software-visible
interface, connected to card BMC which provided telemetry and mailbox
functionalities for Intel PAC FPGA card.

Currently, intel-m10-bmc driver support Intel MAX10 BMC functions via
SPI interface. To support multiple bus interfaces, splits the common
code from intel-m10-bmc driver into intel-m10-bmc-core. On the other
hand, it leverages the regmap APIs to support Intel specific Indirect
Register Interface for register read/write on PMCI driver.

This patchset adding a driver for the PMCI-base interface of Intel MAX10
BMC controller.

patch 1: use ddata for local variables which directly interacts with
dev_get_drvdata()/dev_set_drvdata().
patch 2: split the common code from intel-m10-bmc driver into
intel-m10-bmc-core.
patch 3: add a driver for PMCI.
patch 4: introduce a new data structure m10bmc_csr for the different
register definition of MAX10 CSRs.

v2:
- use regmap APIs to support Intel specific Indirect Register Interface
on PMCI driver.
- fix compile warning reported by lkp.
- rebased on 5.19-rc2

Tianfei Zhang (4):
mfd: intel-m10-bmc: rename the local variables
mfd: intel-m10-bmc: split into core and spi
mfd: intel-m10-bmc: add PMCI driver
mfd: intel-m10-bmc: support multiple register layouts

.../ABI/testing/sysfs-driver-intel-m10-bmc | 8 +-
drivers/mfd/Kconfig | 34 +++-
drivers/mfd/Makefile | 6 +-
.../{intel-m10-bmc.c => intel-m10-bmc-core.c} | 148 ++++++--------
drivers/mfd/intel-m10-bmc-pmci.c | 190 ++++++++++++++++++
drivers/mfd/intel-m10-bmc-spi.c | 83 ++++++++
include/linux/mfd/intel-m10-bmc.h | 43 +++-
7 files changed, 413 insertions(+), 99 deletions(-)
rename drivers/mfd/{intel-m10-bmc.c => intel-m10-bmc-core.c} (56%)
create mode 100644 drivers/mfd/intel-m10-bmc-pmci.c
create mode 100644 drivers/mfd/intel-m10-bmc-spi.c

--
2.26.2


2022-06-17 02:22:27

by Zhang, Tianfei

[permalink] [raw]
Subject: [PATCH v2 3/4] mfd: intel-m10-bmc: add PMCI driver

Adding a driver for the PMCI-base interface of Intel MAX10
BMC controller.

PMCI(Platform Management Control Interface) is a software-visible
interface, connected to card BMC which provided telemetry and mailbox
functionalities. On the other hand, this driver leverages the regmap
APIs to support Intel specific Indirect Register Interface for register
read/write on PMCI.

Signed-off-by: Tianfei Zhang <[email protected]>
Signed-off-by: Russ Weight <[email protected]>
Signed-off-by: Matthew Gerlach <[email protected]>
---
v2:
- fix compile warning reported by lkp
- use regmap API for Indirect Register Interface.
---
.../ABI/testing/sysfs-driver-intel-m10-bmc | 8 +-
drivers/mfd/Kconfig | 12 ++
drivers/mfd/Makefile | 1 +
drivers/mfd/intel-m10-bmc-core.c | 19 +-
drivers/mfd/intel-m10-bmc-pmci.c | 190 ++++++++++++++++++
include/linux/mfd/intel-m10-bmc.h | 8 +
6 files changed, 230 insertions(+), 8 deletions(-)
create mode 100644 drivers/mfd/intel-m10-bmc-pmci.c

diff --git a/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc b/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc
index 9773925138af..a8ab58035c95 100644
--- a/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc
+++ b/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc
@@ -1,4 +1,4 @@
-What: /sys/bus/spi/devices/.../bmc_version
+What: /sys/bus/.../drivers/intel-m10-bmc/.../bmc_version
Date: June 2020
KernelVersion: 5.10
Contact: Xu Yilun <[email protected]>
@@ -6,7 +6,7 @@ Description: Read only. Returns the hardware build version of Intel
MAX10 BMC chip.
Format: "0x%x".

-What: /sys/bus/spi/devices/.../bmcfw_version
+What: /sys/bus/.../drivers/intel-m10-bmc/.../bmcfw_version
Date: June 2020
KernelVersion: 5.10
Contact: Xu Yilun <[email protected]>
@@ -14,7 +14,7 @@ Description: Read only. Returns the firmware version of Intel MAX10
BMC chip.
Format: "0x%x".

-What: /sys/bus/spi/devices/.../mac_address
+What: /sys/bus/.../drivers/intel-m10-bmc/.../mac_address
Date: January 2021
KernelVersion: 5.12
Contact: Russ Weight <[email protected]>
@@ -25,7 +25,7 @@ Description: Read only. Returns the first MAC address in a block
space.
Format: "%02x:%02x:%02x:%02x:%02x:%02x".

-What: /sys/bus/spi/devices/.../mac_count
+What: /sys/bus/.../drivers/intel-m10-bmc/.../mac_count
Date: January 2021
KernelVersion: 5.12
Contact: Russ Weight <[email protected]>
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index ee8398b02321..7300efec3617 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -2177,6 +2177,18 @@ config MFD_INTEL_M10_BMC_SPI
additional drivers must be enabled in order to use the functionality
of the device.

+config MFD_INTEL_M10_BMC_PMCI
+ tristate "Intel MAX 10 Board Management Controller with PMCI"
+ depends on FPGA_DFL
+ select MFD_INTEL_M10_BMC_CORE
+ select REGMAP_INDIRECT_REGISTER
+ help
+ Support for the Intel MAX 10 board management controller via PMCI.
+
+ This driver provides common support for accessing the device,
+ additional drivers must be enabled in order to use the functionality
+ of the device.
+
config MFD_RSMU_I2C
tristate "Renesas Synchronization Management Unit with I2C"
depends on I2C && OF
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index b5d3263c1205..a8ffdc223cf7 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -270,6 +270,7 @@ obj-$(CONFIG_MFD_SIMPLE_MFD_I2C) += simple-mfd-i2c.o
intel-m10-bmc-objs := intel-m10-bmc-core.o
obj-$(CONFIG_MFD_INTEL_M10_BMC_CORE) += intel-m10-bmc.o
obj-$(CONFIG_MFD_INTEL_M10_BMC_SPI) += intel-m10-bmc-spi.o
+obj-$(CONFIG_MFD_INTEL_M10_BMC_PMCI) += intel-m10-bmc-pmci.o

obj-$(CONFIG_MFD_ATC260X) += atc260x-core.o
obj-$(CONFIG_MFD_ATC260X_I2C) += atc260x-i2c.o
diff --git a/drivers/mfd/intel-m10-bmc-core.c b/drivers/mfd/intel-m10-bmc-core.c
index f6dc549e1bc3..c6a1a4c28357 100644
--- a/drivers/mfd/intel-m10-bmc-core.c
+++ b/drivers/mfd/intel-m10-bmc-core.c
@@ -10,6 +10,11 @@
#include <linux/mfd/intel-m10-bmc.h>
#include <linux/module.h>

+static struct mfd_cell m10bmc_n6000_bmc_subdevs[] = {
+ { .name = "n6000bmc-hwmon" },
+ { .name = "n6000bmc-sec-update" }
+};
+
static struct mfd_cell m10bmc_d5005_subdevs[] = {
{ .name = "d5005bmc-hwmon" },
};
@@ -146,10 +151,12 @@ int m10bmc_dev_init(struct intel_m10bmc *m10bmc)

dev_set_drvdata(m10bmc->dev, m10bmc);

- ret = check_m10bmc_version(m10bmc);
- if (ret) {
- dev_err(m10bmc->dev, "Failed to identify m10bmc hardware\n");
- return ret;
+ if (type == M10_N3000 || type == M10_D5005 || type == M10_N5010) {
+ ret = check_m10bmc_version(m10bmc);
+ if (ret) {
+ dev_err(m10bmc->dev, "Failed to identify m10bmc hardware\n");
+ return ret;
+ }
}

switch (type) {
@@ -165,6 +172,10 @@ int m10bmc_dev_init(struct intel_m10bmc *m10bmc)
cells = m10bmc_n5010_subdevs;
n_cell = ARRAY_SIZE(m10bmc_n5010_subdevs);
break;
+ case M10_N6000:
+ cells = m10bmc_n6000_bmc_subdevs;
+ n_cell = ARRAY_SIZE(m10bmc_n6000_bmc_subdevs);
+ break;
default:
return -ENODEV;
}
diff --git a/drivers/mfd/intel-m10-bmc-pmci.c b/drivers/mfd/intel-m10-bmc-pmci.c
new file mode 100644
index 000000000000..249a2db5e742
--- /dev/null
+++ b/drivers/mfd/intel-m10-bmc-pmci.c
@@ -0,0 +1,190 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * PMCI-based interface to MAX10 BMC
+ *
+ * Copyright (C) 2020-2022 Intel Corporation, Inc.
+ *
+ */
+
+#include <linux/dfl.h>
+#include <linux/mfd/intel-m10-bmc.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+
+#define M10BMC_PMCI_INDIRECT_BASE 0x400
+#define INDIRECT_INT_US 1
+#define INDIRECT_TIMEOUT_US 10000
+
+#define INDIRECT_CMD_OFF 0x0
+#define INDIRECT_CMD_RD BIT(0)
+#define INDIRECT_CMD_WR BIT(1)
+#define INDIRECT_CMD_ACK BIT(2)
+
+#define INDIRECT_ADDR_OFF 0x4
+#define INDIRECT_RD_OFF 0x8
+#define INDIRECT_WR_OFF 0xc
+
+struct indirect_ctx {
+ void __iomem *base;
+ struct device *dev;
+ unsigned long sleep_us;
+ unsigned long timeout_us;
+};
+
+struct pmci_device {
+ void __iomem *base;
+ struct device *dev;
+ struct intel_m10bmc m10bmc;
+ struct indirect_ctx ctx;
+};
+
+static int pmci_indirect_bus_clr_cmd(struct indirect_ctx *ctx)
+{
+ unsigned int cmd;
+ int ret;
+
+ writel(0, ctx->base + INDIRECT_CMD_OFF);
+ ret = readl_poll_timeout((ctx->base + INDIRECT_CMD_OFF), cmd,
+ (!cmd), ctx->sleep_us, ctx->timeout_us);
+ if (ret)
+ dev_err(ctx->dev, "%s timed out on clearing cmd 0x%xn", __func__, cmd);
+
+ return ret;
+}
+
+static int pmci_indirect_bus_reg_read(void *context, unsigned int reg,
+ unsigned int *val)
+{
+ struct indirect_ctx *ctx = context;
+ unsigned int cmd;
+ int ret;
+
+ cmd = readl(ctx->base + INDIRECT_CMD_OFF);
+ if (cmd)
+ dev_warn(ctx->dev, "%s non-zero cmd 0x%x\n", __func__, cmd);
+
+ writel(reg, ctx->base + INDIRECT_ADDR_OFF);
+ writel(INDIRECT_CMD_RD, ctx->base + INDIRECT_CMD_OFF);
+ ret = readl_poll_timeout((ctx->base + INDIRECT_CMD_OFF), cmd,
+ (cmd & INDIRECT_CMD_ACK), ctx->sleep_us,
+ ctx->timeout_us);
+ if (ret) {
+ dev_err(ctx->dev, "%s timed out on reg 0x%x cmd 0x%x\n", __func__, reg, cmd);
+ goto out;
+ }
+
+ *val = readl(ctx->base + INDIRECT_RD_OFF);
+
+ if (pmci_indirect_bus_clr_cmd(ctx))
+ ret = -ETIMEDOUT;
+
+out:
+ return ret;
+}
+
+static int pmci_indirect_bus_reg_write(void *context, unsigned int reg,
+ unsigned int val)
+{
+ struct indirect_ctx *ctx = context;
+ unsigned int cmd;
+ int ret;
+
+ cmd = readl(ctx->base + INDIRECT_CMD_OFF);
+ if (cmd)
+ dev_warn(ctx->dev, "%s non-zero cmd 0x%x\n", __func__, cmd);
+
+ writel(val, ctx->base + INDIRECT_WR_OFF);
+ writel(reg, ctx->base + INDIRECT_ADDR_OFF);
+ writel(INDIRECT_CMD_WR, ctx->base + INDIRECT_CMD_OFF);
+ ret = readl_poll_timeout((ctx->base + INDIRECT_CMD_OFF), cmd,
+ (cmd & INDIRECT_CMD_ACK), ctx->sleep_us,
+ ctx->timeout_us);
+ if (ret) {
+ dev_err(ctx->dev, "%s timed out on reg 0x%x cmd 0x%x\n", __func__, reg, cmd);
+ goto out;
+ }
+
+ if (pmci_indirect_bus_clr_cmd(ctx))
+ ret = -ETIMEDOUT;
+
+out:
+ return ret;
+}
+
+static const struct regmap_bus pmci_indirect_bus = {
+ .reg_write = pmci_indirect_bus_reg_write,
+ .reg_read = pmci_indirect_bus_reg_read,
+};
+
+static const struct regmap_range m10bmc_pmci_regmap_range[] = {
+ regmap_reg_range(M10BMC_PMCI_SYS_BASE, M10BMC_PMCI_SYS_END),
+};
+
+static const struct regmap_access_table m10_access_table = {
+ .yes_ranges = m10bmc_pmci_regmap_range,
+ .n_yes_ranges = ARRAY_SIZE(m10bmc_pmci_regmap_range),
+};
+
+static struct regmap_config m10bmc_pmci_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .wr_table = &m10_access_table,
+ .rd_table = &m10_access_table,
+ .max_register = M10BMC_PMCI_SYS_END,
+};
+
+static int pmci_probe(struct dfl_device *ddev)
+{
+ struct device *dev = &ddev->dev;
+ struct pmci_device *pmci;
+
+ pmci = devm_kzalloc(dev, sizeof(*pmci), GFP_KERNEL);
+ if (!pmci)
+ return -ENOMEM;
+
+ pmci->m10bmc.dev = dev;
+ pmci->dev = dev;
+ pmci->m10bmc.type = M10_N6000;
+
+ pmci->base = devm_ioremap_resource(dev, &ddev->mmio_res);
+ if (IS_ERR(pmci->base))
+ return PTR_ERR(pmci->base);
+
+ pmci->ctx.base = pmci->base + M10BMC_PMCI_INDIRECT_BASE;
+ pmci->ctx.sleep_us = INDIRECT_INT_US;
+ pmci->ctx.timeout_us = INDIRECT_TIMEOUT_US;
+ pmci->ctx.dev = dev;
+ pmci->m10bmc.regmap =
+ devm_regmap_init(dev,
+ &pmci_indirect_bus,
+ &pmci->ctx,
+ &m10bmc_pmci_regmap_config);
+ if (IS_ERR(pmci->m10bmc.regmap))
+ return PTR_ERR(pmci->m10bmc.regmap);
+
+ return m10bmc_dev_init(&pmci->m10bmc);
+}
+
+#define FME_FEATURE_ID_PMCI_BMC 0x12
+
+static const struct dfl_device_id pmci_ids[] = {
+ { FME_ID, FME_FEATURE_ID_PMCI_BMC },
+ { }
+};
+MODULE_DEVICE_TABLE(dfl, pmci_ids);
+
+static struct dfl_driver pmci_driver = {
+ .drv = {
+ .name = "dfl-pmci-bmc",
+ .dev_groups = m10bmc_dev_groups,
+ },
+ .id_table = pmci_ids,
+ .probe = pmci_probe,
+};
+
+module_dfl_driver(pmci_driver);
+
+MODULE_DESCRIPTION("MAX10 BMC PMCI-based interface");
+MODULE_AUTHOR("Intel Corporation");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/mfd/intel-m10-bmc.h b/include/linux/mfd/intel-m10-bmc.h
index dd81ffdcf168..83c4d3993dcb 100644
--- a/include/linux/mfd/intel-m10-bmc.h
+++ b/include/linux/mfd/intel-m10-bmc.h
@@ -118,11 +118,19 @@
/* Address of 4KB inverted bit vector containing staging area FLASH count */
#define STAGING_FLASH_COUNT 0x17ffb000

+#define M10BMC_PMCI_SYS_BASE 0x0
+#define M10BMC_PMCI_SYS_END 0xfff
+
+/* Telemetry registers */
+#define M10BMC_PMCI_TELEM_START 0x400
+#define M10BMC_PMCI_TELEM_END 0x78c
+
/* Supported MAX10 BMC types */
enum m10bmc_type {
M10_N3000,
M10_D5005,
M10_N5010,
+ M10_N6000
};

/**
--
2.26.2

2022-06-20 12:06:53

by Xu Yilun

[permalink] [raw]
Subject: Re: [PATCH v2 3/4] mfd: intel-m10-bmc: add PMCI driver

On Thu, Jun 16, 2022 at 10:04:04PM -0400, Tianfei Zhang wrote:
> Adding a driver for the PMCI-base interface of Intel MAX10
> BMC controller.
>
> PMCI(Platform Management Control Interface) is a software-visible
> interface, connected to card BMC which provided telemetry and mailbox

The PMCI interface or the BMC provides the telemetry functionality?

Maybe you should first describe the basic register access
functionality for PMCI interface. This is the main purpose of this
patch.

> functionalities. On the other hand, this driver leverages the regmap
> APIs to support Intel specific Indirect Register Interface for register
> read/write on PMCI.
>
> Signed-off-by: Tianfei Zhang <[email protected]>
> Signed-off-by: Russ Weight <[email protected]>
> Signed-off-by: Matthew Gerlach <[email protected]>
> ---
> v2:
> - fix compile warning reported by lkp
> - use regmap API for Indirect Register Interface.
> ---
> .../ABI/testing/sysfs-driver-intel-m10-bmc | 8 +-
> drivers/mfd/Kconfig | 12 ++
> drivers/mfd/Makefile | 1 +
> drivers/mfd/intel-m10-bmc-core.c | 19 +-
> drivers/mfd/intel-m10-bmc-pmci.c | 190 ++++++++++++++++++

Refering to intel-m10-bmc-spi.c, this is the DFL bus driver, PMCI is just
its internal register accessing implementation.

So maybe intel-m10-bmc-dfl.c?

> include/linux/mfd/intel-m10-bmc.h | 8 +
> 6 files changed, 230 insertions(+), 8 deletions(-)
> create mode 100644 drivers/mfd/intel-m10-bmc-pmci.c
>
> diff --git a/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc b/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc
> index 9773925138af..a8ab58035c95 100644
> --- a/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc
> +++ b/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc
> @@ -1,4 +1,4 @@
> -What: /sys/bus/spi/devices/.../bmc_version
> +What: /sys/bus/.../drivers/intel-m10-bmc/.../bmc_version

The same driver for both PMCI & spi? From your patch, the pmci driver is
named "dfl-pmci-bmc", is it?

> Date: June 2020
> KernelVersion: 5.10
> Contact: Xu Yilun <[email protected]>
> @@ -6,7 +6,7 @@ Description: Read only. Returns the hardware build version of Intel
> MAX10 BMC chip.
> Format: "0x%x".
>
> -What: /sys/bus/spi/devices/.../bmcfw_version
> +What: /sys/bus/.../drivers/intel-m10-bmc/.../bmcfw_version
> Date: June 2020
> KernelVersion: 5.10
> Contact: Xu Yilun <[email protected]>
> @@ -14,7 +14,7 @@ Description: Read only. Returns the firmware version of Intel MAX10
> BMC chip.
> Format: "0x%x".
>
> -What: /sys/bus/spi/devices/.../mac_address
> +What: /sys/bus/.../drivers/intel-m10-bmc/.../mac_address
> Date: January 2021
> KernelVersion: 5.12
> Contact: Russ Weight <[email protected]>
> @@ -25,7 +25,7 @@ Description: Read only. Returns the first MAC address in a block
> space.
> Format: "%02x:%02x:%02x:%02x:%02x:%02x".
>
> -What: /sys/bus/spi/devices/.../mac_count
> +What: /sys/bus/.../drivers/intel-m10-bmc/.../mac_count
> Date: January 2021
> KernelVersion: 5.12
> Contact: Russ Weight <[email protected]>
> diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
> index ee8398b02321..7300efec3617 100644
> --- a/drivers/mfd/Kconfig
> +++ b/drivers/mfd/Kconfig
> @@ -2177,6 +2177,18 @@ config MFD_INTEL_M10_BMC_SPI
> additional drivers must be enabled in order to use the functionality
> of the device.
>
> +config MFD_INTEL_M10_BMC_PMCI
> + tristate "Intel MAX 10 Board Management Controller with PMCI"
> + depends on FPGA_DFL
> + select MFD_INTEL_M10_BMC_CORE
> + select REGMAP_INDIRECT_REGISTER
> + help
> + Support for the Intel MAX 10 board management controller via PMCI.
> +
> + This driver provides common support for accessing the device,
> + additional drivers must be enabled in order to use the functionality
> + of the device.
> +
> config MFD_RSMU_I2C
> tristate "Renesas Synchronization Management Unit with I2C"
> depends on I2C && OF
> diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
> index b5d3263c1205..a8ffdc223cf7 100644
> --- a/drivers/mfd/Makefile
> +++ b/drivers/mfd/Makefile
> @@ -270,6 +270,7 @@ obj-$(CONFIG_MFD_SIMPLE_MFD_I2C) += simple-mfd-i2c.o
> intel-m10-bmc-objs := intel-m10-bmc-core.o
> obj-$(CONFIG_MFD_INTEL_M10_BMC_CORE) += intel-m10-bmc.o
> obj-$(CONFIG_MFD_INTEL_M10_BMC_SPI) += intel-m10-bmc-spi.o
> +obj-$(CONFIG_MFD_INTEL_M10_BMC_PMCI) += intel-m10-bmc-pmci.o
>
> obj-$(CONFIG_MFD_ATC260X) += atc260x-core.o
> obj-$(CONFIG_MFD_ATC260X_I2C) += atc260x-i2c.o
> diff --git a/drivers/mfd/intel-m10-bmc-core.c b/drivers/mfd/intel-m10-bmc-core.c
> index f6dc549e1bc3..c6a1a4c28357 100644
> --- a/drivers/mfd/intel-m10-bmc-core.c
> +++ b/drivers/mfd/intel-m10-bmc-core.c
> @@ -10,6 +10,11 @@
> #include <linux/mfd/intel-m10-bmc.h>
> #include <linux/module.h>
>
> +static struct mfd_cell m10bmc_n6000_bmc_subdevs[] = {
> + { .name = "n6000bmc-hwmon" },
> + { .name = "n6000bmc-sec-update" }
> +};
> +
> static struct mfd_cell m10bmc_d5005_subdevs[] = {
> { .name = "d5005bmc-hwmon" },
> };
> @@ -146,10 +151,12 @@ int m10bmc_dev_init(struct intel_m10bmc *m10bmc)
>
> dev_set_drvdata(m10bmc->dev, m10bmc);
>
> - ret = check_m10bmc_version(m10bmc);
> - if (ret) {
> - dev_err(m10bmc->dev, "Failed to identify m10bmc hardware\n");
> - return ret;
> + if (type == M10_N3000 || type == M10_D5005 || type == M10_N5010) {
> + ret = check_m10bmc_version(m10bmc);
> + if (ret) {
> + dev_err(m10bmc->dev, "Failed to identify m10bmc hardware\n");
> + return ret;
> + }
> }
>
> switch (type) {
> @@ -165,6 +172,10 @@ int m10bmc_dev_init(struct intel_m10bmc *m10bmc)
> cells = m10bmc_n5010_subdevs;
> n_cell = ARRAY_SIZE(m10bmc_n5010_subdevs);
> break;
> + case M10_N6000:
> + cells = m10bmc_n6000_bmc_subdevs;
> + n_cell = ARRAY_SIZE(m10bmc_n6000_bmc_subdevs);
> + break;
> default:
> return -ENODEV;
> }
> diff --git a/drivers/mfd/intel-m10-bmc-pmci.c b/drivers/mfd/intel-m10-bmc-pmci.c
> new file mode 100644
> index 000000000000..249a2db5e742
> --- /dev/null
> +++ b/drivers/mfd/intel-m10-bmc-pmci.c
> @@ -0,0 +1,190 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * PMCI-based interface to MAX10 BMC
> + *
> + * Copyright (C) 2020-2022 Intel Corporation, Inc.
> + *
> + */
> +
> +#include <linux/dfl.h>
> +#include <linux/mfd/intel-m10-bmc.h>
> +#include <linux/module.h>
> +#include <linux/regmap.h>
> +
> +#define M10BMC_PMCI_INDIRECT_BASE 0x400
> +#define INDIRECT_INT_US 1
> +#define INDIRECT_TIMEOUT_US 10000
> +
> +#define INDIRECT_CMD_OFF 0x0
> +#define INDIRECT_CMD_RD BIT(0)
> +#define INDIRECT_CMD_WR BIT(1)
> +#define INDIRECT_CMD_ACK BIT(2)
> +
> +#define INDIRECT_ADDR_OFF 0x4
> +#define INDIRECT_RD_OFF 0x8
> +#define INDIRECT_WR_OFF 0xc
> +
> +struct indirect_ctx {
> + void __iomem *base;
> + struct device *dev;
> + unsigned long sleep_us;
> + unsigned long timeout_us;
> +};
> +
> +struct pmci_device {
> + void __iomem *base;
> + struct device *dev;
> + struct intel_m10bmc m10bmc;
> + struct indirect_ctx ctx;
> +};
> +
> +static int pmci_indirect_bus_clr_cmd(struct indirect_ctx *ctx)
> +{
> + unsigned int cmd;
> + int ret;
> +
> + writel(0, ctx->base + INDIRECT_CMD_OFF);
> + ret = readl_poll_timeout((ctx->base + INDIRECT_CMD_OFF), cmd,
> + (!cmd), ctx->sleep_us, ctx->timeout_us);
> + if (ret)
> + dev_err(ctx->dev, "%s timed out on clearing cmd 0x%xn", __func__, cmd);
> +
> + return ret;
> +}
> +
> +static int pmci_indirect_bus_reg_read(void *context, unsigned int reg,
> + unsigned int *val)
> +{
> + struct indirect_ctx *ctx = context;
> + unsigned int cmd;
> + int ret;
> +
> + cmd = readl(ctx->base + INDIRECT_CMD_OFF);
> + if (cmd)
> + dev_warn(ctx->dev, "%s non-zero cmd 0x%x\n", __func__, cmd);
> +
> + writel(reg, ctx->base + INDIRECT_ADDR_OFF);
> + writel(INDIRECT_CMD_RD, ctx->base + INDIRECT_CMD_OFF);
> + ret = readl_poll_timeout((ctx->base + INDIRECT_CMD_OFF), cmd,
> + (cmd & INDIRECT_CMD_ACK), ctx->sleep_us,
> + ctx->timeout_us);
> + if (ret) {
> + dev_err(ctx->dev, "%s timed out on reg 0x%x cmd 0x%x\n", __func__, reg, cmd);
> + goto out;
> + }
> +
> + *val = readl(ctx->base + INDIRECT_RD_OFF);
> +
> + if (pmci_indirect_bus_clr_cmd(ctx))
> + ret = -ETIMEDOUT;
> +
> +out:
> + return ret;
> +}
> +
> +static int pmci_indirect_bus_reg_write(void *context, unsigned int reg,
> + unsigned int val)
> +{
> + struct indirect_ctx *ctx = context;
> + unsigned int cmd;
> + int ret;
> +
> + cmd = readl(ctx->base + INDIRECT_CMD_OFF);
> + if (cmd)
> + dev_warn(ctx->dev, "%s non-zero cmd 0x%x\n", __func__, cmd);
> +
> + writel(val, ctx->base + INDIRECT_WR_OFF);
> + writel(reg, ctx->base + INDIRECT_ADDR_OFF);
> + writel(INDIRECT_CMD_WR, ctx->base + INDIRECT_CMD_OFF);
> + ret = readl_poll_timeout((ctx->base + INDIRECT_CMD_OFF), cmd,
> + (cmd & INDIRECT_CMD_ACK), ctx->sleep_us,
> + ctx->timeout_us);
> + if (ret) {
> + dev_err(ctx->dev, "%s timed out on reg 0x%x cmd 0x%x\n", __func__, reg, cmd);
> + goto out;
> + }
> +
> + if (pmci_indirect_bus_clr_cmd(ctx))
> + ret = -ETIMEDOUT;
> +
> +out:
> + return ret;
> +}
> +
> +static const struct regmap_bus pmci_indirect_bus = {
> + .reg_write = pmci_indirect_bus_reg_write,
> + .reg_read = pmci_indirect_bus_reg_read,
> +};
> +
> +static const struct regmap_range m10bmc_pmci_regmap_range[] = {
> + regmap_reg_range(M10BMC_PMCI_SYS_BASE, M10BMC_PMCI_SYS_END),
> +};

If you have just one range, why bother defining it?

> +
> +static const struct regmap_access_table m10_access_table = {
> + .yes_ranges = m10bmc_pmci_regmap_range,
> + .n_yes_ranges = ARRAY_SIZE(m10bmc_pmci_regmap_range),
> +};
> +
> +static struct regmap_config m10bmc_pmci_regmap_config = {
> + .reg_bits = 32,
> + .reg_stride = 4,
> + .val_bits = 32,
> + .wr_table = &m10_access_table,
> + .rd_table = &m10_access_table,
> + .max_register = M10BMC_PMCI_SYS_END,
> +};

The same concern, these should be specific to BMC, not PMCI interface,
is it?

> +
> +static int pmci_probe(struct dfl_device *ddev)
> +{
> + struct device *dev = &ddev->dev;
> + struct pmci_device *pmci;
> +
> + pmci = devm_kzalloc(dev, sizeof(*pmci), GFP_KERNEL);
> + if (!pmci)
> + return -ENOMEM;
> +
> + pmci->m10bmc.dev = dev;
> + pmci->dev = dev;
> + pmci->m10bmc.type = M10_N6000;

The DFL feature only binds to N6000 BMC? Then the driver should be named
dfl-n6000-bmc I think.

> +
> + pmci->base = devm_ioremap_resource(dev, &ddev->mmio_res);
> + if (IS_ERR(pmci->base))
> + return PTR_ERR(pmci->base);
> +
> + pmci->ctx.base = pmci->base + M10BMC_PMCI_INDIRECT_BASE;
> + pmci->ctx.sleep_us = INDIRECT_INT_US;
> + pmci->ctx.timeout_us = INDIRECT_TIMEOUT_US;
> + pmci->ctx.dev = dev;
> + pmci->m10bmc.regmap =
> + devm_regmap_init(dev,
> + &pmci_indirect_bus,
> + &pmci->ctx,
> + &m10bmc_pmci_regmap_config);
> + if (IS_ERR(pmci->m10bmc.regmap))
> + return PTR_ERR(pmci->m10bmc.regmap);
> +
> + return m10bmc_dev_init(&pmci->m10bmc);
> +}
> +
> +#define FME_FEATURE_ID_PMCI_BMC 0x12
> +
> +static const struct dfl_device_id pmci_ids[] = {
> + { FME_ID, FME_FEATURE_ID_PMCI_BMC },
> + { }
> +};
> +MODULE_DEVICE_TABLE(dfl, pmci_ids);
> +
> +static struct dfl_driver pmci_driver = {
> + .drv = {
> + .name = "dfl-pmci-bmc",
> + .dev_groups = m10bmc_dev_groups,
> + },
> + .id_table = pmci_ids,
> + .probe = pmci_probe,
> +};
> +
> +module_dfl_driver(pmci_driver);
> +
> +MODULE_DESCRIPTION("MAX10 BMC PMCI-based interface");
> +MODULE_AUTHOR("Intel Corporation");
> +MODULE_LICENSE("GPL");
> diff --git a/include/linux/mfd/intel-m10-bmc.h b/include/linux/mfd/intel-m10-bmc.h
> index dd81ffdcf168..83c4d3993dcb 100644
> --- a/include/linux/mfd/intel-m10-bmc.h
> +++ b/include/linux/mfd/intel-m10-bmc.h
> @@ -118,11 +118,19 @@
> /* Address of 4KB inverted bit vector containing staging area FLASH count */
> #define STAGING_FLASH_COUNT 0x17ffb000
>
> +#define M10BMC_PMCI_SYS_BASE 0x0
> +#define M10BMC_PMCI_SYS_END 0xfff
> +
> +/* Telemetry registers */
> +#define M10BMC_PMCI_TELEM_START 0x400
> +#define M10BMC_PMCI_TELEM_END 0x78c

The same concern, I asumme they are specific to BMC, not PMCI interface.

Thanks,
Yilun

> +
> /* Supported MAX10 BMC types */
> enum m10bmc_type {
> M10_N3000,
> M10_D5005,
> M10_N5010,
> + M10_N6000
> };
>
> /**
> --
> 2.26.2

2022-06-21 02:01:23

by Zhang, Tianfei

[permalink] [raw]
Subject: RE: [PATCH v2 3/4] mfd: intel-m10-bmc: add PMCI driver



> -----Original Message-----
> From: Xu, Yilun <[email protected]>
> Sent: Monday, June 20, 2022 7:55 PM
> To: Zhang, Tianfei <[email protected]>
> Cc: [email protected]; Wu, Hao <[email protected]>; [email protected];
> [email protected]; [email protected]; Weight, Russell H
> <[email protected]>; [email protected]
> Subject: Re: [PATCH v2 3/4] mfd: intel-m10-bmc: add PMCI driver
>
> On Thu, Jun 16, 2022 at 10:04:04PM -0400, Tianfei Zhang wrote:
> > Adding a driver for the PMCI-base interface of Intel MAX10 BMC
> > controller.
> >
> > PMCI(Platform Management Control Interface) is a software-visible
> > interface, connected to card BMC which provided telemetry and mailbox
>
> The PMCI interface or the BMC provides the telemetry functionality?
>
> Maybe you should first describe the basic register access functionality for PMCI
> interface. This is the main purpose of this patch.

Yes, I agree, the telemetry was provided by BMC via PMCI.

>
> > functionalities. On the other hand, this driver leverages the regmap
> > APIs to support Intel specific Indirect Register Interface for
> > register read/write on PMCI.
> >
> > Signed-off-by: Tianfei Zhang <[email protected]>
> > Signed-off-by: Russ Weight <[email protected]>
> > Signed-off-by: Matthew Gerlach <[email protected]>
> > ---
> > v2:
> > - fix compile warning reported by lkp
> > - use regmap API for Indirect Register Interface.
> > ---
> > .../ABI/testing/sysfs-driver-intel-m10-bmc | 8 +-
> > drivers/mfd/Kconfig | 12 ++
> > drivers/mfd/Makefile | 1 +
> > drivers/mfd/intel-m10-bmc-core.c | 19 +-
> > drivers/mfd/intel-m10-bmc-pmci.c | 190 ++++++++++++++++++
>
> Refering to intel-m10-bmc-spi.c, this is the DFL bus driver, PMCI is just its
> internal register accessing implementation.
>
> So maybe intel-m10-bmc-dfl.c?

If we have other bus interface like I2C in future, "intel-m10-bmc-i2c.c" is better.
Like this, PMCI is other bus interface, I think " intel-m10-bmc-pmci.c" will be better.

>
> > include/linux/mfd/intel-m10-bmc.h | 8 +
> > 6 files changed, 230 insertions(+), 8 deletions(-) create mode
> > 100644 drivers/mfd/intel-m10-bmc-pmci.c
> >
> > diff --git a/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc
> > b/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc
> > index 9773925138af..a8ab58035c95 100644
> > --- a/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc
> > +++ b/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc
> > @@ -1,4 +1,4 @@
> > -What: /sys/bus/spi/devices/.../bmc_version
> > +What: /sys/bus/.../drivers/intel-m10-bmc/.../bmc_version
>
> The same driver for both PMCI & spi? From your patch, the pmci driver is named
> "dfl-pmci-bmc", is it?

Yes, the path is for both PMCI and SPI. This is should be "dfl-pmci-bmc".

For PMCI driver:
/sys/bus/dfl/drivers/dfl-pmci-bmc/dfl_dev.X/ bmc_version
For SPI driver:
/sys/bus/spi/drivers/intel-m10-bmc/spi0.0/bmc_version

So this path should be:
/sys/bus/.../drivers/.../.../bmc_version

>
> > Date: June 2020
> > KernelVersion: 5.10
> > Contact: Xu Yilun <[email protected]>
> > @@ -6,7 +6,7 @@ Description: Read only. Returns the hardware build
> version of Intel
> > MAX10 BMC chip.
> > Format: "0x%x".
> >
> > -What: /sys/bus/spi/devices/.../bmcfw_version
> > +What: /sys/bus/.../drivers/intel-m10-bmc/.../bmcfw_version
> > Date: June 2020
> > KernelVersion: 5.10
> > Contact: Xu Yilun <[email protected]>
> > @@ -14,7 +14,7 @@ Description: Read only. Returns the firmware
> version of Intel MAX10
> > BMC chip.
> > Format: "0x%x".
> >
> > -What: /sys/bus/spi/devices/.../mac_address
> > +What: /sys/bus/.../drivers/intel-m10-bmc/.../mac_address
> > Date: January 2021
> > KernelVersion: 5.12
> > Contact: Russ Weight <[email protected]>
> > @@ -25,7 +25,7 @@ Description: Read only. Returns the first MAC
> address in a block
> > space.
> > Format: "%02x:%02x:%02x:%02x:%02x:%02x".
> >
> > -What: /sys/bus/spi/devices/.../mac_count
> > +What: /sys/bus/.../drivers/intel-m10-bmc/.../mac_count
> > Date: January 2021
> > KernelVersion: 5.12
> > Contact: Russ Weight <[email protected]>
> > diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index
> > ee8398b02321..7300efec3617 100644
> > --- a/drivers/mfd/Kconfig
> > +++ b/drivers/mfd/Kconfig
> > @@ -2177,6 +2177,18 @@ config MFD_INTEL_M10_BMC_SPI
> > additional drivers must be enabled in order to use the functionality
> > of the device.
> >
> > +config MFD_INTEL_M10_BMC_PMCI
> > + tristate "Intel MAX 10 Board Management Controller with PMCI"
> > + depends on FPGA_DFL
> > + select MFD_INTEL_M10_BMC_CORE
> > + select REGMAP_INDIRECT_REGISTER
> > + help
> > + Support for the Intel MAX 10 board management controller via PMCI.
> > +
> > + This driver provides common support for accessing the device,
> > + additional drivers must be enabled in order to use the functionality
> > + of the device.
> > +
> > config MFD_RSMU_I2C
> > tristate "Renesas Synchronization Management Unit with I2C"
> > depends on I2C && OF
> > diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index
> > b5d3263c1205..a8ffdc223cf7 100644
> > --- a/drivers/mfd/Makefile
> > +++ b/drivers/mfd/Makefile
> > @@ -270,6 +270,7 @@ obj-$(CONFIG_MFD_SIMPLE_MFD_I2C) += simple-
> mfd-i2c.o
> > intel-m10-bmc-objs := intel-m10-bmc-core.o
> > obj-$(CONFIG_MFD_INTEL_M10_BMC_CORE) += intel-m10-bmc.o
> > obj-$(CONFIG_MFD_INTEL_M10_BMC_SPI) += intel-m10-bmc-spi.o
> > +obj-$(CONFIG_MFD_INTEL_M10_BMC_PMCI) += intel-m10-bmc-pmci.o
> >
> > obj-$(CONFIG_MFD_ATC260X) += atc260x-core.o
> > obj-$(CONFIG_MFD_ATC260X_I2C) += atc260x-i2c.o
> > diff --git a/drivers/mfd/intel-m10-bmc-core.c
> > b/drivers/mfd/intel-m10-bmc-core.c
> > index f6dc549e1bc3..c6a1a4c28357 100644
> > --- a/drivers/mfd/intel-m10-bmc-core.c
> > +++ b/drivers/mfd/intel-m10-bmc-core.c
> > @@ -10,6 +10,11 @@
> > #include <linux/mfd/intel-m10-bmc.h>
> > #include <linux/module.h>
> >
> > +static struct mfd_cell m10bmc_n6000_bmc_subdevs[] = {
> > + { .name = "n6000bmc-hwmon" },
> > + { .name = "n6000bmc-sec-update" }
> > +};
> > +
> > static struct mfd_cell m10bmc_d5005_subdevs[] = {
> > { .name = "d5005bmc-hwmon" },
> > };
> > @@ -146,10 +151,12 @@ int m10bmc_dev_init(struct intel_m10bmc
> *m10bmc)
> >
> > dev_set_drvdata(m10bmc->dev, m10bmc);
> >
> > - ret = check_m10bmc_version(m10bmc);
> > - if (ret) {
> > - dev_err(m10bmc->dev, "Failed to identify m10bmc
> hardware\n");
> > - return ret;
> > + if (type == M10_N3000 || type == M10_D5005 || type == M10_N5010) {
> > + ret = check_m10bmc_version(m10bmc);
> > + if (ret) {
> > + dev_err(m10bmc->dev, "Failed to identify m10bmc
> hardware\n");
> > + return ret;
> > + }
> > }
> >
> > switch (type) {
> > @@ -165,6 +172,10 @@ int m10bmc_dev_init(struct intel_m10bmc *m10bmc)
> > cells = m10bmc_n5010_subdevs;
> > n_cell = ARRAY_SIZE(m10bmc_n5010_subdevs);
> > break;
> > + case M10_N6000:
> > + cells = m10bmc_n6000_bmc_subdevs;
> > + n_cell = ARRAY_SIZE(m10bmc_n6000_bmc_subdevs);
> > + break;
> > default:
> > return -ENODEV;
> > }
> > diff --git a/drivers/mfd/intel-m10-bmc-pmci.c
> > b/drivers/mfd/intel-m10-bmc-pmci.c
> > new file mode 100644
> > index 000000000000..249a2db5e742
> > --- /dev/null
> > +++ b/drivers/mfd/intel-m10-bmc-pmci.c
> > @@ -0,0 +1,190 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * PMCI-based interface to MAX10 BMC
> > + *
> > + * Copyright (C) 2020-2022 Intel Corporation, Inc.
> > + *
> > + */
> > +
> > +#include <linux/dfl.h>
> > +#include <linux/mfd/intel-m10-bmc.h>
> > +#include <linux/module.h>
> > +#include <linux/regmap.h>
> > +
> > +#define M10BMC_PMCI_INDIRECT_BASE 0x400
> > +#define INDIRECT_INT_US 1
> > +#define INDIRECT_TIMEOUT_US 10000
> > +
> > +#define INDIRECT_CMD_OFF 0x0
> > +#define INDIRECT_CMD_RD BIT(0)
> > +#define INDIRECT_CMD_WR BIT(1)
> > +#define INDIRECT_CMD_ACK BIT(2)
> > +
> > +#define INDIRECT_ADDR_OFF 0x4
> > +#define INDIRECT_RD_OFF 0x8
> > +#define INDIRECT_WR_OFF 0xc
> > +
> > +struct indirect_ctx {
> > + void __iomem *base;
> > + struct device *dev;
> > + unsigned long sleep_us;
> > + unsigned long timeout_us;
> > +};
> > +
> > +struct pmci_device {
> > + void __iomem *base;
> > + struct device *dev;
> > + struct intel_m10bmc m10bmc;
> > + struct indirect_ctx ctx;
> > +};
> > +
> > +static int pmci_indirect_bus_clr_cmd(struct indirect_ctx *ctx) {
> > + unsigned int cmd;
> > + int ret;
> > +
> > + writel(0, ctx->base + INDIRECT_CMD_OFF);
> > + ret = readl_poll_timeout((ctx->base + INDIRECT_CMD_OFF), cmd,
> > + (!cmd), ctx->sleep_us, ctx->timeout_us);
> > + if (ret)
> > + dev_err(ctx->dev, "%s timed out on clearing cmd 0x%xn",
> __func__,
> > +cmd);
> > +
> > + return ret;
> > +}
> > +
> > +static int pmci_indirect_bus_reg_read(void *context, unsigned int reg,
> > + unsigned int *val)
> > +{
> > + struct indirect_ctx *ctx = context;
> > + unsigned int cmd;
> > + int ret;
> > +
> > + cmd = readl(ctx->base + INDIRECT_CMD_OFF);
> > + if (cmd)
> > + dev_warn(ctx->dev, "%s non-zero cmd 0x%x\n", __func__,
> cmd);
> > +
> > + writel(reg, ctx->base + INDIRECT_ADDR_OFF);
> > + writel(INDIRECT_CMD_RD, ctx->base + INDIRECT_CMD_OFF);
> > + ret = readl_poll_timeout((ctx->base + INDIRECT_CMD_OFF), cmd,
> > + (cmd & INDIRECT_CMD_ACK), ctx->sleep_us,
> > + ctx->timeout_us);
> > + if (ret) {
> > + dev_err(ctx->dev, "%s timed out on reg 0x%x cmd 0x%x\n",
> __func__, reg, cmd);
> > + goto out;
> > + }
> > +
> > + *val = readl(ctx->base + INDIRECT_RD_OFF);
> > +
> > + if (pmci_indirect_bus_clr_cmd(ctx))
> > + ret = -ETIMEDOUT;
> > +
> > +out:
> > + return ret;
> > +}
> > +
> > +static int pmci_indirect_bus_reg_write(void *context, unsigned int reg,
> > + unsigned int val)
> > +{
> > + struct indirect_ctx *ctx = context;
> > + unsigned int cmd;
> > + int ret;
> > +
> > + cmd = readl(ctx->base + INDIRECT_CMD_OFF);
> > + if (cmd)
> > + dev_warn(ctx->dev, "%s non-zero cmd 0x%x\n", __func__,
> cmd);
> > +
> > + writel(val, ctx->base + INDIRECT_WR_OFF);
> > + writel(reg, ctx->base + INDIRECT_ADDR_OFF);
> > + writel(INDIRECT_CMD_WR, ctx->base + INDIRECT_CMD_OFF);
> > + ret = readl_poll_timeout((ctx->base + INDIRECT_CMD_OFF), cmd,
> > + (cmd & INDIRECT_CMD_ACK), ctx->sleep_us,
> > + ctx->timeout_us);
> > + if (ret) {
> > + dev_err(ctx->dev, "%s timed out on reg 0x%x cmd 0x%x\n",
> __func__, reg, cmd);
> > + goto out;
> > + }
> > +
> > + if (pmci_indirect_bus_clr_cmd(ctx))
> > + ret = -ETIMEDOUT;
> > +
> > +out:
> > + return ret;
> > +}
> > +
> > +static const struct regmap_bus pmci_indirect_bus = {
> > + .reg_write = pmci_indirect_bus_reg_write,
> > + .reg_read = pmci_indirect_bus_reg_read, };
> > +
> > +static const struct regmap_range m10bmc_pmci_regmap_range[] = {
> > + regmap_reg_range(M10BMC_PMCI_SYS_BASE,
> M10BMC_PMCI_SYS_END), };
>
> If you have just one range, why bother defining it?

There is different register range between SPI bus and PMCI bus of BMC.
For SPI bus interface, the register range of BMC is: 0x300800 - 0x300fff
For PMIC bus interface, the register range of BMC is: 0x0 - 0xfff

>
> > +
> > +static const struct regmap_access_table m10_access_table = {
> > + .yes_ranges = m10bmc_pmci_regmap_range,
> > + .n_yes_ranges = ARRAY_SIZE(m10bmc_pmci_regmap_range),
> > +};
> > +
> > +static struct regmap_config m10bmc_pmci_regmap_config = {
> > + .reg_bits = 32,
> > + .reg_stride = 4,
> > + .val_bits = 32,
> > + .wr_table = &m10_access_table,
> > + .rd_table = &m10_access_table,
> > + .max_register = M10BMC_PMCI_SYS_END, };
>
> The same concern, these should be specific to BMC, not PMCI interface, is it?

I think this is related to different regmap configuration for different bus interface like SPI or PMCI, so
It should be in PMCI interface.

>
> > +
> > +static int pmci_probe(struct dfl_device *ddev) {
> > + struct device *dev = &ddev->dev;
> > + struct pmci_device *pmci;
> > +
> > + pmci = devm_kzalloc(dev, sizeof(*pmci), GFP_KERNEL);
> > + if (!pmci)
> > + return -ENOMEM;
> > +
> > + pmci->m10bmc.dev = dev;
> > + pmci->dev = dev;
> > + pmci->m10bmc.type = M10_N6000;
>
> The DFL feature only binds to N6000 BMC? Then the driver should be named dfl-
> n6000-bmc I think.

Yes, maybe M10_DFL should be better.

>
> > +
> > + pmci->base = devm_ioremap_resource(dev, &ddev->mmio_res);
> > + if (IS_ERR(pmci->base))
> > + return PTR_ERR(pmci->base);
> > +
> > + pmci->ctx.base = pmci->base + M10BMC_PMCI_INDIRECT_BASE;
> > + pmci->ctx.sleep_us = INDIRECT_INT_US;
> > + pmci->ctx.timeout_us = INDIRECT_TIMEOUT_US;
> > + pmci->ctx.dev = dev;
> > + pmci->m10bmc.regmap =
> > + devm_regmap_init(dev,
> > + &pmci_indirect_bus,
> > + &pmci->ctx,
> > + &m10bmc_pmci_regmap_config);
> > + if (IS_ERR(pmci->m10bmc.regmap))
> > + return PTR_ERR(pmci->m10bmc.regmap);
> > +
> > + return m10bmc_dev_init(&pmci->m10bmc); }
> > +
> > +#define FME_FEATURE_ID_PMCI_BMC 0x12
> > +
> > +static const struct dfl_device_id pmci_ids[] = {
> > + { FME_ID, FME_FEATURE_ID_PMCI_BMC },
> > + { }
> > +};
> > +MODULE_DEVICE_TABLE(dfl, pmci_ids);
> > +
> > +static struct dfl_driver pmci_driver = {
> > + .drv = {
> > + .name = "dfl-pmci-bmc",
> > + .dev_groups = m10bmc_dev_groups,
> > + },
> > + .id_table = pmci_ids,
> > + .probe = pmci_probe,
> > +};
> > +
> > +module_dfl_driver(pmci_driver);
> > +
> > +MODULE_DESCRIPTION("MAX10 BMC PMCI-based interface");
> > +MODULE_AUTHOR("Intel Corporation"); MODULE_LICENSE("GPL");
> > diff --git a/include/linux/mfd/intel-m10-bmc.h
> > b/include/linux/mfd/intel-m10-bmc.h
> > index dd81ffdcf168..83c4d3993dcb 100644
> > --- a/include/linux/mfd/intel-m10-bmc.h
> > +++ b/include/linux/mfd/intel-m10-bmc.h
> > @@ -118,11 +118,19 @@
> > /* Address of 4KB inverted bit vector containing staging area FLASH count */
> > #define STAGING_FLASH_COUNT 0x17ffb000
> >
> > +#define M10BMC_PMCI_SYS_BASE 0x0
> > +#define M10BMC_PMCI_SYS_END 0xfff
> > +
> > +/* Telemetry registers */
> > +#define M10BMC_PMCI_TELEM_START 0x400
> > +#define M10BMC_PMCI_TELEM_END 0x78c
>
> The same concern, I asumme they are specific to BMC, not PMCI interface.

Yes, I agree, I will remove it.

>
> Thanks,
> Yilun
>
> > +
> > /* Supported MAX10 BMC types */
> > enum m10bmc_type {
> > M10_N3000,
> > M10_D5005,
> > M10_N5010,
> > + M10_N6000
> > };
> >
> > /**
> > --
> > 2.26.2