File Index
Files and directories
Sign in
FILE

icc-emi.c

File preview with syntax highlighting.

linux-6.19.14/drivers/interconnect/mediatek/icc-emi.c C
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * MediaTek External Memory Interface (EMI) Interconnect driver
  4 *
  5 * Copyright (c) 2021 MediaTek Inc.
  6 * Copyright (c) 2024 Collabora Ltd.
  7 *                    AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
  8 */
  9
 10#include <linux/interconnect.h>
 11#include <linux/interconnect-provider.h>
 12#include <linux/module.h>
 13#include <linux/of.h>
 14#include <linux/of_platform.h>
 15#include <linux/overflow.h>
 16#include <linux/platform_device.h>
 17#include <linux/soc/mediatek/dvfsrc.h>
 18
 19#include "icc-emi.h"
 20
 21static int mtk_emi_icc_aggregate(struct icc_node *node, u32 tag, u32 avg_bw,
 22				 u32 peak_bw, u32 *agg_avg, u32 *agg_peak)
 23{
 24	struct mtk_icc_node *in = node->data;
 25
 26	if (check_add_overflow(*agg_avg, avg_bw, agg_avg))
 27		*agg_avg = U32_MAX;
 28
 29	*agg_peak = max_t(u32, *agg_peak, peak_bw);
 30
 31	in->sum_avg = *agg_avg;
 32	in->max_peak = *agg_peak;
 33
 34	return 0;
 35}
 36
 37static int mtk_emi_icc_set(struct icc_node *src, struct icc_node *dst)
 38{
 39	struct mtk_icc_node *node = dst->data;
 40	struct device *dev;
 41	int ret;
 42
 43	if (unlikely(!src->provider))
 44		return -EINVAL;
 45
 46	dev = src->provider->dev->parent;
 47
 48	switch (node->ep) {
 49	case 0:
 50		break;
 51	case 1:
 52		ret = mtk_dvfsrc_send_request(dev, MTK_DVFSRC_CMD_PEAK_BW, node->max_peak);
 53		if (ret) {
 54			dev_err(dev, "Cannot send peak bw request: %d\n", ret);
 55			return ret;
 56		}
 57
 58		ret = mtk_dvfsrc_send_request(dev, MTK_DVFSRC_CMD_BW, node->sum_avg);
 59		if (ret) {
 60			dev_err(dev, "Cannot send bw request: %d\n", ret);
 61			return ret;
 62		}
 63		break;
 64	case 2:
 65		ret = mtk_dvfsrc_send_request(dev, MTK_DVFSRC_CMD_HRT_BW, node->sum_avg);
 66		if (ret) {
 67			dev_err(dev, "Cannot send HRT bw request: %d\n", ret);
 68			return ret;
 69		}
 70		break;
 71	default:
 72		dev_err(src->provider->dev, "Unknown endpoint %u\n", node->ep);
 73		return -EINVAL;
 74	}
 75
 76	return 0;
 77}
 78
 79int mtk_emi_icc_probe(struct platform_device *pdev)
 80{
 81	const struct mtk_icc_desc *desc;
 82	struct device *dev = &pdev->dev;
 83	struct icc_node *node;
 84	struct icc_onecell_data *data;
 85	struct icc_provider *provider;
 86	struct mtk_icc_node **mnodes;
 87	int i, j, ret;
 88
 89	desc = of_device_get_match_data(dev);
 90	if (!desc)
 91		return -EINVAL;
 92
 93	mnodes = desc->nodes;
 94
 95	provider = devm_kzalloc(dev, sizeof(*provider), GFP_KERNEL);
 96	if (!provider)
 97		return -ENOMEM;
 98
 99	data = devm_kzalloc(dev, struct_size(data, nodes, desc->num_nodes), GFP_KERNEL);
100	if (!data)
101		return -ENOMEM;
102
103	provider->dev = dev;
104	provider->set = mtk_emi_icc_set;
105	provider->aggregate = mtk_emi_icc_aggregate;
106	provider->xlate = of_icc_xlate_onecell;
107	INIT_LIST_HEAD(&provider->nodes);
108	provider->data = data;
109
110	for (i = 0; i < desc->num_nodes; i++) {
111		if (!mnodes[i])
112			continue;
113
114		node = icc_node_create(mnodes[i]->id);
115		if (IS_ERR(node)) {
116			ret = PTR_ERR(node);
117			goto err;
118		}
119
120		node->name = mnodes[i]->name;
121		node->data = mnodes[i];
122		icc_node_add(node, provider);
123
124		for (j = 0; j < mnodes[i]->num_links; j++)
125			icc_link_create(node, mnodes[i]->links[j]);
126
127		data->nodes[i] = node;
128	}
129	data->num_nodes = desc->num_nodes;
130
131	ret = icc_provider_register(provider);
132	if (ret)
133		goto err;
134
135	platform_set_drvdata(pdev, provider);
136
137	return 0;
138err:
139	icc_nodes_remove(provider);
140	return ret;
141}
142EXPORT_SYMBOL_GPL(mtk_emi_icc_probe);
143
144void mtk_emi_icc_remove(struct platform_device *pdev)
145{
146	struct icc_provider *provider = platform_get_drvdata(pdev);
147
148	icc_provider_deregister(provider);
149	icc_nodes_remove(provider);
150}
151EXPORT_SYMBOL_GPL(mtk_emi_icc_remove);
152
153MODULE_AUTHOR("AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>");
154MODULE_AUTHOR("Henry Chen <henryc.chen@mediatek.com>");
155MODULE_DESCRIPTION("MediaTek External Memory Interface interconnect driver");
156MODULE_LICENSE("GPL");
~/ Read-only file preview.