From: "Ilpo Järvinen" <ilpo.jarvinen@linux.intel.com>
To: Vadim Pasternak <vadimp@nvidia.com>
Cc: Hans de Goede <hdegoede@redhat.com>,
michaelsh@nvidia.com, crajank@nvidia.com, fradensky@nvidia.com,
oleksandrs@nvidia.com, platform-driver-x86@vger.kernel.org
Subject: Re: [PATCH v5 07/12] platform/mellanox: mlxreg-dpu: Add initial support for Nvidia DPU
Date: Mon, 3 Feb 2025 16:20:46 +0200 (EET) [thread overview]
Message-ID: <84065296-fe2d-f692-51cf-03612abbc874@linux.intel.com> (raw)
In-Reply-To: <20250124172632.22437-8-vadimp@nvidia.com>
[-- Attachment #1: Type: text/plain, Size: 23909 bytes --]
On Fri, 24 Jan 2025, Vadim Pasternak wrote:
> Provide platform support for Nvidia (DPU) Data Processor Unit for the
> Smart Switch SN4280.
>
> The Smart Switch equipped with:
> - Nvidia COME module based on AMD EPYC™ Embedded 3451 CPU.
> - Nvidia Spectrum-3 ASIC.
> - Four DPUs, each equipped with Nvidia BF3 ARM based processor and
> with Lattice LFD2NX-40 FPGA device.
> - 28xQSFP-DD external ports.
> - Two power supplies.
> - Four cooling drawers.
>
> Drivers provides support for the platform management and monitoring
> of DPU components.
> It includes support for health events, resets and boot progress
> indications logic, implemented by FPGA device.
>
> Reviewed-by: Ciju Rajan K <crajank@nvidia.com>
> Signed-off-by: Vadim Pasternak <vadimp@nvidia.com>
> ---
> v4->v5
> Comments pointed out by Ilpo:
> - Add empty line in mlxreg_dpu_config_init().
> - Include 'dev_printk.h' from dev_err().
> - Remove unnecessary comments from mlxreg_dpu_config_exit().
> - Put defer probing test in mlxreg_dpu_probe() before allocation.
> - Remove unnecessary comments from mlxreg_dpu_probe().
>
> v3->v4
> Comments pointed out by Ilpo:
> - Fix method of duplication data.
> - Rename 'count' to 'item_count'.
>
> v2->v3
> Comments pointed out by Ilpo:
> - Fix s/pltaform/platform.
> - Remove semicolon from structure description.
> - In routine mlxreg_dpu_copy_hotplug_data() use 'const struct' for the
> third argument.
> - In mlxreg_dpu_copy_hotplug_data() remove redunadant devm_kmemdup()
> call.
> - Fix identifications in mlxreg_dpu_config_init().
> - Remove label 'fail_register_io" from error flow.
> - One line for devm_regmap_init_i2c() call in mlxreg_dpu_probe().
> ---
> drivers/platform/mellanox/Kconfig | 12 +
> drivers/platform/mellanox/Makefile | 1 +
> drivers/platform/mellanox/mlxreg-dpu.c | 620 +++++++++++++++++++++++++
> 3 files changed, 633 insertions(+)
> create mode 100644 drivers/platform/mellanox/mlxreg-dpu.c
>
> diff --git a/drivers/platform/mellanox/Kconfig b/drivers/platform/mellanox/Kconfig
> index aa760f064a17..7da0fc46b1e7 100644
> --- a/drivers/platform/mellanox/Kconfig
> +++ b/drivers/platform/mellanox/Kconfig
> @@ -27,6 +27,18 @@ config MLX_PLATFORM
>
> If you have a Mellanox system, say Y or M here.
>
> +config MLXREG_DPU
> + tristate "Nvidia Data Processor Unit platform driver support"
> + select REGMAP_I2C
> + help
> + This driver provides support for the Nvidia BF3 Data Processor Units,
> + which are the part of SN4280 Ethernet smart switch systems
> + providing a high performance switching solution for Enterprise Data
> + Centers (EDC) for building Ethernet based clusters, High-Performance
> + Computing (HPC) and embedded environments.
> +
> + If you have a Nvidia smart swicth system, say Y or M here.
> +
> config MLXREG_HOTPLUG
> tristate "Mellanox platform hotplug driver support"
> depends on HWMON
> diff --git a/drivers/platform/mellanox/Makefile b/drivers/platform/mellanox/Makefile
> index ba56485cbe8c..e86723b44c2e 100644
> --- a/drivers/platform/mellanox/Makefile
> +++ b/drivers/platform/mellanox/Makefile
> @@ -7,6 +7,7 @@ obj-$(CONFIG_MLX_PLATFORM) += mlx-platform.o
> obj-$(CONFIG_MLXBF_BOOTCTL) += mlxbf-bootctl.o
> obj-$(CONFIG_MLXBF_PMC) += mlxbf-pmc.o
> obj-$(CONFIG_MLXBF_TMFIFO) += mlxbf-tmfifo.o
> +obj-$(CONFIG_MLXREG_DPU) += mlxreg-dpu.o
> obj-$(CONFIG_MLXREG_HOTPLUG) += mlxreg-hotplug.o
> obj-$(CONFIG_MLXREG_IO) += mlxreg-io.o
> obj-$(CONFIG_MLXREG_LC) += mlxreg-lc.o
> diff --git a/drivers/platform/mellanox/mlxreg-dpu.c b/drivers/platform/mellanox/mlxreg-dpu.c
> new file mode 100644
> index 000000000000..bd5fe24fc2b6
> --- /dev/null
> +++ b/drivers/platform/mellanox/mlxreg-dpu.c
> @@ -0,0 +1,620 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Nvidia Data Processor Unit platform driver
> + *
> + * Copyright (C) 2025 Nvidia Technologies Ltd.
> + */
> +
> +#include <linux/device.h>
> +#include <linux/dev_printk.h>
> +#include <linux/i2c.h>
> +#include <linux/module.h>
> +#include <linux/platform_data/mlxcpld.h>
> +#include <linux/platform_data/mlxreg.h>
> +#include <linux/platform_device.h>
> +#include <linux/regmap.h>
> +
> +/* I2C bus IO offsets */
> +#define MLXREG_DPU_REG_FPGA1_VER_OFFSET 0x2400
> +#define MLXREG_DPU_REG_FPGA1_PN_OFFSET 0x2404
> +#define MLXREG_DPU_REG_FPGA1_PN1_OFFSET 0x2405
> +#define MLXREG_DPU_REG_PG_OFFSET 0x2414
> +#define MLXREG_DPU_REG_PG_EVENT_OFFSET 0x2415
> +#define MLXREG_DPU_REG_PG_MASK_OFFSET 0x2416
> +#define MLXREG_DPU_REG_RESET_GP1_OFFSET 0x2417
> +#define MLXREG_DPU_REG_RST_CAUSE1_OFFSET 0x241e
> +#define MLXREG_DPU_REG_GP0_RO_OFFSET 0x242b
> +#define MLXREG_DPU_REG_GP0_OFFSET 0x242e
> +#define MLXREG_DPU_REG_GP1_OFFSET 0x242c
> +#define MLXREG_DPU_REG_GP4_OFFSET 0x2438
> +#define MLXREG_DPU_REG_AGGRCO_OFFSET 0x2442
> +#define MLXREG_DPU_REG_AGGRCO_MASK_OFFSET 0x2443
> +#define MLXREG_DPU_REG_HEALTH_OFFSET 0x244d
> +#define MLXREG_DPU_REG_HEALTH_EVENT_OFFSET 0x244e
> +#define MLXREG_DPU_REG_HEALTH_MASK_OFFSET 0x244f
> +#define MLXREG_DPU_REG_FPGA1_MVER_OFFSET 0x24de
> +#define MLXREG_DPU_REG_CONFIG3_OFFSET 0x24fd
> +#define MLXREG_DPU_REG_MAX 0x3fff
> +
> +/* Power Good event masks. */
> +#define MLXREG_DPU_PG_VDDIO_MASK BIT(0)
> +#define MLXREG_DPU_PG_VDD_CPU_MASK BIT(1)
> +#define MLXREG_DPU_PG_VDD_MASK BIT(2)
> +#define MLXREG_DPU_PG_1V8_MASK BIT(3)
> +#define MLXREG_DPU_PG_COMPARATOR_MASK BIT(4)
> +#define MLXREG_DPU_PG_VDDQ_MASK BIT(5)
> +#define MLXREG_DPU_PG_HVDD_MASK BIT(6)
> +#define MLXREG_DPU_PG_DVDD_MASK BIT(7)
> +#define MLXREG_DPU_PG_MASK (MLXREG_DPU_PG_DVDD_MASK | \
> + MLXREG_DPU_PG_HVDD_MASK | \
> + MLXREG_DPU_PG_VDDQ_MASK | \
> + MLXREG_DPU_PG_COMPARATOR_MASK | \
> + MLXREG_DPU_PG_1V8_MASK | \
> + MLXREG_DPU_PG_VDD_CPU_MASK | \
> + MLXREG_DPU_PG_VDD_MASK | \
> + MLXREG_DPU_PG_VDDIO_MASK)
> +
> +/* Health event masks. */
> +#define MLXREG_DPU_HLTH_THERMAL_TRIP_MASK BIT(0)
> +#define MLXREG_DPU_HLTH_UFM_UPGRADE_DONE_MASK BIT(1)
> +#define MLXREG_DPU_HLTH_VDDQ_HOT_ALERT_MASK BIT(2)
> +#define MLXREG_DPU_HLTH_VDD_CPU_HOT_ALERT_MASK BIT(3)
> +#define MLXREG_DPU_HLTH_VDDQ_ALERT_MASK BIT(4)
> +#define MLXREG_DPU_HLTH_VDD_CPU_ALERT_MASK BIT(5)
> +#define MLXREG_DPU_HEALTH_MASK (MLXREG_DPU_HLTH_UFM_UPGRADE_DONE_MASK | \
> + MLXREG_DPU_HLTH_VDDQ_HOT_ALERT_MASK | \
> + MLXREG_DPU_HLTH_VDD_CPU_HOT_ALERT_MASK | \
> + MLXREG_DPU_HLTH_VDDQ_ALERT_MASK | \
> + MLXREG_DPU_HLTH_VDD_CPU_ALERT_MASK | \
> + MLXREG_DPU_HLTH_THERMAL_TRIP_MASK)
> +
> +/* Hotplug aggregation masks. */
> +#define MLXREG_DPU_HEALTH_AGGR_MASK BIT(0)
> +#define MLXREG_DPU_PG_AGGR_MASK BIT(1)
> +#define MLXREG_DPU_AGGR_MASK (MLXREG_DPU_HEALTH_AGGR_MASK | \
> + MLXREG_DPU_PG_AGGR_MASK)
> +
> +/* Voltage regulator firmware update status mask. */
> +#define MLXREG_DPU_VOLTREG_UPD_MASK GENMASK(5, 4)
> +
> +#define MLXREG_DPU_NR_NONE (-1)
> +
> +/*
> + * enum mlxreg_dpu_type - Data Processor Unit types
> + *
> + * @MLXREG_DPU_BF3: DPU equipped with BF3 SoC;
> + */
> +enum mlxreg_dpu_type {
> + MLXREG_DPU_BF3 = 0x0050,
> +};
> +
> +/* Default register access data. */
> +static struct mlxreg_core_data mlxreg_dpu_io_data[] = {
> + {
> + .label = "fpga1_version",
> + .reg = MLXREG_DPU_REG_FPGA1_VER_OFFSET,
> + .bit = GENMASK(7, 0),
> + .mode = 0444,
> + },
> + {
> + .label = "fpga1_pn",
> + .reg = MLXREG_DPU_REG_FPGA1_PN_OFFSET,
> + .bit = GENMASK(15, 0),
> + .mode = 0444,
> + .regnum = 2,
> + },
> + {
> + .label = "fpga1_version_min",
> + .reg = MLXREG_DPU_REG_FPGA1_MVER_OFFSET,
> + .bit = GENMASK(7, 0),
> + .mode = 0444,
> + },
> + {
> + .label = "perst_rst",
> + .reg = MLXREG_DPU_REG_RESET_GP1_OFFSET,
> + .mask = GENMASK(7, 0) & ~BIT(0),
> + .mode = 0644,
> + },
> + {
> + .label = "usbphy_rst",
> + .reg = MLXREG_DPU_REG_RESET_GP1_OFFSET,
> + .mask = GENMASK(7, 0) & ~BIT(1),
> + .mode = 0644,
> + },
> + {
> + .label = "phy_rst",
> + .reg = MLXREG_DPU_REG_RESET_GP1_OFFSET,
> + .mask = GENMASK(7, 0) & ~BIT(2),
> + .mode = 0644,
> + },
> + {
> + .label = "tpm_rst",
> + .reg = MLXREG_DPU_REG_RESET_GP1_OFFSET,
> + .mask = GENMASK(7, 0) & ~BIT(6),
> + .mode = 0644,
> + },
> + {
> + .label = "reset_from_main_board",
> + .reg = MLXREG_DPU_REG_RST_CAUSE1_OFFSET,
> + .mask = GENMASK(7, 0) & ~BIT(1),
> + .mode = 0444,
> + },
> + {
> + .label = "reset_aux_pwr_or_reload",
> + .reg = MLXREG_DPU_REG_RST_CAUSE1_OFFSET,
> + .mask = GENMASK(7, 0) & ~BIT(2),
> + .mode = 0444,
> + },
> + {
> + .label = "reset_comex_pwr_fail",
> + .reg = MLXREG_DPU_REG_RST_CAUSE1_OFFSET,
> + .mask = GENMASK(7, 0) & ~BIT(3),
> + .mode = 0444,
> + },
> + {
> + .label = "reset_dpu_thermal",
> + .reg = MLXREG_DPU_REG_RST_CAUSE1_OFFSET,
> + .mask = GENMASK(7, 0) & ~BIT(6),
> + .mode = 0444,
> + },
> + {
> + .label = "reset_pwr_off",
> + .reg = MLXREG_DPU_REG_RST_CAUSE1_OFFSET,
> + .mask = GENMASK(7, 0) & ~BIT(7),
> + .mode = 0444,
> + },
> + {
> + .label = "dpu_id",
> + .reg = MLXREG_DPU_REG_GP0_RO_OFFSET,
> + .mask = GENMASK(3, 0),
> + .mode = 0444,
> + },
> + {
> + .label = "voltreg_update_status",
> + .reg = MLXREG_DPU_REG_GP0_RO_OFFSET,
> + .mask = MLXREG_DPU_VOLTREG_UPD_MASK,
> + .bit = 5,
> + .mode = 0444,
> + },
> + {
> + .label = "boot_progress",
> + .reg = MLXREG_DPU_REG_GP0_OFFSET,
> + .mask = GENMASK(3, 0),
> + .mode = 0444,
> + },
> + {
> + .label = "ufm_upgrade",
> + .reg = MLXREG_DPU_REG_GP4_OFFSET,
> + .mask = GENMASK(7, 0) & ~BIT(1),
> + .mode = 0644,
> + },
> +};
> +
> +static struct mlxreg_core_platform_data mlxreg_dpu_default_regs_io_data = {
> + .data = mlxreg_dpu_io_data,
> + .counter = ARRAY_SIZE(mlxreg_dpu_io_data),
> +};
> +
> +/* Default hotplug data. */
> +static struct mlxreg_core_data mlxreg_dpu_power_events_items_data[] = {
> + {
> + .label = "pg_vddio",
> + .reg = MLXREG_DPU_REG_PG_OFFSET,
> + .mask = MLXREG_DPU_PG_VDDIO_MASK,
> + .hpdev.nr = MLXREG_DPU_NR_NONE,
> + },
> + {
> + .label = "pg_vdd_cpu",
> + .reg = MLXREG_DPU_REG_PG_OFFSET,
> + .mask = MLXREG_DPU_PG_VDD_CPU_MASK,
> + .hpdev.nr = MLXREG_DPU_NR_NONE,
> + },
> + {
> + .label = "pg_vdd",
> + .reg = MLXREG_DPU_REG_PG_OFFSET,
> + .mask = MLXREG_DPU_PG_VDD_MASK,
> + .hpdev.nr = MLXREG_DPU_NR_NONE,
> + },
> + {
> + .label = "pg_1v8",
> + .reg = MLXREG_DPU_REG_PG_OFFSET,
> + .mask = MLXREG_DPU_PG_1V8_MASK,
> + .hpdev.nr = MLXREG_DPU_NR_NONE,
> + },
> + {
> + .label = "pg_comparator",
> + .reg = MLXREG_DPU_REG_PG_OFFSET,
> + .mask = MLXREG_DPU_PG_COMPARATOR_MASK,
> + .hpdev.nr = MLXREG_DPU_NR_NONE,
> + },
> + {
> + .label = "pg_vddq",
> + .reg = MLXREG_DPU_REG_PG_OFFSET,
> + .mask = MLXREG_DPU_PG_VDDQ_MASK,
> + .hpdev.nr = MLXREG_DPU_NR_NONE,
> + },
> + {
> + .label = "pg_hvdd",
> + .reg = MLXREG_DPU_REG_PG_OFFSET,
> + .mask = MLXREG_DPU_PG_HVDD_MASK,
> + .hpdev.nr = MLXREG_DPU_NR_NONE,
> + },
> + {
> + .label = "pg_dvdd",
> + .reg = MLXREG_DPU_REG_PG_OFFSET,
> + .mask = MLXREG_DPU_PG_DVDD_MASK,
> + .hpdev.nr = MLXREG_DPU_NR_NONE,
> + },
> +};
> +
> +static struct mlxreg_core_data mlxreg_dpu_health_events_items_data[] = {
> + {
> + .label = "thermal_trip",
> + .reg = MLXREG_DPU_REG_HEALTH_OFFSET,
> + .mask = MLXREG_DPU_HLTH_THERMAL_TRIP_MASK,
> + .hpdev.nr = MLXREG_DPU_NR_NONE,
> + },
> + {
> + .label = "ufm_upgrade_done",
> + .reg = MLXREG_DPU_REG_HEALTH_OFFSET,
> + .mask = MLXREG_DPU_HLTH_UFM_UPGRADE_DONE_MASK,
> + .hpdev.nr = MLXREG_DPU_NR_NONE,
> + },
> + {
> + .label = "vddq_hot_alert",
> + .reg = MLXREG_DPU_REG_HEALTH_OFFSET,
> + .mask = MLXREG_DPU_HLTH_VDDQ_HOT_ALERT_MASK,
> + .hpdev.nr = MLXREG_DPU_NR_NONE,
> + },
> + {
> + .label = "vdd_cpu_hot_alert",
> + .reg = MLXREG_DPU_REG_HEALTH_OFFSET,
> + .mask = MLXREG_DPU_HLTH_VDD_CPU_HOT_ALERT_MASK,
> + .hpdev.nr = MLXREG_DPU_NR_NONE,
> + },
> + {
> + .label = "vddq_alert",
> + .reg = MLXREG_DPU_REG_HEALTH_OFFSET,
> + .mask = MLXREG_DPU_HLTH_VDDQ_ALERT_MASK,
> + .hpdev.nr = MLXREG_DPU_NR_NONE,
> + },
> + {
> + .label = "vdd_cpu_alert",
> + .reg = MLXREG_DPU_REG_HEALTH_OFFSET,
> + .mask = MLXREG_DPU_HLTH_VDD_CPU_ALERT_MASK,
> + .hpdev.nr = MLXREG_DPU_NR_NONE,
> + },
> +};
> +
> +static struct mlxreg_core_item mlxreg_dpu_hotplug_items[] = {
> + {
> + .data = mlxreg_dpu_power_events_items_data,
> + .aggr_mask = MLXREG_DPU_PG_AGGR_MASK,
> + .reg = MLXREG_DPU_REG_PG_OFFSET,
> + .mask = MLXREG_DPU_PG_MASK,
> + .count = ARRAY_SIZE(mlxreg_dpu_power_events_items_data),
> + .health = false,
> + .inversed = 1,
> + },
> + {
> + .data = mlxreg_dpu_health_events_items_data,
> + .aggr_mask = MLXREG_DPU_HEALTH_AGGR_MASK,
> + .reg = MLXREG_DPU_REG_HEALTH_OFFSET,
> + .mask = MLXREG_DPU_HEALTH_MASK,
> + .count = ARRAY_SIZE(mlxreg_dpu_health_events_items_data),
> + .health = false,
> + .inversed = 1,
> + },
> +};
> +
> +static
> +struct mlxreg_core_hotplug_platform_data mlxreg_dpu_default_hotplug_data = {
> + .items = mlxreg_dpu_hotplug_items,
> + .count = ARRAY_SIZE(mlxreg_dpu_hotplug_items),
> + .cell = MLXREG_DPU_REG_AGGRCO_OFFSET,
> + .mask = MLXREG_DPU_AGGR_MASK,
> +};
> +
> +/* mlxreg_dpu - device private data
Just make this conform to kerneldoc formatting with:
/*
* struct mlxreg_dpu - device private data
I leave adding the second * to actually enable kerneldoc for this struct
is up to your discretion.
> + * @dev: platform device
> + * @data: platform core data
> + * @io_data: register access platform data
> + * @io_regs: register access device
> + * @hotplug_data: hotplug platform data
> + * @hotplug: hotplug device
> + */
> +struct mlxreg_dpu {
> + struct device *dev;
> + struct mlxreg_core_data *data;
> + struct mlxreg_core_platform_data *io_data;
> + struct platform_device *io_regs;
> + struct mlxreg_core_hotplug_platform_data *hotplug_data;
> + struct platform_device *hotplug;
> +};
> +
> +static bool mlxreg_dpu_writeable_reg(struct device *dev, unsigned int reg)
> +{
> + switch (reg) {
> + case MLXREG_DPU_REG_PG_EVENT_OFFSET:
> + case MLXREG_DPU_REG_PG_MASK_OFFSET:
> + case MLXREG_DPU_REG_RESET_GP1_OFFSET:
> + case MLXREG_DPU_REG_GP0_OFFSET:
> + case MLXREG_DPU_REG_GP1_OFFSET:
> + case MLXREG_DPU_REG_GP4_OFFSET:
> + case MLXREG_DPU_REG_AGGRCO_OFFSET:
> + case MLXREG_DPU_REG_AGGRCO_MASK_OFFSET:
> + case MLXREG_DPU_REG_HEALTH_EVENT_OFFSET:
> + case MLXREG_DPU_REG_HEALTH_MASK_OFFSET:
> + return true;
> + }
> + return false;
> +}
> +
> +static bool mlxreg_dpu_readable_reg(struct device *dev, unsigned int reg)
> +{
> + switch (reg) {
> + case MLXREG_DPU_REG_FPGA1_VER_OFFSET:
> + case MLXREG_DPU_REG_FPGA1_PN_OFFSET:
> + case MLXREG_DPU_REG_FPGA1_PN1_OFFSET:
> + case MLXREG_DPU_REG_PG_OFFSET:
> + case MLXREG_DPU_REG_PG_EVENT_OFFSET:
> + case MLXREG_DPU_REG_PG_MASK_OFFSET:
> + case MLXREG_DPU_REG_RESET_GP1_OFFSET:
> + case MLXREG_DPU_REG_RST_CAUSE1_OFFSET:
> + case MLXREG_DPU_REG_GP0_RO_OFFSET:
> + case MLXREG_DPU_REG_GP0_OFFSET:
> + case MLXREG_DPU_REG_GP1_OFFSET:
> + case MLXREG_DPU_REG_GP4_OFFSET:
> + case MLXREG_DPU_REG_AGGRCO_OFFSET:
> + case MLXREG_DPU_REG_AGGRCO_MASK_OFFSET:
> + case MLXREG_DPU_REG_HEALTH_OFFSET:
> + case MLXREG_DPU_REG_HEALTH_EVENT_OFFSET:
> + case MLXREG_DPU_REG_HEALTH_MASK_OFFSET:
> + case MLXREG_DPU_REG_FPGA1_MVER_OFFSET:
> + case MLXREG_DPU_REG_CONFIG3_OFFSET:
> + return true;
> + }
> + return false;
> +}
> +
> +static bool mlxreg_dpu_volatile_reg(struct device *dev, unsigned int reg)
> +{
> + switch (reg) {
> + case MLXREG_DPU_REG_FPGA1_VER_OFFSET:
> + case MLXREG_DPU_REG_FPGA1_PN_OFFSET:
> + case MLXREG_DPU_REG_FPGA1_PN1_OFFSET:
> + case MLXREG_DPU_REG_PG_OFFSET:
> + case MLXREG_DPU_REG_PG_EVENT_OFFSET:
> + case MLXREG_DPU_REG_PG_MASK_OFFSET:
> + case MLXREG_DPU_REG_RESET_GP1_OFFSET:
> + case MLXREG_DPU_REG_RST_CAUSE1_OFFSET:
> + case MLXREG_DPU_REG_GP0_RO_OFFSET:
> + case MLXREG_DPU_REG_GP0_OFFSET:
> + case MLXREG_DPU_REG_GP1_OFFSET:
> + case MLXREG_DPU_REG_GP4_OFFSET:
> + case MLXREG_DPU_REG_AGGRCO_OFFSET:
> + case MLXREG_DPU_REG_AGGRCO_MASK_OFFSET:
> + case MLXREG_DPU_REG_HEALTH_OFFSET:
> + case MLXREG_DPU_REG_HEALTH_EVENT_OFFSET:
> + case MLXREG_DPU_REG_HEALTH_MASK_OFFSET:
> + case MLXREG_DPU_REG_FPGA1_MVER_OFFSET:
> + case MLXREG_DPU_REG_CONFIG3_OFFSET:
> + return true;
> + }
> + return false;
> +}
> +
> +/* Configuration for the register map of a device with 2 bytes address space. */
> +static const struct regmap_config mlxreg_dpu_regmap_conf = {
> + .reg_bits = 16,
> + .val_bits = 8,
> + .max_register = MLXREG_DPU_REG_MAX,
> + .cache_type = REGCACHE_FLAT,
> + .writeable_reg = mlxreg_dpu_writeable_reg,
> + .readable_reg = mlxreg_dpu_readable_reg,
> + .volatile_reg = mlxreg_dpu_volatile_reg,
> +};
> +
> +static int
> +mlxreg_dpu_copy_hotplug_data(struct device *dev, struct mlxreg_dpu *mlxreg_dpu,
> + const struct mlxreg_core_hotplug_platform_data *hotplug_data)
> +{
> + struct mlxreg_core_item *item;
> + int i;
> +
> + mlxreg_dpu->hotplug_data = devm_kmemdup(dev, hotplug_data,
> + sizeof(*mlxreg_dpu->hotplug_data), GFP_KERNEL);
> + if (!mlxreg_dpu->hotplug_data)
> + return -ENOMEM;
> +
> + mlxreg_dpu->hotplug_data->items = devm_kmemdup(dev, hotplug_data->items,
> + mlxreg_dpu->hotplug_data->count *
> + sizeof(*mlxreg_dpu->hotplug_data->items),
> + GFP_KERNEL);
> + if (!mlxreg_dpu->hotplug_data->items)
> + return -ENOMEM;
> +
> + item = mlxreg_dpu->hotplug_data->items;
> + for (i = 0; i < hotplug_data->count; i++, item++) {
> + item->data = devm_kmemdup(dev, hotplug_data->items[i].data,
> + hotplug_data->items[i].count * sizeof(*item->data),
> + GFP_KERNEL);
> + if (!item->data)
> + return -ENOMEM;
> + }
> +
> + return 0;
> +}
> +
> +static int mlxreg_dpu_config_init(struct mlxreg_dpu *mlxreg_dpu, void *regmap,
> + struct mlxreg_core_data *data, int irq)
> +{
> + struct device *dev = &data->hpdev.client->dev;
> + u32 regval;
> + int err;
> +
> + /* Validate DPU type. */
> + err = regmap_read(regmap, MLXREG_DPU_REG_CONFIG3_OFFSET, ®val);
> + if (err)
> + return err;
> +
> + switch (regval) {
> + case MLXREG_DPU_BF3:
> + /* Copy platform specific hotplug data. */
> + err = mlxreg_dpu_copy_hotplug_data(dev, mlxreg_dpu,
> + &mlxreg_dpu_default_hotplug_data);
> + if (err)
> + return err;
> +
> + mlxreg_dpu->io_data = &mlxreg_dpu_default_regs_io_data;
> +
> + break;
> + default:
> + return -ENODEV;
> + }
> +
> + /* Register IO access driver. */
> + if (mlxreg_dpu->io_data) {
> + mlxreg_dpu->io_data->regmap = regmap;
> + mlxreg_dpu->io_regs =
> + platform_device_register_resndata(dev, "mlxreg-io",
> + data->slot, NULL, 0,
> + mlxreg_dpu->io_data,
> + sizeof(*mlxreg_dpu->io_data));
> + if (IS_ERR(mlxreg_dpu->io_regs)) {
> + dev_err(dev, "Failed to create regio for client %s at bus %d at addr 0x%02x\n",
> + data->hpdev.brdinfo->type, data->hpdev.nr,
> + data->hpdev.brdinfo->addr);
> + return PTR_ERR(mlxreg_dpu->io_regs);
> + }
> + }
> +
> + /* Register hotplug driver. */
> + if (mlxreg_dpu->hotplug_data && irq) {
> + mlxreg_dpu->hotplug_data->regmap = regmap;
> + mlxreg_dpu->hotplug_data->irq = irq;
> + mlxreg_dpu->hotplug =
> + platform_device_register_resndata(dev, "mlxreg-hotplug",
> + data->slot, NULL, 0,
> + mlxreg_dpu->hotplug_data,
> + sizeof(*mlxreg_dpu->hotplug_data));
> + if (IS_ERR(mlxreg_dpu->hotplug)) {
> + err = PTR_ERR(mlxreg_dpu->hotplug);
> + goto fail_register_hotplug;
> + }
> + }
> +
> + return 0;
> +
> +fail_register_hotplug:
> + platform_device_unregister(mlxreg_dpu->io_regs);
> +
> + return err;
> +}
> +
> +static void mlxreg_dpu_config_exit(struct mlxreg_dpu *mlxreg_dpu)
> +{
> + /* Unregister hotplug driver. */
> + platform_device_unregister(mlxreg_dpu->hotplug);
> + /* Unregister IO access driver. */
> + platform_device_unregister(mlxreg_dpu->io_regs);
Those two comments can be removed.
Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
--
i.
> +}
> +
> +static int mlxreg_dpu_probe(struct platform_device *pdev)
> +{
> + struct mlxreg_core_data *data;
> + struct mlxreg_dpu *mlxreg_dpu;
> + void *regmap;
> + int err;
> +
> + data = dev_get_platdata(&pdev->dev);
> + if (!data || !data->hpdev.brdinfo)
> + return -EINVAL;
> +
> + data->hpdev.adapter = i2c_get_adapter(data->hpdev.nr);
> + if (!data->hpdev.adapter)
> + return -EPROBE_DEFER;
> +
> + mlxreg_dpu = devm_kzalloc(&pdev->dev, sizeof(*mlxreg_dpu), GFP_KERNEL);
> + if (!mlxreg_dpu)
> + return -ENOMEM;
> +
> + /* Create device at the top of DPU I2C tree.*/
> + data->hpdev.client = i2c_new_client_device(data->hpdev.adapter,
> + data->hpdev.brdinfo);
> + if (IS_ERR(data->hpdev.client)) {
> + dev_err(&pdev->dev, "Failed to create client %s at bus %d at addr 0x%02x\n",
> + data->hpdev.brdinfo->type, data->hpdev.nr, data->hpdev.brdinfo->addr);
> + err = PTR_ERR(data->hpdev.client);
> + goto i2c_new_device_fail;
> + }
> +
> + regmap = devm_regmap_init_i2c(data->hpdev.client, &mlxreg_dpu_regmap_conf);
> + if (IS_ERR(regmap)) {
> + dev_err(&pdev->dev, "Failed to create regmap for client %s at bus %d at addr 0x%02x\n",
> + data->hpdev.brdinfo->type, data->hpdev.nr, data->hpdev.brdinfo->addr);
> + err = PTR_ERR(regmap);
> + goto devm_regmap_init_i2c_fail;
> + }
> +
> + /* Sync registers with hardware. */
> + regcache_mark_dirty(regmap);
> + err = regcache_sync(regmap);
> + if (err) {
> + dev_err(&pdev->dev, "Failed to sync regmap for client %s at bus %d at addr 0x%02x\n",
> + data->hpdev.brdinfo->type, data->hpdev.nr, data->hpdev.brdinfo->addr);
> + err = PTR_ERR(regmap);
> + goto regcache_sync_fail;
> + }
> +
> + mlxreg_dpu->data = data;
> + mlxreg_dpu->dev = &pdev->dev;
> + platform_set_drvdata(pdev, mlxreg_dpu);
> +
> + err = mlxreg_dpu_config_init(mlxreg_dpu, regmap, data, data->hpdev.brdinfo->irq);
> + if (err)
> + goto mlxreg_dpu_config_init_fail;
> +
> + return err;
> +
> +mlxreg_dpu_config_init_fail:
> +regcache_sync_fail:
> +devm_regmap_init_i2c_fail:
> + if (data->hpdev.client) {
> + i2c_unregister_device(data->hpdev.client);
> + data->hpdev.client = NULL;
> + }
> +i2c_new_device_fail:
> + i2c_put_adapter(data->hpdev.adapter);
> + data->hpdev.adapter = NULL;
> + return err;
> +}
> +
> +static void mlxreg_dpu_remove(struct platform_device *pdev)
> +{
> + struct mlxreg_core_data *data = dev_get_platdata(&pdev->dev);
> + struct mlxreg_dpu *mlxreg_dpu = platform_get_drvdata(pdev);
> +
> + mlxreg_dpu_config_exit(mlxreg_dpu);
> + if (data->hpdev.client) {
> + i2c_unregister_device(data->hpdev.client);
> + data->hpdev.client = NULL;
> + i2c_put_adapter(data->hpdev.adapter);
> + data->hpdev.adapter = NULL;
> + }
> +}
> +
> +static struct platform_driver mlxreg_dpu_driver = {
> + .probe = mlxreg_dpu_probe,
> + .remove = mlxreg_dpu_remove,
> + .driver = {
> + .name = "mlxreg-dpu",
> + },
> +};
> +
> +module_platform_driver(mlxreg_dpu_driver);
> +
> +MODULE_AUTHOR("Vadim Pasternak <vadimp@nvidia.com>");
> +MODULE_DESCRIPTION("Nvidia Data Processor Unit platform driver");
> +MODULE_LICENSE("Dual BSD/GPL");
> +MODULE_ALIAS("platform:mlxreg-dpu");
>
next prev parent reply other threads:[~2025-02-03 14:20 UTC|newest]
Thread overview: 25+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-01-24 17:26 [PATCH v5 00/12] platform/mellanox: Add support for new systems, amendments, relocate mlx-platform module Vadim Pasternak
2025-01-24 17:26 ` [PATCH v5 01/12] mellanox: Relocate mlx-platform driver Vadim Pasternak
2025-02-04 14:33 ` Ilpo Järvinen
2025-01-24 17:26 ` [PATCH v5 02/12] platform: mellanox: mlx-platform: Cosmetic changes Vadim Pasternak
2025-01-24 17:26 ` [PATCH v5 03/12] platform: mellanox: mlx-platform: Change register name Vadim Pasternak
2025-01-24 17:26 ` [PATCH v5 04/12] platform_data/mlxreg: Add capability bit and mask fields Vadim Pasternak
2025-02-03 13:50 ` Ilpo Järvinen
2025-02-10 20:30 ` Vadim Pasternak
2025-01-24 17:26 ` [PATCH v5 05/12] platform/mellanox: mlxreg-hotplug: Add support for new flavor of capability registers Vadim Pasternak
2025-02-03 13:47 ` Ilpo Järvinen
2025-02-10 20:30 ` Vadim Pasternak
2025-02-11 14:48 ` Ilpo Järvinen
2025-01-24 17:26 ` [PATCH v5 06/12] platform/mellanox: Rename field to improve code readability Vadim Pasternak
2025-02-03 13:52 ` Ilpo Järvinen
2025-01-24 17:26 ` [PATCH v5 07/12] platform/mellanox: mlxreg-dpu: Add initial support for Nvidia DPU Vadim Pasternak
2025-02-03 14:20 ` Ilpo Järvinen [this message]
2025-01-24 17:26 ` [PATCH v5 08/12] platform: mellanox: Introduce support of Nvidia smart switch Vadim Pasternak
2025-02-03 14:32 ` Ilpo Järvinen
2025-01-24 17:26 ` [PATCH v5 09/12] platform: mellanox: Cosmetic changes to improve code style Vadim Pasternak
2025-02-03 14:35 ` Ilpo Järvinen
2025-01-24 17:26 ` [PATCH v5 10/12] platform: mellanox: mlx-platform: Add support for new Nvidia system Vadim Pasternak
2025-02-03 14:38 ` Ilpo Järvinen
2025-01-24 17:26 ` [PATCH v5 11/12] platform: mellanox: nvsw-sn2200: Add support for new system flavour Vadim Pasternak
2025-01-24 17:26 ` [PATCH v5 12/12] Documentation/ABI: Add new attribute for mlxreg-io sysfs interfaces Vadim Pasternak
2025-02-03 14:40 ` Ilpo Järvinen
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=84065296-fe2d-f692-51cf-03612abbc874@linux.intel.com \
--to=ilpo.jarvinen@linux.intel.com \
--cc=crajank@nvidia.com \
--cc=fradensky@nvidia.com \
--cc=hdegoede@redhat.com \
--cc=michaelsh@nvidia.com \
--cc=oleksandrs@nvidia.com \
--cc=platform-driver-x86@vger.kernel.org \
--cc=vadimp@nvidia.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox