@@ -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);
@@ -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);
@@ -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;
}
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> --- drivers/net/ipa/ipa_endpoint.c | 10 +++--- drivers/net/ipa/ipa_main.c | 63 ++++++++++++++++++++++++---------- drivers/net/ipa/ipa_reg.h | 7 ++++ 3 files changed, 57 insertions(+), 23 deletions(-) -- 2.20.1