LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: [PATCH v11 3/3] DMA: Freescale: update driver to support 8-channel DMA engine
From: Hongbo Zhang @ 2013-10-17  5:56 UTC (permalink / raw)
  To: hongbo.zhang, vinod.koul
  Cc: mark.rutland, devicetree, ian.campbell, pawel.moll, swarren,
	linux-kernel, rob.herring, djbw, linuxppc-dev
In-Reply-To: <1380188023-3936-4-git-send-email-hongbo.zhang@freescale.com>

Hi Vinod,
I have gotten ACK from Mark for both the 1/3 and 2/3 patches.
Thanks.


On 09/26/2013 05:33 PM, hongbo.zhang@freescale.com wrote:
> From: Hongbo Zhang <hongbo.zhang@freescale.com>
>
> This patch adds support to 8-channel DMA engine, thus the driver works for both
> the new 8-channel and the legacy 4-channel DMA engines.
>
> Signed-off-by: Hongbo Zhang <hongbo.zhang@freescale.com>
> ---
>   drivers/dma/Kconfig  |    9 +++++----
>   drivers/dma/fsldma.c |    9 ++++++---
>   drivers/dma/fsldma.h |    2 +-
>   3 files changed, 12 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
> index 6825957..3979c65 100644
> --- a/drivers/dma/Kconfig
> +++ b/drivers/dma/Kconfig
> @@ -89,14 +89,15 @@ config AT_HDMAC
>   	  Support the Atmel AHB DMA controller.
>   
>   config FSL_DMA
> -	tristate "Freescale Elo and Elo Plus DMA support"
> +	tristate "Freescale Elo series DMA support"
>   	depends on FSL_SOC
>   	select DMA_ENGINE
>   	select ASYNC_TX_ENABLE_CHANNEL_SWITCH
>   	---help---
> -	  Enable support for the Freescale Elo and Elo Plus DMA controllers.
> -	  The Elo is the DMA controller on some 82xx and 83xx parts, and the
> -	  Elo Plus is the DMA controller on 85xx and 86xx parts.
> +	  Enable support for the Freescale Elo series DMA controllers.
> +	  The Elo is the DMA controller on some mpc82xx and mpc83xx parts, the
> +	  EloPlus is on mpc85xx and mpc86xx and Pxxx parts, and the Elo3 is on
> +	  some Txxx and Bxxx parts.
>   
>   config MPC512X_DMA
>   	tristate "Freescale MPC512x built-in DMA engine support"
> diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c
> index 49e8fbd..16a9a48 100644
> --- a/drivers/dma/fsldma.c
> +++ b/drivers/dma/fsldma.c
> @@ -1261,7 +1261,9 @@ static int fsl_dma_chan_probe(struct fsldma_device *fdev,
>   	WARN_ON(fdev->feature != chan->feature);
>   
>   	chan->dev = fdev->dev;
> -	chan->id = ((res.start - 0x100) & 0xfff) >> 7;
> +	chan->id = (res.start & 0xfff) < 0x300 ?
> +		   ((res.start - 0x100) & 0xfff) >> 7 :
> +		   ((res.start - 0x200) & 0xfff) >> 7;
>   	if (chan->id >= FSL_DMA_MAX_CHANS_PER_DEVICE) {
>   		dev_err(fdev->dev, "too many channels for device\n");
>   		err = -EINVAL;
> @@ -1434,6 +1436,7 @@ static int fsldma_of_remove(struct platform_device *op)
>   }
>   
>   static const struct of_device_id fsldma_of_ids[] = {
> +	{ .compatible = "fsl,elo3-dma", },
>   	{ .compatible = "fsl,eloplus-dma", },
>   	{ .compatible = "fsl,elo-dma", },
>   	{}
> @@ -1455,7 +1458,7 @@ static struct platform_driver fsldma_of_driver = {
>   
>   static __init int fsldma_init(void)
>   {
> -	pr_info("Freescale Elo / Elo Plus DMA driver\n");
> +	pr_info("Freescale Elo series DMA driver\n");
>   	return platform_driver_register(&fsldma_of_driver);
>   }
>   
> @@ -1467,5 +1470,5 @@ static void __exit fsldma_exit(void)
>   subsys_initcall(fsldma_init);
>   module_exit(fsldma_exit);
>   
> -MODULE_DESCRIPTION("Freescale Elo / Elo Plus DMA driver");
> +MODULE_DESCRIPTION("Freescale Elo series DMA driver");
>   MODULE_LICENSE("GPL");
> diff --git a/drivers/dma/fsldma.h b/drivers/dma/fsldma.h
> index f5c3879..1ffc244 100644
> --- a/drivers/dma/fsldma.h
> +++ b/drivers/dma/fsldma.h
> @@ -112,7 +112,7 @@ struct fsldma_chan_regs {
>   };
>   
>   struct fsldma_chan;
> -#define FSL_DMA_MAX_CHANS_PER_DEVICE 4
> +#define FSL_DMA_MAX_CHANS_PER_DEVICE 8
>   
>   struct fsldma_device {
>   	void __iomem *regs;	/* DGSR register base */

^ permalink raw reply

* RE: [PATCH v5 4/4] powerpc/85xx: add sysfs for pw20 state and altivec idle
From: Bhushan Bharat-R65777 @ 2013-10-17  6:00 UTC (permalink / raw)
  To: Wang Dongsheng-B40534, Wood Scott-B07421; +Cc: linuxppc-dev@lists.ozlabs.org
In-Reply-To: <ABB05CD9C9F68C46A5CEDC7F15439259010B189E@039-SN2MPN1-021.039d.mgd.msft.net>



> -----Original Message-----
> From: Wang Dongsheng-B40534
> Sent: Thursday, October 17, 2013 11:22 AM
> To: Bhushan Bharat-R65777; Wood Scott-B07421
> Cc: linuxppc-dev@lists.ozlabs.org
> Subject: RE: [PATCH v5 4/4] powerpc/85xx: add sysfs for pw20 state and al=
tivec
> idle
>=20
>=20
>=20
> > -----Original Message-----
> > From: Bhushan Bharat-R65777
> > Sent: Thursday, October 17, 2013 11:20 AM
> > To: Wang Dongsheng-B40534; Wood Scott-B07421
> > Cc: linuxppc-dev@lists.ozlabs.org
> > Subject: RE: [PATCH v5 4/4] powerpc/85xx: add sysfs for pw20 state and
> > altivec idle
> >
> >
> >
> > > -----Original Message-----
> > > From: Wang Dongsheng-B40534
> > > Sent: Thursday, October 17, 2013 8:16 AM
> > > To: Bhushan Bharat-R65777; Wood Scott-B07421
> > > Cc: linuxppc-dev@lists.ozlabs.org
> > > Subject: RE: [PATCH v5 4/4] powerpc/85xx: add sysfs for pw20 state
> > > and altivec idle
> > >
> > >
> > >
> > > > -----Original Message-----
> > > > From: Bhushan Bharat-R65777
> > > > Sent: Thursday, October 17, 2013 1:01 AM
> > > > To: Wang Dongsheng-B40534; Wood Scott-B07421
> > > > Cc: linuxppc-dev@lists.ozlabs.org
> > > > Subject: RE: [PATCH v5 4/4] powerpc/85xx: add sysfs for pw20 state
> > > > and altivec idle
> > > >
> > > >
> > > >
> > > > > -----Original Message-----
> > > > > From: Wang Dongsheng-B40534
> > > > > Sent: Tuesday, October 15, 2013 2:51 PM
> > > > > To: Wood Scott-B07421
> > > > > Cc: Bhushan Bharat-R65777; linuxppc-dev@lists.ozlabs.org; Wang
> > > > Dongsheng-B40534
> > > > > Subject: [PATCH v5 4/4] powerpc/85xx: add sysfs for pw20 state
> > > > > and
> > > > altivec idle
> > > > >
> > > > > From: Wang Dongsheng <dongsheng.wang@freescale.com>
> > > > >
> > > > > Add a sys interface to enable/diable pw20 state or altivec idle,
> > > > > and
> > > > control the
> > > > > wait entry time.
> > > > >
> > > > > Enable/Disable interface:
> > > > > 0, disable. 1, enable.
> > > > > /sys/devices/system/cpu/cpuX/pw20_state
> > > > > /sys/devices/system/cpu/cpuX/altivec_idle
> > > > >
> > > > > Set wait time interface:(Nanosecond)
> > > > > /sys/devices/system/cpu/cpuX/pw20_wait_time
> > > > > /sys/devices/system/cpu/cpuX/altivec_idle_wait_time
> > > > > Example: Base on TBfreq is 41MHZ.
> > > > > 1~48(ns): TB[63]
> > > > > 49~97(ns): TB[62]
> > > > > 98~195(ns): TB[61]
> > > > > 196~390(ns): TB[60]
> > > > > 391~780(ns): TB[59]
> > > > > 781~1560(ns): TB[58]
> > > > > ...
> > > > >
> > > > > Signed-off-by: Wang Dongsheng <dongsheng.wang@freescale.com>
> > > > > ---
> > > > > *v5:
> > > > > Change get_idle_ticks_bit function implementation.
> > > > >
> > > > > *v4:
> > > > > Move code from 85xx/common.c to kernel/sysfs.c.
> > > > >
> > > > > Remove has_pw20_altivec_idle function.
> > > > >
> > > > > Change wait "entry_bit" to wait time.
> > > > >
> > > > > diff --git a/arch/powerpc/kernel/sysfs.c
> > > > > b/arch/powerpc/kernel/sysfs.c
> > > > index
> > > > > 27a90b9..10d1128 100644
> > > > > --- a/arch/powerpc/kernel/sysfs.c
> > > > > +++ b/arch/powerpc/kernel/sysfs.c
> > > > > @@ -85,6 +85,284 @@ __setup("smt-snooze-delay=3D",
> > > > setup_smt_snooze_delay);
> > > > >
> > > > >  #endif /* CONFIG_PPC64 */
> > > > >
> > > > > +#ifdef CONFIG_FSL_SOC
> > > > > +#define MAX_BIT				63
> > > > > +
> > > > > +static u64 pw20_wt;
> > > > > +static u64 altivec_idle_wt;
> > > > > +
> > > > > +static unsigned int get_idle_ticks_bit(u64 ns) {
> > > > > +	u64 cycle;
> > > > > +
> > > > > +	if (ns >=3D 10000)
> > > > > +		cycle =3D div_u64(ns + 500, 1000) * tb_ticks_per_usec;
> > > > > +	else
> > > > > +		cycle =3D div_u64(ns * tb_ticks_per_usec, 1000);
> > > > > +
> > > > > +	if (!cycle)
> > > > > +		return 0;
> > > > > +
> > > > > +	return ilog2(cycle);
> > > > > +}
> > > > > +
> > > > > +static void do_show_pwrmgtcr0(void *val) {
> > > > > +	u32 *value =3D val;
> > > > > +
> > > > > +	*value =3D mfspr(SPRN_PWRMGTCR0); }
> > > > > +
> > > > > +static ssize_t show_pw20_state(struct device *dev,
> > > > > +				struct device_attribute *attr, char *buf) {
> > > > > +	u32 value;
> > > > > +	unsigned int cpu =3D dev->id;
> > > > > +
> > > > > +	smp_call_function_single(cpu, do_show_pwrmgtcr0, &value, 1);
> > > > > +
> > > > > +	value &=3D PWRMGTCR0_PW20_WAIT;
> > > > > +
> > > > > +	return sprintf(buf, "%u\n", value ? 1 : 0); }
> > > > > +
> > > > > +static void do_store_pw20_state(void *val) {
> > > > > +	u32 *value =3D val;
> > > > > +	u32 pw20_state;
> > > > > +
> > > > > +	pw20_state =3D mfspr(SPRN_PWRMGTCR0);
> > > > > +
> > > > > +	if (*value)
> > > > > +		pw20_state |=3D PWRMGTCR0_PW20_WAIT;
> > > > > +	else
> > > > > +		pw20_state &=3D ~PWRMGTCR0_PW20_WAIT;
> > > > > +
> > > > > +	mtspr(SPRN_PWRMGTCR0, pw20_state); }
> > > > > +
> > > > > +static ssize_t store_pw20_state(struct device *dev,
> > > > > +				struct device_attribute *attr,
> > > > > +				const char *buf, size_t count) {
> > > > > +	u32 value;
> > > > > +	unsigned int cpu =3D dev->id;
> > > > > +
> > > > > +	if (kstrtou32(buf, 0, &value))
> > > > > +		return -EINVAL;
> > > > > +
> > > > > +	if (value > 1)
> > > > > +		return -EINVAL;
> > > > > +
> > > > > +	smp_call_function_single(cpu, do_store_pw20_state, &value, 1);
> > > > > +
> > > > > +	return count;
> > > > > +}
> > > > > +
> > > > > +static ssize_t show_pw20_wait_time(struct device *dev,
> > > > > +				struct device_attribute *attr, char *buf) {
> > > > > +	u32 value;
> > > > > +	u64 tb_cycle;
> > > > > +	s64 time;
> > > > > +
> > > > > +	unsigned int cpu =3D dev->id;
> > > > > +
> > > > > +	if (!pw20_wt) {
> > > > > +		smp_call_function_single(cpu, do_show_pwrmgtcr0, &value,
> > 1);
> > > > > +		value =3D (value & PWRMGTCR0_PW20_ENT) >>
> > > > > +					PWRMGTCR0_PW20_ENT_SHIFT;
> > > > > +
> > > > > +		tb_cycle =3D (1 << (MAX_BIT - value)) * 2;
> > > >
> > > > Is value =3D 0 and value =3D 1 legal? These will make tb_cycle =3D =
0,
> > > >
> > > > > +		time =3D div_u64(tb_cycle * 1000, tb_ticks_per_usec) - 1;
> > > >
> > > > And time =3D -1;
> > > >
> > > Please look at the end of the function, :)
> > >
> > > "return sprintf(buf, "%llu\n", time > 0 ? time : 0);"
> >
> > I know you return 0 if value =3D 0/1, my question was that, is this
> > correct as per specification?
> >
> > Ahh, also for "value" upto 7 you will return 0, no?
> >
> If value =3D 0, MAX_BIT - value =3D 63
> tb_cycle =3D 0xffffffff_ffffffff, tb_cycle * 1000 will overflow, but this
> situation is not possible.
> Because if the "value =3D 0" means this feature will be "disable".
> Now The default wait bit is 50(MAX_BIT - value, value =3D 13), the PW20/A=
ltivec
> Idle wait entry time is about 1ms, this time is very long for wait idle t=
ime,
> and it's cannot be increased(means (MAX_BIT - value) cannot greater than =
50).

What you said is not obvious from code and so at least write a comment that=
 value will be always >=3D 13 or value will never be less than < 8 and belo=
w calculation will not overflow. may be error out if value is less than 8.

-Bharat

>=20
> If (MAX_BIT-value) =3D 0, tb_cycle =3D 2,
> div_u64(tb_cycle * 1000, tb_ticks_per_usec) - 1 =3D ((2 * 1000) / 41) - 1=
 =3D 48 - 1
> =3D 47
>=20
> the return value is 47
>=20
> > -Bharat
> >
> > >
> > > -dongsheng
> > >
> > > >
> > > > > +	} else {
> > > > > +		time =3D pw20_wt;
> > > > > +	}
> > > > > +
> > > > > +	return sprintf(buf, "%llu\n", time > 0 ? time : 0);
> > > > > }
> > > > > +

^ permalink raw reply

* [PATCH V2] powerpc: Fix 64K page size support for PPC44x
From: Alistair Popple @ 2013-10-17  6:08 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Alistair Popple, aneesh.kumar

PPC44x supports page sizes other than 4K however when 64K page sizes
are selected compilation fails. This is due to a change in the
definition of pgtable_t introduced by the following patch:

commit 5c1f6ee9a31cbdac90bbb8ae1ba4475031ac74b4
Author: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
powerpc: Reduce PTE table memory wastage

The above patch only implements the new layout for PPC64 so it doesn't
compile for PPC32 with a 64K page size. Ideally we should implement
the same layout for PPC32 however for the meantime this patch reverts
the definition of pgtable_t for PPC32.

Signed-off-by: Alistair Popple <alistair@popple.id.au>
---
 arch/powerpc/include/asm/page.h |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/powerpc/include/asm/page.h b/arch/powerpc/include/asm/page.h
index b9f4262..7dde512 100644
--- a/arch/powerpc/include/asm/page.h
+++ b/arch/powerpc/include/asm/page.h
@@ -403,7 +403,7 @@ void arch_free_page(struct page *page, int order);
 
 struct vm_area_struct;
 
-#ifdef CONFIG_PPC_64K_PAGES
+#if defined(CONFIG_PPC_64K_PAGES) && defined(CONFIG_PPC64)
 typedef pte_t *pgtable_t;
 #else
 typedef struct page *pgtable_t;
-- 
1.7.10.4

^ permalink raw reply related

* RE: [PATCH v5 4/4] powerpc/85xx: add sysfs for pw20 state and altivec idle
From: Wang Dongsheng-B40534 @ 2013-10-17  6:34 UTC (permalink / raw)
  To: Bhushan Bharat-R65777, Wood Scott-B07421; +Cc: linuxppc-dev@lists.ozlabs.org
In-Reply-To: <6A3DF150A5B70D4F9B66A25E3F7C888D071C34C1@039-SN2MPN1-013.039d.mgd.msft.net>



> -----Original Message-----
> From: Bhushan Bharat-R65777
> Sent: Thursday, October 17, 2013 2:00 PM
> To: Wang Dongsheng-B40534; Wood Scott-B07421
> Cc: linuxppc-dev@lists.ozlabs.org
> Subject: RE: [PATCH v5 4/4] powerpc/85xx: add sysfs for pw20 state and
> altivec idle
>=20
>=20
>=20
> > -----Original Message-----
> > From: Wang Dongsheng-B40534
> > Sent: Thursday, October 17, 2013 11:22 AM
> > To: Bhushan Bharat-R65777; Wood Scott-B07421
> > Cc: linuxppc-dev@lists.ozlabs.org
> > Subject: RE: [PATCH v5 4/4] powerpc/85xx: add sysfs for pw20 state and
> > altivec idle
> >
> >
> >
> > > -----Original Message-----
> > > From: Bhushan Bharat-R65777
> > > Sent: Thursday, October 17, 2013 11:20 AM
> > > To: Wang Dongsheng-B40534; Wood Scott-B07421
> > > Cc: linuxppc-dev@lists.ozlabs.org
> > > Subject: RE: [PATCH v5 4/4] powerpc/85xx: add sysfs for pw20 state
> > > and altivec idle
> > >
> > >
> > >
> > > > -----Original Message-----
> > > > From: Wang Dongsheng-B40534
> > > > Sent: Thursday, October 17, 2013 8:16 AM
> > > > To: Bhushan Bharat-R65777; Wood Scott-B07421
> > > > Cc: linuxppc-dev@lists.ozlabs.org
> > > > Subject: RE: [PATCH v5 4/4] powerpc/85xx: add sysfs for pw20 state
> > > > and altivec idle
> > > >
> > > >
> > > >
> > > > > -----Original Message-----
> > > > > From: Bhushan Bharat-R65777
> > > > > Sent: Thursday, October 17, 2013 1:01 AM
> > > > > To: Wang Dongsheng-B40534; Wood Scott-B07421
> > > > > Cc: linuxppc-dev@lists.ozlabs.org
> > > > > Subject: RE: [PATCH v5 4/4] powerpc/85xx: add sysfs for pw20
> > > > > state and altivec idle
> > > > >
> > > > >
> > > > >
> > > > > > -----Original Message-----
> > > > > > From: Wang Dongsheng-B40534
> > > > > > Sent: Tuesday, October 15, 2013 2:51 PM
> > > > > > To: Wood Scott-B07421
> > > > > > Cc: Bhushan Bharat-R65777; linuxppc-dev@lists.ozlabs.org; Wang
> > > > > Dongsheng-B40534
> > > > > > Subject: [PATCH v5 4/4] powerpc/85xx: add sysfs for pw20 state
> > > > > > and
> > > > > altivec idle
> > > > > >
> > > > > > From: Wang Dongsheng <dongsheng.wang@freescale.com>
> > > > > >
> > > > > > Add a sys interface to enable/diable pw20 state or altivec
> > > > > > idle, and
> > > > > control the
> > > > > > wait entry time.
> > > > > >
> > > > > > Enable/Disable interface:
> > > > > > 0, disable. 1, enable.
> > > > > > /sys/devices/system/cpu/cpuX/pw20_state
> > > > > > /sys/devices/system/cpu/cpuX/altivec_idle
> > > > > >
> > > > > > Set wait time interface:(Nanosecond)
> > > > > > /sys/devices/system/cpu/cpuX/pw20_wait_time
> > > > > > /sys/devices/system/cpu/cpuX/altivec_idle_wait_time
> > > > > > Example: Base on TBfreq is 41MHZ.
> > > > > > 1~48(ns): TB[63]
> > > > > > 49~97(ns): TB[62]
> > > > > > 98~195(ns): TB[61]
> > > > > > 196~390(ns): TB[60]
> > > > > > 391~780(ns): TB[59]
> > > > > > 781~1560(ns): TB[58]
> > > > > > ...
> > > > > >
> > > > > > Signed-off-by: Wang Dongsheng <dongsheng.wang@freescale.com>
> > > > > > ---
> > > > > > *v5:
> > > > > > Change get_idle_ticks_bit function implementation.
> > > > > >
> > > > > > *v4:
> > > > > > Move code from 85xx/common.c to kernel/sysfs.c.
> > > > > >
> > > > > > Remove has_pw20_altivec_idle function.
> > > > > >
> > > > > > Change wait "entry_bit" to wait time.
> > > > > >
> > > > > > diff --git a/arch/powerpc/kernel/sysfs.c
> > > > > > b/arch/powerpc/kernel/sysfs.c
> > > > > index
> > > > > > 27a90b9..10d1128 100644
> > > > > > --- a/arch/powerpc/kernel/sysfs.c
> > > > > > +++ b/arch/powerpc/kernel/sysfs.c
> > > > > > @@ -85,6 +85,284 @@ __setup("smt-snooze-delay=3D",
> > > > > setup_smt_snooze_delay);
> > > > > >
> > > > > >  #endif /* CONFIG_PPC64 */
> > > > > >
> > > > > > +#ifdef CONFIG_FSL_SOC
> > > > > > +#define MAX_BIT				63
> > > > > > +
> > > > > > +static u64 pw20_wt;
> > > > > > +static u64 altivec_idle_wt;
> > > > > > +
> > > > > > +static unsigned int get_idle_ticks_bit(u64 ns) {
> > > > > > +	u64 cycle;
> > > > > > +
> > > > > > +	if (ns >=3D 10000)
> > > > > > +		cycle =3D div_u64(ns + 500, 1000) * tb_ticks_per_usec;
> > > > > > +	else
> > > > > > +		cycle =3D div_u64(ns * tb_ticks_per_usec, 1000);
> > > > > > +
> > > > > > +	if (!cycle)
> > > > > > +		return 0;
> > > > > > +
> > > > > > +	return ilog2(cycle);
> > > > > > +}
> > > > > > +
> > > > > > +static void do_show_pwrmgtcr0(void *val) {
> > > > > > +	u32 *value =3D val;
> > > > > > +
> > > > > > +	*value =3D mfspr(SPRN_PWRMGTCR0); }
> > > > > > +
> > > > > > +static ssize_t show_pw20_state(struct device *dev,
> > > > > > +				struct device_attribute *attr, char *buf) {
> > > > > > +	u32 value;
> > > > > > +	unsigned int cpu =3D dev->id;
> > > > > > +
> > > > > > +	smp_call_function_single(cpu, do_show_pwrmgtcr0, &value, 1);
> > > > > > +
> > > > > > +	value &=3D PWRMGTCR0_PW20_WAIT;
> > > > > > +
> > > > > > +	return sprintf(buf, "%u\n", value ? 1 : 0); }
> > > > > > +
> > > > > > +static void do_store_pw20_state(void *val) {
> > > > > > +	u32 *value =3D val;
> > > > > > +	u32 pw20_state;
> > > > > > +
> > > > > > +	pw20_state =3D mfspr(SPRN_PWRMGTCR0);
> > > > > > +
> > > > > > +	if (*value)
> > > > > > +		pw20_state |=3D PWRMGTCR0_PW20_WAIT;
> > > > > > +	else
> > > > > > +		pw20_state &=3D ~PWRMGTCR0_PW20_WAIT;
> > > > > > +
> > > > > > +	mtspr(SPRN_PWRMGTCR0, pw20_state); }
> > > > > > +
> > > > > > +static ssize_t store_pw20_state(struct device *dev,
> > > > > > +				struct device_attribute *attr,
> > > > > > +				const char *buf, size_t count) {
> > > > > > +	u32 value;
> > > > > > +	unsigned int cpu =3D dev->id;
> > > > > > +
> > > > > > +	if (kstrtou32(buf, 0, &value))
> > > > > > +		return -EINVAL;
> > > > > > +
> > > > > > +	if (value > 1)
> > > > > > +		return -EINVAL;
> > > > > > +
> > > > > > +	smp_call_function_single(cpu, do_store_pw20_state, &value,
> > > > > > +1);
> > > > > > +
> > > > > > +	return count;
> > > > > > +}
> > > > > > +
> > > > > > +static ssize_t show_pw20_wait_time(struct device *dev,
> > > > > > +				struct device_attribute *attr, char *buf) {
> > > > > > +	u32 value;
> > > > > > +	u64 tb_cycle;
> > > > > > +	s64 time;
> > > > > > +
> > > > > > +	unsigned int cpu =3D dev->id;
> > > > > > +
> > > > > > +	if (!pw20_wt) {
> > > > > > +		smp_call_function_single(cpu, do_show_pwrmgtcr0, &value,
> > > 1);
> > > > > > +		value =3D (value & PWRMGTCR0_PW20_ENT) >>
> > > > > > +					PWRMGTCR0_PW20_ENT_SHIFT;
> > > > > > +
> > > > > > +		tb_cycle =3D (1 << (MAX_BIT - value)) * 2;
> > > > >
> > > > > Is value =3D 0 and value =3D 1 legal? These will make tb_cycle =
=3D 0,
> > > > >
> > > > > > +		time =3D div_u64(tb_cycle * 1000, tb_ticks_per_usec) - 1;
> > > > >
> > > > > And time =3D -1;
> > > > >
> > > > Please look at the end of the function, :)
> > > >
> > > > "return sprintf(buf, "%llu\n", time > 0 ? time : 0);"
> > >
> > > I know you return 0 if value =3D 0/1, my question was that, is this
> > > correct as per specification?
> > >
> > > Ahh, also for "value" upto 7 you will return 0, no?
> > >
> > If value =3D 0, MAX_BIT - value =3D 63
> > tb_cycle =3D 0xffffffff_ffffffff, tb_cycle * 1000 will overflow, but
> > this situation is not possible.
> > Because if the "value =3D 0" means this feature will be "disable".
> > Now The default wait bit is 50(MAX_BIT - value, value =3D 13), the
> > PW20/Altivec Idle wait entry time is about 1ms, this time is very long
> > for wait idle time, and it's cannot be increased(means (MAX_BIT - value=
)
> cannot greater than 50).
>=20
> What you said is not obvious from code and so at least write a comment
> that value will be always >=3D 13 or value will never be less than < 8 an=
d
> below calculation will not overflow. may be error out if value is less
> than 8.
>=20
The "value" less than 10, this will overflow.
There is not error, The code I knew it could not be less than 10, that's wh=
y I use the following code. :)

tb_cycle =3D (1 << (MAX_BIT - value)) * 2;=20
time =3D div_u64(tb_cycle * 1000, tb_ticks_per_usec) - 1;

-dongsheng

> -Bharat
>=20
> >
> > If (MAX_BIT-value) =3D 0, tb_cycle =3D 2,
> > div_u64(tb_cycle * 1000, tb_ticks_per_usec) - 1 =3D ((2 * 1000) / 41) -
> > 1 =3D 48 - 1 =3D 47
> >
> > the return value is 47
> >
> > > -Bharat
> > >
> > > >
> > > > -dongsheng
> > > >
> > > > >
> > > > > > +	} else {
> > > > > > +		time =3D pw20_wt;
> > > > > > +	}
> > > > > > +
> > > > > > +	return sprintf(buf, "%llu\n", time > 0 ? time : 0);
> > > > > > }
> > > > > > +

^ permalink raw reply

* RE: [PATCH v5 4/4] powerpc/85xx: add sysfs for pw20 state and altivec idle
From: Bhushan Bharat-R65777 @ 2013-10-17  6:45 UTC (permalink / raw)
  To: Wang Dongsheng-B40534, Wood Scott-B07421; +Cc: linuxppc-dev@lists.ozlabs.org
In-Reply-To: <ABB05CD9C9F68C46A5CEDC7F15439259010B195F@039-SN2MPN1-021.039d.mgd.msft.net>



> > > -----Original Message-----
> > > From: Wang Dongsheng-B40534
> > > Sent: Thursday, October 17, 2013 11:22 AM
> > > To: Bhushan Bharat-R65777; Wood Scott-B07421
> > > Cc: linuxppc-dev@lists.ozlabs.org
> > > Subject: RE: [PATCH v5 4/4] powerpc/85xx: add sysfs for pw20 state
> > > and altivec idle
> > >
> > >
> > >
> > > > -----Original Message-----
> > > > From: Bhushan Bharat-R65777
> > > > Sent: Thursday, October 17, 2013 11:20 AM
> > > > To: Wang Dongsheng-B40534; Wood Scott-B07421
> > > > Cc: linuxppc-dev@lists.ozlabs.org
> > > > Subject: RE: [PATCH v5 4/4] powerpc/85xx: add sysfs for pw20 state
> > > > and altivec idle
> > > >
> > > >
> > > >
> > > > > -----Original Message-----
> > > > > From: Wang Dongsheng-B40534
> > > > > Sent: Thursday, October 17, 2013 8:16 AM
> > > > > To: Bhushan Bharat-R65777; Wood Scott-B07421
> > > > > Cc: linuxppc-dev@lists.ozlabs.org
> > > > > Subject: RE: [PATCH v5 4/4] powerpc/85xx: add sysfs for pw20
> > > > > state and altivec idle
> > > > >
> > > > >
> > > > >
> > > > > > -----Original Message-----
> > > > > > From: Bhushan Bharat-R65777
> > > > > > Sent: Thursday, October 17, 2013 1:01 AM
> > > > > > To: Wang Dongsheng-B40534; Wood Scott-B07421
> > > > > > Cc: linuxppc-dev@lists.ozlabs.org
> > > > > > Subject: RE: [PATCH v5 4/4] powerpc/85xx: add sysfs for pw20
> > > > > > state and altivec idle
> > > > > >
> > > > > >
> > > > > >
> > > > > > > -----Original Message-----
> > > > > > > From: Wang Dongsheng-B40534
> > > > > > > Sent: Tuesday, October 15, 2013 2:51 PM
> > > > > > > To: Wood Scott-B07421
> > > > > > > Cc: Bhushan Bharat-R65777; linuxppc-dev@lists.ozlabs.org;
> > > > > > > Wang
> > > > > > Dongsheng-B40534
> > > > > > > Subject: [PATCH v5 4/4] powerpc/85xx: add sysfs for pw20
> > > > > > > state and
> > > > > > altivec idle
> > > > > > >
> > > > > > > From: Wang Dongsheng <dongsheng.wang@freescale.com>
> > > > > > >
> > > > > > > Add a sys interface to enable/diable pw20 state or altivec
> > > > > > > idle, and
> > > > > > control the
> > > > > > > wait entry time.
> > > > > > >
> > > > > > > Enable/Disable interface:
> > > > > > > 0, disable. 1, enable.
> > > > > > > /sys/devices/system/cpu/cpuX/pw20_state
> > > > > > > /sys/devices/system/cpu/cpuX/altivec_idle
> > > > > > >
> > > > > > > Set wait time interface:(Nanosecond)
> > > > > > > /sys/devices/system/cpu/cpuX/pw20_wait_time
> > > > > > > /sys/devices/system/cpu/cpuX/altivec_idle_wait_time
> > > > > > > Example: Base on TBfreq is 41MHZ.
> > > > > > > 1~48(ns): TB[63]
> > > > > > > 49~97(ns): TB[62]
> > > > > > > 98~195(ns): TB[61]
> > > > > > > 196~390(ns): TB[60]
> > > > > > > 391~780(ns): TB[59]
> > > > > > > 781~1560(ns): TB[58]
> > > > > > > ...
> > > > > > >
> > > > > > > Signed-off-by: Wang Dongsheng <dongsheng.wang@freescale.com>
> > > > > > > ---
> > > > > > > *v5:
> > > > > > > Change get_idle_ticks_bit function implementation.
> > > > > > >
> > > > > > > *v4:
> > > > > > > Move code from 85xx/common.c to kernel/sysfs.c.
> > > > > > >
> > > > > > > Remove has_pw20_altivec_idle function.
> > > > > > >
> > > > > > > Change wait "entry_bit" to wait time.
> > > > > > >
> > > > > > > diff --git a/arch/powerpc/kernel/sysfs.c
> > > > > > > b/arch/powerpc/kernel/sysfs.c
> > > > > > index
> > > > > > > 27a90b9..10d1128 100644
> > > > > > > --- a/arch/powerpc/kernel/sysfs.c
> > > > > > > +++ b/arch/powerpc/kernel/sysfs.c
> > > > > > > @@ -85,6 +85,284 @@ __setup("smt-snooze-delay=3D",
> > > > > > setup_smt_snooze_delay);
> > > > > > >
> > > > > > >  #endif /* CONFIG_PPC64 */
> > > > > > >
> > > > > > > +#ifdef CONFIG_FSL_SOC
> > > > > > > +#define MAX_BIT				63
> > > > > > > +
> > > > > > > +static u64 pw20_wt;
> > > > > > > +static u64 altivec_idle_wt;
> > > > > > > +
> > > > > > > +static unsigned int get_idle_ticks_bit(u64 ns) {
> > > > > > > +	u64 cycle;
> > > > > > > +
> > > > > > > +	if (ns >=3D 10000)
> > > > > > > +		cycle =3D div_u64(ns + 500, 1000) * tb_ticks_per_usec;
> > > > > > > +	else
> > > > > > > +		cycle =3D div_u64(ns * tb_ticks_per_usec, 1000);
> > > > > > > +
> > > > > > > +	if (!cycle)
> > > > > > > +		return 0;
> > > > > > > +
> > > > > > > +	return ilog2(cycle);
> > > > > > > +}
> > > > > > > +
> > > > > > > +static void do_show_pwrmgtcr0(void *val) {
> > > > > > > +	u32 *value =3D val;
> > > > > > > +
> > > > > > > +	*value =3D mfspr(SPRN_PWRMGTCR0); }
> > > > > > > +
> > > > > > > +static ssize_t show_pw20_state(struct device *dev,
> > > > > > > +				struct device_attribute *attr, char *buf) {
> > > > > > > +	u32 value;
> > > > > > > +	unsigned int cpu =3D dev->id;
> > > > > > > +
> > > > > > > +	smp_call_function_single(cpu, do_show_pwrmgtcr0, &value,
> > > > > > > +1);
> > > > > > > +
> > > > > > > +	value &=3D PWRMGTCR0_PW20_WAIT;
> > > > > > > +
> > > > > > > +	return sprintf(buf, "%u\n", value ? 1 : 0); }
> > > > > > > +
> > > > > > > +static void do_store_pw20_state(void *val) {
> > > > > > > +	u32 *value =3D val;
> > > > > > > +	u32 pw20_state;
> > > > > > > +
> > > > > > > +	pw20_state =3D mfspr(SPRN_PWRMGTCR0);
> > > > > > > +
> > > > > > > +	if (*value)
> > > > > > > +		pw20_state |=3D PWRMGTCR0_PW20_WAIT;
> > > > > > > +	else
> > > > > > > +		pw20_state &=3D ~PWRMGTCR0_PW20_WAIT;
> > > > > > > +
> > > > > > > +	mtspr(SPRN_PWRMGTCR0, pw20_state); }
> > > > > > > +
> > > > > > > +static ssize_t store_pw20_state(struct device *dev,
> > > > > > > +				struct device_attribute *attr,
> > > > > > > +				const char *buf, size_t count) {
> > > > > > > +	u32 value;
> > > > > > > +	unsigned int cpu =3D dev->id;
> > > > > > > +
> > > > > > > +	if (kstrtou32(buf, 0, &value))
> > > > > > > +		return -EINVAL;
> > > > > > > +
> > > > > > > +	if (value > 1)
> > > > > > > +		return -EINVAL;
> > > > > > > +
> > > > > > > +	smp_call_function_single(cpu, do_store_pw20_state, &value,
> > > > > > > +1);
> > > > > > > +
> > > > > > > +	return count;
> > > > > > > +}
> > > > > > > +
> > > > > > > +static ssize_t show_pw20_wait_time(struct device *dev,
> > > > > > > +				struct device_attribute *attr, char *buf) {
> > > > > > > +	u32 value;
> > > > > > > +	u64 tb_cycle;
> > > > > > > +	s64 time;
> > > > > > > +
> > > > > > > +	unsigned int cpu =3D dev->id;
> > > > > > > +
> > > > > > > +	if (!pw20_wt) {
> > > > > > > +		smp_call_function_single(cpu, do_show_pwrmgtcr0, &value,
> > > > 1);
> > > > > > > +		value =3D (value & PWRMGTCR0_PW20_ENT) >>
> > > > > > > +					PWRMGTCR0_PW20_ENT_SHIFT;
> > > > > > > +
> > > > > > > +		tb_cycle =3D (1 << (MAX_BIT - value)) * 2;
> > > > > >
> > > > > > Is value =3D 0 and value =3D 1 legal? These will make tb_cycle =
=3D
> > > > > > 0,
> > > > > >
> > > > > > > +		time =3D div_u64(tb_cycle * 1000, tb_ticks_per_usec) - 1;
> > > > > >
> > > > > > And time =3D -1;
> > > > > >
> > > > > Please look at the end of the function, :)
> > > > >
> > > > > "return sprintf(buf, "%llu\n", time > 0 ? time : 0);"
> > > >
> > > > I know you return 0 if value =3D 0/1, my question was that, is this
> > > > correct as per specification?
> > > >
> > > > Ahh, also for "value" upto 7 you will return 0, no?
> > > >
> > > If value =3D 0, MAX_BIT - value =3D 63
> > > tb_cycle =3D 0xffffffff_ffffffff, tb_cycle * 1000 will overflow, but
> > > this situation is not possible.
> > > Because if the "value =3D 0" means this feature will be "disable".
> > > Now The default wait bit is 50(MAX_BIT - value, value =3D 13), the
> > > PW20/Altivec Idle wait entry time is about 1ms, this time is very
> > > long for wait idle time, and it's cannot be increased(means (MAX_BIT
> > > - value)
> > cannot greater than 50).
> >
> > What you said is not obvious from code and so at least write a comment
> > that value will be always >=3D 13 or value will never be less than < 8
> > and below calculation will not overflow. may be error out if value is
> > less than 8.
> >
> The "value" less than 10, this will overflow.
> There is not error, The code I knew it could not be less than 10, that's =
why I
> use the following code. :)

I am sorry to persist but this is not about what you know, this is about ho=
w code is read and code does not say what you know, so add a comment at lea=
st and error out/warn when "value" is less than a certain number.

-Bharat

>=20
> tb_cycle =3D (1 << (MAX_BIT - value)) * 2; time =3D div_u64(tb_cycle * 10=
00,
> tb_ticks_per_usec) - 1;
>=20
> -dongsheng
>=20
> > -Bharat
> >
> > >
> > > If (MAX_BIT-value) =3D 0, tb_cycle =3D 2, div_u64(tb_cycle * 1000,
> > > tb_ticks_per_usec) - 1 =3D ((2 * 1000) / 41) -
> > > 1 =3D 48 - 1 =3D 47
> > >
> > > the return value is 47
> > >
> > > > -Bharat
> > > >
> > > > >
> > > > > -dongsheng
> > > > >
> > > > > >
> > > > > > > +	} else {
> > > > > > > +		time =3D pw20_wt;
> > > > > > > +	}
> > > > > > > +
> > > > > > > +	return sprintf(buf, "%llu\n", time > 0 ? time : 0);
> > > > > > > }
> > > > > > > +

^ permalink raw reply

* [PATCH] powerpc/p1010rdb:update mtd of nand to adapt to both old and new p1010rdb
From: Zhao Qiang @ 2013-10-17  6:59 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Zhao Qiang

P1010rdb-pa and p1010rdb-pb have different mtd of nand.
So update dts to adapt to both p1010rdb-pa and p1010rdb-pb.

Signed-off-by: Zhao Qiang <B45475@freescale.com>
---
 arch/powerpc/boot/dts/p1010rdb-pa.dts     | 40 +++++++++++++++++++++++++++++++
 arch/powerpc/boot/dts/p1010rdb-pa_36b.dts | 40 +++++++++++++++++++++++++++++++
 arch/powerpc/boot/dts/p1010rdb-pb.dts     | 34 ++++++++++++++++++++++++++
 arch/powerpc/boot/dts/p1010rdb-pb_36b.dts | 34 ++++++++++++++++++++++++++
 arch/powerpc/boot/dts/p1010rdb.dtsi       | 40 +------------------------------
 5 files changed, 149 insertions(+), 39 deletions(-)

diff --git a/arch/powerpc/boot/dts/p1010rdb-pa.dts b/arch/powerpc/boot/dts/p1010rdb-pa.dts
index f210ba5..76f252b 100644
--- a/arch/powerpc/boot/dts/p1010rdb-pa.dts
+++ b/arch/powerpc/boot/dts/p1010rdb-pa.dts
@@ -20,6 +20,46 @@
 
 /include/ "p1010rdb.dtsi"
 
+&ifc_nand {
+	partition@0 {
+		/* This location must not be altered  */
+		/* 1MB for u-boot Bootloader Image */
+		reg = <0x0 0x00100000>;
+		label = "NAND U-Boot Image";
+		read-only;
+	};
+
+	partition@100000 {
+		/* 1MB for DTB Image */
+		reg = <0x00100000 0x00100000>;
+		label = "NAND DTB Image";
+	};
+
+	partition@200000 {
+		/* 4MB for Linux Kernel Image */
+		reg = <0x00200000 0x00400000>;
+		label = "NAND Linux Kernel Image";
+	};
+
+	partition@600000 {
+		/* 4MB for Compressed Root file System Image */
+		reg = <0x00600000 0x00400000>;
+		label = "NAND Compressed RFS Image";
+	};
+
+	partition@a00000 {
+		/* 15MB for JFFS2 based Root file System */
+		reg = <0x00a00000 0x00f00000>;
+		label = "NAND JFFS2 Root File System";
+	};
+
+	partition@1900000 {
+		/* 7MB for User Area */
+		reg = <0x01900000 0x00700000>;
+		label = "NAND User area";
+	};
+};
+
 &phy0 {
 	interrupts = <3 1 0 0>;
 };
diff --git a/arch/powerpc/boot/dts/p1010rdb-pa_36b.dts b/arch/powerpc/boot/dts/p1010rdb-pa_36b.dts
index 9740b0c..2961766 100644
--- a/arch/powerpc/boot/dts/p1010rdb-pa_36b.dts
+++ b/arch/powerpc/boot/dts/p1010rdb-pa_36b.dts
@@ -43,6 +43,46 @@
 
 /include/ "p1010rdb.dtsi"
 
+&ifc_nand {
+	partition@0 {
+		/* This location must not be altered  */
+		/* 1MB for u-boot Bootloader Image */
+		reg = <0x0 0x00100000>;
+		label = "NAND U-Boot Image";
+		read-only;
+	};
+
+	partition@100000 {
+		/* 1MB for DTB Image */
+		reg = <0x00100000 0x00100000>;
+		label = "NAND DTB Image";
+	};
+
+	partition@200000 {
+		/* 4MB for Linux Kernel Image */
+		reg = <0x00200000 0x00400000>;
+		label = "NAND Linux Kernel Image";
+	};
+
+	partition@600000 {
+		/* 4MB for Compressed Root file System Image */
+		reg = <0x00600000 0x00400000>;
+		label = "NAND Compressed RFS Image";
+	};
+
+	partition@a00000 {
+		/* 15MB for JFFS2 based Root file System */
+		reg = <0x00a00000 0x00f00000>;
+		label = "NAND JFFS2 Root File System";
+	};
+
+	partition@1900000 {
+		/* 7MB for User Area */
+		reg = <0x01900000 0x00700000>;
+		label = "NAND User area";
+	};
+};
+
 &phy0 {
 	interrupts = <3 1 0 0>;
 };
diff --git a/arch/powerpc/boot/dts/p1010rdb-pb.dts b/arch/powerpc/boot/dts/p1010rdb-pb.dts
index 6eeb7d3..6187e9c 100644
--- a/arch/powerpc/boot/dts/p1010rdb-pb.dts
+++ b/arch/powerpc/boot/dts/p1010rdb-pb.dts
@@ -20,6 +20,40 @@
 
 /include/ "p1010rdb.dtsi"
 
+&ifc_nand {
+	partition@0 {
+		/* This location must not be altered  */
+		/* 2MB for u-boot Image and environment */
+		reg = <0x0 0x00200000>;
+		label = "NAND U-Boot Image and env";
+		read-only;
+	};
+
+	partition@200000 {
+		/* 1MB for DTB Image */
+		reg = <0x00200000 0x00100000>;
+		label = "NAND DTB Image";
+	};
+
+	partition@300000 {
+		/* 5MB for Linux Kernel Image */
+		reg = <0x00300000 0x00500000>;
+		label = "NAND Linux Kernel Image";
+	};
+
+	partition@800000 {
+		/* 56MB for Compressed Root file System Image */
+		reg = <0x00800000 0x03800000>;
+		label = "NAND  ROOTFS";
+	};
+
+	partition@4000000 {
+		/* 1984MB for User Area */
+		reg = <0x04000000 0x7c000000>;
+		label = "NAND User area";
+	};
+};
+
 &phy0 {
 	interrupts = <0 1 0 0>;
 };
diff --git a/arch/powerpc/boot/dts/p1010rdb-pb_36b.dts b/arch/powerpc/boot/dts/p1010rdb-pb_36b.dts
index 7ab3c90..75d0c20 100644
--- a/arch/powerpc/boot/dts/p1010rdb-pb_36b.dts
+++ b/arch/powerpc/boot/dts/p1010rdb-pb_36b.dts
@@ -43,6 +43,40 @@
 
 /include/ "p1010rdb.dtsi"
 
+&ifc_nand {
+	partition@0 {
+		/* This location must not be altered  */
+		/* 2MB for u-boot Image and environment */
+		reg = <0x0 0x00200000>;
+		label = "NAND U-Boot Image and env";
+		read-only;
+	};
+
+	partition@200000 {
+		/* 1MB for DTB Image */
+		reg = <0x00200000 0x00100000>;
+		label = "NAND DTB Image";
+	};
+
+	partition@300000 {
+		/* 5MB for Linux Kernel Image */
+		reg = <0x00300000 0x00500000>;
+		label = "NAND Linux Kernel Image";
+	};
+
+	partition@800000 {
+		/* 56MB for Compressed Root file System Image */
+		reg = <0x00800000 0x03800000>;
+		label = "NAND  ROOTFS";
+	};
+
+	partition@4000000 {
+		/* 1984MB for User Area */
+		reg = <0x04000000 0x7c000000>;
+		label = "NAND User area";
+	};
+};
+
 &phy0 {
 	interrupts = <0 1 0 0>;
 };
diff --git a/arch/powerpc/boot/dts/p1010rdb.dtsi b/arch/powerpc/boot/dts/p1010rdb.dtsi
index 2433ae4..8b5fa3f 100644
--- a/arch/powerpc/boot/dts/p1010rdb.dtsi
+++ b/arch/powerpc/boot/dts/p1010rdb.dtsi
@@ -69,49 +69,11 @@
 		};
 	};
 
-	nand@1,0 {
+	ifc_nand: nand@1,0 {
 		#address-cells = <1>;
 		#size-cells = <1>;
 		compatible = "fsl,ifc-nand";
 		reg = <0x1 0x0 0x10000>;
-
-		partition@0 {
-			/* This location must not be altered  */
-			/* 1MB for u-boot Bootloader Image */
-			reg = <0x0 0x00100000>;
-			label = "NAND U-Boot Image";
-			read-only;
-		};
-
-		partition@100000 {
-			/* 1MB for DTB Image */
-			reg = <0x00100000 0x00100000>;
-			label = "NAND DTB Image";
-		};
-
-		partition@200000 {
-			/* 4MB for Linux Kernel Image */
-			reg = <0x00200000 0x00400000>;
-			label = "NAND Linux Kernel Image";
-		};
-
-		partition@600000 {
-			/* 4MB for Compressed Root file System Image */
-			reg = <0x00600000 0x00400000>;
-			label = "NAND Compressed RFS Image";
-		};
-
-		partition@a00000 {
-			/* 15MB for JFFS2 based Root file System */
-			reg = <0x00a00000 0x00f00000>;
-			label = "NAND JFFS2 Root File System";
-		};
-
-		partition@1900000 {
-			/* 7MB for User Area */
-			reg = <0x01900000 0x00700000>;
-			label = "NAND User area";
-		};
 	};
 
 	cpld@3,0 {
-- 
1.8.0

^ permalink raw reply related

* Re: [PATCH 1/2] tty/hvc_console: Add DTR/RTS callback to handle HUPCL control
From: Hendrik Brueckner @ 2013-10-17  8:16 UTC (permalink / raw)
  To: Benjamin Herrenschmidt
  Cc: linux-s390, brueckner, gregkh, heiko.carstens, linuxppc-dev,
	linux-kernel, Hendrik Brueckner, schwidefsky, jslaby
In-Reply-To: <1381965672.17841.71.camel@pasglop>

On Wed, Oct 16, 2013 at 06:21:12PM -0500, Benjamin Herrenschmidt wrote:
> On Wed, 2013-10-16 at 11:04 +0200, Hendrik Brueckner wrote:
> > Indeed, two callbacks change the DTR line.  The main difference is that
> > tiocmget/tiocmset can be called from user space by ioctl.  That's not the case
> > for the dtr_cts callback.  Also, tiocmget/tiocmset provide more flags that can
> > be changed (ST, SR, CTS, CD, RNG, RI,  ...)
> > 
> > Assume we would like to unify them have a single callback to change DTR, then
> > we have to take care of these differences.  So the question to you now is
> > whether you plan for a) other modem flags to be changed and b) if changing the
> > DTR line (or other control flags) through an ioctl?
> > 
> > Depending on your results, I could work on sth that helps us both and reduces
> > the callbacks.
> 
> Can we not just have the users of dtr_cts just call the backend's tiocmset ?

That's possible.  The only concern is that the tiocmset() callback could be
triggered from within the hvc_console() layer as well as from user space via
ioctl.  For the hvc_iucv driver, I do not want to introduce this ioctl.

One option would be to add parameter to the hvc_callbacks that indicate the
origin so that a backend could filter.

> If they need to filter or clamp bits, we could handle all that in hvc_console
> by caching the user intended value and passing a cooked value down to the backend..

Sure the hvc_console layer could do as much as possible.

> 
> None of that is urgent or anything, it's just odd and would be nice to cleanup.

Thanks and kind regards,
  Hendrik

^ permalink raw reply

* [PATCHv1 0/8] ALSA: Add SAI driver and enable SGT15000 codec.
From: Xiubo Li @ 2013-10-17  9:01 UTC (permalink / raw)
  To: r65073, timur, lgirdwood, broonie
  Cc: mark.rutland, alsa-devel, linux-doc, tiwai, b18965, perex, LW,
	linux, b42378, oskar, grant.likely, devicetree, ian.campbell,
	pawel.moll, swarren, rob.herring, linux-arm-kernel, fabio.estevam,
	linux-kernel, rob, r64188, shawn.guo, linuxppc-dev

This patch series is mostly Freescale's SAI SoC Digital Audio Interface driver implementation. And the implementation is only compatible with device tree definition.

This patch series is based on linux-next and has been tested on Vybrid VF610 Tower board using device tree.


Added in v1:
- Add SAI SoC Digital Audio Interface driver.
- Add Freescale SAI ALSA SoC Digital Audio Interface node for VF610.
- Enables SAI ALSA SoC DAI device for Vybrid VF610 TOWER board.
- Add device tree bindings for Freescale SAI.
- Revise the bugs about the sgt15000 codec.
- Add SGT15000 based audio machine driver.
- Enable SGT15000 codec based audio driver node for VF610.
- Add device tree bindings for Freescale VF610 sound.

^ permalink raw reply

* [PATCHv1 1/8] ALSA: Add SAI SoC Digital Audio Interface driver.
From: Xiubo Li @ 2013-10-17  9:01 UTC (permalink / raw)
  To: r65073, timur, lgirdwood, broonie
  Cc: mark.rutland, alsa-devel, linux-doc, tiwai, b18965, perex, LW,
	linux, b42378, oskar, grant.likely, devicetree, ian.campbell,
	pawel.moll, swarren, rob.herring, linux-arm-kernel, fabio.estevam,
	linux-kernel, rob, r64188, shawn.guo, linuxppc-dev
In-Reply-To: <1382000477-17304-1-git-send-email-Li.Xiubo@freescale.com>

This adds Freescale SAI ASoC Audio support.
This implementation is only compatible with device tree definition.
Features:
o Supports playback/capture
o Supports 16/20/24 bit PCM
o Supports 8k - 96k sample rates
o Supports slave mode only.

Signed-off-by: Alison Wang <b18965@freescale.com
Signed-off-by: Xiubo Li <Li.Xiubo@freescale.com>
---
 sound/soc/fsl/Kconfig       |  19 ++
 sound/soc/fsl/Makefile      |   7 +
 sound/soc/fsl/fsl-pcm-dma.c |  51 +++++
 sound/soc/fsl/fsl-sai.c     | 515 ++++++++++++++++++++++++++++++++++++++++++++
 sound/soc/fsl/fsl-sai.h     | 127 +++++++++++
 5 files changed, 719 insertions(+)
 create mode 100644 sound/soc/fsl/fsl-pcm-dma.c
 create mode 100644 sound/soc/fsl/fsl-sai.c
 create mode 100644 sound/soc/fsl/fsl-sai.h

diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig
index cd088cc..a49b386 100644
--- a/sound/soc/fsl/Kconfig
+++ b/sound/soc/fsl/Kconfig
@@ -202,3 +202,22 @@ config SND_SOC_IMX_MC13783
 	select SND_SOC_IMX_PCM_DMA
 
 endif # SND_IMX_SOC
+
+menuconfig SND_FSL_SOC
+	tristate "SoC Audio for Freescale FSL CPUs"
+	help
+	  Say Y or M if you want to add support for codecs attached to
+	  the FSL CPUs.
+
+	  This will enable Freeacale SAI, SGT15000 codec.
+
+if SND_FSL_SOC
+
+config SND_SOC_FSL_SAI
+	tristate
+
+config SND_SOC_FSL_PCM
+	tristate
+	select SND_SOC_GENERIC_DMAENGINE_PCM
+
+endif # SND_FSL_SOC
diff --git a/sound/soc/fsl/Makefile b/sound/soc/fsl/Makefile
index 4b5970e..865ac23 100644
--- a/sound/soc/fsl/Makefile
+++ b/sound/soc/fsl/Makefile
@@ -54,3 +54,10 @@ obj-$(CONFIG_SND_MXC_SOC_WM1133_EV1) += snd-soc-wm1133-ev1.o
 obj-$(CONFIG_SND_SOC_IMX_SGTL5000) += snd-soc-imx-sgtl5000.o
 obj-$(CONFIG_SND_SOC_IMX_WM8962) += snd-soc-imx-wm8962.o
 obj-$(CONFIG_SND_SOC_IMX_MC13783) += snd-soc-imx-mc13783.o
+
+# FSL ARM SAI/SGT15000 Platform Support
+snd-soc-fsl-sai-objs := fsl-sai.o
+snd-soc-fsl-pcm-objs := fsl-pcm-dma.o
+
+obj-$(CONFIG_SND_SOC_FSL_SAI) += snd-soc-fsl-sai.o
+obj-$(CONFIG_SND_SOC_FSL_PCM) += snd-soc-fsl-pcm.o
diff --git a/sound/soc/fsl/fsl-pcm-dma.c b/sound/soc/fsl/fsl-pcm-dma.c
new file mode 100644
index 0000000..c4d925e
--- /dev/null
+++ b/sound/soc/fsl/fsl-pcm-dma.c
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2012-2013 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ */
+
+#include <linux/dmaengine.h>
+#include <sound/dmaengine_pcm.h>
+#include "fsl-sai.h"
+
+static struct snd_pcm_hardware snd_fsl_hardware = {
+	.info = SNDRV_PCM_INFO_INTERLEAVED |
+		SNDRV_PCM_INFO_BLOCK_TRANSFER |
+		SNDRV_PCM_INFO_MMAP |
+		SNDRV_PCM_INFO_MMAP_VALID |
+		SNDRV_PCM_INFO_PAUSE |
+		SNDRV_PCM_INFO_RESUME,
+	.formats = SNDRV_PCM_FMTBIT_S16_LE,
+	.rate_min = 8000,
+	.channels_min = 2,
+	.channels_max = 2,
+	.buffer_bytes_max = FSL_SAI_DMABUF_SIZE,
+	.period_bytes_min = 4096,
+	.period_bytes_max = FSL_SAI_DMABUF_SIZE / TCD_NUMBER,
+	.periods_min = TCD_NUMBER,
+	.periods_max = TCD_NUMBER,
+	.fifo_size = 0,
+};
+
+static const struct snd_dmaengine_pcm_config fsl_dmaengine_pcm_config = {
+	.pcm_hardware = &snd_fsl_hardware,
+	.prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config,
+	.prealloc_buffer_size = FSL_SAI_DMABUF_SIZE,
+};
+
+int fsl_pcm_dma_init(struct platform_device *pdev)
+{
+	return snd_dmaengine_pcm_register(&pdev->dev, &fsl_dmaengine_pcm_config,
+			SND_DMAENGINE_PCM_FLAG_NO_RESIDUE);
+}
+EXPORT_SYMBOL_GPL(fsl_pcm_dma_init);
+
+void fsl_pcm_dma_exit(struct platform_device *pdev)
+{
+	snd_dmaengine_pcm_unregister(&pdev->dev);
+}
+EXPORT_SYMBOL_GPL(fsl_pcm_dma_exit);
diff --git a/sound/soc/fsl/fsl-sai.c b/sound/soc/fsl/fsl-sai.c
new file mode 100644
index 0000000..d4c8b44
--- /dev/null
+++ b/sound/soc/fsl/fsl-sai.c
@@ -0,0 +1,515 @@
+/*
+ * Freescale SAI ALSA SoC Digital Audio Interface driver.
+ *
+ * Copyright 2012-2013 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ */
+
+#include <linux/clk.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/of_address.h>
+#include <sound/core.h>
+#include <sound/pcm_params.h>
+#include <linux/delay.h>
+
+#include "fsl-sai.h"
+
+static int fsl_sai_set_dai_sysclk_tr(struct snd_soc_dai *cpu_dai,
+		int clk_id, unsigned int freq, int fsl_dir)
+{
+	u32 val_cr2, reg_cr2;
+	struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
+
+	if (fsl_dir == FSL_FMT_TRANSMITTER)
+		reg_cr2 = SAI_TCR2;
+	else
+		reg_cr2 = SAI_RCR2;
+
+	val_cr2 = readl(sai->base + reg_cr2);
+	switch (clk_id) {
+	case FSL_SAI_CLK_BUS:
+		val_cr2 &= ~SAI_CR2_MSEL_MASK;
+		val_cr2 |= SAI_CR2_MSEL_BUS;
+		break;
+	case FSL_SAI_CLK_MAST1:
+		val_cr2 &= ~SAI_CR2_MSEL_MASK;
+		val_cr2 |= SAI_CR2_MSEL_MCLK1;
+		break;
+	case FSL_SAI_CLK_MAST2:
+		val_cr2 &= ~SAI_CR2_MSEL_MASK;
+		val_cr2 |= SAI_CR2_MSEL_MCLK2;
+		break;
+	case FSL_SAI_CLK_MAST3:
+		val_cr2 &= ~SAI_CR2_MSEL_MASK;
+		val_cr2 |= SAI_CR2_MSEL_MCLK3;
+		break;
+	default:
+		return -EINVAL;
+	}
+	writel(val_cr2, sai->base + reg_cr2);
+
+	return 0;
+}
+
+static int fsl_sai_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
+		int clk_id, unsigned int freq, int dir)
+{
+	int ret;
+
+	if (dir == SND_SOC_CLOCK_IN)
+		return 0;
+
+	ret = fsl_sai_set_dai_sysclk_tr(cpu_dai, clk_id, freq,
+					FSL_FMT_TRANSMITTER);
+	if (ret) {
+		dev_err(cpu_dai->dev,
+				"Cannot set sai's transmitter sysclk: %d\n",
+				ret);
+		return ret;
+	}
+
+	ret = fsl_sai_set_dai_sysclk_tr(cpu_dai, clk_id, freq,
+					FSL_FMT_RECEIVER);
+	if (ret) {
+		dev_err(cpu_dai->dev,
+				"Cannot set sai's receiver sysclk: %d\n",
+				ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int fsl_sai_set_dai_clkdiv(struct snd_soc_dai *cpu_dai,
+		int div_id, int div)
+{
+	struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
+	u32 tcr2, rcr2;
+
+	if (div_id == FSL_SAI_TX_DIV) {
+		tcr2 = readl(sai->base + SAI_TCR2);
+		tcr2 &= ~SAI_CR2_DIV_MASK;
+		tcr2 |= SAI_CR2_DIV(div);
+		writel(tcr2, sai->base + SAI_TCR2);
+
+	} else if (div_id == FSL_SAI_RX_DIV) {
+		rcr2 = readl(sai->base + SAI_RCR2);
+		rcr2 &= ~SAI_CR2_DIV_MASK;
+		rcr2 |= SAI_CR2_DIV(div);
+		writel(rcr2, sai->base + SAI_RCR2);
+
+	} else
+		return -EINVAL;
+
+	return 0;
+}
+
+static int fsl_sai_set_dai_fmt_tr(struct snd_soc_dai *cpu_dai,
+				unsigned int fmt, int fsl_dir)
+{
+	u32 val_cr2, val_cr3, val_cr4, reg_cr2, reg_cr3, reg_cr4;
+	struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
+
+	if (fsl_dir == FSL_FMT_TRANSMITTER) {
+		reg_cr2 = SAI_TCR2;
+		reg_cr3 = SAI_TCR3;
+		reg_cr4 = SAI_TCR4;
+	} else {
+		reg_cr2 = SAI_RCR2;
+		reg_cr3 = SAI_RCR3;
+		reg_cr4 = SAI_RCR4;
+	}
+
+	val_cr2 = readl(sai->base + reg_cr2);
+	val_cr3 = readl(sai->base + reg_cr3);
+	val_cr4 = readl(sai->base + reg_cr4);
+
+	if (sai->fbt == FSL_SAI_FBT_MSB)
+		val_cr4 |= SAI_CR4_MF;
+	else if (sai->fbt == FSL_SAI_FBT_LSB)
+		val_cr4 &= ~SAI_CR4_MF;
+
+	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+	case SND_SOC_DAIFMT_I2S:
+		val_cr4 |= SAI_CR4_FSE;
+		val_cr4 |= SAI_CR4_FSP;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+	case SND_SOC_DAIFMT_IB_IF:
+		val_cr4 |= SAI_CR4_FSP;
+		val_cr2 &= ~SAI_CR2_BCP;
+		break;
+	case SND_SOC_DAIFMT_IB_NF:
+		val_cr4 &= ~SAI_CR4_FSP;
+		val_cr2 &= ~SAI_CR2_BCP;
+		break;
+	case SND_SOC_DAIFMT_NB_IF:
+		val_cr4 |= SAI_CR4_FSP;
+		val_cr2 |= SAI_CR2_BCP;
+		break;
+	case SND_SOC_DAIFMT_NB_NF:
+		val_cr4 &= ~SAI_CR4_FSP;
+		val_cr2 |= SAI_CR2_BCP;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+	case SND_SOC_DAIFMT_CBS_CFS:
+		val_cr2 |= SAI_CR2_BCD_MSTR;
+		val_cr4 |= SAI_CR4_FSD_MSTR;
+		break;
+	case SND_SOC_DAIFMT_CBM_CFM:
+		val_cr2 &= ~SAI_CR2_BCD_MSTR;
+		val_cr4 &= ~SAI_CR4_FSD_MSTR;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	val_cr3 |= SAI_CR3_TRCE;
+
+	if (fsl_dir == FSL_FMT_RECEIVER)
+		val_cr2 |= SAI_CR2_SYNC;
+
+	writel(val_cr2, sai->base + reg_cr2);
+	writel(val_cr3, sai->base + reg_cr3);
+	writel(val_cr4, sai->base + reg_cr4);
+
+	return 0;
+
+}
+
+static int fsl_sai_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
+{
+	int ret;
+
+	ret = fsl_sai_set_dai_fmt_tr(cpu_dai, fmt, FSL_FMT_TRANSMITTER);
+	if (ret) {
+		dev_err(cpu_dai->dev,
+				"Cannot set sai's transmitter format: %d\n",
+				ret);
+		return ret;
+	}
+
+	ret = fsl_sai_set_dai_fmt_tr(cpu_dai, fmt, FSL_FMT_RECEIVER);
+	if (ret) {
+		dev_err(cpu_dai->dev,
+				"Cannot set sai's receiver format: %d\n",
+				ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int fsl_sai_set_dai_tdm_slot(struct snd_soc_dai *cpu_dai,
+		unsigned int tx_mask, unsigned int rx_mask,
+		int slots, int slot_width)
+{
+	struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
+	u32 tcr4, rcr4;
+
+	tcr4 = readl(sai->base + SAI_TCR4);
+	tcr4 &= ~SAI_CR4_FRSZ_MASK;
+	tcr4 |= SAI_CR4_FRSZ(2);
+	writel(tcr4, sai->base + SAI_TCR4);
+	writel(tx_mask, sai->base + SAI_TMR);
+
+	rcr4 = readl(sai->base + SAI_RCR4);
+	rcr4 &= ~SAI_CR4_FRSZ_MASK;
+	rcr4 |= SAI_CR4_FRSZ(2);
+	writel(rcr4, sai->base + SAI_RCR4);
+	writel(rx_mask, sai->base + SAI_RMR);
+
+	return 0;
+}
+
+static int fsl_sai_hw_params_tr(struct snd_pcm_substream *substream,
+		struct snd_pcm_hw_params *params,
+		struct snd_soc_dai *cpu_dai, int fsl_dir)
+{
+	u32 val_cr4, val_cr5, reg_cr4, reg_cr5, word_width;
+	struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
+
+	if (fsl_dir == FSL_FMT_TRANSMITTER) {
+		reg_cr4 = SAI_TCR4;
+		reg_cr5 = SAI_TCR5;
+	} else {
+		reg_cr4 = SAI_RCR4;
+		reg_cr5 = SAI_RCR5;
+	}
+
+	val_cr4 = readl(sai->base + reg_cr4);
+	val_cr4 &= ~SAI_CR4_SYWD_MASK;
+
+	val_cr5 = readl(sai->base + reg_cr5);
+	val_cr5 &= ~SAI_CR5_WNW_MASK;
+	val_cr5 &= ~SAI_CR5_W0W_MASK;
+	val_cr5 &= ~SAI_CR5_FBT_MASK;
+
+	switch (params_format(params)) {
+	case SNDRV_PCM_FORMAT_S16_LE:
+		word_width = 16;
+		break;
+	case SNDRV_PCM_FORMAT_S20_3LE:
+		word_width = 20;
+		break;
+	case SNDRV_PCM_FORMAT_S24_LE:
+		word_width = 24;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	val_cr4 |= SAI_CR4_SYWD(word_width);
+	val_cr5 |= SAI_CR5_WNW(word_width);
+	val_cr5 |= SAI_CR5_W0W(word_width);
+
+	if (sai->fbt == FSL_SAI_FBT_MSB)
+		val_cr5 |= SAI_CR5_FBT(word_width - 1);
+	else if (sai->fbt == FSL_SAI_FBT_LSB)
+		val_cr5 |= SAI_CR5_FBT(0);
+
+	writel(val_cr4, sai->base + reg_cr4);
+	writel(val_cr5, sai->base + reg_cr5);
+
+	return 0;
+
+}
+
+static int fsl_sai_hw_params(struct snd_pcm_substream *substream,
+		struct snd_pcm_hw_params *params,
+		struct snd_soc_dai *cpu_dai)
+{
+	int ret;
+
+	ret = fsl_sai_hw_params_tr(substream, params, cpu_dai,
+				FSL_FMT_TRANSMITTER);
+	if (ret) {
+		dev_err(cpu_dai->dev,
+				"Cannot set sai transmitter hw params: %d\n",
+				ret);
+		return ret;
+	}
+
+	ret = fsl_sai_hw_params_tr(substream, params, cpu_dai,
+				FSL_FMT_RECEIVER);
+	if (ret) {
+		dev_err(cpu_dai->dev,
+				"Cannot set sai's receiver hw params: %d\n",
+				ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int fsl_sai_trigger(struct snd_pcm_substream *substream, int cmd,
+		struct snd_soc_dai *dai)
+{
+	struct fsl_sai *sai = snd_soc_dai_get_drvdata(dai);
+	unsigned int tcsr, rcsr;
+
+	tcsr = readl(sai->base + SAI_TCSR);
+	rcsr = readl(sai->base + SAI_RCSR);
+
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+	case SNDRV_PCM_TRIGGER_RESUME:
+	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+		rcsr |= SAI_CSR_TERE | SAI_CSR_FRDE;
+		tcsr |= SAI_CSR_TERE | SAI_CSR_FRDE;
+		writel(rcsr, sai->base + SAI_RCSR);
+		udelay(10);
+		writel(tcsr, sai->base + SAI_TCSR);
+		break;
+
+	case SNDRV_PCM_TRIGGER_STOP:
+	case SNDRV_PCM_TRIGGER_SUSPEND:
+	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+		tcsr &= ~(SAI_CSR_TERE | SAI_CSR_FRDE);
+		rcsr &= ~(SAI_CSR_TERE | SAI_CSR_FRDE);
+		writel(tcsr, sai->base + SAI_TCSR);
+		udelay(10);
+		writel(rcsr, sai->base + SAI_RCSR);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static struct snd_soc_dai_ops fsl_sai_pcm_dai_ops = {
+	.set_sysclk	= fsl_sai_set_dai_sysclk,
+	.set_clkdiv	= fsl_sai_set_dai_clkdiv,
+	.set_fmt	= fsl_sai_set_dai_fmt,
+	.set_tdm_slot	= fsl_sai_set_dai_tdm_slot,
+	.hw_params	= fsl_sai_hw_params,
+	.trigger	= fsl_sai_trigger,
+};
+
+static int fsl_sai_dai_probe(struct snd_soc_dai *dai)
+{
+	int ret;
+	struct fsl_sai *sai = dev_get_drvdata(dai->dev);
+
+	ret = clk_prepare_enable(sai->clk);
+	if (ret)
+		return ret;
+
+	writel(0x0, sai->base + SAI_RCSR);
+	writel(0x0, sai->base + SAI_TCSR);
+	writel(sai->dma_params_tx.maxburst, sai->base + SAI_TCR1);
+	writel(sai->dma_params_rx.maxburst, sai->base + SAI_RCR1);
+
+	dai->playback_dma_data = &sai->dma_params_tx;
+	dai->capture_dma_data = &sai->dma_params_rx;
+
+	snd_soc_dai_set_drvdata(dai, sai);
+
+	return 0;
+}
+
+int fsl_sai_dai_remove(struct snd_soc_dai *dai)
+{
+	struct fsl_sai *sai = dev_get_drvdata(dai->dev);
+
+	clk_disable_unprepare(sai->clk);
+
+	return 0;
+}
+
+static struct snd_soc_dai_driver fsl_sai_dai = {
+	.probe = fsl_sai_dai_probe,
+	.remove = fsl_sai_dai_remove,
+	.playback = {
+		.channels_min = 1,
+		.channels_max = 2,
+		.rates = SNDRV_PCM_RATE_8000_96000,
+		.formats = FSL_SAI_FORMATS,
+	},
+	.capture = {
+		.channels_min = 1,
+		.channels_max = 2,
+		.rates = SNDRV_PCM_RATE_8000_96000,
+		.formats = FSL_SAI_FORMATS,
+	},
+	.ops = &fsl_sai_pcm_dai_ops,
+};
+
+static const struct snd_soc_component_driver fsl_component = {
+	.name           = "fsl-sai",
+};
+
+static int fsl_sai_probe(struct platform_device *pdev)
+{
+	struct of_phandle_args	dma_args;
+	int index;
+	struct resource *res;
+	struct fsl_sai *sai;
+	int ret = 0;
+	struct device_node *np = pdev->dev.of_node;
+
+	sai = devm_kzalloc(&pdev->dev, sizeof(*sai), GFP_KERNEL);
+	if (!sai)
+		return -ENOMEM;
+
+	sai->fbt = FSL_SAI_FBT_MSB;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	sai->base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(sai->base)) {
+		ret = PTR_ERR(sai->base);
+		return ret;
+	}
+
+	sai->clk = devm_clk_get(&pdev->dev, "sai");
+	if (IS_ERR(sai->clk)) {
+		ret = PTR_ERR(sai->clk);
+		dev_err(&pdev->dev, "Cannot get sai's clock: %d\n", ret);
+		return ret;
+	}
+
+	sai->dma_params_rx.addr = res->start + SAI_RDR;
+	sai->dma_params_rx.maxburst = 6;
+	index = of_property_match_string(np, "dma-names", "rx");
+	ret = of_parse_phandle_with_args(np, "dmas", "#dma-cells", index,
+				&dma_args);
+	if (ret)
+		return ret;
+	sai->dma_params_rx.slave_id = dma_args.args[1];
+
+	sai->dma_params_tx.addr = res->start + SAI_TDR;
+	sai->dma_params_tx.maxburst = 6;
+	index = of_property_match_string(np, "dma-names", "tx");
+	ret = of_parse_phandle_with_args(np, "dmas", "#dma-cells", index,
+				&dma_args);
+	if (ret)
+		return ret;
+	sai->dma_params_tx.slave_id = dma_args.args[1];
+
+	ret = snd_soc_register_component(&pdev->dev, &fsl_component,
+			&fsl_sai_dai, 1);
+	if (ret)
+		return ret;
+
+	ret = fsl_pcm_dma_init(pdev);
+	if (ret)
+		goto out;
+
+	platform_set_drvdata(pdev, sai);
+
+	return 0;
+
+out:
+	snd_soc_unregister_component(&pdev->dev);
+	return ret;
+}
+
+static int fsl_sai_remove(struct platform_device *pdev)
+{
+	struct fsl_sai *sai = platform_get_drvdata(pdev);
+
+	fsl_pcm_dma_exit(pdev);
+
+	snd_soc_unregister_component(&pdev->dev);
+
+	clk_disable_unprepare(sai->clk);
+
+	return 0;
+}
+
+static const struct of_device_id fsl_sai_ids[] = {
+	{ .compatible = "fsl,vf610-sai", },
+	{ /*sentinel*/ },
+};
+
+static struct platform_driver fsl_sai_driver = {
+	.probe = fsl_sai_probe,
+	.remove = fsl_sai_remove,
+
+	.driver = {
+		.name = "fsl-sai",
+		.owner = THIS_MODULE,
+		.of_match_table = fsl_sai_ids,
+	},
+};
+module_platform_driver(fsl_sai_driver);
+
+MODULE_AUTHOR("Xiubo Li, <Li.Xiubo@freescale.com>");
+MODULE_AUTHOR("Alison Wang, <b18965@freescale.com>");
+MODULE_DESCRIPTION("Freescale Soc SAI Interface");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/fsl/fsl-sai.h b/sound/soc/fsl/fsl-sai.h
new file mode 100644
index 0000000..ab76a8e
--- /dev/null
+++ b/sound/soc/fsl/fsl-sai.h
@@ -0,0 +1,127 @@
+/*
+ * Copyright 2012-2013 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __FSL_SAI_H
+#define __FSL_SAI_H
+
+#include <sound/dmaengine_pcm.h>
+
+#define FSL_SAI_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
+			 SNDRV_PCM_FMTBIT_S20_3LE |\
+			 SNDRV_PCM_FMTBIT_S24_LE)
+
+#define FSL_SAI_DMABUF_SIZE	(32 * 1024)
+#define TCD_NUMBER		4
+#define EDMA_PRIO_HIGH          6
+
+/* SAI Transmit/Recieve Control Register */
+#define SAI_TCSR		0x00
+#define SAI_RCSR		0x80
+#define SAI_CSR_TERE		BIT(31)
+#define SAI_CSR_FWF		BIT(17)
+#define SAI_CSR_FRIE		BIT(8)
+#define SAI_CSR_FRDE		BIT(0)
+
+/* SAI Transmit Data/FIFO/MASK Register */
+#define SAI_TDR			0x20
+#define SAI_TFR			0x40
+#define SAI_TMR			0x60
+
+/* SAI Recieve Data/FIFO/MASK Register */
+#define SAI_RDR			0xa0
+#define SAI_RFR			0xc0
+#define SAI_RMR			0xe0
+
+/* SAI Transmit and Recieve Configuration 1 Register */
+#define SAI_TCR1		0x04
+#define SAI_RCR1		0x84
+
+/* SAI Transmit and Recieve Configuration 2 Register */
+#define SAI_TCR2		0x08
+#define SAI_RCR2		0x88
+#define SAI_CR2_SYNC		BIT(30)
+#define SAI_CR2_MSEL_MASK	(0xff << 26)
+#define SAI_CR2_MSEL_BUS	0
+#define SAI_CR2_MSEL_MCLK1	BIT(26)
+#define SAI_CR2_MSEL_MCLK2	BIT(27)
+#define SAI_CR2_MSEL_MCLK3	(BIT(26)|BIT(27))
+#define SAI_CR2_BCP		BIT(25)
+#define SAI_CR2_BCD_MSTR	BIT(24)
+#define SAI_CR2_DIV(x)		(x)
+#define SAI_CR2_DIV_MASK	0xff
+
+/* SAI Transmit and Recieve Configuration 3 Register */
+#define SAI_TCR3		0x0c
+#define SAI_RCR3		0x8c
+#define SAI_CR3_TRCE		BIT(16)
+#define SAI_CR3_WDFL(x)		(x)
+#define SAI_CR3_WDFL_MASK	0x1f
+
+/* SAI Transmit and Recieve Configuration 4 Register */
+#define SAI_TCR4		0x10
+#define SAI_RCR4		0x90
+#define SAI_CR4_FRSZ(x)		(((x) - 1) << 16)
+#define SAI_CR4_FRSZ_MASK	(0x1f << 16)
+#define SAI_CR4_SYWD(x)		(((x) - 1) << 8)
+#define SAI_CR4_SYWD_MASK	(0x1f << 8)
+#define SAI_CR4_MF		BIT(4)
+#define SAI_CR4_FSE		BIT(3)
+#define SAI_CR4_FSP		BIT(1)
+#define SAI_CR4_FSD_MSTR	BIT(0)
+
+/* SAI Transmit and Recieve Configuration 5 Register */
+#define SAI_TCR5		0x14
+#define SAI_RCR5		0x94
+#define SAI_CR5_WNW(x)		(((x) - 1) << 24)
+#define SAI_CR5_WNW_MASK	(0x1f << 24)
+#define SAI_CR5_W0W(x)		(((x) - 1) << 16)
+#define SAI_CR5_W0W_MASK	(0x1f << 16)
+#define SAI_CR5_FBT(x)		((x) << 8)
+#define SAI_CR5_FBT_MASK	(0x1f << 8)
+
+/* SAI audio dividers */
+#define FSL_SAI_TX_DIV		0
+#define FSL_SAI_RX_DIV		1
+
+/* SAI type */
+#define FSL_SAI_DMA		BIT(0)
+#define FSL_SAI_USE_AC97	BIT(1)
+#define FSL_SAI_NET		BIT(2)
+#define FSL_SAI_TRA_SYN		BIT(3)
+#define FSL_SAI_REC_SYN		BIT(4)
+#define FSL_SAI_USE_I2S_SLAVE	BIT(5)
+
+#define FSL_FMT_TRANSMITTER	0
+#define FSL_FMT_RECEIVER	1
+
+/* SAI clock sources */
+#define FSL_SAI_CLK_BUS		0
+#define FSL_SAI_CLK_MAST1	1
+#define FSL_SAI_CLK_MAST2	2
+#define FSL_SAI_CLK_MAST3	3
+
+enum fsl_sai_fbt {
+	FSL_SAI_FBT_MSB,
+	FSL_SAI_FBT_LSB,
+};
+
+struct fsl_sai {
+	struct clk *clk;
+
+	void __iomem *base;
+
+	enum fsl_sai_fbt fbt;
+
+	struct snd_dmaengine_dai_dma_data dma_params_rx;
+	struct snd_dmaengine_dai_dma_data dma_params_tx;
+};
+
+int fsl_pcm_dma_init(struct platform_device *pdev);
+void fsl_pcm_dma_exit(struct platform_device *pdev);
+
+#endif /* __FSL_SAI_H */
-- 
1.8.0

^ permalink raw reply related

* [PATCHv1 2/8] ARM: dts: Add Freescale SAI ALSA SoC Digital Audio Interface node for VF610.
From: Xiubo Li @ 2013-10-17  9:01 UTC (permalink / raw)
  To: r65073, timur, lgirdwood, broonie
  Cc: mark.rutland, alsa-devel, linux-doc, tiwai, b18965, perex, LW,
	linux, b42378, oskar, grant.likely, devicetree, ian.campbell,
	pawel.moll, swarren, rob.herring, Jingchang Lu, linux-arm-kernel,
	fabio.estevam, linux-kernel, rob, r64188, shawn.guo, linuxppc-dev
In-Reply-To: <1382000477-17304-1-git-send-email-Li.Xiubo@freescale.com>

This patch add the SAI's edma mux Tx and Rx support.

Signed-off-by: Jingchang Lu <b35083@freescale.com>
Signed-off-by: Xiubo Li <Li.Xiubo@freescale.com>
---
 arch/arm/boot/dts/vf610.dtsi | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/vf610.dtsi b/arch/arm/boot/dts/vf610.dtsi
index 18e3a4c..391f180 100644
--- a/arch/arm/boot/dts/vf610.dtsi
+++ b/arch/arm/boot/dts/vf610.dtsi
@@ -151,9 +151,11 @@
 			sai2: sai@40031000 {
 				compatible = "fsl,vf610-sai";
 				reg = <0x40031000 0x1000>;
-				interrupts = <0 86 0x04>;
 				clocks = <&clks VF610_CLK_SAI2>;
 				clock-names = "sai";
+				dma-names = "tx", "rx";
+				dmas = <&edma0 0 VF610_EDMA_MUXID0_SAI2_TX>,
+					<&edma0 0 VF610_EDMA_MUXID0_SAI2_RX>;
 				status = "disabled";
 			};
 
-- 
1.8.0

^ permalink raw reply related

* [PATCHv1 3/8] ARM: dts: Enables SAI ALSA SoC DAI device for Vybrid VF610 TOWER board.
From: Xiubo Li @ 2013-10-17  9:01 UTC (permalink / raw)
  To: r65073, timur, lgirdwood, broonie
  Cc: mark.rutland, alsa-devel, linux-doc, tiwai, b18965, perex, LW,
	linux, b42378, oskar, grant.likely, devicetree, ian.campbell,
	pawel.moll, swarren, rob.herring, linux-arm-kernel, fabio.estevam,
	linux-kernel, rob, r64188, shawn.guo, linuxppc-dev
In-Reply-To: <1382000477-17304-1-git-send-email-Li.Xiubo@freescale.com>

This patch add and enable SAI device.

Signed-off-by: Xiubo Li <Li.Xiubo@freescale.com>
---
 arch/arm/boot/dts/vf610-twr.dts | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/arch/arm/boot/dts/vf610-twr.dts b/arch/arm/boot/dts/vf610-twr.dts
index 1a58678..e4106dd 100644
--- a/arch/arm/boot/dts/vf610-twr.dts
+++ b/arch/arm/boot/dts/vf610-twr.dts
@@ -57,6 +57,12 @@
 	status = "okay";
 };
 
+&sai2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_sai2_1>;
+	status = "okay";
+};
+
 &uart1 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_uart1_1>;
-- 
1.8.0

^ permalink raw reply related

* [PATCHv1 4/8] Documentation: Add device tree bindings for Freescale SAI.
From: Xiubo Li @ 2013-10-17  9:01 UTC (permalink / raw)
  To: r65073, timur, lgirdwood, broonie
  Cc: mark.rutland, alsa-devel, linux-doc, tiwai, b18965, perex, LW,
	linux, b42378, oskar, grant.likely, devicetree, ian.campbell,
	pawel.moll, swarren, rob.herring, linux-arm-kernel, fabio.estevam,
	linux-kernel, rob, r64188, shawn.guo, linuxppc-dev
In-Reply-To: <1382000477-17304-1-git-send-email-Li.Xiubo@freescale.com>

This adds the Document for Freescale SAI driver under
Documentation/devicetree/bindings/sound/.

Signed-off-by: Xiubo Li <Li.Xiubo@freescale.com>
---
 .../devicetree/bindings/sound/fsl-sai.txt          | 32 ++++++++++++++++++++++
 1 file changed, 32 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/sound/fsl-sai.txt

diff --git a/Documentation/devicetree/bindings/sound/fsl-sai.txt b/Documentation/devicetree/bindings/sound/fsl-sai.txt
new file mode 100644
index 0000000..267afbd
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/fsl-sai.txt
@@ -0,0 +1,32 @@
+Freescale Synchronous Audio Interface (SAI).
+
+The SAI is based on I2S module that used communicating with audio codecs,
+which provides a synchronous audio interface that supports fullduplex
+serial interfaces with frame synchronization such as I2S, AC97, TDM, and
+codec/DSP interfaces.
+
+
+Required properties:
+- compatible: Compatible list, contains "fsl,vf610-sai".
+- reg: Offset and length of the register set for the device.
+- clocks: Must contain an entry for each entry in clock-names.
+- clock-names : Must include the "sai" entry.
+- dmas : Generic dma devicetree binding as described in
+  Documentation/devicetree/bindings/dma/dma.txt.
+- dma-names : Two dmas have to be defined, "tx" and "rx".
+- pinctrl-names: Must contain a "default" entry.
+- pinctrl-NNN: One property must exist for each entry in pinctrl-names.
+  See ../pinctrl/pinctrl-bindings.txt for details of the property values.
+
+Example:
+sai2: sai@40031000 {
+	      compatible = "fsl,vf610-sai";
+	      reg = <0x40031000 0x1000>;
+	      pinctrl-names = "default";
+	      pinctrl-0 = <&pinctrl_sai2_1>;
+	      clocks = <&clks VF610_CLK_SAI2>;
+	      clock-names = "sai";
+	      dma-names = "tx", "rx";
+	      dmas = <&edma0 0 VF610_EDMA_MUXID0_SAI2_TX>,
+		   <&edma0 0 VF610_EDMA_MUXID0_SAI2_RX>;
+};
-- 
1.8.0

^ permalink raw reply related

* [PATCHv1 5/8] ASoC: sgtl5000: Revise the bugs about the sgt15000 codec.
From: Xiubo Li @ 2013-10-17  9:01 UTC (permalink / raw)
  To: r65073, timur, lgirdwood, broonie
  Cc: mark.rutland, alsa-devel, linux-doc, tiwai, b18965, perex, LW,
	linux, b42378, oskar, grant.likely, devicetree, ian.campbell,
	pawel.moll, swarren, rob.herring, linux-arm-kernel, fabio.estevam,
	linux-kernel, rob, r64188, shawn.guo, linuxppc-dev
In-Reply-To: <1382000477-17304-1-git-send-email-Li.Xiubo@freescale.com>

When the CONFIG_REGULATOR is disabled there will be some warnings
printed out.

Signed-off-by: Xiubo Li <Li.Xiubo@freescale.com>
---
 sound/soc/codecs/sgtl5000.c | 13 ++++++++++++-
 1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c
index 1f4093f..4e2e4c9 100644
--- a/sound/soc/codecs/sgtl5000.c
+++ b/sound/soc/codecs/sgtl5000.c
@@ -883,14 +883,19 @@ static int ldo_regulator_register(struct snd_soc_codec *codec,
 				struct regulator_init_data *init_data,
 				int voltage)
 {
+#ifdef CONFIG_SND_SOC_FSL_SGTL5000
+	return 0;
+#else
 	dev_err(codec->dev, "this setup needs regulator support in the kernel\n");
 	return -EINVAL;
+#endif
 }
 
 static int ldo_regulator_remove(struct snd_soc_codec *codec)
 {
 	return 0;
 }
+
 #endif
 
 /*
@@ -1137,6 +1142,7 @@ static int sgtl5000_resume(struct snd_soc_codec *codec)
 #define sgtl5000_resume  NULL
 #endif	/* CONFIG_SUSPEND */
 
+#ifdef CONFIG_REGULATOR
 /*
  * sgtl5000 has 3 internal power supplies:
  * 1. VAG, normally set to vdda/2
@@ -1269,6 +1275,7 @@ static int sgtl5000_set_power_regs(struct snd_soc_codec *codec)
 
 	return 0;
 }
+#endif
 
 static int sgtl5000_replace_vddd_with_ldo(struct snd_soc_codec *codec)
 {
@@ -1370,6 +1377,7 @@ err_regulator_free:
 				sgtl5000->supplies);
 	if (external_vddd)
 		ldo_regulator_remove(codec);
+
 	return ret;
 
 }
@@ -1391,11 +1399,12 @@ static int sgtl5000_probe(struct snd_soc_codec *codec)
 	if (ret)
 		return ret;
 
+#ifdef CONFIG_REGULATOR
 	/* power up sgtl5000 */
 	ret = sgtl5000_set_power_regs(codec);
 	if (ret)
 		goto err;
-
+#endif
 	/* enable small pop, introduce 400ms delay in turning off */
 	snd_soc_update_bits(codec, SGTL5000_CHIP_REF_CTRL,
 				SGTL5000_SMALL_POP,
@@ -1446,6 +1455,7 @@ err:
 						sgtl5000->supplies);
 	regulator_bulk_free(ARRAY_SIZE(sgtl5000->supplies),
 				sgtl5000->supplies);
+
 	ldo_regulator_remove(codec);
 
 	return ret;
@@ -1461,6 +1471,7 @@ static int sgtl5000_remove(struct snd_soc_codec *codec)
 						sgtl5000->supplies);
 	regulator_bulk_free(ARRAY_SIZE(sgtl5000->supplies),
 				sgtl5000->supplies);
+
 	ldo_regulator_remove(codec);
 
 	return 0;
-- 
1.8.0

^ permalink raw reply related

* [PATCHv1 6/8] ASoC: fsl: add SGT15000 based audio machine driver.
From: Xiubo Li @ 2013-10-17  9:01 UTC (permalink / raw)
  To: r65073, timur, lgirdwood, broonie
  Cc: mark.rutland, alsa-devel, linux-doc, tiwai, b18965, perex, LW,
	linux, b42378, oskar, grant.likely, devicetree, ian.campbell,
	pawel.moll, swarren, rob.herring, linux-arm-kernel, fabio.estevam,
	linux-kernel, rob, r64188, shawn.guo, linuxppc-dev
In-Reply-To: <1382000477-17304-1-git-send-email-Li.Xiubo@freescale.com>

This is the SGTl5000 codec based audio driver supported with both
playback and capture dai link implemention.

This implementation is only compatible with device tree definition.

Signed-off-by: Alison Wang <b18965@freescale.com
Signed-off-by: Xiubo Li <Li.Xiubo@freescale.com>
---
 sound/soc/fsl/Kconfig        |  10 +++
 sound/soc/fsl/Makefile       |   2 +
 sound/soc/fsl/fsl-sgtl5000.c | 208 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 220 insertions(+)
 create mode 100644 sound/soc/fsl/fsl-sgtl5000.c

diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig
index a49b386..3fbbbf2 100644
--- a/sound/soc/fsl/Kconfig
+++ b/sound/soc/fsl/Kconfig
@@ -220,4 +220,14 @@ config SND_SOC_FSL_PCM
 	tristate
 	select SND_SOC_GENERIC_DMAENGINE_PCM
 
+config SND_SOC_FSL_SGTL5000
+	tristate "SoC Audio support for FSL boards with sgtl5000"
+	depends on OF && I2C
+	select SND_SOC_FSL_SAI
+	select SND_SOC_FSL_PCM
+	select SND_SOC_SGTL5000
+	help
+	  Say Y if you want to add support for SoC audio on an FSL board with
+	  a sgtl5000 codec.
+
 endif # SND_FSL_SOC
diff --git a/sound/soc/fsl/Makefile b/sound/soc/fsl/Makefile
index 865ac23..e8bf0bd 100644
--- a/sound/soc/fsl/Makefile
+++ b/sound/soc/fsl/Makefile
@@ -58,6 +58,8 @@ obj-$(CONFIG_SND_SOC_IMX_MC13783) += snd-soc-imx-mc13783.o
 # FSL ARM SAI/SGT15000 Platform Support
 snd-soc-fsl-sai-objs := fsl-sai.o
 snd-soc-fsl-pcm-objs := fsl-pcm-dma.o
+snd-soc-fsl-sgtl5000-objs := fsl-sgtl5000.o
 
 obj-$(CONFIG_SND_SOC_FSL_SAI) += snd-soc-fsl-sai.o
 obj-$(CONFIG_SND_SOC_FSL_PCM) += snd-soc-fsl-pcm.o
+obj-$(CONFIG_SND_SOC_FSL_SGTL5000) += snd-soc-fsl-sgtl5000.o
diff --git a/sound/soc/fsl/fsl-sgtl5000.c b/sound/soc/fsl/fsl-sgtl5000.c
new file mode 100644
index 0000000..bab85ec
--- /dev/null
+++ b/sound/soc/fsl/fsl-sgtl5000.c
@@ -0,0 +1,208 @@
+/*
+ * Freeacale ALSA SoC Audio using SGT1500 as codec.
+ *
+ * Copyright 2012-2013 Freescale Semiconductor, Inc.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/i2c.h>
+#include <linux/clk.h>
+
+#include "../codecs/sgtl5000.h"
+#include "fsl-sai.h"
+
+static unsigned int sysclk_rate;
+
+static int fsl_sgtl5000_dai_init(struct snd_soc_pcm_runtime *rtd)
+{
+	int ret;
+	struct device *dev = rtd->card->dev;
+
+	ret = snd_soc_dai_set_sysclk(rtd->codec_dai, SGTL5000_SYSCLK,
+				     sysclk_rate, SND_SOC_CLOCK_IN);
+	if (ret) {
+		dev_err(dev, "could not set codec driver clock params :%d\n",
+				ret);
+		return ret;
+	}
+
+	ret = snd_soc_dai_set_sysclk(rtd->cpu_dai, FSL_SAI_CLK_BUS,
+				     sysclk_rate, SND_SOC_CLOCK_OUT);
+	if (ret) {
+		dev_err(dev, "could not set cpu dai driver clock params :%d\n",
+				ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int sgtl5000_params(struct snd_pcm_substream *substream,
+		struct snd_pcm_hw_params *params)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+	unsigned int channels = params_channels(params);
+
+	/* TODO: The SAI driver should figure this out for us */
+	switch (channels) {
+	case 2:
+		snd_soc_dai_set_tdm_slot(cpu_dai, 0xfffffffc, 0xfffffffc, 2, 0);
+		break;
+	case 1:
+		snd_soc_dai_set_tdm_slot(cpu_dai, 0xfffffffe, 0xfffffffe, 1, 0);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static struct snd_soc_ops fsl_sgtl5000_hifi_ops = {
+	.hw_params = sgtl5000_params,
+};
+
+static struct snd_soc_dai_link fsl_sgtl5000_dai = {
+	.name = "HiFi",
+	.stream_name = "HiFi",
+	.codec_dai_name = "sgtl5000",
+	.init = &fsl_sgtl5000_dai_init,
+	.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+		SND_SOC_DAIFMT_CBM_CFM,
+	.ops = &fsl_sgtl5000_hifi_ops,
+};
+
+static const struct snd_soc_dapm_widget fsl_sgtl5000_dapm_widgets[] = {
+	SND_SOC_DAPM_MIC("Mic Jack", NULL),
+	SND_SOC_DAPM_LINE("Line In Jack", NULL),
+	SND_SOC_DAPM_HP("Headphone Jack", NULL),
+	SND_SOC_DAPM_SPK("Line Out Jack", NULL),
+	SND_SOC_DAPM_SPK("Ext Spk", NULL),
+};
+
+static struct snd_soc_card fsl_sgt1500_card = {
+	.owner = THIS_MODULE,
+	.num_links = 1,
+	.dai_link = &fsl_sgtl5000_dai,
+	.dapm_widgets = fsl_sgtl5000_dapm_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(fsl_sgtl5000_dapm_widgets),
+};
+
+static int fsl_sgtl5000_parse_dt(struct platform_device *pdev)
+{
+	int ret;
+	struct device_node *sai_np, *codec_np;
+	struct clk *codec_clk;
+	struct i2c_client *codec_dev;
+	struct device_node *np = pdev->dev.of_node;
+
+	ret = snd_soc_of_parse_card_name(&fsl_sgt1500_card, "model");
+	if (ret)
+		return ret;
+
+	ret = snd_soc_of_parse_audio_routing(&fsl_sgt1500_card,
+			"audio-routing");
+	if (ret)
+		return ret;
+
+	sai_np = of_parse_phandle(np, "saif-controller", 0);
+	if (!sai_np) {
+		dev_err(&pdev->dev, "\"saif-controller\" phandle missing or "
+				"invalid\n");
+		return -EINVAL;
+	}
+	fsl_sgtl5000_dai.cpu_of_node = sai_np;
+	fsl_sgtl5000_dai.platform_of_node = sai_np;
+
+	codec_np = of_parse_phandle(np, "audio-codec", 0);
+	if (!codec_np) {
+		dev_err(&pdev->dev, "\"audio-codec\" phandle missing or "
+				"invalid\n");
+		ret = -EINVAL;
+		goto sai_np_fail;
+	}
+	fsl_sgtl5000_dai.codec_of_node = codec_np;
+
+	codec_dev = of_find_i2c_device_by_node(codec_np);
+	if (!codec_dev) {
+		dev_err(&pdev->dev, "failed to find codec platform device\n");
+		ret = PTR_ERR(codec_dev);
+		goto codec_np_fail;
+	}
+
+	codec_clk = devm_clk_get(&codec_dev->dev, NULL);
+	if (IS_ERR(codec_clk)) {
+		dev_err(&pdev->dev, "failed to get codec clock\n");
+		ret = PTR_ERR(codec_clk);
+		goto codec_np_fail;
+	}
+
+	sysclk_rate = clk_get_rate(codec_clk);
+
+codec_np_fail:
+	of_node_put(codec_np);
+sai_np_fail:
+	of_node_put(sai_np);
+
+	return ret;
+}
+
+static int fsl_sgtl5000_probe(struct platform_device *pdev)
+{
+	int ret;
+
+	fsl_sgt1500_card.dev = &pdev->dev;
+
+	ret = fsl_sgtl5000_parse_dt(pdev);
+	if (ret) {
+		dev_err(&pdev->dev,
+				"parse sgtl5000 device tree failed :%d\n",
+				ret);
+		return ret;
+	}
+
+	ret = snd_soc_register_card(&fsl_sgt1500_card);
+	if (ret) {
+		dev_err(&pdev->dev, "register soc sound card failed :%d\n",
+				ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int fsl_sgtl5000_remove(struct platform_device *pdev)
+{
+	snd_soc_unregister_card(&fsl_sgt1500_card);
+
+	return 0;
+}
+
+static const struct of_device_id fsl_sgtl5000_dt_ids[] = {
+	{ .compatible = "fsl,vf610-sgtl5000", },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, fsl_sgtl5000_dt_ids);
+
+static struct platform_driver fsl_sgtl5000_driver = {
+	.driver = {
+		.name = "fsl-sgtl5000",
+		.owner = THIS_MODULE,
+		.of_match_table = fsl_sgtl5000_dt_ids,
+	},
+	.probe = fsl_sgtl5000_probe,
+	.remove = fsl_sgtl5000_remove,
+};
+module_platform_driver(fsl_sgtl5000_driver);
+
+MODULE_AUTHOR("Xiubo Li <Li.Xiubo@freescale.com>");
+MODULE_DESCRIPTION("Freescale SGTL5000 ASoC driver");
+MODULE_LICENSE("GPL");
-- 
1.8.0

^ permalink raw reply related

* [PATCHv1 7/8] ARM: dts: Enable SGT15000 codec based audio driver node for VF610.
From: Xiubo Li @ 2013-10-17  9:01 UTC (permalink / raw)
  To: r65073, timur, lgirdwood, broonie
  Cc: mark.rutland, alsa-devel, linux-doc, tiwai, b18965, perex, LW,
	linux, b42378, oskar, grant.likely, devicetree, ian.campbell,
	pawel.moll, swarren, rob.herring, linux-arm-kernel, fabio.estevam,
	linux-kernel, rob, r64188, shawn.guo, linuxppc-dev
In-Reply-To: <1382000477-17304-1-git-send-email-Li.Xiubo@freescale.com>

This patch add and enable SGT15000 codec support, and also specified
the corresponding SAI node.

Signed-off-by: Xiubo Li <Li.Xiubo@freescale.com>
Signed-off-by: Alison Wang <b18965@freescale.com
---
 arch/arm/boot/dts/vf610-twr.dts | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/arch/arm/boot/dts/vf610-twr.dts b/arch/arm/boot/dts/vf610-twr.dts
index e4106dd..a2d9214 100644
--- a/arch/arm/boot/dts/vf610-twr.dts
+++ b/arch/arm/boot/dts/vf610-twr.dts
@@ -34,6 +34,19 @@
 		};
 	};
 
+	sound {
+		compatible = "fsl,vf610-sgtl5000";
+		model = "vf610-sgtl5000";
+		saif-controller = <&sai2>;
+		audio-codec = <&codec>;
+		audio-routing =
+			"MIC_IN", "Mic Jack",
+			"Mic Jack", "Mic Bias",
+			"LINE_IN", "Line In Jack",
+			"Headphone Jack", "HP_OUT",
+			"Ext Spk", "LINE_OUT";
+	};
+
 };
 
 &fec0 {
@@ -55,6 +68,12 @@
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_i2c0_1>;
 	status = "okay";
+
+	codec: sgtl5000@0a {
+		compatible = "fsl,sgtl5000";
+		reg = <0x0a>;
+		clocks = <&clks VF610_CLK_SAI2>;
+	};
 };
 
 &sai2 {
-- 
1.8.0

^ permalink raw reply related

* [PATCHv1 8/8] Documentation: Add device tree bindings for Freescale VF610 sound.
From: Xiubo Li @ 2013-10-17  9:01 UTC (permalink / raw)
  To: r65073, timur, lgirdwood, broonie
  Cc: mark.rutland, alsa-devel, linux-doc, tiwai, b18965, perex, LW,
	linux, b42378, oskar, grant.likely, devicetree, ian.campbell,
	pawel.moll, swarren, rob.herring, linux-arm-kernel, fabio.estevam,
	linux-kernel, rob, r64188, shawn.guo, linuxppc-dev
In-Reply-To: <1382000477-17304-1-git-send-email-Li.Xiubo@freescale.com>

This adds the Document for Freescale VF610 sound driver under
Documentation/devicetree/bindings/sound/.

Signed-off-by: Xiubo Li <Li.Xiubo@freescale.com>
---
 .../devicetree/bindings/sound/fsl-sgtl5000.txt     | 52 ++++++++++++++++++++++
 1 file changed, 52 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/sound/fsl-sgtl5000.txt

diff --git a/Documentation/devicetree/bindings/sound/fsl-sgtl5000.txt b/Documentation/devicetree/bindings/sound/fsl-sgtl5000.txt
new file mode 100644
index 0000000..43e350f
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/fsl-sgtl5000.txt
@@ -0,0 +1,52 @@
+Freescale VF610 audio complex with SGTL5000 codec
+
+Required properties:
+- compatible: "fsl,vf610-sgtl5000"
+- model: The user-visible name of this sound complex.
+- saif-controllers: The phandle list of the SAI controller.
+- audio-codec: The phandle of the SGTL5000 audio codec.
+- audio-routing : A list of the connections between audio components.
+  Each entry is a pair of strings, the first being the connection's sink,
+  the second being the connection's source. Valid names could be power
+  supplies, SGTL5000 pins, and the jacks on the board:
+
+  -- Power supplies:
+     * Mic Bias
+
+  -- SGTL5000 pins:
+     * MIC_IN
+     * LINE_IN
+     * HP_OUT
+     * LINE_OUT
+
+  -- Board connectors:
+     * Mic Jack
+     * Line In Jack
+     * Headphone Jack
+     * Line Out Jack
+     * Ext Spk
+
+Example:
+
+sound {
+	compatible = "fsl,vf610-sgtl5000";
+	model = "vf610-sgtl5000";
+	saif-controller = <&sai2>;
+	audio-codec = <&codec>;
+	audio-routing =
+		"MIC_IN", "Mic Jack",
+		"Mic Jack", "Mic Bias",
+		"LINE_IN", "Line In Jack",
+		"Headphone Jack", "HP_OUT",
+		"Ext Spk", "LINE_OUT";
+};
+
+&i2c0 {
+	...
+
+	codec: sgtl5000@0a {
+	       compatible = "fsl,sgtl5000";
+	       reg = <0x0a>;
+	       clocks = <&clks VF610_CLK_SAI2>;
+       };
+};
-- 
1.8.0

^ permalink raw reply related

* Re: [PATCH] ASoC: fsl_ssi: Fix irq_of_parse_and_map() return value check
From: Mark Brown @ 2013-10-17  9:40 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: alsa-devel, Timur Tabi, Takashi Iwai, linux-kernel, Liam Girdwood,
	Jaroslav Kysela, Geert Uytterhoeven, Grant Likely, linuxppc-dev
In-Reply-To: <525F4421.3090404@roeck-us.net>

[-- Attachment #1: Type: text/plain, Size: 176 bytes --]

On Wed, Oct 16, 2013 at 06:57:53PM -0700, Guenter Roeck wrote:

> do you plan to send this patch upstream anytime soon ?

It'll go next time I send stuff if it hasn't already.

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply

* Re: [PATCHv1 1/8] ALSA: Add SAI SoC Digital Audio Interface driver.
From: Lothar Waßmann @ 2013-10-17  9:42 UTC (permalink / raw)
  To: Xiubo Li
  Cc: mark.rutland, alsa-devel, linux-doc, tiwai, b18965, timur, perex,
	r65073, linux, b42378, linux-arm-kernel, grant.likely, devicetree,
	ian.campbell, pawel.moll, swarren, rob.herring, broonie, oskar,
	fabio.estevam, lgirdwood, linux-kernel, rob, r64188, shawn.guo,
	linuxppc-dev
In-Reply-To: <1382000477-17304-2-git-send-email-Li.Xiubo@freescale.com>

Hi,

Xiubo Li <Li.Xiubo@freescale.com> wrote:
[...]
> diff --git a/sound/soc/fsl/fsl-pcm-dma.c b/sound/soc/fsl/fsl-pcm-dma.c
> new file mode 100644
> index 0000000..c4d925e
> --- /dev/null
> +++ b/sound/soc/fsl/fsl-pcm-dma.c
> @@ -0,0 +1,51 @@
[...]
> +
> +static int fsl_sai_probe(struct platform_device *pdev)
> +{
> +	struct of_phandle_args	dma_args;
> +	int index;
> +	struct resource *res;
> +	struct fsl_sai *sai;
> +	int ret =3D 0;
> +	struct device_node *np =3D pdev->dev.of_node;
> +
> +	sai =3D devm_kzalloc(&pdev->dev, sizeof(*sai), GFP_KERNEL);
> +	if (!sai)
> +		return -ENOMEM;
> +
> +	sai->fbt =3D FSL_SAI_FBT_MSB;
> +
> +	res =3D platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	sai->base =3D devm_ioremap_resource(&pdev->dev, res);
> +	if (IS_ERR(sai->base)) {
> +		ret =3D PTR_ERR(sai->base);
> +		return ret;
>
could be:
		return PTR_ERR(sai->base);

[...]
> +static const struct of_device_id fsl_sai_ids[] =3D {
> +	{ .compatible =3D "fsl,vf610-sai", },
> +	{ /*sentinel*/ },
>
The comma after the last entry in a struct initializer is there to make
patches that append another entry cleaner. Since this entry is and
always must be the last entry, the comma is useless here.

> diff --git a/sound/soc/fsl/fsl-sai.h b/sound/soc/fsl/fsl-sai.h
> new file mode 100644
> index 0000000..ab76a8e
> --- /dev/null
> +++ b/sound/soc/fsl/fsl-sai.h
> @@ -0,0 +1,127 @@
> +/*
> + * Copyright 2012-2013 Freescale Semiconductor, Inc.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#ifndef __FSL_SAI_H
> +#define __FSL_SAI_H
> +
> +#include <sound/dmaengine_pcm.h>
> +
> +#define FSL_SAI_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
> +			 SNDRV_PCM_FMTBIT_S20_3LE |\
> +			 SNDRV_PCM_FMTBIT_S24_LE)
> +
> +#define FSL_SAI_DMABUF_SIZE	(32 * 1024)
> +#define TCD_NUMBER		4
> +#define EDMA_PRIO_HIGH          6
> +
strange indentation with mixed spaces and tabs.

> +/* SAI Transmit and Recieve Configuration 2 Register */
> +#define SAI_TCR2		0x08
> +#define SAI_RCR2		0x88
> +#define SAI_CR2_SYNC		BIT(30)
> +#define SAI_CR2_MSEL_MASK	(0xff << 26)
> +#define SAI_CR2_MSEL_BUS	0
> +#define SAI_CR2_MSEL_MCLK1	BIT(26)
> +#define SAI_CR2_MSEL_MCLK2	BIT(27)
> +#define SAI_CR2_MSEL_MCLK3	(BIT(26)|BIT(27))
>
spaces around '|'?


Lothar Wa=C3=9Fmann
--=20
___________________________________________________________

Ka-Ro electronics GmbH | Pascalstra=C3=9Fe 22 | D - 52076 Aachen
Phone: +49 2408 1402-0 | Fax: +49 2408 1402-10
Gesch=C3=A4ftsf=C3=BChrer: Matthias Kaussen
Handelsregistereintrag: Amtsgericht Aachen, HRB 4996

www.karo-electronics.de | info@karo-electronics.de
___________________________________________________________

^ permalink raw reply

* Re: [PATCHv1 8/8] Documentation: Add device tree bindings for Freescale VF610 sound.
From: Lucas Stach @ 2013-10-17  9:46 UTC (permalink / raw)
  To: Xiubo Li
  Cc: mark.rutland, alsa-devel, linux-doc, tiwai, b18965, timur, perex,
	r65073, LW, linux, b42378, oskar, grant.likely, devicetree,
	ian.campbell, pawel.moll, swarren, rob.herring, broonie,
	linux-arm-kernel, fabio.estevam, lgirdwood, linux-kernel, rob,
	r64188, shawn.guo, linuxppc-dev
In-Reply-To: <1382000477-17304-9-git-send-email-Li.Xiubo@freescale.com>

Am Donnerstag, den 17.10.2013, 17:01 +0800 schrieb Xiubo Li:
> This adds the Document for Freescale VF610 sound driver under
> Documentation/devicetree/bindings/sound/.
> 
> Signed-off-by: Xiubo Li <Li.Xiubo@freescale.com>
> ---
>  .../devicetree/bindings/sound/fsl-sgtl5000.txt     | 52 ++++++++++++++++++++++
>  1 file changed, 52 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/sound/fsl-sgtl5000.txt
> 
> diff --git a/Documentation/devicetree/bindings/sound/fsl-sgtl5000.txt b/Documentation/devicetree/bindings/sound/fsl-sgtl5000.txt
> new file mode 100644
> index 0000000..43e350f
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/sound/fsl-sgtl5000.txt

This document name is overly generic, there are more than one FSL
platforms with SGTL5000 codecs. Please include the vf610 here.

> @@ -0,0 +1,52 @@
> +Freescale VF610 audio complex with SGTL5000 codec
> +
> +Required properties:
> +- compatible: "fsl,vf610-sgtl5000"
> +- model: The user-visible name of this sound complex.
> +- saif-controllers: The phandle list of the SAI controller.
> +- audio-codec: The phandle of the SGTL5000 audio codec.
> +- audio-routing : A list of the connections between audio components.
> +  Each entry is a pair of strings, the first being the connection's sink,
> +  the second being the connection's source. Valid names could be power
> +  supplies, SGTL5000 pins, and the jacks on the board:
> +
> +  -- Power supplies:
> +     * Mic Bias
> +
> +  -- SGTL5000 pins:
> +     * MIC_IN
> +     * LINE_IN
> +     * HP_OUT
> +     * LINE_OUT
> +
> +  -- Board connectors:
> +     * Mic Jack
> +     * Line In Jack
> +     * Headphone Jack
> +     * Line Out Jack
> +     * Ext Spk
> +
> +Example:
> +
> +sound {
> +	compatible = "fsl,vf610-sgtl5000";
> +	model = "vf610-sgtl5000";
> +	saif-controller = <&sai2>;
> +	audio-codec = <&codec>;
> +	audio-routing =
> +		"MIC_IN", "Mic Jack",
> +		"Mic Jack", "Mic Bias",
> +		"LINE_IN", "Line In Jack",
> +		"Headphone Jack", "HP_OUT",
> +		"Ext Spk", "LINE_OUT";
> +};
> +
> +&i2c0 {
> +	...
> +
> +	codec: sgtl5000@0a {
> +	       compatible = "fsl,sgtl5000";
> +	       reg = <0x0a>;
> +	       clocks = <&clks VF610_CLK_SAI2>;
> +       };
> +};

-- 
Pengutronix e.K.                           | Lucas Stach                 |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-5076 |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

^ permalink raw reply

* Re: [PATCHv1 5/8] ASoC: sgtl5000: Revise the bugs about the sgt15000 codec.
From: Nicolin Chen @ 2013-10-17  9:56 UTC (permalink / raw)
  To: Xiubo Li
  Cc: mark.rutland, alsa-devel, linux-doc, tiwai, b18965, timur, perex,
	r65073, LW, linux, linux-arm-kernel, grant.likely, devicetree,
	ian.campbell, pawel.moll, swarren, rob.herring, broonie, oskar,
	fabio.estevam, lgirdwood, linux-kernel, rob, r64188, shawn.guo,
	linuxppc-dev
In-Reply-To: <1382000477-17304-6-git-send-email-Li.Xiubo@freescale.com>

Hi,

On Thu, Oct 17, 2013 at 05:01:14PM +0800, Xiubo Li wrote:
> When the CONFIG_REGULATOR is disabled there will be some warnings
> printed out.

A little confused by the title. But after looking at the comments,
is the patch just gonna add some debug info for the case when the
CONFIG_REGULATOR's been un-selected? 

Well first, I think at least the title should be more explicit.
And second, the necessity of this patch might just a little...
if CONFIG_REGULATOR is required to power it up, why not turn it on.

> 
> Signed-off-by: Xiubo Li <Li.Xiubo@freescale.com>
> ---
>  sound/soc/codecs/sgtl5000.c | 13 ++++++++++++-
>  1 file changed, 12 insertions(+), 1 deletion(-)
> 
> diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c
> index 1f4093f..4e2e4c9 100644
> --- a/sound/soc/codecs/sgtl5000.c
> +++ b/sound/soc/codecs/sgtl5000.c
> @@ -883,14 +883,19 @@ static int ldo_regulator_register(struct snd_soc_codec *codec,
>  				struct regulator_init_data *init_data,
>  				int voltage)
>  {
> +#ifdef CONFIG_SND_SOC_FSL_SGTL5000

Why there's FSL_SGTL5000 here? Not supposed to be CONFIG_REGULATOR?

> +	return 0;
> +#else
>  	dev_err(codec->dev, "this setup needs regulator support in the kernel\n");
>  	return -EINVAL;
> +#endif
>  }
>  
>  static int ldo_regulator_remove(struct snd_soc_codec *codec)
>  {
>  	return 0;
>  }
> +

I don't think it's fair to add a meaningless line. It doesn't make any sense
according to the title and comments.

>  #endif
>  
>  /*
> @@ -1137,6 +1142,7 @@ static int sgtl5000_resume(struct snd_soc_codec *codec)
>  #define sgtl5000_resume  NULL
>  #endif	/* CONFIG_SUSPEND */
>  
> +#ifdef CONFIG_REGULATOR

The inline regulator-related functions are already have REGULATOR dependency.
Is that necessary to put an additional one here?

>  /*
>   * sgtl5000 has 3 internal power supplies:
>   * 1. VAG, normally set to vdda/2
> @@ -1269,6 +1275,7 @@ static int sgtl5000_set_power_regs(struct snd_soc_codec *codec)
>  
>  	return 0;
>  }
> +#endif
>  
>  static int sgtl5000_replace_vddd_with_ldo(struct snd_soc_codec *codec)
>  {
> @@ -1370,6 +1377,7 @@ err_regulator_free:
>  				sgtl5000->supplies);
>  	if (external_vddd)
>  		ldo_regulator_remove(codec);
> +

Pls drop this.

>  	return ret;
>  
>  }
> @@ -1391,11 +1399,12 @@ static int sgtl5000_probe(struct snd_soc_codec *codec)
>  	if (ret)
>  		return ret;
>  
> +#ifdef CONFIG_REGULATOR
>  	/* power up sgtl5000 */
>  	ret = sgtl5000_set_power_regs(codec);
>  	if (ret)
>  		goto err;
> -
> +#endif
>  	/* enable small pop, introduce 400ms delay in turning off */
>  	snd_soc_update_bits(codec, SGTL5000_CHIP_REF_CTRL,
>  				SGTL5000_SMALL_POP,
> @@ -1446,6 +1455,7 @@ err:
>  						sgtl5000->supplies);
>  	regulator_bulk_free(ARRAY_SIZE(sgtl5000->supplies),
>  				sgtl5000->supplies);
> +

Ditto

>  	ldo_regulator_remove(codec);
>  
>  	return ret;
> @@ -1461,6 +1471,7 @@ static int sgtl5000_remove(struct snd_soc_codec *codec)
>  						sgtl5000->supplies);
>  	regulator_bulk_free(ARRAY_SIZE(sgtl5000->supplies),
>  				sgtl5000->supplies);
> +

Ditto 

Best regards,
Nicolin Chen

>  	ldo_regulator_remove(codec);
>  
>  	return 0;
> -- 
> 1.8.0
> 

^ permalink raw reply

* Re: [PATCHv1 5/8] ASoC: sgtl5000: Revise the bugs about the sgt15000 codec.
From: Lothar Waßmann @ 2013-10-17 10:17 UTC (permalink / raw)
  To: Xiubo Li
  Cc: mark.rutland, alsa-devel, linux-doc, tiwai, b18965, timur, perex,
	r65073, linux, b42378, linux-arm-kernel, grant.likely, devicetree,
	ian.campbell, pawel.moll, swarren, rob.herring, broonie, oskar,
	fabio.estevam, lgirdwood, linux-kernel, rob, r64188, shawn.guo,
	linuxppc-dev
In-Reply-To: <1382000477-17304-6-git-send-email-Li.Xiubo@freescale.com>

Hi,

Xiubo Li <Li.Xiubo@freescale.com> wrote:
> When the CONFIG_REGULATOR is disabled there will be some warnings
> printed out.
>=20
> Signed-off-by: Xiubo Li <Li.Xiubo@freescale.com>
> ---
>  sound/soc/codecs/sgtl5000.c | 13 ++++++++++++-
>  1 file changed, 12 insertions(+), 1 deletion(-)
>=20
> diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c
> index 1f4093f..4e2e4c9 100644
> --- a/sound/soc/codecs/sgtl5000.c
> +++ b/sound/soc/codecs/sgtl5000.c
> @@ -883,14 +883,19 @@ static int ldo_regulator_register(struct snd_soc_co=
dec *codec,
>  				struct regulator_init_data *init_data,
>  				int voltage)
>  {
> +#ifdef CONFIG_SND_SOC_FSL_SGTL5000
> +	return 0;
> +#else
>  	dev_err(codec->dev, "this setup needs regulator support in the kernel\n=
");
>  	return -EINVAL;
> +#endif
>
This looks wrong to me, as this will disable the error for unsolicited
platforms in a multi arch kernel!

>  static int ldo_regulator_remove(struct snd_soc_codec *codec)
>  {
>  	return 0;
>  }
> +
>  #endif
> =20
Why do you add an extra empty line here?


Lothar Wa=C3=9Fmann
--=20
___________________________________________________________

Ka-Ro electronics GmbH | Pascalstra=C3=9Fe 22 | D - 52076 Aachen
Phone: +49 2408 1402-0 | Fax: +49 2408 1402-10
Gesch=C3=A4ftsf=C3=BChrer: Matthias Kaussen
Handelsregistereintrag: Amtsgericht Aachen, HRB 4996

www.karo-electronics.de | info@karo-electronics.de
___________________________________________________________

^ permalink raw reply

* [PATCH 5/7] jump_label: relax branch hinting restrictions
From: Radim Krčmář @ 2013-10-17 10:10 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-mips, x86, Radim Krčmář, linux-doc,
	Heiko Carstens, sparclinux, Paul Mackerras, H. Peter Anvin,
	Masami Hiramatsu, linux-s390, Russell King, Raghavendra K T,
	Ingo Molnar, Andrew Jones, Konrad Rzeszutek Wilk, Steven Rostedt,
	Thomas Gleixner, linux-arm-kernel, Richard Henderson, Jiri Kosina,
	Ralf Baechle, Rob Landley, Martin Schwidefsky, linux390,
	linuxppc-dev, David S. Miller
In-Reply-To: <1382004631-25895-1-git-send-email-rkrcmar@redhat.com>

We implemented the optimized branch selection in higher levels of api.
That made static_keys very unintuitive, so this patch introduces another
element to jump_table, carrying one bit that tells the underlying code
which branch to optimize.

It is now possible to select optimized branch for every jump_entry.

Current side effect is 1/3 increase increase in space, we could:
* use bitmasks and selectors on 2+ aligned code/struct.
  - aligning jump target is easy, but because it is not done by default
    and few bytes in .text are much worse that few kilos in .data,
    I chose not to
  - data is probably aligned by default on all current architectures,
    but programmer can force misalignment of static_key
* optimize each architecture independently
  - I can't test everything and this patch shouldn't break anything, so
    others can contribute in the future
* choose something worse, like packing or splitting
* ignore

proof: example & x86_64 disassembly: (F = ffffffff)

  struct static_key flexible_feature;
  noinline void jump_label_experiment(void) {
  	if ( static_key_false(&flexible_feature))
  	     asm ("push 0xa1");
  	else asm ("push 0xa0");
  	if (!static_key_false(&flexible_feature))
  	     asm ("push 0xb0");
  	else asm ("push 0xb1");
  	if ( static_key_true(&flexible_feature))
  	     asm ("push 0xc1");
  	else asm ("push 0xc0");
  	if (!static_key_true(&flexible_feature))
  	     asm ("push 0xd0");
  	else asm ("push 0xd1");
  }

  Disassembly of section .text: (push marked by "->")

  F81002000 <jump_label_experiment>:
  F81002000:       e8 7b 29 75 00          callq  F81754980 <__fentry__>
  F81002005:       55                      push   %rbp
  F81002006:       48 89 e5                mov    %rsp,%rbp
  F81002009:       0f 1f 44 00 00          nopl   0x0(%rax,%rax,1)
  F8100200e: ->    ff 34 25 a0 00 00 00    pushq  0xa0
  F81002015:       0f 1f 44 00 00          nopl   0x0(%rax,%rax,1)
  F8100201a: ->    ff 34 25 b0 00 00 00    pushq  0xb0
  F81002021:       0f 1f 44 00 00          nopl   0x0(%rax,%rax,1)
  F81002026: ->    ff 34 25 c1 00 00 00    pushq  0xc1
  F8100202d:       0f 1f 00                nopl   (%rax)
  F81002030:       0f 1f 44 00 00          nopl   0x0(%rax,%rax,1)
  F81002035: ->    ff 34 25 d1 00 00 00    pushq  0xd1
  F8100203c:       5d                      pop    %rbp
  F8100203d:       0f 1f 00                nopl   (%rax)
  F81002040:       c3                      retq
  F81002041:       0f 1f 80 00 00 00 00    nopl   0x0(%rax)
  F81002048: ->    ff 34 25 d0 00 00 00    pushq  0xd0
  F8100204f:       5d                      pop    %rbp
  F81002050:       c3                      retq
  F81002051:       0f 1f 80 00 00 00 00    nopl   0x0(%rax)
  F81002058: ->    ff 34 25 c0 00 00 00    pushq  0xc0
  F8100205f:       90                      nop
  F81002060:       eb cb                   jmp    F8100202d <[...]+0x2d>
  F81002062:       66 0f 1f 44 00 00       nopw   0x0(%rax,%rax,1)
  F81002068: ->    ff 34 25 b1 00 00 00    pushq  0xb1
  F8100206f:       90                      nop
  F81002070:       eb af                   jmp    F81002021 <[...]+0x21>
  F81002072:       66 0f 1f 44 00 00       nopw   0x0(%rax,%rax,1)
  F81002078: ->    ff 34 25 a1 00 00 00    pushq  0xa1
  F8100207f:       90                      nop
  F81002080:       eb 93                   jmp    F81002015 <[...]+0x15>
  F81002082:       66 66 66 66 66 2e 0f    [...]
  F81002089:       1f 84 00 00 00 00 00

  Contents of section .data: (relevant part of embedded __jump_table)
    F81d26a40 09200081 ffffffff 78200081 ffffffff
    F81d26a50 20600f82 ffffffff 00000000 00000000
    F81d26a60 15200081 ffffffff 68200081 ffffffff
    F81d26a70 20600f82 ffffffff 00000000 00000000
    F81d26a80 21200081 ffffffff 58200081 ffffffff
    F81d26a90 20600f82 ffffffff 01000000 00000000
    F81d26aa0 30200081 ffffffff 48200081 ffffffff
    F81d26ab0 20600f82 ffffffff 01000000 00000000

  (I've also compiled for s390x, blocks were placed correctly,
   jump table looked ok too;
   I hope the least significant bit is correct everywhere)

Signed-off-by: Radim Krčmář <rkrcmar@redhat.com>
---
 Documentation/static-keys.txt         |  6 ----
 arch/arm/include/asm/jump_label.h     | 19 ++++++++----
 arch/arm/kernel/jump_label.c          |  2 +-
 arch/mips/include/asm/jump_label.h    | 19 ++++++++----
 arch/mips/kernel/jump_label.c         |  2 +-
 arch/powerpc/include/asm/jump_label.h | 19 ++++++++----
 arch/powerpc/kernel/jump_label.c      |  2 +-
 arch/s390/include/asm/jump_label.h    | 19 ++++++++----
 arch/s390/kernel/jump_label.c         |  2 +-
 arch/sparc/include/asm/jump_label.h   | 19 ++++++++----
 arch/sparc/kernel/jump_label.c        |  2 +-
 arch/x86/include/asm/jump_label.h     | 19 ++++++++----
 arch/x86/kernel/jump_label.c          | 32 ++++----------------
 include/linux/jump_label.h            | 55 ++++++++++++-----------------------
 kernel/jump_label.c                   | 29 ++++--------------
 15 files changed, 119 insertions(+), 127 deletions(-)

diff --git a/Documentation/static-keys.txt b/Documentation/static-keys.txt
index 9f5263d..57c040e 100644
--- a/Documentation/static-keys.txt
+++ b/Documentation/static-keys.txt
@@ -103,12 +103,6 @@ Or:
         else
                 do unlikely code
 
-A key that is initialized via 'STATIC_KEY_INIT_FALSE', must be used in a
-'static_key_false()' construct. Likewise, a key initialized via
-'STATIC_KEY_INIT_TRUE' must be used in a 'static_key_true()' construct. A
-single key can be used in many branches, but all the branches must match the
-way that the key has been initialized.
-
 The branch(es) can then be switched via:
 
 	static_key_slow_inc(&key);
diff --git a/arch/arm/include/asm/jump_label.h b/arch/arm/include/asm/jump_label.h
index 863c892..f4ec3af 100644
--- a/arch/arm/include/asm/jump_label.h
+++ b/arch/arm/include/asm/jump_label.h
@@ -14,18 +14,21 @@
 #define JUMP_LABEL_NOP	"nop"
 #endif
 
-static __always_inline bool arch_static_branch(struct static_key *key)
+struct static_key;
+
+static __always_inline bool arch_static_branch(struct static_key *key,
+		const bool default_branch)
 {
 	asm_volatile_goto("1:\n\t"
 		 JUMP_LABEL_NOP "\n\t"
 		 ".pushsection __jump_table,  \"aw\"\n\t"
-		 ".word 1b, %l[l_yes], %c0\n\t"
+		 ".word 1b, %l[l_yes], %c0, %c1\n\t"
 		 ".popsection\n\t"
-		 : :  "i" (key) :  : l_yes);
+		 : :  "i" (key), "i" (default_branch) :  : l_yes);
 
-	return false;
+	return default_branch;
 l_yes:
-	return true;
+	return !default_branch;
 }
 
 #endif /* __KERNEL__ */
@@ -36,6 +39,12 @@ struct jump_entry {
 	jump_label_t code;
 	jump_label_t target;
 	jump_label_t key;
+	union {
+		jump_label_t flags;
+		struct {
+			unsigned default_branch:1; /* lsb */
+		};
+	};
 };
 
 #endif
diff --git a/arch/arm/kernel/jump_label.c b/arch/arm/kernel/jump_label.c
index 4ce4f78..b02c531 100644
--- a/arch/arm/kernel/jump_label.c
+++ b/arch/arm/kernel/jump_label.c
@@ -13,7 +13,7 @@ static void __arch_jump_label_transform(struct jump_entry *entry,
 	void *addr = (void *)entry->code;
 	unsigned int insn;
 
-	if (type == JUMP_LABEL_ENABLE)
+	if (type != jump_label_default_branch(entry))
 		insn = arm_gen_branch(entry->code, entry->target);
 	else
 		insn = arm_gen_nop();
diff --git a/arch/mips/include/asm/jump_label.h b/arch/mips/include/asm/jump_label.h
index e194f95..2c065ec 100644
--- a/arch/mips/include/asm/jump_label.h
+++ b/arch/mips/include/asm/jump_label.h
@@ -20,17 +20,20 @@
 #define WORD_INSN ".word"
 #endif
 
-static __always_inline bool arch_static_branch(struct static_key *key)
+struct static_key;
+
+static __always_inline bool arch_static_branch(struct static_key *key,
+		const bool default_branch)
 {
 	asm_volatile_goto("1:\tnop\n\t"
 		"nop\n\t"
 		".pushsection __jump_table,  \"aw\"\n\t"
-		WORD_INSN " 1b, %l[l_yes], %0\n\t"
+		WORD_INSN " 1b, %l[l_yes], %0, %1\n\t"
 		".popsection\n\t"
-		: :  "i" (key) : : l_yes);
-	return false;
+		: :  "i" (key), "i" (default_branch) : : l_yes);
+	return default_branch;
 l_yes:
-	return true;
+	return !default_branch;
 }
 
 #endif /* __KERNEL__ */
@@ -45,6 +48,12 @@ struct jump_entry {
 	jump_label_t code;
 	jump_label_t target;
 	jump_label_t key;
+	union {
+		jump_label_t flags;
+		struct {
+			unsigned default_branch:1; /* lsb */
+		};
+	};
 };
 
 #endif /* _ASM_MIPS_JUMP_LABEL_H */
diff --git a/arch/mips/kernel/jump_label.c b/arch/mips/kernel/jump_label.c
index 6001610..e5b17ee 100644
--- a/arch/mips/kernel/jump_label.c
+++ b/arch/mips/kernel/jump_label.c
@@ -33,7 +33,7 @@ void arch_jump_label_transform(struct jump_entry *e,
 	/* Target must have 4 byte alignment. */
 	BUG_ON((e->target & 3) != 0);
 
-	if (type == JUMP_LABEL_ENABLE) {
+	if (type != jump_label_default_branch(entry)) {
 		insn.j_format.opcode = j_op;
 		insn.j_format.target = (e->target & J_RANGE_MASK) >> 2;
 	} else {
diff --git a/arch/powerpc/include/asm/jump_label.h b/arch/powerpc/include/asm/jump_label.h
index f016bb6..463c03d 100644
--- a/arch/powerpc/include/asm/jump_label.h
+++ b/arch/powerpc/include/asm/jump_label.h
@@ -17,17 +17,20 @@
 #define JUMP_ENTRY_TYPE		stringify_in_c(FTR_ENTRY_LONG)
 #define JUMP_LABEL_NOP_SIZE	4
 
-static __always_inline bool arch_static_branch(struct static_key *key)
+struct static_key;
+
+static __always_inline bool arch_static_branch(struct static_key *key,
+		const bool default_branch)
 {
 	asm_volatile_goto("1:\n\t"
 		 "nop\n\t"
 		 ".pushsection __jump_table,  \"aw\"\n\t"
-		 JUMP_ENTRY_TYPE "1b, %l[l_yes], %c0\n\t"
+		 JUMP_ENTRY_TYPE "1b, %l[l_yes], %c0, %c1\n\t"
 		 ".popsection \n\t"
-		 : :  "i" (key) : : l_yes);
-	return false;
+		 : :  "i" (key), "i" (default_branch) : : l_yes);
+	return default_branch;
 l_yes:
-	return true;
+	return !default_branch;
 }
 
 #ifdef CONFIG_PPC64
@@ -40,6 +43,12 @@ struct jump_entry {
 	jump_label_t code;
 	jump_label_t target;
 	jump_label_t key;
+	union {
+		jump_label_t flags;
+		struct {
+			unsigned default_branch:1; /* lsb */
+		};
+	};
 };
 
 #endif /* _ASM_POWERPC_JUMP_LABEL_H */
diff --git a/arch/powerpc/kernel/jump_label.c b/arch/powerpc/kernel/jump_label.c
index a1ed8a8..ebf148b 100644
--- a/arch/powerpc/kernel/jump_label.c
+++ b/arch/powerpc/kernel/jump_label.c
@@ -17,7 +17,7 @@ void arch_jump_label_transform(struct jump_entry *entry,
 {
 	u32 *addr = (u32 *)(unsigned long)entry->code;
 
-	if (type == JUMP_LABEL_ENABLE)
+	if (type != jump_label_default_branch(entry))
 		patch_branch(addr, entry->target, 0);
 	else
 		patch_instruction(addr, PPC_INST_NOP);
diff --git a/arch/s390/include/asm/jump_label.h b/arch/s390/include/asm/jump_label.h
index 346b1c8..5259b49 100644
--- a/arch/s390/include/asm/jump_label.h
+++ b/arch/s390/include/asm/jump_label.h
@@ -13,17 +13,20 @@
 #define ASM_ALIGN ".balign 4"
 #endif
 
-static __always_inline bool arch_static_branch(struct static_key *key)
+struct static_key;
+
+static __always_inline bool arch_static_branch(struct static_key *key,
+		const bool default_branch)
 {
 	asm_volatile_goto("0:	brcl 0,0\n"
 		".pushsection __jump_table, \"aw\"\n"
 		ASM_ALIGN "\n"
-		ASM_PTR " 0b, %l[label], %0\n"
+		ASM_PTR " 0b, %l[label], %0, %1\n"
 		".popsection\n"
-		: : "X" (key) : : label);
-	return false;
+		: : "X" (key), "X" (default_branch) : : label);
+	return default_branch;
 label:
-	return true;
+	return !default_branch;
 }
 
 typedef unsigned long jump_label_t;
@@ -32,6 +35,12 @@ struct jump_entry {
 	jump_label_t code;
 	jump_label_t target;
 	jump_label_t key;
+	union {
+		jump_label_t flags;
+		struct {
+			unsigned default_branch:1; /* lsb */
+		};
+	};
 };
 
 #endif
diff --git a/arch/s390/kernel/jump_label.c b/arch/s390/kernel/jump_label.c
index b987ab2..95958c5 100644
--- a/arch/s390/kernel/jump_label.c
+++ b/arch/s390/kernel/jump_label.c
@@ -28,7 +28,7 @@ static void __jump_label_transform(struct jump_entry *entry,
 	struct insn insn;
 	int rc;
 
-	if (type == JUMP_LABEL_ENABLE) {
+	if (type != jump_label_default_branch(entry)) {
 		/* brcl 15,offset */
 		insn.opcode = 0xc0f4;
 		insn.offset = (entry->target - entry->code) >> 1;
diff --git a/arch/sparc/include/asm/jump_label.h b/arch/sparc/include/asm/jump_label.h
index ec2e2e2..67b763d 100644
--- a/arch/sparc/include/asm/jump_label.h
+++ b/arch/sparc/include/asm/jump_label.h
@@ -7,19 +7,22 @@
 
 #define JUMP_LABEL_NOP_SIZE 4
 
-static __always_inline bool arch_static_branch(struct static_key *key)
+struct static_key;
+
+static __always_inline bool arch_static_branch(struct static_key *key,
+		const bool default_branch)
 {
 		asm_volatile_goto("1:\n\t"
 			 "nop\n\t"
 			 "nop\n\t"
 			 ".pushsection __jump_table,  \"aw\"\n\t"
 			 ".align 4\n\t"
-			 ".word 1b, %l[l_yes], %c0\n\t"
+			 ".word 1b, %l[l_yes], %c0, %c1\n\t"
 			 ".popsection \n\t"
-			 : :  "i" (key) : : l_yes);
-	return false;
+			 : :  "i" (key), "i" (default_branch) : : l_yes);
+	return default_branch;
 l_yes:
-	return true;
+	return !default_branch;
 }
 
 #endif /* __KERNEL__ */
@@ -30,6 +33,12 @@ struct jump_entry {
 	jump_label_t code;
 	jump_label_t target;
 	jump_label_t key;
+	union {
+		jump_label_t flags;
+		struct {
+			unsigned default_branch:1; /* lsb */
+		};
+	};
 };
 
 #endif
diff --git a/arch/sparc/kernel/jump_label.c b/arch/sparc/kernel/jump_label.c
index 48565c1..c963a9c 100644
--- a/arch/sparc/kernel/jump_label.c
+++ b/arch/sparc/kernel/jump_label.c
@@ -16,7 +16,7 @@ void arch_jump_label_transform(struct jump_entry *entry,
 	u32 val;
 	u32 *insn = (u32 *) (unsigned long) entry->code;
 
-	if (type == JUMP_LABEL_ENABLE) {
+	if (type != jump_label_default_branch(entry)) {
 		s32 off = (s32)entry->target - (s32)entry->code;
 
 #ifdef CONFIG_SPARC64
diff --git a/arch/x86/include/asm/jump_label.h b/arch/x86/include/asm/jump_label.h
index 6a2cefb..18e192e 100644
--- a/arch/x86/include/asm/jump_label.h
+++ b/arch/x86/include/asm/jump_label.h
@@ -16,18 +16,21 @@
 # define STATIC_KEY_INIT_NOP GENERIC_NOP5_ATOMIC
 #endif
 
-static __always_inline bool arch_static_branch(struct static_key *key)
+struct static_key;
+
+static __always_inline bool arch_static_branch(struct static_key *key,
+		const bool default_branch)
 {
 	asm_volatile_goto("1:"
 		".byte " __stringify(STATIC_KEY_INIT_NOP) "\n\t"
 		".pushsection __jump_table,  \"aw\" \n\t"
 		_ASM_ALIGN "\n\t"
-		_ASM_PTR "1b, %l[l_yes], %c0 \n\t"
+		_ASM_PTR "1b, %l[l_yes], %c0, %c1 \n\t"
 		".popsection \n\t"
-		: :  "i" (key) : : l_yes);
-	return false;
+		: :  "i" (key), "i" (default_branch) : : l_yes);
+	return default_branch;
 l_yes:
-	return true;
+	return !default_branch;
 }
 
 #endif /* __KERNEL__ */
@@ -42,6 +45,12 @@ struct jump_entry {
 	jump_label_t code;
 	jump_label_t target;
 	jump_label_t key;
+	union {
+		jump_label_t flags;
+		struct {
+			unsigned default_branch:1; /* lsb */
+		};
+	};
 };
 
 #endif
diff --git a/arch/x86/kernel/jump_label.c b/arch/x86/kernel/jump_label.c
index ee11b7d..8b66855 100644
--- a/arch/x86/kernel/jump_label.c
+++ b/arch/x86/kernel/jump_label.c
@@ -43,13 +43,15 @@ static void __jump_label_transform(struct jump_entry *entry,
 {
 	union jump_code_union code;
 	const unsigned char *ideal_nop = ideal_nops[NOP_ATOMIC5];
+	const unsigned char default_nop[] = { STATIC_KEY_INIT_NOP };
 
-	if (type == JUMP_LABEL_ENABLE) {
+	if (type != jump_label_default_branch(entry)) {
 		/*
 		 * We are enabling this jump label. If it is not a nop
 		 * then something must have gone wrong.
 		 */
-		if (unlikely(memcmp((void *)entry->code, ideal_nop, 5) != 0))
+		if (unlikely(memcmp((void *)entry->code,
+		                    init ? default_nop : ideal_nop, 5) != 0))
 			bug_at((void *)entry->code, __LINE__);
 
 		code.jump = 0xe9;
@@ -63,7 +65,6 @@ static void __jump_label_transform(struct jump_entry *entry,
 		 * are converting the default nop to the ideal nop.
 		 */
 		if (init) {
-			const unsigned char default_nop[] = { STATIC_KEY_INIT_NOP };
 			if (unlikely(memcmp((void *)entry->code, default_nop, 5) != 0))
 				bug_at((void *)entry->code, __LINE__);
 		} else {
@@ -101,33 +102,10 @@ void arch_jump_label_transform(struct jump_entry *entry,
 	put_online_cpus();
 }
 
-static enum {
-	JL_STATE_START,
-	JL_STATE_NO_UPDATE,
-	JL_STATE_UPDATE,
-} jlstate __initdata_or_module = JL_STATE_START;
-
 __init_or_module void arch_jump_label_transform_static(struct jump_entry *entry,
 				      enum jump_label_type type)
 {
-	/*
-	 * This function is called at boot up and when modules are
-	 * first loaded. Check if the default nop, the one that is
-	 * inserted at compile time, is the ideal nop. If it is, then
-	 * we do not need to update the nop, and we can leave it as is.
-	 * If it is not, then we need to update the nop to the ideal nop.
-	 */
-	if (jlstate == JL_STATE_START) {
-		const unsigned char default_nop[] = { STATIC_KEY_INIT_NOP };
-		const unsigned char *ideal_nop = ideal_nops[NOP_ATOMIC5];
-
-		if (memcmp(ideal_nop, default_nop, 5) != 0)
-			jlstate = JL_STATE_UPDATE;
-		else
-			jlstate = JL_STATE_NO_UPDATE;
-	}
-	if (jlstate == JL_STATE_UPDATE)
-		__jump_label_transform(entry, type, text_poke_early, 1);
+	__jump_label_transform(entry, type, text_poke_early, 1);
 }
 
 #endif
diff --git a/include/linux/jump_label.h b/include/linux/jump_label.h
index 848bd15..a06791c 100644
--- a/include/linux/jump_label.h
+++ b/include/linux/jump_label.h
@@ -10,7 +10,8 @@
  * Jump labels provide an interface to generate dynamic branches using
  * self-modifying code. Assuming toolchain and architecture support the result
  * of a "if (static_key_false(&key))" statement is a unconditional branch (which
- * defaults to false - and the true block is placed out of line).
+ * defaults to false - and the true block is placed out of line,
+ * static_key_true(&key) has default to true)
  *
  * However at runtime we can change the branch target using
  * static_key_slow_{inc,dec}(). These function as a 'reference' count on the key
@@ -32,17 +33,9 @@
  * Lacking toolchain and or architecture support, it falls back to a simple
  * conditional branch.
  *
- * struct static_key my_key = STATIC_KEY_INIT_TRUE;
- *
- *   if (static_key_true(&my_key)) {
- *   }
- *
- * will result in the true case being in-line and starts the key with a single
- * reference. Mixing static_key_true() and static_key_false() on the same key is not
- * allowed.
- *
- * Not initializing the key (static data is initialized to 0s anyway) is the
- * same as using STATIC_KEY_INIT_FALSE.
+ * Initial count can be set by STATIC_KEY_INIT(x), defaults to 0, but it takes
+ * effect after jump_label_init() has finished, so static_key_enabled() must be
+ * used instead of static_key_{true,false} before.
  *
 */
 
@@ -53,7 +46,6 @@
 
 struct static_key {
 	atomic_t enabled;
-/* Set lsb bit to 1 if branch is default true, 0 ot */
 	struct jump_entry *entries;
 #ifdef CONFIG_MODULES
 	struct static_key_mod *next;
@@ -75,30 +67,20 @@ struct module;
 #include <linux/atomic.h>
 #ifdef HAVE_JUMP_LABEL
 
-#define JUMP_LABEL_TRUE_BRANCH 1UL
-
 static
 inline struct jump_entry *jump_label_get_entries(struct static_key *key)
 {
-	return (struct jump_entry *)((unsigned long)key->entries
-						& ~JUMP_LABEL_TRUE_BRANCH);
-}
-
-static inline bool jump_label_get_branch_default(struct static_key *key)
-{
-	if ((unsigned long)key->entries & JUMP_LABEL_TRUE_BRANCH)
-		return true;
-	return false;
+	return (struct jump_entry *)((unsigned long)key->entries);
 }
 
 static __always_inline bool static_key_false(struct static_key *key)
 {
-	return arch_static_branch(key);
+	return arch_static_branch(key, false);
 }
 
 static __always_inline bool static_key_true(struct static_key *key)
 {
-	return !static_key_false(key);
+	return arch_static_branch(key, true);
 }
 
 extern struct jump_entry __start___jump_table[];
@@ -116,10 +98,13 @@ extern void static_key_slow_inc(struct static_key *key);
 extern void static_key_slow_dec(struct static_key *key);
 extern void jump_label_apply_nops(struct module *mod);
 
-#define STATIC_KEY_INIT_TRUE ((struct static_key) \
-	{ .enabled = ATOMIC_INIT(1), .entries = (void *)1 })
-#define STATIC_KEY_INIT_FALSE ((struct static_key) \
-	{ .enabled = ATOMIC_INIT(0), .entries = (void *)0 })
+/* this function does not exactly belong here, but it is the path of least
+ * resistance; refactoring will move it into arch specific code */
+static inline enum jump_label_type
+jump_label_default_branch(struct jump_entry *entry) {
+	return entry->default_branch ? JUMP_LABEL_ENABLE
+	                             : JUMP_LABEL_DISABLE;
+}
 
 #else  /* !HAVE_JUMP_LABEL */
 
@@ -168,14 +153,12 @@ static inline int jump_label_apply_nops(struct module *mod)
 	return 0;
 }
 
-#define STATIC_KEY_INIT_TRUE ((struct static_key) \
-		{ .enabled = ATOMIC_INIT(1) })
-#define STATIC_KEY_INIT_FALSE ((struct static_key) \
-		{ .enabled = ATOMIC_INIT(0) })
-
 #endif	/* HAVE_JUMP_LABEL */
 
-#define STATIC_KEY_INIT STATIC_KEY_INIT_FALSE
+#define STATIC_KEY_INIT(x) ((struct static_key) { .enabled = ATOMIC_INIT(x) })
+#define STATIC_KEY_INIT_TRUE  STATIC_KEY_INIT(1)
+#define STATIC_KEY_INIT_FALSE STATIC_KEY_INIT(0)
+
 #define jump_label_enabled static_key_enabled
 
 static inline bool static_key_enabled(struct static_key *key)
diff --git a/kernel/jump_label.c b/kernel/jump_label.c
index 30aa3b0..3670c0e 100644
--- a/kernel/jump_label.c
+++ b/kernel/jump_label.c
@@ -63,10 +63,7 @@ void static_key_slow_inc(struct static_key *key)
 
 	jump_label_lock();
 	if (atomic_read(&key->enabled) == 0) {
-		if (!jump_label_get_branch_default(key))
-			jump_label_update(key, JUMP_LABEL_ENABLE);
-		else
-			jump_label_update(key, JUMP_LABEL_DISABLE);
+		jump_label_update(key, JUMP_LABEL_ENABLE);
 	}
 	atomic_inc(&key->enabled);
 	jump_label_unlock();
@@ -98,10 +95,7 @@ static void __static_key_slow_dec(struct static_key *key,
 			WARN(1, "jump label: negative deferred count!\n");
 		}
 	} else {
-		if (!jump_label_get_branch_default(key))
-			jump_label_update(key, JUMP_LABEL_DISABLE);
-		else
-			jump_label_update(key, JUMP_LABEL_ENABLE);
+		jump_label_update(key, JUMP_LABEL_DISABLE);
 	}
 	jump_label_unlock();
 }
@@ -189,13 +183,8 @@ static void __jump_label_update(struct static_key *key,
 
 static enum jump_label_type jump_label_type(struct static_key *key)
 {
-	bool true_branch = jump_label_get_branch_default(key);
-	bool state = static_key_enabled(key);
-
-	if ((!true_branch && state) || (true_branch && !state))
-		return JUMP_LABEL_ENABLE;
-
-	return JUMP_LABEL_DISABLE;
+	return static_key_enabled(key) ? JUMP_LABEL_ENABLE
+	                               : JUMP_LABEL_DISABLE;
 }
 
 static void static_key_rate_limit_flush(struct static_key *key)
@@ -225,10 +214,7 @@ void __init jump_label_init(void)
 			continue;
 
 		key = iterk;
-		/*
-		 * Set key->entries to iter, but preserve JUMP_LABEL_TRUE_BRANCH.
-		 */
-		*((unsigned long *)&key->entries) += (unsigned long)iter;
+		*((unsigned long *)&key->entries) = (unsigned long)iter;
 #ifdef CONFIG_MODULES
 		key->next = NULL;
 #endif
@@ -319,10 +305,7 @@ static int jump_label_add_module(struct module *mod)
 
 		key = iterk;
 		if (__module_address(iter->key) == mod) {
-			/*
-			 * Set key->entries to iter, but preserve JUMP_LABEL_TRUE_BRANCH.
-			 */
-			*((unsigned long *)&key->entries) += (unsigned long)iter;
+			*((unsigned long *)&key->entries) = (unsigned long)iter;
 			key->next = NULL;
 			continue;
 		}
-- 
1.8.3.1

^ permalink raw reply related

* Re: [PATCHv1 0/8] ALSA: Add SAI driver and enable SGT15000 codec.
From: Lothar Waßmann @ 2013-10-17 10:22 UTC (permalink / raw)
  To: Xiubo Li
  Cc: mark.rutland, alsa-devel, linux-doc, tiwai, b18965, timur, perex,
	r65073, linux, b42378, linux-arm-kernel, grant.likely, devicetree,
	ian.campbell, pawel.moll, swarren, rob.herring, broonie, oskar,
	fabio.estevam, lgirdwood, linux-kernel, rob, r64188, shawn.guo,
	linuxppc-dev
In-Reply-To: <1382000477-17304-1-git-send-email-Li.Xiubo@freescale.com>

Hi,

Xiubo Li <Li.Xiubo@freescale.com> wrote:

The subject has a wrong name for the codec "SGT1..." instead of
"SGTL...", which will make it difficult to search for this thread in
mail archives or in commit messages once this patches should be applied!


Lothar Wa=C3=9Fmann
--=20
___________________________________________________________

Ka-Ro electronics GmbH | Pascalstra=C3=9Fe 22 | D - 52076 Aachen
Phone: +49 2408 1402-0 | Fax: +49 2408 1402-10
Gesch=C3=A4ftsf=C3=BChrer: Matthias Kaussen
Handelsregistereintrag: Amtsgericht Aachen, HRB 4996

www.karo-electronics.de | info@karo-electronics.de
___________________________________________________________

^ permalink raw reply

* Re: [PATCH] powerpc/vio: Fix modalias_show return values
From: Prarit Bhargava @ 2013-10-17 11:50 UTC (permalink / raw)
  To: Ben Hutchings; +Cc: linuxppc-dev, stable
In-Reply-To: <1381982024.3267.14.camel@deadeye.wl.decadent.org.uk>



On 10/16/2013 11:53 PM, Ben Hutchings wrote:
> Commit e82b89a6f19bae73fb064d1b3dd91fcefbb478f4 introduces a trivial
> local denial of service.
> 
>> --- a/arch/powerpc/kernel/vio.c
>> +++ b/arch/powerpc/kernel/vio.c
>> @@ -1351,11 +1351,15 @@ static ssize_t modalias_show(struct devi
>>  	const char *cp;
>>  
>>  	dn = dev->of_node;
>> -	if (!dn)
>> -		return -ENODEV;
>> +	if (!dn) {
>> +		strcat(buf, "\n");
> 
> Every read from the same sysfs file handle uses the same buffer, which
> gets zero-initialised just once.  So if I open the file, read it and
> seek back to 0 repeatedly, I can make modalias_show() write arbitrary
> numbers of newlines into *and beyond* that page-sized buffer.
> 
> Obviously strcat() should be strcpy().
> 

D'oh!  Of course -- I wasn't thinking clearly about that.  I'll send out a new
patch.

P.

> Ben.
> 
>> +		return strlen(buf);
>> +	}
>>  	cp = of_get_property(dn, "compatible", NULL);
>> -	if (!cp)
>> -		return -ENODEV;
>> +	if (!cp) {
>> +		strcat(buf, "\n");
>> +		return strlen(buf);
>> +	}
>>  
>>  	return sprintf(buf, "vio:T%sS%s\n", vio_dev->type, cp);
>>  }
> 

^ permalink raw reply

* [PATCH] [PATCH] powerpc/vio: use strcpy in modalias_show
From: Prarit Bhargava @ 2013-10-17 12:00 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Prarit Bhargava, ben, stable

Commit e82b89a6f19bae73fb064d1b3dd91fcefbb478f4 used strcat instead of
strcpy which can result in an overflow of newlines on the buffer.

Signed-off-by: Prarit Bhargava
Cc: benh@kernel.crashing.org
Cc: ben@decadent.org.uk
Cc: stable@vger.kernel.org
---
 arch/powerpc/kernel/vio.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c
index d38cc08..cb92d82 100644
--- a/arch/powerpc/kernel/vio.c
+++ b/arch/powerpc/kernel/vio.c
@@ -1531,12 +1531,12 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
 
 	dn = dev->of_node;
 	if (!dn) {
-		strcat(buf, "\n");
+		strcpy(buf, "\n");
 		return strlen(buf);
 	}
 	cp = of_get_property(dn, "compatible", NULL);
 	if (!cp) {
-		strcat(buf, "\n");
+		strcpy(buf, "\n");
 		return strlen(buf);
 	}
 
-- 
1.7.9.3

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox