/* Max prefetch is 1 segment (do not set MAX_PREFETCH_FMASK) */
- /* We enable the doorbell engine for IPA v3.5.1 */
- if (gsi->version == IPA_VERSION_3_5_1 && doorbell)
+ /* No need to use the doorbell engine starting at IPA v4.0 */
+ if (gsi->version < IPA_VERSION_4_0 && doorbell)
val |= USE_DB_ENG_FMASK;
/* v4.0 introduces an escape buffer for prefetch. We use it
* on all but the AP command channel.
*/
- if (gsi->version != IPA_VERSION_3_5_1 && !channel->command) {
+ if (gsi->version >= IPA_VERSION_4_0 && !channel->command) {
/* If not otherwise set, prefetch buffers are used */
if (gsi->version < IPA_VERSION_4_5)
val |= USE_ESCAPE_BUF_ONLY_FMASK;
gsi_channel_reset_command(channel);
/* Due to a hardware quirk we may need to reset RX channels twice. */
- if (gsi->version == IPA_VERSION_3_5_1 && !channel->toward_ipa)
+ if (gsi->version < IPA_VERSION_4_0 && !channel->toward_ipa)
gsi_channel_reset_command(channel);
gsi_channel_program(channel, doorbell);
/* IPA_CMD_REGISTER_WRITE */
-/* For IPA v4.0+, this opcode gets modified with pipeline clear options */
-
+/* For IPA v4.0+, the pipeline clear options are encoded in the opcode */
#define REGISTER_WRITE_OPCODE_SKIP_CLEAR_FMASK GENMASK(8, 8)
#define REGISTER_WRITE_OPCODE_CLEAR_OPTION_FMASK GENMASK(10, 9)
struct ipa_cmd_register_write {
- __le16 flags; /* Unused/reserved for IPA v3.5.1 */
+ __le16 flags; /* Unused/reserved prior to IPA v4.0 */
__le16 offset;
__le32 value;
__le32 value_mask;
};
/* Field masks for ipa_cmd_register_write structure fields */
-/* The next field is present for IPA v4.0 and above */
+/* The next field is present for IPA v4.0+ */
#define REGISTER_WRITE_FLAGS_OFFSET_HIGH_FMASK GENMASK(14, 11)
-/* The next field is present for IPA v3.5.1 only */
+/* The next field is not present for IPA v4.0+ */
#define REGISTER_WRITE_FLAGS_SKIP_CLEAR_FMASK GENMASK(15, 15)
-/* The next field and its values are present for IPA v3.5.1 only */
+/* The next field and its values are not present for IPA v4.0+ */
#define REGISTER_WRITE_CLEAR_OPTIONS_FMASK GENMASK(1, 0)
/* IPA_CMD_IP_PACKET_INIT */
/* Field masks for ipa_cmd_hw_dma_mem_mem structure fields */
#define DMA_SHARED_MEM_FLAGS_DIRECTION_FMASK GENMASK(0, 0)
-/* The next two fields are present for IPA v3.5.1 only. */
+/* The next two fields are not present for IPA v4.0+ */
#define DMA_SHARED_MEM_FLAGS_SKIP_CLEAR_FMASK GENMASK(1, 1)
#define DMA_SHARED_MEM_FLAGS_CLEAR_OPTIONS_FMASK GENMASK(3, 2)
u32 bit_count;
/* The maximum offset in a register_write immediate command depends
- * on the version of IPA. IPA v3.5.1 supports a 16 bit offset, but
- * newer versions allow some additional high-order bits.
+ * on the version of IPA. A 16 bit offset is always supported,
+ * but starting with IPA v4.0 some additional high-order bits are
+ * allowed.
*/
bit_count = BITS_PER_BYTE * sizeof(payload->offset);
- if (ipa->version != IPA_VERSION_3_5_1)
+ if (ipa->version >= IPA_VERSION_4_0)
bit_count += hweight32(REGISTER_WRITE_FLAGS_OFFSET_HIGH_FMASK);
BUILD_BUG_ON(bit_count > 32);
offset_max = ~0U >> (32 - bit_count);
/* pipeline_clear_src_grp is not used */
clear_option = clear_full ? pipeline_clear_full : pipeline_clear_hps;
- if (ipa->version != IPA_VERSION_3_5_1) {
+ /* IPA v4.0+ represents the pipeline clear options in the opcode. It
+ * also supports a larger offset by encoding additional high-order
+ * bits in the payload flags field.
+ */
+ if (ipa->version >= IPA_VERSION_4_0) {
u16 offset_high;
u32 val;
* if (endpoint->toward_ipa)
* assert(ipa->version != IPA_VERSION_4.2);
* else
- * assert(ipa->version == IPA_VERSION_3_5_1);
+ * assert(ipa->version < IPA_VERSION_4_0);
*/
mask = endpoint->toward_ipa ? ENDP_DELAY_FMASK : ENDP_SUSPEND_FMASK;
{
bool suspended;
- if (endpoint->ipa->version != IPA_VERSION_3_5_1)
+ if (endpoint->ipa->version >= IPA_VERSION_4_0)
return enable; /* For IPA v4.0+, no change made */
/* assert(!endpoint->toward_ipa); */
/* Where IPA will write the length */
offset = offsetof(struct rmnet_map_header, pkt_len);
/* Upper bits are stored in HDR_EXT with IPA v4.5 */
- if (version == IPA_VERSION_4_5)
+ if (version >= IPA_VERSION_4_5)
offset &= field_mask(HDR_OFST_PKT_SIZE_FMASK);
val |= HDR_OFST_PKT_SIZE_VALID_FMASK;
/* IPA v4.5 adds some most-significant bits to a few fields,
* two of which are defined in the HDR (not HDR_EXT) register.
*/
- if (ipa->version == IPA_VERSION_4_5) {
+ if (ipa->version >= IPA_VERSION_4_5) {
/* HDR_TOTAL_LEN_OR_PAD_OFFSET is 0, so MSB is 0 */
if (endpoint->data->qmap && !endpoint->toward_ipa) {
u32 offset;
if (!microseconds)
return 0; /* Nothing to compute if timer period is 0 */
- if (ipa->version == IPA_VERSION_4_5)
+ if (ipa->version >= IPA_VERSION_4_5)
return hol_block_timer_qtime_val(ipa, microseconds);
/* Use 64 bit arithmetic to avoid overflow... */
* is active, we need to handle things specially to recover.
* All other cases just need to reset the underlying GSI channel.
*/
- special = ipa->version == IPA_VERSION_3_5_1 &&
- !endpoint->toward_ipa &&
+ special = ipa->version < IPA_VERSION_4_0 && !endpoint->toward_ipa &&
endpoint->data->aggregation;
if (special && ipa_endpoint_aggr_active(endpoint))
ret = ipa_endpoint_reset_rx_aggr(endpoint);
(void)ipa_endpoint_program_suspend(endpoint, true);
}
- /* IPA v3.5.1 doesn't use channel stop for suspend */
- stop_channel = endpoint->ipa->version != IPA_VERSION_3_5_1;
+ /* Starting with IPA v4.0, endpoints are suspended by stopping the
+ * underlying GSI channel rather than using endpoint suspend mode.
+ */
+ stop_channel = endpoint->ipa->version >= IPA_VERSION_4_0;
ret = gsi_channel_suspend(gsi, endpoint->channel_id, stop_channel);
if (ret)
dev_err(dev, "error %d suspending channel %u\n", ret,
if (!endpoint->toward_ipa)
(void)ipa_endpoint_program_suspend(endpoint, false);
- /* IPA v3.5.1 doesn't use channel start for resume */
- start_channel = endpoint->ipa->version != IPA_VERSION_3_5_1;
+ /* Starting with IPA v4.0, the underlying GSI channel must be
+ * restarted for resume.
+ */
+ start_channel = endpoint->ipa->version >= IPA_VERSION_4_0;
ret = gsi_channel_resume(gsi, endpoint->channel_id, start_channel);
if (ret)
dev_err(dev, "error %d resuming channel %u\n", ret,
{
u32 val;
- /* Nothing to configure for IPA v3.5.1 */
- if (ipa->version == IPA_VERSION_3_5_1)
+ /* Nothing to configure prior to IPA v4.0 */
+ if (ipa->version < IPA_VERSION_4_0)
return;
val = ioread32(ipa->reg_virt + IPA_REG_COMP_CFG_OFFSET);
}
/* Implement some hardware workarounds */
- if (version != IPA_VERSION_3_5_1 && version < IPA_VERSION_4_5) {
+ if (version >= IPA_VERSION_4_0 && version < IPA_VERSION_4_5) {
/* Enable open global clocks (not needed for IPA v4.5) */
val = GLOBAL_FMASK;
val |= GLOBAL_2X_CLK_FMASK;
/* None of the stats fields are valid (IPA v4.0 and above) */
- if (ipa->version != IPA_VERSION_3_5_1) {
+ if (ipa->version >= IPA_VERSION_4_0) {
mem = &ipa->mem[IPA_MEM_STATS_QUOTA_MODEM];
if (mem->size) {
req.hw_stats_quota_base_addr_valid = 1;