Re: [RFC PATCH v5 2/6] interconnect: Add generic interconnect driver for Exynos SoCs

From: Georgi Djakov
Date: Wed Jul 01 2020 - 08:50:11 EST


Hi Sylwester,

Thanks for the patch and apologies for the delayed reply.

On 5/29/20 19:31, Sylwester Nawrocki wrote:
> This patch adds a generic interconnect driver for Exynos SoCs in order
> to provide interconnect functionality for each "samsung,exynos-bus"
> compatible device.
>
> The SoC topology is a graph (or more specifically, a tree) and its
> edges are specified using the 'samsung,interconnect-parent' in the
> DT. Due to unspecified relative probing order, -EPROBE_DEFER may be
> propagated to ensure that the parent is probed before its children.
>
> Each bus is now an interconnect provider and an interconnect node as
> well (cf. Documentation/interconnect/interconnect.rst), i.e. every bus
> registers itself as a node. Node IDs are not hardcoded but rather
> assigned dynamically at runtime. This approach allows for using this
> driver with various Exynos SoCs.
>
> Frequencies requested via the interconnect API for a given node are
> propagated to devfreq using dev_pm_qos_update_request(). Please note
> that it is not an error when CONFIG_INTERCONNECT is 'n', in which
> case all interconnect API functions are no-op.
>
> Signed-off-by: Artur ÅwigoÅ <a.swigon@xxxxxxxxxxx>
> Signed-off-by: Sylwester Nawrocki <s.nawrocki@xxxxxxxxxxx>
>
> Changes for v5:
> - adjust to renamed exynos,interconnect-parent-node property,
> - use automatically generated platform device id as the interconect
> node id instead of a now unavailable devfreq->id field,
> - add icc_ prefix to some variables to make the code more self-commenting,
> - use icc_nodes_remove() instead of icc_node_del() + icc_node_destroy(),
> - adjust to exynos,interconnect-parent-node property rename to
> samsung,interconnect-parent,
> - converted to a separate platform driver in drivers/i.nterconnect.
> ---
> drivers/interconnect/Kconfig | 1 +
> drivers/interconnect/Makefile | 1 +
> drivers/interconnect/exynos/Kconfig | 6 ++
> drivers/interconnect/exynos/Makefile | 4 +
> drivers/interconnect/exynos/exynos.c | 185 +++++++++++++++++++++++++++++++++++
> 5 files changed, 197 insertions(+)
> create mode 100644 drivers/interconnect/exynos/Kconfig
> create mode 100644 drivers/interconnect/exynos/Makefile
> create mode 100644 drivers/interconnect/exynos/exynos.c
[..]
> +static struct icc_node *exynos_icc_get_parent(struct device_node *np)
> +{
> + struct of_phandle_args args;
> + int num, ret;
> +
> + num = of_count_phandle_with_args(np, "samsung,interconnect-parent",
> + "#interconnect-cells");
> + if (num != 1)
> + return NULL; /* parent nodes are optional */
> +
> + ret = of_parse_phandle_with_args(np, "samsung,interconnect-parent",
> + "#interconnect-cells", 0, &args);
> + if (ret < 0)
> + return ERR_PTR(ret);
> +
> + of_node_put(args.np);
> +
> + return of_icc_get_from_provider(&args);
> +}
> +
> +

Nit: multiple blank lines

[..]
> +static struct icc_node *exynos_generic_icc_xlate(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 int exynos_generic_icc_remove(struct platform_device *pdev)
> +{
> + struct exynos_icc_priv *priv = platform_get_drvdata(pdev);
> + struct icc_node *parent_node, *node = priv->node;
> +
> + parent_node = exynos_icc_get_parent(priv->dev->parent->of_node);
> + if (parent_node && !IS_ERR(parent_node))

Nit: !IS_ERR_OR_NULL?

> + icc_link_destroy(node, parent_node);
> +
> + icc_nodes_remove(&priv->provider);
> + icc_provider_del(&priv->provider);
> +
> + return 0;
> +}
> +
> +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;
> + int ret;
> +
> + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
> + if (!priv)
> + return -ENOMEM;
> +
> + priv->dev = &pdev->dev;
> + platform_set_drvdata(pdev, priv);
> +
> + provider = &priv->provider;
> +
> + provider->set = exynos_generic_icc_set;
> + provider->aggregate = icc_std_aggregate;
> + provider->xlate = exynos_generic_icc_xlate;
> + provider->dev = bus_dev;
> + provider->inter_set = true;
> + provider->data = priv;
> +
> + ret = icc_provider_add(provider);

Nit: Maybe it would be better to move this after the node is created. The
idea is to create the nodes first and add the provider when the topology is
populated. It's fine either way here, but i am planning to change this in
some of the existing provider drivers.

> + if (ret < 0)
> + return ret;
> +
> + icc_node = icc_node_create(pdev->id);
> + if (IS_ERR(icc_node)) {
> + ret = PTR_ERR(icc_node);
> + goto err_prov_del;
> + }
> +
> + priv->node = icc_node;
> + icc_node->name = bus_dev->of_node->name;
> + icc_node->data = priv;
> + icc_node_add(icc_node, provider);
> +
> + icc_parent_node = exynos_icc_get_parent(bus_dev->of_node);
> + if (IS_ERR(icc_parent_node)) {
> + ret = PTR_ERR(icc_parent_node);
> + goto err_node_del;
> + }
> + if (icc_parent_node) {
> + ret = icc_link_create(icc_node, icc_parent_node->id);
> + if (ret < 0)
> + goto err_node_del;
> + }
> +
> + /*
> + * Register a PM QoS request for the bus device for which also devfreq
> + * functionality is registered.
> + */
> + ret = dev_pm_qos_add_request(bus_dev, &priv->qos_req,
> + DEV_PM_QOS_MIN_FREQUENCY, 0);
> + if (ret < 0)
> + goto err_link_destroy;
> +
> + return 0;
> +
> +err_link_destroy:
> + if (icc_parent_node)
> + icc_link_destroy(icc_node, icc_parent_node);
> +err_node_del:
> + icc_nodes_remove(provider);
> +err_prov_del:
> + icc_provider_del(provider);
> +
> + return ret;
> +}
> +
> +static struct platform_driver exynos_generic_icc_driver = {
> + .driver = {
> + .name = "exynos-generic-icc",
> + },
> + .probe = exynos_generic_icc_probe,
> + .remove = exynos_generic_icc_remove,
> +};
> +module_platform_driver(exynos_generic_icc_driver);
> +
> +MODULE_DESCRIPTION("Exynos generic interconnect driver");
> +MODULE_AUTHOR("Artur ÅwigoÅ <a.swigon@xxxxxxxxxxx>");
> +MODULE_AUTHOR("Sylwester Nawrocki <s.nawrocki@xxxxxxxxxxx>");
> +MODULE_LICENSE("GPL v2");
> +MODULE_ALIAS("platform:exynos-generic-icc");

All looks good to me, but it seems that the patch-set is not on
Rob's radar currently, so please re-send and CC the DT mailing list.

Thanks,
Georgi