drivers/interconnect/samsung/exynos.c

Source file repositories/reference/linux-study-clean/drivers/interconnect/samsung/exynos.c

File Facts

System
Linux kernel
Corpus path
drivers/interconnect/samsung/exynos.c
Extension
.c
Size
4916 bytes
Lines
197
Domain
Driver Families
Bucket
drivers/interconnect
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct exynos_icc_priv {
	struct device *dev;

	/* One interconnect node per provider */
	struct icc_provider provider;
	struct icc_node *node;

	struct dev_pm_qos_request qos_req;
	u32 bus_clk_ratio;
};

static struct icc_node *exynos_icc_get_parent(struct device_node *np)
{
	struct of_phandle_args args;
	struct icc_node_data *icc_node_data;
	struct icc_node *icc_node;
	int num, ret;

	num = of_count_phandle_with_args(np, "interconnects",
					 "#interconnect-cells");
	if (num < 1)
		return NULL; /* parent nodes are optional */

	/* Get the interconnect target node */
	ret = of_parse_phandle_with_args(np, "interconnects",
					"#interconnect-cells", 0, &args);
	if (ret < 0)
		return ERR_PTR(ret);

	icc_node_data = of_icc_get_from_provider(&args);
	of_node_put(args.np);

	if (IS_ERR(icc_node_data))
		return ERR_CAST(icc_node_data);

	icc_node = icc_node_data->node;
	kfree(icc_node_data);

	return icc_node;
}

static int exynos_generic_icc_set(struct icc_node *src, struct icc_node *dst)
{
	struct exynos_icc_priv *src_priv = src->data, *dst_priv = dst->data;
	s32 src_freq = max(src->avg_bw, src->peak_bw) / src_priv->bus_clk_ratio;
	s32 dst_freq = max(dst->avg_bw, dst->peak_bw) / dst_priv->bus_clk_ratio;
	int ret;

	ret = dev_pm_qos_update_request(&src_priv->qos_req, src_freq);
	if (ret < 0) {
		dev_err(src_priv->dev, "failed to update PM QoS of %s (src)\n",
			src->name);
		return ret;
	}

	ret = dev_pm_qos_update_request(&dst_priv->qos_req, dst_freq);
	if (ret < 0) {
		dev_err(dst_priv->dev, "failed to update PM QoS of %s (dst)\n",
			dst->name);
		return ret;
	}

	return 0;
}

static struct icc_node *exynos_generic_icc_xlate(const struct of_phandle_args *spec,
						 void *data)
{
	struct exynos_icc_priv *priv = data;

	if (spec->np != priv->dev->parent->of_node)
		return ERR_PTR(-EINVAL);

	return priv->node;
}

static void exynos_generic_icc_remove(struct platform_device *pdev)
{
	struct exynos_icc_priv *priv = platform_get_drvdata(pdev);

	icc_provider_deregister(&priv->provider);
	icc_nodes_remove(&priv->provider);
}

static int exynos_generic_icc_probe(struct platform_device *pdev)
{
	struct device *bus_dev = pdev->dev.parent;
	struct exynos_icc_priv *priv;
	struct icc_provider *provider;
	struct icc_node *icc_node, *icc_parent_node;

Annotation

Implementation Notes