PCI/switchtec: Add Gen4 flash information interface support
authorKelvin Cao <kelvin.cao@microchip.com>
Wed, 15 Jan 2020 03:56:47 +0000 (20:56 -0700)
committerBjorn Helgaas <bhelgaas@google.com>
Wed, 15 Jan 2020 17:00:39 +0000 (11:00 -0600)
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: Kelvin Cao <kelvin.cao@microchip.com>
Signed-off-by: Logan Gunthorpe <logang@deltatee.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
drivers/pci/switch/switchtec.c
include/linux/switchtec.h
include/uapi/linux/switchtec_ioctl.h

index b09c3f53a552c3fd03893bfcf082458da666666c..af85d232d200b39eb10f3274544bf34392874ced 100644 (file)
@@ -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;
        }
index d012520e5cc5c2b78fbc2efe3b8dfec637a8f7ad..e8515524413581dbce2ef00dd9e652568bcc1677 100644 (file)
@@ -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;
        };
 };
 
index 4d09cfa2e9e6da8e26ccd1f8cd632138667069dd..2c661a3557e519eaa9ba16baf6ac3f2ba3e0e20b 100644 (file)
 #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