Skip to content

Commit 6358c88

Browse files
Marek Vasutbebarino
authored andcommitted
clk: fsl-sai: Add MCLK generation support
The driver currently supports generating BCLK. There are systems which require generation of MCLK instead. Register new MCLK clock and handle clock-cells = <1> to differentiate between BCLK and MCLK. In case of a legacy system with clock-cells = <0>, the driver behaves as before, i.e. always returns BCLK. Note that it is not possible re-use the current SAI audio driver to generate MCLK and correctly enable and disable the MCLK. If SAI (audio driver) is used to control the MCLK enablement, then MCLK clock is not always enabled, and it is not necessarily enabled when the codec may need the clock to be enabled. There is also no way for the codec node to specify phandle to clock provider in DT, because the SAI (audio driver) is not clock provider. If SAI (clock driver) is used to control the MCLK enablement, then MCLK clock is enabled when the codec needs the clock enabled, because the codec is the clock consumer and the SAI (clock driver) is the clock provider, and the codec driver can request the clock to be enabled when needed. There is also the usual phandle to clock provider in DT, because the SAI (clock driver) is clock provider. Acked-by: Michael Walle <mwalle@kernel.org> Signed-off-by: Marek Vasut <marex@nabladev.com> Reviewed-by: Brian Masney <bmasney@redhat.com> Signed-off-by: Stephen Boyd <sboyd@kernel.org>
1 parent 32b0c7a commit 6358c88

1 file changed

Lines changed: 33 additions & 1 deletion

File tree

drivers/clk/clk-fsl-sai.c

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,19 +16,27 @@
1616

1717
#define I2S_CSR 0x00
1818
#define I2S_CR2 0x08
19+
#define I2S_MCR 0x100
1920
#define CSR_BCE_BIT 28
21+
#define CSR_TE_BIT 31
2022
#define CR2_BCD BIT(24)
2123
#define CR2_DIV_SHIFT 0
2224
#define CR2_DIV_WIDTH 8
25+
#define MCR_MOE BIT(30)
2326

2427
struct fsl_sai_data {
2528
unsigned int offset; /* Register offset */
29+
bool have_mclk; /* Have MCLK control */
2630
};
2731

2832
struct fsl_sai_clk {
33+
const struct fsl_sai_data *data;
2934
struct clk_divider bclk_div;
35+
struct clk_divider mclk_div;
3036
struct clk_gate bclk_gate;
37+
struct clk_gate mclk_gate;
3138
struct clk_hw *bclk_hw;
39+
struct clk_hw *mclk_hw;
3240
spinlock_t lock;
3341
};
3442

@@ -37,7 +45,17 @@ fsl_sai_of_clk_get(struct of_phandle_args *clkspec, void *data)
3745
{
3846
struct fsl_sai_clk *sai_clk = data;
3947

40-
return sai_clk->bclk_hw;
48+
if (clkspec->args_count == 0)
49+
return sai_clk->bclk_hw;
50+
51+
if (clkspec->args_count == 1) {
52+
if (clkspec->args[0] == 0)
53+
return sai_clk->bclk_hw;
54+
if (sai_clk->data->have_mclk && clkspec->args[0] == 1)
55+
return sai_clk->mclk_hw;
56+
}
57+
58+
return ERR_PTR(-EINVAL);
4159
}
4260

4361
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)
104122
if (IS_ERR(clk_bus))
105123
return PTR_ERR(clk_bus);
106124

125+
sai_clk->data = data;
107126
spin_lock_init(&sai_clk->lock);
108127

109128
ret = fsl_sai_clk_register(dev, base, &sai_clk->lock,
@@ -113,15 +132,28 @@ static int fsl_sai_clk_probe(struct platform_device *pdev)
113132
if (ret)
114133
return ret;
115134

135+
if (data->have_mclk) {
136+
ret = fsl_sai_clk_register(dev, base, &sai_clk->lock,
137+
&sai_clk->mclk_div,
138+
&sai_clk->mclk_gate,
139+
&sai_clk->mclk_hw,
140+
CSR_TE_BIT, MCR_MOE, I2S_MCR,
141+
"MCLK");
142+
if (ret)
143+
return ret;
144+
}
145+
116146
return devm_of_clk_add_hw_provider(dev, fsl_sai_of_clk_get, sai_clk);
117147
}
118148

119149
static const struct fsl_sai_data fsl_sai_vf610_data = {
120150
.offset = 0,
151+
.have_mclk = false,
121152
};
122153

123154
static const struct fsl_sai_data fsl_sai_imx8mq_data = {
124155
.offset = 8,
156+
.have_mclk = true,
125157
};
126158

127159
static const struct of_device_id of_fsl_sai_clk_ids[] = {

0 commit comments

Comments
 (0)