diff --git a/drivers/clk/clk-fsl-sai.c b/drivers/clk/clk-fsl-sai.c index c595d340e00f..eded6a5fac21 100644 --- a/drivers/clk/clk-fsl-sai.c +++ b/drivers/clk/clk-fsl-sai.c @@ -16,19 +16,27 @@ #define I2S_CSR 0x00 #define I2S_CR2 0x08 +#define I2S_MCR 0x100 #define CSR_BCE_BIT 28 +#define CSR_TE_BIT 31 #define CR2_BCD BIT(24) #define CR2_DIV_SHIFT 0 #define CR2_DIV_WIDTH 8 +#define MCR_MOE BIT(30) struct fsl_sai_data { unsigned int offset; /* Register offset */ + bool have_mclk; /* Have MCLK control */ }; struct fsl_sai_clk { + const struct fsl_sai_data *data; struct clk_divider bclk_div; + struct clk_divider mclk_div; struct clk_gate bclk_gate; + struct clk_gate mclk_gate; struct clk_hw *bclk_hw; + struct clk_hw *mclk_hw; spinlock_t lock; }; @@ -37,7 +45,17 @@ fsl_sai_of_clk_get(struct of_phandle_args *clkspec, void *data) { struct fsl_sai_clk *sai_clk = data; - return sai_clk->bclk_hw; + if (clkspec->args_count == 0) + return sai_clk->bclk_hw; + + if (clkspec->args_count == 1) { + if (clkspec->args[0] == 0) + return sai_clk->bclk_hw; + if (sai_clk->data->have_mclk && clkspec->args[0] == 1) + return sai_clk->mclk_hw; + } + + return ERR_PTR(-EINVAL); } static int fsl_sai_clk_register(struct device *dev, void __iomem *base, @@ -104,6 +122,7 @@ static int fsl_sai_clk_probe(struct platform_device *pdev) if (IS_ERR(clk_bus)) return PTR_ERR(clk_bus); + sai_clk->data = data; spin_lock_init(&sai_clk->lock); ret = fsl_sai_clk_register(dev, base, &sai_clk->lock, @@ -113,15 +132,28 @@ static int fsl_sai_clk_probe(struct platform_device *pdev) if (ret) return ret; + if (data->have_mclk) { + ret = fsl_sai_clk_register(dev, base, &sai_clk->lock, + &sai_clk->mclk_div, + &sai_clk->mclk_gate, + &sai_clk->mclk_hw, + CSR_TE_BIT, MCR_MOE, I2S_MCR, + "MCLK"); + if (ret) + return ret; + } + return devm_of_clk_add_hw_provider(dev, fsl_sai_of_clk_get, sai_clk); } static const struct fsl_sai_data fsl_sai_vf610_data = { .offset = 0, + .have_mclk = false, }; static const struct fsl_sai_data fsl_sai_imx8mq_data = { .offset = 8, + .have_mclk = true, }; static const struct of_device_id of_fsl_sai_clk_ids[] = {