Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 
0003 /* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
0004  * Copyright (C) 2018-2021 Linaro Ltd.
0005  */
0006 
0007 #include <linux/types.h>
0008 #include <linux/kernel.h>
0009 
0010 #include "ipa.h"
0011 #include "ipa_data.h"
0012 #include "ipa_reg.h"
0013 #include "ipa_resource.h"
0014 
0015 /**
0016  * DOC: IPA Resources
0017  *
0018  * The IPA manages a set of resources internally for various purposes.
0019  * A given IPA version has a fixed number of resource types, and a fixed
0020  * total number of resources of each type.  "Source" resource types
0021  * are separate from "destination" resource types.
0022  *
0023  * Each version of IPA also has some number of resource groups.  Each
0024  * endpoint is assigned to a resource group, and all endpoints in the
0025  * same group share pools of each type of resource.  A subset of the
0026  * total resources of each type is assigned for use by each group.
0027  */
0028 
0029 static bool ipa_resource_limits_valid(struct ipa *ipa,
0030                       const struct ipa_resource_data *data)
0031 {
0032     u32 group_count;
0033     u32 i;
0034     u32 j;
0035 
0036     /* We program at most 8 source or destination resource group limits */
0037     BUILD_BUG_ON(IPA_RESOURCE_GROUP_MAX > 8);
0038 
0039     group_count = data->rsrc_group_src_count;
0040     if (!group_count || group_count > IPA_RESOURCE_GROUP_MAX)
0041         return false;
0042 
0043     /* Return an error if a non-zero resource limit is specified
0044      * for a resource group not supported by hardware.
0045      */
0046     for (i = 0; i < data->resource_src_count; i++) {
0047         const struct ipa_resource *resource;
0048 
0049         resource = &data->resource_src[i];
0050         for (j = group_count; j < IPA_RESOURCE_GROUP_MAX; j++)
0051             if (resource->limits[j].min || resource->limits[j].max)
0052                 return false;
0053     }
0054 
0055     group_count = data->rsrc_group_dst_count;
0056     if (!group_count || group_count > IPA_RESOURCE_GROUP_MAX)
0057         return false;
0058 
0059     for (i = 0; i < data->resource_dst_count; i++) {
0060         const struct ipa_resource *resource;
0061 
0062         resource = &data->resource_dst[i];
0063         for (j = group_count; j < IPA_RESOURCE_GROUP_MAX; j++)
0064             if (resource->limits[j].min || resource->limits[j].max)
0065                 return false;
0066     }
0067 
0068     return true;
0069 }
0070 
0071 static void
0072 ipa_resource_config_common(struct ipa *ipa, u32 offset,
0073                const struct ipa_resource_limits *xlimits,
0074                const struct ipa_resource_limits *ylimits)
0075 {
0076     u32 val;
0077 
0078     val = u32_encode_bits(xlimits->min, X_MIN_LIM_FMASK);
0079     val |= u32_encode_bits(xlimits->max, X_MAX_LIM_FMASK);
0080     if (ylimits) {
0081         val |= u32_encode_bits(ylimits->min, Y_MIN_LIM_FMASK);
0082         val |= u32_encode_bits(ylimits->max, Y_MAX_LIM_FMASK);
0083     }
0084 
0085     iowrite32(val, ipa->reg_virt + offset);
0086 }
0087 
0088 static void ipa_resource_config_src(struct ipa *ipa, u32 resource_type,
0089                     const struct ipa_resource_data *data)
0090 {
0091     u32 group_count = data->rsrc_group_src_count;
0092     const struct ipa_resource_limits *ylimits;
0093     const struct ipa_resource *resource;
0094     u32 offset;
0095 
0096     resource = &data->resource_src[resource_type];
0097 
0098     offset = IPA_REG_SRC_RSRC_GRP_01_RSRC_TYPE_N_OFFSET(resource_type);
0099     ylimits = group_count == 1 ? NULL : &resource->limits[1];
0100     ipa_resource_config_common(ipa, offset, &resource->limits[0], ylimits);
0101 
0102     if (group_count < 3)
0103         return;
0104 
0105     offset = IPA_REG_SRC_RSRC_GRP_23_RSRC_TYPE_N_OFFSET(resource_type);
0106     ylimits = group_count == 3 ? NULL : &resource->limits[3];
0107     ipa_resource_config_common(ipa, offset, &resource->limits[2], ylimits);
0108 
0109     if (group_count < 5)
0110         return;
0111 
0112     offset = IPA_REG_SRC_RSRC_GRP_45_RSRC_TYPE_N_OFFSET(resource_type);
0113     ylimits = group_count == 5 ? NULL : &resource->limits[5];
0114     ipa_resource_config_common(ipa, offset, &resource->limits[4], ylimits);
0115 
0116     if (group_count < 7)
0117         return;
0118 
0119     offset = IPA_REG_SRC_RSRC_GRP_67_RSRC_TYPE_N_OFFSET(resource_type);
0120     ylimits = group_count == 7 ? NULL : &resource->limits[7];
0121     ipa_resource_config_common(ipa, offset, &resource->limits[6], ylimits);
0122 }
0123 
0124 static void ipa_resource_config_dst(struct ipa *ipa, u32 resource_type,
0125                     const struct ipa_resource_data *data)
0126 {
0127     u32 group_count = data->rsrc_group_dst_count;
0128     const struct ipa_resource_limits *ylimits;
0129     const struct ipa_resource *resource;
0130     u32 offset;
0131 
0132     resource = &data->resource_dst[resource_type];
0133 
0134     offset = IPA_REG_DST_RSRC_GRP_01_RSRC_TYPE_N_OFFSET(resource_type);
0135     ylimits = group_count == 1 ? NULL : &resource->limits[1];
0136     ipa_resource_config_common(ipa, offset, &resource->limits[0], ylimits);
0137 
0138     if (group_count < 3)
0139         return;
0140 
0141     offset = IPA_REG_DST_RSRC_GRP_23_RSRC_TYPE_N_OFFSET(resource_type);
0142     ylimits = group_count == 3 ? NULL : &resource->limits[3];
0143     ipa_resource_config_common(ipa, offset, &resource->limits[2], ylimits);
0144 
0145     if (group_count < 5)
0146         return;
0147 
0148     offset = IPA_REG_DST_RSRC_GRP_45_RSRC_TYPE_N_OFFSET(resource_type);
0149     ylimits = group_count == 5 ? NULL : &resource->limits[5];
0150     ipa_resource_config_common(ipa, offset, &resource->limits[4], ylimits);
0151 
0152     if (group_count < 7)
0153         return;
0154 
0155     offset = IPA_REG_DST_RSRC_GRP_67_RSRC_TYPE_N_OFFSET(resource_type);
0156     ylimits = group_count == 7 ? NULL : &resource->limits[7];
0157     ipa_resource_config_common(ipa, offset, &resource->limits[6], ylimits);
0158 }
0159 
0160 /* Configure resources; there is no ipa_resource_deconfig() */
0161 int ipa_resource_config(struct ipa *ipa, const struct ipa_resource_data *data)
0162 {
0163     u32 i;
0164 
0165     if (!ipa_resource_limits_valid(ipa, data))
0166         return -EINVAL;
0167 
0168     for (i = 0; i < data->resource_src_count; i++)
0169         ipa_resource_config_src(ipa, i, data);
0170 
0171     for (i = 0; i < data->resource_dst_count; i++)
0172         ipa_resource_config_dst(ipa, i, data);
0173 
0174     return 0;
0175 }