Commit 4efa1d2e authored by Kelvin Cao's avatar Kelvin Cao Committed by Bjorn Helgaas
Browse files

PCI/switchtec: Add Gen4 flash information interface support

Add the new flash_info registers struct and the implementation of
ioctl_flash_part_info() for the new Gen4 hardware.

[logang@deltatee.com: rewrote commit message]
Link: https://lore.kernel.org/r/20200115035648.2578-7-logang@deltatee.com


Signed-off-by: default avatarKelvin Cao <kelvin.cao@microchip.com>
Signed-off-by: default avatarLogan Gunthorpe <logang@deltatee.com>
Signed-off-by: default avatarBjorn Helgaas <bhelgaas@google.com>
parent a3321ca3
Loading
Loading
Loading
Loading
+111 −0
Original line number Diff line number Diff line
@@ -600,6 +600,9 @@ static int ioctl_flash_info(struct switchtec_dev *stdev,
	if (stdev->gen == SWITCHTEC_GEN3) {
		info.flash_length = ioread32(&fi->gen3.flash_length);
		info.num_partitions = SWITCHTEC_NUM_PARTITIONS_GEN3;
	} else if (stdev->gen == SWITCHTEC_GEN4) {
		info.flash_length = ioread32(&fi->gen4.flash_length);
		info.num_partitions = SWITCHTEC_NUM_PARTITIONS_GEN4;
	} else {
		return -ENOTSUPP;
	}
@@ -687,6 +690,110 @@ static int flash_part_info_gen3(struct switchtec_dev *stdev,
	return 0;
}

static int flash_part_info_gen4(struct switchtec_dev *stdev,
		struct switchtec_ioctl_flash_part_info *info)
{
	struct flash_info_regs_gen4 __iomem *fi = &stdev->mmio_flash_info->gen4;
	struct sys_info_regs_gen4 __iomem *si = &stdev->mmio_sys_info->gen4;
	struct active_partition_info_gen4 __iomem *af = &fi->active_flag;

	switch (info->flash_partition) {
	case SWITCHTEC_IOCTL_PART_MAP_0:
		set_fw_info_part(info, &fi->map0);
		break;
	case SWITCHTEC_IOCTL_PART_MAP_1:
		set_fw_info_part(info, &fi->map1);
		break;
	case SWITCHTEC_IOCTL_PART_KEY_0:
		set_fw_info_part(info, &fi->key0);
		if (ioread8(&af->key) == SWITCHTEC_GEN4_KEY0_ACTIVE)
			info->active |= SWITCHTEC_IOCTL_PART_ACTIVE;
		if (ioread16(&si->key_running) == SWITCHTEC_GEN4_KEY0_RUNNING)
			info->active |= SWITCHTEC_IOCTL_PART_RUNNING;
		break;
	case SWITCHTEC_IOCTL_PART_KEY_1:
		set_fw_info_part(info, &fi->key1);
		if (ioread8(&af->key) == SWITCHTEC_GEN4_KEY1_ACTIVE)
			info->active |= SWITCHTEC_IOCTL_PART_ACTIVE;
		if (ioread16(&si->key_running) == SWITCHTEC_GEN4_KEY1_RUNNING)
			info->active |= SWITCHTEC_IOCTL_PART_RUNNING;
		break;
	case SWITCHTEC_IOCTL_PART_BL2_0:
		set_fw_info_part(info, &fi->bl2_0);
		if (ioread8(&af->bl2) == SWITCHTEC_GEN4_BL2_0_ACTIVE)
			info->active |= SWITCHTEC_IOCTL_PART_ACTIVE;
		if (ioread16(&si->bl2_running) == SWITCHTEC_GEN4_BL2_0_RUNNING)
			info->active |= SWITCHTEC_IOCTL_PART_RUNNING;
		break;
	case SWITCHTEC_IOCTL_PART_BL2_1:
		set_fw_info_part(info, &fi->bl2_1);
		if (ioread8(&af->bl2) == SWITCHTEC_GEN4_BL2_1_ACTIVE)
			info->active |= SWITCHTEC_IOCTL_PART_ACTIVE;
		if (ioread16(&si->bl2_running) == SWITCHTEC_GEN4_BL2_1_RUNNING)
			info->active |= SWITCHTEC_IOCTL_PART_RUNNING;
		break;
	case SWITCHTEC_IOCTL_PART_CFG0:
		set_fw_info_part(info, &fi->cfg0);
		if (ioread8(&af->cfg) == SWITCHTEC_GEN4_CFG0_ACTIVE)
			info->active |= SWITCHTEC_IOCTL_PART_ACTIVE;
		if (ioread16(&si->cfg_running) == SWITCHTEC_GEN4_CFG0_RUNNING)
			info->active |= SWITCHTEC_IOCTL_PART_RUNNING;
		break;
	case SWITCHTEC_IOCTL_PART_CFG1:
		set_fw_info_part(info, &fi->cfg1);
		if (ioread8(&af->cfg) == SWITCHTEC_GEN4_CFG1_ACTIVE)
			info->active |= SWITCHTEC_IOCTL_PART_ACTIVE;
		if (ioread16(&si->cfg_running) == SWITCHTEC_GEN4_CFG1_RUNNING)
			info->active |= SWITCHTEC_IOCTL_PART_RUNNING;
		break;
	case SWITCHTEC_IOCTL_PART_IMG0:
		set_fw_info_part(info, &fi->img0);
		if (ioread8(&af->img) == SWITCHTEC_GEN4_IMG0_ACTIVE)
			info->active |= SWITCHTEC_IOCTL_PART_ACTIVE;
		if (ioread16(&si->img_running) == SWITCHTEC_GEN4_IMG0_RUNNING)
			info->active |= SWITCHTEC_IOCTL_PART_RUNNING;
		break;
	case SWITCHTEC_IOCTL_PART_IMG1:
		set_fw_info_part(info, &fi->img1);
		if (ioread8(&af->img) == SWITCHTEC_GEN4_IMG1_ACTIVE)
			info->active |= SWITCHTEC_IOCTL_PART_ACTIVE;
		if (ioread16(&si->img_running) == SWITCHTEC_GEN4_IMG1_RUNNING)
			info->active |= SWITCHTEC_IOCTL_PART_RUNNING;
		break;
	case SWITCHTEC_IOCTL_PART_NVLOG:
		set_fw_info_part(info, &fi->nvlog);
		break;
	case SWITCHTEC_IOCTL_PART_VENDOR0:
		set_fw_info_part(info, &fi->vendor[0]);
		break;
	case SWITCHTEC_IOCTL_PART_VENDOR1:
		set_fw_info_part(info, &fi->vendor[1]);
		break;
	case SWITCHTEC_IOCTL_PART_VENDOR2:
		set_fw_info_part(info, &fi->vendor[2]);
		break;
	case SWITCHTEC_IOCTL_PART_VENDOR3:
		set_fw_info_part(info, &fi->vendor[3]);
		break;
	case SWITCHTEC_IOCTL_PART_VENDOR4:
		set_fw_info_part(info, &fi->vendor[4]);
		break;
	case SWITCHTEC_IOCTL_PART_VENDOR5:
		set_fw_info_part(info, &fi->vendor[5]);
		break;
	case SWITCHTEC_IOCTL_PART_VENDOR6:
		set_fw_info_part(info, &fi->vendor[6]);
		break;
	case SWITCHTEC_IOCTL_PART_VENDOR7:
		set_fw_info_part(info, &fi->vendor[7]);
		break;
	default:
		return -EINVAL;
	}

	return 0;
}

static int ioctl_flash_part_info(struct switchtec_dev *stdev,
		struct switchtec_ioctl_flash_part_info __user *uinfo)
{
@@ -700,6 +807,10 @@ static int ioctl_flash_part_info(struct switchtec_dev *stdev,
		ret = flash_part_info_gen3(stdev, &info);
		if (ret)
			return ret;
	} else if (stdev->gen == SWITCHTEC_GEN4) {
		ret = flash_part_info_gen4(stdev, &info);
		if (ret)
			return ret;
	} else {
		return -ENOTSUPP;
	}
+52 −0
Original line number Diff line number Diff line
@@ -109,6 +109,30 @@ enum {
	SWITCHTEC_GEN3_IMG1_RUNNING = 0x07,
};

enum {
	SWITCHTEC_GEN4_MAP0_RUNNING = 0x00,
	SWITCHTEC_GEN4_MAP1_RUNNING = 0x01,
	SWITCHTEC_GEN4_KEY0_RUNNING = 0x02,
	SWITCHTEC_GEN4_KEY1_RUNNING = 0x03,
	SWITCHTEC_GEN4_BL2_0_RUNNING = 0x04,
	SWITCHTEC_GEN4_BL2_1_RUNNING = 0x05,
	SWITCHTEC_GEN4_CFG0_RUNNING = 0x06,
	SWITCHTEC_GEN4_CFG1_RUNNING = 0x07,
	SWITCHTEC_GEN4_IMG0_RUNNING = 0x08,
	SWITCHTEC_GEN4_IMG1_RUNNING = 0x09,
};

enum {
	SWITCHTEC_GEN4_KEY0_ACTIVE = 0,
	SWITCHTEC_GEN4_KEY1_ACTIVE = 1,
	SWITCHTEC_GEN4_BL2_0_ACTIVE = 0,
	SWITCHTEC_GEN4_BL2_1_ACTIVE = 1,
	SWITCHTEC_GEN4_CFG0_ACTIVE = 0,
	SWITCHTEC_GEN4_CFG1_ACTIVE = 1,
	SWITCHTEC_GEN4_IMG0_ACTIVE = 0,
	SWITCHTEC_GEN4_IMG1_ACTIVE = 1,
};

struct sys_info_regs_gen3 {
	u32 reserved1;
	u32 vendor_table_revision;
@@ -205,9 +229,37 @@ struct flash_info_regs_gen3 {
	struct partition_info vendor[8];
};

struct flash_info_regs_gen4 {
	u32 flash_address;
	u32 flash_length;

	struct active_partition_info_gen4 {
		unsigned char bl2;
		unsigned char cfg;
		unsigned char img;
		unsigned char key;
	} active_flag;

	u32 reserved[3];

	struct partition_info map0;
	struct partition_info map1;
	struct partition_info key0;
	struct partition_info key1;
	struct partition_info bl2_0;
	struct partition_info bl2_1;
	struct partition_info cfg0;
	struct partition_info cfg1;
	struct partition_info img0;
	struct partition_info img1;
	struct partition_info nvlog;
	struct partition_info vendor[8];
};

struct flash_info_regs {
	union {
		struct flash_info_regs_gen3 gen3;
		struct flash_info_regs_gen4 gen4;
	};
};

+8 −0
Original line number Diff line number Diff line
@@ -32,7 +32,15 @@
#define SWITCHTEC_IOCTL_PART_VENDOR5	10
#define SWITCHTEC_IOCTL_PART_VENDOR6	11
#define SWITCHTEC_IOCTL_PART_VENDOR7	12
#define SWITCHTEC_IOCTL_PART_BL2_0	13
#define SWITCHTEC_IOCTL_PART_BL2_1	14
#define SWITCHTEC_IOCTL_PART_MAP_0	15
#define SWITCHTEC_IOCTL_PART_MAP_1	16
#define SWITCHTEC_IOCTL_PART_KEY_0	17
#define SWITCHTEC_IOCTL_PART_KEY_1	18

#define SWITCHTEC_NUM_PARTITIONS_GEN3	13
#define SWITCHTEC_NUM_PARTITIONS_GEN4	19

/* obsolete: for compatibility with old userspace software */
#define SWITCHTEC_IOCTL_NUM_PARTITIONS	SWITCHTEC_NUM_PARTITIONS_GEN3