brintos

brintos / linux-shallow public Read only

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