Skip to content

Commit e71d2b9

Browse files
committed
Merge branch 'net-ipa-start-adding-ipa-v4-5-support'
Alex Elder says: ==================== net: ipa: start adding IPA v4.5 support This series starts updating the IPA code to support IPA hardware version 4.5. The first patch fixes a problem found while preparing these updates. Testing shows the code works with or without the change, and with the fix the code matches "downstream" Qualcomm code. The second patch updates the definitions for IPA register offsets and field masks to reflect the changes that come with IPA v4.5. A few register updates have been deferred until later, because making use of them involves some nontrivial code updates. One type of change that IPA v4.5 brings is expanding the range of certain configuration values. High-order bits are added in a few cases, and the third patch implements the code changes necessary to use those newly available bits. The fourth patch implements several fairly minor changes to the code required for IPA v4.5 support. The last two patches implement changes to the GSI registers used for IPA. Almost none of the registers change, but the range of memory in which most of the GSI registers is located is shifted by a fixed amount. The fifth patch updates the GSI register definitions, and the last patch implements the memory shift for IPA v4.5. ==================== Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
2 parents 3567e23 + cdeee49 commit e71d2b9

File tree

6 files changed

+220
-46
lines changed

6 files changed

+220
-46
lines changed

drivers/net/ipa/gsi.c

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,8 @@ static void gsi_irq_type_disable(struct gsi *gsi, enum gsi_irq_type_id type_id)
195195
/* Turn off all GSI interrupts initially */
196196
static void gsi_irq_setup(struct gsi *gsi)
197197
{
198+
u32 adjust;
199+
198200
/* Disable all interrupt types */
199201
gsi_irq_type_update(gsi, 0);
200202

@@ -203,8 +205,12 @@ static void gsi_irq_setup(struct gsi *gsi)
203205
iowrite32(0, gsi->virt + GSI_CNTXT_SRC_EV_CH_IRQ_MSK_OFFSET);
204206
iowrite32(0, gsi->virt + GSI_CNTXT_GLOB_IRQ_EN_OFFSET);
205207
iowrite32(0, gsi->virt + GSI_CNTXT_SRC_IEOB_IRQ_MSK_OFFSET);
206-
iowrite32(0, gsi->virt + GSI_INTER_EE_SRC_CH_IRQ_OFFSET);
207-
iowrite32(0, gsi->virt + GSI_INTER_EE_SRC_EV_CH_IRQ_OFFSET);
208+
209+
/* Reverse the offset adjustment for inter-EE register offsets */
210+
adjust = gsi->version < IPA_VERSION_4_5 ? 0 : GSI_EE_REG_ADJUST;
211+
iowrite32(0, gsi->virt + adjust + GSI_INTER_EE_SRC_CH_IRQ_OFFSET);
212+
iowrite32(0, gsi->virt + adjust + GSI_INTER_EE_SRC_EV_CH_IRQ_OFFSET);
213+
208214
iowrite32(0, gsi->virt + GSI_CNTXT_GSI_IRQ_EN_OFFSET);
209215
}
210216

@@ -781,9 +787,17 @@ static void gsi_channel_program(struct gsi_channel *channel, bool doorbell)
781787
if (gsi->version == IPA_VERSION_3_5_1 && doorbell)
782788
val |= USE_DB_ENG_FMASK;
783789

784-
/* Starting with IPA v4.0 the command channel uses the escape buffer */
785-
if (gsi->version != IPA_VERSION_3_5_1 && channel->command)
786-
val |= USE_ESCAPE_BUF_ONLY_FMASK;
790+
/* v4.0 introduces an escape buffer for prefetch. We use it
791+
* on all but the AP command channel.
792+
*/
793+
if (gsi->version != IPA_VERSION_3_5_1 && !channel->command) {
794+
/* If not otherwise set, prefetch buffers are used */
795+
if (gsi->version < IPA_VERSION_4_5)
796+
val |= USE_ESCAPE_BUF_ONLY_FMASK;
797+
else
798+
val |= u32_encode_bits(GSI_ESCAPE_BUF_ONLY,
799+
PREFETCH_MODE_FMASK);
800+
}
787801

788802
iowrite32(val, gsi->virt + GSI_CH_C_QOS_OFFSET(channel_id));
789803

@@ -2081,6 +2095,7 @@ int gsi_init(struct gsi *gsi, struct platform_device *pdev,
20812095
struct device *dev = &pdev->dev;
20822096
struct resource *res;
20832097
resource_size_t size;
2098+
u32 adjust;
20842099
int ret;
20852100

20862101
gsi_validate_build();
@@ -2107,11 +2122,21 @@ int gsi_init(struct gsi *gsi, struct platform_device *pdev,
21072122
return -EINVAL;
21082123
}
21092124

2125+
/* Make sure we can make our pointer adjustment if necessary */
2126+
adjust = gsi->version < IPA_VERSION_4_5 ? 0 : GSI_EE_REG_ADJUST;
2127+
if (res->start < adjust) {
2128+
dev_err(dev, "DT memory resource \"gsi\" too low (< %u)\n",
2129+
adjust);
2130+
return -EINVAL;
2131+
}
2132+
21102133
gsi->virt = ioremap(res->start, size);
21112134
if (!gsi->virt) {
21122135
dev_err(dev, "unable to remap \"gsi\" memory\n");
21132136
return -ENOMEM;
21142137
}
2138+
/* Adjust register range pointer downward for newer IPA versions */
2139+
gsi->virt -= adjust;
21152140

21162141
init_completion(&gsi->completion);
21172142

drivers/net/ipa/gsi_reg.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,17 @@
3838
* (though the actual limit is hardware-dependent).
3939
*/
4040

41+
/* GSI EE registers as a group are shifted downward by a fixed
42+
* constant amount for IPA versions 4.5 and beyond. This applies
43+
* to all GSI registers we use *except* the ones that disable
44+
* inter-EE interrupts for channels and event channels.
45+
*
46+
* We handle this by adjusting the pointer to the mapped GSI memory
47+
* region downward. Then in the one place we use them (gsi_irq_setup())
48+
* we undo that adjustment for the inter-EE interrupt registers.
49+
*/
50+
#define GSI_EE_REG_ADJUST 0x0000d000 /* IPA v4.5+ */
51+
4152
#define GSI_INTER_EE_SRC_CH_IRQ_OFFSET \
4253
GSI_INTER_EE_N_SRC_CH_IRQ_OFFSET(GSI_EE_AP)
4354
#define GSI_INTER_EE_N_SRC_CH_IRQ_OFFSET(ee) \
@@ -105,6 +116,16 @@ enum gsi_channel_type {
105116
#define USE_DB_ENG_FMASK GENMASK(9, 9)
106117
/* The next field is only present for IPA v4.0, v4.1, and v4.2 */
107118
#define USE_ESCAPE_BUF_ONLY_FMASK GENMASK(10, 10)
119+
/* The next two fields are present for IPA v4.5 and above */
120+
#define PREFETCH_MODE_FMASK GENMASK(13, 10)
121+
#define EMPTY_LVL_THRSHOLD_FMASK GENMASK(23, 16)
122+
/** enum gsi_prefetch_mode - PREFETCH_MODE field in CH_C_QOS */
123+
enum gsi_prefetch_mode {
124+
GSI_USE_PREFETCH_BUFS = 0x0,
125+
GSI_ESCAPE_BUF_ONLY = 0x1,
126+
GSI_SMART_PREFETCH = 0x2,
127+
GSI_FREE_PREFETCH = 0x3,
128+
};
108129

109130
#define GSI_CH_C_SCRATCH_0_OFFSET(ch) \
110131
GSI_EE_N_CH_C_SCRATCH_0_OFFSET((ch), GSI_EE_AP)
@@ -287,6 +308,9 @@ enum gsi_iram_size {
287308
/* The next two values are available for IPA v4.0 and above */
288309
IRAM_SIZE_TWO_N_HALF_KB = 0x2,
289310
IRAM_SIZE_THREE_KB = 0x3,
311+
/* The next two values are available for IPA v4.5 and above */
312+
IRAM_SIZE_THREE_N_HALF_KB = 0x4,
313+
IRAM_SIZE_FOUR_KB = 0x5,
290314
};
291315

292316
/* IRQ condition for each type is cleared by writing type-specific register */

drivers/net/ipa/ipa_endpoint.c

Lines changed: 36 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -485,45 +485,52 @@ static void ipa_endpoint_init_cfg(struct ipa_endpoint *endpoint)
485485
static void ipa_endpoint_init_hdr(struct ipa_endpoint *endpoint)
486486
{
487487
u32 offset = IPA_REG_ENDP_INIT_HDR_N_OFFSET(endpoint->endpoint_id);
488+
struct ipa *ipa = endpoint->ipa;
488489
u32 val = 0;
489490

490491
if (endpoint->data->qmap) {
491492
size_t header_size = sizeof(struct rmnet_map_header);
493+
enum ipa_version version = ipa->version;
492494

493495
/* We might supply a checksum header after the QMAP header */
494496
if (endpoint->toward_ipa && endpoint->data->checksum)
495497
header_size += sizeof(struct rmnet_map_ul_csum_header);
496-
val |= u32_encode_bits(header_size, HDR_LEN_FMASK);
498+
val |= ipa_header_size_encoded(version, header_size);
497499

498500
/* Define how to fill fields in a received QMAP header */
499501
if (!endpoint->toward_ipa) {
500-
u32 off; /* Field offset within header */
502+
u32 offset; /* Field offset within header */
501503

502504
/* Where IPA will write the metadata value */
503-
off = offsetof(struct rmnet_map_header, mux_id);
504-
val |= u32_encode_bits(off, HDR_OFST_METADATA_FMASK);
505+
offset = offsetof(struct rmnet_map_header, mux_id);
506+
val |= ipa_metadata_offset_encoded(version, offset);
505507

506508
/* Where IPA will write the length */
507-
off = offsetof(struct rmnet_map_header, pkt_len);
509+
offset = offsetof(struct rmnet_map_header, pkt_len);
510+
/* Upper bits are stored in HDR_EXT with IPA v4.5 */
511+
if (version == IPA_VERSION_4_5)
512+
offset &= field_mask(HDR_OFST_PKT_SIZE_FMASK);
513+
508514
val |= HDR_OFST_PKT_SIZE_VALID_FMASK;
509-
val |= u32_encode_bits(off, HDR_OFST_PKT_SIZE_FMASK);
515+
val |= u32_encode_bits(offset, HDR_OFST_PKT_SIZE_FMASK);
510516
}
511517
/* For QMAP TX, metadata offset is 0 (modem assumes this) */
512518
val |= HDR_OFST_METADATA_VALID_FMASK;
513519

514520
/* HDR_ADDITIONAL_CONST_LEN is 0; (RX only) */
515521
/* HDR_A5_MUX is 0 */
516522
/* HDR_LEN_INC_DEAGG_HDR is 0 */
517-
/* HDR_METADATA_REG_VALID is 0 (TX only) */
523+
/* HDR_METADATA_REG_VALID is 0 (TX only, version < v4.5) */
518524
}
519525

520-
iowrite32(val, endpoint->ipa->reg_virt + offset);
526+
iowrite32(val, ipa->reg_virt + offset);
521527
}
522528

523529
static void ipa_endpoint_init_hdr_ext(struct ipa_endpoint *endpoint)
524530
{
525531
u32 offset = IPA_REG_ENDP_INIT_HDR_EXT_N_OFFSET(endpoint->endpoint_id);
526532
u32 pad_align = endpoint->data->rx.pad_align;
533+
struct ipa *ipa = endpoint->ipa;
527534
u32 val = 0;
528535

529536
val |= HDR_ENDIANNESS_FMASK; /* big endian */
@@ -545,10 +552,24 @@ static void ipa_endpoint_init_hdr_ext(struct ipa_endpoint *endpoint)
545552
if (!endpoint->toward_ipa)
546553
val |= u32_encode_bits(pad_align, HDR_PAD_TO_ALIGNMENT_FMASK);
547554

548-
iowrite32(val, endpoint->ipa->reg_virt + offset);
555+
/* IPA v4.5 adds some most-significant bits to a few fields,
556+
* two of which are defined in the HDR (not HDR_EXT) register.
557+
*/
558+
if (ipa->version == IPA_VERSION_4_5) {
559+
/* HDR_TOTAL_LEN_OR_PAD_OFFSET is 0, so MSB is 0 */
560+
if (endpoint->data->qmap && !endpoint->toward_ipa) {
561+
u32 offset;
562+
563+
offset = offsetof(struct rmnet_map_header, pkt_len);
564+
offset >>= hweight32(HDR_OFST_PKT_SIZE_FMASK);
565+
val |= u32_encode_bits(offset,
566+
HDR_OFST_PKT_SIZE_MSB_FMASK);
567+
/* HDR_ADDITIONAL_CONST_LEN is 0 so MSB is 0 */
568+
}
569+
}
570+
iowrite32(val, ipa->reg_virt + offset);
549571
}
550572

551-
552573
static void ipa_endpoint_init_hdr_metadata_mask(struct ipa_endpoint *endpoint)
553574
{
554575
u32 endpoint_id = endpoint->endpoint_id;
@@ -634,6 +655,7 @@ static void ipa_endpoint_init_aggr(struct ipa_endpoint *endpoint)
634655
/* other fields ignored */
635656
}
636657
/* AGGR_FORCE_CLOSE is 0 */
658+
/* AGGR_GRAN_SEL is 0 for IPA v4.5 */
637659
} else {
638660
val |= u32_encode_bits(IPA_BYPASS_AGGR, AGGR_EN_FMASK);
639661
/* other fields ignored */
@@ -844,9 +866,10 @@ static void ipa_endpoint_status(struct ipa_endpoint *endpoint)
844866
val |= u32_encode_bits(status_endpoint_id,
845867
STATUS_ENDP_FMASK);
846868
}
847-
/* STATUS_LOCATION is 0 (status element precedes packet) */
848-
/* The next field is present for IPA v4.0 and above */
849-
/* STATUS_PKT_SUPPRESS_FMASK is 0 */
869+
/* STATUS_LOCATION is 0, meaning status element precedes
870+
* packet (not present for IPA v4.5)
871+
*/
872+
/* STATUS_PKT_SUPPRESS_FMASK is 0 (not present for v3.5.1) */
850873
}
851874

852875
iowrite32(val, ipa->reg_virt + offset);

drivers/net/ipa/ipa_main.c

Lines changed: 52 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -230,8 +230,10 @@ static void ipa_hardware_config_comp(struct ipa *ipa)
230230
val &= ~IPA_QMB_SELECT_CONS_EN_FMASK;
231231
val &= ~IPA_QMB_SELECT_PROD_EN_FMASK;
232232
val &= ~IPA_QMB_SELECT_GLOBAL_EN_FMASK;
233-
} else {
233+
} else if (ipa->version < IPA_VERSION_4_5) {
234234
val |= GSI_MULTI_AXI_MASTERS_DIS_FMASK;
235+
} else {
236+
/* For IPA v4.5 IPA_FULL_FLUSH_WAIT_RSC_CLOSE_EN is 0 */
235237
}
236238

237239
val |= GSI_MULTI_INORDER_RD_DIS_FMASK;
@@ -243,25 +245,47 @@ static void ipa_hardware_config_comp(struct ipa *ipa)
243245
/* Configure DDR and PCIe max read/write QSB values */
244246
static void ipa_hardware_config_qsb(struct ipa *ipa)
245247
{
248+
enum ipa_version version = ipa->version;
249+
u32 max0;
250+
u32 max1;
246251
u32 val;
247252

248-
/* QMB_0 represents DDR; QMB_1 represents PCIe (not present in 4.2) */
253+
/* QMB_0 represents DDR; QMB_1 represents PCIe */
249254
val = u32_encode_bits(8, GEN_QMB_0_MAX_WRITES_FMASK);
250-
if (ipa->version == IPA_VERSION_4_2)
251-
val |= u32_encode_bits(0, GEN_QMB_1_MAX_WRITES_FMASK);
252-
else
253-
val |= u32_encode_bits(4, GEN_QMB_1_MAX_WRITES_FMASK);
255+
switch (version) {
256+
case IPA_VERSION_4_2:
257+
max1 = 0; /* PCIe not present */
258+
break;
259+
case IPA_VERSION_4_5:
260+
max1 = 8;
261+
break;
262+
default:
263+
max1 = 4;
264+
break;
265+
}
266+
val |= u32_encode_bits(max1, GEN_QMB_1_MAX_WRITES_FMASK);
254267
iowrite32(val, ipa->reg_virt + IPA_REG_QSB_MAX_WRITES_OFFSET);
255268

256-
if (ipa->version == IPA_VERSION_3_5_1) {
257-
val = u32_encode_bits(8, GEN_QMB_0_MAX_READS_FMASK);
258-
val |= u32_encode_bits(12, GEN_QMB_1_MAX_READS_FMASK);
259-
} else {
260-
val = u32_encode_bits(12, GEN_QMB_0_MAX_READS_FMASK);
261-
if (ipa->version == IPA_VERSION_4_2)
262-
val |= u32_encode_bits(0, GEN_QMB_1_MAX_READS_FMASK);
263-
else
264-
val |= u32_encode_bits(12, GEN_QMB_1_MAX_READS_FMASK);
269+
max1 = 12;
270+
switch (version) {
271+
case IPA_VERSION_3_5_1:
272+
max0 = 8;
273+
break;
274+
case IPA_VERSION_4_0:
275+
case IPA_VERSION_4_1:
276+
max0 = 12;
277+
break;
278+
case IPA_VERSION_4_2:
279+
max0 = 12;
280+
max1 = 0; /* PCIe not present */
281+
break;
282+
case IPA_VERSION_4_5:
283+
max0 = 16;
284+
break;
285+
}
286+
val = u32_encode_bits(max0, GEN_QMB_0_MAX_READS_FMASK);
287+
val |= u32_encode_bits(max1, GEN_QMB_1_MAX_READS_FMASK);
288+
if (version != IPA_VERSION_3_5_1) {
265289
/* GEN_QMB_0_MAX_READS_BEATS is 0 */
266290
/* GEN_QMB_1_MAX_READS_BEATS is 0 */
267291
}
@@ -294,7 +318,7 @@ static void ipa_idle_indication_cfg(struct ipa *ipa,
294318
*/
295319
static void ipa_hardware_dcd_config(struct ipa *ipa)
296320
{
297-
/* Recommended values for IPA 3.5 according to IPA HPG */
321+
/* Recommended values for IPA 3.5 and later according to IPA HPG */
298322
ipa_idle_indication_cfg(ipa, 256, false);
299323
}
300324

@@ -310,20 +334,24 @@ static void ipa_hardware_dcd_deconfig(struct ipa *ipa)
310334
*/
311335
static void ipa_hardware_config(struct ipa *ipa)
312336
{
337+
enum ipa_version version = ipa->version;
313338
u32 granularity;
314339
u32 val;
315340

316-
/* Fill in backward-compatibility register, based on version */
317-
val = ipa_reg_bcr_val(ipa->version);
318-
iowrite32(val, ipa->reg_virt + IPA_REG_BCR_OFFSET);
341+
/* IPA v4.5 has no backward compatibility register */
342+
if (version < IPA_VERSION_4_5) {
343+
val = ipa_reg_bcr_val(version);
344+
iowrite32(val, ipa->reg_virt + IPA_REG_BCR_OFFSET);
345+
}
319346

320-
if (ipa->version != IPA_VERSION_3_5_1) {
321-
/* Enable open global clocks (hardware workaround) */
347+
/* Implement some hardware workarounds */
348+
if (version != IPA_VERSION_3_5_1 && version < IPA_VERSION_4_5) {
349+
/* Enable open global clocks (not needed for IPA v4.5) */
322350
val = GLOBAL_FMASK;
323351
val |= GLOBAL_2X_CLK_FMASK;
324352
iowrite32(val, ipa->reg_virt + IPA_REG_CLKON_CFG_OFFSET);
325353

326-
/* Disable PA mask to allow HOLB drop (hardware workaround) */
354+
/* Disable PA mask to allow HOLB drop */
327355
val = ioread32(ipa->reg_virt + IPA_REG_TX_CFG_OFFSET);
328356
val &= ~PA_MASK_EN_FMASK;
329357
iowrite32(val, ipa->reg_virt + IPA_REG_TX_CFG_OFFSET);
@@ -340,8 +368,8 @@ static void ipa_hardware_config(struct ipa *ipa)
340368
iowrite32(val, ipa->reg_virt + IPA_REG_COUNTER_CFG_OFFSET);
341369

342370
/* IPA v4.2 does not support hashed tables, so disable them */
343-
if (ipa->version == IPA_VERSION_4_2) {
344-
u32 offset = ipa_reg_filt_rout_hash_en_offset(ipa->version);
371+
if (version == IPA_VERSION_4_2) {
372+
u32 offset = ipa_reg_filt_rout_hash_en_offset(version);
345373

346374
iowrite32(0, ipa->reg_virt + offset);
347375
}

0 commit comments

Comments
 (0)