PCI: brcmstb: Add bcm7278 register info
authorJim Quinlan <jquinlan@broadcom.com>
Fri, 11 Sep 2020 17:52:23 +0000 (13:52 -0400)
committerLorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Thu, 17 Sep 2020 11:30:38 +0000 (12:30 +0100)
Add in compatibility strings and code for three Broadcom STB chips.  Some
of the register locations, shifts, and masks are different for certain
chips, requiring the use of different constants based on of_id.

We would like to add the following at this time to the match list but we
need to wait until the end of this patchset so that everything works.

    { .compatible = "brcm,bcm7211-pcie", .data = &generic_cfg },
    { .compatible = "brcm,bcm7278-pcie", .data = &bcm7278_cfg },
    { .compatible = "brcm,bcm7216-pcie", .data = &bcm7278_cfg },
    { .compatible = "brcm,bcm7445-pcie", .data = &generic_cfg },

Link: https://lore.kernel.org/r/20200911175232.19016-4-james.quinlan@broadcom.com
Signed-off-by: Jim Quinlan <jquinlan@broadcom.com>
Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Acked-by: Florian Fainelli <f.fainelli@gmail.com>
Acked-by: Rob Herring <robh@kernel.org>
drivers/pci/controller/pcie-brcmstb.c

index 85fa7d5..c2b3d29 100644 (file)
 #define  PCIE_EXT_SLOT_SHIFT                           15
 #define  PCIE_EXT_FUNC_SHIFT                           12
 
-#define PCIE_RGR1_SW_INIT_1                            0x9210
 #define  PCIE_RGR1_SW_INIT_1_PERST_MASK                        0x1
-#define  PCIE_RGR1_SW_INIT_1_INIT_MASK                 0x2
+#define  PCIE_RGR1_SW_INIT_1_PERST_SHIFT               0x0
 
 /* PCIe parameters */
 #define BRCM_NUM_PCIE_OUT_WINS         0x4
 #define SSC_STATUS_SSC_MASK            0x400
 #define SSC_STATUS_PLL_LOCK_MASK       0x800
 
+#define IDX_ADDR(pcie)                 (pcie->reg_offsets[EXT_CFG_INDEX])
+#define DATA_ADDR(pcie)                        (pcie->reg_offsets[EXT_CFG_DATA])
+#define PCIE_RGR1_SW_INIT_1(pcie)      (pcie->reg_offsets[RGR1_SW_INIT_1])
+
+enum {
+       RGR1_SW_INIT_1,
+       EXT_CFG_INDEX,
+       EXT_CFG_DATA,
+};
+
+enum {
+       RGR1_SW_INIT_1_INIT_MASK,
+       RGR1_SW_INIT_1_INIT_SHIFT,
+};
+
+enum pcie_type {
+       GENERIC,
+       BCM7278,
+       BCM2711,
+};
+
+struct pcie_cfg_data {
+       const int *reg_field_info;
+       const int *offsets;
+       const enum pcie_type type;
+};
+
+static const int pcie_reg_field_info[] = {
+       [RGR1_SW_INIT_1_INIT_MASK] = 0x2,
+       [RGR1_SW_INIT_1_INIT_SHIFT] = 0x1,
+};
+
+static const int pcie_reg_field_info_bcm7278[] = {
+       [RGR1_SW_INIT_1_INIT_MASK] = 0x1,
+       [RGR1_SW_INIT_1_INIT_SHIFT] = 0x0,
+};
+
+static const int pcie_offsets[] = {
+       [RGR1_SW_INIT_1] = 0x9210,
+       [EXT_CFG_INDEX]  = 0x9000,
+       [EXT_CFG_DATA]   = 0x9004,
+};
+
+static const struct pcie_cfg_data generic_cfg = {
+       .reg_field_info = pcie_reg_field_info,
+       .offsets        = pcie_offsets,
+       .type           = GENERIC,
+};
+
+static const int pcie_offset_bcm7278[] = {
+       [RGR1_SW_INIT_1] = 0xc010,
+       [EXT_CFG_INDEX] = 0x9000,
+       [EXT_CFG_DATA] = 0x9004,
+};
+
+static const struct pcie_cfg_data bcm7278_cfg = {
+       .reg_field_info = pcie_reg_field_info_bcm7278,
+       .offsets        = pcie_offset_bcm7278,
+       .type           = BCM7278,
+};
+
+static const struct pcie_cfg_data bcm2711_cfg = {
+       .reg_field_info = pcie_reg_field_info,
+       .offsets        = pcie_offsets,
+       .type           = BCM2711,
+};
+
 struct brcm_msi {
        struct device           *dev;
        void __iomem            *base;
@@ -177,6 +243,9 @@ struct brcm_pcie {
        int                     gen;
        u64                     msi_target_addr;
        struct brcm_msi         *msi;
+       const int               *reg_offsets;
+       const int               *reg_field_info;
+       enum pcie_type          type;
 };
 
 /*
@@ -603,20 +672,21 @@ static struct pci_ops brcm_pcie_ops = {
 
 static inline void brcm_pcie_bridge_sw_init_set(struct brcm_pcie *pcie, u32 val)
 {
-       u32 tmp;
+       u32 tmp, mask =  pcie->reg_field_info[RGR1_SW_INIT_1_INIT_MASK];
+       u32 shift = pcie->reg_field_info[RGR1_SW_INIT_1_INIT_SHIFT];
 
-       tmp = readl(pcie->base + PCIE_RGR1_SW_INIT_1);
-       u32p_replace_bits(&tmp, val, PCIE_RGR1_SW_INIT_1_INIT_MASK);
-       writel(tmp, pcie->base + PCIE_RGR1_SW_INIT_1);
+       tmp = readl(pcie->base + PCIE_RGR1_SW_INIT_1(pcie));
+       tmp = (tmp & ~mask) | ((val << shift) & mask);
+       writel(tmp, pcie->base + PCIE_RGR1_SW_INIT_1(pcie));
 }
 
 static inline void brcm_pcie_perst_set(struct brcm_pcie *pcie, u32 val)
 {
        u32 tmp;
 
-       tmp = readl(pcie->base + PCIE_RGR1_SW_INIT_1);
+       tmp = readl(pcie->base + PCIE_RGR1_SW_INIT_1(pcie));
        u32p_replace_bits(&tmp, val, PCIE_RGR1_SW_INIT_1_PERST_MASK);
-       writel(tmp, pcie->base + PCIE_RGR1_SW_INIT_1);
+       writel(tmp, pcie->base + PCIE_RGR1_SW_INIT_1(pcie));
 }
 
 static inline int brcm_pcie_get_rc_bar2_size_and_offset(struct brcm_pcie *pcie,
@@ -927,11 +997,17 @@ static int brcm_pcie_remove(struct platform_device *pdev)
        return 0;
 }
 
+static const struct of_device_id brcm_pcie_match[] = {
+       { .compatible = "brcm,bcm2711-pcie", .data = &bcm2711_cfg },
+       {},
+};
+
 static int brcm_pcie_probe(struct platform_device *pdev)
 {
        struct device_node *np = pdev->dev.of_node, *msi_np;
        struct pci_host_bridge *bridge;
        struct device_node *fw_np;
+       const struct pcie_cfg_data *data;
        struct brcm_pcie *pcie;
        int ret;
 
@@ -953,9 +1029,18 @@ static int brcm_pcie_probe(struct platform_device *pdev)
        if (!bridge)
                return -ENOMEM;
 
+       data = of_device_get_match_data(&pdev->dev);
+       if (!data) {
+               pr_err("failed to look up compatible string\n");
+               return -EINVAL;
+       }
+
        pcie = pci_host_bridge_priv(bridge);
        pcie->dev = &pdev->dev;
        pcie->np = np;
+       pcie->reg_offsets = data->offsets;
+       pcie->reg_field_info = data->reg_field_info;
+       pcie->type = data->type;
 
        pcie->base = devm_platform_ioremap_resource(pdev, 0);
        if (IS_ERR(pcie->base))
@@ -1000,10 +1085,6 @@ fail:
        return ret;
 }
 
-static const struct of_device_id brcm_pcie_match[] = {
-       { .compatible = "brcm,bcm2711-pcie" },
-       {},
-};
 MODULE_DEVICE_TABLE(of, brcm_pcie_match);
 
 static struct platform_driver brcm_pcie_driver = {