raw/ifpga/base: add PMCI base driver
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 <wei.huang@intel.com> Acked-by: Tianfei Zhang <tianfei.zhang@intel.com> Reviewed-by: Rosen Xu <rosen.xu@intel.com>
This commit is contained in:
parent
e53ed84acb
commit
ca6eb0f7c8
@ -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
|
||||
|
@ -227,6 +227,8 @@ static struct feature_driver fme_feature_drvs[] = {
|
||||
&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 */
|
||||
};
|
||||
|
||||
|
@ -178,6 +178,7 @@ extern struct ifpga_feature_ops fme_spi_master_ops;
|
||||
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);
|
||||
|
@ -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,
|
||||
};
|
||||
|
@ -4,51 +4,42 @@
|
||||
|
||||
#include "opae_intel_max10.h"
|
||||
#include <libfdt.h>
|
||||
|
||||
int max10_reg_read(struct intel_max10_device *dev,
|
||||
unsigned int reg, unsigned int *val)
|
||||
{
|
||||
if (!dev)
|
||||
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);
|
||||
}
|
||||
|
||||
int max10_reg_write(struct intel_max10_device *dev,
|
||||
unsigned int reg, 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, reg, val);
|
||||
|
||||
return spi_transaction_write(dev->spi_tran_dev,
|
||||
reg, 4, (unsigned char *)&tmp);
|
||||
}
|
||||
#include "opae_osdep.h"
|
||||
|
||||
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;
|
||||
|
||||
|
||||
return max10_reg_read(dev, dev->base + offset, val);
|
||||
return dev->ops->reg_read(dev, dev->csr->base + offset, val);
|
||||
}
|
||||
|
||||
int max10_sys_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, dev->csr->base + offset, val);
|
||||
}
|
||||
|
||||
int max10_reg_read(struct intel_max10_device *dev,
|
||||
unsigned int offset, unsigned int *val)
|
||||
{
|
||||
if (!dev || !dev->ops->reg_read)
|
||||
return -ENODEV;
|
||||
|
||||
return dev->ops->reg_read(dev, offset, val);
|
||||
}
|
||||
|
||||
int max10_reg_write(struct intel_max10_device *dev,
|
||||
unsigned int offset, unsigned int val)
|
||||
{
|
||||
if (!dev || !dev->ops->reg_write)
|
||||
return -ENODEV;
|
||||
|
||||
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 @@ max10_non_secure_hw_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,
|
||||
};
|
||||
|
||||
int
|
||||
intel_max10_device_init(struct intel_max10_device *dev)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
TAILQ_INIT(&dev->opae_sensor_list);
|
||||
|
||||
dev->spi_master = spi;
|
||||
|
||||
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;
|
||||
if (dev->type == M10_N3000) {
|
||||
dev->ops = &m10bmc_n3000_regmap;
|
||||
dev->csr = &m10bmc_spi_csr;
|
||||
|
||||
/* check the max10 version */
|
||||
ret = check_max10_version(dev);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to find max10 hardware!\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* load the MAX10 device table */
|
||||
ret = init_max10_device_table(dev);
|
||||
if (ret) {
|
||||
dev_err(dev, "Init max10 device table fail\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");
|
||||
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;
|
||||
|
||||
ret = pthread_mutex_init(&dev->bmc_ops.lock, NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (!dev->bmc_ops.mutex)
|
||||
dev->bmc_ops.mutex = &dev->bmc_ops.lock;
|
||||
}
|
||||
|
||||
/* check the max10 version */
|
||||
ret = check_max10_version(dev);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to find max10 hardware!\n");
|
||||
goto free_dev;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/* 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");
|
||||
|
||||
return dev;
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
pthread_mutex_destroy(&dev->bmc_ops.lock);
|
||||
|
||||
if (dev->spi_tran_dev)
|
||||
spi_transaction_remove(dev->spi_tran_dev);
|
||||
if (dev->type == M10_N3000) {
|
||||
max10_sensor_uinit(dev);
|
||||
|
||||
if (dev->fdt_root)
|
||||
opae_free(dev->fdt_root);
|
||||
|
||||
opae_free(dev);
|
||||
if (dev->fdt_root)
|
||||
opae_free(dev->fdt_root);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user