From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: 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 --- 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 -- 1.8.3.1