Merge branch 'icc-imx8mp' into icc-next

This patchset is to support i.MX8MP NoC settings, i.MX8MP NoC initial
value after power up is invalid, need set a valid value after related
power domain up.

This patchset also includes two patch[1,2] during my development to enable
the ICC feature for i.MX8MP.

I not include ddrc DVFS in this patchset, ths patchset is only to
support NoC value mode/priority/ext_control being set to a valid value
that suggested by i.MX Chip Design Team. The value is same as NXP
downstream one inside Arm Trusted Firmware:
https://source.codeaurora.org/external/imx/imx-atf/tree/plat/imx/imx8m/i/gpc.c?h=lf_v2.4#n97

Link: https://lore.kernel.org/r/20220703091132.1412063-1-peng.fan@oss.nxp.com
Signed-off-by: Georgi Djakov <djakov@kernel.org>
This commit is contained in:
Georgi Djakov 2022-07-15 17:55:48 +03:00
commit 33f033dc30
13 changed files with 496 additions and 23 deletions

View File

@ -26,14 +26,16 @@ properties:
oneOf: oneOf:
- items: - items:
- enum: - enum:
- fsl,imx8mn-nic
- fsl,imx8mm-nic - fsl,imx8mm-nic
- fsl,imx8mn-nic
- fsl,imx8mp-nic
- fsl,imx8mq-nic - fsl,imx8mq-nic
- const: fsl,imx8m-nic - const: fsl,imx8m-nic
- items: - items:
- enum: - enum:
- fsl,imx8mn-noc
- fsl,imx8mm-noc - fsl,imx8mm-noc
- fsl,imx8mn-noc
- fsl,imx8mp-noc
- fsl,imx8mq-noc - fsl,imx8mq-noc
- const: fsl,imx8m-noc - const: fsl,imx8m-noc
- const: fsl,imx8m-nic - const: fsl,imx8m-nic

View File

@ -145,6 +145,7 @@ static const struct of_device_id imx_bus_of_match[] = {
{ .compatible = "fsl,imx8mq-noc", .data = "imx8mq-interconnect", }, { .compatible = "fsl,imx8mq-noc", .data = "imx8mq-interconnect", },
{ .compatible = "fsl,imx8mm-noc", .data = "imx8mm-interconnect", }, { .compatible = "fsl,imx8mm-noc", .data = "imx8mm-interconnect", },
{ .compatible = "fsl,imx8mn-noc", .data = "imx8mn-interconnect", }, { .compatible = "fsl,imx8mn-noc", .data = "imx8mn-interconnect", },
{ .compatible = "fsl,imx8mp-noc", .data = "imx8mp-interconnect", },
{ .compatible = "fsl,imx8m-noc", }, { .compatible = "fsl,imx8m-noc", },
{ .compatible = "fsl,imx8m-nic", }, { .compatible = "fsl,imx8m-nic", },
{ /* sentinel */ }, { /* sentinel */ },

View File

@ -115,3 +115,45 @@ void icc_bulk_disable(int num_paths, const struct icc_bulk_data *paths)
icc_disable(paths[num_paths].path); icc_disable(paths[num_paths].path);
} }
EXPORT_SYMBOL_GPL(icc_bulk_disable); EXPORT_SYMBOL_GPL(icc_bulk_disable);
struct icc_bulk_devres {
struct icc_bulk_data *paths;
int num_paths;
};
static void devm_icc_bulk_release(struct device *dev, void *res)
{
struct icc_bulk_devres *devres = res;
icc_bulk_put(devres->num_paths, devres->paths);
}
/**
* devm_of_icc_bulk_get() - resource managed of_icc_bulk_get
* @dev: the device requesting the path
* @num_paths: the number of icc_bulk_data
* @paths: the table with the paths we want to get
*
* Returns 0 on success or negative errno otherwise.
*/
int devm_of_icc_bulk_get(struct device *dev, int num_paths, struct icc_bulk_data *paths)
{
struct icc_bulk_devres *devres;
int ret;
devres = devres_alloc(devm_icc_bulk_release, sizeof(*devres), GFP_KERNEL);
if (!devres)
return -ENOMEM;
ret = of_icc_bulk_get(dev, num_paths, paths);
if (!ret) {
devres->paths = paths;
devres->num_paths = num_paths;
devres_add(dev, devres);
} else {
devres_free(devres);
}
return ret;
}
EXPORT_SYMBOL_GPL(devm_of_icc_bulk_get);

View File

@ -15,3 +15,7 @@ config INTERCONNECT_IMX8MN
config INTERCONNECT_IMX8MQ config INTERCONNECT_IMX8MQ
tristate "i.MX8MQ interconnect driver" tristate "i.MX8MQ interconnect driver"
depends on INTERCONNECT_IMX depends on INTERCONNECT_IMX
config INTERCONNECT_IMX8MP
tristate "i.MX8MP interconnect driver"
depends on INTERCONNECT_IMX

View File

@ -2,8 +2,10 @@ imx-interconnect-objs := imx.o
imx8mm-interconnect-objs := imx8mm.o imx8mm-interconnect-objs := imx8mm.o
imx8mq-interconnect-objs := imx8mq.o imx8mq-interconnect-objs := imx8mq.o
imx8mn-interconnect-objs := imx8mn.o imx8mn-interconnect-objs := imx8mn.o
imx8mp-interconnect-objs := imx8mp.o
obj-$(CONFIG_INTERCONNECT_IMX) += imx-interconnect.o obj-$(CONFIG_INTERCONNECT_IMX) += imx-interconnect.o
obj-$(CONFIG_INTERCONNECT_IMX8MM) += imx8mm-interconnect.o obj-$(CONFIG_INTERCONNECT_IMX8MM) += imx8mm-interconnect.o
obj-$(CONFIG_INTERCONNECT_IMX8MQ) += imx8mq-interconnect.o obj-$(CONFIG_INTERCONNECT_IMX8MQ) += imx8mq-interconnect.o
obj-$(CONFIG_INTERCONNECT_IMX8MN) += imx8mn-interconnect.o obj-$(CONFIG_INTERCONNECT_IMX8MN) += imx8mn-interconnect.o
obj-$(CONFIG_INTERCONNECT_IMX8MP) += imx8mp-interconnect.o

View File

@ -10,6 +10,7 @@
#include <linux/device.h> #include <linux/device.h>
#include <linux/interconnect-provider.h> #include <linux/interconnect-provider.h>
#include <linux/io.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_platform.h> #include <linux/of_platform.h>
@ -21,8 +22,10 @@
/* private icc_node data */ /* private icc_node data */
struct imx_icc_node { struct imx_icc_node {
const struct imx_icc_node_desc *desc; const struct imx_icc_node_desc *desc;
const struct imx_icc_noc_setting *setting;
struct device *qos_dev; struct device *qos_dev;
struct dev_pm_qos_request qos_req; struct dev_pm_qos_request qos_req;
struct imx_icc_provider *imx_provider;
}; };
static int imx_icc_get_bw(struct icc_node *node, u32 *avg, u32 *peak) static int imx_icc_get_bw(struct icc_node *node, u32 *avg, u32 *peak)
@ -37,8 +40,30 @@ static int imx_icc_node_set(struct icc_node *node)
{ {
struct device *dev = node->provider->dev; struct device *dev = node->provider->dev;
struct imx_icc_node *node_data = node->data; struct imx_icc_node *node_data = node->data;
void __iomem *base;
u32 prio;
u64 freq; u64 freq;
if (node_data->setting && node->peak_bw) {
base = node_data->setting->reg + node_data->imx_provider->noc_base;
if (node_data->setting->mode == IMX_NOC_MODE_FIXED) {
prio = node_data->setting->prio_level;
prio = PRIORITY_COMP_MARK | (prio << 8) | prio;
writel(prio, base + IMX_NOC_PRIO_REG);
writel(node_data->setting->mode, base + IMX_NOC_MODE_REG);
writel(node_data->setting->ext_control, base + IMX_NOC_EXT_CTL_REG);
dev_dbg(dev, "%s: mode: 0x%x, prio: 0x%x, ext_control: 0x%x\n",
node_data->desc->name, node_data->setting->mode, prio,
node_data->setting->ext_control);
} else if (node_data->setting->mode == IMX_NOC_MODE_UNCONFIGURED) {
dev_dbg(dev, "%s: mode not unconfigured\n", node_data->desc->name);
} else {
dev_info(dev, "%s: mode: %d not supported\n",
node_data->desc->name, node_data->setting->mode);
return -EOPNOTSUPP;
}
}
if (!node_data->qos_dev) if (!node_data->qos_dev)
return 0; return 0;
@ -61,6 +86,12 @@ static int imx_icc_node_set(struct icc_node *node)
static int imx_icc_set(struct icc_node *src, struct icc_node *dst) static int imx_icc_set(struct icc_node *src, struct icc_node *dst)
{ {
int ret;
ret = imx_icc_node_set(src);
if (ret)
return ret;
return imx_icc_node_set(dst); return imx_icc_node_set(dst);
} }
@ -128,9 +159,11 @@ static int imx_icc_node_init_qos(struct icc_provider *provider,
DEV_PM_QOS_MIN_FREQUENCY, 0); DEV_PM_QOS_MIN_FREQUENCY, 0);
} }
static struct icc_node *imx_icc_node_add(struct icc_provider *provider, static struct icc_node *imx_icc_node_add(struct imx_icc_provider *imx_provider,
const struct imx_icc_node_desc *node_desc) const struct imx_icc_node_desc *node_desc,
const struct imx_icc_noc_setting *setting)
{ {
struct icc_provider *provider = &imx_provider->provider;
struct device *dev = provider->dev; struct device *dev = provider->dev;
struct imx_icc_node *node_data; struct imx_icc_node *node_data;
struct icc_node *node; struct icc_node *node;
@ -157,6 +190,8 @@ static struct icc_node *imx_icc_node_add(struct icc_provider *provider,
node->name = node_desc->name; node->name = node_desc->name;
node->data = node_data; node->data = node_data;
node_data->desc = node_desc; node_data->desc = node_desc;
node_data->setting = setting;
node_data->imx_provider = imx_provider;
icc_node_add(node, provider); icc_node_add(node, provider);
if (node_desc->adj) { if (node_desc->adj) {
@ -178,10 +213,12 @@ static void imx_icc_unregister_nodes(struct icc_provider *provider)
imx_icc_node_destroy(node); imx_icc_node_destroy(node);
} }
static int imx_icc_register_nodes(struct icc_provider *provider, static int imx_icc_register_nodes(struct imx_icc_provider *imx_provider,
const struct imx_icc_node_desc *descs, const struct imx_icc_node_desc *descs,
int count) int count,
const struct imx_icc_noc_setting *settings)
{ {
struct icc_provider *provider = &imx_provider->provider;
struct icc_onecell_data *provider_data = provider->data; struct icc_onecell_data *provider_data = provider->data;
int ret; int ret;
int i; int i;
@ -191,7 +228,8 @@ static int imx_icc_register_nodes(struct icc_provider *provider,
const struct imx_icc_node_desc *node_desc = &descs[i]; const struct imx_icc_node_desc *node_desc = &descs[i];
size_t j; size_t j;
node = imx_icc_node_add(provider, node_desc); node = imx_icc_node_add(imx_provider, node_desc,
settings ? &settings[node_desc->id] : NULL);
if (IS_ERR(node)) { if (IS_ERR(node)) {
ret = dev_err_probe(provider->dev, PTR_ERR(node), ret = dev_err_probe(provider->dev, PTR_ERR(node),
"failed to add %s\n", node_desc->name); "failed to add %s\n", node_desc->name);
@ -229,32 +267,44 @@ static int get_max_node_id(struct imx_icc_node_desc *nodes, int nodes_count)
} }
int imx_icc_register(struct platform_device *pdev, int imx_icc_register(struct platform_device *pdev,
struct imx_icc_node_desc *nodes, int nodes_count) struct imx_icc_node_desc *nodes, int nodes_count,
struct imx_icc_noc_setting *settings)
{ {
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct icc_onecell_data *data; struct icc_onecell_data *data;
struct imx_icc_provider *imx_provider;
struct icc_provider *provider; struct icc_provider *provider;
int max_node_id; int num_nodes;
int ret; int ret;
/* icc_onecell_data is indexed by node_id, unlike nodes param */ /* icc_onecell_data is indexed by node_id, unlike nodes param */
max_node_id = get_max_node_id(nodes, nodes_count); num_nodes = get_max_node_id(nodes, nodes_count) + 1;
data = devm_kzalloc(dev, struct_size(data, nodes, max_node_id), data = devm_kzalloc(dev, struct_size(data, nodes, num_nodes),
GFP_KERNEL); GFP_KERNEL);
if (!data) if (!data)
return -ENOMEM; return -ENOMEM;
data->num_nodes = max_node_id; data->num_nodes = num_nodes;
provider = devm_kzalloc(dev, sizeof(*provider), GFP_KERNEL); imx_provider = devm_kzalloc(dev, sizeof(*imx_provider), GFP_KERNEL);
if (!provider) if (!imx_provider)
return -ENOMEM; return -ENOMEM;
provider = &imx_provider->provider;
provider->set = imx_icc_set; provider->set = imx_icc_set;
provider->get_bw = imx_icc_get_bw; provider->get_bw = imx_icc_get_bw;
provider->aggregate = icc_std_aggregate; provider->aggregate = icc_std_aggregate;
provider->xlate = of_icc_xlate_onecell; provider->xlate = of_icc_xlate_onecell;
provider->data = data; provider->data = data;
provider->dev = dev->parent; provider->dev = dev->parent;
platform_set_drvdata(pdev, provider); platform_set_drvdata(pdev, imx_provider);
if (settings) {
imx_provider->noc_base = devm_of_iomap(dev, provider->dev->of_node, 0, NULL);
if (IS_ERR(imx_provider->noc_base)) {
ret = PTR_ERR(imx_provider->noc_base);
dev_err(dev, "Error mapping NoC: %d\n", ret);
return ret;
}
}
ret = icc_provider_add(provider); ret = icc_provider_add(provider);
if (ret) { if (ret) {
@ -262,7 +312,7 @@ int imx_icc_register(struct platform_device *pdev,
return ret; return ret;
} }
ret = imx_icc_register_nodes(provider, nodes, nodes_count); ret = imx_icc_register_nodes(imx_provider, nodes, nodes_count, settings);
if (ret) if (ret)
goto provider_del; goto provider_del;
@ -276,11 +326,11 @@ EXPORT_SYMBOL_GPL(imx_icc_register);
int imx_icc_unregister(struct platform_device *pdev) int imx_icc_unregister(struct platform_device *pdev)
{ {
struct icc_provider *provider = platform_get_drvdata(pdev); struct imx_icc_provider *imx_provider = platform_get_drvdata(pdev);
imx_icc_unregister_nodes(provider); imx_icc_unregister_nodes(&imx_provider->provider);
return icc_provider_del(provider); return icc_provider_del(&imx_provider->provider);
} }
EXPORT_SYMBOL_GPL(imx_icc_unregister); EXPORT_SYMBOL_GPL(imx_icc_unregister);

View File

@ -10,10 +10,42 @@
#ifndef __DRIVERS_INTERCONNECT_IMX_H #ifndef __DRIVERS_INTERCONNECT_IMX_H
#define __DRIVERS_INTERCONNECT_IMX_H #define __DRIVERS_INTERCONNECT_IMX_H
#include <linux/interconnect-provider.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#define IMX_ICC_MAX_LINKS 4 #define IMX_ICC_MAX_LINKS 4
/*
* High throughput priority level in Regulator mode
* Read Priority in Fixed/Limiter mode
*/
#define PRIORITY0_SHIFT 0
/*
* Low throughput priority level in Regulator mode
* Write Priority in Fixed/Limiter mode
*/
#define PRIORITY1_SHIFT 8
#define PRIORITY_MASK 0x7
#define PRIORITY_COMP_MARK BIT(31) /* Must set */
#define IMX_NOC_MODE_FIXED 0
#define IMX_NOC_MODE_LIMITER 1
#define IMX_NOC_MODE_BYPASS 2
#define IMX_NOC_MODE_REGULATOR 3
#define IMX_NOC_MODE_UNCONFIGURED 0xFF
#define IMX_NOC_PRIO_REG 0x8
#define IMX_NOC_MODE_REG 0xC
#define IMX_NOC_BANDWIDTH_REG 0x10
#define IMX_NOC_SATURATION 0x14
#define IMX_NOC_EXT_CTL_REG 0x18
struct imx_icc_provider {
void __iomem *noc_base;
struct icc_provider provider;
};
/* /*
* struct imx_icc_node_adj - Describe a dynamic adjustable node * struct imx_icc_node_adj - Describe a dynamic adjustable node
*/ */
@ -38,6 +70,20 @@ struct imx_icc_node_desc {
const struct imx_icc_node_adj_desc *adj; const struct imx_icc_node_adj_desc *adj;
}; };
/*
* struct imx_icc_noc_setting - Describe an interconnect node setting
* @reg: register offset inside the NoC
* @prio_level: priority level
* @mode: functional mode
* @ext_control: external input control
*/
struct imx_icc_noc_setting {
u32 reg;
u32 prio_level;
u32 mode;
u32 ext_control;
};
#define DEFINE_BUS_INTERCONNECT(_name, _id, _adj, ...) \ #define DEFINE_BUS_INTERCONNECT(_name, _id, _adj, ...) \
{ \ { \
.id = _id, \ .id = _id, \
@ -55,7 +101,8 @@ struct imx_icc_node_desc {
int imx_icc_register(struct platform_device *pdev, int imx_icc_register(struct platform_device *pdev,
struct imx_icc_node_desc *nodes, struct imx_icc_node_desc *nodes,
int nodes_count); int nodes_count,
struct imx_icc_noc_setting *noc_settings);
int imx_icc_unregister(struct platform_device *pdev); int imx_icc_unregister(struct platform_device *pdev);
#endif /* __DRIVERS_INTERCONNECT_IMX_H */ #endif /* __DRIVERS_INTERCONNECT_IMX_H */

View File

@ -83,7 +83,7 @@ static struct imx_icc_node_desc nodes[] = {
static int imx8mm_icc_probe(struct platform_device *pdev) static int imx8mm_icc_probe(struct platform_device *pdev)
{ {
return imx_icc_register(pdev, nodes, ARRAY_SIZE(nodes)); return imx_icc_register(pdev, nodes, ARRAY_SIZE(nodes), NULL);
} }
static int imx8mm_icc_remove(struct platform_device *pdev) static int imx8mm_icc_remove(struct platform_device *pdev)

View File

@ -72,7 +72,7 @@ static struct imx_icc_node_desc nodes[] = {
static int imx8mn_icc_probe(struct platform_device *pdev) static int imx8mn_icc_probe(struct platform_device *pdev)
{ {
return imx_icc_register(pdev, nodes, ARRAY_SIZE(nodes)); return imx_icc_register(pdev, nodes, ARRAY_SIZE(nodes), NULL);
} }
static int imx8mn_icc_remove(struct platform_device *pdev) static int imx8mn_icc_remove(struct platform_device *pdev)

View File

@ -0,0 +1,259 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Interconnect framework driver for i.MX8MP SoC
*
* Copyright 2022 NXP
* Peng Fan <peng.fan@nxp.com>
*/
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <dt-bindings/interconnect/fsl,imx8mp.h>
#include "imx.h"
static const struct imx_icc_node_adj_desc imx8mp_noc_adj = {
.bw_mul = 1,
.bw_div = 16,
.main_noc = true,
};
static struct imx_icc_noc_setting noc_setting_nodes[] = {
[IMX8MP_ICM_MLMIX] = {
.reg = 0x180,
.mode = IMX_NOC_MODE_FIXED,
.prio_level = 3,
},
[IMX8MP_ICM_DSP] = {
.reg = 0x200,
.mode = IMX_NOC_MODE_FIXED,
.prio_level = 3,
},
[IMX8MP_ICM_SDMA2PER] = {
.reg = 0x280,
.mode = IMX_NOC_MODE_FIXED,
.prio_level = 4,
},
[IMX8MP_ICM_SDMA2BURST] = {
.reg = 0x300,
.mode = IMX_NOC_MODE_FIXED,
.prio_level = 4,
},
[IMX8MP_ICM_SDMA3PER] = {
.reg = 0x380,
.mode = IMX_NOC_MODE_FIXED,
.prio_level = 4,
},
[IMX8MP_ICM_SDMA3BURST] = {
.reg = 0x400,
.mode = IMX_NOC_MODE_FIXED,
.prio_level = 4,
},
[IMX8MP_ICM_EDMA] = {
.reg = 0x480,
.mode = IMX_NOC_MODE_FIXED,
.prio_level = 4,
},
[IMX8MP_ICM_GPU3D] = {
.reg = 0x500,
.mode = IMX_NOC_MODE_FIXED,
.prio_level = 3,
},
[IMX8MP_ICM_GPU2D] = {
.reg = 0x580,
.mode = IMX_NOC_MODE_FIXED,
.prio_level = 3,
},
[IMX8MP_ICM_HRV] = {
.reg = 0x600,
.mode = IMX_NOC_MODE_FIXED,
.prio_level = 2,
.ext_control = 1,
},
[IMX8MP_ICM_LCDIF_HDMI] = {
.reg = 0x680,
.mode = IMX_NOC_MODE_FIXED,
.prio_level = 2,
.ext_control = 1,
},
[IMX8MP_ICM_HDCP] = {
.reg = 0x700,
.mode = IMX_NOC_MODE_FIXED,
.prio_level = 5,
},
[IMX8MP_ICM_NOC_PCIE] = {
.reg = 0x780,
.mode = IMX_NOC_MODE_FIXED,
.prio_level = 3,
},
[IMX8MP_ICM_USB1] = {
.reg = 0x800,
.mode = IMX_NOC_MODE_FIXED,
.prio_level = 3,
},
[IMX8MP_ICM_USB2] = {
.reg = 0x880,
.mode = IMX_NOC_MODE_FIXED,
.prio_level = 3,
},
[IMX8MP_ICM_PCIE] = {
.reg = 0x900,
.mode = IMX_NOC_MODE_FIXED,
.prio_level = 3,
},
[IMX8MP_ICM_LCDIF_RD] = {
.reg = 0x980,
.mode = IMX_NOC_MODE_FIXED,
.prio_level = 2,
.ext_control = 1,
},
[IMX8MP_ICM_LCDIF_WR] = {
.reg = 0xa00,
.mode = IMX_NOC_MODE_FIXED,
.prio_level = 2,
.ext_control = 1,
},
[IMX8MP_ICM_ISI0] = {
.reg = 0xa80,
.mode = IMX_NOC_MODE_FIXED,
.prio_level = 2,
.ext_control = 1,
},
[IMX8MP_ICM_ISI1] = {
.reg = 0xb00,
.mode = IMX_NOC_MODE_FIXED,
.prio_level = 2,
.ext_control = 1,
},
[IMX8MP_ICM_ISI2] = {
.reg = 0xb80,
.mode = IMX_NOC_MODE_FIXED,
.prio_level = 2,
.ext_control = 1,
},
[IMX8MP_ICM_ISP0] = {
.reg = 0xc00,
.mode = IMX_NOC_MODE_FIXED,
.prio_level = 7,
},
[IMX8MP_ICM_ISP1] = {
.reg = 0xc80,
.mode = IMX_NOC_MODE_FIXED,
.prio_level = 7,
},
[IMX8MP_ICM_DWE] = {
.reg = 0xd00,
.mode = IMX_NOC_MODE_FIXED,
.prio_level = 7,
},
[IMX8MP_ICM_VPU_G1] = {
.reg = 0xd80,
.mode = IMX_NOC_MODE_FIXED,
.prio_level = 3,
},
[IMX8MP_ICM_VPU_G2] = {
.reg = 0xe00,
.mode = IMX_NOC_MODE_FIXED,
.prio_level = 3,
},
[IMX8MP_ICM_VPU_H1] = {
.reg = 0xe80,
.mode = IMX_NOC_MODE_FIXED,
.prio_level = 3,
},
[IMX8MP_ICN_MEDIA] = {
.mode = IMX_NOC_MODE_UNCONFIGURED,
},
[IMX8MP_ICN_VIDEO] = {
.mode = IMX_NOC_MODE_UNCONFIGURED,
},
[IMX8MP_ICN_AUDIO] = {
.mode = IMX_NOC_MODE_UNCONFIGURED,
},
[IMX8MP_ICN_HDMI] = {
.mode = IMX_NOC_MODE_UNCONFIGURED,
},
[IMX8MP_ICN_GPU] = {
.mode = IMX_NOC_MODE_UNCONFIGURED,
},
[IMX8MP_ICN_HSIO] = {
.mode = IMX_NOC_MODE_UNCONFIGURED,
},
};
/* Describe bus masters, slaves and connections between them */
static struct imx_icc_node_desc nodes[] = {
DEFINE_BUS_INTERCONNECT("NOC", IMX8MP_ICN_NOC, &imx8mp_noc_adj,
IMX8MP_ICS_DRAM, IMX8MP_ICN_MAIN),
DEFINE_BUS_SLAVE("OCRAM", IMX8MP_ICS_OCRAM, NULL),
DEFINE_BUS_SLAVE("DRAM", IMX8MP_ICS_DRAM, NULL),
DEFINE_BUS_MASTER("A53", IMX8MP_ICM_A53, IMX8MP_ICN_NOC),
DEFINE_BUS_MASTER("SUPERMIX", IMX8MP_ICM_SUPERMIX, IMX8MP_ICN_NOC),
DEFINE_BUS_MASTER("GIC", IMX8MP_ICM_GIC, IMX8MP_ICN_NOC),
DEFINE_BUS_MASTER("MLMIX", IMX8MP_ICM_MLMIX, IMX8MP_ICN_NOC),
DEFINE_BUS_INTERCONNECT("NOC_AUDIO", IMX8MP_ICN_AUDIO, NULL, IMX8MP_ICN_NOC),
DEFINE_BUS_MASTER("DSP", IMX8MP_ICM_DSP, IMX8MP_ICN_AUDIO),
DEFINE_BUS_MASTER("SDMA2PER", IMX8MP_ICM_SDMA2PER, IMX8MP_ICN_AUDIO),
DEFINE_BUS_MASTER("SDMA2BURST", IMX8MP_ICM_SDMA2BURST, IMX8MP_ICN_AUDIO),
DEFINE_BUS_MASTER("SDMA3PER", IMX8MP_ICM_SDMA3PER, IMX8MP_ICN_AUDIO),
DEFINE_BUS_MASTER("SDMA3BURST", IMX8MP_ICM_SDMA3BURST, IMX8MP_ICN_AUDIO),
DEFINE_BUS_MASTER("EDMA", IMX8MP_ICM_EDMA, IMX8MP_ICN_AUDIO),
DEFINE_BUS_INTERCONNECT("NOC_GPU", IMX8MP_ICN_GPU, NULL, IMX8MP_ICN_NOC),
DEFINE_BUS_MASTER("GPU 2D", IMX8MP_ICM_GPU2D, IMX8MP_ICN_GPU),
DEFINE_BUS_MASTER("GPU 3D", IMX8MP_ICM_GPU3D, IMX8MP_ICN_GPU),
DEFINE_BUS_INTERCONNECT("NOC_HDMI", IMX8MP_ICN_HDMI, NULL, IMX8MP_ICN_NOC),
DEFINE_BUS_MASTER("HRV", IMX8MP_ICM_HRV, IMX8MP_ICN_HDMI),
DEFINE_BUS_MASTER("LCDIF_HDMI", IMX8MP_ICM_LCDIF_HDMI, IMX8MP_ICN_HDMI),
DEFINE_BUS_MASTER("HDCP", IMX8MP_ICM_HDCP, IMX8MP_ICN_HDMI),
DEFINE_BUS_INTERCONNECT("NOC_HSIO", IMX8MP_ICN_HSIO, NULL, IMX8MP_ICN_NOC),
DEFINE_BUS_MASTER("NOC_PCIE", IMX8MP_ICM_NOC_PCIE, IMX8MP_ICN_HSIO),
DEFINE_BUS_MASTER("USB1", IMX8MP_ICM_USB1, IMX8MP_ICN_HSIO),
DEFINE_BUS_MASTER("USB2", IMX8MP_ICM_USB2, IMX8MP_ICN_HSIO),
DEFINE_BUS_MASTER("PCIE", IMX8MP_ICM_PCIE, IMX8MP_ICN_HSIO),
DEFINE_BUS_INTERCONNECT("NOC_MEDIA", IMX8MP_ICN_MEDIA, NULL, IMX8MP_ICN_NOC),
DEFINE_BUS_MASTER("LCDIF_RD", IMX8MP_ICM_LCDIF_RD, IMX8MP_ICN_MEDIA),
DEFINE_BUS_MASTER("LCDIF_WR", IMX8MP_ICM_LCDIF_WR, IMX8MP_ICN_MEDIA),
DEFINE_BUS_MASTER("ISI0", IMX8MP_ICM_ISI0, IMX8MP_ICN_MEDIA),
DEFINE_BUS_MASTER("ISI1", IMX8MP_ICM_ISI1, IMX8MP_ICN_MEDIA),
DEFINE_BUS_MASTER("ISI2", IMX8MP_ICM_ISI2, IMX8MP_ICN_MEDIA),
DEFINE_BUS_MASTER("ISP0", IMX8MP_ICM_ISP0, IMX8MP_ICN_MEDIA),
DEFINE_BUS_MASTER("ISP1", IMX8MP_ICM_ISP1, IMX8MP_ICN_MEDIA),
DEFINE_BUS_MASTER("DWE", IMX8MP_ICM_DWE, IMX8MP_ICN_MEDIA),
DEFINE_BUS_INTERCONNECT("NOC_VIDEO", IMX8MP_ICN_VIDEO, NULL, IMX8MP_ICN_NOC),
DEFINE_BUS_MASTER("VPU G1", IMX8MP_ICM_VPU_G1, IMX8MP_ICN_VIDEO),
DEFINE_BUS_MASTER("VPU G2", IMX8MP_ICM_VPU_G2, IMX8MP_ICN_VIDEO),
DEFINE_BUS_MASTER("VPU H1", IMX8MP_ICM_VPU_H1, IMX8MP_ICN_VIDEO),
DEFINE_BUS_INTERCONNECT("PL301_MAIN", IMX8MP_ICN_MAIN, NULL,
IMX8MP_ICN_NOC, IMX8MP_ICS_OCRAM),
};
static int imx8mp_icc_probe(struct platform_device *pdev)
{
return imx_icc_register(pdev, nodes, ARRAY_SIZE(nodes), noc_setting_nodes);
}
static int imx8mp_icc_remove(struct platform_device *pdev)
{
return imx_icc_unregister(pdev);
}
static struct platform_driver imx8mp_icc_driver = {
.probe = imx8mp_icc_probe,
.remove = imx8mp_icc_remove,
.driver = {
.name = "imx8mp-interconnect",
},
};
module_platform_driver(imx8mp_icc_driver);
MODULE_AUTHOR("Peng Fan <peng.fan@nxp.com>");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:imx8mp-interconnect");

View File

@ -82,7 +82,7 @@ static struct imx_icc_node_desc nodes[] = {
static int imx8mq_icc_probe(struct platform_device *pdev) static int imx8mq_icc_probe(struct platform_device *pdev)
{ {
return imx_icc_register(pdev, nodes, ARRAY_SIZE(nodes)); return imx_icc_register(pdev, nodes, ARRAY_SIZE(nodes), NULL);
} }
static int imx8mq_icc_remove(struct platform_device *pdev) static int imx8mq_icc_remove(struct platform_device *pdev)

View File

@ -0,0 +1,59 @@
/* SPDX-License-Identifier: GPL-2.0 OR MIT */
/*
* Interconnect framework driver for i.MX SoC
*
* Copyright 2022 NXP
* Peng Fan <peng.fan@nxp.com>
*/
#ifndef __DT_BINDINGS_INTERCONNECT_IMX8MP_H
#define __DT_BINDINGS_INTERCONNECT_IMX8MP_H
#define IMX8MP_ICN_NOC 0
#define IMX8MP_ICN_MAIN 1
#define IMX8MP_ICS_DRAM 2
#define IMX8MP_ICS_OCRAM 3
#define IMX8MP_ICM_A53 4
#define IMX8MP_ICM_SUPERMIX 5
#define IMX8MP_ICM_GIC 6
#define IMX8MP_ICM_MLMIX 7
#define IMX8MP_ICN_AUDIO 8
#define IMX8MP_ICM_DSP 9
#define IMX8MP_ICM_SDMA2PER 10
#define IMX8MP_ICM_SDMA2BURST 11
#define IMX8MP_ICM_SDMA3PER 12
#define IMX8MP_ICM_SDMA3BURST 13
#define IMX8MP_ICM_EDMA 14
#define IMX8MP_ICN_GPU 15
#define IMX8MP_ICM_GPU2D 16
#define IMX8MP_ICM_GPU3D 17
#define IMX8MP_ICN_HDMI 18
#define IMX8MP_ICM_HRV 19
#define IMX8MP_ICM_LCDIF_HDMI 20
#define IMX8MP_ICM_HDCP 21
#define IMX8MP_ICN_HSIO 22
#define IMX8MP_ICM_NOC_PCIE 23
#define IMX8MP_ICM_USB1 24
#define IMX8MP_ICM_USB2 25
#define IMX8MP_ICM_PCIE 26
#define IMX8MP_ICN_MEDIA 27
#define IMX8MP_ICM_LCDIF_RD 28
#define IMX8MP_ICM_LCDIF_WR 29
#define IMX8MP_ICM_ISI0 30
#define IMX8MP_ICM_ISI1 31
#define IMX8MP_ICM_ISI2 32
#define IMX8MP_ICM_ISP0 33
#define IMX8MP_ICM_ISP1 34
#define IMX8MP_ICM_DWE 35
#define IMX8MP_ICN_VIDEO 36
#define IMX8MP_ICM_VPU_G1 37
#define IMX8MP_ICM_VPU_G2 38
#define IMX8MP_ICM_VPU_H1 39
#endif /* __DT_BINDINGS_INTERCONNECT_IMX8MP_H */

View File

@ -44,6 +44,7 @@ struct icc_path *icc_get(struct device *dev, const int src_id,
const int dst_id); const int dst_id);
struct icc_path *of_icc_get(struct device *dev, const char *name); struct icc_path *of_icc_get(struct device *dev, const char *name);
struct icc_path *devm_of_icc_get(struct device *dev, const char *name); struct icc_path *devm_of_icc_get(struct device *dev, const char *name);
int devm_of_icc_bulk_get(struct device *dev, int num_paths, struct icc_bulk_data *paths);
struct icc_path *of_icc_get_by_index(struct device *dev, int idx); struct icc_path *of_icc_get_by_index(struct device *dev, int idx);
void icc_put(struct icc_path *path); void icc_put(struct icc_path *path);
int icc_enable(struct icc_path *path); int icc_enable(struct icc_path *path);
@ -116,6 +117,12 @@ static inline int of_icc_bulk_get(struct device *dev, int num_paths, struct icc_
return 0; return 0;
} }
static inline int devm_of_icc_bulk_get(struct device *dev, int num_paths,
struct icc_bulk_data *paths)
{
return 0;
}
static inline void icc_bulk_put(int num_paths, struct icc_bulk_data *paths) static inline void icc_bulk_put(int num_paths, struct icc_bulk_data *paths)
{ {
} }