Add audio clocks support for ZTE ZX296718
Subsystems (2)
v2 cover Add audio clocks support for ZTE ZX296718
From: Shawn Guo <[email protected]>
It adds missing audio related clocks for ZTE SoC ZX296718. With these clocks added, we can get HDMI audio work through SPDIF interface.
Changes for v2:
- Add a patch to clean up existing driver code.
- Clean up unused divider configuration lookup table.
- Use uintptr_t instead of u64 to cast 'reg_base' for summation.
- Instead of panic, give an error message and return error code when of_clk_add_hw_provider() call fails.
- Drop unnecessary ulong type cast.
- Use pr_debug instead of pr_info to avoid noisy messages
Jun Nie (1):
clk: zte: add audio clocks for zx296718
Shawn Guo (2):
clk: zx296718: do not panic on failure
dt-bindings: zx296718-clk: add compatible for audio clock controller
.../devicetree/bindings/clock/zx296718-clk.txt | 3 + drivers/clk/zte/clk-zx296718.c | 154 +++++++++++++++++++-- drivers/clk/zte/clk.c | 127 +++++++++++++++++ drivers/clk/zte/clk.h | 21 +++ 4 files changed, 296 insertions(+), 9 deletions(-)
Signature · 1 line
1.9.1
PATCH v2 1/3 clk: zx296718: do not panic on failure
From: Shawn Guo <[email protected]>
Instead of using panic, we should give an error message and return error code when of_clk_add_hw_provider() call fails.
Since we have error prompt for failures, the "init over" pr_info output isn't really necessary but becomes a debug noise. So let's clean it up along the way.
--- drivers/clk/zte/clk-zx296718.c | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-)
drivers/clk/zte/clk-zx296718.c +18 -9
@@ -610,9 +610,12 @@ static int __init top_clocks_init(struct device_node *np) } } -if (of_clk_add_hw_provider (np, of_clk_hw_onecell_get, &top_hw_onecell_data)) -panic ("could not register clk provider\n" ); -pr_info ("top clk init over, nr:%d\n" ,TOP_NR_CLKS ); + ret =of_clk_add_hw_provider (np, of_clk_hw_onecell_get, + &top_hw_onecell_data); +if (ret) { +pr_err ("failed to register top clk provider: %d\n" , ret); +return ret; + }return 0 ; }
@@ -776,9 +779,12 @@ static int __init lsp0_clocks_init(struct device_node *np) } } -if (of_clk_add_hw_provider (np, of_clk_hw_onecell_get, &lsp0_hw_onecell_data)) -panic ("could not register clk provider\n" ); -pr_info ("lsp0-clk init over:%d\n" ,LSP0_NR_CLKS ); + ret =of_clk_add_hw_provider (np, of_clk_hw_onecell_get, + &lsp0_hw_onecell_data); +if (ret) { +pr_err ("failed to register lsp0 clk provider: %d\n" , ret); +return ret; + }return 0 ; }
@@ -881,9 +887,12 @@ static int __init lsp1_clocks_init(struct device_node *np) } } -if (of_clk_add_hw_provider (np, of_clk_hw_onecell_get, &lsp1_hw_onecell_data)) -panic ("could not register clk provider\n" ); -pr_info ("lsp1-clk init over, nr:%d\n" ,LSP1_NR_CLKS ); + ret =of_clk_add_hw_provider (np, of_clk_hw_onecell_get, + &lsp1_hw_onecell_data); +if (ret) { +pr_err ("failed to register lsp1 clk provider: %d\n" , ret); +return ret; + }return 0 ; }
Signature · 1 line
1.9.1
Stephen Boyd
AppliedPATCH v2 1/3 clk: zx296718: do not panic on failure
Quoted 11 lines · Shawn Guo
From: Shawn Guo <[email protected]>
Instead of using panic, we should give an error message and return error code when
of_clk_add_hw_provider()call fails.Since we have error prompt for failures, the "init over"
pr_infooutput isn't really necessary but becomes a debug noise. So let's clean it up along the way.Signed-off-by Shawn Guo <[email protected]>---
Applied to clk-next
Signature · 2 lines
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project
PATCH v2 2/3 dt-bindings: zx296718-clk: add compatible for audio clock controller
In reply to Shawn GuoFrom: Shawn Guo <[email protected]>
It adds the compatible string for zx296718 audio clock controller.
--- Documentation/devicetree/bindings/clock/zx296718-clk.txt | 3 +++ 1 file changed, 3 insertions(+)
Documentation/devicetree/bindings/clock/zx296718-clk.txt +3 -0
@@ -13,6 +13,9 @@ Required properties: "zte,zx296718-lsp1crm": zx296718 device level clock selection and gating + "zte,zx296718-audiocrm": + zx296718 audio clock selection, divider and gating + - reg: Address and length of the register set The clock consumer should specify the desired clock by having the clock
Signature · 1 line
1.9.1
Stephen Boyd
AppliedPATCH v2 2/3 dt-bindings: zx296718-clk: add compatible for audio clock controller
Quoted 7 lines · Shawn Guo
From: Shawn Guo <[email protected]>
It adds the compatible string for zx296718 audio clock controller.
Signed-off-by Shawn Guo <[email protected]>Acked-by Rob Herring <[email protected]>---
Applied to clk-next
Signature · 2 lines
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project
PATCH v2 3/3 clk: zte: add audio clocks for zx296718
In reply to Shawn GuoFrom: Jun Nie <[email protected]>
The audio related clock support is missing from the existing zx296718 clock driver. Let's add it, so that the upstream ZX SPDIF driver can work for HDMI audio support.
--- drivers/clk/zte/clk-zx296718.c | 127 +++++++++++++++++++++++++++++++++++++++++ drivers/clk/zte/clk.c | 127 +++++++++++++++++++++++++++++++++++++++++ drivers/clk/zte/clk.h | 21 +++++++ 3 files changed, 275 insertions(+)
drivers/clk/zte/clk-zx296718.c +127 -0
@@ -897,10 +897,137 @@ static int __init lsp1_clocks_init(struct device_node *np)return 0 ; } +PNAME (audio_wclk_common_p) = { +"audio_99m" , +"audio_24m" , +}; + +PNAME (audio_timer_p) = { +"audio_24m" , +"audio_32k" , +}; + +static struct zx_clk_mux audio_mux_clk[] = { +MUX (0 ,"i2s0_wclk_mux" , audio_wclk_common_p,AUDIO_I2S0_CLK ,0 ,1 ), +MUX (0 ,"i2s1_wclk_mux" , audio_wclk_common_p,AUDIO_I2S1_CLK ,0 ,1 ), +MUX (0 ,"i2s2_wclk_mux" , audio_wclk_common_p,AUDIO_I2S2_CLK ,0 ,1 ), +MUX (0 ,"i2s3_wclk_mux" , audio_wclk_common_p,AUDIO_I2S3_CLK ,0 ,1 ), +MUX (0 ,"i2c0_wclk_mux" , audio_wclk_common_p,AUDIO_I2C0_CLK ,0 ,1 ), +MUX (0 ,"spdif0_wclk_mux" , audio_wclk_common_p,AUDIO_SPDIF0_CLK ,0 ,1 ), +MUX (0 ,"spdif1_wclk_mux" , audio_wclk_common_p,AUDIO_SPDIF1_CLK ,0 ,1 ), +MUX (0 ,"timer_wclk_mux" , audio_timer_p,AUDIO_TIMER_CLK ,0 ,1 ), +}; + +struct clk_zx_audio_divider audio_adiv_clk[] = { +AUDIO_DIV (0 ,"i2s0_wclk_div" ,"i2s0_wclk_mux" ,AUDIO_I2S0_DIV_CFG1 ), +AUDIO_DIV (0 ,"i2s1_wclk_div" ,"i2s1_wclk_mux" ,AUDIO_I2S1_DIV_CFG1 ), +AUDIO_DIV (0 ,"i2s2_wclk_div" ,"i2s2_wclk_mux" ,AUDIO_I2S2_DIV_CFG1 ), +AUDIO_DIV (0 ,"i2s3_wclk_div" ,"i2s3_wclk_mux" ,AUDIO_I2S3_DIV_CFG1 ), +AUDIO_DIV (0 ,"spdif0_wclk_div" ,"spdif0_wclk_mux" ,AUDIO_SPDIF0_DIV_CFG1 ), +AUDIO_DIV (0 ,"spdif1_wclk_div" ,"spdif1_wclk_mux" ,AUDIO_SPDIF1_DIV_CFG1 ), +}; + +struct zx_clk_div audio_div_clk[] = { +DIV_T (0 ,"tdm_wclk_div" ,"audio_16m384" ,AUDIO_TDM_CLK ,8 ,4 ,0 , common_div_table), +}; + +struct zx_clk_gate audio_gate_clk[] = { +GATE (AUDIO_I2S0_WCLK ,"i2s0_wclk" ,"i2s0_wclk_div" ,AUDIO_I2S0_CLK ,9 ,CLK_SET_RATE_PARENT ,0 ), +GATE (AUDIO_I2S1_WCLK ,"i2s1_wclk" ,"i2s1_wclk_div" ,AUDIO_I2S1_CLK ,9 ,CLK_SET_RATE_PARENT ,0 ), +GATE (AUDIO_I2S2_WCLK ,"i2s2_wclk" ,"i2s2_wclk_div" ,AUDIO_I2S2_CLK ,9 ,CLK_SET_RATE_PARENT ,0 ), +GATE (AUDIO_I2S3_WCLK ,"i2s3_wclk" ,"i2s3_wclk_div" ,AUDIO_I2S3_CLK ,9 ,CLK_SET_RATE_PARENT ,0 ), +GATE (AUDIO_I2C0_WCLK ,"i2c0_wclk" ,"i2c0_wclk_mux" ,AUDIO_I2C0_CLK ,9 ,CLK_SET_RATE_PARENT ,0 ), +GATE (AUDIO_SPDIF0_WCLK ,"spdif0_wclk" ,"spdif0_wclk_div" ,AUDIO_SPDIF0_CLK ,9 ,CLK_SET_RATE_PARENT ,0 ), +GATE (AUDIO_SPDIF1_WCLK ,"spdif1_wclk" ,"spdif1_wclk_div" ,AUDIO_SPDIF1_CLK ,9 ,CLK_SET_RATE_PARENT ,0 ), +GATE (AUDIO_TDM_WCLK ,"tdm_wclk" ,"tdm_wclk_div" ,AUDIO_TDM_CLK ,17 ,CLK_SET_RATE_PARENT ,0 ), +GATE (AUDIO_TS_PCLK ,"tempsensor_pclk" ,"clk49m5" ,AUDIO_TS_CLK ,1 ,0 ,0 ), +}; + +static struct clk_hw_onecell_data audio_hw_onecell_data = { + .num =AUDIO_NR_CLKS , + .hws = { + [AUDIO_NR_CLKS -1 ] =NULL , + }, +}; + +static int __init audio_clocks_init (struct device_node *np) +{ +void __iomem *reg_base; +int i, ret; + + reg_base =of_iomap (np,0 ); +if (!reg_base) { +pr_err ("%s: Unable to map audio clk base\n" , __func__); +return -ENXIO ; + } + +for (i =0 ; i <ARRAY_SIZE (audio_mux_clk); i++) { +if (audio_mux_clk[i].id) + audio_hw_onecell_data.hws[audio_mux_clk[i].id] = + &audio_mux_clk[i].mux.hw; + + audio_mux_clk[i].mux.reg += (uintptr_t )reg_base; + ret =clk_hw_register (NULL , &audio_mux_clk[i].mux.hw); +if (ret) { +pr_warn ("audio clk %s init error!\n" , + audio_mux_clk[i].mux.hw.init->name); + } + } + +for (i =0 ; i <ARRAY_SIZE (audio_adiv_clk); i++) { +if (audio_adiv_clk[i].id) + audio_hw_onecell_data.hws[audio_adiv_clk[i].id] = + &audio_adiv_clk[i].hw; + + audio_adiv_clk[i].reg_base += (uintptr_t )reg_base; + ret =clk_hw_register (NULL , &audio_adiv_clk[i].hw); +if (ret) { +pr_warn ("audio clk %s init error!\n" , + audio_adiv_clk[i].hw.init->name); + } + } + +for (i =0 ; i <ARRAY_SIZE (audio_div_clk); i++) { +if (audio_div_clk[i].id) + audio_hw_onecell_data.hws[audio_div_clk[i].id] = + &audio_div_clk[i].div.hw; + + audio_div_clk[i].div.reg += (uintptr_t )reg_base; + ret =clk_hw_register (NULL , &audio_div_clk[i].div.hw); +if (ret) { +pr_warn ("audio clk %s init error!\n" , + audio_div_clk[i].div.hw.init->name); + } + } + +for (i =0 ; i <ARRAY_SIZE (audio_gate_clk); i++) { +if (audio_gate_clk[i].id) + audio_hw_onecell_data.hws[audio_gate_clk[i].id] = + &audio_gate_clk[i].gate.hw; + + audio_gate_clk[i].gate.reg += (uintptr_t )reg_base; + ret =clk_hw_register (NULL , &audio_gate_clk[i].gate.hw); +if (ret) { +pr_warn ("audio clk %s init error!\n" , + audio_gate_clk[i].gate.hw.init->name); + } + } + + ret =of_clk_add_hw_provider (np, of_clk_hw_onecell_get, + &audio_hw_onecell_data); +if (ret) { +pr_err ("failed to register audio clk provider: %d\n" , ret); +return ret; + } + +return 0 ; +} +static const struct of_device_id zx_clkc_match_table[] = { { .compatible ="zte,zx296718-topcrm" , .data = &top_clocks_init }, { .compatible ="zte,zx296718-lsp0crm" , .data = &lsp0_clocks_init }, { .compatible ="zte,zx296718-lsp1crm" , .data = &lsp1_clocks_init }, + { .compatible ="zte,zx296718-audiocrm" , .data = &audio_clocks_init }, { } };
drivers/clk/zte/clk.c +127 -0
136 lines not on this page · raw message
drivers/clk/zte/clk.h +21 -0
@@ -153,6 +153,25 @@ struct zx_clk_div { .id = _id, \ } +struct clk_zx_audio_divider { +struct clk_hw hw; +void __iomem *reg_base; +unsigned int rate_count; +spinlock_t *lock; +u16 id; +}; + +#define AUDIO_DIV (_id, _name, _parent, _reg) \ +{ \ + .reg_base = (void __iomem *) _reg, \ + .lock = &clk_lock, \ + .hw.init = CLK_HW_INIT(_name, \ + _parent, \ + &zx_audio_div_ops, \ + 0), \ + .id = _id, \ +} +struct clk *clk_register_zx_pll (const char *name,const char *parent_name,unsigned long flags,void __iomem *reg_base,const struct zx_pll_config *lookup_table,int count,spinlock_t *lock);
@@ -167,4 +186,6 @@ struct clk *clk_register_zx_audio(const char *name, unsigned long flags, void __iomem *reg_base);extern const struct clk_ops zx_pll_ops; +extern const struct clk_ops zx_audio_div_ops; +#endif
Signature · 1 line
1.9.1
Stephen Boyd
AppliedPATCH v2 3/3 clk: zte: add audio clocks for zx296718
Quoted 9 lines · Shawn Guo
From: Jun Nie <[email protected]>
The audio related clock support is missing from the existing zx296718 clock driver. Let's add it, so that the upstream ZX SPDIF driver can work for HDMI audio support.
Signed-off-by Jun Nie <[email protected]>Signed-off-by Shawn Guo <[email protected]>---
Applied to clk-next + I added static to some more structures.
Signature · 2 lines
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project