ARM: dts: imx6sx: Fix sdma node
Fabio Estevam
reviewerPATCH 1/5 ARM: dts: imx6sx: Fix sdma node
From: Fabio Estevam <[email protected]>
Use the correct compatible string for sdma and also provide the sdma firmware path.
--- arch/arm/boot/dts/imx6sx.dtsi | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
arch/arm/boot/dts/imx6sx.dtsi +3 -1
@@ -703,13 +703,15 @@ }; sdma: sdma at 020ec000 { - compatible = "fsl,imx6sx-sdma"; + compatible = "fsl,imx6sx-sdma", "fsl,imx35-sdma"; reg = <0x020ec000 0x4000>; interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>; clocks = <&clks IMX6SX_CLK_SDMA>, <&clks IMX6SX_CLK_SDMA>; clock-names = "ipg", "ahb"; #dma-cells = <3>; + /* imx6sx reuses imx6q sdma firmware */ + fsl,sdma-ram-script-name = "imx/sdma/sdma-imx6q.bin"; }; };
Signature · 1 line
1.8.3.2
Fabio Estevam
reviewerPATCH 2/5 ARM: dts: imx6sx: Fix SSI nodes
From: Fabio Estevam <[email protected]>
The fsl_ssi driver only needs one clock to work, so only pass the required SSI clock as done in the other mx6 dtsi files.
Also pass the fsl,fifo-depth property.
--- arch/arm/boot/dts/imx6sx.dtsi | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-)
arch/arm/boot/dts/imx6sx.dtsi +6 -9
@@ -301,11 +301,10 @@ compatible = "fsl,imx6sx-ssi", "fsl,imx21-ssi"; reg = <0x02028000 0x4000>; interrupts = <GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clks IMX6SX_CLK_SSI1_IPG>, - <&clks IMX6SX_CLK_SSI1>; - clock-names = "ipg", "baud"; + clocks = <&clks IMX6SX_CLK_SSI1>; dmas = <&sdma 37 1 0>, <&sdma 38 1 0>; dma-names = "rx", "tx"; + fsl,fifo-depth = <15>; status = "disabled"; };
@@ -313,11 +312,10 @@ compatible = "fsl,imx6sx-ssi", "fsl,imx21-ssi"; reg = <0x0202c000 0x4000>; interrupts = <GIC_SPI 47 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clks IMX6SX_CLK_SSI2_IPG>, - <&clks IMX6SX_CLK_SSI2>; - clock-names = "ipg", "baud"; + clocks = <&clks IMX6SX_CLK_SSI2>; dmas = <&sdma 41 1 0>, <&sdma 42 1 0>; dma-names = "rx", "tx"; + fsl,fifo-depth = <15>; status = "disabled"; };
@@ -325,11 +323,10 @@ compatible = "fsl,imx6sx-ssi", "fsl,imx21-ssi"; reg = <0x02030000 0x4000>; interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clks IMX6SX_CLK_SSI3_IPG>, - <&clks IMX6SX_CLK_SSI3>; - clock-names = "ipg", "baud"; + clocks = <&clks IMX6SX_CLK_SSI3>; dmas = <&sdma 45 1 0>, <&sdma 46 1 0>; dma-names = "rx", "tx"; + fsl,fifo-depth = <15>; status = "disabled"; };
Signature · 1 line
1.8.3.2
PATCH 2/5 ARM: dts: imx6sx: Fix SSI nodes
Hi Fabio,
Quoted 4 lines · Fabio Estevam
From: Fabio Estevam <[email protected]>
The
fsl_ssidriver only needs one clock to work, so only pass the required SSI clock as done in the other mx6 dtsi files.
Actually I would prefer to have the clock defined in the .dtsi files. The fsl-ssi driver only enables the baud clock if the SSI unit is the clock master. So in all other cases the clock is not enabled and keeps disabled.
Also the clock is SSI specific, you don't have a choice which clock to use, there is no board dependency on this clock. So I think we should fix the other imx6 dtsi files instead.
Quoted 13 lines
Also pass the fsl,fifo-depth property.
Signed-off-by Fabio Estevam <[email protected]>--- arch/arm/boot/dts/imx6sx.dtsi | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-)arch/arm/boot/dts/imx6sx.dtsi +0
-0
arch/arm/boot/dts/imx6sx.dtsi line 304
Quoted 7 lines
arch/arm/boot/dts/imx6sx.dtsi +1
-3@@ -301,11 +301,10 @@ compatible = "fsl,imx6sx-ssi", "fsl,imx21-ssi"; reg = <0x02028000 0x4000>; interrupts = <GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clks IMX6SX_CLK_SSI1_IPG>, - <&clks IMX6SX_CLK_SSI1>; - clock-names = "ipg", "baud"; + clocks = <&clks IMX6SX_CLK_SSI1>;
It seems you are removing the wrong clock here. 'ipg' is necessary, 'baud' is only used for master mode.
Regards,
Markus
Quoted 43 lines
arch/arm/boot/dts/imx6sx.dtsi +5
-6dmas = <&sdma 37 1 0>, <&sdma 38 1 0>; dma-names = "rx", "tx"; + fsl,fifo-depth = <15>; status = "disabled"; };@@ -313,11 +312,10 @@ compatible = "fsl,imx6sx-ssi", "fsl,imx21-ssi"; reg = <0x0202c000 0x4000>; interrupts = <GIC_SPI 47 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clks IMX6SX_CLK_SSI2_IPG>, - <&clks IMX6SX_CLK_SSI2>; - clock-names = "ipg", "baud"; + clocks = <&clks IMX6SX_CLK_SSI2>; dmas = <&sdma 41 1 0>, <&sdma 42 1 0>; dma-names = "rx", "tx"; + fsl,fifo-depth = <15>; status = "disabled"; };@@ -325,11 +323,10 @@ compatible = "fsl,imx6sx-ssi", "fsl,imx21-ssi"; reg = <0x02030000 0x4000>; interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clks IMX6SX_CLK_SSI3_IPG>, - <&clks IMX6SX_CLK_SSI3>; - clock-names = "ipg", "baud"; + clocks = <&clks IMX6SX_CLK_SSI3>; dmas = <&sdma 45 1 0>, <&sdma 46 1 0>; dma-names = "rx", "tx"; + fsl,fifo-depth = <15>; status = "disabled"; };Signature · 7 lines
1.8.3.2 _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel at lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
Signature · 11 lines
Pengutronix e.K. | | Industrial Linux Solutions | http://www.pengutronix.de/ | Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 | -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 836 bytes Desc: Digital signature URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140701/a8b5123f/attachment.sig>
PATCH 2/5 ARM: dts: imx6sx: Fix SSI nodes
Quoted 25 lines · Markus Pargmann
Hi Fabio,
Quoted 4 lines · Fabio Estevam
From: Fabio Estevam <[email protected]>
The
fsl_ssidriver only needs one clock to work, so only pass the required SSI clock as done in the other mx6 dtsi files.Actually I would prefer to have the clock defined in the .dtsi files. The fsl-ssi driver only enables the baud clock if the SSI unit is the clock master. So in all other cases the clock is not enabled and keeps disabled.
Also the clock is SSI specific, you don't have a choice which clock to use, there is no board dependency on this clock. So I think we should fix the other imx6 dtsi files instead.
Quoted 8 lines
Also pass the fsl,fifo-depth property.
Signed-off-by Fabio Estevam <[email protected]>--- arch/arm/boot/dts/imx6sx.dtsi | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-)
Quoted 15 lines
arch/arm/boot/dts/imx6sx.dtsi line 304
Quoted 12 lines
arch/arm/boot/dts/imx6sx.dtsi +1
-3@@ -301,11 +301,10 @@ compatible = "fsl,imx6sx-ssi", "fsl,imx21-ssi"; reg = <0x02028000 0x4000>; interrupts = <GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clks IMX6SX_CLK_SSI1_IPG>, - <&clks IMX6SX_CLK_SSI1>; - clock-names = "ipg", "baud"; + clocks = <&clks IMX6SX_CLK_SSI1>;It seems you are removing the wrong clock here. 'ipg' is necessary, 'baud' is only used for master mode.
Oh a later patch explains the removal of the 'wrong' clock. So just ignore this part.
Regards,
Markus
Signature · 11 lines
Pengutronix e.K. | | Industrial Linux Solutions | http://www.pengutronix.de/ | Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 | -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 836 bytes Desc: Digital signature URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140701/7bdb8965/attachment-0001.sig>
Fabio Estevam
reviewerPATCH 3/5 ARM: imx: clk-imx6sx: Remove SSI IPG clocks
In reply to Fabio EstevamFrom: Fabio Estevam <[email protected]>
Looking at the CCGR5 register we see that that each SSI has its corresponding clock gate field.
There are no SSI IPG clock gate field, so remove these SSI IPG variants as they point to the same SSI clock fields and have no use in the kernel.
--- arch/arm/mach-imx/clk-imx6sx.c | 3 --- 1 file changed, 3 deletions(-)
arch/arm/mach-imx/clk-imx6sx.c +0 -3
@@ -409,9 +409,6 @@ static void __init imx6sx_clocks_init(struct device_node *ccm_node) clks[IMX6SX_CLK_SPBA ] =imx_clk_gate2 ("spba" ,"ipg" , base +0x7c ,12 ); clks[IMX6SX_CLK_AUDIO ] =imx_clk_gate2_shared ("audio" ,"audio_podf" , base +0x7c ,14 , &share_count_audio); clks[IMX6SX_CLK_SPDIF ] =imx_clk_gate2_shared ("spdif" ,"spdif_podf" , base +0x7c ,14 , &share_count_audio); - clks[IMX6SX_CLK_SSI1_IPG ] =imx_clk_gate2 ("ssi1_ipg" ,"ipg" , base +0x7c ,18 ); - clks[IMX6SX_CLK_SSI2_IPG ] =imx_clk_gate2 ("ssi2_ipg" ,"ipg" , base +0x7c ,20 ); - clks[IMX6SX_CLK_SSI3_IPG ] =imx_clk_gate2 ("ssi3_ipg" ,"ipg" , base +0x7c ,22 ); clks[IMX6SX_CLK_SSI1 ] =imx_clk_gate2 ("ssi1" ,"ssi1_podf" , base +0x7c ,18 ); clks[IMX6SX_CLK_SSI2 ] =imx_clk_gate2 ("ssi2" ,"ssi2_podf" , base +0x7c ,20 ); clks[IMX6SX_CLK_SSI3 ] =imx_clk_gate2 ("ssi3" ,"ssi3_podf" , base +0x7c ,22 );
Signature · 1 line
1.8.3.2
PATCH 3/5 ARM: imx: clk-imx6sx: Remove SSI IPG clocks
Hi Fabio,
Quoted 7 lines · Fabio Estevam
From: Fabio Estevam <[email protected]>
Looking at the CCGR5 register we see that that each SSI has its corresponding clock gate field.
There are no SSI IPG clock gate field, so remove these SSI IPG variants as they point to the same SSI clock fields and have no use in the kernel.
I was just abort to say that actually each SSI has an IPG clock as CCM shows:
SSIn ssi_clk ssin_clk_root CCGR5[CG11:CG9] (ssi[3:1]_clk_enable)
ipg_clk ipg_clk_root CCGR5[CG11:CG9] (ssi[3:1]_clk_enable)
ipg_clk_s ipg_clk_root CCGR5[CG11:CG9] (ssi[3:1]_clk_enable)So we don't have to remove the IPG one. Instead we shall protect IPG and baud clocks with imx_clk_gate2_shared().
Thank you,
Nicolin
Quoted 23 lines
Signed-off-by Fabio Estevam <[email protected]>--- arch/arm/mach-imx/clk-imx6sx.c | 3 --- 1 file changed, 3 deletions(-)arch/arm/mach-imx/clk-imx6sx.c +0
-3@@ -409,9 +409,6 @@ static void __init imx6sx_clocks_init(struct device_node *ccm_node) clks[IMX6SX_CLK_SPBA ] =imx_clk_gate2 ("spba" ,"ipg" , base +0x7c ,12 ); clks[IMX6SX_CLK_AUDIO ] =imx_clk_gate2_shared ("audio" ,"audio_podf" , base +0x7c ,14 , &share_count_audio); clks[IMX6SX_CLK_SPDIF ] =imx_clk_gate2_shared ("spdif" ,"spdif_podf" , base +0x7c ,14 , &share_count_audio); - clks[IMX6SX_CLK_SSI1_IPG ] =imx_clk_gate2 ("ssi1_ipg" ,"ipg" , base +0x7c ,18 ); - clks[IMX6SX_CLK_SSI2_IPG ] =imx_clk_gate2 ("ssi2_ipg" ,"ipg" , base +0x7c ,20 ); - clks[IMX6SX_CLK_SSI3_IPG ] =imx_clk_gate2 ("ssi3_ipg" ,"ipg" , base +0x7c ,22 ); clks[IMX6SX_CLK_SSI1 ] =imx_clk_gate2 ("ssi1" ,"ssi1_podf" , base +0x7c ,18 ); clks[IMX6SX_CLK_SSI2 ] =imx_clk_gate2 ("ssi2" ,"ssi2_podf" , base +0x7c ,20 ); clks[IMX6SX_CLK_SSI3 ] =imx_clk_gate2 ("ssi3" ,"ssi3_podf" , base +0x7c ,22 );Signature · 1 line
1.8.3.2
Fabio Estevam
reviewerPATCH 4/5 ARM: imx: clk-gate2: Use post decrement for share_count
In reply to Fabio EstevamFrom: Fabio Estevam <[email protected]>
SSI clocks use the share_count mechanism since SSI and SPDIF share the same clock gate bits.
When using the share_count for the SSI clock we notice that it gets disabled due to the usage of pre-decrement operation in the clk_gate2_disable() function.
Use the post-decrement operation so that the correct share_count is used and the SSI clock does not get disable when an audio file needs to be played.
--- arch/arm/mach-imx/clk-gate2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/arm/mach-imx/clk-gate2.c +1 -1
@@ -67,7 +67,7 @@ static void clk_gate2_disable(struct clk_hw *hw)spin_lock_irqsave (gate->lock, flags); -if (gate->share_count && --(*gate->share_count) >0 ) +if (gate->share_count && (*gate->share_count)-- >0 ) goto out; reg =readl (gate->reg);
Signature · 1 line
1.8.3.2
PATCH 4/5 ARM: imx: clk-gate2: Use post decrement for share_count
Quoted 21 lines · Fabio Estevam
From: Fabio Estevam <[email protected]>
SSI clocks use the
share_countmechanism since SSI and SPDIF share the same clock gate bits.When using the
share_countfor the SSI clock we notice that it gets disabled due to the usage of pre-decrement operation in theclk_gate2_disable()function.Use the post-decrement operation so that the correct
share_countis used and the SSI clock does not get disable when an audio file needs to be played.Signed-off-by Fabio Estevam <[email protected]>--- arch/arm/mach-imx/clk-gate2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)arch/arm/mach-imx/clk-gate2.c +0
-0
arch/arm/mach-imx/clk-gate2.c static void clk_gate2_disable(struct clk_hw *hw) · line 70
Quoted 5 lines
arch/arm/mach-imx/clk-gate2.c +1
-1@@ -67,7 +67,7 @@ static void clk_gate2_disable(struct clk_hw *hw)spin_lock_irqsave (gate->lock, flags); -if (gate->share_count && --(*gate->share_count) >0 ) +if (gate->share_count && (*gate->share_count)-- >0 )
The change makes no sense. Let's say that clk_gate2_disable() gets called with share_count being 1. In this case, we should access register to gate the clock, right?
Shawn
Quoted 6 lines
arch/arm/mach-imx/clk-gate2.c +0
-0goto out; reg =readl (gate->reg);Signature · 1 line
1.8.3.2
Fabio Estevam
reviewerPATCH 4/5 ARM: imx: clk-gate2: Use post decrement for share_count
Quoted 4 lines · Shawn Guo
Quoted 4 lines
arch/arm/mach-imx/clk-gate2.c +0
-0@@ -67,7 +67,7 @@ static void clk_gate2_disable(struct clk_hw *hw)
Quoted 8 lines
arch/arm/mach-imx/clk-gate2.c static void clk_gate2_disable(struct clk_hw *hw) · line 70
Quoted 4 lines
arch/arm/mach-imx/clk-gate2.c +1
-1spin_lock_irqsave (gate->lock, flags); -if (gate->share_count && --(*gate->share_count) >0 ) +if (gate->share_count && (*gate->share_count)-- >0 )The change makes no sense. Let's say that
clk_gate2_disable()gets called withshare_countbeing 1. In this case, we should access register to gate the clock, right?
If share_count is 1 it means that someone else is using the clock and we can't disable it.
Please try running the series without this patch. When the extern audio clock is enabled, share_count is 1. Later the the spdif clock (the one that is shared with extern audio clock) is disabled by the CCF as it is not used, which makes the extern audio clock to be also disabled, which is not what we want.
What would you suggest?
PATCH 4/5 ARM: imx: clk-gate2: Use post decrement for share_count
Quoted 15 lines · Fabio Estevam
Quoted 4 lines · Shawn Guo
Quoted 4 lines
arch/arm/mach-imx/clk-gate2.c +0
-0@@ -67,7 +67,7 @@ static void clk_gate2_disable(struct clk_hw *hw)Quoted 8 lines
arch/arm/mach-imx/clk-gate2.c static void clk_gate2_disable(struct clk_hw *hw) · line 70
Quoted 4 lines
arch/arm/mach-imx/clk-gate2.c +1
-1spin_lock_irqsave (gate->lock, flags); -if (gate->share_count && --(*gate->share_count) >0 ) +if (gate->share_count && (*gate->share_count)-- >0 )The change makes no sense. Let's say that
clk_gate2_disable()gets called withshare_countbeing 1. In this case, we should access register to gate the clock, right?
Quoted 2 lines
If
share_countis 1 it means that someone else is using the clock and we can't disable it.
You do not really know it's someone else or itself.
Quoted 8 lines
Please try running the series without this patch. When the extern audio clock is enabled,
share_countis 1. Later the the spdif clock (the one that is shared with extern audio clock) is disabled by the CCF as it is not used, which makes the extern audio clock to be also disabled, which is not what we want.What would you suggest?
What about the patch below?
Shawn
----8<-------------
Quoted 1 line
From
0ed4b3edc661c63f86c914ea3c6deb3af3438151Mon Sep 17 00:00:00 2001
From: Shawn Guo <[email protected]>
Date: Wed, 2 Jul 2014 11:32:06 +0800
Subject: [PATCH] ARM: imx: fix shared gate clock to have its own enable count
Let's say clock A and B are two gate clocks that share the same register bit in hardware. Therefore they should be registered as shared gate clocks with imx_clk_gate2_shared().
In the current implementation, clk_enable(A) call will have share_count become 1. If clk_disable(B) is called right after that, the register bit will be cleared to gate off the clocks. This is unexpected. The cause for that is there is no enable count tracking for clock A and B respectively.
The patch fixes the issue by adding enable_count into clk_gate2, and tracks it prior to share_count in .enable and .disable. Also, .is_enabled is fixed to report enable state instead of hardware state in case of shared gate clock.
--- arch/arm/mach-imx/clk-gate2.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+)
arch/arm/mach-imx/clk-gate2.c +14 -0
@@ -33,6 +33,7 @@ struct clk_gate2 {u8 bit_idx;u8 flags;spinlock_t *lock; +unsigned int enable_count;unsigned int *share_count; };
@@ -46,6 +47,9 @@ static int clk_gate2_enable(struct clk_hw *hw)spin_lock_irqsave (gate->lock, flags); +if (gate->enable_count++ >0 ) + goto out; +if (gate->share_count && (*gate->share_count)++ >0 ) goto out;
@@ -67,6 +71,9 @@ static void clk_gate2_disable(struct clk_hw *hw)spin_lock_irqsave (gate->lock, flags); +if (--gate->enable_count >0 ) + goto out; +if (gate->share_count && --(*gate->share_count) >0 ) goto out;
@@ -83,6 +90,13 @@ static int clk_gate2_is_enabled(struct clk_hw *hw)u32 reg;struct clk_gate2 *gate =to_clk_gate2 (hw); +/* +* In case this is a shared gate, we cannot just report the hardware +* state but its own enable state. +*/ +if (gate->share_count) +return !!gate->enable_count; + reg =readl (gate->reg);if (((reg >> gate->bit_idx) &1 ) ==1 )
Signature · 1 line
1.8.3.2
Fabio Estevam
reviewerPATCH 4/5 ARM: imx: clk-gate2: Use post decrement for share_count
Quoted 1 line · Shawn Guo
What about the patch below?
It does allow audio to play, but it resulted in CCGR5 as 0xffffffff (all clocks enabled), so we still need to adjust it.
Quoted 19 lines
Shawn
----8<-------------
From
0ed4b3edc661c63f86c914ea3c6deb3af3438151Mon Sep 17 00:00:00 2001
From: Shawn Guo <[email protected]>
Date: Wed, 2 Jul 2014 11:32:06 +0800
Subject: [PATCH] ARM: imx: fix shared gate clock to have its own enable countLet's say clock A and B are two gate clocks that share the same register bit in hardware. Therefore they should be registered as shared gate clocks with
imx_clk_gate2_shared().In the current implementation,
clk_enable(A)call will haveshare_countbecome 1. Ifclk_disable(B)is called right after that, the register bit will be cleared to gate off the clocks. This is unexpected. The cause for that is there is no enable count tracking for clock A and B respectively.
Quoted 8 lines
The patch fixes the issue by adding
enable_countintoclk_gate2, and tracks it prior toshare_countin .enable and .disable. Also, .is_enabled is fixed to report enable state instead of hardware state in case of shared gate clock.Reported-by Fabio Estevam <[email protected]>Cc <[email protected]>Fixes f9f28cdf2167 ("ARM: imx: add shared gate clock support")
No need to Cc stable on this one as the this commit did not reach stable.
Quoted 28 lines
Signed-off-by Shawn Guo <[email protected]>--- arch/arm/mach-imx/clk-gate2.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+)arch/arm/mach-imx/clk-gate2.c +4
-0@@ -33,6 +33,7 @@ struct clk_gate2 {u8 bit_idx;u8 flags;spinlock_t *lock; +unsigned int enable_count;unsigned int *share_count; };@@ -46,6 +47,9 @@ static int clk_gate2_enable(struct clk_hw *hw)spin_lock_irqsave (gate->lock, flags); +if (gate->enable_count++ >0 ) + goto out; +if (gate->share_count && (*gate->share_count)++ >0 ) goto out;
arch/arm/mach-imx/clk-gate2.c static void clk_gate2_disable(struct clk_hw *hw) · line 75
Quoted 5 lines
arch/arm/mach-imx/clk-gate2.c +2
-0@@ -67,6 +71,9 @@ static void clk_gate2_disable(struct clk_hw *hw)spin_lock_irqsave (gate->lock, flags); +if (--gate->enable_count >0 ) + goto out;
All these pre-decrement look buggy because enable_count and share_count are 'unsigned int'.
If share_count is 0 and then you decrement it, it will still be greater than zero.
--(*gate->share_count) > 0 and --gate->enable_count > 0 are always true.
I have tried to make share_count and enable_count as 'int'. Then it resulted CGR5 as
0FFFCFFF, which still leaves ssi1 and ssi3 enabled (I have locally made ssi a shared clock now)
I will post a v2 without touching arch/arm/mach-imx/clk-gate2.c to make it easier for us to debug it.
Thanks,
Fabio Estevam
PATCH 4/5 ARM: imx: clk-gate2: Use post decrement for share_count
Quoted 20 lines · Fabio Estevam
Quoted 20 lines
From
0ed4b3edc661c63f86c914ea3c6deb3af3438151Mon Sep 17 00:00:00 2001
From: Shawn Guo <[email protected]>
Date: Wed, 2 Jul 2014 11:32:06 +0800
Subject: [PATCH] ARM: imx: fix shared gate clock to have its own enable countLet's say clock A and B are two gate clocks that share the same register bit in hardware. Therefore they should be registered as shared gate clocks with
imx_clk_gate2_shared().In the current implementation,
clk_enable(A)call will haveshare_countbecome 1. Ifclk_disable(B)is called right after that, the register bit will be cleared to gate off the clocks. This is unexpected. The cause for that is there is no enable count tracking for clock A and B respectively.The patch fixes the issue by adding
enable_countintoclk_gate2, and tracks it prior toshare_countin .enable and .disable. Also, .is_enabled is fixed to report enable state instead of hardware state in case of shared gate clock.
Quoted 5 lines
Quoted 3 lines
Reported-by Fabio Estevam <[email protected]>Cc <[email protected]>Fixes f9f28cdf2167 ("ARM: imx: add shared gate clock support")No need to Cc stable on this one as the this commit did not reach stable.
Yes, you're right.
...
Quoted 10 lines
Review static void clk_gate2_disable(struct clk_hw *hw) · line 75
Quoted 6 lines
(quoted diff) +2
-0@@ -67,6 +71,9 @@ static void clk_gate2_disable(struct clk_hw *hw) spin_lock_irqsave(gate->lock, flags); + if (--gate->enable_count > 0) + goto out;All these pre-decrement look buggy because
enable_countandshare_countare 'unsigned int'.
Quoted 3 lines
If
share_countis 0 and then you decrement it, it will still be greater than zero.
--(*gate->share_count) > 0 and --gate->enable_count > 0 are always true.
Hmm, clk_gate2_disable() should never be called with a zero share_count. I will add a check for that.
Quoted 4 lines
I have tried to make
share_countandenable_countas 'int'. Then it resulted CGR5 as
0FFFCFFF, which still leaves ssi1 and ssi3 enabled (I have locally made ssi a shared clock now)
Right. The patch did not fix the problem correctly. I just started it over again with the one below. Can you please test it? Thanks.
Shawn
---8<-------------------
Quoted 1 line
From
e057f4c129e77639372f2b4a3b9eb8a9de2095f8Mon Sep 17 00:00:00 2001
From: Shawn Guo <[email protected]>
Date: Wed, 2 Jul 2014 11:32:06 +0800
Subject: [PATCH] ARM: imx: fix shared gate clock
to be added ...
--- arch/arm/mach-imx/clk-gate2.c | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-)
arch/arm/mach-imx/clk-gate2.c +22 -8
@@ -67,8 +67,12 @@ static void clk_gate2_disable(struct clk_hw *hw)spin_lock_irqsave (gate->lock, flags); -if (gate->share_count && --(*gate->share_count) >0 ) - goto out; +if (gate->share_count) { +if (WARN_ON (*gate->share_count ==0 )) + goto out; +else if (--(*gate->share_count) >0 ) + goto out; + } reg =readl (gate->reg); reg &= ~(3 << gate->bit_idx);
@@ -78,19 +82,26 @@ out:spin_unlock_irqrestore (gate->lock, flags); } -static int clk_gate2_is_enabled (struct clk_hw *hw) +static int clk_gate2_reg_is_enabled (void __iomem *reg,u8 bit_idx) { -u32 reg; -struct clk_gate2 *gate =to_clk_gate2 (hw); +u32 val =readl (reg); - reg =readl (gate->reg); - -if (((reg >> gate->bit_idx) &1 ) ==1 ) +if (((val >> bit_idx) &1 ) ==1 )return 1 ;return 0 ; } +static int clk_gate2_is_enabled (struct clk_hw *hw) +{ +struct clk_gate2 *gate =to_clk_gate2 (hw); + +if (gate->share_count) +return !!(*gate->share_count); +else +return clk_gate2_reg_is_enabled (gate->reg, gate->bit_idx); +} +static struct clk_ops clk_gate2_ops = { .enable = clk_gate2_enable, .disable = clk_gate2_disable,
@@ -116,6 +127,9 @@ struct clk *clk_register_gate2(struct device *dev, const char *name, gate->bit_idx = bit_idx; gate->flags = clk_gate2_flags; gate->lock = lock; + +if (share_count) + *share_count =clk_gate2_reg_is_enabled (reg, bit_idx) ?1 :0 ; gate->share_count = share_count; init.name = name;
Signature · 1 line
1.8.3.2
PATCH 4/5 ARM: imx: clk-gate2: Use post decrement for share_count
In reply to Fabio EstevamQuoting Fabio Estevam (2014-07-01 10:44:40)
Quoted 15 lines · Shawn Guo
Quoted 5 lines
Quoted 5 lines
arch/arm/mach-imx/clk-gate2.c +0
-0@@ -67,7 +67,7 @@ static void clk_gate2_disable(struct clk_hw *hw)Quoted 8 lines
arch/arm/mach-imx/clk-gate2.c static void clk_gate2_disable(struct clk_hw *hw) · line 70
Quoted 4 lines
arch/arm/mach-imx/clk-gate2.c +1
-1spin_lock_irqsave (gate->lock, flags); -if (gate->share_count && --(*gate->share_count) >0 ) +if (gate->share_count && (*gate->share_count)-- >0 )The change makes no sense. Let's say that
clk_gate2_disable()gets called withshare_countbeing 1. In this case, we should access register to gate the clock, right?
Quoted 2 lines
If
share_countis 1 it means that someone else is using the clock and we can't disable it.
Why do you keep track of share_count at all? Is the enable_count bookkeeping within the clock framework insufficient for your needs?
Regards,
Mike
Quoted 13 lines
Please try running the series without this patch. When the extern audio clock is enabled,
share_countis 1. Later the the spdif clock (the one that is shared with extern audio clock) is disabled by the CCF as it is not used, which makes the extern audio clock to be also disabled, which is not what we want.What would you suggest?
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel at lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
Fabio Estevam
reviewerPATCH 4/5 ARM: imx: clk-gate2: Use post decrement for share_count
Hi Mike,
Quoted 5 lines · Mike Turquette
Quoted 2 lines
If
share_countis 1 it means that someone else is using the clock and we can't disable it.Why do you keep track of
share_countat all? Is theenable_countbookkeeping within the clock framework insufficient for your needs?
What we are trying to handle here is the case when two clocks share the same clock gating bit.
Let's say clocks clk1 and clk2 share the same clock gating bit.
What we want to achieve are:
Scenario 1:
clk2 is disabled
clk1 is enabled --> clock gate bit is set to 1
clk1 is disabled --> clock gate bit is set to 0. As clk2 is disabled, it is OK to gate off the clock here
Scenario 2:
clk1 is enabled -> clock gate bit is set to 1
clk2 is disabled -> clock gate bit cannot be set to 0 because clk1 is enabled
We currently have arch/arm/mach-imx/clk-gate2.c and we are trying to fix it because the scenario 2 is not working.
I am wondering if we should just extend drivers/clk/clk-gate.c to handle shared clock instead of doing this in arch/arm/mach-imx?
What do you think?
Thanks,
Fabio Estevam
PATCH 4/5 ARM: imx: clk-gate2: Use post decrement for share_count
Quoting Fabio Estevam (2014-07-02 09:52:56)
Quoted 29 lines
Hi Mike,
Quoted 5 lines · Mike Turquette
Quoted 2 lines
If
share_countis 1 it means that someone else is using the clock and we can't disable it.Why do you keep track of
share_countat all? Is theenable_countbookkeeping within the clock framework insufficient for your needs?What we are trying to handle here is the case when two clocks share the same clock gating bit.
Let's say clocks clk1 and clk2 share the same clock gating bit.
What we want to achieve are:
Scenario 1:
clk2 is disabled
clk1 is enabled --> clock gate bit is set to 1
clk1 is disabled --> clock gate bit is set to 0. As clk2 is disabled, it is OK to gate off the clock hereScenario 2:
clk1 is enabled -> clock gate bit is set to 1
clk2 is disabled -> clock gate bit cannot be set to 0 because clk1 is enabled
Quoted 7 lines
We currently have
arch/arm/mach-imx/clk-gate2.cand we are trying to fix it because the scenario 2 is not working.I am wondering if we should just extend
drivers/clk/clk-gate.cto handle shared clock instead of doing this inarch/arm/mach-imx?What do you think?
I am actually looking into this right now, so it is good timing for me to come across this thread. While hacking on the coordinated clock rates feature I started to think about coordinating clock enables for exactly your case: a single clock control enables or disables multiple clock outputs.
I think some core framework changes are needed to support this sensibly, and only putting the changes into clk-gate.c might not be sufficient or elegant. I've added this task to my stack and will keep you Cc'd when something hits the list.
Regards,
Mike
Quoted 4 lines
Thanks,
Fabio Estevam
PATCH 4/5 ARM: imx: clk-gate2: Use post decrement for share_count
In reply to Fabio EstevamQuoted 24 lines · Fabio Estevam
Hi Mike,
Quoted 5 lines · Mike Turquette
Quoted 2 lines
If
share_countis 1 it means that someone else is using the clock and we can't disable it.Why do you keep track of
share_countat all? Is theenable_countbookkeeping within the clock framework insufficient for your needs?What we are trying to handle here is the case when two clocks share the same clock gating bit.
Let's say clocks clk1 and clk2 share the same clock gating bit.
What we want to achieve are:
Scenario 1:
clk2 is disabled
clk1 is enabled --> clock gate bit is set to 1
clk1 is disabled --> clock gate bit is set to 0. As clk2 is disabled, it is OK to gate off the clock here
Quoted 4 lines
Scenario 2:
clk1 is enabled -> clock gate bit is set to 1
clk2 is disabled -> clock gate bit cannot be set to 0 because clk1 is enabled
This never happens. If clk2 is disabled by clk_disable() without being enabled by clk_enable() beforehand, it returns from __clk_disable() immediately due to hitting of the WARN below.
if (WARN_ON(clk->enable_count == 0)) return;
Shawn
Quoted 12 lines
We currently have
arch/arm/mach-imx/clk-gate2.cand we are trying to fix it because the scenario 2 is not working.I am wondering if we should just extend
drivers/clk/clk-gate.cto handle shared clock instead of doing this inarch/arm/mach-imx?What do you think?
Thanks,
Fabio Estevam
PATCH 4/5 ARM: imx: clk-gate2: Use post decrement for share_count
Quoted 11 lines · Shawn Guo
Quoted 4 lines
Scenario 2:
clk1 is enabled -> clock gate bit is set to 1
clk2 is disabled -> clock gate bit cannot be set to 0 because clk1 is enabledThis never happens. If clk2 is disabled by
clk_disable()without being enabled byclk_enable()beforehand, it returns from__clk_disable()immediately due to hitting of the WARN below.if (WARN_ON(clk->enable_count == 0)) return;
Well, it only happens in case that clock core calls clk->ops->disable() directly from clk_disable_unused_subtree() in order to disable unused clocks.
Shawn
Fabio Estevam
reviewerPATCH 5/5 ARM: dts: imx6sx-sdb: Add audio support
In reply to Fabio EstevamFrom: Fabio Estevam <[email protected]>
--- arch/arm/boot/dts/imx6sx-sdb.dts | 72 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+)
arch/arm/boot/dts/imx6sx-sdb.dts +72 -0
@@ -82,9 +82,39 @@ gpio = <&gpio1 12 GPIO_ACTIVE_HIGH>; enable-active-high; }; + + reg_psu_5v: regulator at 3 { + compatible = "regulator-fixed"; + reg = <3>; + regulator-name = "PSU-5V0"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + }; + }; + + sound { + compatible = "fsl,imx6sx-sdb-wm8962", "fsl,imx-audio-wm8962"; + model = "wm8962-audio"; + ssi-controller = <&ssi2>; + audio-codec = <&codec>; + audio-routing = + "Headphone Jack", "HPOUTL", + "Headphone Jack", "HPOUTR", + "Ext Spk", "SPKOUTL", + "Ext Spk", "SPKOUTR", + "AMIC", "MICBIAS", + "IN3R", "AMIC"; + mux-int-port = <2>; + mux-ext-port = <6>; }; }; +&audmux { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_audmux>; + status = "okay"; +}; + &fec1 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_enet1>;
@@ -200,6 +230,31 @@ }; }; +&i2c4 { + clock-frequency = <100000>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2c4>; + status = "okay"; + + codec: wm8962 at 1a { + compatible = "wlf,wm8962"; + reg = <0x1a>; + clocks = <&clks IMX6SX_CLK_AUDIO>; + DCVDD-supply = <&vgen4_reg>; + DBVDD-supply = <&vgen4_reg>; + AVDD-supply = <&vgen4_reg>; + CPVDD-supply = <&vgen4_reg>; + MICVDD-supply = <&vgen3_reg>; + PLLVDD-supply = <&vgen4_reg>; + SPKVDD1-supply = <®_psu_5v>; + SPKVDD2-supply = <®_psu_5v>; + }; +}; + +&ssi2 { + status = "okay"; +}; + &uart1 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_uart1>;
@@ -260,6 +315,16 @@ &iomuxc { imx6x-sdb { + pinctrl_audmux: audmuxgrp { + fsl,pins = < + MX6SX_PAD_CSI_DATA00__AUDMUX_AUD6_TXC 0x130b0 + MX6SX_PAD_CSI_DATA01__AUDMUX_AUD6_TXFS 0x130b0 + MX6SX_PAD_CSI_HSYNC__AUDMUX_AUD6_TXD 0x120b0 + MX6SX_PAD_CSI_VSYNC__AUDMUX_AUD6_RXD 0x130b0 + MX6SX_PAD_CSI_PIXCLK__AUDMUX_MCLK 0x130b0 + >; + }; + pinctrl_enet1: enet1grp { fsl,pins = < MX6SX_PAD_ENET1_MDIO__ENET1_MDIO 0xa0b1
@@ -293,6 +358,13 @@ >; }; + pinctrl_i2c4: i2c4grp { + fsl,pins = < + MX6SX_PAD_CSI_DATA07__I2C4_SDA 0x4001b8b1 + MX6SX_PAD_CSI_DATA06__I2C4_SCL 0x4001b8b1 + >; + }; + pinctrl_vcc_sd3: vccsd3grp { fsl,pins = < MX6SX_PAD_KEY_COL1__GPIO2_IO_11 0x17059
Signature · 1 line
1.8.3.2