Commit 1af15c2a authored by Alex Elder's avatar Alex Elder Committed by Jakub Kicinski

net: ipa: add new most-significant bits to registers

IPA v4.5 adds a few fields to the endpoint header and extended
header configuration registers that represent new high-order bits
for certain offsets and sizes.  Add code to incorporate these upper
bits into the registers for IPA v4.5.

This includes creating ipa_header_size_encoded(), which handles
encoding the metadata offset field for use in the ENDP_INIT_HDR
register in a way appropriate for the hardware version.  This and
ipa_metadata_offset_encoded() ensure the mask argument passed to
u32_encode_bits() is constant.
Signed-off-by: default avatarAlex Elder <elder@linaro.org>
Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent 5b6cd69e
......@@ -485,28 +485,34 @@ static void ipa_endpoint_init_cfg(struct ipa_endpoint *endpoint)
static void ipa_endpoint_init_hdr(struct ipa_endpoint *endpoint)
{
u32 offset = IPA_REG_ENDP_INIT_HDR_N_OFFSET(endpoint->endpoint_id);
struct ipa *ipa = endpoint->ipa;
u32 val = 0;
if (endpoint->data->qmap) {
size_t header_size = sizeof(struct rmnet_map_header);
enum ipa_version version = ipa->version;
/* We might supply a checksum header after the QMAP header */
if (endpoint->toward_ipa && endpoint->data->checksum)
header_size += sizeof(struct rmnet_map_ul_csum_header);
val |= u32_encode_bits(header_size, HDR_LEN_FMASK);
val |= ipa_header_size_encoded(version, header_size);
/* Define how to fill fields in a received QMAP header */
if (!endpoint->toward_ipa) {
u32 off; /* Field offset within header */
u32 offset; /* Field offset within header */
/* Where IPA will write the metadata value */
off = offsetof(struct rmnet_map_header, mux_id);
val |= u32_encode_bits(off, HDR_OFST_METADATA_FMASK);
offset = offsetof(struct rmnet_map_header, mux_id);
val |= ipa_metadata_offset_encoded(version, offset);
/* Where IPA will write the length */
off = offsetof(struct rmnet_map_header, pkt_len);
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)
offset &= field_mask(HDR_OFST_PKT_SIZE_FMASK);
val |= HDR_OFST_PKT_SIZE_VALID_FMASK;
val |= u32_encode_bits(off, HDR_OFST_PKT_SIZE_FMASK);
val |= u32_encode_bits(offset, HDR_OFST_PKT_SIZE_FMASK);
}
/* For QMAP TX, metadata offset is 0 (modem assumes this) */
val |= HDR_OFST_METADATA_VALID_FMASK;
......@@ -517,13 +523,14 @@ static void ipa_endpoint_init_hdr(struct ipa_endpoint *endpoint)
/* HDR_METADATA_REG_VALID is 0 (TX only) */
}
iowrite32(val, endpoint->ipa->reg_virt + offset);
iowrite32(val, ipa->reg_virt + offset);
}
static void ipa_endpoint_init_hdr_ext(struct ipa_endpoint *endpoint)
{
u32 offset = IPA_REG_ENDP_INIT_HDR_EXT_N_OFFSET(endpoint->endpoint_id);
u32 pad_align = endpoint->data->rx.pad_align;
struct ipa *ipa = endpoint->ipa;
u32 val = 0;
val |= HDR_ENDIANNESS_FMASK; /* big endian */
......@@ -545,10 +552,24 @@ static void ipa_endpoint_init_hdr_ext(struct ipa_endpoint *endpoint)
if (!endpoint->toward_ipa)
val |= u32_encode_bits(pad_align, HDR_PAD_TO_ALIGNMENT_FMASK);
iowrite32(val, endpoint->ipa->reg_virt + offset);
/* 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) {
/* HDR_TOTAL_LEN_OR_PAD_OFFSET is 0, so MSB is 0 */
if (endpoint->data->qmap && !endpoint->toward_ipa) {
u32 offset;
offset = offsetof(struct rmnet_map_header, pkt_len);
offset >>= hweight32(HDR_OFST_PKT_SIZE_FMASK);
val |= u32_encode_bits(offset,
HDR_OFST_PKT_SIZE_MSB_FMASK);
/* HDR_ADDITIONAL_CONST_LEN is 0 so MSB is 0 */
}
}
iowrite32(val, ipa->reg_virt + offset);
}
static void ipa_endpoint_init_hdr_metadata_mask(struct ipa_endpoint *endpoint)
{
u32 endpoint_id = endpoint->endpoint_id;
......
......@@ -367,6 +367,40 @@ enum ipa_cs_offload_en {
#define HDR_LEN_MSB_FMASK GENMASK(29, 28)
#define HDR_OFST_METADATA_MSB_FMASK GENMASK(31, 30)
/* Encoded value for ENDP_INIT_HDR register HDR_LEN* field(s) */
static inline u32 ipa_header_size_encoded(enum ipa_version version,
u32 header_size)
{
u32 val;
val = u32_encode_bits(header_size, HDR_LEN_FMASK);
if (version < IPA_VERSION_4_5)
return val;
/* IPA v4.5 adds a few more most-significant bits */
header_size >>= hweight32(HDR_LEN_FMASK);
val |= u32_encode_bits(header_size, HDR_LEN_MSB_FMASK);
return val;
}
/* Encoded value for ENDP_INIT_HDR register OFST_METADATA* field(s) */
static inline u32 ipa_metadata_offset_encoded(enum ipa_version version,
u32 offset)
{
u32 val;
val = u32_encode_bits(offset, HDR_OFST_METADATA_FMASK);
if (version < IPA_VERSION_4_5)
return val;
/* IPA v4.5 adds a few more most-significant bits */
offset >>= hweight32(HDR_OFST_METADATA_FMASK);
val |= u32_encode_bits(offset, HDR_OFST_METADATA_MSB_FMASK);
return val;
}
#define IPA_REG_ENDP_INIT_HDR_EXT_N_OFFSET(ep) \
(0x00000814 + 0x0070 * (ep))
#define HDR_ENDIANNESS_FMASK GENMASK(0, 0)
......@@ -461,7 +495,7 @@ enum ipa_aggr_type {
#define IPA_REG_ENDP_INIT_RSRC_GRP_N_OFFSET(ep) \
(0x00000838 + 0x0070 * (ep))
/* Encoded value for RSRC_GRP endpoint register RSRC_GRP field */
/* Encoded value for ENDP_INIT_RSRC_GRP register RSRC_GRP field */
static inline u32 rsrc_grp_encoded(enum ipa_version version, u32 rsrc_grp)
{
switch (version) {
......@@ -492,7 +526,7 @@ static inline u32 rsrc_grp_encoded(enum ipa_version version, u32 rsrc_grp)
* @IPA_SEQ_INVALID: invalid sequencer type
*
* The values defined here are broken into 4-bit nibbles that are written
* into fields of the INIT_SEQ_N endpoint registers.
* into fields of the ENDP_INIT_SEQ registers.
*/
enum ipa_seq_type {
IPA_SEQ_DMA_ONLY = 0x0000,
......
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