forked from Minki/linux
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:
commit
33f033dc30
@ -26,14 +26,16 @@ properties:
|
||||
oneOf:
|
||||
- items:
|
||||
- enum:
|
||||
- fsl,imx8mn-nic
|
||||
- fsl,imx8mm-nic
|
||||
- fsl,imx8mn-nic
|
||||
- fsl,imx8mp-nic
|
||||
- fsl,imx8mq-nic
|
||||
- const: fsl,imx8m-nic
|
||||
- items:
|
||||
- enum:
|
||||
- fsl,imx8mn-noc
|
||||
- fsl,imx8mm-noc
|
||||
- fsl,imx8mn-noc
|
||||
- fsl,imx8mp-noc
|
||||
- fsl,imx8mq-noc
|
||||
- const: fsl,imx8m-noc
|
||||
- const: fsl,imx8m-nic
|
||||
|
@ -145,6 +145,7 @@ static const struct of_device_id imx_bus_of_match[] = {
|
||||
{ .compatible = "fsl,imx8mq-noc", .data = "imx8mq-interconnect", },
|
||||
{ .compatible = "fsl,imx8mm-noc", .data = "imx8mm-interconnect", },
|
||||
{ .compatible = "fsl,imx8mn-noc", .data = "imx8mn-interconnect", },
|
||||
{ .compatible = "fsl,imx8mp-noc", .data = "imx8mp-interconnect", },
|
||||
{ .compatible = "fsl,imx8m-noc", },
|
||||
{ .compatible = "fsl,imx8m-nic", },
|
||||
{ /* sentinel */ },
|
||||
|
@ -115,3 +115,45 @@ void icc_bulk_disable(int num_paths, const struct icc_bulk_data *paths)
|
||||
icc_disable(paths[num_paths].path);
|
||||
}
|
||||
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);
|
||||
|
@ -15,3 +15,7 @@ config INTERCONNECT_IMX8MN
|
||||
config INTERCONNECT_IMX8MQ
|
||||
tristate "i.MX8MQ interconnect driver"
|
||||
depends on INTERCONNECT_IMX
|
||||
|
||||
config INTERCONNECT_IMX8MP
|
||||
tristate "i.MX8MP interconnect driver"
|
||||
depends on INTERCONNECT_IMX
|
||||
|
@ -2,8 +2,10 @@ imx-interconnect-objs := imx.o
|
||||
imx8mm-interconnect-objs := imx8mm.o
|
||||
imx8mq-interconnect-objs := imx8mq.o
|
||||
imx8mn-interconnect-objs := imx8mn.o
|
||||
imx8mp-interconnect-objs := imx8mp.o
|
||||
|
||||
obj-$(CONFIG_INTERCONNECT_IMX) += imx-interconnect.o
|
||||
obj-$(CONFIG_INTERCONNECT_IMX8MM) += imx8mm-interconnect.o
|
||||
obj-$(CONFIG_INTERCONNECT_IMX8MQ) += imx8mq-interconnect.o
|
||||
obj-$(CONFIG_INTERCONNECT_IMX8MN) += imx8mn-interconnect.o
|
||||
obj-$(CONFIG_INTERCONNECT_IMX8MP) += imx8mp-interconnect.o
|
||||
|
@ -10,6 +10,7 @@
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/interconnect-provider.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_platform.h>
|
||||
@ -21,8 +22,10 @@
|
||||
/* private icc_node data */
|
||||
struct imx_icc_node {
|
||||
const struct imx_icc_node_desc *desc;
|
||||
const struct imx_icc_noc_setting *setting;
|
||||
struct device *qos_dev;
|
||||
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)
|
||||
@ -37,8 +40,30 @@ static int imx_icc_node_set(struct icc_node *node)
|
||||
{
|
||||
struct device *dev = node->provider->dev;
|
||||
struct imx_icc_node *node_data = node->data;
|
||||
void __iomem *base;
|
||||
u32 prio;
|
||||
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)
|
||||
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)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = imx_icc_node_set(src);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
static struct icc_node *imx_icc_node_add(struct icc_provider *provider,
|
||||
const struct imx_icc_node_desc *node_desc)
|
||||
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_noc_setting *setting)
|
||||
{
|
||||
struct icc_provider *provider = &imx_provider->provider;
|
||||
struct device *dev = provider->dev;
|
||||
struct imx_icc_node *node_data;
|
||||
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->data = node_data;
|
||||
node_data->desc = node_desc;
|
||||
node_data->setting = setting;
|
||||
node_data->imx_provider = imx_provider;
|
||||
icc_node_add(node, provider);
|
||||
|
||||
if (node_desc->adj) {
|
||||
@ -178,10 +213,12 @@ static void imx_icc_unregister_nodes(struct icc_provider *provider)
|
||||
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,
|
||||
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;
|
||||
int ret;
|
||||
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];
|
||||
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)) {
|
||||
ret = dev_err_probe(provider->dev, PTR_ERR(node),
|
||||
"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,
|
||||
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 icc_onecell_data *data;
|
||||
struct imx_icc_provider *imx_provider;
|
||||
struct icc_provider *provider;
|
||||
int max_node_id;
|
||||
int num_nodes;
|
||||
int ret;
|
||||
|
||||
/* icc_onecell_data is indexed by node_id, unlike nodes param */
|
||||
max_node_id = get_max_node_id(nodes, nodes_count);
|
||||
data = devm_kzalloc(dev, struct_size(data, nodes, max_node_id),
|
||||
num_nodes = get_max_node_id(nodes, nodes_count) + 1;
|
||||
data = devm_kzalloc(dev, struct_size(data, nodes, num_nodes),
|
||||
GFP_KERNEL);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
data->num_nodes = max_node_id;
|
||||
data->num_nodes = num_nodes;
|
||||
|
||||
provider = devm_kzalloc(dev, sizeof(*provider), GFP_KERNEL);
|
||||
if (!provider)
|
||||
imx_provider = devm_kzalloc(dev, sizeof(*imx_provider), GFP_KERNEL);
|
||||
if (!imx_provider)
|
||||
return -ENOMEM;
|
||||
provider = &imx_provider->provider;
|
||||
provider->set = imx_icc_set;
|
||||
provider->get_bw = imx_icc_get_bw;
|
||||
provider->aggregate = icc_std_aggregate;
|
||||
provider->xlate = of_icc_xlate_onecell;
|
||||
provider->data = data;
|
||||
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);
|
||||
if (ret) {
|
||||
@ -262,7 +312,7 @@ int imx_icc_register(struct platform_device *pdev,
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = imx_icc_register_nodes(provider, nodes, nodes_count);
|
||||
ret = imx_icc_register_nodes(imx_provider, nodes, nodes_count, settings);
|
||||
if (ret)
|
||||
goto provider_del;
|
||||
|
||||
@ -276,11 +326,11 @@ EXPORT_SYMBOL_GPL(imx_icc_register);
|
||||
|
||||
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);
|
||||
|
||||
|
@ -10,10 +10,42 @@
|
||||
#ifndef __DRIVERS_INTERCONNECT_IMX_H
|
||||
#define __DRIVERS_INTERCONNECT_IMX_H
|
||||
|
||||
#include <linux/interconnect-provider.h>
|
||||
#include <linux/kernel.h>
|
||||
|
||||
#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
|
||||
*/
|
||||
@ -38,6 +70,20 @@ struct imx_icc_node_desc {
|
||||
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, ...) \
|
||||
{ \
|
||||
.id = _id, \
|
||||
@ -55,7 +101,8 @@ struct imx_icc_node_desc {
|
||||
|
||||
int imx_icc_register(struct platform_device *pdev,
|
||||
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);
|
||||
|
||||
#endif /* __DRIVERS_INTERCONNECT_IMX_H */
|
||||
|
@ -83,7 +83,7 @@ static struct imx_icc_node_desc nodes[] = {
|
||||
|
||||
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)
|
||||
|
@ -72,7 +72,7 @@ static struct imx_icc_node_desc nodes[] = {
|
||||
|
||||
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)
|
||||
|
259
drivers/interconnect/imx/imx8mp.c
Normal file
259
drivers/interconnect/imx/imx8mp.c
Normal 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");
|
@ -82,7 +82,7 @@ static struct imx_icc_node_desc nodes[] = {
|
||||
|
||||
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)
|
||||
|
59
include/dt-bindings/interconnect/fsl,imx8mp.h
Normal file
59
include/dt-bindings/interconnect/fsl,imx8mp.h
Normal 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 */
|
@ -44,6 +44,7 @@ struct icc_path *icc_get(struct device *dev, const int src_id,
|
||||
const int dst_id);
|
||||
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);
|
||||
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);
|
||||
void icc_put(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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user