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, ®map_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