net: ipa: add support to code for IPA v4.5
authorAlex Elder <elder@linaro.org>
Wed, 25 Nov 2020 20:45:20 +0000 (14:45 -0600)
committerJakub Kicinski <kuba@kernel.org>
Sat, 28 Nov 2020 20:13:55 +0000 (12:13 -0800)
Update the IPA code to make use of the updated IPA v4.5 register
definitions.  Generally what this patch does is, if IPA v4.5
hardware is in use:
  - Ensure new registers or fields in IPA v4.5 are updated where
    required
  - Ensure registers or fields not supported in IPA v4.5 are not
    examined when read, or are set to 0 when written
It does this while preserving the existing functionality for IPA
versions lower than v4.5.

The values to program for QSB_MAX_READS and QSB_MAX_WRITES and the
source and destination resource counts are updated to be correct for
all versions through v4.5 as well.

Note that IPA_RESOURCE_GROUP_SRC_MAX and IPA_RESOURCE_GROUP_DST_MAX
already reflect that 5 is an acceptable number of resources (which
IPA v4.5 implements).

Signed-off-by: Alex Elder <elder@linaro.org>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/ipa/ipa_endpoint.c
drivers/net/ipa/ipa_main.c
drivers/net/ipa/ipa_reg.h

index f28ea06..27f543b 100644 (file)
@@ -520,7 +520,7 @@ static void ipa_endpoint_init_hdr(struct ipa_endpoint *endpoint)
                /* HDR_ADDITIONAL_CONST_LEN is 0; (RX only) */
                /* HDR_A5_MUX is 0 */
                /* HDR_LEN_INC_DEAGG_HDR is 0 */
-               /* HDR_METADATA_REG_VALID is 0 (TX only) */
+               /* HDR_METADATA_REG_VALID is 0 (TX only, version < v4.5) */
        }
 
        iowrite32(val, ipa->reg_virt + offset);
@@ -655,6 +655,7 @@ static void ipa_endpoint_init_aggr(struct ipa_endpoint *endpoint)
                        /* other fields ignored */
                }
                /* AGGR_FORCE_CLOSE is 0 */
+               /* AGGR_GRAN_SEL is 0 for IPA v4.5 */
        } else {
                val |= u32_encode_bits(IPA_BYPASS_AGGR, AGGR_EN_FMASK);
                /* other fields ignored */
@@ -865,9 +866,10 @@ static void ipa_endpoint_status(struct ipa_endpoint *endpoint)
                        val |= u32_encode_bits(status_endpoint_id,
                                               STATUS_ENDP_FMASK);
                }
-               /* STATUS_LOCATION is 0 (status element precedes packet) */
-               /* The next field is present for IPA v4.0 and above */
-               /* STATUS_PKT_SUPPRESS_FMASK is 0 */
+               /* STATUS_LOCATION is 0, meaning status element precedes
+                * packet (not present for IPA v4.5)
+                */
+               /* STATUS_PKT_SUPPRESS_FMASK is 0 (not present for v3.5.1) */
        }
 
        iowrite32(val, ipa->reg_virt + offset);
index 7cd7f6c..f25bcfe 100644 (file)
@@ -230,8 +230,10 @@ static void ipa_hardware_config_comp(struct ipa *ipa)
                val &= ~IPA_QMB_SELECT_CONS_EN_FMASK;
                val &= ~IPA_QMB_SELECT_PROD_EN_FMASK;
                val &= ~IPA_QMB_SELECT_GLOBAL_EN_FMASK;
-       } else  {
+       } else if (ipa->version < IPA_VERSION_4_5) {
                val |= GSI_MULTI_AXI_MASTERS_DIS_FMASK;
+       } else {
+               /* For IPA v4.5 IPA_FULL_FLUSH_WAIT_RSC_CLOSE_EN is 0 */
        }
 
        val |= GSI_MULTI_INORDER_RD_DIS_FMASK;
@@ -243,25 +245,47 @@ static void ipa_hardware_config_comp(struct ipa *ipa)
 /* Configure DDR and PCIe max read/write QSB values */
 static void ipa_hardware_config_qsb(struct ipa *ipa)
 {
+       enum ipa_version version = ipa->version;
+       u32 max0;
+       u32 max1;
        u32 val;
 
-       /* QMB_0 represents DDR; QMB_1 represents PCIe (not present in 4.2) */
+       /* QMB_0 represents DDR; QMB_1 represents PCIe */
        val = u32_encode_bits(8, GEN_QMB_0_MAX_WRITES_FMASK);
-       if (ipa->version == IPA_VERSION_4_2)
-               val |= u32_encode_bits(0, GEN_QMB_1_MAX_WRITES_FMASK);
-       else
-               val |= u32_encode_bits(4, GEN_QMB_1_MAX_WRITES_FMASK);
+       switch (version) {
+       case IPA_VERSION_4_2:
+               max1 = 0;               /* PCIe not present */
+               break;
+       case IPA_VERSION_4_5:
+               max1 = 8;
+               break;
+       default:
+               max1 = 4;
+               break;
+       }
+       val |= u32_encode_bits(max1, GEN_QMB_1_MAX_WRITES_FMASK);
        iowrite32(val, ipa->reg_virt + IPA_REG_QSB_MAX_WRITES_OFFSET);
 
-       if (ipa->version == IPA_VERSION_3_5_1) {
-               val = u32_encode_bits(8, GEN_QMB_0_MAX_READS_FMASK);
-               val |= u32_encode_bits(12, GEN_QMB_1_MAX_READS_FMASK);
-       } else {
-               val = u32_encode_bits(12, GEN_QMB_0_MAX_READS_FMASK);
-               if (ipa->version == IPA_VERSION_4_2)
-                       val |= u32_encode_bits(0, GEN_QMB_1_MAX_READS_FMASK);
-               else
-                       val |= u32_encode_bits(12, GEN_QMB_1_MAX_READS_FMASK);
+       max1 = 12;
+       switch (version) {
+       case IPA_VERSION_3_5_1:
+               max0 = 8;
+               break;
+       case IPA_VERSION_4_0:
+       case IPA_VERSION_4_1:
+               max0 = 12;
+               break;
+       case IPA_VERSION_4_2:
+               max0 = 12;
+               max1 = 0;               /* PCIe not present */
+               break;
+       case IPA_VERSION_4_5:
+               max0 = 16;
+               break;
+       }
+       val = u32_encode_bits(max0, GEN_QMB_0_MAX_READS_FMASK);
+       val |= u32_encode_bits(max1, GEN_QMB_1_MAX_READS_FMASK);
+       if (version != IPA_VERSION_3_5_1) {
                /* GEN_QMB_0_MAX_READS_BEATS is 0 */
                /* GEN_QMB_1_MAX_READS_BEATS is 0 */
        }
@@ -294,7 +318,7 @@ static void ipa_idle_indication_cfg(struct ipa *ipa,
  */
 static void ipa_hardware_dcd_config(struct ipa *ipa)
 {
-       /* Recommended values for IPA 3.5 according to IPA HPG */
+       /* Recommended values for IPA 3.5 and later according to IPA HPG */
        ipa_idle_indication_cfg(ipa, 256, false);
 }
 
@@ -320,13 +344,14 @@ static void ipa_hardware_config(struct ipa *ipa)
                iowrite32(val, ipa->reg_virt + IPA_REG_BCR_OFFSET);
        }
 
-       if (version != IPA_VERSION_3_5_1) {
-               /* Enable open global clocks (hardware workaround) */
+       /* Implement some hardware workarounds */
+       if (version != IPA_VERSION_3_5_1 && version < IPA_VERSION_4_5) {
+               /* Enable open global clocks (not needed for IPA v4.5) */
                val = GLOBAL_FMASK;
                val |= GLOBAL_2X_CLK_FMASK;
                iowrite32(val, ipa->reg_virt + IPA_REG_CLKON_CFG_OFFSET);
 
-               /* Disable PA mask to allow HOLB drop (hardware workaround) */
+               /* Disable PA mask to allow HOLB drop */
                val = ioread32(ipa->reg_virt + IPA_REG_TX_CFG_OFFSET);
                val &= ~PA_MASK_EN_FMASK;
                iowrite32(val, ipa->reg_virt + IPA_REG_TX_CFG_OFFSET);
index 7d10fa6..3fabafd 100644 (file)
@@ -238,6 +238,7 @@ static inline u32 ipa_aggr_granularity_val(u32 usec)
        return DIV_ROUND_CLOSEST(usec * TIMER_FREQUENCY, USEC_PER_SEC) - 1;
 }
 
+/* The next register is not present for IPA v4.5 */
 #define IPA_REG_TX_CFG_OFFSET                          0x000001fc
 /* The first three fields are present for IPA v3.5.1 only */
 #define TX0_PREFETCH_DISABLE_FMASK             GENMASK(0, 0)
@@ -285,6 +286,9 @@ static inline u32 ipa_resource_group_src_count(enum ipa_version version)
        case IPA_VERSION_4_2:
                return 1;
 
+       case IPA_VERSION_4_5:
+               return 5;
+
        default:
                return 0;
        }
@@ -304,6 +308,9 @@ static inline u32 ipa_resource_group_dst_count(enum ipa_version version)
        case IPA_VERSION_4_2:
                return 1;
 
+       case IPA_VERSION_4_5:
+               return 5;
+
        default:
                return 0;
        }