diff options
Diffstat (limited to 'sound/soc/fsl/fsl_mqs.c')
-rw-r--r-- | sound/soc/fsl/fsl_mqs.c | 128 |
1 files changed, 113 insertions, 15 deletions
diff --git a/sound/soc/fsl/fsl_mqs.c b/sound/soc/fsl/fsl_mqs.c index 60929c36a0e3..e34e5ea98de5 100644 --- a/sound/soc/fsl/fsl_mqs.c +++ b/sound/soc/fsl/fsl_mqs.c @@ -6,6 +6,7 @@ // Copyright 2019 NXP #include <linux/clk.h> +#include <linux/firmware/imx/sm.h> #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/mfd/syscon.h> @@ -28,10 +29,16 @@ #define MQS_CLK_DIV_MASK (0xFF << 0) #define MQS_CLK_DIV_SHIFT (0) +enum reg_type { + TYPE_REG_OWN, /* module own register space */ + TYPE_REG_GPR, /* register in GPR space */ + TYPE_REG_SM, /* System Manager controls the register */ +}; + /** * struct fsl_mqs_soc_data - soc specific data * - * @use_gpr: control register is in General Purpose Register group + * @type: control register space type * @ctrl_off: control register offset * @en_mask: enable bit mask * @en_shift: enable bit shift @@ -43,7 +50,7 @@ * @div_shift: clock divider bit shift */ struct fsl_mqs_soc_data { - bool use_gpr; + enum reg_type type; int ctrl_off; int en_mask; int en_shift; @@ -68,6 +75,29 @@ struct fsl_mqs { #define FSL_MQS_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000) #define FSL_MQS_FORMATS SNDRV_PCM_FMTBIT_S16_LE +static int fsl_mqs_sm_read(void *context, unsigned int reg, unsigned int *val) +{ + struct fsl_mqs *mqs_priv = context; + int num = 1; + + if (IS_ENABLED(CONFIG_IMX_SCMI_MISC_DRV) && + mqs_priv->soc->ctrl_off == reg) + return scmi_imx_misc_ctrl_get(SCMI_IMX_CTRL_MQS1_SETTINGS, &num, val); + + return -EINVAL; +}; + +static int fsl_mqs_sm_write(void *context, unsigned int reg, unsigned int val) +{ + struct fsl_mqs *mqs_priv = context; + + if (IS_ENABLED(CONFIG_IMX_SCMI_MISC_DRV) && + mqs_priv->soc->ctrl_off == reg) + return scmi_imx_misc_ctrl_set(SCMI_IMX_CTRL_MQS1_SETTINGS, val); + + return -EINVAL; +}; + static int fsl_mqs_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) @@ -182,6 +212,13 @@ static const struct regmap_config fsl_mqs_regmap_config = { .cache_type = REGCACHE_NONE, }; +static const struct regmap_config fsl_mqs_sm_regmap = { + .reg_bits = 32, + .val_bits = 32, + .reg_read = fsl_mqs_sm_read, + .reg_write = fsl_mqs_sm_write, +}; + static int fsl_mqs_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; @@ -200,7 +237,7 @@ static int fsl_mqs_probe(struct platform_device *pdev) */ mqs_priv->soc = of_device_get_match_data(&pdev->dev); - if (mqs_priv->soc->use_gpr) { + if (mqs_priv->soc->type == TYPE_REG_GPR) { gpr_np = of_parse_phandle(np, "gpr", 0); if (!gpr_np) { dev_err(&pdev->dev, "failed to get gpr node by phandle\n"); @@ -213,6 +250,16 @@ static int fsl_mqs_probe(struct platform_device *pdev) dev_err(&pdev->dev, "failed to get gpr regmap\n"); return PTR_ERR(mqs_priv->regmap); } + } else if (mqs_priv->soc->type == TYPE_REG_SM) { + mqs_priv->regmap = devm_regmap_init(&pdev->dev, + NULL, + mqs_priv, + &fsl_mqs_sm_regmap); + if (IS_ERR(mqs_priv->regmap)) { + dev_err(&pdev->dev, "failed to init regmap: %ld\n", + PTR_ERR(mqs_priv->regmap)); + return PTR_ERR(mqs_priv->regmap); + } } else { regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(regs)) @@ -259,7 +306,6 @@ static void fsl_mqs_remove(struct platform_device *pdev) pm_runtime_disable(&pdev->dev); } -#ifdef CONFIG_PM static int fsl_mqs_runtime_resume(struct device *dev) { struct fsl_mqs *mqs_priv = dev_get_drvdata(dev); @@ -293,18 +339,14 @@ static int fsl_mqs_runtime_suspend(struct device *dev) return 0; } -#endif static const struct dev_pm_ops fsl_mqs_pm_ops = { - SET_RUNTIME_PM_OPS(fsl_mqs_runtime_suspend, - fsl_mqs_runtime_resume, - NULL) - SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, - pm_runtime_force_resume) + RUNTIME_PM_OPS(fsl_mqs_runtime_suspend, fsl_mqs_runtime_resume, NULL) + SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume) }; static const struct fsl_mqs_soc_data fsl_mqs_imx8qm_data = { - .use_gpr = false, + .type = TYPE_REG_OWN, .ctrl_off = REG_MQS_CTRL, .en_mask = MQS_EN_MASK, .en_shift = MQS_EN_SHIFT, @@ -317,7 +359,7 @@ static const struct fsl_mqs_soc_data fsl_mqs_imx8qm_data = { }; static const struct fsl_mqs_soc_data fsl_mqs_imx6sx_data = { - .use_gpr = true, + .type = TYPE_REG_GPR, .ctrl_off = IOMUXC_GPR2, .en_mask = IMX6SX_GPR2_MQS_EN_MASK, .en_shift = IMX6SX_GPR2_MQS_EN_SHIFT, @@ -330,7 +372,7 @@ static const struct fsl_mqs_soc_data fsl_mqs_imx6sx_data = { }; static const struct fsl_mqs_soc_data fsl_mqs_imx93_data = { - .use_gpr = true, + .type = TYPE_REG_GPR, .ctrl_off = 0x20, .en_mask = BIT(1), .en_shift = 1, @@ -342,21 +384,77 @@ static const struct fsl_mqs_soc_data fsl_mqs_imx93_data = { .div_shift = 8, }; +static const struct fsl_mqs_soc_data fsl_mqs_imx95_aon_data = { + .type = TYPE_REG_SM, + .ctrl_off = 0x88, + .en_mask = BIT(1), + .en_shift = 1, + .rst_mask = BIT(2), + .rst_shift = 2, + .osr_mask = BIT(3), + .osr_shift = 3, + .div_mask = GENMASK(15, 8), + .div_shift = 8, +}; + +static const struct fsl_mqs_soc_data fsl_mqs_imx95_netc_data = { + .type = TYPE_REG_GPR, + .ctrl_off = 0x0, + .en_mask = BIT(2), + .en_shift = 2, + .rst_mask = BIT(3), + .rst_shift = 3, + .osr_mask = BIT(4), + .osr_shift = 4, + .div_mask = GENMASK(16, 9), + .div_shift = 9, +}; + +static const struct fsl_mqs_soc_data fsl_mqs_imx943_aon_data = { + .type = TYPE_REG_SM, + .ctrl_off = 0x88, + .en_mask = BIT(1), + .en_shift = 1, + .rst_mask = BIT(2), + .rst_shift = 2, + .osr_mask = BIT(3), + .osr_shift = 3, + .div_mask = GENMASK(15, 8), + .div_shift = 8, +}; + +static const struct fsl_mqs_soc_data fsl_mqs_imx943_wakeup_data = { + .type = TYPE_REG_GPR, + .ctrl_off = 0x10, + .en_mask = BIT(1), + .en_shift = 1, + .rst_mask = BIT(2), + .rst_shift = 2, + .osr_mask = BIT(3), + .osr_shift = 3, + .div_mask = GENMASK(15, 8), + .div_shift = 8, +}; + static const struct of_device_id fsl_mqs_dt_ids[] = { { .compatible = "fsl,imx8qm-mqs", .data = &fsl_mqs_imx8qm_data }, { .compatible = "fsl,imx6sx-mqs", .data = &fsl_mqs_imx6sx_data }, { .compatible = "fsl,imx93-mqs", .data = &fsl_mqs_imx93_data }, + { .compatible = "fsl,imx95-aonmix-mqs", .data = &fsl_mqs_imx95_aon_data }, + { .compatible = "fsl,imx95-netcmix-mqs", .data = &fsl_mqs_imx95_netc_data }, + { .compatible = "fsl,imx943-aonmix-mqs", .data = &fsl_mqs_imx943_aon_data }, + { .compatible = "fsl,imx943-wakeupmix-mqs", .data = &fsl_mqs_imx943_wakeup_data }, {} }; MODULE_DEVICE_TABLE(of, fsl_mqs_dt_ids); static struct platform_driver fsl_mqs_driver = { .probe = fsl_mqs_probe, - .remove_new = fsl_mqs_remove, + .remove = fsl_mqs_remove, .driver = { .name = "fsl-mqs", .of_match_table = fsl_mqs_dt_ids, - .pm = &fsl_mqs_pm_ops, + .pm = pm_ptr(&fsl_mqs_pm_ops), }, }; |