From patchwork Fri Jun 17 07:19:32 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Wei Huang X-Patchwork-Id: 112960 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 486BFA0093; Fri, 17 Jun 2022 09:11:54 +0200 (CEST) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 82DF2415D7; Fri, 17 Jun 2022 09:11:51 +0200 (CEST) Received: from mga04.intel.com (mga04.intel.com [192.55.52.120]) by mails.dpdk.org (Postfix) with ESMTP id 3444241148; Fri, 17 Jun 2022 09:11:49 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1655449909; x=1686985909; h=from:to:cc:subject:date:message-id:in-reply-to: references; bh=sMFunHrKUberMOMUzTMMkWEwZJh0oimc8VwciYeyLGY=; b=nzb3tPqQ3qAPMq56BHF93fQOFkZhfRr9ORBAHrqJuHDxeV3rjOruKBD4 slMRnTt/XwAo0WRATTsHDcPEUAvFbR7Pm78G//4Y/Tp6fcHQRJtsDQVtr 9R9De+ZT8NBpVjyKYjm8acht4W1IBCDkcSwn6sMa5OYAIH2Nld9sKDe0f PB86Q9tZ3f/CGA4Q9T9xX5YCl6v8Pkt2FCCIQALMsTKrfkIVc7i7aO0aN rJqKrBwsS8k5Qbhi2hIhah/Sppe4/whvItI5a6b9wRz7Bv7dCfsEBXKaR bk3dGWnzHP+rL6ui+EEur6HswtYnHcM66Gg++yhRoU2ZYERkKLpKUcBl4 Q==; X-IronPort-AV: E=McAfee;i="6400,9594,10380"; a="278236399" X-IronPort-AV: E=Sophos;i="5.92,306,1650956400"; d="scan'208";a="278236399" Received: from fmsmga005.fm.intel.com ([10.253.24.32]) by fmsmga104.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Jun 2022 00:11:48 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.92,306,1650956400"; d="scan'208";a="912502464" Received: from unknown (HELO zj-fpga-amt.sh.intel.com) ([10.238.175.102]) by fmsmga005.fm.intel.com with ESMTP; 17 Jun 2022 00:11:46 -0700 From: Wei Huang To: dev@dpdk.org, thomas@monjalon.net, nipun.gupta@nxp.com, hemant.agrawal@nxp.com Cc: stable@dpdk.org, rosen.xu@intel.com, tianfei.zhang@intel.com, qi.z.zhang@intel.com, Wei Huang Subject: [PATCH v3 1/4] raw/ifpga/base: add PMCI base driver Date: Fri, 17 Jun 2022 03:19:32 -0400 Message-Id: <1655450375-10739-2-git-send-email-wei.huang@intel.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1655450375-10739-1-git-send-email-wei.huang@intel.com> References: <1654827900-10023-1-git-send-email-wei.huang@intel.com> <1655450375-10739-1-git-send-email-wei.huang@intel.com> X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org PMCI (Platform Management Control Interface) is a new module in FPGA, which is designed to cooperate with BMC chip to fulfill board management functions. This base driver implements interfaces to access registers of BMC chip. Signed-off-by: Wei Huang Acked-by: Tianfei Zhang Reviewed-by: Rosen Xu --- v2: fix typo. 'spi_master' is not misspelled and is not introduced in this patch --- v3: split PMCI driver into several patches --- drivers/raw/ifpga/base/ifpga_defines.h | 2 + drivers/raw/ifpga/base/ifpga_feature_dev.c | 2 + drivers/raw/ifpga/base/ifpga_feature_dev.h | 1 + drivers/raw/ifpga/base/ifpga_fme.c | 142 ++++++++++++-- drivers/raw/ifpga/base/opae_intel_max10.c | 297 ++++++++++++++++++++--------- drivers/raw/ifpga/base/opae_intel_max10.h | 229 +++++++++++++++++++++- drivers/raw/ifpga/base/opae_osdep.h | 43 ++++- 7 files changed, 597 insertions(+), 119 deletions(-) diff --git a/drivers/raw/ifpga/base/ifpga_defines.h b/drivers/raw/ifpga/base/ifpga_defines.h index 9a280eb..f84ed1d 100644 --- a/drivers/raw/ifpga/base/ifpga_defines.h +++ b/drivers/raw/ifpga/base/ifpga_defines.h @@ -23,6 +23,7 @@ #define FME_FEATURE_NIOS_SPI "fme_nios_spi" #define FME_FEATURE_I2C_MASTER "fme_i2c_master" #define FME_FEATURE_ETH_GROUP "fme_eth_group" +#define FME_FEATURE_PMCI "fme_pmci" #define PORT_FEATURE_HEADER "port_hdr" #define PORT_FEATURE_UAFU "port_uafu" @@ -91,6 +92,7 @@ enum fpga_id_type { #define FME_FEATURE_ID_NIOS_SPI 0xd #define FME_FEATURE_ID_I2C_MASTER 0xf #define FME_FEATURE_ID_ETH_GROUP 0x10 +#define FME_FEATURE_ID_PMCI 0x12 #define PORT_FEATURE_ID_HEADER FEATURE_ID_FIU_HEADER #define PORT_FEATURE_ID_ERROR 0x10 diff --git a/drivers/raw/ifpga/base/ifpga_feature_dev.c b/drivers/raw/ifpga/base/ifpga_feature_dev.c index dbecc7b..0a00af1 100644 --- a/drivers/raw/ifpga/base/ifpga_feature_dev.c +++ b/drivers/raw/ifpga/base/ifpga_feature_dev.c @@ -227,6 +227,8 @@ int port_clear_error(struct ifpga_port_hw *port) &fme_i2c_master_ops),}, {FEATURE_DRV(FME_FEATURE_ID_ETH_GROUP, FME_FEATURE_ETH_GROUP, &fme_eth_group_ops),}, + {FEATURE_DRV(FME_FEATURE_ID_PMCI, FME_FEATURE_PMCI, + &fme_pmci_ops),}, {0, NULL, NULL}, /* end of arrary */ }; diff --git a/drivers/raw/ifpga/base/ifpga_feature_dev.h b/drivers/raw/ifpga/base/ifpga_feature_dev.h index b355d22..a637eb5 100644 --- a/drivers/raw/ifpga/base/ifpga_feature_dev.h +++ b/drivers/raw/ifpga/base/ifpga_feature_dev.h @@ -178,6 +178,7 @@ int do_pr(struct ifpga_hw *hw, u32 port_id, const char *buffer, u32 size, extern struct ifpga_feature_ops fme_i2c_master_ops; extern struct ifpga_feature_ops fme_eth_group_ops; extern struct ifpga_feature_ops fme_nios_spi_master_ops; +extern struct ifpga_feature_ops fme_pmci_ops; int port_get_prop(struct ifpga_port_hw *port, struct feature_prop *prop); int port_set_prop(struct ifpga_port_hw *port, struct feature_prop *prop); diff --git a/drivers/raw/ifpga/base/ifpga_fme.c b/drivers/raw/ifpga/base/ifpga_fme.c index 43c7b9c..4d089d2 100644 --- a/drivers/raw/ifpga/base/ifpga_fme.c +++ b/drivers/raw/ifpga/base/ifpga_fme.c @@ -983,11 +983,25 @@ static int fme_spi_init(struct ifpga_feature *feature) altera_spi_init(spi_master); - max10 = intel_max10_device_probe(spi_master, 0); - if (!max10) { + max10 = opae_zmalloc(sizeof(*max10)); + if (!max10) + goto release_dev; + + max10->spi_master = spi_master; + max10->type = M10_N3000; + + max10->spi_tran_dev = spi_transaction_init(spi_master, 0); + if (!max10->spi_tran_dev) { + dev_err(fme, "%s spi tran init fail\n", __func__); + goto free_max10; + } + + /* init the max10 device */ + ret = intel_max10_device_init(max10); + if (ret) { ret = -ENODEV; dev_err(fme, "max10 init fail\n"); - goto spi_fail; + goto release_spi_tran_dev; } fme->max10_dev = max10; @@ -1002,7 +1016,12 @@ static int fme_spi_init(struct ifpga_feature *feature) max10_fail: intel_max10_device_remove(fme->max10_dev); -spi_fail: +release_spi_tran_dev: + if (max10->spi_tran_dev) + spi_transaction_remove(max10->spi_tran_dev); +free_max10: + opae_free(max10); +release_dev: altera_spi_release(spi_master); return ret; } @@ -1011,8 +1030,10 @@ static void fme_spi_uinit(struct ifpga_feature *feature) { struct ifpga_fme_hw *fme = (struct ifpga_fme_hw *)feature->parent; - if (fme->max10_dev) + if (fme->max10_dev) { intel_max10_device_remove(fme->max10_dev); + opae_free(fme->max10_dev); + } } struct ifpga_feature_ops fme_spi_master_ops = { @@ -1157,20 +1178,30 @@ static int fme_nios_spi_init(struct ifpga_feature *feature) /* 3. init the spi master*/ altera_spi_init(spi_master); + max10 = opae_zmalloc(sizeof(*max10)); + if (!max10) + goto release_dev; + + max10->spi_master = spi_master; + max10->type = M10_N3000; + + max10->spi_tran_dev = spi_transaction_init(spi_master, 0); + if (!max10->spi_tran_dev) { + dev_err(fme, "%s spi tran init fail\n", __func__); + goto free_max10; + } + /* init the max10 device */ - max10 = intel_max10_device_probe(spi_master, 0); - if (!max10) { + ret = intel_max10_device_init(max10); + if (ret) { ret = -ENODEV; dev_err(fme, "max10 init fail\n"); - goto release_dev; + goto release_spi_tran_dev; } fme->max10_dev = max10; - max10->bus = hw->pci_data->bus; - fme_get_board_interface(fme); - mgr->sensor_list = &max10->opae_sensor_list; /* SPI self test */ @@ -1187,6 +1218,11 @@ static int fme_nios_spi_init(struct ifpga_feature *feature) spi_fail: intel_max10_device_remove(fme->max10_dev); +release_spi_tran_dev: + if (max10->spi_tran_dev) + spi_transaction_remove(max10->spi_tran_dev); +free_max10: + opae_free(max10); release_dev: altera_spi_release(spi_master); return -ENODEV; @@ -1197,8 +1233,10 @@ static void fme_nios_spi_uinit(struct ifpga_feature *feature) struct ifpga_fme_hw *fme = (struct ifpga_fme_hw *)feature->parent; release_sec_mgr(fme); - if (fme->max10_dev) + if (fme->max10_dev) { intel_max10_device_remove(fme->max10_dev); + opae_free(fme->max10_dev); + } } struct ifpga_feature_ops fme_nios_spi_master_ops = { @@ -1230,7 +1268,7 @@ static int i2c_mac_rom_test(struct altera_i2c_dev *dev) } if (memcmp(buf, read_buf, strlen(string))) { - dev_err(NULL, "%s test fail!\n", __func__); + dev_info(NULL, "%s test fail!\n", __func__); return -EFAULT; } @@ -1499,3 +1537,81 @@ int fme_mgr_get_sensor_value(struct ifpga_fme_hw *fme, return 0; } + +static int fme_pmci_init(struct ifpga_feature *feature) +{ + struct ifpga_fme_hw *fme = (struct ifpga_fme_hw *)feature->parent; + struct intel_max10_device *max10; + struct ifpga_hw *hw; + struct opae_manager *mgr; + opae_share_data *sd = NULL; + int ret = 0; + + hw = fme->parent; + if (!hw) + return -ENODEV; + + mgr = hw->adapter->mgr; + if (!mgr) + return -ENODEV; + + dev_info(fme, "FME PMCI Init.\n"); + dev_debug(fme, "FME PMCI base addr %p.\n", + feature->addr); + + max10 = opae_zmalloc(sizeof(*max10)); + if (!max10) + return -ENOMEM; + + max10->type = M10_N6000; + max10->mmio = feature->addr; + if (hw->adapter && hw->adapter->shm.ptr) { + sd = (opae_share_data *)hw->adapter->shm.ptr; + max10->bmc_ops.mutex = &sd->spi_mutex; + } else { + max10->bmc_ops.mutex = NULL; + } + + /* init the max10 device */ + ret = intel_max10_device_init(max10); + if (ret) { + dev_err(fme, "max10 init fail\n"); + goto free_max10; + } + + fme->max10_dev = max10; + max10->bus = hw->pci_data->bus; + fme_get_board_interface(fme); + mgr->sensor_list = &max10->opae_sensor_list; + + ret = init_sec_mgr(fme); + if (ret) { + dev_err(fme, "security manager init fail\n"); + goto release_max10; + } + + return ret; + +release_max10: + intel_max10_device_remove(max10); +free_max10: + opae_free(max10); + + return ret; +} + +static void fme_pmci_uinit(struct ifpga_feature *feature) +{ + struct ifpga_fme_hw *fme = (struct ifpga_fme_hw *)feature->parent; + + release_sec_mgr(fme); + if (fme->max10_dev) { + intel_max10_device_remove(fme->max10_dev); + opae_free(fme->max10_dev); + } +} + +struct ifpga_feature_ops fme_pmci_ops = { + .init = fme_pmci_init, + .uinit = fme_pmci_uinit, +}; diff --git a/drivers/raw/ifpga/base/opae_intel_max10.c b/drivers/raw/ifpga/base/opae_intel_max10.c index 9d82fb0..901a258 100644 --- a/drivers/raw/ifpga/base/opae_intel_max10.c +++ b/drivers/raw/ifpga/base/opae_intel_max10.c @@ -4,51 +4,42 @@ #include "opae_intel_max10.h" #include +#include "opae_osdep.h" -int max10_reg_read(struct intel_max10_device *dev, - unsigned int reg, unsigned int *val) +int max10_sys_read(struct intel_max10_device *dev, + unsigned int offset, unsigned int *val) { - if (!dev) + if (!dev || !dev->ops->reg_read) return -ENODEV; - dev_debug(dev, "%s: bus:0x%x, reg:0x%x\n", __func__, dev->bus, reg); - - return spi_transaction_read(dev->spi_tran_dev, - reg, 4, (unsigned char *)val); + return dev->ops->reg_read(dev, dev->csr->base + offset, val); } -int max10_reg_write(struct intel_max10_device *dev, - unsigned int reg, unsigned int val) +int max10_sys_write(struct intel_max10_device *dev, + unsigned int offset, unsigned int val) { - unsigned int tmp = val; - - if (!dev) + if (!dev || !dev->ops->reg_write) return -ENODEV; - dev_debug(dev, "%s: bus:0x%x, reg:0x%x, val:0x%x\n", __func__, - dev->bus, reg, val); - - return spi_transaction_write(dev->spi_tran_dev, - reg, 4, (unsigned char *)&tmp); + return dev->ops->reg_write(dev, dev->csr->base + offset, val); } -int max10_sys_read(struct intel_max10_device *dev, +int max10_reg_read(struct intel_max10_device *dev, unsigned int offset, unsigned int *val) { - if (!dev) + if (!dev || !dev->ops->reg_read) return -ENODEV; - - return max10_reg_read(dev, dev->base + offset, val); + return dev->ops->reg_read(dev, offset, val); } -int max10_sys_write(struct intel_max10_device *dev, +int max10_reg_write(struct intel_max10_device *dev, unsigned int offset, unsigned int val) { - if (!dev) + if (!dev || !dev->ops->reg_write) return -ENODEV; - return max10_reg_write(dev, dev->base + offset, val); + return dev->ops->reg_write(dev, offset, val); } int max10_sys_update_bits(struct intel_max10_device *dev, unsigned int offset, @@ -67,6 +58,135 @@ int max10_sys_update_bits(struct intel_max10_device *dev, unsigned int offset, return max10_sys_write(dev, offset, temp); } +static int max10_spi_read(struct intel_max10_device *dev, + unsigned int addr, unsigned int *val) +{ + if (!dev) + return -ENODEV; + + dev_debug(dev, "%s: bus:0x%x, addr:0x%x\n", __func__, dev->bus, addr); + + return spi_transaction_read(dev->spi_tran_dev, + addr, 4, (unsigned char *)val); +} + +static int max10_spi_write(struct intel_max10_device *dev, + unsigned int addr, unsigned int val) +{ + unsigned int tmp = val; + + if (!dev) + return -ENODEV; + + dev_debug(dev, "%s: bus:0x%x, reg:0x%x, val:0x%x\n", __func__, + dev->bus, addr, val); + + return spi_transaction_write(dev->spi_tran_dev, + addr, 4, (unsigned char *)&tmp); +} + +static int indirect_bus_clr_cmd(struct intel_max10_device *dev) +{ + unsigned int cmd; + int ret; + + opae_writel(0, dev->mmio + INDIRECT_CMD_OFF); + + ret = opae_readl_poll_timeout((dev->mmio + INDIRECT_CMD_OFF), cmd, + (!cmd), INDIRECT_INT_US, INDIRECT_TIMEOUT_US); + + if (ret) + dev_err(dev, "%s timed out on clearing cmd 0x%x\n", + __func__, cmd); + + return ret; +} + +static int max10_indirect_reg_read(struct intel_max10_device *dev, + unsigned int addr, unsigned int *val) +{ + unsigned int cmd; + int ret; + + if (!dev) + return -ENODEV; + + pthread_mutex_lock(dev->bmc_ops.mutex); + + cmd = opae_readl(dev->mmio + INDIRECT_CMD_OFF); + if (cmd) + dev_warn(dev, "%s non-zero cmd 0x%x\n", __func__, cmd); + + opae_writel(addr, dev->mmio + INDIRECT_ADDR_OFF); + + opae_writel(INDIRECT_CMD_RD, dev->mmio + INDIRECT_CMD_OFF); + + ret = opae_readl_poll_timeout((dev->mmio + INDIRECT_CMD_OFF), cmd, + (cmd & INDIRECT_CMD_ACK), INDIRECT_INT_US, + INDIRECT_TIMEOUT_US); + + *val = opae_readl(dev->mmio + INDIRECT_RD_OFF); + + if (ret) + dev_err(dev, "%s timed out on reg 0x%x cmd 0x%x\n", + __func__, addr, cmd); + + if (indirect_bus_clr_cmd(dev)) + ret = -ETIME; + + pthread_mutex_unlock(dev->bmc_ops.mutex); + + return ret; +} + +static int max10_indirect_reg_write(struct intel_max10_device *dev, + unsigned int addr, unsigned int val) +{ + unsigned int cmd; + int ret; + + if (!dev) + return -ENODEV; + + pthread_mutex_lock(dev->bmc_ops.mutex); + + cmd = readl(dev->mmio + INDIRECT_CMD_OFF); + + if (cmd) + dev_warn(dev, "%s non-zero cmd 0x%x\n", __func__, cmd); + + opae_writel(val, dev->mmio + INDIRECT_WR_OFF); + + opae_writel(addr, dev->mmio + INDIRECT_ADDR_OFF); + + writel(INDIRECT_CMD_WR, dev->mmio + INDIRECT_CMD_OFF); + + ret = opae_readl_poll_timeout((dev->mmio + INDIRECT_CMD_OFF), cmd, + (cmd & INDIRECT_CMD_ACK), INDIRECT_INT_US, + INDIRECT_TIMEOUT_US); + + if (ret) + dev_err(dev, "%s timed out on reg 0x%x cmd 0x%x\n", + __func__, addr, cmd); + + if (indirect_bus_clr_cmd(dev)) + ret = -ETIME; + + pthread_mutex_unlock(dev->bmc_ops.mutex); + + return ret; +} + +const struct m10bmc_regmap m10bmc_pmci_regmap = { + .reg_write = max10_indirect_reg_write, + .reg_read = max10_indirect_reg_read, +}; + +const struct m10bmc_regmap m10bmc_n3000_regmap = { + .reg_write = max10_spi_write, + .reg_read = max10_spi_read, +}; + static struct max10_compatible_id max10_id_table[] = { {.compatible = MAX10_PAC,}, {.compatible = MAX10_PAC_N3000,}, @@ -561,11 +681,9 @@ static int check_max10_version(struct intel_max10_device *dev) &v)) { if (v != 0xffffffff) { dev_info(dev, "secure MAX10 detected\n"); - dev->base = MAX10_SEC_BASE_ADDR; dev->flags |= MAX10_FLAGS_SECURE; } else { dev_info(dev, "non-secure MAX10 detected\n"); - dev->base = MAX10_BASE_ADDR; } return 0; } @@ -648,73 +766,75 @@ static int max10_staging_area_init(struct intel_max10_device *dev) return 0; } -struct intel_max10_device * -intel_max10_device_probe(struct altera_spi_device *spi, - int chipselect) -{ - struct intel_max10_device *dev; - int ret; - unsigned int val; +static const struct m10bmc_csr m10bmc_spi_csr = { + .base = MAX10_SEC_BASE_ADDR, + .build_version = MAX10_BUILD_VER, + .fw_version = NIOS2_FW_VERSION, + .fpga_page_info = FPGA_PAGE_INFO, + .doorbell = MAX10_DOORBELL, + .auth_result = MAX10_AUTH_RESULT, +}; - dev = opae_malloc(sizeof(*dev)); - if (!dev) - return NULL; +static const struct m10bmc_csr m10bmc_pmci_csr = { + .base = M10BMC_PMCI_SYS_BASE, + .build_version = M10BMC_PMCI_BUILD_VER, + .fw_version = NIOS2_PMCI_FW_VERSION, + .fpga_page_info = M10BMC_PMCI_FPGA_CONF_STS, + .doorbell = M10BMC_PMCI_DOORBELL, + .auth_result = M10BMC_PMCI_AUTH_RESULT, +}; - TAILQ_INIT(&dev->opae_sensor_list); +int +intel_max10_device_init(struct intel_max10_device *dev) +{ + int ret = 0; - dev->spi_master = spi; + TAILQ_INIT(&dev->opae_sensor_list); - dev->spi_tran_dev = spi_transaction_init(spi, chipselect); - if (!dev->spi_tran_dev) { - dev_err(dev, "%s spi tran init fail\n", __func__); - goto free_dev; - } - /* check the max10 version */ - ret = check_max10_version(dev); - if (ret) { - dev_err(dev, "Failed to find max10 hardware!\n"); - goto free_dev; - } + if (dev->type == M10_N3000) { + dev->ops = &m10bmc_n3000_regmap; + dev->csr = &m10bmc_spi_csr; - /* load the MAX10 device table */ - ret = init_max10_device_table(dev); - if (ret) { - dev_err(dev, "Init max10 device table fail\n"); - goto free_dev; - } + /* check the max10 version */ + ret = check_max10_version(dev); + if (ret) { + dev_err(dev, "Failed to find max10 hardware!\n"); + return ret; + } - /* init max10 devices, like sensor*/ - if (dev->flags & MAX10_FLAGS_SECURE) - ret = max10_secure_hw_init(dev); - else - ret = max10_non_secure_hw_init(dev); - if (ret) { - dev_err(dev, "Failed to init max10 hardware!\n"); - goto free_dtb; - } + /* load the MAX10 device table */ + ret = init_max10_device_table(dev); + if (ret) { + dev_err(dev, "Init max10 device table fail\n"); + return ret; + } - /* read FPGA loading information */ - ret = max10_sys_read(dev, FPGA_PAGE_INFO, &val); - if (ret) { - dev_err(dev, "fail to get FPGA loading info\n"); - goto release_max10_hw; - } - dev_info(dev, "FPGA loaded from %s Image\n", val ? "User" : "Factory"); + /* init max10 devices, like sensor*/ + if (dev->flags & MAX10_FLAGS_SECURE) + ret = max10_secure_hw_init(dev); + else + ret = max10_non_secure_hw_init(dev); + if (ret) { + dev_err(dev, "Failed to init max10 hardware!\n"); + opae_free(dev->fdt_root); + return ret; + } + } else if (dev->type == M10_N6000) { + dev->ops = &m10bmc_pmci_regmap; + dev->csr = &m10bmc_pmci_csr; + dev->staging_area_size = MAX_STAGING_AREA_SIZE; + dev->flags |= MAX10_FLAGS_SECURE; - return dev; + ret = pthread_mutex_init(&dev->bmc_ops.lock, NULL); + if (ret) + return ret; -release_max10_hw: - max10_sensor_uinit(dev); -free_dtb: - if (dev->fdt_root) - opae_free(dev->fdt_root); - if (dev->spi_tran_dev) - spi_transaction_remove(dev->spi_tran_dev); -free_dev: - opae_free(dev); + if (!dev->bmc_ops.mutex) + dev->bmc_ops.mutex = &dev->bmc_ops.lock; + } - return NULL; + return ret; } int intel_max10_device_remove(struct intel_max10_device *dev) @@ -722,15 +842,14 @@ int intel_max10_device_remove(struct intel_max10_device *dev) if (!dev) return 0; - max10_sensor_uinit(dev); - - if (dev->spi_tran_dev) - spi_transaction_remove(dev->spi_tran_dev); + pthread_mutex_destroy(&dev->bmc_ops.lock); - if (dev->fdt_root) - opae_free(dev->fdt_root); + if (dev->type == M10_N3000) { + max10_sensor_uinit(dev); - opae_free(dev); + if (dev->fdt_root) + opae_free(dev->fdt_root); + } return 0; } diff --git a/drivers/raw/ifpga/base/opae_intel_max10.h b/drivers/raw/ifpga/base/opae_intel_max10.h index e761d7e..0d31196 100644 --- a/drivers/raw/ifpga/base/opae_intel_max10.h +++ b/drivers/raw/ifpga/base/opae_intel_max10.h @@ -7,6 +7,9 @@ #include "opae_osdep.h" #include "opae_spi.h" +#include "ifpga_compat.h" + +struct intel_max10_device; struct max10_compatible_id { char compatible[128]; @@ -29,6 +32,52 @@ struct max10_compatible_id { /** List of opae sensors */ TAILQ_HEAD(opae_sensor_list, opae_sensor_info); +/* Supported MAX10 BMC types */ +enum m10bmc_type { + M10_N3000, + M10_N6000 +}; + +struct regmap_range { + unsigned int min; + unsigned int max; +}; + +struct m10bmc_regmap { + int (*reg_write)(struct intel_max10_device *dev, + unsigned int reg, unsigned int val); + int (*reg_read)(struct intel_max10_device *dev, + unsigned int reg, unsigned int *val); + const struct regmap_range *range; + int num_ranges; +}; + +struct m10bmc_csr { + unsigned int base; + unsigned int build_version; + unsigned int fw_version; + unsigned int fpga_page_info; + unsigned int doorbell; + unsigned int auth_result; +}; + +/** + * struct m10bmc_ops - device specific operations + * @lock: prevent concurrent flash read/write + * @mutex: prevent concurrent bmc read/write + * @flash_read: read a block of data from flash + * @flash_write: write a block of data to flash + */ +struct m10bmc_ops { + pthread_mutex_t lock; + pthread_mutex_t *mutex; + int (*check_flash_range)(u32 start, u32 end); + int (*flash_read)(struct intel_max10_device *dev, u32 addr, + void *buf, u32 size); + int (*flash_write)(struct intel_max10_device *dev, u32 addr, + void *buf, u32 size); +}; + struct intel_max10_device { unsigned int flags; /*max10 hardware capability*/ struct altera_spi_device *spi_master; @@ -40,6 +89,11 @@ struct intel_max10_device { struct opae_sensor_list opae_sensor_list; u32 staging_area_base; u32 staging_area_size; + enum m10bmc_type type; + const struct m10bmc_regmap *ops; + const struct m10bmc_csr *csr; + struct m10bmc_ops bmc_ops; + u8 *mmio; /* mmio address for PMCI */ }; /* retimer speed */ @@ -87,6 +141,7 @@ struct opae_retimer_status { /* System Registers */ #define MAX10_BASE_ADDR 0x300400 #define MAX10_SEC_BASE_ADDR 0x300800 + /* Register offset of system registers */ #define NIOS2_FW_VERSION 0x0 #define MAX10_MACADDR1 0x10 @@ -151,6 +206,32 @@ struct opae_retimer_status { #define SEC_STATUS_NON_INC 0x6 #define SEC_STATUS_ERASE_FAIL 0x7 #define SEC_STATUS_WEAROUT 0x8 +#define SEC_STATUS_PMCI_SS_FAIL 0x9 +#define SEC_STATUS_FLASH_CMD 0xa +#define SEC_STATUS_FACTORY_UNVERITY 0xb +#define SEC_STATUS_FACTORY_ACTIVE 0xc +#define SEC_STATUS_POWER_DOWN 0xd +#define SEC_STATUS_CANCELLATION 0xe +#define SEC_STATUS_HASH 0xf +#define SEC_STATUS_FLASH_ACCESS 0x10 +#define SEC_STATUS_SDM_PR_CERT 0x20 +#define SEC_STATUS_SDM_PR_NIOS_BUSY 0x21 +#define SEC_STATUS_SDM_PR_TIMEOUT 0x22 +#define SEC_STATUS_SDM_PR_FAILED 0x23 +#define SEC_STATUS_SDM_PR_MISMATCH 0x24 +#define SEC_STATUS_SDM_PR_FLUSH 0x25 +#define SEC_STATUS_SDM_SR_CERT 0x30 +#define SEC_STATUS_SDM_SR_NIOS_BUSY 0x31 +#define SEC_STATUS_SDM_SR_TIMEOUT 0x32 +#define SEC_STATUS_SDM_SR_FAILED 0x33 +#define SEC_STATUS_SDM_SR_MISMATCH 0x34 +#define SEC_STATUS_SDM_SR_FLUSH 0x35 +#define SEC_STATUS_SDM_KEY_CERT 0x40 +#define SEC_STATUS_SDM_KEY_NIOS_BUSY 0x41 +#define SEC_STATUS_SDM_KEY_TIMEOUT 0x42 +#define SEC_STATUS_SDM_KEY_FAILED 0x43 +#define SEC_STATUS_SDM_KEY_MISMATCH 0x44 +#define SEC_STATUS_SDM_KEY_FLUSH 0x45 #define SEC_STATUS_NIOS_OK 0x80 #define SEC_STATUS_USER_OK 0x81 #define SEC_STATUS_FACTORY_OK 0x82 @@ -158,9 +239,65 @@ struct opae_retimer_status { #define SEC_STATUS_FACTORY_FAIL 0x84 #define SEC_STATUS_NIOS_FLASH_ERR 0x85 #define SEC_STATUS_FPGA_FLASH_ERR 0x86 +#define SEC_STATUS_MAX SEC_STATUS_FPGA_FLASH_ERR + +/* Authentication status */ +#define SEC_AUTH_G(v) ((v) & 0xff) +#define AUTH_STAT_PASS 0x0 +#define AUTH_STAT_B0_MAGIC 0x1 +#define AUTH_STAT_CONLEN 0x2 +#define AUTH_STAT_CONTYPE 0x3 +#define AUTH_STAT_B1_MAGIC 0x4 +#define AUTH_STAT_ROOT_MAGIC 0x5 +#define AUTH_STAT_CURVE_MAGIC 0x6 +#define AUTH_STAT_PERMISSION 0x7 +#define AUTH_STAT_KEY_ID 0x8 +#define AUTH_STAT_CSK_MAGIC 0x9 +#define AUTH_STAT_CSK_CURVE 0xa +#define AUTH_STAT_CSK_PERMISSION 0xb +#define AUTH_STAT_CSK_ID 0xc +#define AUTH_STAT_CSK_SM 0xd +#define AUTH_STAT_B0_E_MAGIC 0xe +#define AUTH_STAT_B0_E_SIGN 0xf +#define AUTH_STAT_RK_P 0x10 +#define AUTH_STAT_RE_SHA 0x11 +#define AUTH_STAT_CSK_SHA 0x12 +#define AUTH_STAT_B0_SHA 0x13 +#define AUTH_STAT_KEY_INV 0x14 +#define AUTH_STAT_KEY_CAN 0x15 +#define AUTH_STAT_UP_SHA 0x16 +#define AUTH_STAT_CAN_SHA 0x17 +#define AUTH_STAT_HASH 0x18 +#define AUTH_STAT_INV_ID 0x19 +#define AUTH_STAT_KEY_PROG 0x1a +#define AUTH_STAT_INV_BC 0x1b +#define AUTH_STAT_INV_SLOT 0x1c +#define AUTH_STAT_IN_OP 0x1d +#define AUTH_STAT_TIME_OUT 0X1e +#define AUTH_STAT_SHA_TO 0x1f +#define AUTH_STAT_CSK_TO 0x20 +#define AUTH_STAT_B0_TO 0x21 +#define AUTH_STAT_UP_TO 0x22 +#define AUTH_STAT_CAN_TO 0x23 +#define AUTH_STAT_HASH_TO 0x24 +#define AUTH_STAT_AUTH_IDLE 0xfe +#define AUTH_STAT_GA_FAIL 0xff +#define AUTH_STAT_S_ERR 0x8000 +#define AUTH_STAT_S_MN 0x8001 +#define AUTH_STAT_SH_CRC 0x8002 +#define AUTH_STAT_SD_CRC 0x8003 +#define AUTH_STAT_SD_LEN 0x8004 +#define AUTH_STAT_S_ID 0x8005 +#define AUTH_STAT_S_THR 0x8006 +#define AUTH_STAT_S_TO 0x8007 +#define AUTH_STAT_S_EN 0x8008 +#define AUTH_STAT_SF 0x8009 +#define AUTH_STAT_MAX AUTH_STAT_SF + #define CONFIG_SEL BIT(28) #define CONFIG_SEL_S(v) (((v) & 0x1) << 28) #define REBOOT_REQ BIT(29) +#define REBOOT_DISABLED BIT(30) #define MAX10_AUTH_RESULT 0x404 /* PKVL related registers, in system register region */ @@ -185,19 +322,21 @@ struct opae_retimer_status { #define MAX_STAGING_AREA_BASE 0xffffffff #define MAX_STAGING_AREA_SIZE 0x3800000 -int max10_reg_read(struct intel_max10_device *dev, - unsigned int reg, unsigned int *val); -int max10_reg_write(struct intel_max10_device *dev, - unsigned int reg, unsigned int val); +#define m10bmc_base(max10) ((max10)->csr->base) +#define doorbell_reg(max10) ((max10)->csr->doorbell) +#define auth_result_reg(max10) ((max10)->csr->auth_result) + int max10_sys_read(struct intel_max10_device *dev, unsigned int offset, unsigned int *val); int max10_sys_write(struct intel_max10_device *dev, unsigned int offset, unsigned int val); +int max10_reg_read(struct intel_max10_device *dev, + unsigned int offset, unsigned int *val); +int max10_reg_write(struct intel_max10_device *dev, + unsigned int offset, unsigned int val); int max10_sys_update_bits(struct intel_max10_device *dev, unsigned int offset, unsigned int msk, unsigned int val); -struct intel_max10_device * -intel_max10_device_probe(struct altera_spi_device *spi, - int chipselect); +int intel_max10_device_init(struct intel_max10_device *dev); int intel_max10_device_remove(struct intel_max10_device *dev); @@ -254,4 +393,80 @@ struct opae_sensor_info { unsigned int value_reg; }; +/* indirect access for PMCI */ +#define PMCI_INDIRECT_BASE 0x400 +#define INDIRECT_CMD_OFF (PMCI_INDIRECT_BASE + 0x0) +#define INDIRECT_CMD_RD BIT(0) +#define INDIRECT_CMD_WR BIT(1) +#define INDIRECT_CMD_ACK BIT(2) + +#define INDIRECT_ADDR_OFF (PMCI_INDIRECT_BASE + 0x4) +#define INDIRECT_RD_OFF (PMCI_INDIRECT_BASE + 0x8) +#define INDIRECT_WR_OFF (PMCI_INDIRECT_BASE + 0xc) + +#define INDIRECT_INT_US 1 +#define INDIRECT_TIMEOUT_US 10000 + +#define M10BMC_PMCI_SYS_BASE 0x0 +#define M10BMC_PMCI_SYS_END 0xfff + +#define M10BMC_PMCI_BUILD_VER 0x0 +#define NIOS2_PMCI_FW_VERSION 0x4 + +#define M10BMC_PMCI_PWR_STATE 0xb4 +#define PMCI_PRIMARY_IMAGE_PAGE GENMASK(10, 8) + +#define M10BMC_PMCI_DOORBELL 0x1c0 +#define PMCI_DRBL_REBOOT_DISABLED BIT(1) +#define M10BMC_PMCI_AUTH_RESULT 0x1c4 + +#define M10BMC_PMCI_MAX10_RECONF 0xfc +#define PMCI_MAX10_REBOOT_REQ BIT(0) +#define PMCI_MAX10_REBOOT_PAGE BIT(1) + +#define M10BMC_PMCI_FPGA_RECONF 0xb8 +#define PMCI_FPGA_RECONF_PAGE GENMASK(22, 20) +#define PMCI_FPGA_RP_LOAD BIT(23) + +#define M10BMC_PMCI_FPGA_POC 0xb0 +#define PMCI_FPGA_POC BIT(0) +#define PMCI_NIOS_REQ_CLEAR BIT(1) +#define PMCI_NIOS_STATUS GENMASK(5, 4) +#define NIOS_STATUS_IDLE 0 +#define NIOS_STATUS_SUCCESS 1 +#define NIOS_STATUS_FAIL 2 +#define PMCI_USER_IMAGE_PAGE GENMASK(10, 8) +#define POC_USER_IMAGE_1 1 +#define POC_USER_IMAGE_2 2 +#define PMCI_FACTORY_IMAGE_SEL BIT(31) + +#define M10BMC_PMCI_FPGA_CONF_STS 0xa0 +#define PMCI_FPGA_BOOT_PAGE GENMASK(2, 0) +#define PMCI_FPGA_CONFIGURED BIT(3) + +#define M10BMC_PMCI_SDM_CTRL_STS 0x230 +#define PMCI_SDM_IMG_REQ BIT(0) +#define PMCI_SDM_STAT GENMASK(23, 16) + +#define SDM_STAT_DONE 0x0 +#define SDM_STAT_PROV 0x1 +#define SDM_STAT_BUSY 0x2 +#define SDM_STAT_INV 0x3 +#define SDM_STAT_FAIL 0x4 +#define SDM_STAT_BMC_BUSY 0x5 +#define SDM_STAT_TO 0x6 +#define SDM_STAT_DB 0x7 +#define SDM_STAT_CON_R 0x8 +#define SDM_STAT_CON_E 0x9 +#define SDM_STAT_WAIT 0xa +#define SDM_STAT_RTO 0xb +#define SDM_STAT_SB 0xc +#define SDM_STAT_RE 0xd +#define SDM_STAT_PDD 0xe +#define SDM_STAT_ISC 0xf +#define SDM_STAT_SIC 0x10 +#define SDM_STAT_NO_PROV 0x11 +#define SDM_STAT_CS_MIS 0x12 +#define SDM_STAT_PR_MIS 0x13 +#define SDM_STAT_MAX SDM_STAT_PR_MIS #endif diff --git a/drivers/raw/ifpga/base/opae_osdep.h b/drivers/raw/ifpga/base/opae_osdep.h index 18e6a11..033b7e0 100644 --- a/drivers/raw/ifpga/base/opae_osdep.h +++ b/drivers/raw/ifpga/base/opae_osdep.h @@ -79,15 +79,38 @@ struct uuid { #define time_before(a, b) time_after(b, a) #define opae_memset(a, b, c) memset((a), (b), (c)) -#define opae_readq_poll_timeout(addr, val, cond, invl, timeout)\ -({ \ - int wait = 0; \ - for (; wait <= timeout; wait += invl) { \ - (val) = opae_readq(addr); \ - if (cond) \ - break; \ - udelay(invl); \ - } \ - (cond) ? 0 : -ETIMEDOUT; \ +#define readx_poll_timeout(op, val, cond, invl, timeout, args...) \ +({ \ + unsigned long __wait = 0; \ + unsigned long __invl = (invl); \ + unsigned long __timeout = (timeout); \ + for (; __wait <= __timeout; __wait += __invl) { \ + (val) = op(args); \ + if (cond) \ + break; \ + udelay(__invl); \ + } \ + (cond) ? 0 : -ETIMEDOUT; \ }) + +#define opae_readq_poll_timeout(addr, val, cond, invl, timeout) \ + readx_poll_timeout(opae_readq, val, cond, invl, timeout, addr) + +#define opae_readl_poll_timeout(addr, val, cond, invl, timeout) \ + readx_poll_timeout(opae_readl, val, cond, invl, timeout, addr) + +#define opae_readw_poll_timeout(addr, val, cond, invl, timeout) \ + readx_poll_timeout(opae_readw, val, cond, invl, timeout, addr) + +#define opae_readb_poll_timeout(addr, val, cond, invl, timeout) \ + readx_poll_timeout(opae_readb, val, cond, invl, timeout, addr) + +#define opae_max10_read_poll_timeout(dev, addr, value, cond, invl, timeout) \ +({ \ + int __ret, __tmp; \ + __tmp = readx_poll_timeout(max10_sys_read, __ret, __ret || (cond), \ + invl, timeout, (dev), (addr), &(value)); \ + __ret?:__tmp; \ +}) + #endif From patchwork Fri Jun 17 07:19:33 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Wei Huang X-Patchwork-Id: 112961 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 0A79FA0093; Fri, 17 Jun 2022 09:12:04 +0200 (CEST) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 377804282D; Fri, 17 Jun 2022 09:11:54 +0200 (CEST) Received: from mga04.intel.com (mga04.intel.com [192.55.52.120]) by mails.dpdk.org (Postfix) with ESMTP id 9B22A427F9; Fri, 17 Jun 2022 09:11:51 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1655449911; x=1686985911; h=from:to:cc:subject:date:message-id:in-reply-to: references; bh=79rtx4immMq2yUG1mzF+OCOGCUjIIu6TZZAJ4vrbwuY=; b=L3z89vee7FOsr97zZIFponW2asHEXWuhY1wZXaMGKg1wDWk1VYx3EHIM PDEgaU4lxtFRX2yYzJ2QUhy/iBfRWoISjFxsScw5x405iOa9ZuvJObH3p HMlpRBmdCj3uLW/4e/oZ6cMaQDY8+3f+5FOAOkb9vJoZmf2T1j++P3FiY SJHm3jOyPi06CO5UuKMr/B0pDoeZQvmgKiSlaQ2FuwO+RsRzJfAQqd1ew Q3Kn8VuEYWVSNJ42VKh6VUvFY/aGIKZFQhsmXDHxOqYsPB+cB2E6I5YIP 9k/rq3wVO2qlEBEVWNPj99j8h5sUSMKo8bt/401afJge72A5PvlbLKq9J w==; X-IronPort-AV: E=McAfee;i="6400,9594,10380"; a="278236411" X-IronPort-AV: E=Sophos;i="5.92,306,1650956400"; d="scan'208";a="278236411" Received: from fmsmga005.fm.intel.com ([10.253.24.32]) by fmsmga104.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Jun 2022 00:11:51 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.92,306,1650956400"; d="scan'208";a="912502480" Received: from unknown (HELO zj-fpga-amt.sh.intel.com) ([10.238.175.102]) by fmsmga005.fm.intel.com with ESMTP; 17 Jun 2022 00:11:49 -0700 From: Wei Huang To: dev@dpdk.org, thomas@monjalon.net, nipun.gupta@nxp.com, hemant.agrawal@nxp.com Cc: stable@dpdk.org, rosen.xu@intel.com, tianfei.zhang@intel.com, qi.z.zhang@intel.com, Wei Huang Subject: [PATCH v3 2/4] raw/ifpga/base: update board information Date: Fri, 17 Jun 2022 03:19:33 -0400 Message-Id: <1655450375-10739-3-git-send-email-wei.huang@intel.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1655450375-10739-1-git-send-email-wei.huang@intel.com> References: <1654827900-10023-1-git-send-email-wei.huang@intel.com> <1655450375-10739-1-git-send-email-wei.huang@intel.com> X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org N6000 ADP platform has different definition of board information, they can be recognized after this patch. Signed-off-by: Wei Huang Acked-by: Tianfei Zhang Reviewed-by: Rosen Xu --- drivers/raw/ifpga/base/ifpga_defines.h | 101 +++++++++++++++---------- drivers/raw/ifpga/base/ifpga_fme.c | 121 ++++++++++++++++++++---------- drivers/raw/ifpga/base/ifpga_fme_error.c | 2 + drivers/raw/ifpga/base/ifpga_port_error.c | 2 +- drivers/raw/ifpga/base/opae_intel_max10.c | 45 +++++++++++ drivers/raw/ifpga/base/opae_intel_max10.h | 3 + 6 files changed, 194 insertions(+), 80 deletions(-) diff --git a/drivers/raw/ifpga/base/ifpga_defines.h b/drivers/raw/ifpga/base/ifpga_defines.h index f84ed1d..7c8fa89 100644 --- a/drivers/raw/ifpga/base/ifpga_defines.h +++ b/drivers/raw/ifpga/base/ifpga_defines.h @@ -268,6 +268,24 @@ struct feature_fme_bitstream_id { union { u64 csr; struct { + u8 build_patch:8; + u8 build_minor:8; + u8 build_major:8; + u8 fvl_bypass:1; + u8 mac_lightweight:1; + u8 disagregate:1; + u8 lightweiht:1; + u8 seu:1; + u8 ptp:1; + u8 reserve:2; + u8 interface:4; + u32 afu_revision:12; + u8 patch:4; + u8 minor:4; + u8 major:4; + u8 reserved:4; + } v1; + struct { u32 gitrepo_hash:32; /* GIT repository hash */ /* * HSSI configuration identifier: @@ -276,7 +294,8 @@ struct feature_fme_bitstream_id { * 2 - Ethernet */ u8 hssi_id:4; - u16 rsvd1:12; /* Reserved */ + u8 rsvd1:4; + u8 fim_type:8; /* Bitstream version patch number */ u8 bs_verpatch:4; /* Bitstream version minor number */ @@ -285,7 +304,7 @@ struct feature_fme_bitstream_id { u8 bs_vermajor:4; /* Bitstream version debug number */ u8 bs_verdebug:4; - }; + } v2; }; }; @@ -1672,31 +1691,6 @@ struct bts_header { #define check_support(n) (n == 1 ? "support" : "no") -/* bitstream id definition */ -struct fme_bitstream_id { - union { - u64 id; - struct { - u8 build_patch:8; - u8 build_minor:8; - u8 build_major:8; - u8 fvl_bypass:1; - u8 mac_lightweight:1; - u8 disagregate:1; - u8 lightweiht:1; - u8 seu:1; - u8 ptp:1; - u8 reserve:2; - u8 interface:4; - u32 afu_revision:12; - u8 patch:4; - u8 minor:4; - u8 major:4; - u8 reserved:4; - }; - }; -}; - enum board_interface { VC_8_10G = 0, VC_4_25G = 1, @@ -1705,10 +1699,30 @@ enum board_interface { VC_2_2_25G = 4, }; +enum fim_type { + BASE_ADP = 0, + BASE_FDK, + BASE_X16_ADP, + BASE_X16_FDK, + FIMA_10G_ADP, + FIMA_25G_ADP, + FIMA_100G_ADP, + FIMB_ADP, + FIMC_ADP +}; + +enum hssi_id { + NO_HSSI = 0, + PCIE_RP, + ETHER_NET +}; + enum pac_major { VISTA_CREEK = 0, RUSH_CREEK = 1, DARBY_CREEK = 2, + LIGHTNING_CREEK = 3, + ARROW_CREEK = 5, }; enum pac_minor { @@ -1720,23 +1734,30 @@ enum pac_minor { struct opae_board_info { enum pac_major major; enum pac_minor minor; - enum board_interface type; - - /* PAC features */ - u8 fvl_bypass; - u8 mac_lightweight; - u8 disaggregate; - u8 lightweight; - u8 seu; - u8 ptp; u32 boot_page; u32 max10_version; u32 nios_fw_version; - u32 nums_of_retimer; - u32 ports_per_retimer; - u32 nums_of_fvl; - u32 ports_per_fvl; + + union { + struct { /* N3000 specific */ + enum board_interface type; + u8 fvl_bypass; + u8 mac_lightweight; + u8 disaggregate; + u8 lightweight; + u8 seu; + u8 ptp; + u32 nums_of_retimer; + u32 ports_per_retimer; + u32 nums_of_fvl; + u32 ports_per_fvl; + }; + struct { + enum fim_type n6000_fim_type; + enum hssi_id n6000_hssi_id; + }; + }; }; #pragma pack(pop) diff --git a/drivers/raw/ifpga/base/ifpga_fme.c b/drivers/raw/ifpga/base/ifpga_fme.c index 4d089d2..608a352 100644 --- a/drivers/raw/ifpga/base/ifpga_fme.c +++ b/drivers/raw/ifpga/base/ifpga_fme.c @@ -790,19 +790,32 @@ struct ifpga_feature_ops fme_emif_ops = { .uinit = fme_emif_uinit, }; -static const char *board_type_to_string(u32 type) -{ - switch (type) { - case VC_8_10G: - return "VC_8x10G"; - case VC_4_25G: - return "VC_4x25G"; - case VC_2_1_25: - return "VC_2x1x25G"; - case VC_4_25G_2_25G: - return "VC_4x25G+2x25G"; - case VC_2_2_25G: - return "VC_2x2x25G"; +static const char *board_type_to_string(u32 board, u32 type) +{ + if (board == VISTA_CREEK) { + switch (type) { + case VC_8_10G: + return "8x10G"; + case VC_4_25G: + return "4x25G"; + case VC_2_1_25: + return "2x1x25G"; + case VC_4_25G_2_25G: + return "4x25G+2x25G"; + case VC_2_2_25G: + return "2x2x25G"; + break; + } + } else { + switch (type) { + case FIMA_10G_ADP: + return "2x4x10G"; + case FIMA_25G_ADP: + return "2x2x25G"; + case FIMA_100G_ADP: + return "2x100G"; + break; + } } return "unknown"; @@ -817,6 +830,12 @@ static const char *board_major_to_string(u32 major) return "RUSH_CREEK"; case DARBY_CREEK: return "DARBY_CREEK"; + case LIGHTNING_CREEK: + return "LIGHTNING_CREEK"; + case ARROW_CREEK: + return "ARROW_CREEK"; + default: + break; } return "unknown"; @@ -859,35 +878,56 @@ static int board_type_to_info(u32 type, static int fme_get_board_interface(struct ifpga_fme_hw *fme) { - struct fme_bitstream_id id; + struct feature_fme_bitstream_id id; struct ifpga_hw *hw; u32 val; + const char *type = NULL; + int ret; hw = fme->parent; if (!hw) return -ENODEV; - if (fme_hdr_get_bitstream_id(fme, &id.id)) + if (fme_hdr_get_bitstream_id(fme, &id.csr)) return -EINVAL; - fme->board_info.major = id.major; - fme->board_info.minor = id.minor; - fme->board_info.type = id.interface; - fme->board_info.fvl_bypass = id.fvl_bypass; - fme->board_info.mac_lightweight = id.mac_lightweight; - fme->board_info.lightweight = id.lightweiht; - fme->board_info.disaggregate = id.disagregate; - fme->board_info.seu = id.seu; - fme->board_info.ptp = id.ptp; + if (id.v1.major == ARROW_CREEK) { + fme->board_info.major = id.v2.bs_vermajor; + fme->board_info.minor = id.v2.bs_verminor; + fme->board_info.n6000_fim_type = id.v2.fim_type; + fme->board_info.n6000_hssi_id = id.v2.hssi_id; + type = board_type_to_string(fme->board_info.major, + fme->board_info.n6000_fim_type); + } else { + fme->board_info.major = id.v1.major; + fme->board_info.minor = id.v1.minor; + fme->board_info.type = id.v1.interface; + fme->board_info.fvl_bypass = id.v1.fvl_bypass; + fme->board_info.mac_lightweight = id.v1.mac_lightweight; + fme->board_info.lightweight = id.v1.lightweiht; + fme->board_info.disaggregate = id.v1.disagregate; + fme->board_info.seu = id.v1.seu; + fme->board_info.ptp = id.v1.ptp; + type = board_type_to_string(fme->board_info.major, + fme->board_info.type); + } dev_info(fme, "found: PCI dev: %02x:%02x:%x board: %s type: %s\n", hw->pci_data->bus, hw->pci_data->devid, hw->pci_data->function, board_major_to_string(fme->board_info.major), - board_type_to_string(fme->board_info.type)); + type); - dev_info(fme, "support feature:\n" + ret = max10_get_fpga_load_info(fme->max10_dev, &val); + if (ret) + return ret; + fme->board_info.boot_page = val; + + if (fme->board_info.major == VISTA_CREEK) { + dev_info(dev, "FPGA loaded from %s Image\n", + val ? "User" : "Factory"); + dev_info(fme, "support feature:\n" "fvl_bypass:%s\n" "mac_lightweight:%s\n" "lightweight:%s\n" @@ -901,26 +941,29 @@ static int fme_get_board_interface(struct ifpga_fme_hw *fme) check_support(fme->board_info.seu), check_support(fme->board_info.ptp)); + if (board_type_to_info(fme->board_info.type, &fme->board_info)) + return -EINVAL; - if (board_type_to_info(fme->board_info.type, &fme->board_info)) - return -EINVAL; - - dev_info(fme, "get board info: nums_retimers %d ports_per_retimer %d nums_fvl %d ports_per_fvl %d\n", + dev_info(fme, "get board info: nums_retimers %d " + "ports_per_retimer %d nums_fvl %d " + "ports_per_fvl %d\n", fme->board_info.nums_of_retimer, fme->board_info.ports_per_retimer, fme->board_info.nums_of_fvl, fme->board_info.ports_per_fvl); + } else { + dev_info(dev, "FPGA loaded from %s Image\n", + val ? (val == 1 ? "User1" : "User2") : "Factory"); + } - if (max10_sys_read(fme->max10_dev, FPGA_PAGE_INFO, &val)) - return -EINVAL; - fme->board_info.boot_page = val & 0x7; - - if (max10_sys_read(fme->max10_dev, MAX10_BUILD_VER, &val)) - return -EINVAL; + ret = max10_get_bmc_version(fme->max10_dev, &val); + if (ret) + return ret; fme->board_info.max10_version = val; - if (max10_sys_read(fme->max10_dev, NIOS2_FW_VERSION, &val)) - return -EINVAL; + ret = max10_get_bmcfw_version(fme->max10_dev, &val); + if (ret) + return ret; fme->board_info.nios_fw_version = val; dev_info(fme, "max10 version 0x%x, nios fw version 0x%x\n", @@ -1023,7 +1066,7 @@ static int fme_spi_init(struct ifpga_feature *feature) opae_free(max10); release_dev: altera_spi_release(spi_master); - return ret; + return -ENODEV; } static void fme_spi_uinit(struct ifpga_feature *feature) diff --git a/drivers/raw/ifpga/base/ifpga_fme_error.c b/drivers/raw/ifpga/base/ifpga_fme_error.c index 5905eac..c5bed28 100644 --- a/drivers/raw/ifpga/base/ifpga_fme_error.c +++ b/drivers/raw/ifpga/base/ifpga_fme_error.c @@ -224,6 +224,8 @@ static int fme_global_error_init(struct ifpga_feature *feature) { struct ifpga_fme_hw *fme = feature->parent; + dev_info(NULL, "FME error_module Init.\n"); + fme_error_enable(fme); if (feature->ctx_num) diff --git a/drivers/raw/ifpga/base/ifpga_port_error.c b/drivers/raw/ifpga/base/ifpga_port_error.c index 189f762..6c8a7d7 100644 --- a/drivers/raw/ifpga/base/ifpga_port_error.c +++ b/drivers/raw/ifpga/base/ifpga_port_error.c @@ -88,7 +88,7 @@ static int port_error_init(struct ifpga_feature *feature) { struct ifpga_port_hw *port = feature->parent; - dev_info(NULL, "port error Init.\n"); + dev_info(NULL, "port error_module Init.\n"); spinlock_lock(&port->lock); port_err_mask(port, false); diff --git a/drivers/raw/ifpga/base/opae_intel_max10.c b/drivers/raw/ifpga/base/opae_intel_max10.c index 901a258..26f323c 100644 --- a/drivers/raw/ifpga/base/opae_intel_max10.c +++ b/drivers/raw/ifpga/base/opae_intel_max10.c @@ -766,6 +766,51 @@ static int max10_staging_area_init(struct intel_max10_device *dev) return 0; } +int max10_get_fpga_load_info(struct intel_max10_device *dev, unsigned int *val) +{ + int ret; + unsigned int value; + + /* read FPGA loading information */ + ret = max10_sys_read(dev, dev->csr->fpga_page_info, &value); + if (ret) { + dev_err(dev, "fail to get FPGA loading info\n"); + return ret; + } + + if (dev->type == M10_N3000) + *val = value & 0x7; + else if (dev->type == M10_N6000) { + if (!GET_FIELD(PMCI_FPGA_CONFIGURED, value)) + return -EINVAL; + *val = GET_FIELD(PMCI_FPGA_BOOT_PAGE, value); + } + + return 0; +} + +int max10_get_bmc_version(struct intel_max10_device *dev, unsigned int *val) +{ + int ret; + + ret = max10_sys_read(dev, dev->csr->build_version, val); + if (ret) + return ret; + + return 0; +} + +int max10_get_bmcfw_version(struct intel_max10_device *dev, unsigned int *val) +{ + int ret; + + ret = max10_sys_read(dev, dev->csr->fw_version, val); + if (ret) + return ret; + + return 0; +} + static const struct m10bmc_csr m10bmc_spi_csr = { .base = MAX10_SEC_BASE_ADDR, .build_version = MAX10_BUILD_VER, diff --git a/drivers/raw/ifpga/base/opae_intel_max10.h b/drivers/raw/ifpga/base/opae_intel_max10.h index 0d31196..6a1b122 100644 --- a/drivers/raw/ifpga/base/opae_intel_max10.h +++ b/drivers/raw/ifpga/base/opae_intel_max10.h @@ -336,6 +336,9 @@ int max10_reg_write(struct intel_max10_device *dev, unsigned int offset, unsigned int val); int max10_sys_update_bits(struct intel_max10_device *dev, unsigned int offset, unsigned int msk, unsigned int val); +int max10_get_bmcfw_version(struct intel_max10_device *dev, unsigned int *val); +int max10_get_bmc_version(struct intel_max10_device *dev, unsigned int *val); +int max10_get_fpga_load_info(struct intel_max10_device *dev, unsigned int *val); int intel_max10_device_init(struct intel_max10_device *dev); int intel_max10_device_remove(struct intel_max10_device *dev); From patchwork Fri Jun 17 07:19:34 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Wei Huang X-Patchwork-Id: 112962 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 22115A0093; Fri, 17 Jun 2022 09:12:13 +0200 (CEST) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 5CB3742B6E; Fri, 17 Jun 2022 09:11:56 +0200 (CEST) Received: from mga04.intel.com (mga04.intel.com [192.55.52.120]) by mails.dpdk.org (Postfix) with ESMTP id 10DF24282A; Fri, 17 Jun 2022 09:11:53 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1655449914; x=1686985914; h=from:to:cc:subject:date:message-id:in-reply-to: references; bh=FX3awFiyyQtv2/ykeaiV6xg60TxhVthD3Fv7xfeDEFc=; b=LrZ1gNFsuVGLRuMuU0h5ChcmaEkjRHt+mRw0LXb115O21vbfGhroBXyd 7/4/9JyX4c5KlFBaDe13m6VPibtUUEW0GQaBD8vv+6ijG7QlH0NG9blbQ GWAAki6Z6y2xVi4J9f7yU08LIJ86fpwUc1UWlNZWgUlaoiKV3wmBQbiMI gAtC+LofOxV7hMwf79ujdNq2e013s/fhsEzgOI+iETAOmWS+hyCY9hHNF jeXQPf6MmwfMtqud4s17+shPNIJlq5/QdTa9bATzMXoufEqp+bqq0SkHZ zKu6B7EQmCd9+HWoCc7HqvFPmED0hy1NRbVoDUZIqbUDABrsIz/bIuXuz g==; X-IronPort-AV: E=McAfee;i="6400,9594,10380"; a="278236424" X-IronPort-AV: E=Sophos;i="5.92,306,1650956400"; d="scan'208";a="278236424" Received: from fmsmga005.fm.intel.com ([10.253.24.32]) by fmsmga104.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Jun 2022 00:11:53 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.92,306,1650956400"; d="scan'208";a="912502496" Received: from unknown (HELO zj-fpga-amt.sh.intel.com) ([10.238.175.102]) by fmsmga005.fm.intel.com with ESMTP; 17 Jun 2022 00:11:51 -0700 From: Wei Huang To: dev@dpdk.org, thomas@monjalon.net, nipun.gupta@nxp.com, hemant.agrawal@nxp.com Cc: stable@dpdk.org, rosen.xu@intel.com, tianfei.zhang@intel.com, qi.z.zhang@intel.com, Wei Huang Subject: [PATCH v3 3/4] raw/ifpga/base: update flash operation interface Date: Fri, 17 Jun 2022 03:19:34 -0400 Message-Id: <1655450375-10739-4-git-send-email-wei.huang@intel.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1655450375-10739-1-git-send-email-wei.huang@intel.com> References: <1654827900-10023-1-git-send-email-wei.huang@intel.com> <1655450375-10739-1-git-send-email-wei.huang@intel.com> X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org In N6000 ADP platform, SPI protocol, master and QSPI flash are transparent to host software. The SPI master implemented in PMCI automatically converts the mailbox commands to the SPI protocol required by SPI slave. That means flash operation is different from old platform, new interfaces are introduced to adapt these changes. Signed-off-by: Wei Huang Acked-by: Tianfei Zhang Reviewed-by: Rosen Xu --- drivers/raw/ifpga/base/ifpga_api.c | 9 + drivers/raw/ifpga/base/ifpga_feature_dev.h | 2 + drivers/raw/ifpga/base/ifpga_fme.c | 8 + drivers/raw/ifpga/base/opae_hw_api.c | 20 ++ drivers/raw/ifpga/base/opae_hw_api.h | 2 + drivers/raw/ifpga/base/opae_intel_max10.c | 282 +++++++++++++++++++++++ drivers/raw/ifpga/base/opae_intel_max10.h | 46 ++++ drivers/raw/ifpga/base/osdep_rte/osdep_generic.h | 10 + 8 files changed, 379 insertions(+) diff --git a/drivers/raw/ifpga/base/ifpga_api.c b/drivers/raw/ifpga/base/ifpga_api.c index f19cc26..098de0c 100644 --- a/drivers/raw/ifpga/base/ifpga_api.c +++ b/drivers/raw/ifpga/base/ifpga_api.c @@ -268,6 +268,14 @@ static int ifpga_mgr_reload(struct opae_manager *mgr, int type, int page) return fpga_reload(fme, type, page); } +static int ifpga_mgr_read_flash(struct opae_manager *mgr, u32 address, + u32 size, void *buf) +{ + struct ifpga_fme_hw *fme = mgr->data; + + return fme_mgr_read_flash(fme, address, size, buf); +} + struct opae_manager_ops ifpga_mgr_ops = { .flash = ifpga_mgr_flash, .get_eth_group_region_info = ifpga_mgr_get_eth_group_region_info, @@ -277,6 +285,7 @@ struct opae_manager_ops ifpga_mgr_ops = { .update_flash = ifpga_mgr_update_flash, .stop_flash_update = ifpga_mgr_stop_flash_update, .reload = ifpga_mgr_reload, + .read_flash = ifpga_mgr_read_flash }; static int ifpga_mgr_read_mac_rom(struct opae_manager *mgr, int offset, diff --git a/drivers/raw/ifpga/base/ifpga_feature_dev.h b/drivers/raw/ifpga/base/ifpga_feature_dev.h index a637eb5..7a2f2e5 100644 --- a/drivers/raw/ifpga/base/ifpga_feature_dev.h +++ b/drivers/raw/ifpga/base/ifpga_feature_dev.h @@ -223,4 +223,6 @@ int fme_mgr_get_retimer_status(struct ifpga_fme_hw *fme, int fme_mgr_get_sensor_value(struct ifpga_fme_hw *fme, struct opae_sensor_info *sensor, unsigned int *value); +int fme_mgr_read_flash(struct ifpga_fme_hw *fme, u32 address, + u32 size, void *buf); #endif /* _IFPGA_FEATURE_DEV_H_ */ diff --git a/drivers/raw/ifpga/base/ifpga_fme.c b/drivers/raw/ifpga/base/ifpga_fme.c index 608a352..25ff819 100644 --- a/drivers/raw/ifpga/base/ifpga_fme.c +++ b/drivers/raw/ifpga/base/ifpga_fme.c @@ -1658,3 +1658,11 @@ struct ifpga_feature_ops fme_pmci_ops = { .init = fme_pmci_init, .uinit = fme_pmci_uinit, }; + +int fme_mgr_read_flash(struct ifpga_fme_hw *fme, u32 address, + u32 size, void *buf) +{ + struct intel_max10_device *max10 = fme->max10_dev; + + return opae_read_flash(max10, address, size, buf); +} diff --git a/drivers/raw/ifpga/base/opae_hw_api.c b/drivers/raw/ifpga/base/opae_hw_api.c index 87256fc..fd08326 100644 --- a/drivers/raw/ifpga/base/opae_hw_api.c +++ b/drivers/raw/ifpga/base/opae_hw_api.c @@ -1041,3 +1041,23 @@ int opae_mgr_reload(struct opae_manager *mgr, int type, int page) return -ENOENT; } +/** + * opae_mgr_read_flash - read flash content + * @mgr: targeted manager + * @address: the start address of flash + * @size: the size of flash + * @buf: the read buffer + * + * Return: 0 on success, otherwise error code. + */ +int opae_mgr_read_flash(struct opae_manager *mgr, u32 address, + u32 size, void *buf) +{ + if (!mgr) + return -EINVAL; + + if (mgr->ops && mgr->ops->read_flash) + return mgr->ops->read_flash(mgr, address, size, buf); + + return -ENOENT; +} diff --git a/drivers/raw/ifpga/base/opae_hw_api.h b/drivers/raw/ifpga/base/opae_hw_api.h index fd40e09..de1e984 100644 --- a/drivers/raw/ifpga/base/opae_hw_api.h +++ b/drivers/raw/ifpga/base/opae_hw_api.h @@ -60,6 +60,7 @@ struct opae_manager_ops { u64 *status); int (*stop_flash_update)(struct opae_manager *mgr, int force); int (*reload)(struct opae_manager *mgr, int type, int page); + int (*read_flash)(struct opae_manager *mgr, u32 address, u32 size, void *buf); }; /* networking management ops in FME */ @@ -368,4 +369,5 @@ int opae_mgr_update_flash(struct opae_manager *mgr, const char *image, uint64_t *status); int opae_mgr_stop_flash_update(struct opae_manager *mgr, int force); int opae_mgr_reload(struct opae_manager *mgr, int type, int page); +int opae_mgr_read_flash(struct opae_manager *mgr, u32 address, u32 size, void *buf); #endif /* _OPAE_HW_API_H_*/ diff --git a/drivers/raw/ifpga/base/opae_intel_max10.c b/drivers/raw/ifpga/base/opae_intel_max10.c index 26f323c..9c01729 100644 --- a/drivers/raw/ifpga/base/opae_intel_max10.c +++ b/drivers/raw/ifpga/base/opae_intel_max10.c @@ -58,6 +58,279 @@ int max10_sys_update_bits(struct intel_max10_device *dev, unsigned int offset, return max10_sys_write(dev, offset, temp); } +static int n3000_bulk_raw_write(struct intel_max10_device *dev, uint32_t addr, + void *buf, uint32_t len) +{ + uint32_t v = 0; + uint32_t i = 0; + char *p = buf; + int ret = 0; + + len = IFPGA_ALIGN(len, 4); + + for (i = 0; i < len; i += 4) { + v = *(uint32_t *)(p + i); + ret = max10_reg_write(dev, addr + i, v); + if (ret < 0) { + dev_err(dev, + "Failed to write to staging area 0x%08x [e:%d]\n", + addr + i, ret); + return ret; + } + } + + return 0; +} + +static int n3000_bulk_raw_read(struct intel_max10_device *dev, + uint32_t addr, void *buf, uint32_t len) +{ + u32 v, i; + char *p = buf; + int ret; + + len = IFPGA_ALIGN(len, 4); + + for (i = 0; i < len; i += 4) { + ret = max10_reg_read(dev, addr + i, &v); + if (ret < 0) { + dev_err(dev, + "Failed to write to staging area 0x%08x [e:%d]\n", + addr + i, ret); + return ret; + } + *(u32 *)(p + i) = v; + } + + return 0; +} + +static int n3000_flash_read(struct intel_max10_device *dev, + u32 addr, void *buf, u32 size) +{ + if (!dev->raw_blk_ops.read_blk) + return -ENODEV; + + return dev->raw_blk_ops.read_blk(dev, addr, buf, size); +} + +static int n3000_flash_write(struct intel_max10_device *dev, + u32 addr, void *buf, u32 size) +{ + if (!dev->raw_blk_ops.write_blk) + return -ENODEV; + + return dev->raw_blk_ops.write_blk(dev, addr, buf, size); +} + +static u32 +pmci_get_write_space(struct intel_max10_device *dev, u32 size) +{ + u32 count, val; + int ret; + + ret = opae_readl_poll_timeout(dev->mmio + PMCI_FLASH_CTRL, val, + GET_FIELD(PMCI_FLASH_FIFO_SPACE, val) == + PMCI_FIFO_MAX_WORDS, + PMCI_FLASH_INT_US, PMCI_FLASH_TIMEOUT_US); + if (ret == -ETIMEDOUT) + return 0; + + count = GET_FIELD(PMCI_FLASH_FIFO_SPACE, val) * 4; + + return (size > count) ? count : size; +} + +static void pmci_write_fifo(void __iomem *base, char *buf, size_t count) +{ + size_t i; + u32 val; + + for (i = 0; i < count/4 ; i++) { + val = *(u32 *)(buf + i * 4); + writel(val, base); + } +} + +static void pmci_read_fifo(void __iomem *base, char *buf, size_t count) +{ + size_t i; + u32 val; + + for (i = 0; i < count/4; i++) { + val = readl(base); + *(u32 *)(buf + i * 4) = val; + } +} + +static int +__pmci_flash_bulk_write(struct intel_max10_device *dev, u32 addr, + void *buf, u32 size) +{ + UNUSED(addr); + u32 blk_size, n_offset = 0; + + while (size) { + blk_size = pmci_get_write_space(dev, size); + if (blk_size == 0) { + dev_err(pmci->dev, "get FIFO available size fail\n"); + return -EIO; + } + size -= blk_size; + pmci_write_fifo(dev->mmio + PMCI_FLASH_FIFO, (char *)buf + n_offset, + blk_size); + n_offset += blk_size; + } + + return 0; +} + +static int +pmci_flash_bulk_write(struct intel_max10_device *dev, u32 addr, + void *buf, u32 size) +{ + int ret; + + pthread_mutex_lock(dev->bmc_ops.mutex); + + ret = __pmci_flash_bulk_write(dev, addr, buf, size); + + pthread_mutex_unlock(dev->bmc_ops.mutex); + return ret; +} + +static int +pmci_set_flash_host_mux(struct intel_max10_device *dev, bool request) +{ + u32 ctrl; + int ret; + + ret = max10_sys_update_bits(dev, + m10bmc_base(dev) + M10BMC_PMCI_FLASH_CTRL, + FLASH_HOST_REQUEST, + SET_FIELD(FLASH_HOST_REQUEST, request)); + if (ret) + return ret; + + return opae_max10_read_poll_timeout(dev, m10bmc_base(dev) + M10BMC_PMCI_FLASH_CTRL, + ctrl, request ? (get_flash_mux(ctrl) == FLASH_MUX_HOST) : + (get_flash_mux(ctrl) != FLASH_MUX_HOST), + PMCI_FLASH_INT_US, PMCI_FLASH_TIMEOUT_US); +} + +static int +pmci_get_mux(struct intel_max10_device *dev) +{ + pthread_mutex_lock(dev->bmc_ops.mutex); + return pmci_set_flash_host_mux(dev, true); +} + +static int +pmci_put_mux(struct intel_max10_device *dev) +{ + int ret; + + ret = pmci_set_flash_host_mux(dev, false); + pthread_mutex_unlock(dev->bmc_ops.mutex); + return ret; +} + +static int +__pmci_flash_bulk_read(struct intel_max10_device *dev, u32 addr, + void *buf, u32 size) +{ + u32 blk_size, offset = 0, val; + int ret; + + while (size) { + blk_size = min_t(u32, size, PMCI_READ_BLOCK_SIZE); + + opae_writel(addr + offset, dev->mmio + PMCI_FLASH_ADDR); + + opae_writel(SET_FIELD(PMCI_FLASH_READ_COUNT, blk_size / 4) + | PMCI_FLASH_RD_MODE, + dev->mmio + PMCI_FLASH_CTRL); + + ret = opae_readl_poll_timeout((dev->mmio + PMCI_FLASH_CTRL), + val, !(val & PMCI_FLASH_BUSY), + PMCI_FLASH_INT_US, + PMCI_FLASH_TIMEOUT_US); + if (ret) { + dev_err(dev, "%s timed out on reading flash 0x%xn", + __func__, val); + return ret; + } + + pmci_read_fifo(dev->mmio + PMCI_FLASH_FIFO, (char *)buf + offset, + blk_size); + + size -= blk_size; + offset += blk_size; + + opae_writel(0, dev->mmio + PMCI_FLASH_CTRL); + } + + return 0; +} + +static int +pmci_flash_bulk_read(struct intel_max10_device *dev, u32 addr, + void *buf, u32 size) +{ + int ret; + + ret = pmci_get_mux(dev); + if (ret) + goto fail; + + ret = __pmci_flash_bulk_read(dev, addr, buf, size); + if (ret) + goto fail; + + return pmci_put_mux(dev); + +fail: + pmci_put_mux(dev); + return ret; +} + +static int pmci_check_flash_address(u32 start, u32 end) +{ + if (start < PMCI_FLASH_START || end > PMCI_FLASH_END) + return -EINVAL; + + return 0; +} + +int opae_read_flash(struct intel_max10_device *dev, u32 addr, + u32 size, void *buf) +{ + int ret; + + if (!dev->bmc_ops.flash_read) + return -ENODEV; + + if (!buf) + return -EINVAL; + + if (dev->bmc_ops.check_flash_range) { + ret = dev->bmc_ops.check_flash_range(addr, addr + size); + if (ret) + return ret; + } else { + u32 top_addr = dev->staging_area_base + dev->staging_area_size; + if ((addr < dev->staging_area_base) || + ((addr + size) >= top_addr)) + return -EINVAL; + } + + ret = dev->bmc_ops.flash_read(dev, addr, buf, size); + if (ret) + return ret; + + return 0; +} + static int max10_spi_read(struct intel_max10_device *dev, unsigned int addr, unsigned int *val) { @@ -841,6 +1114,11 @@ int max10_get_bmcfw_version(struct intel_max10_device *dev, unsigned int *val) dev->ops = &m10bmc_n3000_regmap; dev->csr = &m10bmc_spi_csr; + dev->raw_blk_ops.write_blk = n3000_bulk_raw_write; + dev->raw_blk_ops.read_blk = n3000_bulk_raw_read; + dev->bmc_ops.flash_read = n3000_flash_read; + dev->bmc_ops.flash_write = n3000_flash_write; + /* check the max10 version */ ret = check_max10_version(dev); if (ret) { @@ -871,6 +1149,10 @@ int max10_get_bmcfw_version(struct intel_max10_device *dev, unsigned int *val) dev->staging_area_size = MAX_STAGING_AREA_SIZE; dev->flags |= MAX10_FLAGS_SECURE; + dev->bmc_ops.flash_read = pmci_flash_bulk_read; + dev->bmc_ops.flash_write = pmci_flash_bulk_write; + dev->bmc_ops.check_flash_range = pmci_check_flash_address; + ret = pthread_mutex_init(&dev->bmc_ops.lock, NULL); if (ret) return ret; diff --git a/drivers/raw/ifpga/base/opae_intel_max10.h b/drivers/raw/ifpga/base/opae_intel_max10.h index 6a1b122..0f3360e 100644 --- a/drivers/raw/ifpga/base/opae_intel_max10.h +++ b/drivers/raw/ifpga/base/opae_intel_max10.h @@ -62,9 +62,22 @@ struct m10bmc_csr { }; /** + * struct flash_raw_blk_ops - device specific operations for flash R/W + * @write_blk: write a block of data to flash + * @read_blk: read a block of data from flash + */ +struct flash_raw_blk_ops { + int (*write_blk)(struct intel_max10_device *dev, uint32_t addr, + void *buf, uint32_t size); + int (*read_blk)(struct intel_max10_device *dev, uint32_t addr, + void *buf, uint32_t size); +}; + +/** * struct m10bmc_ops - device specific operations * @lock: prevent concurrent flash read/write * @mutex: prevent concurrent bmc read/write + * @check_flash_range: validate flash address * @flash_read: read a block of data from flash * @flash_write: write a block of data to flash */ @@ -92,6 +105,7 @@ struct intel_max10_device { enum m10bmc_type type; const struct m10bmc_regmap *ops; const struct m10bmc_csr *csr; + struct flash_raw_blk_ops raw_blk_ops; struct m10bmc_ops bmc_ops; u8 *mmio; /* mmio address for PMCI */ }; @@ -431,6 +445,22 @@ struct opae_sensor_info { #define PMCI_FPGA_RECONF_PAGE GENMASK(22, 20) #define PMCI_FPGA_RP_LOAD BIT(23) +#define PMCI_FLASH_CTRL 0x40 +#define PMCI_FLASH_WR_MODE BIT(0) +#define PMCI_FLASH_RD_MODE BIT(1) +#define PMCI_FLASH_BUSY BIT(2) +#define PMCI_FLASH_FIFO_SPACE GENMASK(13, 4) +#define PMCI_FLASH_READ_COUNT GENMASK(25, 16) + +#define PMCI_FLASH_INT_US 1 +#define PMCI_FLASH_TIMEOUT_US 10000 + +#define PMCI_FLASH_ADDR 0x44 +#define PMCI_FLASH_FIFO 0x800 +#define PMCI_READ_BLOCK_SIZE 0x800 +#define PMCI_FIFO_MAX_BYTES 0x800 +#define PMCI_FIFO_MAX_WORDS (PMCI_FIFO_MAX_BYTES / 4) + #define M10BMC_PMCI_FPGA_POC 0xb0 #define PMCI_FPGA_POC BIT(0) #define PMCI_NIOS_REQ_CLEAR BIT(1) @@ -447,6 +477,16 @@ struct opae_sensor_info { #define PMCI_FPGA_BOOT_PAGE GENMASK(2, 0) #define PMCI_FPGA_CONFIGURED BIT(3) +#define M10BMC_PMCI_FLASH_CTRL 0x1d0 +#define FLASH_MUX_SELECTION GENMASK(2, 0) +#define FLASH_MUX_IDLE 0 +#define FLASH_MUX_NIOS 1 +#define FLASH_MUX_HOST 2 +#define FLASH_MUX_PFL 4 +#define get_flash_mux(mux) GET_FIELD(FLASH_MUX_SELECTION, mux) +#define FLASH_NIOS_REQUEST BIT(4) +#define FLASH_HOST_REQUEST BIT(5) + #define M10BMC_PMCI_SDM_CTRL_STS 0x230 #define PMCI_SDM_IMG_REQ BIT(0) #define PMCI_SDM_STAT GENMASK(23, 16) @@ -472,4 +512,10 @@ struct opae_sensor_info { #define SDM_STAT_CS_MIS 0x12 #define SDM_STAT_PR_MIS 0x13 #define SDM_STAT_MAX SDM_STAT_PR_MIS + +#define PMCI_FLASH_START 0x10000 +#define PMCI_FLASH_END 0xC7FFFFF + +int opae_read_flash(struct intel_max10_device *dev, u32 addr, + u32 size, void *buf); #endif diff --git a/drivers/raw/ifpga/base/osdep_rte/osdep_generic.h b/drivers/raw/ifpga/base/osdep_rte/osdep_generic.h index 3ff49a8..68499e6 100644 --- a/drivers/raw/ifpga/base/osdep_rte/osdep_generic.h +++ b/drivers/raw/ifpga/base/osdep_rte/osdep_generic.h @@ -39,6 +39,16 @@ #define min(a, b) RTE_MIN(a, b) #define max(a, b) RTE_MAX(a, b) +#define min_t(type, x, y) ({ \ + type __min1 = (x); \ + type __min2 = (y); \ + __min1 < __min2 ? __min1 : __min2; }) + +#define max_t(type, x, y) ({ \ + type __max1 = (x); \ + type __max2 = (y); \ + __max1 > __max2 ? __max1 : __max2; }) + #define spinlock_t rte_spinlock_t #define spinlock_init(x) rte_spinlock_init(x) #define spinlock_lock(x) rte_spinlock_lock(x) From patchwork Fri Jun 17 07:19:35 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Wei Huang X-Patchwork-Id: 112963 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 36414A0093; Fri, 17 Jun 2022 09:12:22 +0200 (CEST) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id DFBCD42B78; Fri, 17 Jun 2022 09:11:58 +0200 (CEST) Received: from mga04.intel.com (mga04.intel.com [192.55.52.120]) by mails.dpdk.org (Postfix) with ESMTP id 749E942B70; Fri, 17 Jun 2022 09:11:56 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1655449916; x=1686985916; h=from:to:cc:subject:date:message-id:in-reply-to: references; bh=dvTQw7t+tLpe5JEJV/vqgUGZAdXjRtnUZhP6eL5uIZo=; b=KehIRng58a4wfnDqQy2ZjLZJqbbYnwhmQ5Y9EpB3/oTM8DQnp5t3vyYS 1k6EsJehCrJWKpoGNthn0bNddqYzhumjVqjykeZOUPHKfUpyBN6l21TUG MpX3up2yJJwtI9PaLv5VYvipcMdk1iEsmGwS/VkhZoh+4W+oVYr/itXPF FwK1supcYHkQ/iDgPHDuUVNeaVQ7UfsDyA77ZxGxLyKkXQdUzsCl4GPCE QsABCAKgRE7DZ85e1hXWLvMx7Y5kuVwsRh/husPGKxw2wHIqgmm2WiP3B AvdCZQhPFssQQQqST2vV+1VFnq+rXqSjqN5s2okifmwC+sXG6eY4ihodY Q==; X-IronPort-AV: E=McAfee;i="6400,9594,10380"; a="278236433" X-IronPort-AV: E=Sophos;i="5.92,306,1650956400"; d="scan'208";a="278236433" Received: from fmsmga005.fm.intel.com ([10.253.24.32]) by fmsmga104.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Jun 2022 00:11:56 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.92,306,1650956400"; d="scan'208";a="912502505" Received: from unknown (HELO zj-fpga-amt.sh.intel.com) ([10.238.175.102]) by fmsmga005.fm.intel.com with ESMTP; 17 Jun 2022 00:11:53 -0700 From: Wei Huang To: dev@dpdk.org, thomas@monjalon.net, nipun.gupta@nxp.com, hemant.agrawal@nxp.com Cc: stable@dpdk.org, rosen.xu@intel.com, tianfei.zhang@intel.com, qi.z.zhang@intel.com, Wei Huang Subject: [PATCH v3 4/4] raw/ifpga/base: add PMCI sensor driver Date: Fri, 17 Jun 2022 03:19:35 -0400 Message-Id: <1655450375-10739-5-git-send-email-wei.huang@intel.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1655450375-10739-1-git-send-email-wei.huang@intel.com> References: <1654827900-10023-1-git-send-email-wei.huang@intel.com> <1655450375-10739-1-git-send-email-wei.huang@intel.com> X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org N6000 ADP platform support more sensors than N3000, they are accessed with the help of PMCI sensor driver. Signed-off-by: Wei Huang Acked-by: Tianfei Zhang Reviewed-by: Rosen Xu --- drivers/raw/ifpga/base/opae_hw_api.c | 29 +++ drivers/raw/ifpga/base/opae_hw_api.h | 1 + drivers/raw/ifpga/base/opae_intel_max10.c | 326 ++++++++++++++++++++++++++++++ drivers/raw/ifpga/base/opae_intel_max10.h | 35 ++++ 4 files changed, 391 insertions(+) diff --git a/drivers/raw/ifpga/base/opae_hw_api.c b/drivers/raw/ifpga/base/opae_hw_api.c index fd08326..1117c3e 100644 --- a/drivers/raw/ifpga/base/opae_hw_api.c +++ b/drivers/raw/ifpga/base/opae_hw_api.c @@ -831,6 +831,35 @@ int opae_manager_get_retimer_status(struct opae_manager *mgr, } /** + * opae_manager_get_sensor_list - get sensor name list + * @mgr: opae_manager of sensors + * @buf: buffer to accommodate name list separated by semicolon + * @size: size of buffer + * + * Return: the pointer of the opae_sensor_info + */ +int +opae_mgr_get_sensor_list(struct opae_manager *mgr, char *buf, size_t size) +{ + struct opae_sensor_info *sensor; + uint32_t offset = 0; + + opae_mgr_for_each_sensor(mgr, sensor) { + if (sensor->name) { + if (buf && (offset < size)) + snprintf(buf + offset, size - offset, "%s;", + sensor->name); + offset += strlen(sensor->name) + 1; + } + } + + if (buf && (offset > 0) && (offset <= size)) + buf[offset-1] = 0; + + return offset; +} + +/** * opae_manager_get_sensor_by_id - get sensor device * @id: the id of the sensor * diff --git a/drivers/raw/ifpga/base/opae_hw_api.h b/drivers/raw/ifpga/base/opae_hw_api.h index de1e984..613563a 100644 --- a/drivers/raw/ifpga/base/opae_hw_api.h +++ b/drivers/raw/ifpga/base/opae_hw_api.h @@ -94,6 +94,7 @@ int opae_manager_flash(struct opae_manager *mgr, int acc_id, const char *buf, u32 size, u64 *status); int opae_manager_get_eth_group_region_info(struct opae_manager *mgr, u8 group_id, struct opae_eth_group_region_info *info); +int opae_mgr_get_sensor_list(struct opae_manager *mgr, char *buf, size_t size); struct opae_sensor_info *opae_mgr_get_sensor_by_name(struct opae_manager *mgr, const char *name); struct opae_sensor_info *opae_mgr_get_sensor_by_id(struct opae_manager *mgr, diff --git a/drivers/raw/ifpga/base/opae_intel_max10.c b/drivers/raw/ifpga/base/opae_intel_max10.c index 9c01729..dd97a5f 100644 --- a/drivers/raw/ifpga/base/opae_intel_max10.c +++ b/drivers/raw/ifpga/base/opae_intel_max10.c @@ -1102,6 +1102,328 @@ int max10_get_bmcfw_version(struct intel_max10_device *dev, unsigned int *val) .auth_result = M10BMC_PMCI_AUTH_RESULT, }; +static const struct max10_sensor_raw_data n6000bmc_temp_tbl[] = { + { 0x444, 0x448, 0x44c, 0x0, 0x0, 500, + "FPGA E-TILE Temperature #1" }, + { 0x450, 0x454, 0x458, 0x0, 0x0, 500, + "FPGA E-TILE Temperature #2" }, + { 0x45c, 0x460, 0x464, 0x0, 0x0, 500, + "FPGA E-TILE Temperature #3" }, + { 0x468, 0x46c, 0x470, 0x0, 0x0, 500, + "FPGA E-TILE Temperature #4" }, + { 0x474, 0x478, 0x47c, 0x0, 0x0, 500, + "FPGA P-TILE Temperature" }, + { 0x484, 0x488, 0x48c, 0x0, 0x0, 500, + "FPGA FABRIC Digital Temperature#1" }, + { 0x490, 0x494, 0x498, 0x0, 0x0, 500, + "FPGA FABRIC Digital Temperature#2" }, + { 0x49c, 0x4a0, 0x4a4, 0x0, 0x0, 500, + "FPGA FABRIC Digital Temperature#3" }, + { 0x4a8, 0x4ac, 0x4b0, 0x0, 0x0, 500, + "FPGA FABRIC Digital Temperature#4" }, + { 0x4b4, 0x4b8, 0x4bc, 0x0, 0x0, 500, + "FPGA FABRIC Digital Temperature#5" }, + { 0x4c0, 0x4c4, 0x4c8, 0x0, 0x0, 500, + "FPGA FABRIC Remote Digital Temperature#1" }, + { 0x4cc, 0x4d0, 0x4d4, 0x0, 0x0, 500, + "FPGA FABRIC Remote Digital Temperature#2" }, + { 0x4d8, 0x4dc, 0x4e0, 0x0, 0x0, 500, + "FPGA FABRIC Remote Digital Temperature#3" }, + { 0x4e4, 0x4e8, 0x4ec, 0x0, 0x0, 500, + "FPGA FABRIC Remote Digital Temperature#4" }, + { 0x4f0, 0x4f4, 0x4f8, 0x0, 0x0, 500, + "Board Top Near FPGA Temperature" }, + { 0x4fc, 0x500, 0x504, 0x52c, 0x0, 500, + "Board Bottom Near CVL Temperature" }, + { 0x508, 0x50c, 0x510, 0x52c, 0x0, 500, + "Board Top East Near VRs Temperature" }, + { 0x514, 0x518, 0x51c, 0x52c, 0x0, 500, + "Columbiaville Die Temperature" }, + { 0x520, 0x524, 0x528, 0x52c, 0x0, 500, + "Board Rear Side Temperature" }, + { 0x530, 0x534, 0x538, 0x52c, 0x0, 500, + "Board Front Side Temperature" }, + { 0x53c, 0x540, 0x544, 0x0, 0x0, 500, + "QSFP1 Temperature" }, + { 0x548, 0x54c, 0x550, 0x0, 0x0, 500, + "QSFP2 Temperature" }, + { 0x554, 0x0, 0x0, 0x0, 0x0, 500, + "FPGA Core Voltage Phase 0 VR Temperature" }, + { 0x560, 0x0, 0x0, 0x0, 0x0, 500, + "FPGA Core Voltage Phase 1 VR Temperature" }, + { 0x56c, 0x0, 0x0, 0x0, 0x0, 500, + "FPGA Core Voltage Phase 2 VR Temperature" }, + { 0x578, 0x0, 0x0, 0x0, 0x0, 500, + "FPGA Core Voltage VR Controller Temperature" }, + { 0x584, 0x0, 0x0, 0x0, 0x0, 500, + "FPGA VCCH VR Temperature" }, + { 0x590, 0x0, 0x0, 0x0, 0x0, 500, + "FPGA VCC_1V2 VR Temperature" }, + { 0x59c, 0x0, 0x0, 0x0, 0x0, 500, + "FPGA VCCH, VCC_1V2 VR Controller Temperature" }, + { 0x5a8, 0x0, 0x0, 0x0, 0x0, 500, + "3V3 VR Temperature" }, + { 0x5b4, 0x5b8, 0x5bc, 0x0, 0x0, 500, + "CVL Core Voltage VR Temperature" }, + { 0x5c4, 0x5c8, 0x5cc, 0x5c0, 0x0, 500, + "FPGA P-Tile Temperature [Remote]" }, + { 0x5d0, 0x5d4, 0x5d8, 0x5c0, 0x0, 500, + "FPGA E-Tile Temperature [Remote]" }, + { 0x5dc, 0x5e0, 0x5e4, 0x5c0, 0x0, 500, + "FPGA SDM Temperature [Remote]" }, + { 0x5e8, 0x5ec, 0x5f0, 0x5c0, 0x0, 500, + "FPGA Corner Temperature [Remote]" }, +}; + +static const struct max10_sensor_data n6000bmc_tmp_data = { + .type = SENSOR_TMP_NAME, + .number = ARRAY_SIZE(n6000bmc_temp_tbl), + .table = n6000bmc_temp_tbl, +}; + +static const struct max10_sensor_raw_data n6000bmc_in_tbl[] = { + { 0x5f4, 0x0, 0x0, 0x0, 0x0, 1, + "Inlet 12V PCIe Rail Voltage" }, + { 0x60c, 0x0, 0x0, 0x0, 0x0, 1, + "Inlet 12V Aux Rail Voltage" }, + { 0x624, 0x0, 0x0, 0x0, 0x0, 1, + "Inlet 3V3 PCIe Rail Voltage" }, + { 0x63c, 0x0, 0x0, 0x0, 0x0, 1, + "FPGA Core Voltage Rail Voltage" }, + { 0x644, 0x0, 0x0, 0x0, 0x0, 1, + "FPGA VCCH Rail Voltage" }, + { 0x64c, 0x0, 0x0, 0x0, 0x0, 1, + "FPGA VCC_1V2 Rail Voltage" }, + { 0x654, 0x0, 0x0, 0x0, 0x0, 1, + "FPGA VCCH_GXER_1V1, VCCA_1V8 Voltage" }, + { 0x664, 0x0, 0x0, 0x0, 0x0, 1, + "FPGA VCCIO_1V2 Voltage" }, + { 0x674, 0x0, 0x0, 0x0, 0x0, 1, + "CVL Non Core Rails Inlet Voltage" }, + { 0x684, 0x0, 0x0, 0x0, 0x0, 1, + "MAX10 & Board CLK PWR 3V3 Inlet Voltage" }, + { 0x694, 0x0, 0x0, 0x0, 0x0, 1, + "CVL Core Voltage Rail Voltage" }, + { 0x6ac, 0x0, 0x0, 0x0, 0x0, 1, + "Board 3V3 VR Voltage" }, + { 0x6b4, 0x0, 0x0, 0x0, 0x0, 1, + "QSFP 3V3 Rail Voltage" }, + { 0x6c4, 0x0, 0x0, 0x0, 0x0, 1, + "QSFP (Primary) Supply Rail Voltage" }, + { 0x6c8, 0x0, 0x0, 0x0, 0x0, 1, + "QSFP (Secondary) Supply Rail Voltage" }, + { 0x6cc, 0x0, 0x0, 0x0, 0x0, 1, + "VCCCLK_GXER_2V5 Voltage" }, + { 0x6d0, 0x0, 0x0, 0x0, 0x0, 1, + "AVDDH_1V1_CVL Voltage" }, + { 0x6d4, 0x0, 0x0, 0x0, 0x0, 1, + "VDDH_1V8_CVL Voltage" }, + { 0x6d8, 0x0, 0x0, 0x0, 0x0, 1, + "VCCA_PLL Voltage" }, + { 0x6e0, 0x0, 0x0, 0x0, 0x0, 1, + "VCCRT_GXER_0V9 Voltage" }, + { 0x6e8, 0x0, 0x0, 0x0, 0x0, 1, + "VCCRT_GXEL_0V9 Voltage" }, + { 0x6f0, 0x0, 0x0, 0x0, 0x0, 1, + "VCCH_GXPL_1V8 Voltage" }, + { 0x6f4, 0x0, 0x0, 0x0, 0x0, 1, + "VCCPT_1V8 Voltage" }, + { 0x6fc, 0x0, 0x0, 0x0, 0x0, 1, + "VCC_3V3_M10 Voltage" }, + { 0x700, 0x0, 0x0, 0x0, 0x0, 1, + "VCC_1V8_M10 Voltage" }, + { 0x704, 0x0, 0x0, 0x0, 0x0, 1, + "VCC_1V2_EMIF1_2_3 Voltage" }, + { 0x70c, 0x0, 0x0, 0x0, 0x0, 1, + "VCC_1V2_EMIF4_5 Voltage" }, + { 0x714, 0x0, 0x0, 0x0, 0x0, 1, + "VCCA_1V8 Voltage" }, + { 0x718, 0x0, 0x0, 0x0, 0x0, 1, + "VCCH_GXER_1V1 Voltage" }, + { 0x71c, 0x0, 0x0, 0x0, 0x0, 1, + "AVDD_ETH_0V9_CVL Voltage" }, + { 0x720, 0x0, 0x0, 0x0, 0x0, 1, + "AVDD_PCIE_0V9_CVL Voltage" }, +}; + +static const struct max10_sensor_data n6000bmc_in_data = { + .type = SENSOR_IN_NAME, + .number = ARRAY_SIZE(n6000bmc_in_tbl), + .table = n6000bmc_in_tbl, +}; + +static const struct max10_sensor_raw_data n6000bmc_curr_tbl[] = { + { 0x600, 0x604, 0x608, 0x0, 0x0, 1, + "Inlet 12V PCIe Rail Current" }, + { 0x618, 0x61c, 0x620, 0x0, 0x0, 1, + "Inlet 12V Aux Rail Current" }, + { 0x630, 0x634, 0x638, 0x0, 0x0, 1, + "Inlet 3V3 PCIe Rail Current" }, + { 0x640, 0x0, 0x0, 0x0, 0x0, 1, + "FPGA Core Voltage Rail Current" }, + { 0x648, 0x0, 0x0, 0x0, 0x0, 1, + "FPGA VCCH Rail Current" }, + { 0x650, 0x0, 0x0, 0x0, 0x0, 1, + "FPGA VCC_1V2 Rail Current" }, + { 0x658, 0x65c, 0x660, 0x0, 0x0, 1, + "FPGA VCCH_GXER_1V1, VCCA_1V8 Current" }, + { 0x668, 0x66c, 0x670, 0x0, 0x0, 1, + "FPGA VCCIO_1V2 Current" }, + { 0x678, 0x67c, 0x680, 0x0, 0x0, 1, + "CVL Non Core Rails Inlet Current" }, + { 0x688, 0x68c, 0x680, 0x0, 0x0, 1, + "MAX10 & Board CLK PWR 3V3 Inlet Current" }, + { 0x690, 0x0, 0x0, 0x0, 0x0, 1, + "CVL Core Voltage Rail Current" }, + { 0x6b0, 0x0, 0x0, 0x0, 0x0, 1, + "Board 3V3 VR Current" }, + { 0x6b8, 0x6bc, 0x670, 0x0, 0x0, 1, + "QSFP 3V3 Rail Current" }, +}; + +static const struct max10_sensor_data n6000bmc_curr_data = { + .type = SENSOR_CURR_NAME, + .number = ARRAY_SIZE(n6000bmc_curr_tbl), + .table = n6000bmc_curr_tbl, +}; + +static const struct max10_sensor_raw_data n6000bmc_power_tbl[] = { + { 0x724, 0x0, 0x0, 0x0, 0x0, 1000, "Board Power" }, +}; + +static const struct max10_sensor_data n6000bmc_power_data = { + .type = SENSOR_POWER_NAME, + .number = ARRAY_SIZE(n6000bmc_power_tbl), + .table = n6000bmc_power_tbl, +}; + +static const struct max10_sensor_board_data n6000bmc_sensor_board_data = { + .tables = { + [sensor_temp] = &n6000bmc_tmp_data, + [sensor_in] = &n6000bmc_in_data, + [sensor_curr] = &n6000bmc_curr_data, + [sensor_power] = &n6000bmc_power_data, + }, +}; + +static int get_sensor_data(struct intel_max10_device *dev, + struct opae_sensor_info *sensor, + unsigned int *value, + unsigned int reg, + unsigned int flags) +{ + int ret; + unsigned int data; + + if (!reg) + return 0; + + ret = max10_sys_read(dev, reg, &data); + if (ret) + return ret; + + if (data == SENSOR_INVALID) { + dev_debug(dev, "%s: sensor:%s invalid 0x%x at:%d\n", + __func__, sensor->name, data, reg); + return ret; + } + + *value = data * sensor->multiplier; + sensor->flags |= flags; + + return 0; +} + +static int max10_parse_sensor_data(struct intel_max10_device *dev, + const struct max10_sensor_data *sdata) +{ + struct opae_sensor_info *sensor; + const struct max10_sensor_raw_data *raw; + const struct max10_sensor_raw_data *table = + (const struct max10_sensor_raw_data *)sdata->table; + unsigned int i; + static unsigned int sensor_id; + int ret = 0; + + for (i = 0; i < sdata->number; i++) { + raw = &table[i]; + + sensor = opae_zmalloc(sizeof(*sensor)); + if (!sensor) { + ret = -EINVAL; + goto free_sensor; + } + + sensor->type = sdata->type; + sensor->id = sensor_id++; + + if (!raw->reg_input) + continue; + + sensor->value_reg = raw->reg_input; + sensor->multiplier = raw->multiplier; + sensor->name = raw->label; + + ret = get_sensor_data(dev, sensor, + &sensor->high_warn, + raw->reg_high_warn, + OPAE_SENSOR_HIGH_WARN_VALID); + if (ret) + break; + + ret = get_sensor_data(dev, sensor, + &sensor->high_fatal, + raw->reg_high_fatal, + OPAE_SENSOR_HIGH_FATAL_VALID); + if (ret) + break; + + ret = get_sensor_data(dev, sensor, + &sensor->hysteresis, + raw->reg_hyst, + OPAE_SENSOR_HYSTERESIS_VALID); + if (ret) + break; + + ret = get_sensor_data(dev, sensor, + &sensor->low_warn, + raw->reg_low_warn, + OPAE_SENSOR_LOW_WARN_VALID); + if (ret) + break; + + sensor->flags |= OPAE_SENSOR_VALID; + + TAILQ_INSERT_TAIL(&dev->opae_sensor_list, sensor, node); + dev_info(dev, "found valid sensor: %s\n", sensor->name); + } + + return ret; + +free_sensor: + max10_sensor_uinit(dev); + return ret; +} + +static int max10_sensor_init_table(struct intel_max10_device *dev, + const struct max10_sensor_board_data *data) +{ + int ret = 0; + unsigned int i; + const struct max10_sensor_data *sdata; + + for (i = 0; i < ARRAY_SIZE(data->tables); i++) { + sdata = data->tables[i]; + if (!sdata) + continue; + ret = max10_parse_sensor_data(dev, sdata); + if (ret) + break; + } + + return ret; +} + int intel_max10_device_init(struct intel_max10_device *dev) { @@ -1153,6 +1475,10 @@ int max10_get_bmcfw_version(struct intel_max10_device *dev, unsigned int *val) dev->bmc_ops.flash_write = pmci_flash_bulk_write; dev->bmc_ops.check_flash_range = pmci_check_flash_address; + ret = max10_sensor_init_table(dev, &n6000bmc_sensor_board_data); + if (ret) + return ret; + ret = pthread_mutex_init(&dev->bmc_ops.lock, NULL); if (ret) return ret; diff --git a/drivers/raw/ifpga/base/opae_intel_max10.h b/drivers/raw/ifpga/base/opae_intel_max10.h index 0f3360e..7841df1 100644 --- a/drivers/raw/ifpga/base/opae_intel_max10.h +++ b/drivers/raw/ifpga/base/opae_intel_max10.h @@ -410,6 +410,41 @@ struct opae_sensor_info { unsigned int value_reg; }; +#define SENSOR_INVALID 0xdeadbeef + +struct max10_sensor_raw_data { + unsigned int reg_input; + unsigned int reg_high_warn; + unsigned int reg_high_fatal; + unsigned int reg_hyst; + unsigned int reg_low_warn; + unsigned int multiplier; + const char *label; +}; + +struct max10_sensor_data { + const char *type; + unsigned int number; + const struct max10_sensor_raw_data *table; +}; + +enum max10_sensor_types { + sensor_temp, + sensor_in, + sensor_curr, + sensor_power, + sensor_max, +}; + +#define SENSOR_TMP_NAME "Temperature" +#define SENSOR_IN_NAME "Voltage" +#define SENSOR_CURR_NAME "Current" +#define SENSOR_POWER_NAME "Power" + +struct max10_sensor_board_data { + const struct max10_sensor_data *tables[sensor_max]; +}; + /* indirect access for PMCI */ #define PMCI_INDIRECT_BASE 0x400 #define INDIRECT_CMD_OFF (PMCI_INDIRECT_BASE + 0x0)