[PATCH 4/5] soc: imx: imx8m-blk-ctrl: support i.MX8MP media blk ctrl noc settings

Laurent Pinchart laurent.pinchart at ideasonboard.com
Wed Apr 6 02:42:27 PDT 2022


Hi Peng,

Thank you for the patch.

On Wed, Apr 06, 2022 at 04:23:29PM +0800, Peng Fan (OSS) wrote:
> From: Peng Fan <peng.fan at nxp.com>
> 
> The out of reset value of 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 at nxp.com>
> ---
>  drivers/soc/imx/imx8m-blk-ctrl.c | 109 +++++++++++++++++++++++++++++++
>  1 file changed, 109 insertions(+)
> 
> diff --git a/drivers/soc/imx/imx8m-blk-ctrl.c b/drivers/soc/imx/imx8m-blk-ctrl.c
> index 3a6abd70520c..5b382b4e6a64 100644
> --- a/drivers/soc/imx/imx8m-blk-ctrl.c
> +++ b/drivers/soc/imx/imx8m-blk-ctrl.c
> @@ -12,6 +12,7 @@
>  #include <linux/pm_runtime.h>
>  #include <linux/regmap.h>
>  #include <linux/clk.h>
> +#include <linux/mfd/syscon.h>
>  
>  #include <dt-bindings/power/imx8mm-power.h>
>  #include <dt-bindings/power/imx8mn-power.h>
> @@ -29,10 +30,19 @@ struct imx8m_blk_ctrl {
>  	struct notifier_block power_nb;
>  	struct device *bus_power_dev;
>  	struct regmap *regmap;
> +	struct regmap *noc_regmap;
>  	struct imx8m_blk_ctrl_domain *domains;
>  	struct genpd_onecell_data onecell_data;
>  };
>  
> +struct imx8m_blk_ctrl_noc_data {
> +	u32 off;

Maybe "offset" ?

> +	u32 priority;
> +	u32 mode;
> +	u32 extctrl;
> +};
> +
> +#define DOMAIN_MAX_NOC	4

And a blank line here.

We have 3 NoC entries at most below, so this could be lowered, but I
wonder if it wouldn't be nicer to actually drop the macro (see below).

>  struct imx8m_blk_ctrl_domain_data {
>  	const char *name;
>  	const char * const *clk_names;
> @@ -49,6 +59,7 @@ struct imx8m_blk_ctrl_domain_data {
>  	 * register.
>  	 */
>  	u32 mipi_phy_rst_mask;
> +	const struct imx8m_blk_ctrl_noc_data *noc_data[DOMAIN_MAX_NOC];

This would become just

	const struct imx8m_blk_ctrl_noc_data **noc_data;

>  };
>  
>  #define DOMAIN_MAX_CLKS 3
> @@ -66,6 +77,7 @@ struct imx8m_blk_ctrl_data {
>  	notifier_fn_t power_notifier_fn;
>  	const struct imx8m_blk_ctrl_domain_data *domains;
>  	int num_domains;
> +	bool has_noc;
>  };
>  
>  static inline struct imx8m_blk_ctrl_domain *
> @@ -74,6 +86,27 @@ to_imx8m_blk_ctrl_domain(struct generic_pm_domain *genpd)
>  	return container_of(genpd, struct imx8m_blk_ctrl_domain, genpd);
>  }
>  
> +static int imx8m_blk_ctrl_noc_set(struct imx8m_blk_ctrl_domain *domain)
> +{
> +	const struct imx8m_blk_ctrl_domain_data *data = domain->data;
> +	struct imx8m_blk_ctrl *bc = domain->bc;
> +	struct regmap *regmap = bc->noc_regmap;
> +	int i;

As it can never be negative, you can make i an unsigned int.

> +
> +	if (!data || !regmap)
> +		return 0;
> +
> +	for (i = 0; i < DOMAIN_MAX_NOC; i++) {
> +		if (!data->noc_data[i])
> +			continue;

With

		const struct imx8m_blk_ctrl_noc_data *noc_data = &data->noc_data[i];

		if (!noc_data)
			continue;

you could then write

		regmap_write(regmap, noc_data->off + 0x8, noc_data->priority);
		regmap_write(regmap, noc_data->off + 0xc, noc_data->mode);
		regmap_write(regmap, noc_data->off + 0x18, noc_data->extctrl);

which is a bit nicer.

If we drop the harcoded number of NoC entries, the loop could become

	const struct imx8m_blk_ctrl_noc_data *noc_data;

	for (i = 0; data->noc_data[i]; i++) {
		const struct imx8m_blk_ctrl_noc_data *noc_data = data->noc_data[i];

		regmap_write(regmap, noc_data->off + 0x8, noc_data->priority);
		regmap_write(regmap, noc_data->off + 0xc, noc_data->mode);
		regmap_write(regmap, noc_data->off + 0x18, noc_data->extctrl);
	}

You would then need a sentinel entry at the end of the noc_data array,
initialized to NULL.

> +		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 imx8m_blk_ctrl_power_on(struct generic_pm_domain *genpd)
>  {
>  	struct imx8m_blk_ctrl_domain *domain = to_imx8m_blk_ctrl_domain(genpd);
> @@ -117,6 +150,8 @@ static int imx8m_blk_ctrl_power_on(struct generic_pm_domain *genpd)
>  	if (data->mipi_phy_rst_mask)
>  		regmap_set_bits(bc->regmap, BLK_MIPI_RESET_DIV, data->mipi_phy_rst_mask);
>  
> +	imx8m_blk_ctrl_noc_set(domain);
> +
>  	/* disable upstream clocks */
>  	clk_bulk_disable_unprepare(data->num_clks, domain->clks);
>  
> @@ -172,6 +207,7 @@ static int imx8m_blk_ctrl_probe(struct platform_device *pdev)
>  	const struct imx8m_blk_ctrl_data *bc_data;
>  	struct device *dev = &pdev->dev;
>  	struct imx8m_blk_ctrl *bc;
> +	struct regmap *regmap;
>  	void __iomem *base;
>  	int i, ret;
>  
> @@ -218,6 +254,10 @@ static int imx8m_blk_ctrl_probe(struct platform_device *pdev)
>  		return dev_err_probe(dev, PTR_ERR(bc->bus_power_dev),
>  				     "failed to attach power domain\n");
>  
> +	regmap = syscon_regmap_lookup_by_compatible("fsl,imx8m-noc");
> +	if (!IS_ERR(regmap))
> +		bc->noc_regmap = regmap;
> +
>  	for (i = 0; i < bc_data->num_domains; i++) {
>  		const struct imx8m_blk_ctrl_domain_data *data = &bc_data->domains[i];
>  		struct imx8m_blk_ctrl_domain *domain = &bc->domains[i];
> @@ -677,6 +717,55 @@ static int imx8mp_media_power_notifier(struct notifier_block *nb,
>  	return NOTIFY_OK;
>  }
>  
> +#define IMX8MP_MEDIABLK_LCDIF_RD	0
> +#define IMX8MP_MEDIABLK_LCDIF_WR	1
> +#define IMX8MP_MEDIABLK_ISI0		2
> +#define IMX8MP_MEDIABLK_ISI1		3
> +#define IMX8MP_MEDIABLK_ISI2		4

Would these be the two AXI write and the AXI read ports of the ISI ?
Could they then be named accordingly (e.g. ISI_WR0, ISI_WR1, ISI_RD) ? I
don't know which is which though.

> +#define IMX8MP_MEDIABLK_ISP0		5
> +#define IMX8MP_MEDIABLK_ISP1		6
> +#define IMX8MP_MEDIABLK_DWE		7
> +
> +static const struct imx8m_blk_ctrl_noc_data imx8mp_media_noc_data[] = {
> +	[IMX8MP_MEDIABLK_LCDIF_RD] = {
> +		.off = 0x980,
> +		.priority = 0x80000202,
> +		.extctrl = 1,
> +	},
> +	[IMX8MP_MEDIABLK_LCDIF_WR] = {
> +		.off = 0xa00,
> +		.priority = 0x80000202,
> +		.extctrl = 1,
> +	},
> +	[IMX8MP_MEDIABLK_ISI0] = {
> +		.off = 0xa80,
> +		.priority = 0x80000202,
> +		.extctrl = 1,
> +	},
> +	[IMX8MP_MEDIABLK_ISI1] = {
> +		.off = 0xb00,
> +		.priority = 0x80000202,
> +		.extctrl = 1,
> +	},
> +	[IMX8MP_MEDIABLK_ISI2] = {
> +		.off = 0xb80,
> +		.priority = 0x80000202,
> +		.extctrl = 1,
> +	},
> +	[IMX8MP_MEDIABLK_ISP0] = {
> +		.off = 0xc00,
> +		.priority = 0x80000707,
> +	},
> +	[IMX8MP_MEDIABLK_ISP1] = {
> +		.off = 0xc80,
> +		.priority = 0x80000707,
> +	},
> +	[IMX8MP_MEDIABLK_DWE] = {
> +		.off = 0xd00,
> +		.priority = 0x80000707,
> +	},

This matches the TF-A implementation.

With the above comments taken into account,

Reviewed-by: Laurent Pinchart <laurent.pinchart at ideasonboard.com>

> +};
> +
>  /*
>   * From i.MX 8M Plus Applications Processor Reference Manual, Rev. 1,
>   * section 13.2.2, 13.2.3
> @@ -708,6 +797,10 @@ static const struct imx8m_blk_ctrl_domain_data imx8mp_media_blk_ctl_domain_data[
>  		.gpc_name = "lcdif1",
>  		.rst_mask = BIT(4) | BIT(5) | BIT(23),
>  		.clk_mask = BIT(4) | BIT(5) | BIT(23),
> +		.noc_data = {
> +			&imx8mp_media_noc_data[IMX8MP_MEDIABLK_LCDIF_RD],
> +			&imx8mp_media_noc_data[IMX8MP_MEDIABLK_LCDIF_WR],
> +		},
>  	},
>  	[IMX8MP_MEDIABLK_PD_ISI] = {
>  		.name = "mediablk-isi",
> @@ -716,6 +809,11 @@ static const struct imx8m_blk_ctrl_domain_data imx8mp_media_blk_ctl_domain_data[
>  		.gpc_name = "isi",
>  		.rst_mask = BIT(6) | BIT(7),
>  		.clk_mask = BIT(6) | BIT(7),
> +		.noc_data = {
> +			&imx8mp_media_noc_data[IMX8MP_MEDIABLK_ISI0],
> +			&imx8mp_media_noc_data[IMX8MP_MEDIABLK_ISI1],
> +			&imx8mp_media_noc_data[IMX8MP_MEDIABLK_ISI2],
> +		},
>  	},
>  	[IMX8MP_MEDIABLK_PD_MIPI_CSI2_2] = {
>  		.name = "mediablk-mipi-csi2-2",
> @@ -733,6 +831,10 @@ static const struct imx8m_blk_ctrl_domain_data imx8mp_media_blk_ctl_domain_data[
>  		.gpc_name = "lcdif2",
>  		.rst_mask = BIT(11) | BIT(12) | BIT(24),
>  		.clk_mask = BIT(11) | BIT(12) | BIT(24),
> +		.noc_data = {
> +			&imx8mp_media_noc_data[IMX8MP_MEDIABLK_LCDIF_RD],
> +			&imx8mp_media_noc_data[IMX8MP_MEDIABLK_LCDIF_WR],
> +		},
>  	},
>  	[IMX8MP_MEDIABLK_PD_ISP2] = {
>  		.name = "mediablk-isp2",
> @@ -749,6 +851,10 @@ static const struct imx8m_blk_ctrl_domain_data imx8mp_media_blk_ctl_domain_data[
>  		.gpc_name = "isp1",
>  		.rst_mask = BIT(16) | BIT(17) | BIT(18),
>  		.clk_mask = BIT(16) | BIT(17) | BIT(18),
> +		.noc_data = {
> +			&imx8mp_media_noc_data[IMX8MP_MEDIABLK_ISP0],
> +			&imx8mp_media_noc_data[IMX8MP_MEDIABLK_ISP1],
> +		},
>  	},
>  	[IMX8MP_MEDIABLK_PD_DWE] = {
>  		.name = "mediablk-dwe",
> @@ -757,6 +863,9 @@ static const struct imx8m_blk_ctrl_domain_data imx8mp_media_blk_ctl_domain_data[
>  		.gpc_name = "dwe",
>  		.rst_mask = BIT(19) | BIT(20) | BIT(21),
>  		.clk_mask = BIT(19) | BIT(20) | BIT(21),
> +		.noc_data = {
> +			&imx8mp_media_noc_data[IMX8MP_MEDIABLK_DWE],
> +		},
>  	},
>  	[IMX8MP_MEDIABLK_PD_MIPI_DSI_2] = {
>  		.name = "mediablk-mipi-dsi-2",

-- 
Regards,

Laurent Pinchart



More information about the linux-arm-kernel mailing list