ipa_resource.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. // SPDX-License-Identifier: GPL-2.0
  2. /* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
  3. * Copyright (C) 2018-2024 Linaro Ltd.
  4. */
  5. #include <linux/types.h>
  6. #include "ipa.h"
  7. #include "ipa_data.h"
  8. #include "ipa_reg.h"
  9. #include "ipa_resource.h"
  10. /**
  11. * DOC: IPA Resources
  12. *
  13. * The IPA manages a set of resources internally for various purposes.
  14. * A given IPA version has a fixed number of resource types, and a fixed
  15. * total number of resources of each type. "Source" resource types
  16. * are separate from "destination" resource types.
  17. *
  18. * Each version of IPA also has some number of resource groups. Each
  19. * endpoint is assigned to a resource group, and all endpoints in the
  20. * same group share pools of each type of resource. A subset of the
  21. * total resources of each type is assigned for use by each group.
  22. */
  23. static bool ipa_resource_limits_valid(struct ipa *ipa,
  24. const struct ipa_resource_data *data)
  25. {
  26. u32 group_count;
  27. u32 i;
  28. u32 j;
  29. /* We program at most 8 source or destination resource group limits */
  30. BUILD_BUG_ON(IPA_RESOURCE_GROUP_MAX > 8);
  31. group_count = data->rsrc_group_src_count;
  32. if (!group_count || group_count > IPA_RESOURCE_GROUP_MAX)
  33. return false;
  34. /* Return an error if a non-zero resource limit is specified
  35. * for a resource group not supported by hardware.
  36. */
  37. for (i = 0; i < data->resource_src_count; i++) {
  38. const struct ipa_resource *resource;
  39. resource = &data->resource_src[i];
  40. for (j = group_count; j < IPA_RESOURCE_GROUP_MAX; j++)
  41. if (resource->limits[j].min || resource->limits[j].max)
  42. return false;
  43. }
  44. group_count = data->rsrc_group_dst_count;
  45. if (!group_count || group_count > IPA_RESOURCE_GROUP_MAX)
  46. return false;
  47. for (i = 0; i < data->resource_dst_count; i++) {
  48. const struct ipa_resource *resource;
  49. resource = &data->resource_dst[i];
  50. for (j = group_count; j < IPA_RESOURCE_GROUP_MAX; j++)
  51. if (resource->limits[j].min || resource->limits[j].max)
  52. return false;
  53. }
  54. return true;
  55. }
  56. static void
  57. ipa_resource_config_common(struct ipa *ipa, u32 resource_type,
  58. const struct reg *reg,
  59. const struct ipa_resource_limits *xlimits,
  60. const struct ipa_resource_limits *ylimits)
  61. {
  62. u32 val;
  63. val = reg_encode(reg, X_MIN_LIM, xlimits->min);
  64. val |= reg_encode(reg, X_MAX_LIM, xlimits->max);
  65. if (ylimits) {
  66. val |= reg_encode(reg, Y_MIN_LIM, ylimits->min);
  67. val |= reg_encode(reg, Y_MAX_LIM, ylimits->max);
  68. }
  69. iowrite32(val, ipa->reg_virt + reg_n_offset(reg, resource_type));
  70. }
  71. static void ipa_resource_config_src(struct ipa *ipa, u32 resource_type,
  72. const struct ipa_resource_data *data)
  73. {
  74. u32 group_count = data->rsrc_group_src_count;
  75. const struct ipa_resource_limits *ylimits;
  76. const struct ipa_resource *resource;
  77. const struct reg *reg;
  78. resource = &data->resource_src[resource_type];
  79. reg = ipa_reg(ipa, SRC_RSRC_GRP_01_RSRC_TYPE);
  80. ylimits = group_count == 1 ? NULL : &resource->limits[1];
  81. ipa_resource_config_common(ipa, resource_type, reg,
  82. &resource->limits[0], ylimits);
  83. if (group_count < 3)
  84. return;
  85. reg = ipa_reg(ipa, SRC_RSRC_GRP_23_RSRC_TYPE);
  86. ylimits = group_count == 3 ? NULL : &resource->limits[3];
  87. ipa_resource_config_common(ipa, resource_type, reg,
  88. &resource->limits[2], ylimits);
  89. if (group_count < 5)
  90. return;
  91. reg = ipa_reg(ipa, SRC_RSRC_GRP_45_RSRC_TYPE);
  92. ylimits = group_count == 5 ? NULL : &resource->limits[5];
  93. ipa_resource_config_common(ipa, resource_type, reg,
  94. &resource->limits[4], ylimits);
  95. if (group_count < 7)
  96. return;
  97. reg = ipa_reg(ipa, SRC_RSRC_GRP_67_RSRC_TYPE);
  98. ylimits = group_count == 7 ? NULL : &resource->limits[7];
  99. ipa_resource_config_common(ipa, resource_type, reg,
  100. &resource->limits[6], ylimits);
  101. }
  102. static void ipa_resource_config_dst(struct ipa *ipa, u32 resource_type,
  103. const struct ipa_resource_data *data)
  104. {
  105. u32 group_count = data->rsrc_group_dst_count;
  106. const struct ipa_resource_limits *ylimits;
  107. const struct ipa_resource *resource;
  108. const struct reg *reg;
  109. resource = &data->resource_dst[resource_type];
  110. reg = ipa_reg(ipa, DST_RSRC_GRP_01_RSRC_TYPE);
  111. ylimits = group_count == 1 ? NULL : &resource->limits[1];
  112. ipa_resource_config_common(ipa, resource_type, reg,
  113. &resource->limits[0], ylimits);
  114. if (group_count < 3)
  115. return;
  116. reg = ipa_reg(ipa, DST_RSRC_GRP_23_RSRC_TYPE);
  117. ylimits = group_count == 3 ? NULL : &resource->limits[3];
  118. ipa_resource_config_common(ipa, resource_type, reg,
  119. &resource->limits[2], ylimits);
  120. if (group_count < 5)
  121. return;
  122. reg = ipa_reg(ipa, DST_RSRC_GRP_45_RSRC_TYPE);
  123. ylimits = group_count == 5 ? NULL : &resource->limits[5];
  124. ipa_resource_config_common(ipa, resource_type, reg,
  125. &resource->limits[4], ylimits);
  126. if (group_count < 7)
  127. return;
  128. reg = ipa_reg(ipa, DST_RSRC_GRP_67_RSRC_TYPE);
  129. ylimits = group_count == 7 ? NULL : &resource->limits[7];
  130. ipa_resource_config_common(ipa, resource_type, reg,
  131. &resource->limits[6], ylimits);
  132. }
  133. /* Configure resources; there is no ipa_resource_deconfig() */
  134. int ipa_resource_config(struct ipa *ipa, const struct ipa_resource_data *data)
  135. {
  136. u32 i;
  137. if (!ipa_resource_limits_valid(ipa, data))
  138. return -EINVAL;
  139. for (i = 0; i < data->resource_src_count; i++)
  140. ipa_resource_config_src(ipa, i, data);
  141. for (i = 0; i < data->resource_dst_count; i++)
  142. ipa_resource_config_dst(ipa, i, data);
  143. return 0;
  144. }