[PATCH 0/2] ASoC: q6afe: add clocks support
q6afe already exposes clocks using apis, but not as proper clock controller driver. This patch puts those clocks in to a proper clock controller so that other drivers that depend on those clocks can be properly expressed.
Srinivas Kandagatla (2): ASoC: q6afe: dt-bindings: add q6afe clock bindings ASoC: q6afe-clocks: add q6afe clock controller
.../devicetree/bindings/sound/qcom,q6afe.txt | 23 ++ include/dt-bindings/sound/qcom,q6afe.h | 74 ++++- sound/soc/qcom/Kconfig | 4 + sound/soc/qcom/qdsp6/Makefile | 1 + sound/soc/qcom/qdsp6/q6afe-clocks.c | 270 ++++++++++++++++++ 5 files changed, 371 insertions(+), 1 deletion(-) create mode 100644 sound/soc/qcom/qdsp6/q6afe-clocks.c
q6afe exposes various lpass clocks controls via q6dsp q6afe commands. This patch adds bindings required for this clock controller.
Signed-off-by: Srinivas Kandagatla srinivas.kandagatla@linaro.org --- .../devicetree/bindings/sound/qcom,q6afe.txt | 23 ++++++ include/dt-bindings/sound/qcom,q6afe.h | 74 ++++++++++++++++++- 2 files changed, 96 insertions(+), 1 deletion(-)
diff --git a/Documentation/devicetree/bindings/sound/qcom,q6afe.txt b/Documentation/devicetree/bindings/sound/qcom,q6afe.txt index 4916dd6a0896..2d6fb2ea75a0 100644 --- a/Documentation/devicetree/bindings/sound/qcom,q6afe.txt +++ b/Documentation/devicetree/bindings/sound/qcom,q6afe.txt @@ -98,6 +98,24 @@ configuration of each dai. Must contain the following properties. 0 - MSB 1 - LSB
+= AFE CLOCKSS +"clocks" subnode of the AFE node. It represents q6afe clocks +"clocks" node should have following properties. +- compatible: + Usage: required + Value type: <stringlist> + Definition: must be "qcom,q6afe-clocks" + +- #clock-cells: + Usage: required + Value type: <u32> + Definition: Must be 2. Clock Id followed by + below valid clock coupling attributes. + 1 - for no coupled clock + 2 - for dividend of the coupled clock + 3 - for divisor of the coupled clock + 4 - for inverted and no couple clock + = EXAMPLE
apr-service@4 { @@ -175,4 +193,9 @@ apr-service@4 { qcom,sd-lines = <1>; }; }; + + clocks { + compatible = "qcom,q6afe-clocks"; + #clock-cells = <2>; + }; }; diff --git a/include/dt-bindings/sound/qcom,q6afe.h b/include/dt-bindings/sound/qcom,q6afe.h index 7207ab2b57bf..f64b5d2e6efd 100644 --- a/include/dt-bindings/sound/qcom,q6afe.h +++ b/include/dt-bindings/sound/qcom,q6afe.h @@ -130,5 +130,77 @@ #define RX_CODEC_DMA_RX_6 125 #define RX_CODEC_DMA_RX_7 126
-#endif /* __DT_BINDINGS_Q6_AFE_H__ */ +#define LPASS_CLK_ID_PRI_MI2S_IBIT 1 +#define LPASS_CLK_ID_PRI_MI2S_EBIT 2 +#define LPASS_CLK_ID_SEC_MI2S_IBIT 3 +#define LPASS_CLK_ID_SEC_MI2S_EBIT 4 +#define LPASS_CLK_ID_TER_MI2S_IBIT 5 +#define LPASS_CLK_ID_TER_MI2S_EBIT 6 +#define LPASS_CLK_ID_QUAD_MI2S_IBIT 7 +#define LPASS_CLK_ID_QUAD_MI2S_EBIT 8 +#define LPASS_CLK_ID_SPEAKER_I2S_IBIT 9 +#define LPASS_CLK_ID_SPEAKER_I2S_EBIT 10 +#define LPASS_CLK_ID_SPEAKER_I2S_OSR 11 +#define LPASS_CLK_ID_QUI_MI2S_IBIT 12 +#define LPASS_CLK_ID_QUI_MI2S_EBIT 13 +#define LPASS_CLK_ID_SEN_MI2S_IBIT 14 +#define LPASS_CLK_ID_SEN_MI2S_EBIT 15 +#define LPASS_CLK_ID_INT0_MI2S_IBIT 16 +#define LPASS_CLK_ID_INT1_MI2S_IBIT 17 +#define LPASS_CLK_ID_INT2_MI2S_IBIT 18 +#define LPASS_CLK_ID_INT3_MI2S_IBIT 19 +#define LPASS_CLK_ID_INT4_MI2S_IBIT 20 +#define LPASS_CLK_ID_INT5_MI2S_IBIT 21 +#define LPASS_CLK_ID_INT6_MI2S_IBIT 22 +#define LPASS_CLK_ID_QUI_MI2S_OSR 23 +#define LPASS_CLK_ID_PRI_PCM_IBIT 24 +#define LPASS_CLK_ID_PRI_PCM_EBIT 25 +#define LPASS_CLK_ID_SEC_PCM_IBIT 26 +#define LPASS_CLK_ID_SEC_PCM_EBIT 27 +#define LPASS_CLK_ID_TER_PCM_IBIT 28 +#define LPASS_CLK_ID_TER_PCM_EBIT 29 +#define LPASS_CLK_ID_QUAD_PCM_IBIT 30 +#define LPASS_CLK_ID_QUAD_PCM_EBIT 31 +#define LPASS_CLK_ID_QUIN_PCM_IBIT 32 +#define LPASS_CLK_ID_QUIN_PCM_EBIT 33 +#define LPASS_CLK_ID_QUI_PCM_OSR 34 +#define LPASS_CLK_ID_PRI_TDM_IBIT 35 +#define LPASS_CLK_ID_PRI_TDM_EBIT 36 +#define LPASS_CLK_ID_SEC_TDM_IBIT 37 +#define LPASS_CLK_ID_SEC_TDM_EBIT 38 +#define LPASS_CLK_ID_TER_TDM_IBIT 39 +#define LPASS_CLK_ID_TER_TDM_EBIT 40 +#define LPASS_CLK_ID_QUAD_TDM_IBIT 41 +#define LPASS_CLK_ID_QUAD_TDM_EBIT 42 +#define LPASS_CLK_ID_QUIN_TDM_IBIT 43 +#define LPASS_CLK_ID_QUIN_TDM_EBIT 44 +#define LPASS_CLK_ID_QUIN_TDM_OSR 45 +#define LPASS_CLK_ID_MCLK_1 46 +#define LPASS_CLK_ID_MCLK_2 47 +#define LPASS_CLK_ID_MCLK_3 48 +#define LPASS_CLK_ID_MCLK_4 49 +#define LPASS_CLK_ID_INTERNAL_DIGITAL_CODEC_CORE 50 +#define LPASS_CLK_ID_INT_MCLK_0 51 +#define LPASS_CLK_ID_INT_MCLK_1 52 +#define LPASS_CLK_ID_MCLK_5 53 +#define LPASS_CLK_ID_WSA_CORE_MCLK 54 +#define LPASS_CLK_ID_WSA_CORE_NPL_MCLK 55 +#define LPASS_CLK_ID_VA_CORE_MCLK 56 +#define LPASS_CLK_ID_TX_CORE_MCLK 57 +#define LPASS_CLK_ID_TX_CORE_NPL_MCLK 58 +#define LPASS_CLK_ID_RX_CORE_MCLK 59 +#define LPASS_CLK_ID_RX_CORE_NPL_MCLK 60 +#define LPASS_CLK_ID_VA_CORE_2X_MCLK 61 + +#define LPASS_HW_AVTIMER_VOTE 101 +#define LPASS_HW_MACRO_VOTE 102 +#define LPASS_HW_DCODEC_VOTE 103 + +#define Q6AFE_MAX_CLK_ID 104
+#define LPASS_CLK_ATTRIBUTE_INVALID 0x0 +#define LPASS_CLK_ATTRIBUTE_COUPLE_NO 0x1 +#define LPASS_CLK_ATTRIBUTE_COUPLE_DIVIDEND 0x2 +#define LPASS_CLK_ATTRIBUTE_COUPLE_DIVISOR 0x3 + +#endif /* __DT_BINDINGS_Q6_AFE_H__ */
q6afe already exposes lpass clocks, however this was not presented as proper clock controller driver. This patch basically adds clock controller support for q6afe clocks.
This is useful for other drivers like lpass digital codec or lpass lowpower island drivers to request or vote for these clocks.
Signed-off-by: Srinivas Kandagatla srinivas.kandagatla@linaro.org --- sound/soc/qcom/Kconfig | 4 + sound/soc/qcom/qdsp6/Makefile | 1 + sound/soc/qcom/qdsp6/q6afe-clocks.c | 270 ++++++++++++++++++++++++++++ 3 files changed, 275 insertions(+) create mode 100644 sound/soc/qcom/qdsp6/q6afe-clocks.c
diff --git a/sound/soc/qcom/Kconfig b/sound/soc/qcom/Kconfig index a607ace8b089..a7ef62685b41 100644 --- a/sound/soc/qcom/Kconfig +++ b/sound/soc/qcom/Kconfig @@ -63,6 +63,9 @@ config SND_SOC_QDSP6_AFE config SND_SOC_QDSP6_AFE_DAI tristate
+config SND_SOC_QDSP6_AFE_CLOCKS + tristate + config SND_SOC_QDSP6_ADM tristate
@@ -83,6 +86,7 @@ config SND_SOC_QDSP6 select SND_SOC_QDSP6_CORE select SND_SOC_QDSP6_AFE select SND_SOC_QDSP6_AFE_DAI + select SND_SOC_QDSP6_AFE_CLOCKS select SND_SOC_QDSP6_ADM select SND_SOC_QDSP6_ROUTING select SND_SOC_QDSP6_ASM diff --git a/sound/soc/qcom/qdsp6/Makefile b/sound/soc/qcom/qdsp6/Makefile index 7e91e96f7ad5..3c1dd9f32f1d 100644 --- a/sound/soc/qcom/qdsp6/Makefile +++ b/sound/soc/qcom/qdsp6/Makefile @@ -3,6 +3,7 @@ obj-$(CONFIG_SND_SOC_QDSP6_COMMON) += q6dsp-common.o obj-$(CONFIG_SND_SOC_QDSP6_CORE) += q6core.o obj-$(CONFIG_SND_SOC_QDSP6_AFE) += q6afe.o obj-$(CONFIG_SND_SOC_QDSP6_AFE_DAI) += q6afe-dai.o +obj-$(CONFIG_SND_SOC_QDSP6_AFE_CLOCKS) += q6afe-clocks.o obj-$(CONFIG_SND_SOC_QDSP6_ADM) += q6adm.o obj-$(CONFIG_SND_SOC_QDSP6_ROUTING) += q6routing.o obj-$(CONFIG_SND_SOC_QDSP6_ASM) += q6asm.o diff --git a/sound/soc/qcom/qdsp6/q6afe-clocks.c b/sound/soc/qcom/qdsp6/q6afe-clocks.c new file mode 100644 index 000000000000..2967f4546af5 --- /dev/null +++ b/sound/soc/qcom/qdsp6/q6afe-clocks.c @@ -0,0 +1,270 @@ +// SPDX-License-Identifier: GPL-1.0 +// Copyright (c) 2020, Linaro Limited + +#include <linux/err.h> +#include <linux/init.h> +#include <linux/clk-provider.h> +#include <linux/module.h> +#include <linux/device.h> +#include <linux/platform_device.h> +#include <linux/of.h> +#include <linux/slab.h> +#include "q6afe.h" + +#define Q6AFE_CLK(id) &(struct q6afe_clk) { \ + .clk_id = id, \ + .afe_clk_id = Q6AFE_##id, \ + .name = #id, \ + .attributes = LPASS_CLK_ATTRIBUTE_COUPLE_NO, \ + .hw.init = &(struct clk_init_data) { \ + .ops = &clk_q6afe_ops, \ + .name = #id, \ + }, \ + } + +#define Q6AFE_VOTE_CLK(id, blkid, n) &(struct q6afe_clk) { \ + .clk_id = id, \ + .afe_clk_id = blkid, \ + .name = #n, \ + .hw.init = &(struct clk_init_data) { \ + .ops = &clk_vote_q6afe_ops, \ + .name = #id, \ + }, \ + } + +struct q6afe_clk { + struct device *dev; + int clk_id; + int afe_clk_id; + char *name; + int attributes; + int rate; + uint32_t handle; + struct clk_hw hw; +}; + +#define to_q6afe_clk(_hw) container_of(_hw, struct q6afe_clk, hw) + +struct q6afe_cc { + struct device *dev; + struct q6afe_clk **clks; + int num_clks; +}; + +static int clk_q6afe_prepare(struct clk_hw *hw) +{ + struct q6afe_clk *clk = to_q6afe_clk(hw); + + return q6afe_set_lpass_clock(clk->dev, clk->afe_clk_id, clk->attributes, + Q6AFE_LPASS_CLK_ROOT_DEFAULT, clk->rate); +} + +static void clk_q6afe_unprepare(struct clk_hw *hw) +{ + struct q6afe_clk *clk = to_q6afe_clk(hw); + + q6afe_set_lpass_clock(clk->dev, clk->afe_clk_id, clk->attributes, + Q6AFE_LPASS_CLK_ROOT_DEFAULT, 0); +} + +static int clk_q6afe_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct q6afe_clk *clk = to_q6afe_clk(hw); + + clk->rate = rate; + + return 0; +} + +static unsigned long clk_q6afe_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct q6afe_clk *clk = to_q6afe_clk(hw); + + return clk->rate; +} + +static long clk_q6afe_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *parent_rate) +{ + return rate; +} + +static const struct clk_ops clk_q6afe_ops = { + .prepare = clk_q6afe_prepare, + .unprepare = clk_q6afe_unprepare, + .set_rate = clk_q6afe_set_rate, + .round_rate = clk_q6afe_round_rate, + .recalc_rate = clk_q6afe_recalc_rate, +}; + +static int clk_vote_q6afe_block(struct clk_hw *hw) +{ + struct q6afe_clk *clk = to_q6afe_clk(hw); + + return q6afe_vote_lpass_core_hw(clk->dev, clk->afe_clk_id, + clk->name, &clk->handle); +} + +static void clk_unvote_q6afe_block(struct clk_hw *hw) +{ + struct q6afe_clk *clk = to_q6afe_clk(hw); + + q6afe_unvote_lpass_core_hw(clk->dev, clk->afe_clk_id, clk->handle); +} + +static const struct clk_ops clk_vote_q6afe_ops = { + .prepare = clk_vote_q6afe_block, + .unprepare = clk_unvote_q6afe_block, +}; + +struct q6afe_clk *q6afe_clks[Q6AFE_MAX_CLK_ID] = { + [LPASS_CLK_ID_PRI_MI2S_IBIT] = Q6AFE_CLK(LPASS_CLK_ID_PRI_MI2S_IBIT), + [LPASS_CLK_ID_PRI_MI2S_EBIT] = Q6AFE_CLK(LPASS_CLK_ID_PRI_MI2S_EBIT), + [LPASS_CLK_ID_SEC_MI2S_IBIT] = Q6AFE_CLK(LPASS_CLK_ID_SEC_MI2S_IBIT), + [LPASS_CLK_ID_SEC_MI2S_EBIT] = Q6AFE_CLK(LPASS_CLK_ID_SEC_MI2S_EBIT), + [LPASS_CLK_ID_TER_MI2S_IBIT] = Q6AFE_CLK(LPASS_CLK_ID_TER_MI2S_IBIT), + [LPASS_CLK_ID_TER_MI2S_EBIT] = Q6AFE_CLK(LPASS_CLK_ID_TER_MI2S_EBIT), + [LPASS_CLK_ID_QUAD_MI2S_IBIT] = Q6AFE_CLK(LPASS_CLK_ID_QUAD_MI2S_IBIT), + [LPASS_CLK_ID_QUAD_MI2S_EBIT] = Q6AFE_CLK(LPASS_CLK_ID_QUAD_MI2S_EBIT), + [LPASS_CLK_ID_SPEAKER_I2S_IBIT] = + Q6AFE_CLK(LPASS_CLK_ID_SPEAKER_I2S_IBIT), + [LPASS_CLK_ID_SPEAKER_I2S_EBIT] = + Q6AFE_CLK(LPASS_CLK_ID_SPEAKER_I2S_EBIT), + [LPASS_CLK_ID_SPEAKER_I2S_OSR] = + Q6AFE_CLK(LPASS_CLK_ID_SPEAKER_I2S_OSR), + [LPASS_CLK_ID_QUI_MI2S_IBIT] = Q6AFE_CLK(LPASS_CLK_ID_QUI_MI2S_IBIT), + [LPASS_CLK_ID_QUI_MI2S_EBIT] = Q6AFE_CLK(LPASS_CLK_ID_QUI_MI2S_EBIT), + [LPASS_CLK_ID_SEN_MI2S_IBIT] = Q6AFE_CLK(LPASS_CLK_ID_SEN_MI2S_IBIT), + [LPASS_CLK_ID_SEN_MI2S_EBIT] = Q6AFE_CLK(LPASS_CLK_ID_SEN_MI2S_EBIT), + [LPASS_CLK_ID_INT0_MI2S_IBIT] = Q6AFE_CLK(LPASS_CLK_ID_INT0_MI2S_IBIT), + [LPASS_CLK_ID_INT1_MI2S_IBIT] = Q6AFE_CLK(LPASS_CLK_ID_INT1_MI2S_IBIT), + [LPASS_CLK_ID_INT2_MI2S_IBIT] = Q6AFE_CLK(LPASS_CLK_ID_INT2_MI2S_IBIT), + [LPASS_CLK_ID_INT3_MI2S_IBIT] = Q6AFE_CLK(LPASS_CLK_ID_INT3_MI2S_IBIT), + [LPASS_CLK_ID_INT4_MI2S_IBIT] = Q6AFE_CLK(LPASS_CLK_ID_INT4_MI2S_IBIT), + [LPASS_CLK_ID_INT5_MI2S_IBIT] = Q6AFE_CLK(LPASS_CLK_ID_INT5_MI2S_IBIT), + [LPASS_CLK_ID_INT6_MI2S_IBIT] = Q6AFE_CLK(LPASS_CLK_ID_INT6_MI2S_IBIT), + [LPASS_CLK_ID_QUI_MI2S_OSR] = Q6AFE_CLK(LPASS_CLK_ID_QUI_MI2S_OSR), + [LPASS_CLK_ID_PRI_PCM_IBIT] = Q6AFE_CLK(LPASS_CLK_ID_PRI_PCM_IBIT), + [LPASS_CLK_ID_PRI_PCM_EBIT] = Q6AFE_CLK(LPASS_CLK_ID_PRI_PCM_EBIT), + [LPASS_CLK_ID_SEC_PCM_IBIT] = Q6AFE_CLK(LPASS_CLK_ID_SEC_PCM_IBIT), + [LPASS_CLK_ID_SEC_PCM_EBIT] = Q6AFE_CLK(LPASS_CLK_ID_SEC_PCM_EBIT), + [LPASS_CLK_ID_TER_PCM_IBIT] = Q6AFE_CLK(LPASS_CLK_ID_TER_PCM_IBIT), + [LPASS_CLK_ID_TER_PCM_EBIT] = Q6AFE_CLK(LPASS_CLK_ID_TER_PCM_EBIT), + [LPASS_CLK_ID_QUAD_PCM_IBIT] = Q6AFE_CLK(LPASS_CLK_ID_QUAD_PCM_IBIT), + [LPASS_CLK_ID_QUAD_PCM_EBIT] = Q6AFE_CLK(LPASS_CLK_ID_QUAD_PCM_EBIT), + [LPASS_CLK_ID_QUIN_PCM_IBIT] = Q6AFE_CLK(LPASS_CLK_ID_QUIN_PCM_IBIT), + [LPASS_CLK_ID_QUIN_PCM_EBIT] = Q6AFE_CLK(LPASS_CLK_ID_QUIN_PCM_EBIT), + [LPASS_CLK_ID_QUI_PCM_OSR] = Q6AFE_CLK(LPASS_CLK_ID_QUI_PCM_OSR), + [LPASS_CLK_ID_PRI_TDM_IBIT] = Q6AFE_CLK(LPASS_CLK_ID_PRI_TDM_IBIT), + [LPASS_CLK_ID_PRI_TDM_EBIT] = Q6AFE_CLK(LPASS_CLK_ID_PRI_TDM_EBIT), + [LPASS_CLK_ID_SEC_TDM_IBIT] = Q6AFE_CLK(LPASS_CLK_ID_SEC_TDM_IBIT), + [LPASS_CLK_ID_SEC_TDM_EBIT] = Q6AFE_CLK(LPASS_CLK_ID_SEC_TDM_EBIT), + [LPASS_CLK_ID_TER_TDM_IBIT] = Q6AFE_CLK(LPASS_CLK_ID_TER_TDM_IBIT), + [LPASS_CLK_ID_TER_TDM_EBIT] = Q6AFE_CLK(LPASS_CLK_ID_TER_TDM_EBIT), + [LPASS_CLK_ID_QUAD_TDM_IBIT] = Q6AFE_CLK(LPASS_CLK_ID_QUAD_TDM_IBIT), + [LPASS_CLK_ID_QUAD_TDM_EBIT] = Q6AFE_CLK(LPASS_CLK_ID_QUAD_TDM_EBIT), + [LPASS_CLK_ID_QUIN_TDM_IBIT] = Q6AFE_CLK(LPASS_CLK_ID_QUIN_TDM_IBIT), + [LPASS_CLK_ID_QUIN_TDM_EBIT] = Q6AFE_CLK(LPASS_CLK_ID_QUIN_TDM_EBIT), + [LPASS_CLK_ID_QUIN_TDM_OSR] = Q6AFE_CLK(LPASS_CLK_ID_QUIN_TDM_OSR), + [LPASS_CLK_ID_MCLK_1] = Q6AFE_CLK(LPASS_CLK_ID_MCLK_1), + [LPASS_CLK_ID_MCLK_2] = Q6AFE_CLK(LPASS_CLK_ID_MCLK_2), + [LPASS_CLK_ID_MCLK_3] = Q6AFE_CLK(LPASS_CLK_ID_MCLK_3), + [LPASS_CLK_ID_MCLK_4] = Q6AFE_CLK(LPASS_CLK_ID_MCLK_4), + [LPASS_CLK_ID_INTERNAL_DIGITAL_CODEC_CORE] = + Q6AFE_CLK(LPASS_CLK_ID_INTERNAL_DIGITAL_CODEC_CORE), + [LPASS_CLK_ID_INT_MCLK_0] = Q6AFE_CLK(LPASS_CLK_ID_INT_MCLK_0), + [LPASS_CLK_ID_INT_MCLK_1] = Q6AFE_CLK(LPASS_CLK_ID_INT_MCLK_1), + [LPASS_CLK_ID_WSA_CORE_MCLK] = Q6AFE_CLK(LPASS_CLK_ID_WSA_CORE_MCLK), + [LPASS_CLK_ID_WSA_CORE_NPL_MCLK] = + Q6AFE_CLK(LPASS_CLK_ID_WSA_CORE_NPL_MCLK), + [LPASS_CLK_ID_VA_CORE_MCLK] = Q6AFE_CLK(LPASS_CLK_ID_VA_CORE_MCLK), + [LPASS_CLK_ID_TX_CORE_MCLK] = Q6AFE_CLK(LPASS_CLK_ID_TX_CORE_MCLK), + [LPASS_CLK_ID_TX_CORE_NPL_MCLK] = + Q6AFE_CLK(LPASS_CLK_ID_TX_CORE_NPL_MCLK), + [LPASS_CLK_ID_RX_CORE_MCLK] = Q6AFE_CLK(LPASS_CLK_ID_RX_CORE_MCLK), + [LPASS_CLK_ID_RX_CORE_NPL_MCLK] = + Q6AFE_CLK(LPASS_CLK_ID_RX_CORE_NPL_MCLK), + [LPASS_CLK_ID_VA_CORE_2X_MCLK] = + Q6AFE_CLK(LPASS_CLK_ID_VA_CORE_2X_MCLK), + [LPASS_HW_AVTIMER_VOTE] = Q6AFE_VOTE_CLK(LPASS_HW_AVTIMER_VOTE, + Q6AFE_LPASS_CORE_AVTIMER_BLOCK, + "LPASS_AVTIMER_MACRO"), + [LPASS_HW_MACRO_VOTE] = Q6AFE_VOTE_CLK(LPASS_HW_MACRO_VOTE, + Q6AFE_LPASS_CORE_HW_MACRO_BLOCK, + "LPASS_HW_MACRO"), + [LPASS_HW_DCODEC_VOTE] = Q6AFE_VOTE_CLK(LPASS_HW_DCODEC_VOTE, + Q6AFE_LPASS_CORE_HW_DCODEC_BLOCK, + "LPASS_HW_DCODEC"), +}; + +static struct clk_hw *q6afe_of_clk_hw_get(struct of_phandle_args *clkspec, + void *data) +{ + struct q6afe_cc *cc = data; + unsigned int idx = clkspec->args[0]; + unsigned int attr = clkspec->args[1]; + + if (idx >= cc->num_clks || attr > LPASS_CLK_ATTRIBUTE_COUPLE_DIVISOR) { + dev_err(cc->dev, "Invalid clk specifier (%d, %d)\n", idx, attr); + return ERR_PTR(-EINVAL); + } + + if (cc->clks[idx]) { + cc->clks[idx]->attributes = attr; + return &cc->clks[idx]->hw; + } + + return ERR_PTR(-ENOENT); +} + +static int q6afe_clock_dev_probe(struct platform_device *pdev) +{ + struct q6afe_cc *cc; + struct device *dev = &pdev->dev; + int i, ret; + + cc = devm_kzalloc(dev, sizeof(*cc), GFP_KERNEL); + if (!cc) + return -ENOMEM; + + cc->clks = &q6afe_clks[0]; + cc->num_clks = ARRAY_SIZE(q6afe_clks); + for (i = 0; i < ARRAY_SIZE(q6afe_clks); i++) { + if (!q6afe_clks[i]) + continue; + + q6afe_clks[i]->dev = dev; + + ret = devm_clk_hw_register(dev, &q6afe_clks[i]->hw); + if (ret) + return ret; + } + + ret = of_clk_add_hw_provider(dev->of_node, q6afe_of_clk_hw_get, cc); + if (ret) + return ret; + + dev_set_drvdata(dev, cc); + + return 0; +} + +static const struct of_device_id q6afe_clock_device_id[] = { + { .compatible = "qcom,q6afe-clocks" }, + {}, +}; +MODULE_DEVICE_TABLE(of, q6afe_clock_device_id); + +static struct platform_driver q6afe_clock_platform_driver = { + .driver = { + .name = "q6afe-clock", + .of_match_table = of_match_ptr(q6afe_clock_device_id), + }, + .probe = q6afe_clock_dev_probe, +}; +module_platform_driver(q6afe_clock_platform_driver); + +MODULE_DESCRIPTION("Q6 Audio Frontend clock driver"); +MODULE_LICENSE("GPL v2");
On Thu, 10 Sep 2020 14:57:06 +0100, Srinivas Kandagatla wrote:
q6afe already exposes clocks using apis, but not as proper clock controller driver. This patch puts those clocks in to a proper clock controller so that other drivers that depend on those clocks can be properly expressed.
Srinivas Kandagatla (2): ASoC: q6afe: dt-bindings: add q6afe clock bindings ASoC: q6afe-clocks: add q6afe clock controller
[...]
Applied to
https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-next
Thanks!
[1/2] ASoC: q6afe: dt-bindings: add q6afe clock bindings commit: 4e398353a7e51410c34fd19f8b7dfc56fff5901b [2/2] ASoC: q6afe-clocks: add q6afe clock controller commit: 520a1c396d1966b64884d8e0176a580150d5a09e
All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying to this mail.
Thanks, Mark
participants (2)
-
Mark Brown
-
Srinivas Kandagatla