Commit 6052a005 authored by Ilpo Järvinen's avatar Ilpo Järvinen Committed by Lee Jones
Browse files

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: default avatarTianfei zhang <tianfei.zhang@intel.com>
Signed-off-by: default avatarTianfei zhang <tianfei.zhang@intel.com>
Reviewed-by: default avatarRuss Weight <russell.h.weight@intel.com>
Reviewed-by: default avatarXu Yilun <yilun.xu@intel.com>
Signed-off-by: default avatarIlpo Järvinen <ilpo.jarvinen@linux.intel.com>
Signed-off-by: default avatarLee Jones <lee@kernel.org>
Link: https://lore.kernel.org/r/20230116100845.6153-6-ilpo.jarvinen@linux.intel.com
parent 603aed8f
Loading
Loading
Loading
Loading
+49 −24
Original line number Diff line number Diff line
@@ -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) {
+5 −5
Original line number Diff line number Diff line
@@ -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;

+23 −0
Original line number Diff line number Diff line
@@ -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[] = {
+34 −4
Original line number Diff line number Diff line
@@ -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