mfd: intel-m10-bmc: Support multiple CSR register layouts

There are different addresses for the MAX10 CSR registers. Introducing
a new data structure m10bmc_csr_map for the register definition of
MAX10 CSR.

Provide the csr_map for SPI.

Co-developed-by: Tianfei zhang <tianfei.zhang@intel.com>
Signed-off-by: Tianfei zhang <tianfei.zhang@intel.com>
Reviewed-by: Russ Weight <russell.h.weight@intel.com>
Reviewed-by: Xu Yilun <yilun.xu@intel.com>
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
Signed-off-by: Lee Jones <lee@kernel.org>
Link: https://lore.kernel.org/r/20230116100845.6153-6-ilpo.jarvinen@linux.intel.com
This commit is contained in:
Ilpo Järvinen 2023-01-16 12:08:39 +02:00 committed by Lee Jones
parent 603aed8ffd
commit 6052a005ca
4 changed files with 111 additions and 33 deletions

View file

@ -73,16 +73,24 @@ show_root_entry_hash(struct device *dev, u32 exp_magic,
return cnt;
}
#define DEVICE_ATTR_SEC_REH_RO(_name, _magic, _prog_addr, _reh_addr) \
#define DEVICE_ATTR_SEC_REH_RO(_name) \
static ssize_t _name##_root_entry_hash_show(struct device *dev, \
struct device_attribute *attr, \
char *buf) \
{ return show_root_entry_hash(dev, _magic, _prog_addr, _reh_addr, buf); } \
{ \
struct m10bmc_sec *sec = dev_get_drvdata(dev); \
const struct m10bmc_csr_map *csr_map = sec->m10bmc->info->csr_map; \
\
return show_root_entry_hash(dev, csr_map->_name##_magic, \
csr_map->_name##_prog_addr, \
csr_map->_name##_reh_addr, \
buf); \
} \
static DEVICE_ATTR_RO(_name##_root_entry_hash)
DEVICE_ATTR_SEC_REH_RO(bmc, BMC_PROG_MAGIC, BMC_PROG_ADDR, BMC_REH_ADDR);
DEVICE_ATTR_SEC_REH_RO(sr, SR_PROG_MAGIC, SR_PROG_ADDR, SR_REH_ADDR);
DEVICE_ATTR_SEC_REH_RO(pr, PR_PROG_MAGIC, PR_PROG_ADDR, PR_REH_ADDR);
DEVICE_ATTR_SEC_REH_RO(bmc);
DEVICE_ATTR_SEC_REH_RO(sr);
DEVICE_ATTR_SEC_REH_RO(pr);
#define CSK_BIT_LEN 128U
#define CSK_32ARRAY_SIZE DIV_ROUND_UP(CSK_BIT_LEN, 32)
@ -122,18 +130,25 @@ show_canceled_csk(struct device *dev, u32 addr, char *buf)
return bitmap_print_to_pagebuf(1, buf, csk_map, CSK_BIT_LEN);
}
#define DEVICE_ATTR_SEC_CSK_RO(_name, _addr) \
#define DEVICE_ATTR_SEC_CSK_RO(_name) \
static ssize_t _name##_canceled_csks_show(struct device *dev, \
struct device_attribute *attr, \
char *buf) \
{ return show_canceled_csk(dev, _addr, buf); } \
{ \
struct m10bmc_sec *sec = dev_get_drvdata(dev); \
const struct m10bmc_csr_map *csr_map = sec->m10bmc->info->csr_map; \
\
return show_canceled_csk(dev, \
csr_map->_name##_prog_addr + CSK_VEC_OFFSET, \
buf); \
} \
static DEVICE_ATTR_RO(_name##_canceled_csks)
#define CSK_VEC_OFFSET 0x34
DEVICE_ATTR_SEC_CSK_RO(bmc, BMC_PROG_ADDR + CSK_VEC_OFFSET);
DEVICE_ATTR_SEC_CSK_RO(sr, SR_PROG_ADDR + CSK_VEC_OFFSET);
DEVICE_ATTR_SEC_CSK_RO(pr, PR_PROG_ADDR + CSK_VEC_OFFSET);
DEVICE_ATTR_SEC_CSK_RO(bmc);
DEVICE_ATTR_SEC_CSK_RO(sr);
DEVICE_ATTR_SEC_CSK_RO(pr);
#define FLASH_COUNT_SIZE 4096 /* count stored as inverted bit vector */
@ -141,6 +156,7 @@ static ssize_t flash_count_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct m10bmc_sec *sec = dev_get_drvdata(dev);
const struct m10bmc_csr_map *csr_map = sec->m10bmc->info->csr_map;
unsigned int stride, num_bits;
u8 *flash_buf;
int cnt, ret;
@ -160,12 +176,12 @@ static ssize_t flash_count_show(struct device *dev,
if (!flash_buf)
return -ENOMEM;
ret = regmap_bulk_read(sec->m10bmc->regmap, STAGING_FLASH_COUNT,
ret = regmap_bulk_read(sec->m10bmc->regmap, csr_map->rsu_update_counter,
flash_buf, FLASH_COUNT_SIZE / stride);
if (ret) {
dev_err(sec->dev,
"failed to read flash count: %x cnt %x: %d\n",
STAGING_FLASH_COUNT, FLASH_COUNT_SIZE / stride, ret);
csr_map->rsu_update_counter, FLASH_COUNT_SIZE / stride, ret);
goto exit_free;
}
cnt = num_bits - bitmap_weight((unsigned long *)flash_buf, num_bits);
@ -200,20 +216,22 @@ static const struct attribute_group *m10bmc_sec_attr_groups[] = {
static void log_error_regs(struct m10bmc_sec *sec, u32 doorbell)
{
const struct m10bmc_csr_map *csr_map = sec->m10bmc->info->csr_map;
u32 auth_result;
dev_err(sec->dev, "RSU error status: 0x%08x\n", doorbell);
if (!m10bmc_sys_read(sec->m10bmc, M10BMC_AUTH_RESULT, &auth_result))
if (!m10bmc_sys_read(sec->m10bmc, csr_map->auth_result, &auth_result))
dev_err(sec->dev, "RSU auth result: 0x%08x\n", auth_result);
}
static enum fw_upload_err rsu_check_idle(struct m10bmc_sec *sec)
{
const struct m10bmc_csr_map *csr_map = sec->m10bmc->info->csr_map;
u32 doorbell;
int ret;
ret = m10bmc_sys_read(sec->m10bmc, M10BMC_DOORBELL, &doorbell);
ret = m10bmc_sys_read(sec->m10bmc, csr_map->doorbell, &doorbell);
if (ret)
return FW_UPLOAD_ERR_RW_ERROR;
@ -246,11 +264,12 @@ static inline bool rsu_start_done(u32 doorbell)
static enum fw_upload_err rsu_update_init(struct m10bmc_sec *sec)
{
const struct m10bmc_csr_map *csr_map = sec->m10bmc->info->csr_map;
u32 doorbell, status;
int ret;
ret = regmap_update_bits(sec->m10bmc->regmap,
M10BMC_SYS_BASE + M10BMC_DOORBELL,
csr_map->base + csr_map->doorbell,
DRBL_RSU_REQUEST | DRBL_HOST_STATUS,
DRBL_RSU_REQUEST |
FIELD_PREP(DRBL_HOST_STATUS,
@ -259,7 +278,7 @@ static enum fw_upload_err rsu_update_init(struct m10bmc_sec *sec)
return FW_UPLOAD_ERR_RW_ERROR;
ret = regmap_read_poll_timeout(sec->m10bmc->regmap,
M10BMC_SYS_BASE + M10BMC_DOORBELL,
csr_map->base + csr_map->doorbell,
doorbell,
rsu_start_done(doorbell),
NIOS_HANDSHAKE_INTERVAL_US,
@ -286,11 +305,12 @@ static enum fw_upload_err rsu_update_init(struct m10bmc_sec *sec)
static enum fw_upload_err rsu_prog_ready(struct m10bmc_sec *sec)
{
const struct m10bmc_csr_map *csr_map = sec->m10bmc->info->csr_map;
unsigned long poll_timeout;
u32 doorbell, progress;
int ret;
ret = m10bmc_sys_read(sec->m10bmc, M10BMC_DOORBELL, &doorbell);
ret = m10bmc_sys_read(sec->m10bmc, csr_map->doorbell, &doorbell);
if (ret)
return FW_UPLOAD_ERR_RW_ERROR;
@ -300,7 +320,7 @@ static enum fw_upload_err rsu_prog_ready(struct m10bmc_sec *sec)
if (time_after(jiffies, poll_timeout))
break;
ret = m10bmc_sys_read(sec->m10bmc, M10BMC_DOORBELL, &doorbell);
ret = m10bmc_sys_read(sec->m10bmc, csr_map->doorbell, &doorbell);
if (ret)
return FW_UPLOAD_ERR_RW_ERROR;
}
@ -319,11 +339,12 @@ static enum fw_upload_err rsu_prog_ready(struct m10bmc_sec *sec)
static enum fw_upload_err rsu_send_data(struct m10bmc_sec *sec)
{
const struct m10bmc_csr_map *csr_map = sec->m10bmc->info->csr_map;
u32 doorbell;
int ret;
ret = regmap_update_bits(sec->m10bmc->regmap,
M10BMC_SYS_BASE + M10BMC_DOORBELL,
csr_map->base + csr_map->doorbell,
DRBL_HOST_STATUS,
FIELD_PREP(DRBL_HOST_STATUS,
HOST_STATUS_WRITE_DONE));
@ -331,7 +352,7 @@ static enum fw_upload_err rsu_send_data(struct m10bmc_sec *sec)
return FW_UPLOAD_ERR_RW_ERROR;
ret = regmap_read_poll_timeout(sec->m10bmc->regmap,
M10BMC_SYS_BASE + M10BMC_DOORBELL,
csr_map->base + csr_map->doorbell,
doorbell,
rsu_prog(doorbell) != RSU_PROG_READY,
NIOS_HANDSHAKE_INTERVAL_US,
@ -360,7 +381,9 @@ static enum fw_upload_err rsu_send_data(struct m10bmc_sec *sec)
static int rsu_check_complete(struct m10bmc_sec *sec, u32 *doorbell)
{
if (m10bmc_sys_read(sec->m10bmc, M10BMC_DOORBELL, doorbell))
const struct m10bmc_csr_map *csr_map = sec->m10bmc->info->csr_map;
if (m10bmc_sys_read(sec->m10bmc, csr_map->doorbell, doorbell))
return -EIO;
switch (rsu_stat(*doorbell)) {
@ -389,10 +412,11 @@ static int rsu_check_complete(struct m10bmc_sec *sec, u32 *doorbell)
static enum fw_upload_err rsu_cancel(struct m10bmc_sec *sec)
{
const struct m10bmc_csr_map *csr_map = sec->m10bmc->info->csr_map;
u32 doorbell;
int ret;
ret = m10bmc_sys_read(sec->m10bmc, M10BMC_DOORBELL, &doorbell);
ret = m10bmc_sys_read(sec->m10bmc, csr_map->doorbell, &doorbell);
if (ret)
return FW_UPLOAD_ERR_RW_ERROR;
@ -400,7 +424,7 @@ static enum fw_upload_err rsu_cancel(struct m10bmc_sec *sec)
return FW_UPLOAD_ERR_BUSY;
ret = regmap_update_bits(sec->m10bmc->regmap,
M10BMC_SYS_BASE + M10BMC_DOORBELL,
csr_map->base + csr_map->doorbell,
DRBL_HOST_STATUS,
FIELD_PREP(DRBL_HOST_STATUS,
HOST_STATUS_ABORT_RSU));
@ -445,6 +469,7 @@ static enum fw_upload_err m10bmc_sec_write(struct fw_upload *fwl, const u8 *data
u32 offset, u32 size, u32 *written)
{
struct m10bmc_sec *sec = fwl->dd_handle;
const struct m10bmc_csr_map *csr_map = sec->m10bmc->info->csr_map;
u32 blk_size, doorbell, extra_offset;
unsigned int stride, extra = 0;
int ret;
@ -453,7 +478,7 @@ static enum fw_upload_err m10bmc_sec_write(struct fw_upload *fwl, const u8 *data
if (sec->cancel_request)
return rsu_cancel(sec);
ret = m10bmc_sys_read(sec->m10bmc, M10BMC_DOORBELL, &doorbell);
ret = m10bmc_sys_read(sec->m10bmc, csr_map->doorbell, &doorbell);
if (ret) {
return FW_UPLOAD_ERR_RW_ERROR;
} else if (rsu_prog(doorbell) != RSU_PROG_READY) {

View file

@ -19,7 +19,7 @@ static ssize_t bmc_version_show(struct device *dev,
unsigned int val;
int ret;
ret = m10bmc_sys_read(ddata, M10BMC_BUILD_VER, &val);
ret = m10bmc_sys_read(ddata, ddata->info->csr_map->build_version, &val);
if (ret)
return ret;
@ -34,7 +34,7 @@ static ssize_t bmcfw_version_show(struct device *dev,
unsigned int val;
int ret;
ret = m10bmc_sys_read(ddata, NIOS2_FW_VERSION, &val);
ret = m10bmc_sys_read(ddata, ddata->info->csr_map->fw_version, &val);
if (ret)
return ret;
@ -49,11 +49,11 @@ static ssize_t mac_address_show(struct device *dev,
unsigned int macaddr_low, macaddr_high;
int ret;
ret = m10bmc_sys_read(ddata, M10BMC_MAC_LOW, &macaddr_low);
ret = m10bmc_sys_read(ddata, ddata->info->csr_map->mac_low, &macaddr_low);
if (ret)
return ret;
ret = m10bmc_sys_read(ddata, M10BMC_MAC_HIGH, &macaddr_high);
ret = m10bmc_sys_read(ddata, ddata->info->csr_map->mac_high, &macaddr_high);
if (ret)
return ret;
@ -74,7 +74,7 @@ static ssize_t mac_count_show(struct device *dev,
unsigned int macaddr_high;
int ret;
ret = m10bmc_sys_read(ddata, M10BMC_MAC_HIGH, &macaddr_high);
ret = m10bmc_sys_read(ddata, ddata->info->csr_map->mac_high, &macaddr_high);
if (ret)
return ret;

View file

@ -91,6 +91,26 @@ static int intel_m10_bmc_spi_probe(struct spi_device *spi)
return m10bmc_dev_init(ddata, info);
}
static const struct m10bmc_csr_map m10bmc_n3000_csr_map = {
.base = M10BMC_SYS_BASE,
.build_version = M10BMC_BUILD_VER,
.fw_version = NIOS2_FW_VERSION,
.mac_low = M10BMC_MAC_LOW,
.mac_high = M10BMC_MAC_HIGH,
.doorbell = M10BMC_DOORBELL,
.auth_result = M10BMC_AUTH_RESULT,
.bmc_prog_addr = BMC_PROG_ADDR,
.bmc_reh_addr = BMC_REH_ADDR,
.bmc_magic = BMC_PROG_MAGIC,
.sr_prog_addr = SR_PROG_ADDR,
.sr_reh_addr = SR_REH_ADDR,
.sr_magic = SR_PROG_MAGIC,
.pr_prog_addr = PR_PROG_ADDR,
.pr_reh_addr = PR_REH_ADDR,
.pr_magic = PR_PROG_MAGIC,
.rsu_update_counter = STAGING_FLASH_COUNT,
};
static struct mfd_cell m10bmc_d5005_subdevs[] = {
{ .name = "d5005bmc-hwmon" },
{ .name = "d5005bmc-sec-update" },
@ -109,16 +129,19 @@ static struct mfd_cell m10bmc_n5010_subdevs[] = {
static const struct intel_m10bmc_platform_info m10bmc_spi_n3000 = {
.cells = m10bmc_pacn3000_subdevs,
.n_cells = ARRAY_SIZE(m10bmc_pacn3000_subdevs),
.csr_map = &m10bmc_n3000_csr_map,
};
static const struct intel_m10bmc_platform_info m10bmc_spi_d5005 = {
.cells = m10bmc_d5005_subdevs,
.n_cells = ARRAY_SIZE(m10bmc_d5005_subdevs),
.csr_map = &m10bmc_n3000_csr_map,
};
static const struct intel_m10bmc_platform_info m10bmc_spi_n5010 = {
.cells = m10bmc_n5010_subdevs,
.n_cells = ARRAY_SIZE(m10bmc_n5010_subdevs),
.csr_map = &m10bmc_n3000_csr_map,
};
static const struct spi_device_id m10bmc_spi_id[] = {

View file

@ -121,14 +121,39 @@
/* Address of 4KB inverted bit vector containing staging area FLASH count */
#define STAGING_FLASH_COUNT 0x17ffb000
/**
* struct m10bmc_csr_map - Intel MAX 10 BMC CSR register map
*/
struct m10bmc_csr_map {
unsigned int base;
unsigned int build_version;
unsigned int fw_version;
unsigned int mac_low;
unsigned int mac_high;
unsigned int doorbell;
unsigned int auth_result;
unsigned int bmc_prog_addr;
unsigned int bmc_reh_addr;
unsigned int bmc_magic;
unsigned int sr_prog_addr;
unsigned int sr_reh_addr;
unsigned int sr_magic;
unsigned int pr_prog_addr;
unsigned int pr_reh_addr;
unsigned int pr_magic;
unsigned int rsu_update_counter;
};
/**
* struct intel_m10bmc_platform_info - Intel MAX 10 BMC platform specific information
* @cells: MFD cells
* @n_cells: MFD cells ARRAY_SIZE()
* @csr_map: the mappings for register definition of MAX10 BMC
*/
struct intel_m10bmc_platform_info {
struct mfd_cell *cells;
int n_cells;
const struct m10bmc_csr_map *csr_map;
};
/**
@ -167,12 +192,17 @@ m10bmc_raw_read(struct intel_m10bmc *m10bmc, unsigned int addr,
* The base of the system registers could be configured by HW developers, and
* in HW SPEC, the base is not added to the addresses of the system registers.
*
* This macro helps to simplify the accessing of the system registers. And if
* This function helps to simplify the accessing of the system registers. And if
* the base is reconfigured in HW, SW developers could simply change the
* M10BMC_SYS_BASE accordingly.
* csr_map's base accordingly.
*/
#define m10bmc_sys_read(m10bmc, offset, val) \
m10bmc_raw_read(m10bmc, M10BMC_SYS_BASE + (offset), val)
static inline int m10bmc_sys_read(struct intel_m10bmc *m10bmc, unsigned int offset,
unsigned int *val)
{
const struct m10bmc_csr_map *csr_map = m10bmc->info->csr_map;
return m10bmc_raw_read(m10bmc, csr_map->base + offset, val);
}
/*
* MAX10 BMC Core support