0001
0002
0003
0004
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
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
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
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
0044
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
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 }