diff mbox series

[5/5] soc: imx: imx8mp-blk-ctrl: introduce HSIO blk ctrl noc settings

Message ID 20220406082330.2681591-6-peng.fan@oss.nxp.com
State New
Headers show
Series imx: support noc settings with power domain | expand

Commit Message

Peng Fan (OSS) April 6, 2022, 8:23 a.m. UTC
From: Peng Fan <peng.fan@nxp.com>

The out of reset value of HSIO NoC is not a valid value, we need
set it to a correct value. We only need to set it after power on.

Signed-off-by: Peng Fan <peng.fan@nxp.com>
---
 drivers/soc/imx/imx8mp-blk-ctrl.c | 74 +++++++++++++++++++++++++++++++
 1 file changed, 74 insertions(+)
diff mbox series

Patch

diff --git a/drivers/soc/imx/imx8mp-blk-ctrl.c b/drivers/soc/imx/imx8mp-blk-ctrl.c
index e832c007b063..929fd9b770ae 100644
--- a/drivers/soc/imx/imx8mp-blk-ctrl.c
+++ b/drivers/soc/imx/imx8mp-blk-ctrl.c
@@ -12,6 +12,7 @@ 
 #include <linux/pm_domain.h>
 #include <linux/pm_runtime.h>
 #include <linux/regmap.h>
+#include <linux/mfd/syscon.h>
 
 #include <dt-bindings/power/imx8mp-power.h>
 
@@ -26,14 +27,24 @@  struct imx8mp_hsio_blk_ctrl {
 	struct notifier_block power_nb;
 	struct device *bus_power_dev;
 	struct regmap *regmap;
+	struct regmap *noc_regmap;
 	struct imx8mp_hsio_blk_ctrl_domain *domains;
 	struct genpd_onecell_data onecell_data;
 };
 
+struct imx8mp_hsio_blk_ctrl_noc_data {
+	u32 off;
+	u32 priority;
+	u32 mode;
+	u32 extctrl;
+};
+
+#define DOMAIN_MAX_NOC	2
 struct imx8mp_hsio_blk_ctrl_domain_data {
 	const char *name;
 	const char *clk_name;
 	const char *gpc_name;
+	const struct imx8mp_hsio_blk_ctrl_noc_data *noc_data[DOMAIN_MAX_NOC];
 };
 
 struct imx8mp_hsio_blk_ctrl_domain {
@@ -41,6 +52,7 @@  struct imx8mp_hsio_blk_ctrl_domain {
 	struct clk *clk;
 	struct device *power_dev;
 	struct imx8mp_hsio_blk_ctrl *bc;
+	const struct imx8mp_hsio_blk_ctrl_domain_data *data;
 	int id;
 };
 
@@ -50,6 +62,27 @@  to_imx8mp_hsio_blk_ctrl_domain(struct generic_pm_domain *genpd)
 	return container_of(genpd, struct imx8mp_hsio_blk_ctrl_domain, genpd);
 }
 
+static int imx8mp_hsio_noc_set(struct imx8mp_hsio_blk_ctrl_domain *domain)
+{
+	const struct imx8mp_hsio_blk_ctrl_domain_data *data = domain->data;
+	struct imx8mp_hsio_blk_ctrl *bc = domain->bc;
+	struct regmap *regmap = bc->noc_regmap;
+	int i;
+
+	if (!data || !regmap)
+		return 0;
+
+	for (i = 0; i < DOMAIN_MAX_NOC; i++) {
+		if (!data->noc_data[i])
+			continue;
+		regmap_write(regmap, data->noc_data[i]->off + 0x8, data->noc_data[i]->priority);
+		regmap_write(regmap, data->noc_data[i]->off + 0xc, data->noc_data[i]->mode);
+		regmap_write(regmap, data->noc_data[i]->off + 0x18, data->noc_data[i]->extctrl);
+	}
+
+	return 0;
+}
+
 static int imx8mp_hsio_blk_ctrl_power_on(struct generic_pm_domain *genpd)
 {
 	struct imx8mp_hsio_blk_ctrl_domain *domain =
@@ -89,6 +122,8 @@  static int imx8mp_hsio_blk_ctrl_power_on(struct generic_pm_domain *genpd)
 		goto clk_disable;
 	}
 
+	imx8mp_hsio_noc_set(domain);
+
 	return 0;
 
 clk_disable:
@@ -143,11 +178,39 @@  imx8m_blk_ctrl_xlate(struct of_phandle_args *args, void *data)
 
 static struct lock_class_key blk_ctrl_genpd_lock_class;
 
+#define IMX8MP_HSIOBLK_NOC_PCIE	0
+#define IMX8MP_HSIOBLK_USB1	1
+#define IMX8MP_HSIOBLK_USB2	2
+#define IMX8MP_HSIOBLK_PCIE	3
+
+static const struct imx8mp_hsio_blk_ctrl_noc_data imx8mp_hsio_noc_data[] = {
+	[IMX8MP_HSIOBLK_NOC_PCIE] = {
+		.off = 0x780,
+		.priority = 0x80000303,
+	},
+	[IMX8MP_HSIOBLK_USB1] = {
+		.off = 0x800,
+		.priority = 0x80000303,
+	},
+	[IMX8MP_HSIOBLK_USB2] = {
+		.off = 0x880,
+		.priority = 0x80000303,
+	},
+	[IMX8MP_HSIOBLK_PCIE] = {
+		.off = 0x900,
+		.priority = 0x80000303,
+	},
+};
+
 static const struct imx8mp_hsio_blk_ctrl_domain_data imx8mp_hsio_domain_data[] = {
 	[IMX8MP_HSIOBLK_PD_USB] = {
 		.name = "hsioblk-usb",
 		.clk_name = "usb",
 		.gpc_name = "usb",
+		.noc_data = {
+			&imx8mp_hsio_noc_data[IMX8MP_HSIOBLK_USB1],
+			&imx8mp_hsio_noc_data[IMX8MP_HSIOBLK_USB2]
+		},
 	},
 	[IMX8MP_HSIOBLK_PD_USB_PHY1] = {
 		.name = "hsioblk-usb-phy1",
@@ -161,6 +224,10 @@  static const struct imx8mp_hsio_blk_ctrl_domain_data imx8mp_hsio_domain_data[] =
 		.name = "hsioblk-pcie",
 		.clk_name = "pcie",
 		.gpc_name = "pcie",
+		.noc_data = {
+			&imx8mp_hsio_noc_data[IMX8MP_HSIOBLK_NOC_PCIE],
+			&imx8mp_hsio_noc_data[IMX8MP_HSIOBLK_PCIE]
+		},
 	},
 	[IMX8MP_HSIOBLK_PD_PCIE_PHY] = {
 		.name = "hsioblk-pcie-phy",
@@ -215,6 +282,7 @@  static int imx8mp_hsio_blk_ctrl_probe(struct platform_device *pdev)
 	int num_domains = ARRAY_SIZE(imx8mp_hsio_domain_data);
 	struct device *dev = &pdev->dev;
 	struct imx8mp_hsio_blk_ctrl *bc;
+	struct regmap *regmap;
 	void __iomem *base;
 	int i, ret;
 
@@ -259,11 +327,17 @@  static int imx8mp_hsio_blk_ctrl_probe(struct platform_device *pdev)
 		return dev_err_probe(dev, PTR_ERR(bc->bus_power_dev),
 				     "failed to attach bus power domain\n");
 
+	regmap = syscon_regmap_lookup_by_compatible("fsl,imx8m-noc");
+	if (!IS_ERR(regmap))
+		bc->noc_regmap = regmap;
+
 	for (i = 0; i < num_domains; i++) {
 		const struct imx8mp_hsio_blk_ctrl_domain_data *data =
 				&imx8mp_hsio_domain_data[i];
 		struct imx8mp_hsio_blk_ctrl_domain *domain = &bc->domains[i];
 
+		domain->data = data;
+
 		if (data->clk_name) {
 			domain->clk = devm_clk_get(dev, data->clk_name);
 			if (IS_ERR(domain->clk)) {