162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright 2022 NXP, Peng Fan <peng.fan@nxp.com>
462306a36Sopenharmony_ci */
562306a36Sopenharmony_ci
662306a36Sopenharmony_ci#include <linux/clk.h>
762306a36Sopenharmony_ci#include <linux/device.h>
862306a36Sopenharmony_ci#include <linux/module.h>
962306a36Sopenharmony_ci#include <linux/of.h>
1062306a36Sopenharmony_ci#include <linux/platform_device.h>
1162306a36Sopenharmony_ci#include <linux/pm_domain.h>
1262306a36Sopenharmony_ci#include <linux/pm_runtime.h>
1362306a36Sopenharmony_ci#include <linux/regmap.h>
1462306a36Sopenharmony_ci#include <linux/sizes.h>
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_ci#include <dt-bindings/power/fsl,imx93-power.h>
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_ci#define BLK_SFT_RSTN	0x0
1962306a36Sopenharmony_ci#define BLK_CLK_EN	0x4
2062306a36Sopenharmony_ci#define BLK_MAX_CLKS	4
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_ci#define DOMAIN_MAX_CLKS 4
2362306a36Sopenharmony_ci
2462306a36Sopenharmony_ci#define LCDIF_QOS_REG		0xC
2562306a36Sopenharmony_ci#define LCDIF_DEFAULT_QOS_OFF	12
2662306a36Sopenharmony_ci#define LCDIF_CFG_QOS_OFF	8
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_ci#define PXP_QOS_REG		0x10
2962306a36Sopenharmony_ci#define PXP_R_DEFAULT_QOS_OFF	28
3062306a36Sopenharmony_ci#define PXP_R_CFG_QOS_OFF	24
3162306a36Sopenharmony_ci#define PXP_W_DEFAULT_QOS_OFF	20
3262306a36Sopenharmony_ci#define PXP_W_CFG_QOS_OFF	16
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_ci#define ISI_CACHE_REG		0x14
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_ci#define ISI_QOS_REG		0x1C
3762306a36Sopenharmony_ci#define ISI_V_DEFAULT_QOS_OFF	28
3862306a36Sopenharmony_ci#define ISI_V_CFG_QOS_OFF	24
3962306a36Sopenharmony_ci#define ISI_U_DEFAULT_QOS_OFF	20
4062306a36Sopenharmony_ci#define ISI_U_CFG_QOS_OFF	16
4162306a36Sopenharmony_ci#define ISI_Y_R_DEFAULT_QOS_OFF	12
4262306a36Sopenharmony_ci#define ISI_Y_R_CFG_QOS_OFF	8
4362306a36Sopenharmony_ci#define ISI_Y_W_DEFAULT_QOS_OFF	4
4462306a36Sopenharmony_ci#define ISI_Y_W_CFG_QOS_OFF	0
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_ci#define PRIO_MASK		0xF
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_ci#define PRIO(X)			(X)
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_cistruct imx93_blk_ctrl_domain;
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_cistruct imx93_blk_ctrl {
5362306a36Sopenharmony_ci	struct device *dev;
5462306a36Sopenharmony_ci	struct regmap *regmap;
5562306a36Sopenharmony_ci	int num_clks;
5662306a36Sopenharmony_ci	struct clk_bulk_data clks[BLK_MAX_CLKS];
5762306a36Sopenharmony_ci	struct imx93_blk_ctrl_domain *domains;
5862306a36Sopenharmony_ci	struct genpd_onecell_data onecell_data;
5962306a36Sopenharmony_ci};
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_ci#define DOMAIN_MAX_QOS 4
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_cistruct imx93_blk_ctrl_qos {
6462306a36Sopenharmony_ci	u32 reg;
6562306a36Sopenharmony_ci	u32 cfg_off;
6662306a36Sopenharmony_ci	u32 default_prio;
6762306a36Sopenharmony_ci	u32 cfg_prio;
6862306a36Sopenharmony_ci};
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_cistruct imx93_blk_ctrl_domain_data {
7162306a36Sopenharmony_ci	const char *name;
7262306a36Sopenharmony_ci	const char * const *clk_names;
7362306a36Sopenharmony_ci	int num_clks;
7462306a36Sopenharmony_ci	u32 rst_mask;
7562306a36Sopenharmony_ci	u32 clk_mask;
7662306a36Sopenharmony_ci	int num_qos;
7762306a36Sopenharmony_ci	struct imx93_blk_ctrl_qos qos[DOMAIN_MAX_QOS];
7862306a36Sopenharmony_ci};
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_cistruct imx93_blk_ctrl_domain {
8162306a36Sopenharmony_ci	struct generic_pm_domain genpd;
8262306a36Sopenharmony_ci	const struct imx93_blk_ctrl_domain_data *data;
8362306a36Sopenharmony_ci	struct clk_bulk_data clks[DOMAIN_MAX_CLKS];
8462306a36Sopenharmony_ci	struct imx93_blk_ctrl *bc;
8562306a36Sopenharmony_ci};
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_cistruct imx93_blk_ctrl_data {
8862306a36Sopenharmony_ci	const struct imx93_blk_ctrl_domain_data *domains;
8962306a36Sopenharmony_ci	int num_domains;
9062306a36Sopenharmony_ci	const char * const *clk_names;
9162306a36Sopenharmony_ci	int num_clks;
9262306a36Sopenharmony_ci	const struct regmap_access_table *reg_access_table;
9362306a36Sopenharmony_ci};
9462306a36Sopenharmony_ci
9562306a36Sopenharmony_cistatic inline struct imx93_blk_ctrl_domain *
9662306a36Sopenharmony_cito_imx93_blk_ctrl_domain(struct generic_pm_domain *genpd)
9762306a36Sopenharmony_ci{
9862306a36Sopenharmony_ci	return container_of(genpd, struct imx93_blk_ctrl_domain, genpd);
9962306a36Sopenharmony_ci}
10062306a36Sopenharmony_ci
10162306a36Sopenharmony_cistatic int imx93_blk_ctrl_set_qos(struct imx93_blk_ctrl_domain *domain)
10262306a36Sopenharmony_ci{
10362306a36Sopenharmony_ci	const struct imx93_blk_ctrl_domain_data *data = domain->data;
10462306a36Sopenharmony_ci	struct imx93_blk_ctrl *bc = domain->bc;
10562306a36Sopenharmony_ci	const struct imx93_blk_ctrl_qos *qos;
10662306a36Sopenharmony_ci	u32 val, mask;
10762306a36Sopenharmony_ci	int i;
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_ci	for (i = 0; i < data->num_qos; i++) {
11062306a36Sopenharmony_ci		qos = &data->qos[i];
11162306a36Sopenharmony_ci
11262306a36Sopenharmony_ci		mask = PRIO_MASK << qos->cfg_off;
11362306a36Sopenharmony_ci		mask |= PRIO_MASK << (qos->cfg_off + 4);
11462306a36Sopenharmony_ci		val = qos->cfg_prio << qos->cfg_off;
11562306a36Sopenharmony_ci		val |= qos->default_prio << (qos->cfg_off + 4);
11662306a36Sopenharmony_ci
11762306a36Sopenharmony_ci		regmap_write_bits(bc->regmap, qos->reg, mask, val);
11862306a36Sopenharmony_ci
11962306a36Sopenharmony_ci		dev_dbg(bc->dev, "data->qos[i].reg 0x%x 0x%x\n", qos->reg, val);
12062306a36Sopenharmony_ci	}
12162306a36Sopenharmony_ci
12262306a36Sopenharmony_ci	return 0;
12362306a36Sopenharmony_ci}
12462306a36Sopenharmony_ci
12562306a36Sopenharmony_cistatic int imx93_blk_ctrl_power_on(struct generic_pm_domain *genpd)
12662306a36Sopenharmony_ci{
12762306a36Sopenharmony_ci	struct imx93_blk_ctrl_domain *domain = to_imx93_blk_ctrl_domain(genpd);
12862306a36Sopenharmony_ci	const struct imx93_blk_ctrl_domain_data *data = domain->data;
12962306a36Sopenharmony_ci	struct imx93_blk_ctrl *bc = domain->bc;
13062306a36Sopenharmony_ci	int ret;
13162306a36Sopenharmony_ci
13262306a36Sopenharmony_ci	ret = clk_bulk_prepare_enable(bc->num_clks, bc->clks);
13362306a36Sopenharmony_ci	if (ret) {
13462306a36Sopenharmony_ci		dev_err(bc->dev, "failed to enable bus clocks\n");
13562306a36Sopenharmony_ci		return ret;
13662306a36Sopenharmony_ci	}
13762306a36Sopenharmony_ci
13862306a36Sopenharmony_ci	ret = clk_bulk_prepare_enable(data->num_clks, domain->clks);
13962306a36Sopenharmony_ci	if (ret) {
14062306a36Sopenharmony_ci		clk_bulk_disable_unprepare(bc->num_clks, bc->clks);
14162306a36Sopenharmony_ci		dev_err(bc->dev, "failed to enable clocks\n");
14262306a36Sopenharmony_ci		return ret;
14362306a36Sopenharmony_ci	}
14462306a36Sopenharmony_ci
14562306a36Sopenharmony_ci	ret = pm_runtime_get_sync(bc->dev);
14662306a36Sopenharmony_ci	if (ret < 0) {
14762306a36Sopenharmony_ci		pm_runtime_put_noidle(bc->dev);
14862306a36Sopenharmony_ci		dev_err(bc->dev, "failed to power up domain\n");
14962306a36Sopenharmony_ci		goto disable_clk;
15062306a36Sopenharmony_ci	}
15162306a36Sopenharmony_ci
15262306a36Sopenharmony_ci	/* ungate clk */
15362306a36Sopenharmony_ci	regmap_clear_bits(bc->regmap, BLK_CLK_EN, data->clk_mask);
15462306a36Sopenharmony_ci
15562306a36Sopenharmony_ci	/* release reset */
15662306a36Sopenharmony_ci	regmap_set_bits(bc->regmap, BLK_SFT_RSTN, data->rst_mask);
15762306a36Sopenharmony_ci
15862306a36Sopenharmony_ci	dev_dbg(bc->dev, "pd_on: name: %s\n", genpd->name);
15962306a36Sopenharmony_ci
16062306a36Sopenharmony_ci	return imx93_blk_ctrl_set_qos(domain);
16162306a36Sopenharmony_ci
16262306a36Sopenharmony_cidisable_clk:
16362306a36Sopenharmony_ci	clk_bulk_disable_unprepare(data->num_clks, domain->clks);
16462306a36Sopenharmony_ci
16562306a36Sopenharmony_ci	clk_bulk_disable_unprepare(bc->num_clks, bc->clks);
16662306a36Sopenharmony_ci
16762306a36Sopenharmony_ci	return ret;
16862306a36Sopenharmony_ci}
16962306a36Sopenharmony_ci
17062306a36Sopenharmony_cistatic int imx93_blk_ctrl_power_off(struct generic_pm_domain *genpd)
17162306a36Sopenharmony_ci{
17262306a36Sopenharmony_ci	struct imx93_blk_ctrl_domain *domain = to_imx93_blk_ctrl_domain(genpd);
17362306a36Sopenharmony_ci	const struct imx93_blk_ctrl_domain_data *data = domain->data;
17462306a36Sopenharmony_ci	struct imx93_blk_ctrl *bc = domain->bc;
17562306a36Sopenharmony_ci
17662306a36Sopenharmony_ci	dev_dbg(bc->dev, "pd_off: name: %s\n", genpd->name);
17762306a36Sopenharmony_ci
17862306a36Sopenharmony_ci	regmap_clear_bits(bc->regmap, BLK_SFT_RSTN, data->rst_mask);
17962306a36Sopenharmony_ci	regmap_set_bits(bc->regmap, BLK_CLK_EN, data->clk_mask);
18062306a36Sopenharmony_ci
18162306a36Sopenharmony_ci	pm_runtime_put(bc->dev);
18262306a36Sopenharmony_ci
18362306a36Sopenharmony_ci	clk_bulk_disable_unprepare(data->num_clks, domain->clks);
18462306a36Sopenharmony_ci
18562306a36Sopenharmony_ci	clk_bulk_disable_unprepare(bc->num_clks, bc->clks);
18662306a36Sopenharmony_ci
18762306a36Sopenharmony_ci	return 0;
18862306a36Sopenharmony_ci}
18962306a36Sopenharmony_ci
19062306a36Sopenharmony_cistatic struct lock_class_key blk_ctrl_genpd_lock_class;
19162306a36Sopenharmony_ci
19262306a36Sopenharmony_cistatic int imx93_blk_ctrl_probe(struct platform_device *pdev)
19362306a36Sopenharmony_ci{
19462306a36Sopenharmony_ci	struct device *dev = &pdev->dev;
19562306a36Sopenharmony_ci	const struct imx93_blk_ctrl_data *bc_data = of_device_get_match_data(dev);
19662306a36Sopenharmony_ci	struct imx93_blk_ctrl *bc;
19762306a36Sopenharmony_ci	void __iomem *base;
19862306a36Sopenharmony_ci	int i, ret;
19962306a36Sopenharmony_ci
20062306a36Sopenharmony_ci	struct regmap_config regmap_config = {
20162306a36Sopenharmony_ci		.reg_bits	= 32,
20262306a36Sopenharmony_ci		.val_bits	= 32,
20362306a36Sopenharmony_ci		.reg_stride	= 4,
20462306a36Sopenharmony_ci		.rd_table	= bc_data->reg_access_table,
20562306a36Sopenharmony_ci		.wr_table	= bc_data->reg_access_table,
20662306a36Sopenharmony_ci		.max_register   = SZ_4K,
20762306a36Sopenharmony_ci	};
20862306a36Sopenharmony_ci
20962306a36Sopenharmony_ci	bc = devm_kzalloc(dev, sizeof(*bc), GFP_KERNEL);
21062306a36Sopenharmony_ci	if (!bc)
21162306a36Sopenharmony_ci		return -ENOMEM;
21262306a36Sopenharmony_ci
21362306a36Sopenharmony_ci	bc->dev = dev;
21462306a36Sopenharmony_ci
21562306a36Sopenharmony_ci	base = devm_platform_ioremap_resource(pdev, 0);
21662306a36Sopenharmony_ci	if (IS_ERR(base))
21762306a36Sopenharmony_ci		return PTR_ERR(base);
21862306a36Sopenharmony_ci
21962306a36Sopenharmony_ci	bc->regmap = devm_regmap_init_mmio(dev, base, &regmap_config);
22062306a36Sopenharmony_ci	if (IS_ERR(bc->regmap))
22162306a36Sopenharmony_ci		return dev_err_probe(dev, PTR_ERR(bc->regmap),
22262306a36Sopenharmony_ci				     "failed to init regmap\n");
22362306a36Sopenharmony_ci
22462306a36Sopenharmony_ci	bc->domains = devm_kcalloc(dev, bc_data->num_domains,
22562306a36Sopenharmony_ci				   sizeof(struct imx93_blk_ctrl_domain),
22662306a36Sopenharmony_ci				   GFP_KERNEL);
22762306a36Sopenharmony_ci	if (!bc->domains)
22862306a36Sopenharmony_ci		return -ENOMEM;
22962306a36Sopenharmony_ci
23062306a36Sopenharmony_ci	bc->onecell_data.num_domains = bc_data->num_domains;
23162306a36Sopenharmony_ci	bc->onecell_data.domains =
23262306a36Sopenharmony_ci		devm_kcalloc(dev, bc_data->num_domains,
23362306a36Sopenharmony_ci			     sizeof(struct generic_pm_domain *), GFP_KERNEL);
23462306a36Sopenharmony_ci	if (!bc->onecell_data.domains)
23562306a36Sopenharmony_ci		return -ENOMEM;
23662306a36Sopenharmony_ci
23762306a36Sopenharmony_ci	for (i = 0; i < bc_data->num_clks; i++)
23862306a36Sopenharmony_ci		bc->clks[i].id = bc_data->clk_names[i];
23962306a36Sopenharmony_ci	bc->num_clks = bc_data->num_clks;
24062306a36Sopenharmony_ci
24162306a36Sopenharmony_ci	ret = devm_clk_bulk_get(dev, bc->num_clks, bc->clks);
24262306a36Sopenharmony_ci	if (ret) {
24362306a36Sopenharmony_ci		dev_err_probe(dev, ret, "failed to get bus clock\n");
24462306a36Sopenharmony_ci		return ret;
24562306a36Sopenharmony_ci	}
24662306a36Sopenharmony_ci
24762306a36Sopenharmony_ci	for (i = 0; i < bc_data->num_domains; i++) {
24862306a36Sopenharmony_ci		const struct imx93_blk_ctrl_domain_data *data = &bc_data->domains[i];
24962306a36Sopenharmony_ci		struct imx93_blk_ctrl_domain *domain = &bc->domains[i];
25062306a36Sopenharmony_ci		int j;
25162306a36Sopenharmony_ci
25262306a36Sopenharmony_ci		domain->data = data;
25362306a36Sopenharmony_ci
25462306a36Sopenharmony_ci		for (j = 0; j < data->num_clks; j++)
25562306a36Sopenharmony_ci			domain->clks[j].id = data->clk_names[j];
25662306a36Sopenharmony_ci
25762306a36Sopenharmony_ci		ret = devm_clk_bulk_get(dev, data->num_clks, domain->clks);
25862306a36Sopenharmony_ci		if (ret) {
25962306a36Sopenharmony_ci			dev_err_probe(dev, ret, "failed to get clock\n");
26062306a36Sopenharmony_ci			goto cleanup_pds;
26162306a36Sopenharmony_ci		}
26262306a36Sopenharmony_ci
26362306a36Sopenharmony_ci		domain->genpd.name = data->name;
26462306a36Sopenharmony_ci		domain->genpd.power_on = imx93_blk_ctrl_power_on;
26562306a36Sopenharmony_ci		domain->genpd.power_off = imx93_blk_ctrl_power_off;
26662306a36Sopenharmony_ci		domain->bc = bc;
26762306a36Sopenharmony_ci
26862306a36Sopenharmony_ci		ret = pm_genpd_init(&domain->genpd, NULL, true);
26962306a36Sopenharmony_ci		if (ret) {
27062306a36Sopenharmony_ci			dev_err_probe(dev, ret, "failed to init power domain\n");
27162306a36Sopenharmony_ci			goto cleanup_pds;
27262306a36Sopenharmony_ci		}
27362306a36Sopenharmony_ci
27462306a36Sopenharmony_ci		/*
27562306a36Sopenharmony_ci		 * We use runtime PM to trigger power on/off of the upstream GPC
27662306a36Sopenharmony_ci		 * domain, as a strict hierarchical parent/child power domain
27762306a36Sopenharmony_ci		 * setup doesn't allow us to meet the sequencing requirements.
27862306a36Sopenharmony_ci		 * This means we have nested locking of genpd locks, without the
27962306a36Sopenharmony_ci		 * nesting being visible at the genpd level, so we need a
28062306a36Sopenharmony_ci		 * separate lock class to make lockdep aware of the fact that
28162306a36Sopenharmony_ci		 * this are separate domain locks that can be nested without a
28262306a36Sopenharmony_ci		 * self-deadlock.
28362306a36Sopenharmony_ci		 */
28462306a36Sopenharmony_ci		lockdep_set_class(&domain->genpd.mlock,
28562306a36Sopenharmony_ci				  &blk_ctrl_genpd_lock_class);
28662306a36Sopenharmony_ci
28762306a36Sopenharmony_ci		bc->onecell_data.domains[i] = &domain->genpd;
28862306a36Sopenharmony_ci	}
28962306a36Sopenharmony_ci
29062306a36Sopenharmony_ci	pm_runtime_enable(dev);
29162306a36Sopenharmony_ci
29262306a36Sopenharmony_ci	ret = of_genpd_add_provider_onecell(dev->of_node, &bc->onecell_data);
29362306a36Sopenharmony_ci	if (ret) {
29462306a36Sopenharmony_ci		dev_err_probe(dev, ret, "failed to add power domain provider\n");
29562306a36Sopenharmony_ci		goto cleanup_pds;
29662306a36Sopenharmony_ci	}
29762306a36Sopenharmony_ci
29862306a36Sopenharmony_ci	dev_set_drvdata(dev, bc);
29962306a36Sopenharmony_ci
30062306a36Sopenharmony_ci	return 0;
30162306a36Sopenharmony_ci
30262306a36Sopenharmony_cicleanup_pds:
30362306a36Sopenharmony_ci	for (i--; i >= 0; i--)
30462306a36Sopenharmony_ci		pm_genpd_remove(&bc->domains[i].genpd);
30562306a36Sopenharmony_ci
30662306a36Sopenharmony_ci	return ret;
30762306a36Sopenharmony_ci}
30862306a36Sopenharmony_ci
30962306a36Sopenharmony_cistatic int imx93_blk_ctrl_remove(struct platform_device *pdev)
31062306a36Sopenharmony_ci{
31162306a36Sopenharmony_ci	struct imx93_blk_ctrl *bc = dev_get_drvdata(&pdev->dev);
31262306a36Sopenharmony_ci	int i;
31362306a36Sopenharmony_ci
31462306a36Sopenharmony_ci	of_genpd_del_provider(pdev->dev.of_node);
31562306a36Sopenharmony_ci
31662306a36Sopenharmony_ci	for (i = 0; bc->onecell_data.num_domains; i++) {
31762306a36Sopenharmony_ci		struct imx93_blk_ctrl_domain *domain = &bc->domains[i];
31862306a36Sopenharmony_ci
31962306a36Sopenharmony_ci		pm_genpd_remove(&domain->genpd);
32062306a36Sopenharmony_ci	}
32162306a36Sopenharmony_ci
32262306a36Sopenharmony_ci	return 0;
32362306a36Sopenharmony_ci}
32462306a36Sopenharmony_ci
32562306a36Sopenharmony_cistatic const struct imx93_blk_ctrl_domain_data imx93_media_blk_ctl_domain_data[] = {
32662306a36Sopenharmony_ci	[IMX93_MEDIABLK_PD_MIPI_DSI] = {
32762306a36Sopenharmony_ci		.name = "mediablk-mipi-dsi",
32862306a36Sopenharmony_ci		.clk_names = (const char *[]){ "dsi" },
32962306a36Sopenharmony_ci		.num_clks = 1,
33062306a36Sopenharmony_ci		.rst_mask = BIT(11) | BIT(12),
33162306a36Sopenharmony_ci		.clk_mask = BIT(11) | BIT(12),
33262306a36Sopenharmony_ci	},
33362306a36Sopenharmony_ci	[IMX93_MEDIABLK_PD_MIPI_CSI] = {
33462306a36Sopenharmony_ci		.name = "mediablk-mipi-csi",
33562306a36Sopenharmony_ci		.clk_names = (const char *[]){ "cam", "csi" },
33662306a36Sopenharmony_ci		.num_clks = 2,
33762306a36Sopenharmony_ci		.rst_mask = BIT(9) | BIT(10),
33862306a36Sopenharmony_ci		.clk_mask = BIT(9) | BIT(10),
33962306a36Sopenharmony_ci	},
34062306a36Sopenharmony_ci	[IMX93_MEDIABLK_PD_PXP] = {
34162306a36Sopenharmony_ci		.name = "mediablk-pxp",
34262306a36Sopenharmony_ci		.clk_names = (const char *[]){ "pxp" },
34362306a36Sopenharmony_ci		.num_clks = 1,
34462306a36Sopenharmony_ci		.rst_mask = BIT(7) | BIT(8),
34562306a36Sopenharmony_ci		.clk_mask = BIT(7) | BIT(8),
34662306a36Sopenharmony_ci		.num_qos = 2,
34762306a36Sopenharmony_ci		.qos = {
34862306a36Sopenharmony_ci			{
34962306a36Sopenharmony_ci				.reg = PXP_QOS_REG,
35062306a36Sopenharmony_ci				.cfg_off = PXP_R_CFG_QOS_OFF,
35162306a36Sopenharmony_ci				.default_prio = PRIO(3),
35262306a36Sopenharmony_ci				.cfg_prio = PRIO(6),
35362306a36Sopenharmony_ci			}, {
35462306a36Sopenharmony_ci				.reg = PXP_QOS_REG,
35562306a36Sopenharmony_ci				.cfg_off = PXP_W_CFG_QOS_OFF,
35662306a36Sopenharmony_ci				.default_prio = PRIO(3),
35762306a36Sopenharmony_ci				.cfg_prio = PRIO(6),
35862306a36Sopenharmony_ci			}
35962306a36Sopenharmony_ci		}
36062306a36Sopenharmony_ci	},
36162306a36Sopenharmony_ci	[IMX93_MEDIABLK_PD_LCDIF] = {
36262306a36Sopenharmony_ci		.name = "mediablk-lcdif",
36362306a36Sopenharmony_ci		.clk_names = (const char *[]){ "disp", "lcdif" },
36462306a36Sopenharmony_ci		.num_clks = 2,
36562306a36Sopenharmony_ci		.rst_mask = BIT(4) | BIT(5) | BIT(6),
36662306a36Sopenharmony_ci		.clk_mask = BIT(4) | BIT(5) | BIT(6),
36762306a36Sopenharmony_ci		.num_qos = 1,
36862306a36Sopenharmony_ci		.qos = {
36962306a36Sopenharmony_ci			{
37062306a36Sopenharmony_ci			.reg = LCDIF_QOS_REG,
37162306a36Sopenharmony_ci			.cfg_off = LCDIF_CFG_QOS_OFF,
37262306a36Sopenharmony_ci			.default_prio = PRIO(3),
37362306a36Sopenharmony_ci			.cfg_prio = PRIO(7),
37462306a36Sopenharmony_ci			}
37562306a36Sopenharmony_ci		}
37662306a36Sopenharmony_ci	},
37762306a36Sopenharmony_ci	[IMX93_MEDIABLK_PD_ISI] = {
37862306a36Sopenharmony_ci		.name = "mediablk-isi",
37962306a36Sopenharmony_ci		.clk_names = (const char *[]){ "isi" },
38062306a36Sopenharmony_ci		.num_clks = 1,
38162306a36Sopenharmony_ci		.rst_mask = BIT(2) | BIT(3),
38262306a36Sopenharmony_ci		.clk_mask = BIT(2) | BIT(3),
38362306a36Sopenharmony_ci		.num_qos = 4,
38462306a36Sopenharmony_ci		.qos = {
38562306a36Sopenharmony_ci			{
38662306a36Sopenharmony_ci				.reg = ISI_QOS_REG,
38762306a36Sopenharmony_ci				.cfg_off = ISI_Y_W_CFG_QOS_OFF,
38862306a36Sopenharmony_ci				.default_prio = PRIO(3),
38962306a36Sopenharmony_ci				.cfg_prio = PRIO(7),
39062306a36Sopenharmony_ci			}, {
39162306a36Sopenharmony_ci				.reg = ISI_QOS_REG,
39262306a36Sopenharmony_ci				.cfg_off = ISI_Y_R_CFG_QOS_OFF,
39362306a36Sopenharmony_ci				.default_prio = PRIO(3),
39462306a36Sopenharmony_ci				.cfg_prio = PRIO(7),
39562306a36Sopenharmony_ci			}, {
39662306a36Sopenharmony_ci				.reg = ISI_QOS_REG,
39762306a36Sopenharmony_ci				.cfg_off = ISI_U_CFG_QOS_OFF,
39862306a36Sopenharmony_ci				.default_prio = PRIO(3),
39962306a36Sopenharmony_ci				.cfg_prio = PRIO(7),
40062306a36Sopenharmony_ci			}, {
40162306a36Sopenharmony_ci				.reg = ISI_QOS_REG,
40262306a36Sopenharmony_ci				.cfg_off = ISI_V_CFG_QOS_OFF,
40362306a36Sopenharmony_ci				.default_prio = PRIO(3),
40462306a36Sopenharmony_ci				.cfg_prio = PRIO(7),
40562306a36Sopenharmony_ci			}
40662306a36Sopenharmony_ci		}
40762306a36Sopenharmony_ci	},
40862306a36Sopenharmony_ci};
40962306a36Sopenharmony_ci
41062306a36Sopenharmony_cistatic const struct regmap_range imx93_media_blk_ctl_yes_ranges[] = {
41162306a36Sopenharmony_ci	regmap_reg_range(BLK_SFT_RSTN, BLK_CLK_EN),
41262306a36Sopenharmony_ci	regmap_reg_range(LCDIF_QOS_REG, ISI_CACHE_REG),
41362306a36Sopenharmony_ci	regmap_reg_range(ISI_QOS_REG, ISI_QOS_REG),
41462306a36Sopenharmony_ci};
41562306a36Sopenharmony_ci
41662306a36Sopenharmony_cistatic const struct regmap_access_table imx93_media_blk_ctl_access_table = {
41762306a36Sopenharmony_ci	.yes_ranges = imx93_media_blk_ctl_yes_ranges,
41862306a36Sopenharmony_ci	.n_yes_ranges = ARRAY_SIZE(imx93_media_blk_ctl_yes_ranges),
41962306a36Sopenharmony_ci};
42062306a36Sopenharmony_ci
42162306a36Sopenharmony_cistatic const struct imx93_blk_ctrl_data imx93_media_blk_ctl_dev_data = {
42262306a36Sopenharmony_ci	.domains = imx93_media_blk_ctl_domain_data,
42362306a36Sopenharmony_ci	.num_domains = ARRAY_SIZE(imx93_media_blk_ctl_domain_data),
42462306a36Sopenharmony_ci	.clk_names = (const char *[]){ "axi", "apb", "nic", },
42562306a36Sopenharmony_ci	.num_clks = 3,
42662306a36Sopenharmony_ci	.reg_access_table = &imx93_media_blk_ctl_access_table,
42762306a36Sopenharmony_ci};
42862306a36Sopenharmony_ci
42962306a36Sopenharmony_cistatic const struct of_device_id imx93_blk_ctrl_of_match[] = {
43062306a36Sopenharmony_ci	{
43162306a36Sopenharmony_ci		.compatible = "fsl,imx93-media-blk-ctrl",
43262306a36Sopenharmony_ci		.data = &imx93_media_blk_ctl_dev_data
43362306a36Sopenharmony_ci	}, {
43462306a36Sopenharmony_ci		/* Sentinel */
43562306a36Sopenharmony_ci	}
43662306a36Sopenharmony_ci};
43762306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, imx93_blk_ctrl_of_match);
43862306a36Sopenharmony_ci
43962306a36Sopenharmony_cistatic struct platform_driver imx93_blk_ctrl_driver = {
44062306a36Sopenharmony_ci	.probe = imx93_blk_ctrl_probe,
44162306a36Sopenharmony_ci	.remove = imx93_blk_ctrl_remove,
44262306a36Sopenharmony_ci	.driver = {
44362306a36Sopenharmony_ci		.name = "imx93-blk-ctrl",
44462306a36Sopenharmony_ci		.of_match_table = imx93_blk_ctrl_of_match,
44562306a36Sopenharmony_ci	},
44662306a36Sopenharmony_ci};
44762306a36Sopenharmony_cimodule_platform_driver(imx93_blk_ctrl_driver);
44862306a36Sopenharmony_ci
44962306a36Sopenharmony_ciMODULE_AUTHOR("Peng Fan <peng.fan@nxp.com>");
45062306a36Sopenharmony_ciMODULE_DESCRIPTION("i.MX93 BLK CTRL driver");
45162306a36Sopenharmony_ciMODULE_LICENSE("GPL");
452