Merge branch 'ipa-v3.1'

Alex Elder says:

====================
net: ipa: add support for IPA v3.1

This series adds support for IPA v3.1, used by the Qualcomm
Snapdragon 835 (MSM8998).

The first patch adds "qcom,msm8998-ipa" to the DT binding.

The next four patches add code to ensure correct operation on
IPA v3.1:
  - Avoid touching unsupported inter-EE interrupt mask registers
  - Set the proper flags in the clock configuration register
  - Work around the lack of an IPA FLAVOR_0 register
  - Work around the lack of a GSI PARAM_2 register

The last patch defines configuration data for this version of IPA.

Many thanks are due to AngeloGioacchino Del Regno and Jami Kettunen,
both associated with SoMainline.  Angelo first posted code to
implement most of what was required for this, and Jami has been
helpful testing these changes on his hardware.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
David S. Miller 2021-06-21 12:31:00 -07:00
commit 63d66ec924
9 changed files with 629 additions and 40 deletions

View File

@ -44,6 +44,7 @@ description:
properties:
compatible:
enum:
- qcom,msm8998-ipa
- qcom,sc7180-ipa
- qcom,sc7280-ipa
- qcom,sdm845-ipa

View File

@ -10,6 +10,6 @@ ipa-y := ipa_main.o ipa_clock.o ipa_reg.o ipa_mem.o \
ipa_resource.o ipa_qmi.o ipa_qmi_msg.o \
ipa_sysfs.o
ipa-y += ipa_data-v3.5.1.o ipa_data-v4.2.o \
ipa_data-v4.5.o ipa_data-v4.9.o \
ipa_data-v4.11.o
ipa-y += ipa_data-v3.1.o ipa_data-v3.5.1.o \
ipa_data-v4.2.o ipa_data-v4.5.o \
ipa_data-v4.9.o ipa_data-v4.11.o

View File

@ -210,13 +210,65 @@ static void gsi_irq_setup(struct gsi *gsi)
iowrite32(0, gsi->virt + GSI_CNTXT_GLOB_IRQ_EN_OFFSET);
iowrite32(0, gsi->virt + GSI_CNTXT_SRC_IEOB_IRQ_MSK_OFFSET);
/* The inter-EE registers are in the non-adjusted address range */
iowrite32(0, gsi->virt_raw + GSI_INTER_EE_SRC_CH_IRQ_MSK_OFFSET);
iowrite32(0, gsi->virt_raw + GSI_INTER_EE_SRC_EV_CH_IRQ_MSK_OFFSET);
/* The inter-EE interrupts are not supported for IPA v3.0-v3.1 */
if (gsi->version > IPA_VERSION_3_1) {
u32 offset;
/* These registers are in the non-adjusted address range */
offset = GSI_INTER_EE_SRC_CH_IRQ_MSK_OFFSET;
iowrite32(0, gsi->virt_raw + offset);
offset = GSI_INTER_EE_SRC_EV_CH_IRQ_MSK_OFFSET;
iowrite32(0, gsi->virt_raw + offset);
}
iowrite32(0, gsi->virt + GSI_CNTXT_GSI_IRQ_EN_OFFSET);
}
/* Get # supported channel and event rings; there is no gsi_ring_teardown() */
static int gsi_ring_setup(struct gsi *gsi)
{
struct device *dev = gsi->dev;
u32 count;
u32 val;
if (gsi->version < IPA_VERSION_3_5_1) {
/* No HW_PARAM_2 register prior to IPA v3.5.1, assume the max */
gsi->channel_count = GSI_CHANNEL_COUNT_MAX;
gsi->evt_ring_count = GSI_EVT_RING_COUNT_MAX;
return 0;
}
val = ioread32(gsi->virt + GSI_GSI_HW_PARAM_2_OFFSET);
count = u32_get_bits(val, NUM_CH_PER_EE_FMASK);
if (!count) {
dev_err(dev, "GSI reports zero channels supported\n");
return -EINVAL;
}
if (count > GSI_CHANNEL_COUNT_MAX) {
dev_warn(dev, "limiting to %u channels; hardware supports %u\n",
GSI_CHANNEL_COUNT_MAX, count);
count = GSI_CHANNEL_COUNT_MAX;
}
gsi->channel_count = count;
count = u32_get_bits(val, NUM_EV_PER_EE_FMASK);
if (!count) {
dev_err(dev, "GSI reports zero event rings supported\n");
return -EINVAL;
}
if (count > GSI_EVT_RING_COUNT_MAX) {
dev_warn(dev,
"limiting to %u event rings; hardware supports %u\n",
GSI_EVT_RING_COUNT_MAX, count);
count = GSI_EVT_RING_COUNT_MAX;
}
gsi->evt_ring_count = count;
return 0;
}
/* Event ring commands are performed one at a time. Their completion
* is signaled by the event ring control GSI interrupt type, which is
* only enabled when we issue an event ring command. Only the event
@ -1827,43 +1879,21 @@ static void gsi_channel_teardown(struct gsi *gsi)
/* Setup function for GSI. GSI firmware must be loaded and initialized */
int gsi_setup(struct gsi *gsi)
{
struct device *dev = gsi->dev;
u32 val;
int ret;
/* Here is where we first touch the GSI hardware */
val = ioread32(gsi->virt + GSI_GSI_STATUS_OFFSET);
if (!(val & ENABLED_FMASK)) {
dev_err(dev, "GSI has not been enabled\n");
dev_err(gsi->dev, "GSI has not been enabled\n");
return -EIO;
}
gsi_irq_setup(gsi); /* No matching teardown required */
val = ioread32(gsi->virt + GSI_GSI_HW_PARAM_2_OFFSET);
gsi->channel_count = u32_get_bits(val, NUM_CH_PER_EE_FMASK);
if (!gsi->channel_count) {
dev_err(dev, "GSI reports zero channels supported\n");
return -EINVAL;
}
if (gsi->channel_count > GSI_CHANNEL_COUNT_MAX) {
dev_warn(dev,
"limiting to %u channels; hardware supports %u\n",
GSI_CHANNEL_COUNT_MAX, gsi->channel_count);
gsi->channel_count = GSI_CHANNEL_COUNT_MAX;
}
gsi->evt_ring_count = u32_get_bits(val, NUM_EV_PER_EE_FMASK);
if (!gsi->evt_ring_count) {
dev_err(dev, "GSI reports zero event rings supported\n");
return -EINVAL;
}
if (gsi->evt_ring_count > GSI_EVT_RING_COUNT_MAX) {
dev_warn(dev,
"limiting to %u event rings; hardware supports %u\n",
GSI_EVT_RING_COUNT_MAX, gsi->evt_ring_count);
gsi->evt_ring_count = GSI_EVT_RING_COUNT_MAX;
}
ret = gsi_ring_setup(gsi); /* No matching teardown required */
if (ret)
return ret;
/* Initialize the error log */
iowrite32(0, gsi->virt + GSI_ERROR_LOG_OFFSET);

View File

@ -17,7 +17,7 @@
/* Maximum number of channels and event rings supported by the driver */
#define GSI_CHANNEL_COUNT_MAX 23
#define GSI_EVT_RING_COUNT_MAX 20
#define GSI_EVT_RING_COUNT_MAX 24
/* Maximum TLV FIFO size for a channel; 64 here is arbitrary (and high) */
#define GSI_TLV_MAX 64

View File

@ -52,7 +52,8 @@
*/
#define GSI_EE_REG_ADJUST 0x0000d000 /* IPA v4.5+ */
/* The two inter-EE IRQ register offsets are relative to gsi->virt_raw */
/* The inter-EE IRQ registers are relative to gsi->virt_raw (IPA v3.5+) */
#define GSI_INTER_EE_SRC_CH_IRQ_MSK_OFFSET \
GSI_INTER_EE_N_SRC_CH_IRQ_MSK_OFFSET(GSI_EE_AP)
#define GSI_INTER_EE_N_SRC_CH_IRQ_MSK_OFFSET(ee) \

View File

@ -0,0 +1,533 @@
// SPDX-License-Identifier: GPL-2.0
/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
* Copyright (C) 2019-2021 Linaro Ltd.
*/
#include <linux/log2.h>
#include "gsi.h"
#include "ipa_data.h"
#include "ipa_endpoint.h"
#include "ipa_mem.h"
/** enum ipa_resource_type - IPA resource types for an SoC having IPA v3.1 */
enum ipa_resource_type {
/* Source resource types; first must have value 0 */
IPA_RESOURCE_TYPE_SRC_PKT_CONTEXTS = 0,
IPA_RESOURCE_TYPE_SRC_HDR_SECTORS,
IPA_RESOURCE_TYPE_SRC_HDRI1_BUFFER,
IPA_RESOURCE_TYPE_SRC_DESCRIPTOR_LISTS,
IPA_RESOURCE_TYPE_SRC_DESCRIPTOR_BUFF,
IPA_RESOURCE_TYPE_SRC_HDRI2_BUFFERS,
IPA_RESOURCE_TYPE_SRC_HPS_DMARS,
IPA_RESOURCE_TYPE_SRC_ACK_ENTRIES,
/* Destination resource types; first must have value 0 */
IPA_RESOURCE_TYPE_DST_DATA_SECTORS = 0,
IPA_RESOURCE_TYPE_DST_DATA_SECTOR_LISTS,
IPA_RESOURCE_TYPE_DST_DPS_DMARS,
};
/* Resource groups used for an SoC having IPA v3.1 */
enum ipa_rsrc_group_id {
/* Source resource group identifiers */
IPA_RSRC_GROUP_SRC_UL = 0,
IPA_RSRC_GROUP_SRC_DL,
IPA_RSRC_GROUP_SRC_DIAG,
IPA_RSRC_GROUP_SRC_DMA,
IPA_RSRC_GROUP_SRC_UNUSED,
IPA_RSRC_GROUP_SRC_UC_RX_Q,
IPA_RSRC_GROUP_SRC_COUNT, /* Last in set; not a source group */
/* Destination resource group identifiers */
IPA_RSRC_GROUP_DST_UL = 0,
IPA_RSRC_GROUP_DST_DL,
IPA_RSRC_GROUP_DST_DIAG_DPL,
IPA_RSRC_GROUP_DST_DMA,
IPA_RSRC_GROUP_DST_Q6ZIP_GENERAL,
IPA_RSRC_GROUP_DST_Q6ZIP_ENGINE,
IPA_RSRC_GROUP_DST_COUNT, /* Last; not a destination group */
};
/* QSB configuration data for an SoC having IPA v3.1 */
static const struct ipa_qsb_data ipa_qsb_data[] = {
[IPA_QSB_MASTER_DDR] = {
.max_writes = 8,
.max_reads = 8,
},
[IPA_QSB_MASTER_PCIE] = {
.max_writes = 2,
.max_reads = 8,
},
};
/* Endpoint data for an SoC having IPA v3.1 */
static const struct ipa_gsi_endpoint_data ipa_gsi_endpoint_data[] = {
[IPA_ENDPOINT_AP_COMMAND_TX] = {
.ee_id = GSI_EE_AP,
.channel_id = 6,
.endpoint_id = 22,
.toward_ipa = true,
.channel = {
.tre_count = 256,
.event_count = 256,
.tlv_count = 18,
},
.endpoint = {
.config = {
.resource_group = IPA_RSRC_GROUP_SRC_UL,
.dma_mode = true,
.dma_endpoint = IPA_ENDPOINT_AP_LAN_RX,
.tx = {
.seq_type = IPA_SEQ_DMA,
},
},
},
},
[IPA_ENDPOINT_AP_LAN_RX] = {
.ee_id = GSI_EE_AP,
.channel_id = 7,
.endpoint_id = 15,
.toward_ipa = false,
.channel = {
.tre_count = 256,
.event_count = 256,
.tlv_count = 8,
},
.endpoint = {
.config = {
.resource_group = IPA_RSRC_GROUP_SRC_UL,
.aggregation = true,
.status_enable = true,
.rx = {
.pad_align = ilog2(sizeof(u32)),
},
},
},
},
[IPA_ENDPOINT_AP_MODEM_TX] = {
.ee_id = GSI_EE_AP,
.channel_id = 5,
.endpoint_id = 3,
.toward_ipa = true,
.channel = {
.tre_count = 512,
.event_count = 512,
.tlv_count = 16,
},
.endpoint = {
.filter_support = true,
.config = {
.resource_group = IPA_RSRC_GROUP_SRC_UL,
.checksum = true,
.qmap = true,
.status_enable = true,
.tx = {
.seq_type = IPA_SEQ_2_PASS_SKIP_LAST_UC,
.status_endpoint =
IPA_ENDPOINT_MODEM_AP_RX,
},
},
},
},
[IPA_ENDPOINT_AP_MODEM_RX] = {
.ee_id = GSI_EE_AP,
.channel_id = 8,
.endpoint_id = 16,
.toward_ipa = false,
.channel = {
.tre_count = 256,
.event_count = 256,
.tlv_count = 8,
},
.endpoint = {
.config = {
.resource_group = IPA_RSRC_GROUP_DST_DL,
.checksum = true,
.qmap = true,
.aggregation = true,
.rx = {
.aggr_close_eof = true,
},
},
},
},
[IPA_ENDPOINT_MODEM_LAN_TX] = {
.ee_id = GSI_EE_MODEM,
.channel_id = 4,
.endpoint_id = 9,
.toward_ipa = true,
.endpoint = {
.filter_support = true,
},
},
[IPA_ENDPOINT_MODEM_AP_TX] = {
.ee_id = GSI_EE_MODEM,
.channel_id = 0,
.endpoint_id = 5,
.toward_ipa = true,
.endpoint = {
.filter_support = true,
},
},
[IPA_ENDPOINT_MODEM_AP_RX] = {
.ee_id = GSI_EE_MODEM,
.channel_id = 5,
.endpoint_id = 18,
.toward_ipa = false,
},
};
/* Source resource configuration data for an SoC having IPA v3.1 */
static const struct ipa_resource ipa_resource_src[] = {
[IPA_RESOURCE_TYPE_SRC_PKT_CONTEXTS] = {
.limits[IPA_RSRC_GROUP_SRC_UL] = {
.min = 3, .max = 255,
},
.limits[IPA_RSRC_GROUP_SRC_DL] = {
.min = 3, .max = 255,
},
.limits[IPA_RSRC_GROUP_SRC_DIAG] = {
.min = 1, .max = 255,
},
.limits[IPA_RSRC_GROUP_SRC_DMA] = {
.min = 1, .max = 255,
},
.limits[IPA_RSRC_GROUP_SRC_UC_RX_Q] = {
.min = 2, .max = 255,
},
},
[IPA_RESOURCE_TYPE_SRC_HDR_SECTORS] = {
.limits[IPA_RSRC_GROUP_SRC_UL] = {
.min = 0, .max = 255,
},
.limits[IPA_RSRC_GROUP_SRC_DL] = {
.min = 0, .max = 255,
},
.limits[IPA_RSRC_GROUP_SRC_DIAG] = {
.min = 0, .max = 255,
},
.limits[IPA_RSRC_GROUP_SRC_DMA] = {
.min = 0, .max = 255,
},
.limits[IPA_RSRC_GROUP_SRC_UC_RX_Q] = {
.min = 0, .max = 255,
},
},
[IPA_RESOURCE_TYPE_SRC_HDRI1_BUFFER] = {
.limits[IPA_RSRC_GROUP_SRC_UL] = {
.min = 0, .max = 255,
},
.limits[IPA_RSRC_GROUP_SRC_DL] = {
.min = 0, .max = 255,
},
.limits[IPA_RSRC_GROUP_SRC_DIAG] = {
.min = 0, .max = 255,
},
.limits[IPA_RSRC_GROUP_SRC_DMA] = {
.min = 0, .max = 255,
},
.limits[IPA_RSRC_GROUP_SRC_UC_RX_Q] = {
.min = 0, .max = 255,
},
},
[IPA_RESOURCE_TYPE_SRC_DESCRIPTOR_LISTS] = {
.limits[IPA_RSRC_GROUP_SRC_UL] = {
.min = 14, .max = 14,
},
.limits[IPA_RSRC_GROUP_SRC_DL] = {
.min = 16, .max = 16,
},
.limits[IPA_RSRC_GROUP_SRC_DIAG] = {
.min = 5, .max = 5,
},
.limits[IPA_RSRC_GROUP_SRC_DMA] = {
.min = 5, .max = 5,
},
.limits[IPA_RSRC_GROUP_SRC_UC_RX_Q] = {
.min = 8, .max = 8,
},
},
[IPA_RESOURCE_TYPE_SRC_DESCRIPTOR_BUFF] = {
.limits[IPA_RSRC_GROUP_SRC_UL] = {
.min = 19, .max = 19,
},
.limits[IPA_RSRC_GROUP_SRC_DL] = {
.min = 26, .max = 26,
},
.limits[IPA_RSRC_GROUP_SRC_DIAG] = {
.min = 5, .max = 5, /* 3 downstream */
},
.limits[IPA_RSRC_GROUP_SRC_DMA] = {
.min = 5, .max = 5, /* 7 downstream */
},
.limits[IPA_RSRC_GROUP_SRC_UC_RX_Q] = {
.min = 8, .max = 8,
},
},
[IPA_RESOURCE_TYPE_SRC_HDRI2_BUFFERS] = {
.limits[IPA_RSRC_GROUP_SRC_UL] = {
.min = 0, .max = 255,
},
.limits[IPA_RSRC_GROUP_SRC_DL] = {
.min = 0, .max = 255,
},
.limits[IPA_RSRC_GROUP_SRC_DIAG] = {
.min = 0, .max = 255,
},
.limits[IPA_RSRC_GROUP_SRC_DMA] = {
.min = 0, .max = 255,
},
.limits[IPA_RSRC_GROUP_SRC_UC_RX_Q] = {
.min = 0, .max = 255,
},
},
[IPA_RESOURCE_TYPE_SRC_HPS_DMARS] = {
.limits[IPA_RSRC_GROUP_SRC_UL] = {
.min = 0, .max = 255,
},
.limits[IPA_RSRC_GROUP_SRC_DL] = {
.min = 0, .max = 255,
},
.limits[IPA_RSRC_GROUP_SRC_DIAG] = {
.min = 0, .max = 255,
},
.limits[IPA_RSRC_GROUP_SRC_DMA] = {
.min = 0, .max = 255,
},
.limits[IPA_RSRC_GROUP_SRC_UC_RX_Q] = {
.min = 0, .max = 255,
},
},
[IPA_RESOURCE_TYPE_SRC_ACK_ENTRIES] = {
.limits[IPA_RSRC_GROUP_SRC_UL] = {
.min = 19, .max = 19,
},
.limits[IPA_RSRC_GROUP_SRC_DL] = {
.min = 26, .max = 26,
},
.limits[IPA_RSRC_GROUP_SRC_DIAG] = {
.min = 5, .max = 5,
},
.limits[IPA_RSRC_GROUP_SRC_DMA] = {
.min = 5, .max = 5,
},
.limits[IPA_RSRC_GROUP_SRC_UC_RX_Q] = {
.min = 8, .max = 8,
},
},
};
/* Destination resource configuration data for an SoC having IPA v3.1 */
static const struct ipa_resource ipa_resource_dst[] = {
[IPA_RESOURCE_TYPE_DST_DATA_SECTORS] = {
.limits[IPA_RSRC_GROUP_DST_UL] = {
.min = 3, .max = 3, /* 2 downstream */
},
.limits[IPA_RSRC_GROUP_DST_DL] = {
.min = 3, .max = 3,
},
.limits[IPA_RSRC_GROUP_DST_DIAG_DPL] = {
.min = 1, .max = 1, /* 0 downstream */
},
/* IPA_RSRC_GROUP_DST_DMA uses 2 downstream */
.limits[IPA_RSRC_GROUP_DST_Q6ZIP_GENERAL] = {
.min = 3, .max = 3,
},
.limits[IPA_RSRC_GROUP_DST_Q6ZIP_ENGINE] = {
.min = 3, .max = 3,
},
},
[IPA_RESOURCE_TYPE_DST_DATA_SECTOR_LISTS] = {
.limits[IPA_RSRC_GROUP_DST_UL] = {
.min = 0, .max = 255,
},
.limits[IPA_RSRC_GROUP_DST_DL] = {
.min = 0, .max = 255,
},
.limits[IPA_RSRC_GROUP_DST_DIAG_DPL] = {
.min = 0, .max = 255,
},
.limits[IPA_RSRC_GROUP_DST_DMA] = {
.min = 0, .max = 255,
},
.limits[IPA_RSRC_GROUP_DST_Q6ZIP_GENERAL] = {
.min = 0, .max = 255,
},
.limits[IPA_RSRC_GROUP_DST_Q6ZIP_ENGINE] = {
.min = 0, .max = 255,
},
},
[IPA_RESOURCE_TYPE_DST_DPS_DMARS] = {
.limits[IPA_RSRC_GROUP_DST_UL] = {
.min = 1, .max = 1,
},
.limits[IPA_RSRC_GROUP_DST_DL] = {
.min = 1, .max = 1,
},
.limits[IPA_RSRC_GROUP_DST_DIAG_DPL] = {
.min = 1, .max = 1,
},
.limits[IPA_RSRC_GROUP_DST_DMA] = {
.min = 1, .max = 1,
},
.limits[IPA_RSRC_GROUP_DST_Q6ZIP_GENERAL] = {
.min = 1, .max = 1,
},
},
};
/* Resource configuration data for an SoC having IPA v3.1 */
static const struct ipa_resource_data ipa_resource_data = {
.rsrc_group_src_count = IPA_RSRC_GROUP_SRC_COUNT,
.rsrc_group_dst_count = IPA_RSRC_GROUP_DST_COUNT,
.resource_src_count = ARRAY_SIZE(ipa_resource_src),
.resource_src = ipa_resource_src,
.resource_dst_count = ARRAY_SIZE(ipa_resource_dst),
.resource_dst = ipa_resource_dst,
};
/* IPA-resident memory region data for an SoC having IPA v3.1 */
static const struct ipa_mem ipa_mem_local_data[] = {
{
.id = IPA_MEM_UC_SHARED,
.offset = 0x0000,
.size = 0x0080,
.canary_count = 0,
},
{
.id = IPA_MEM_UC_INFO,
.offset = 0x0080,
.size = 0x0200,
.canary_count = 0,
},
{
.id = IPA_MEM_V4_FILTER_HASHED,
.offset = 0x0288,
.size = 0x0078,
.canary_count = 2,
},
{
.id = IPA_MEM_V4_FILTER,
.offset = 0x0308,
.size = 0x0078,
.canary_count = 2,
},
{
.id = IPA_MEM_V6_FILTER_HASHED,
.offset = 0x0388,
.size = 0x0078,
.canary_count = 2,
},
{
.id = IPA_MEM_V6_FILTER,
.offset = 0x0408,
.size = 0x0078,
.canary_count = 2,
},
{
.id = IPA_MEM_V4_ROUTE_HASHED,
.offset = 0x0488,
.size = 0x0078,
.canary_count = 2,
},
{
.id = IPA_MEM_V4_ROUTE,
.offset = 0x0508,
.size = 0x0078,
.canary_count = 2,
},
{
.id = IPA_MEM_V6_ROUTE_HASHED,
.offset = 0x0588,
.size = 0x0078,
.canary_count = 2,
},
{
.id = IPA_MEM_V6_ROUTE,
.offset = 0x0608,
.size = 0x0078,
.canary_count = 2,
},
{
.id = IPA_MEM_MODEM_HEADER,
.offset = 0x0688,
.size = 0x0140,
.canary_count = 2,
},
{
.id = IPA_MEM_MODEM_PROC_CTX,
.offset = 0x07d0,
.size = 0x0200,
.canary_count = 2,
},
{
.id = IPA_MEM_AP_PROC_CTX,
.offset = 0x09d0,
.size = 0x0200,
.canary_count = 0,
},
{
.id = IPA_MEM_MODEM,
.offset = 0x0bd8,
.size = 0x1424,
.canary_count = 0,
},
{
.id = IPA_MEM_END_MARKER,
.offset = 0x2000,
.size = 0,
.canary_count = 1,
},
};
/* Memory configuration data for an SoC having IPA v3.1 */
static const struct ipa_mem_data ipa_mem_data = {
.local_count = ARRAY_SIZE(ipa_mem_local_data),
.local = ipa_mem_local_data,
.imem_addr = 0x146bd000,
.imem_size = 0x00002000,
.smem_id = 497,
.smem_size = 0x00002000,
};
/* Interconnect bandwidths are in 1000 byte/second units */
static const struct ipa_interconnect_data ipa_interconnect_data[] = {
{
.name = "memory",
.peak_bandwidth = 640000, /* 640 MBps */
.average_bandwidth = 80000, /* 80 MBps */
},
{
.name = "imem",
.peak_bandwidth = 640000, /* 640 MBps */
.average_bandwidth = 80000, /* 80 MBps */
},
/* Average bandwidth is unused for the next interconnect */
{
.name = "config",
.peak_bandwidth = 80000, /* 80 MBps */
.average_bandwidth = 0, /* unused */
},
};
/* Clock and interconnect configuration data for an SoC having IPA v3.1 */
static const struct ipa_clock_data ipa_clock_data = {
.core_clock_rate = 16 * 1000 * 1000, /* Hz */
.interconnect_count = ARRAY_SIZE(ipa_interconnect_data),
.interconnect_data = ipa_interconnect_data,
};
/* Configuration data for an SoC having IPA v3.1 */
const struct ipa_data ipa_data_v3_1 = {
.version = IPA_VERSION_3_1,
.backward_compat = BCR_CMDQ_L_LACK_ONE_ENTRY_FMASK,
.qsb_count = ARRAY_SIZE(ipa_qsb_data),
.qsb_data = ipa_qsb_data,
.endpoint_count = ARRAY_SIZE(ipa_gsi_endpoint_data),
.endpoint_data = ipa_gsi_endpoint_data,
.resource_data = &ipa_resource_data,
.mem_data = &ipa_mem_data,
.clock_data = &ipa_clock_data,
};

View File

@ -300,6 +300,7 @@ struct ipa_data {
const struct ipa_clock_data *clock_data;
};
extern const struct ipa_data ipa_data_v3_1;
extern const struct ipa_data ipa_data_v3_5_1;
extern const struct ipa_data ipa_data_v4_2;
extern const struct ipa_data ipa_data_v4_5;

View File

@ -1731,6 +1731,21 @@ int ipa_endpoint_config(struct ipa *ipa)
u32 max;
u32 val;
/* Prior to IPAv3.5, the FLAVOR_0 register was not supported.
* Furthermore, the endpoints were not grouped such that TX
* endpoint numbers started with 0 and RX endpoints had numbers
* higher than all TX endpoints, so we can't do the simple
* direction check used for newer hardware below.
*
* For hardware that doesn't support the FLAVOR_0 register,
* just set the available mask to support any endpoint, and
* assume the configuration is valid.
*/
if (ipa->version < IPA_VERSION_3_5) {
ipa->available = ~0;
return 0;
}
/* Find out about the endpoints supplied by the hardware, and ensure
* the highest one doesn't exceed the number we support.
*/

View File

@ -400,16 +400,20 @@ static void ipa_hardware_config(struct ipa *ipa, const struct ipa_data *data)
/* Implement some hardware workarounds */
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;
iowrite32(val, ipa->reg_virt + IPA_REG_CLKON_CFG_OFFSET);
/* 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);
/* Enable open global clocks in the CLKON configuration */
val = GLOBAL_FMASK | GLOBAL_2X_CLK_FMASK;
} else if (version == IPA_VERSION_3_1) {
val = MISC_FMASK; /* Disable MISC clock gating */
} else {
val = 0; /* No CLKON configuration needed */
}
if (val)
iowrite32(val, ipa->reg_virt + IPA_REG_CLKON_CFG_OFFSET);
ipa_hardware_config_comp(ipa);
@ -574,6 +578,10 @@ out_release_firmware:
}
static const struct of_device_id ipa_match[] = {
{
.compatible = "qcom,msm8998-ipa",
.data = &ipa_data_v3_1,
},
{
.compatible = "qcom,sdm845-ipa",
.data = &ipa_data_v3_5_1,