Commit e1d07700 authored by Jakub Kicinski's avatar Jakub Kicinski

Merge branch 'net-ipa-generalized-register-definitions'

Alex Elder says:

====================
net: ipa: generalized register definitions

This series is quite a bit bigger than what I normally like to send,
and I apologize for that.  I would like it to get incorporated in
its entirety this week if possible, and splitting up the series
carries a small risk that wouldn't happen.

Each IPA register has a defined offset, and in most cases, a set
of masks that define the width and position of fields within the
register.  Most registers currently use the same offset for all
versions of IPA.  Usually fields within registers are also the same
across many versions.  Offsets and fields like this are defined
using preprocessor constants.

When a register has a different offset for different versions of
IPA, an inline function is used to determine its offset.  And in
places where a field differs between versions, an inline function is
used to determine how a value is encoded within the field, depending
on IPA version.

Starting with IPA version 5.0, the number of IPA endpoints supported
is greater than 32.  As a consequence, *many* IPA register offsets
differ considerably from prior versions.  This increase in endpoints
also requires a lot of field sizes and/or positions to change (such
as those that contain an endpoint ID).

Defining these things with constants is no longer simple, and rather
than fill the code with one-off functions to define offsets and
encode field values, this series puts in place a new way of defining
IPA registers and their fields.  Note that this series creates this
new scheme, but does not add IPA v5.0+ support.

An enumerated type will now define a unique ID for each IPA register.
Each defined register will have a structure that contains its offset
and its name (a printable string).  Each version of IPA will have an
array of these register structures, indexed by register ID.

Some "parameterized" registers are duplicated (this is not new).
For example, each endpoint has an INIT_HDR register, and the offset
of a given endpoint's INIT_HDR register is dependent on the endpoint
number (the parameter).  In such cases, the register's "stride" is
defined as the distance between two of these registers.

If a register contains fields, each field will have a unique ID
that's used as an index into an array of field masks defined for the
register.  The register structure also defines the number of entries
in this field array.

When a register is to be used in code, its register structure will
be fetched using function ipa_reg().  Other functions are then used
to determine the register's offset, or to encode a value into one of
the register's fields, and so on.

Each version of IPA defines the set of registers that are available,
including all fields for these registers.  The array of defined
registers is set up at probe time based on the IPA version, and it
is associated with the main IPA structure.
====================

Link: https://lore.kernel.org/r/20220926220931.3261749-1-elder@linaro.orgSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 8f1e1658 181ca020
...@@ -13,4 +13,6 @@ ipa-y := ipa_main.o ipa_power.o ipa_reg.o ipa_mem.o \ ...@@ -13,4 +13,6 @@ ipa-y := ipa_main.o ipa_power.o ipa_reg.o ipa_mem.o \
ipa_resource.o ipa_qmi.o ipa_qmi_msg.o \ ipa_resource.o ipa_qmi.o ipa_qmi_msg.o \
ipa_sysfs.o ipa_sysfs.o
ipa-y += $(IPA_VERSIONS:%=reg/ipa_reg-v%.o)
ipa-y += $(IPA_VERSIONS:%=data/ipa_data-v%.o) ipa-y += $(IPA_VERSIONS:%=data/ipa_data-v%.o)
...@@ -44,6 +44,7 @@ struct ipa_interrupt; ...@@ -44,6 +44,7 @@ struct ipa_interrupt;
* @uc_loaded: true after microcontroller has reported it's ready * @uc_loaded: true after microcontroller has reported it's ready
* @reg_addr: DMA address used for IPA register access * @reg_addr: DMA address used for IPA register access
* @reg_virt: Virtual address used for IPA register access * @reg_virt: Virtual address used for IPA register access
* @regs: IPA register definitions
* @mem_addr: DMA address of IPA-local memory space * @mem_addr: DMA address of IPA-local memory space
* @mem_virt: Virtual address of IPA-local memory space * @mem_virt: Virtual address of IPA-local memory space
* @mem_offset: Offset from @mem_virt used for access to IPA memory * @mem_offset: Offset from @mem_virt used for access to IPA memory
...@@ -90,6 +91,7 @@ struct ipa { ...@@ -90,6 +91,7 @@ struct ipa {
dma_addr_t reg_addr; dma_addr_t reg_addr;
void __iomem *reg_virt; void __iomem *reg_virt;
const struct ipa_regs *regs;
dma_addr_t mem_addr; dma_addr_t mem_addr;
void *mem_virt; void *mem_virt;
......
...@@ -305,6 +305,7 @@ static bool ipa_cmd_register_write_offset_valid(struct ipa *ipa, ...@@ -305,6 +305,7 @@ static bool ipa_cmd_register_write_offset_valid(struct ipa *ipa,
/* Check whether offsets passed to register_write are valid */ /* Check whether offsets passed to register_write are valid */
static bool ipa_cmd_register_write_valid(struct ipa *ipa) static bool ipa_cmd_register_write_valid(struct ipa *ipa)
{ {
const struct ipa_reg *reg;
const char *name; const char *name;
u32 offset; u32 offset;
...@@ -312,7 +313,8 @@ static bool ipa_cmd_register_write_valid(struct ipa *ipa) ...@@ -312,7 +313,8 @@ static bool ipa_cmd_register_write_valid(struct ipa *ipa)
* offset will fit in a register write IPA immediate command. * offset will fit in a register write IPA immediate command.
*/ */
if (ipa_table_hash_support(ipa)) { if (ipa_table_hash_support(ipa)) {
offset = ipa_reg_filt_rout_hash_flush_offset(ipa->version); reg = ipa_reg(ipa, FILT_ROUT_HASH_FLUSH);
offset = ipa_reg_offset(reg);
name = "filter/route hash flush"; name = "filter/route hash flush";
if (!ipa_cmd_register_write_offset_valid(ipa, name, offset)) if (!ipa_cmd_register_write_offset_valid(ipa, name, offset))
return false; return false;
...@@ -325,7 +327,8 @@ static bool ipa_cmd_register_write_valid(struct ipa *ipa) ...@@ -325,7 +327,8 @@ static bool ipa_cmd_register_write_valid(struct ipa *ipa)
* worst case (highest endpoint number) offset of that endpoint * worst case (highest endpoint number) offset of that endpoint
* fits in the register write command field(s) that must hold it. * fits in the register write command field(s) that must hold it.
*/ */
offset = IPA_REG_ENDP_STATUS_N_OFFSET(IPA_ENDPOINT_COUNT - 1); reg = ipa_reg(ipa, ENDP_STATUS);
offset = ipa_reg_n_offset(reg, IPA_ENDPOINT_COUNT - 1);
name = "maximal endpoint status"; name = "maximal endpoint status";
if (!ipa_cmd_register_write_offset_valid(ipa, name, offset)) if (!ipa_cmd_register_write_offset_valid(ipa, name, offset))
return false; return false;
......
This diff is collapsed.
...@@ -53,13 +53,15 @@ static void ipa_interrupt_process(struct ipa_interrupt *interrupt, u32 irq_id) ...@@ -53,13 +53,15 @@ static void ipa_interrupt_process(struct ipa_interrupt *interrupt, u32 irq_id)
{ {
bool uc_irq = ipa_interrupt_uc(interrupt, irq_id); bool uc_irq = ipa_interrupt_uc(interrupt, irq_id);
struct ipa *ipa = interrupt->ipa; struct ipa *ipa = interrupt->ipa;
const struct ipa_reg *reg;
u32 mask = BIT(irq_id); u32 mask = BIT(irq_id);
u32 offset; u32 offset;
/* For microcontroller interrupts, clear the interrupt right away, /* For microcontroller interrupts, clear the interrupt right away,
* "to avoid clearing unhandled interrupts." * "to avoid clearing unhandled interrupts."
*/ */
offset = ipa_reg_irq_clr_offset(ipa->version); reg = ipa_reg(ipa, IPA_IRQ_CLR);
offset = ipa_reg_offset(reg);
if (uc_irq) if (uc_irq)
iowrite32(mask, ipa->reg_virt + offset); iowrite32(mask, ipa->reg_virt + offset);
...@@ -80,6 +82,7 @@ static irqreturn_t ipa_isr_thread(int irq, void *dev_id) ...@@ -80,6 +82,7 @@ static irqreturn_t ipa_isr_thread(int irq, void *dev_id)
struct ipa_interrupt *interrupt = dev_id; struct ipa_interrupt *interrupt = dev_id;
struct ipa *ipa = interrupt->ipa; struct ipa *ipa = interrupt->ipa;
u32 enabled = interrupt->enabled; u32 enabled = interrupt->enabled;
const struct ipa_reg *reg;
struct device *dev; struct device *dev;
u32 pending; u32 pending;
u32 offset; u32 offset;
...@@ -95,7 +98,8 @@ static irqreturn_t ipa_isr_thread(int irq, void *dev_id) ...@@ -95,7 +98,8 @@ static irqreturn_t ipa_isr_thread(int irq, void *dev_id)
* including conditions whose interrupt is not enabled. Handle * including conditions whose interrupt is not enabled. Handle
* only the enabled ones. * only the enabled ones.
*/ */
offset = ipa_reg_irq_stts_offset(ipa->version); reg = ipa_reg(ipa, IPA_IRQ_STTS);
offset = ipa_reg_offset(reg);
pending = ioread32(ipa->reg_virt + offset); pending = ioread32(ipa->reg_virt + offset);
while ((mask = pending & enabled)) { while ((mask = pending & enabled)) {
do { do {
...@@ -112,7 +116,8 @@ static irqreturn_t ipa_isr_thread(int irq, void *dev_id) ...@@ -112,7 +116,8 @@ static irqreturn_t ipa_isr_thread(int irq, void *dev_id)
if (pending) { if (pending) {
dev_dbg(dev, "clearing disabled IPA interrupts 0x%08x\n", dev_dbg(dev, "clearing disabled IPA interrupts 0x%08x\n",
pending); pending);
offset = ipa_reg_irq_clr_offset(ipa->version); reg = ipa_reg(ipa, IPA_IRQ_CLR);
offset = ipa_reg_offset(reg);
iowrite32(pending, ipa->reg_virt + offset); iowrite32(pending, ipa->reg_virt + offset);
} }
out_power_put: out_power_put:
...@@ -128,6 +133,7 @@ static void ipa_interrupt_suspend_control(struct ipa_interrupt *interrupt, ...@@ -128,6 +133,7 @@ static void ipa_interrupt_suspend_control(struct ipa_interrupt *interrupt,
{ {
struct ipa *ipa = interrupt->ipa; struct ipa *ipa = interrupt->ipa;
u32 mask = BIT(endpoint_id); u32 mask = BIT(endpoint_id);
const struct ipa_reg *reg;
u32 offset; u32 offset;
u32 val; u32 val;
...@@ -137,7 +143,8 @@ static void ipa_interrupt_suspend_control(struct ipa_interrupt *interrupt, ...@@ -137,7 +143,8 @@ static void ipa_interrupt_suspend_control(struct ipa_interrupt *interrupt,
if (ipa->version == IPA_VERSION_3_0) if (ipa->version == IPA_VERSION_3_0)
return; return;
offset = ipa_reg_irq_suspend_en_offset(ipa->version); reg = ipa_reg(ipa, IRQ_SUSPEND_EN);
offset = ipa_reg_offset(reg);
val = ioread32(ipa->reg_virt + offset); val = ioread32(ipa->reg_virt + offset);
if (enable) if (enable)
val |= mask; val |= mask;
...@@ -164,18 +171,18 @@ ipa_interrupt_suspend_disable(struct ipa_interrupt *interrupt, u32 endpoint_id) ...@@ -164,18 +171,18 @@ ipa_interrupt_suspend_disable(struct ipa_interrupt *interrupt, u32 endpoint_id)
void ipa_interrupt_suspend_clear_all(struct ipa_interrupt *interrupt) void ipa_interrupt_suspend_clear_all(struct ipa_interrupt *interrupt)
{ {
struct ipa *ipa = interrupt->ipa; struct ipa *ipa = interrupt->ipa;
u32 offset; const struct ipa_reg *reg;
u32 val; u32 val;
offset = ipa_reg_irq_suspend_info_offset(ipa->version); reg = ipa_reg(ipa, IRQ_SUSPEND_INFO);
val = ioread32(ipa->reg_virt + offset); val = ioread32(ipa->reg_virt + ipa_reg_offset(reg));
/* SUSPEND interrupt status isn't cleared on IPA version 3.0 */ /* SUSPEND interrupt status isn't cleared on IPA version 3.0 */
if (ipa->version == IPA_VERSION_3_0) if (ipa->version == IPA_VERSION_3_0)
return; return;
offset = ipa_reg_irq_suspend_clr_offset(ipa->version); reg = ipa_reg(ipa, IRQ_SUSPEND_CLR);
iowrite32(val, ipa->reg_virt + offset); iowrite32(val, ipa->reg_virt + ipa_reg_offset(reg));
} }
/* Simulate arrival of an IPA TX_SUSPEND interrupt */ /* Simulate arrival of an IPA TX_SUSPEND interrupt */
...@@ -189,7 +196,7 @@ void ipa_interrupt_add(struct ipa_interrupt *interrupt, ...@@ -189,7 +196,7 @@ void ipa_interrupt_add(struct ipa_interrupt *interrupt,
enum ipa_irq_id ipa_irq, ipa_irq_handler_t handler) enum ipa_irq_id ipa_irq, ipa_irq_handler_t handler)
{ {
struct ipa *ipa = interrupt->ipa; struct ipa *ipa = interrupt->ipa;
u32 offset; const struct ipa_reg *reg;
if (WARN_ON(ipa_irq >= IPA_IRQ_COUNT)) if (WARN_ON(ipa_irq >= IPA_IRQ_COUNT))
return; return;
...@@ -198,8 +205,9 @@ void ipa_interrupt_add(struct ipa_interrupt *interrupt, ...@@ -198,8 +205,9 @@ void ipa_interrupt_add(struct ipa_interrupt *interrupt,
/* Update the IPA interrupt mask to enable it */ /* Update the IPA interrupt mask to enable it */
interrupt->enabled |= BIT(ipa_irq); interrupt->enabled |= BIT(ipa_irq);
offset = ipa_reg_irq_en_offset(ipa->version);
iowrite32(interrupt->enabled, ipa->reg_virt + offset); reg = ipa_reg(ipa, IPA_IRQ_EN);
iowrite32(interrupt->enabled, ipa->reg_virt + ipa_reg_offset(reg));
} }
/* Remove the handler for an IPA interrupt type */ /* Remove the handler for an IPA interrupt type */
...@@ -207,15 +215,16 @@ void ...@@ -207,15 +215,16 @@ void
ipa_interrupt_remove(struct ipa_interrupt *interrupt, enum ipa_irq_id ipa_irq) ipa_interrupt_remove(struct ipa_interrupt *interrupt, enum ipa_irq_id ipa_irq)
{ {
struct ipa *ipa = interrupt->ipa; struct ipa *ipa = interrupt->ipa;
u32 offset; const struct ipa_reg *reg;
if (WARN_ON(ipa_irq >= IPA_IRQ_COUNT)) if (WARN_ON(ipa_irq >= IPA_IRQ_COUNT))
return; return;
/* Update the IPA interrupt mask to disable it */ /* Update the IPA interrupt mask to disable it */
interrupt->enabled &= ~BIT(ipa_irq); interrupt->enabled &= ~BIT(ipa_irq);
offset = ipa_reg_irq_en_offset(ipa->version);
iowrite32(interrupt->enabled, ipa->reg_virt + offset); reg = ipa_reg(ipa, IPA_IRQ_EN);
iowrite32(interrupt->enabled, ipa->reg_virt + ipa_reg_offset(reg));
interrupt->handler[ipa_irq] = NULL; interrupt->handler[ipa_irq] = NULL;
} }
...@@ -225,8 +234,8 @@ struct ipa_interrupt *ipa_interrupt_config(struct ipa *ipa) ...@@ -225,8 +234,8 @@ struct ipa_interrupt *ipa_interrupt_config(struct ipa *ipa)
{ {
struct device *dev = &ipa->pdev->dev; struct device *dev = &ipa->pdev->dev;
struct ipa_interrupt *interrupt; struct ipa_interrupt *interrupt;
const struct ipa_reg *reg;
unsigned int irq; unsigned int irq;
u32 offset;
int ret; int ret;
ret = platform_get_irq_byname(ipa->pdev, "ipa"); ret = platform_get_irq_byname(ipa->pdev, "ipa");
...@@ -244,8 +253,8 @@ struct ipa_interrupt *ipa_interrupt_config(struct ipa *ipa) ...@@ -244,8 +253,8 @@ struct ipa_interrupt *ipa_interrupt_config(struct ipa *ipa)
interrupt->irq = irq; interrupt->irq = irq;
/* Start with all IPA interrupts disabled */ /* Start with all IPA interrupts disabled */
offset = ipa_reg_irq_en_offset(ipa->version); reg = ipa_reg(ipa, IPA_IRQ_EN);
iowrite32(0, ipa->reg_virt + offset); iowrite32(0, ipa->reg_virt + ipa_reg_offset(reg));
ret = request_threaded_irq(irq, NULL, ipa_isr_thread, IRQF_ONESHOT, ret = request_threaded_irq(irq, NULL, ipa_isr_thread, IRQF_ONESHOT,
"ipa", interrupt); "ipa", interrupt);
......
This diff is collapsed.
...@@ -75,6 +75,7 @@ ipa_mem_zero_region_add(struct gsi_trans *trans, enum ipa_mem_id mem_id) ...@@ -75,6 +75,7 @@ ipa_mem_zero_region_add(struct gsi_trans *trans, enum ipa_mem_id mem_id)
int ipa_mem_setup(struct ipa *ipa) int ipa_mem_setup(struct ipa *ipa)
{ {
dma_addr_t addr = ipa->zero_addr; dma_addr_t addr = ipa->zero_addr;
const struct ipa_reg *reg;
const struct ipa_mem *mem; const struct ipa_mem *mem;
struct gsi_trans *trans; struct gsi_trans *trans;
u32 offset; u32 offset;
...@@ -112,8 +113,10 @@ int ipa_mem_setup(struct ipa *ipa) ...@@ -112,8 +113,10 @@ int ipa_mem_setup(struct ipa *ipa)
/* Tell the hardware where the processing context area is located */ /* Tell the hardware where the processing context area is located */
mem = ipa_mem_find(ipa, IPA_MEM_MODEM_PROC_CTX); mem = ipa_mem_find(ipa, IPA_MEM_MODEM_PROC_CTX);
offset = ipa->mem_offset + mem->offset; offset = ipa->mem_offset + mem->offset;
val = proc_cntxt_base_addr_encoded(ipa->version, offset);
iowrite32(val, ipa->reg_virt + IPA_REG_LOCAL_PKT_PROC_CNTXT_OFFSET); reg = ipa_reg(ipa, LOCAL_PKT_PROC_CNTXT);
val = ipa_reg_encode(reg, IPA_BASE_ADDR, offset);
iowrite32(val, ipa->reg_virt + ipa_reg_offset(reg));
return 0; return 0;
} }
...@@ -306,6 +309,7 @@ static bool ipa_mem_size_valid(struct ipa *ipa) ...@@ -306,6 +309,7 @@ static bool ipa_mem_size_valid(struct ipa *ipa)
int ipa_mem_config(struct ipa *ipa) int ipa_mem_config(struct ipa *ipa)
{ {
struct device *dev = &ipa->pdev->dev; struct device *dev = &ipa->pdev->dev;
const struct ipa_reg *reg;
const struct ipa_mem *mem; const struct ipa_mem *mem;
dma_addr_t addr; dma_addr_t addr;
u32 mem_size; u32 mem_size;
...@@ -314,12 +318,14 @@ int ipa_mem_config(struct ipa *ipa) ...@@ -314,12 +318,14 @@ int ipa_mem_config(struct ipa *ipa)
u32 i; u32 i;
/* Check the advertised location and size of the shared memory area */ /* Check the advertised location and size of the shared memory area */
val = ioread32(ipa->reg_virt + IPA_REG_SHARED_MEM_SIZE_OFFSET); reg = ipa_reg(ipa, SHARED_MEM_SIZE);
val = ioread32(ipa->reg_virt + ipa_reg_offset(reg));
/* The fields in the register are in 8 byte units */ /* The fields in the register are in 8 byte units */
ipa->mem_offset = 8 * u32_get_bits(val, SHARED_MEM_BADDR_FMASK); ipa->mem_offset = 8 * ipa_reg_decode(reg, MEM_BADDR, val);
/* Make sure the end is within the region's mapped space */ /* Make sure the end is within the region's mapped space */
mem_size = 8 * u32_get_bits(val, SHARED_MEM_SIZE_FMASK); mem_size = 8 * ipa_reg_decode(reg, MEM_SIZE, val);
/* If the sizes don't match, issue a warning */ /* If the sizes don't match, issue a warning */
if (ipa->mem_offset + mem_size < ipa->mem_size) { if (ipa->mem_offset + mem_size < ipa->mem_size) {
......
...@@ -9,11 +9,105 @@ ...@@ -9,11 +9,105 @@
#include "ipa.h" #include "ipa.h"
#include "ipa_reg.h" #include "ipa_reg.h"
/* Is this register valid and defined for the current IPA version? */
static bool ipa_reg_valid(struct ipa *ipa, enum ipa_reg_id reg_id)
{
enum ipa_version version = ipa->version;
bool valid;
/* Check for bogus (out of range) register IDs */
if ((u32)reg_id >= ipa->regs->reg_count)
return false;
switch (reg_id) {
case IPA_BCR:
case COUNTER_CFG:
valid = version < IPA_VERSION_4_5;
break;
case IPA_TX_CFG:
case FLAVOR_0:
case IDLE_INDICATION_CFG:
valid = version >= IPA_VERSION_3_5;
break;
case QTIME_TIMESTAMP_CFG:
case TIMERS_XO_CLK_DIV_CFG:
case TIMERS_PULSE_GRAN_CFG:
valid = version >= IPA_VERSION_4_5;
break;
case SRC_RSRC_GRP_45_RSRC_TYPE:
case DST_RSRC_GRP_45_RSRC_TYPE:
valid = version <= IPA_VERSION_3_1 ||
version == IPA_VERSION_4_5;
break;
case SRC_RSRC_GRP_67_RSRC_TYPE:
case DST_RSRC_GRP_67_RSRC_TYPE:
valid = version <= IPA_VERSION_3_1;
break;
case ENDP_FILTER_ROUTER_HSH_CFG:
valid = version != IPA_VERSION_4_2;
break;
case IRQ_SUSPEND_EN:
case IRQ_SUSPEND_CLR:
valid = version >= IPA_VERSION_3_1;
break;
default:
valid = true; /* Others should be defined for all versions */
break;
}
/* To be valid, it must be defined */
return valid && ipa->regs->reg[reg_id];
}
const struct ipa_reg *ipa_reg(struct ipa *ipa, enum ipa_reg_id reg_id)
{
if (WARN_ON(!ipa_reg_valid(ipa, reg_id)))
return NULL;
return ipa->regs->reg[reg_id];
}
static const struct ipa_regs *ipa_regs(enum ipa_version version)
{
switch (version) {
case IPA_VERSION_3_1:
return &ipa_regs_v3_1;
case IPA_VERSION_3_5_1:
return &ipa_regs_v3_5_1;
case IPA_VERSION_4_2:
return &ipa_regs_v4_2;
case IPA_VERSION_4_5:
return &ipa_regs_v4_5;
case IPA_VERSION_4_9:
return &ipa_regs_v4_9;
case IPA_VERSION_4_11:
return &ipa_regs_v4_11;
default:
return NULL;
}
}
int ipa_reg_init(struct ipa *ipa) int ipa_reg_init(struct ipa *ipa)
{ {
struct device *dev = &ipa->pdev->dev; struct device *dev = &ipa->pdev->dev;
const struct ipa_regs *regs;
struct resource *res; struct resource *res;
regs = ipa_regs(ipa->version);
if (!regs)
return -EINVAL;
if (WARN_ON(regs->reg_count > IPA_REG_ID_COUNT))
return -EINVAL;
/* Setup IPA register memory */ /* Setup IPA register memory */
res = platform_get_resource_byname(ipa->pdev, IORESOURCE_MEM, res = platform_get_resource_byname(ipa->pdev, IORESOURCE_MEM,
"ipa-reg"); "ipa-reg");
...@@ -28,6 +122,7 @@ int ipa_reg_init(struct ipa *ipa) ...@@ -28,6 +122,7 @@ int ipa_reg_init(struct ipa *ipa)
return -ENOMEM; return -ENOMEM;
} }
ipa->reg_addr = res->start; ipa->reg_addr = res->start;
ipa->regs = regs;
return 0; return 0;
} }
......
This diff is collapsed.
...@@ -69,20 +69,21 @@ static bool ipa_resource_limits_valid(struct ipa *ipa, ...@@ -69,20 +69,21 @@ static bool ipa_resource_limits_valid(struct ipa *ipa,
} }
static void static void
ipa_resource_config_common(struct ipa *ipa, u32 offset, ipa_resource_config_common(struct ipa *ipa, u32 resource_type,
const struct ipa_reg *reg,
const struct ipa_resource_limits *xlimits, const struct ipa_resource_limits *xlimits,
const struct ipa_resource_limits *ylimits) const struct ipa_resource_limits *ylimits)
{ {
u32 val; u32 val;
val = u32_encode_bits(xlimits->min, X_MIN_LIM_FMASK); val = ipa_reg_encode(reg, X_MIN_LIM, xlimits->min);
val |= u32_encode_bits(xlimits->max, X_MAX_LIM_FMASK); val |= ipa_reg_encode(reg, X_MAX_LIM, xlimits->max);
if (ylimits) { if (ylimits) {
val |= u32_encode_bits(ylimits->min, Y_MIN_LIM_FMASK); val |= ipa_reg_encode(reg, Y_MIN_LIM, ylimits->min);
val |= u32_encode_bits(ylimits->max, Y_MAX_LIM_FMASK); val |= ipa_reg_encode(reg, Y_MAX_LIM, ylimits->max);
} }
iowrite32(val, ipa->reg_virt + offset); iowrite32(val, ipa->reg_virt + ipa_reg_n_offset(reg, resource_type));
} }
static void ipa_resource_config_src(struct ipa *ipa, u32 resource_type, static void ipa_resource_config_src(struct ipa *ipa, u32 resource_type,
...@@ -91,34 +92,35 @@ static void ipa_resource_config_src(struct ipa *ipa, u32 resource_type, ...@@ -91,34 +92,35 @@ static void ipa_resource_config_src(struct ipa *ipa, u32 resource_type,
u32 group_count = data->rsrc_group_src_count; u32 group_count = data->rsrc_group_src_count;
const struct ipa_resource_limits *ylimits; const struct ipa_resource_limits *ylimits;
const struct ipa_resource *resource; const struct ipa_resource *resource;
u32 offset; const struct ipa_reg *reg;
resource = &data->resource_src[resource_type]; resource = &data->resource_src[resource_type];
offset = IPA_REG_SRC_RSRC_GRP_01_RSRC_TYPE_N_OFFSET(resource_type); reg = ipa_reg(ipa, SRC_RSRC_GRP_01_RSRC_TYPE);
ylimits = group_count == 1 ? NULL : &resource->limits[1]; ylimits = group_count == 1 ? NULL : &resource->limits[1];
ipa_resource_config_common(ipa, offset, &resource->limits[0], ylimits); ipa_resource_config_common(ipa, resource_type, reg,
&resource->limits[0], ylimits);
if (group_count < 3) if (group_count < 3)
return; return;
offset = IPA_REG_SRC_RSRC_GRP_23_RSRC_TYPE_N_OFFSET(resource_type); reg = ipa_reg(ipa, SRC_RSRC_GRP_23_RSRC_TYPE);
ylimits = group_count == 3 ? NULL : &resource->limits[3]; ylimits = group_count == 3 ? NULL : &resource->limits[3];
ipa_resource_config_common(ipa, offset, &resource->limits[2], ylimits); ipa_resource_config_common(ipa, resource_type, reg,
&resource->limits[2], ylimits);
if (group_count < 5) if (group_count < 5)
return; return;
offset = IPA_REG_SRC_RSRC_GRP_45_RSRC_TYPE_N_OFFSET(resource_type); reg = ipa_reg(ipa, SRC_RSRC_GRP_45_RSRC_TYPE);
ylimits = group_count == 5 ? NULL : &resource->limits[5]; ylimits = group_count == 5 ? NULL : &resource->limits[5];
ipa_resource_config_common(ipa, offset, &resource->limits[4], ylimits); ipa_resource_config_common(ipa, resource_type, reg,
&resource->limits[4], ylimits);
if (group_count < 7) if (group_count < 7)
return; return;
offset = IPA_REG_SRC_RSRC_GRP_67_RSRC_TYPE_N_OFFSET(resource_type); reg = ipa_reg(ipa, SRC_RSRC_GRP_67_RSRC_TYPE);
ylimits = group_count == 7 ? NULL : &resource->limits[7]; ylimits = group_count == 7 ? NULL : &resource->limits[7];
ipa_resource_config_common(ipa, offset, &resource->limits[6], ylimits); ipa_resource_config_common(ipa, resource_type, reg,
&resource->limits[6], ylimits);
} }
static void ipa_resource_config_dst(struct ipa *ipa, u32 resource_type, static void ipa_resource_config_dst(struct ipa *ipa, u32 resource_type,
...@@ -127,34 +129,35 @@ static void ipa_resource_config_dst(struct ipa *ipa, u32 resource_type, ...@@ -127,34 +129,35 @@ static void ipa_resource_config_dst(struct ipa *ipa, u32 resource_type,
u32 group_count = data->rsrc_group_dst_count; u32 group_count = data->rsrc_group_dst_count;
const struct ipa_resource_limits *ylimits; const struct ipa_resource_limits *ylimits;
const struct ipa_resource *resource; const struct ipa_resource *resource;
u32 offset; const struct ipa_reg *reg;
resource = &data->resource_dst[resource_type]; resource = &data->resource_dst[resource_type];
offset = IPA_REG_DST_RSRC_GRP_01_RSRC_TYPE_N_OFFSET(resource_type); reg = ipa_reg(ipa, DST_RSRC_GRP_01_RSRC_TYPE);
ylimits = group_count == 1 ? NULL : &resource->limits[1]; ylimits = group_count == 1 ? NULL : &resource->limits[1];
ipa_resource_config_common(ipa, offset, &resource->limits[0], ylimits); ipa_resource_config_common(ipa, resource_type, reg,
&resource->limits[0], ylimits);
if (group_count < 3) if (group_count < 3)
return; return;
offset = IPA_REG_DST_RSRC_GRP_23_RSRC_TYPE_N_OFFSET(resource_type); reg = ipa_reg(ipa, DST_RSRC_GRP_23_RSRC_TYPE);
ylimits = group_count == 3 ? NULL : &resource->limits[3]; ylimits = group_count == 3 ? NULL : &resource->limits[3];
ipa_resource_config_common(ipa, offset, &resource->limits[2], ylimits); ipa_resource_config_common(ipa, resource_type, reg,
&resource->limits[2], ylimits);
if (group_count < 5) if (group_count < 5)
return; return;
offset = IPA_REG_DST_RSRC_GRP_45_RSRC_TYPE_N_OFFSET(resource_type); reg = ipa_reg(ipa, DST_RSRC_GRP_45_RSRC_TYPE);
ylimits = group_count == 5 ? NULL : &resource->limits[5]; ylimits = group_count == 5 ? NULL : &resource->limits[5];
ipa_resource_config_common(ipa, offset, &resource->limits[4], ylimits); ipa_resource_config_common(ipa, resource_type, reg,
&resource->limits[4], ylimits);
if (group_count < 7) if (group_count < 7)
return; return;
offset = IPA_REG_DST_RSRC_GRP_67_RSRC_TYPE_N_OFFSET(resource_type); reg = ipa_reg(ipa, DST_RSRC_GRP_67_RSRC_TYPE);
ylimits = group_count == 7 ? NULL : &resource->limits[7]; ylimits = group_count == 7 ? NULL : &resource->limits[7];
ipa_resource_config_common(ipa, offset, &resource->limits[6], ylimits); ipa_resource_config_common(ipa, resource_type, reg,
&resource->limits[6], ylimits);
} }
/* Configure resources; there is no ipa_resource_deconfig() */ /* Configure resources; there is no ipa_resource_deconfig() */
......
...@@ -384,8 +384,9 @@ void ipa_table_reset(struct ipa *ipa, bool modem) ...@@ -384,8 +384,9 @@ void ipa_table_reset(struct ipa *ipa, bool modem)
int ipa_table_hash_flush(struct ipa *ipa) int ipa_table_hash_flush(struct ipa *ipa)
{ {
u32 offset = ipa_reg_filt_rout_hash_flush_offset(ipa->version); const struct ipa_reg *reg;
struct gsi_trans *trans; struct gsi_trans *trans;
u32 offset;
u32 val; u32 val;
if (!ipa_table_hash_support(ipa)) if (!ipa_table_hash_support(ipa))
...@@ -397,8 +398,13 @@ int ipa_table_hash_flush(struct ipa *ipa) ...@@ -397,8 +398,13 @@ int ipa_table_hash_flush(struct ipa *ipa)
return -EBUSY; return -EBUSY;
} }
val = IPV4_FILTER_HASH_FMASK | IPV6_FILTER_HASH_FMASK; reg = ipa_reg(ipa, FILT_ROUT_HASH_FLUSH);
val |= IPV6_ROUTER_HASH_FMASK | IPV4_ROUTER_HASH_FMASK; offset = ipa_reg_offset(reg);
val = ipa_reg_bit(reg, IPV6_ROUTER_HASH);
val |= ipa_reg_bit(reg, IPV6_FILTER_HASH);
val |= ipa_reg_bit(reg, IPV4_ROUTER_HASH);
val |= ipa_reg_bit(reg, IPV4_FILTER_HASH);
ipa_cmd_register_write_add(trans, offset, val, val, false); ipa_cmd_register_write_add(trans, offset, val, val, false);
...@@ -516,15 +522,18 @@ int ipa_table_setup(struct ipa *ipa) ...@@ -516,15 +522,18 @@ int ipa_table_setup(struct ipa *ipa)
static void ipa_filter_tuple_zero(struct ipa_endpoint *endpoint) static void ipa_filter_tuple_zero(struct ipa_endpoint *endpoint)
{ {
u32 endpoint_id = endpoint->endpoint_id; u32 endpoint_id = endpoint->endpoint_id;
struct ipa *ipa = endpoint->ipa;
const struct ipa_reg *reg;
u32 offset; u32 offset;
u32 val; u32 val;
offset = IPA_REG_ENDP_FILTER_ROUTER_HSH_CFG_N_OFFSET(endpoint_id); reg = ipa_reg(ipa, ENDP_FILTER_ROUTER_HSH_CFG);
offset = ipa_reg_n_offset(reg, endpoint_id);
val = ioread32(endpoint->ipa->reg_virt + offset); val = ioread32(endpoint->ipa->reg_virt + offset);
/* Zero all filter-related fields, preserving the rest */ /* Zero all filter-related fields, preserving the rest */
val &= ~IPA_REG_ENDP_FILTER_HASH_MSK_ALL; val &= ~ipa_reg_fmask(reg, FILTER_HASH_MSK_ALL);
iowrite32(val, endpoint->ipa->reg_virt + offset); iowrite32(val, endpoint->ipa->reg_virt + offset);
} }
...@@ -565,13 +574,17 @@ static bool ipa_route_id_modem(u32 route_id) ...@@ -565,13 +574,17 @@ static bool ipa_route_id_modem(u32 route_id)
*/ */
static void ipa_route_tuple_zero(struct ipa *ipa, u32 route_id) static void ipa_route_tuple_zero(struct ipa *ipa, u32 route_id)
{ {
u32 offset = IPA_REG_ENDP_FILTER_ROUTER_HSH_CFG_N_OFFSET(route_id); const struct ipa_reg *reg;
u32 offset;
u32 val; u32 val;
reg = ipa_reg(ipa, ENDP_FILTER_ROUTER_HSH_CFG);
offset = ipa_reg_n_offset(reg, route_id);
val = ioread32(ipa->reg_virt + offset); val = ioread32(ipa->reg_virt + offset);
/* Zero all route-related fields, preserving the rest */ /* Zero all route-related fields, preserving the rest */
val &= ~IPA_REG_ENDP_ROUTER_HASH_MSK_ALL; val &= ~ipa_reg_fmask(reg, ROUTER_HASH_MSK_ALL);
iowrite32(val, ipa->reg_virt + offset); iowrite32(val, ipa->reg_virt + offset);
} }
......
...@@ -222,7 +222,7 @@ void ipa_uc_power(struct ipa *ipa) ...@@ -222,7 +222,7 @@ void ipa_uc_power(struct ipa *ipa)
static void send_uc_command(struct ipa *ipa, u32 command, u32 command_param) static void send_uc_command(struct ipa *ipa, u32 command, u32 command_param)
{ {
struct ipa_uc_mem_area *shared = ipa_uc_shared(ipa); struct ipa_uc_mem_area *shared = ipa_uc_shared(ipa);
u32 offset; const struct ipa_reg *reg;
u32 val; u32 val;
/* Fill in the command data */ /* Fill in the command data */
...@@ -233,9 +233,10 @@ static void send_uc_command(struct ipa *ipa, u32 command, u32 command_param) ...@@ -233,9 +233,10 @@ static void send_uc_command(struct ipa *ipa, u32 command, u32 command_param)
shared->response_param = 0; shared->response_param = 0;
/* Use an interrupt to tell the microcontroller the command is ready */ /* Use an interrupt to tell the microcontroller the command is ready */
val = u32_encode_bits(1, UC_INTR_FMASK); reg = ipa_reg(ipa, IPA_IRQ_UC);
offset = ipa_reg_irq_uc_offset(ipa->version); val = ipa_reg_bit(reg, UC_INTR);
iowrite32(val, ipa->reg_virt + offset);
iowrite32(val, ipa->reg_virt + ipa_reg_offset(reg));
} }
/* Tell the microcontroller the AP is shutting down */ /* Tell the microcontroller the AP is shutting down */
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment