Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2] firmware: qcom: scm: Fix incorrect of_node_put call in scm_init
From: Stephen Boyd @ 2017-12-08 17:04 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <c049d689-44f0-3ee6-ca50-af4873545fce@baylibre.com>

On 12/07, Loys Ollivier wrote:
> 
> 
> On 07/12/2017 09:42, Jerome Forissier wrote:
> > 
> > 
> > On 12/06/2017 09:06 PM, Stephen Boyd wrote:
> >> On 12/06, Loys Ollivier wrote:
> >>> When using other platform architectures, in the init of the qcom_scm
> >>> driver, of_node_put is called on /firmware if no qcom dt is found.
> >>> This results in a kernel error: Bad of_node_put() on /firmware.
> >>>
> >>> The call to of_node_put from the qcom_scm init is unnecessary as
> >>> of_find_matching_node is calling it automatically.
> >>>
> >>> Remove this of_node_put().
> >>>
> >>> Fixes: d0f6fa7ba2d6 ("firmware: qcom: scm: Convert SCM to platform driver")
> >>> Signed-off-by: Loys Ollivier <lollivier@baylibre.com>
> >>> ---
> >>
> >> This still looks wrong. Especially if of_find_matching_node() is
> >> going to look for siblings of the /firmware node for the
> >> compatible string for scm device. Why do we check at all? Can't
> >> we just delete this and let of_platform_populate() take care of
> >> it? BTW, OP-TEE driver seems to have a similar problem.
> > 
> > https://lkml.org/lkml/2017/11/29/230
> >
> Well, the patch I sent is a fix for a specific bug I am encountering.
> I tested the patch and it solves my problem. Stephen, your changes looks
> good but it's a change in the driver's behavior. Maybe it could be
> another patch ?

Sure. But there's another of_node_put(fw_np) in this function, so
why isn't that also removed? Assuming of_find_matching_node() is
calling of_node_put() on what's passed in, then the node is going
to get put twice in the "working" case.

Andy?

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

^ permalink raw reply

* next/master boot: 270 boots: 35 failed, 213 passed with 20 offline, 2 untried/unknown (next-20171207)
From: Stephen Boyd @ 2017-12-08 16:59 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <7ad6d330-d277-85ae-b891-cb76367461ce@samsung.com>

On 12/08, Marek Szyprowski wrote:
> Hi Krzysztof,
> 
> On 2017-12-08 13:33, Krzysztof Kozlowski wrote:
> >On Fri, Dec 8, 2017 at 1:27 PM, Mark Brown <broonie@kernel.org> wrote:
> >>On Fri, Dec 08, 2017 at 12:20:07PM +0000, Mark Brown wrote:
> >>>On Thu, Dec 07, 2017 at 03:54:47PM -0800, kernelci.org bot wrote:
> >>>
> >>>Today's -next failed to boot on peach-pi:
> >>>
> >>>>     exynos_defconfig:
> >>>>         exynos5800-peach-pi:
> >>>>             lab-collabora: new failure (last pass: next-20171205)
> >>>with details at https://kernelci.org/boot/id/5a2a2e7859b5141bc2afa17c/
> >>>(including logs and comparisons with other boots, the last good boot was
> >>>Wednesday).  It looks like it hangs somewhere late on in boot, the last
> >>>output on the console is:
> >>>
> >>>[    4.827139] smsc95xx 3-1.1:1.0 eth0: register 'smsc95xx' at usb-xhci-hcd.3.auto-1.1, smsc95xx USB 2.0 Ethernet, 94:eb:2c:00:03:c0
> >>>[    5.781037] dma-pl330 3880000.adma: Loaded driver for PL330 DMAC-241330
> >>>[    5.786247] dma-pl330 3880000.adma:        DBUFF-4x8bytes Num_Chans-6 Num_Peri-16 Num_Events-6
> >>>[    5.819200] dma-pl330 3880000.adma: PM domain MAU will not be powered off
> >>>[   64.529228] random: crng init done
> >>>
> >>>and there's failures earlier to instantiate the display.
> >>I just noticed that further up the log there's a lockdep splat with a
> >>conflict between the genpd and clock API locking - an ABBA issue with
> >>genpd->mlock and the clock API prepare_lock.
> >+Cc Marek Szyprowski,
> >
> >The lockdep issue and display failures (including regulator warning)
> >were present for some time. They also appear in boot log for
> >next-20171206 (https://storage.kernelci.org/next/master/next-20171206/arm/exynos_defconfig/lab-collabora/boot-exynos5800-peach-pi.html).
> >The difference is that 20171208 hangs on "random: crng init done"
> >which did not appear before at all.

I haven't looked at the lockdep splat yet, but is that happening
because of runtime PM usage by the clk framework?

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

^ permalink raw reply

* [PATCH v3 07/16] KVM: Move vcpu_load to arch-specific kvm_arch_vcpu_ioctl_set_sregs
From: David Hildenbrand @ 2017-12-08 16:26 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20171204203538.8370-8-cdall@kernel.org>


>  
>  int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
> diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c
> index f647e121070e..cdf0be02c95a 100644
> --- a/arch/powerpc/kvm/booke.c
> +++ b/arch/powerpc/kvm/booke.c
> @@ -1632,18 +1632,25 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
>  {
>  	int ret;
>  
> +	vcpu_load(vcpu);
> +
> +	ret = -EINVAL;

you can initialize this directly.

>  	if (vcpu->arch.pvr != sregs->pvr)
> -		return -EINVAL;
> +		goto out;
>  
>  	ret = set_sregs_base(vcpu, sregs);
>  	if (ret < 0)
> -		return ret;
> +		goto out;
>  
>  	ret = set_sregs_arch206(vcpu, sregs);
>  	if (ret < 0)
> -		return ret;
> +		goto out;
> +
> +	ret = vcpu->kvm->arch.kvm_ops->set_sregs(vcpu, sregs);
>  
> -	return vcpu->kvm->arch.kvm_ops->set_sregs(vcpu, sregs);
> +out:
> +	vcpu_put(vcpu);
> +	return ret;
>  }
>  
>  int kvmppc_get_one_reg(struct kvm_vcpu *vcpu, u64 id,
> diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
> index 18011fc4ac49..d95b4f15e52b 100644
> --- a/arch/s390/kvm/kvm-s390.c
> +++ b/arch/s390/kvm/kvm-s390.c
> @@ -2729,8 +2729,12 @@ int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
>  int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
>  				  struct kvm_sregs *sregs)
>  {
> +	vcpu_load(vcpu);
> +
>  	memcpy(&vcpu->run->s.regs.acrs, &sregs->acrs, sizeof(sregs->acrs));
>  	memcpy(&vcpu->arch.sie_block->gcr, &sregs->crs, sizeof(sregs->crs));
> +
> +	vcpu_put(vcpu);
>  	return 0;
>  }
>  
> diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
> index 20a5f6776eea..a31a80aee0b9 100644
> --- a/arch/x86/kvm/x86.c
> +++ b/arch/x86/kvm/x86.c
> @@ -7500,15 +7500,19 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
>  	int mmu_reset_needed = 0;
>  	int pending_vec, max_bits, idx;
>  	struct desc_ptr dt;
> +	int ret;
> +
> +	vcpu_load(vcpu);
>  
> +	ret = -EINVAL;

dito


Reviewed-by: David Hildenbrand <david@redhat.com>

-- 

Thanks,

David / dhildenb

^ permalink raw reply

* [PATCH v3 06/16] KVM: Move vcpu_load to arch-specific kvm_arch_vcpu_ioctl_get_sregs
From: David Hildenbrand @ 2017-12-08 16:23 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20171204203538.8370-7-cdall@kernel.org>

On 04.12.2017 21:35, Christoffer Dall wrote:
> From: Christoffer Dall <christoffer.dall@linaro.org>
> 
> Move vcpu_load() and vcpu_put() into the architecture specific
> implementations of kvm_arch_vcpu_ioctl_get_sregs().
> 
> Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
> ---
>  arch/powerpc/kvm/book3s.c | 8 +++++++-
>  arch/powerpc/kvm/booke.c  | 9 ++++++++-
>  arch/s390/kvm/kvm-s390.c  | 4 ++++
>  arch/x86/kvm/x86.c        | 3 +++
>  virt/kvm/kvm_main.c       | 2 --
>  5 files changed, 22 insertions(+), 4 deletions(-)
> 
> diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c
> index 24bc7aabfc44..6cc2377549f7 100644
> --- a/arch/powerpc/kvm/book3s.c
> +++ b/arch/powerpc/kvm/book3s.c
> @@ -484,7 +484,13 @@ void kvmppc_subarch_vcpu_uninit(struct kvm_vcpu *vcpu)
>  int kvm_arch_vcpu_ioctl_get_sregs(struct kvm_vcpu *vcpu,
>  				  struct kvm_sregs *sregs)
>  {
> -	return vcpu->kvm->arch.kvm_ops->get_sregs(vcpu, sregs);
> +	int ret;
> +
> +	vcpu_load(vcpu);
> +	ret = vcpu->kvm->arch.kvm_ops->get_sregs(vcpu, sregs);
> +	vcpu_put(vcpu);
> +
> +	return ret;
>  }
>  
>  int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
> diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c
> index bcbbeddc3430..f647e121070e 100644
> --- a/arch/powerpc/kvm/booke.c
> +++ b/arch/powerpc/kvm/booke.c
> @@ -1613,11 +1613,18 @@ int kvmppc_set_sregs_ivor(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs)
>  int kvm_arch_vcpu_ioctl_get_sregs(struct kvm_vcpu *vcpu,
>                                    struct kvm_sregs *sregs)
>  {
> +	int ret;
> +
> +	vcpu_load(vcpu);
> +
>  	sregs->pvr = vcpu->arch.pvr;
>  
>  	get_sregs_base(vcpu, sregs);
>  	get_sregs_arch206(vcpu, sregs);
> -	return vcpu->kvm->arch.kvm_ops->get_sregs(vcpu, sregs);
> +	ret = vcpu->kvm->arch.kvm_ops->get_sregs(vcpu, sregs);
> +
> +	vcpu_put(vcpu);
> +	return ret;
>  }
>  
>  int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
> diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
> index e3476430578a..18011fc4ac49 100644
> --- a/arch/s390/kvm/kvm-s390.c
> +++ b/arch/s390/kvm/kvm-s390.c
> @@ -2737,8 +2737,12 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
>  int kvm_arch_vcpu_ioctl_get_sregs(struct kvm_vcpu *vcpu,
>  				  struct kvm_sregs *sregs)
>  {
> +	vcpu_load(vcpu);
> +
>  	memcpy(&sregs->acrs, &vcpu->run->s.regs.acrs, sizeof(sregs->acrs));
>  	memcpy(&sregs->crs, &vcpu->arch.sie_block->gcr, sizeof(sregs->crs));
> +
> +	vcpu_put(vcpu);
>  	return 0;
>  }
>  
> diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
> index 75eacce78f59..20a5f6776eea 100644
> --- a/arch/x86/kvm/x86.c
> +++ b/arch/x86/kvm/x86.c
> @@ -7400,6 +7400,8 @@ int kvm_arch_vcpu_ioctl_get_sregs(struct kvm_vcpu *vcpu,
>  {
>  	struct desc_ptr dt;
>  
> +	vcpu_load(vcpu);
> +
>  	kvm_get_segment(vcpu, &sregs->cs, VCPU_SREG_CS);
>  	kvm_get_segment(vcpu, &sregs->ds, VCPU_SREG_DS);
>  	kvm_get_segment(vcpu, &sregs->es, VCPU_SREG_ES);
> @@ -7431,6 +7433,7 @@ int kvm_arch_vcpu_ioctl_get_sregs(struct kvm_vcpu *vcpu,
>  		set_bit(vcpu->arch.interrupt.nr,
>  			(unsigned long *)sregs->interrupt_bitmap);
>  
> +	vcpu_put(vcpu);
>  	return 0;
>  }
>  
> diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
> index 963e249d7b79..779c03e39fa4 100644
> --- a/virt/kvm/kvm_main.c
> +++ b/virt/kvm/kvm_main.c
> @@ -2581,9 +2581,7 @@ static long kvm_vcpu_ioctl(struct file *filp,
>  		r = -ENOMEM;
>  		if (!kvm_sregs)
>  			goto out;
> -		vcpu_load(vcpu);
>  		r = kvm_arch_vcpu_ioctl_get_sregs(vcpu, kvm_sregs);
> -		vcpu_put(vcpu);
>  		if (r)
>  			goto out;
>  		r = -EFAULT;
> 

Reviewed-by: David Hildenbrand <david@redhat.com>

-- 

Thanks,

David / dhildenb

^ permalink raw reply

* [PATCH v3 05/16] KVM: Move vcpu_load to arch-specific kvm_arch_vcpu_ioctl_set_regs
From: David Hildenbrand @ 2017-12-08 16:22 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20171204203538.8370-6-cdall@kernel.org>

On 04.12.2017 21:35, Christoffer Dall wrote:
> From: Christoffer Dall <christoffer.dall@linaro.org>
> 
> Move vcpu_load() and vcpu_put() into the architecture specific
> implementations of kvm_arch_vcpu_ioctl_set_regs().
> 
> Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
> ---
>  arch/mips/kvm/mips.c      | 3 +++
>  arch/powerpc/kvm/book3s.c | 3 +++
>  arch/powerpc/kvm/booke.c  | 3 +++
>  arch/s390/kvm/kvm-s390.c  | 2 ++
>  arch/x86/kvm/x86.c        | 3 +++
>  virt/kvm/kvm_main.c       | 2 --
>  6 files changed, 14 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/mips/kvm/mips.c b/arch/mips/kvm/mips.c
> index adfca57420d1..3a898712d6cd 100644
> --- a/arch/mips/kvm/mips.c
> +++ b/arch/mips/kvm/mips.c
> @@ -1151,6 +1151,8 @@ int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
>  {
>  	int i;
>  
> +	vcpu_load(vcpu);
> +
>  	for (i = 1; i < ARRAY_SIZE(vcpu->arch.gprs); i++)
>  		vcpu->arch.gprs[i] = regs->gpr[i];
>  	vcpu->arch.gprs[0] = 0; /* zero is special, and cannot be set. */
> @@ -1158,6 +1160,7 @@ int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
>  	vcpu->arch.lo = regs->lo;
>  	vcpu->arch.pc = regs->pc;
>  
> +	vcpu_put(vcpu);
>  	return 0;
>  }
>  
> diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c
> index d85bfd733ccd..24bc7aabfc44 100644
> --- a/arch/powerpc/kvm/book3s.c
> +++ b/arch/powerpc/kvm/book3s.c
> @@ -528,6 +528,8 @@ int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
>  {
>  	int i;
>  
> +	vcpu_load(vcpu);
> +
>  	kvmppc_set_pc(vcpu, regs->pc);
>  	kvmppc_set_cr(vcpu, regs->cr);
>  	kvmppc_set_ctr(vcpu, regs->ctr);
> @@ -548,6 +550,7 @@ int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
>  	for (i = 0; i < ARRAY_SIZE(regs->gpr); i++)
>  		kvmppc_set_gpr(vcpu, i, regs->gpr[i]);
>  
> +	vcpu_put(vcpu);
>  	return 0;
>  }
>  
> diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c
> index e0e4f04c5535..bcbbeddc3430 100644
> --- a/arch/powerpc/kvm/booke.c
> +++ b/arch/powerpc/kvm/booke.c
> @@ -1462,6 +1462,8 @@ int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
>  {
>  	int i;
>  
> +	vcpu_load(vcpu);
> +
>  	vcpu->arch.pc = regs->pc;
>  	kvmppc_set_cr(vcpu, regs->cr);
>  	vcpu->arch.ctr = regs->ctr;
> @@ -1483,6 +1485,7 @@ int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
>  	for (i = 0; i < ARRAY_SIZE(regs->gpr); i++)
>  		kvmppc_set_gpr(vcpu, i, regs->gpr[i]);
>  
> +	vcpu_put(vcpu);
>  	return 0;
>  }
>  
> diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
> index 37b7caae2484..e3476430578a 100644
> --- a/arch/s390/kvm/kvm-s390.c
> +++ b/arch/s390/kvm/kvm-s390.c
> @@ -2712,7 +2712,9 @@ static int kvm_arch_vcpu_ioctl_initial_reset(struct kvm_vcpu *vcpu)
>  
>  int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
>  {
> +	vcpu_load(vcpu);
>  	memcpy(&vcpu->run->s.regs.gprs, &regs->gprs, sizeof(regs->gprs));
> +	vcpu_put(vcpu);
>  	return 0;
>  }
>  
> diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
> index 597e1f8fc8da..75eacce78f59 100644
> --- a/arch/x86/kvm/x86.c
> +++ b/arch/x86/kvm/x86.c
> @@ -7350,6 +7350,8 @@ int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
>  
>  int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
>  {
> +	vcpu_load(vcpu);
> +
>  	vcpu->arch.emulate_regs_need_sync_from_vcpu = true;
>  	vcpu->arch.emulate_regs_need_sync_to_vcpu = false;
>  
> @@ -7379,6 +7381,7 @@ int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
>  
>  	kvm_make_request(KVM_REQ_EVENT, vcpu);
>  
> +	vcpu_put(vcpu);
>  	return 0;
>  }
>  
> diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
> index 843d481f58cb..963e249d7b79 100644
> --- a/virt/kvm/kvm_main.c
> +++ b/virt/kvm/kvm_main.c
> @@ -2572,9 +2572,7 @@ static long kvm_vcpu_ioctl(struct file *filp,
>  			r = PTR_ERR(kvm_regs);
>  			goto out;
>  		}
> -		vcpu_load(vcpu);
>  		r = kvm_arch_vcpu_ioctl_set_regs(vcpu, kvm_regs);
> -		vcpu_put(vcpu);
>  		kfree(kvm_regs);
>  		break;
>  	}
> 

Reviewed-by: David Hildenbrand <david@redhat.com>

-- 

Thanks,

David / dhildenb

^ permalink raw reply

* [PATCH v3 04/16] KVM: Move vcpu_load to arch-specific kvm_arch_vcpu_ioctl_get_regs
From: David Hildenbrand @ 2017-12-08 16:21 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20171204203538.8370-5-cdall@kernel.org>

On 04.12.2017 21:35, Christoffer Dall wrote:
> From: Christoffer Dall <christoffer.dall@linaro.org>
> 
> Move vcpu_load() and vcpu_put() into the architecture specific
> implementations of kvm_arch_vcpu_ioctl_get_regs().
> 
> Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
> ---
>  arch/mips/kvm/mips.c      | 3 +++
>  arch/powerpc/kvm/book3s.c | 3 +++
>  arch/powerpc/kvm/booke.c  | 3 +++
>  arch/s390/kvm/kvm-s390.c  | 2 ++
>  arch/x86/kvm/x86.c        | 3 +++
>  virt/kvm/kvm_main.c       | 2 --
>  6 files changed, 14 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/mips/kvm/mips.c b/arch/mips/kvm/mips.c
> index b5c28f0730f8..adfca57420d1 100644
> --- a/arch/mips/kvm/mips.c
> +++ b/arch/mips/kvm/mips.c
> @@ -1165,6 +1165,8 @@ int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
>  {
>  	int i;
>  
> +	vcpu_load(vcpu);
> +
>  	for (i = 0; i < ARRAY_SIZE(vcpu->arch.gprs); i++)
>  		regs->gpr[i] = vcpu->arch.gprs[i];
>  
> @@ -1172,6 +1174,7 @@ int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
>  	regs->lo = vcpu->arch.lo;
>  	regs->pc = vcpu->arch.pc;
>  
> +	vcpu_put(vcpu);
>  	return 0;
>  }
>  
> diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c
> index 72d977e30952..d85bfd733ccd 100644
> --- a/arch/powerpc/kvm/book3s.c
> +++ b/arch/powerpc/kvm/book3s.c
> @@ -497,6 +497,8 @@ int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
>  {
>  	int i;
>  
> +	vcpu_load(vcpu);
> +
>  	regs->pc = kvmppc_get_pc(vcpu);
>  	regs->cr = kvmppc_get_cr(vcpu);
>  	regs->ctr = kvmppc_get_ctr(vcpu);
> @@ -518,6 +520,7 @@ int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
>  	for (i = 0; i < ARRAY_SIZE(regs->gpr); i++)
>  		regs->gpr[i] = kvmppc_get_gpr(vcpu, i);
>  
> +	vcpu_put(vcpu);
>  	return 0;
>  }
>  
> diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c
> index 83b485810aea..e0e4f04c5535 100644
> --- a/arch/powerpc/kvm/booke.c
> +++ b/arch/powerpc/kvm/booke.c
> @@ -1431,6 +1431,8 @@ int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
>  {
>  	int i;
>  
> +	vcpu_load(vcpu);
> +
>  	regs->pc = vcpu->arch.pc;
>  	regs->cr = kvmppc_get_cr(vcpu);
>  	regs->ctr = vcpu->arch.ctr;
> @@ -1452,6 +1454,7 @@ int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
>  	for (i = 0; i < ARRAY_SIZE(regs->gpr); i++)
>  		regs->gpr[i] = kvmppc_get_gpr(vcpu, i);
>  
> +	vcpu_put(vcpu);
>  	return 0;
>  }
>  
> diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
> index 2b3e874ea76c..37b7caae2484 100644
> --- a/arch/s390/kvm/kvm-s390.c
> +++ b/arch/s390/kvm/kvm-s390.c
> @@ -2718,7 +2718,9 @@ int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
>  
>  int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
>  {
> +	vcpu_load(vcpu);
>  	memcpy(&regs->gprs, &vcpu->run->s.regs.gprs, sizeof(regs->gprs));
> +	vcpu_put(vcpu);
>  	return 0;
>  }
>  
> diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
> index d9deb6222055..597e1f8fc8da 100644
> --- a/arch/x86/kvm/x86.c
> +++ b/arch/x86/kvm/x86.c
> @@ -7309,6 +7309,8 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
>  
>  int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
>  {
> +	vcpu_load(vcpu);
> +
>  	if (vcpu->arch.emulate_regs_need_sync_to_vcpu) {
>  		/*
>  		 * We are here if userspace calls get_regs() in the middle of
> @@ -7342,6 +7344,7 @@ int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
>  	regs->rip = kvm_rip_read(vcpu);
>  	regs->rflags = kvm_get_rflags(vcpu);
>  
> +	vcpu_put(vcpu);
>  	return 0;
>  }
>  
> diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
> index 198f2f9edcaf..843d481f58cb 100644
> --- a/virt/kvm/kvm_main.c
> +++ b/virt/kvm/kvm_main.c
> @@ -2552,9 +2552,7 @@ static long kvm_vcpu_ioctl(struct file *filp,
>  		kvm_regs = kzalloc(sizeof(struct kvm_regs), GFP_KERNEL);
>  		if (!kvm_regs)
>  			goto out;
> -		vcpu_load(vcpu);
>  		r = kvm_arch_vcpu_ioctl_get_regs(vcpu, kvm_regs);
> -		vcpu_put(vcpu);
>  		if (r)
>  			goto out_free1;
>  		r = -EFAULT;
> 

Reviewed-by: David Hildenbrand <david@redhat.com>

-- 

Thanks,

David / dhildenb

^ permalink raw reply

* [Patch v6 05/12] [media] videodev2.h: Add v4l2 definition for HEVC
From: Mauro Carvalho Chehab @ 2017-12-08 16:07 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1512748044.24635.1.camel@ndufresne.ca>

Em Fri, 08 Dec 2017 10:47:24 -0500
Nicolas Dufresne <nicolas@ndufresne.ca> escreveu:

> Le vendredi 08 d?cembre 2017 ? 14:38 +0530, Smitha T Murthy a ?crit :
> > Add V4L2 definition for HEVC compressed format
> > 
> > Signed-off-by: Smitha T Murthy <smitha.t@samsung.com>
> > Reviewed-by: Andrzej Hajda <a.hajda@samsung.com>
> > Reviewed-by: Stanimir Varbanov <stanimir.varbanov@linaro.org>
> > Acked-by: Hans Verkuil <hans.verkuil@cisco.com>
> > ---
> >  include/uapi/linux/videodev2.h | 1 +
> >  1 file changed, 1 insertion(+)
> > 
> > diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
> > index 185d6a0..bd9b5d5 100644
> > --- a/include/uapi/linux/videodev2.h
> > +++ b/include/uapi/linux/videodev2.h
> > @@ -634,6 +634,7 @@ struct v4l2_pix_format {
> >  #define V4L2_PIX_FMT_VC1_ANNEX_L v4l2_fourcc('V', 'C', '1', 'L') /* SMPTE 421M Annex L compliant stream */
> >  #define V4L2_PIX_FMT_VP8      v4l2_fourcc('V', 'P', '8', '0') /* VP8 */
> >  #define V4L2_PIX_FMT_VP9      v4l2_fourcc('V', 'P', '9', '0') /* VP9 */
> > +#define V4L2_PIX_FMT_HEVC     v4l2_fourcc('H', 'E', 'V', 'C') /* HEVC aka H.265 */  
> 
> Wouldn't it be more consistent to call it V4L2_PIX_FMT_H265 as we have
> used H264 for the previous generation, or is there a formal rationale ?

It would, but what I'm afraid on using specs name here, due to what
happened with MPEG-4 specs. Originally, it was referred to one codec
(ASP). Then, part 10 came with a different compression codec (AVC). So,
now, when referring to MPEG-4, one need to explicitly mention if the code
is AVC or not. The ITU-T didn't make the same mistake (yet?), but nobody
can predict what will happen in the future.

So, now that an spec can be modified to include additional parts with
different codecs, it sounds less risky to use the codec name instead
of the spec number, as this shouldn't change :-)

> Also, this is byte-stream right ? With start codes ?

> 
> >  
> >  /*  Vendor-specific formats   */
> >  #define V4L2_PIX_FMT_CPIA1    v4l2_fourcc('C', 'P', 'I', 'A') /* cpia1 YUV */  



Thanks,
Mauro

^ permalink raw reply

* [PATCH 0/2] acpi, x86: Add SPCR table support
From: Prarit Bhargava @ 2017-12-08 16:02 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <bd727a15-c697-741f-864b-8b48b8e5e272@codeaurora.org>



On 12/08/2017 10:31 AM, Jeffrey Hugo wrote:
> On 12/8/2017 7:29 AM, Prarit Bhargava wrote:
>>
>>
>> On 12/08/2017 01:29 AM, Ingo Molnar wrote:
>>>
>>> * Prarit Bhargava <prarit@redhat.com> wrote:
>>>
>>>> The SPCR (Serial Port Console Redirection) Table provides information
>>>> about the configuration of serial port.  This information can be used
>>>> to configure the early console.
>>>
>>> s/about the configuration of serial port
>>>   /about the configuration of the serial port
>>>
>>>> SPCR support was added for arm64 and is made available across all arches
>>>> in this patchset.  The first patch adds a weak per-arch configuration function
>>>> and moves the SPCR code into ACPI.  The second patch adds support to x86.
>>>>
>>>> The existing behaviour on arm64 is maintained.  If the SPCR exists the
>>>> earlycon and console are automatically configured.
>>>
>>> s/arm64
>>>   /ARM64
>>>
>>> which is easier to read and it's also the prevalent spelling:
>>>
>>>   triton:~/tip> for N in $(git grep -ih arm64 arch/arm64/ | sed
>>> 's/[[:punct:]]/ /g'); do echo $N | grep -iw arm64; done | sort | uniq -c
>>>       412 arm64
>>>         1 Arm64
>>>       854 ARM64
>>>
>>>> The existing default behaviour on x86 is also maintained.  If no console or
>>>> earlycon parameter is defined and the SPCR exists , the serial port is not
>>>> configured.  If the earlycon parameter is used both the early console
>>>> and the console are configured using the data from the SPCR.
>>>
>>> s/exists , the
>>>   /exists, the
>>>
>>> But, the logic to not use the SPCR looks confusing to me.
>>>
>>> The SPCR is only present if the user has explicitly configured a serial console
>>> for that machine, either in the firmware, or remotely via IPMI, correct? I.e.
>>> SPCR
>>> will not be spuriously present by default on systems that have a serial console
>>> but the user never expressed any interest for them, right?
>>
>> If I disable "Serial Port Console Debug" in my BIOS I still see the SPCR
>> configured:
>>
>> [root at prarit-lab ~]# dmesg | grep SPCR
>> [    0.000000] ACPI: SPCR 0x0000000069031000 000050 (v01
>> 00000000      00000000)
>>
>> AFAICT the SPCR is always enabled on some systems.
> 
> "Serial Port Console Debug" sounds like DBG2 to me, although I am unsure of the
> specific platform you are referencing.
> 
>>
>>>
>>> If so then we should pick up that serial console configuration and activate it,
>>> regardless of any kernel boot options!
>>
>> I'm worried about someone who doesn't want a console on ttyS0 suddenly ending up
>> with one.  The SPCR could contain incorrect data, etc.
>>
>> I originally wanted this on by default, but the chances of breaking someone's
>> setup seems significant doesn't it?  Maybe I'm being too cautious.  Anyone else
>> want to weigh in?  I'm not ignoring your idea Ingo, I'm just worried about being
>> yelled at by a user :) because I broke their default console setup.
>>
> 
> SPCR is always present on QDF2400 (ARM64 platform).  Firmware will automatically
> update the SPCR table to point to the correct console (IE Serial-over-LAN or SOL
> if configured via IPMI).  Unless a user specifically chooses to override the
> SPCR via "console=", we expect that a console will be present based on the data
> in SPCR.

Hey Jeffrey -- I think Ingo's & my conversation is x86-specific.  I am *NOT*
changing the behaviour on ARM64.

P.

> 

^ permalink raw reply

* [RESEND PATCH V2] ARM: dts: introduce the sama5d2 ptc ek board
From: Alexandre Belloni @ 2017-12-08 15:57 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20171207082453.10593-1-ludovic.desroches@microchip.com>

On 07/12/2017 at 09:24:53 +0100, Ludovic Desroches wrote:
> Add the official SAMA5D2 Peripheral Touch Controller Evaluation
> Kit board.
> 
> Signed-off-by: Ludovic Desroches <ludovic.desroches@microchip.com>
> ---
> Resend: Put SPDX-License-Identifier at the beginning of the file.
> 
> Changes:
> - v2:
>   - remove memory node
>   - use SPDX-License-Identifier
> 
>  arch/arm/boot/dts/Makefile                |   1 +
>  arch/arm/boot/dts/at91-sama5d2_ptc_ek.dts | 401 ++++++++++++++++++++++++++++++
>  2 files changed, 402 insertions(+)
>  create mode 100644 arch/arm/boot/dts/at91-sama5d2_ptc_ek.dts
> 
Applied, thanks.

-- 
Alexandre Belloni, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com

^ permalink raw reply

* [PATCH] dt-bindings: pinctrl: stm32: fix copyright and adopt SPDX identifier
From: Alexandre Torgue @ 2017-12-08 15:53 UTC (permalink / raw)
  To: linux-arm-kernel

Add missing copyright and add SPDX identifier.

Signed-off-by: Alexandre Torgue <alexandre.torgue@st.com>

diff --git a/include/dt-bindings/pinctrl/stm32-pinfunc.h b/include/dt-bindings/pinctrl/stm32-pinfunc.h
index b8dfe31..b5a2174 100644
--- a/include/dt-bindings/pinctrl/stm32-pinfunc.h
+++ b/include/dt-bindings/pinctrl/stm32-pinfunc.h
@@ -1,3 +1,9 @@
+/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
+/*
+ * Copyright (C) STMicroelectronics 2017 - All Rights Reserved
+ * Author: Torgue Alexandre <alexandre.torgue@st.com> for STMicroelectronics.
+ */
+
 #ifndef _DT_BINDINGS_STM32_PINFUNC_H
 #define _DT_BINDINGS_STM32_PINFUNC_H
 
-- 
2.7.4

^ permalink raw reply related

* [Patch v6 05/12] [media] videodev2.h: Add v4l2 definition for HEVC
From: Nicolas Dufresne @ 2017-12-08 15:47 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1512724105-1778-6-git-send-email-smitha.t@samsung.com>

Le vendredi 08 d?cembre 2017 ? 14:38 +0530, Smitha T Murthy a ?crit :
> Add V4L2 definition for HEVC compressed format
> 
> Signed-off-by: Smitha T Murthy <smitha.t@samsung.com>
> Reviewed-by: Andrzej Hajda <a.hajda@samsung.com>
> Reviewed-by: Stanimir Varbanov <stanimir.varbanov@linaro.org>
> Acked-by: Hans Verkuil <hans.verkuil@cisco.com>
> ---
>  include/uapi/linux/videodev2.h | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
> index 185d6a0..bd9b5d5 100644
> --- a/include/uapi/linux/videodev2.h
> +++ b/include/uapi/linux/videodev2.h
> @@ -634,6 +634,7 @@ struct v4l2_pix_format {
>  #define V4L2_PIX_FMT_VC1_ANNEX_L v4l2_fourcc('V', 'C', '1', 'L') /* SMPTE 421M Annex L compliant stream */
>  #define V4L2_PIX_FMT_VP8      v4l2_fourcc('V', 'P', '8', '0') /* VP8 */
>  #define V4L2_PIX_FMT_VP9      v4l2_fourcc('V', 'P', '9', '0') /* VP9 */
> +#define V4L2_PIX_FMT_HEVC     v4l2_fourcc('H', 'E', 'V', 'C') /* HEVC aka H.265 */

Wouldn't it be more consistent to call it V4L2_PIX_FMT_H265 as we have
used H264 for the previous generation, or is there a formal rationale ?
Also, this is byte-stream right ? With start codes ?

>  
>  /*  Vendor-specific formats   */
>  #define V4L2_PIX_FMT_CPIA1    v4l2_fourcc('C', 'P', 'I', 'A') /* cpia1 YUV */
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 195 bytes
Desc: This is a digitally signed message part
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20171208/8fe4280d/attachment-0001.sig>

^ permalink raw reply

* [PATCH net-next v4 0/2] net: thunderx: add support for PTP clock
From: Richard Cochran @ 2017-12-08 15:45 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20171208103442.19354-1-aleksey.makarov@cavium.com>

On Fri, Dec 08, 2017 at 01:34:38PM +0300, Aleksey Makarov wrote:
> This series adds support for IEEE 1588 Precision Time Protocol
> to Cavium ethernet driver.
> 
> The first patch adds support for the Precision Time Protocol Clocks and
> Timestamping coprocessor (PTP) found on Cavium processors.
> It registers a new PTP clock in the PTP core and provides functions
> to use the counter in BGX, TNS, GTI, and NIC blocks.
> 
> The second patch introduces support for the PTP protocol to the
> Cavium ThunderX ethernet driver.
> 
> v4:
> - use IS_ENABLED. This fixes compilation of the ptp as a module (David Miller)
> - select PTP_1588_CLOCK, not depend on it.  This fixes a build warning.

It should be "imply" not "select".

Thanks,
Richard

^ permalink raw reply

* [RFC PATCH 2/5] perf jevents: add support for arch recommended events
From: John Garry @ 2017-12-08 15:42 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20171208122918.GE2799@krava>

On 08/12/2017 12:29, Jiri Olsa wrote:
> On Wed, Dec 06, 2017 at 03:20:14PM +0000, John Garry wrote:
>> On 06/12/2017 13:36, Jiri Olsa wrote:
>>> On Wed, Dec 06, 2017 at 12:13:16AM +0800, John Garry wrote:
>>>> For some architectures (like arm64), there are architecture-
>>>> defined recommended events. Vendors may not be obliged to
>>>> follow the recommendation and may implement their own pmu
>>>> event for a specific event code.
>>>>
>>>> This patch adds support for parsing events from arch-defined
>>>> recommended JSONs, and then fixing up vendor events when
>>>> they have implemented these events as recommended.
>>>
>>> in the previous patch you added the vendor support, so
>>> you have arch|vendor|platform key for the event list
>>> and perf have the most current/local event list
>>>
>>> why would you need to fix it? if there's new event list,
>>> the table gets updated, perf is rebuilt.. I'm clearly
>>> missing something ;-)
>>
>> The 2 patches are quite separate. In the first patch, I just added support
>> for the vendor subdirectory.
>>
>> So this patch is not related to rebuilding when adding a new event list or
>> dependency checking.
>>
>> Here we are trying to allow the vendor to just specify that an event is
>> supported as standard in their platform, without duplicating all the
>> standard event fields in their JSON. When processing the vendor JSONs, the
>> jevents tool can figure which events are standard and create the proper
>> event entries in the pmu events table, referencing the architecture JSON.
>

Hi jirka,

> I think we should keep this simple and mangle this with some pointer logic
>
> now you have arch/vendor/platform directory structure..

I'm glad that there seems to be no objection to this, as I feel that 
this was a problem.

why don't
> you add events for every such directory? I understand there will
> be duplications, but we already have them for other archs and it's
> not big deal:

The amount of duplication was the concern. As mentioned earlier, it 
would be anticipated that every vendor would implement these events as 
recommended, so a copy for every platform from every vendor. We're 
looking for a way to avoid this.

Actually having a scalable JSON standard format for pmu events, which 
allows us to define common events per architecture / vendor and 
reference them per platform JSON could be useful.

Here we're dealing with trade-off between duplication (simplicity) vs 
complexity (or over-engineering).

>
> 	[jolsa at krava perf]$ grep -r L2_RQSTS.DEMAND_DATA_RD_MISS pmu-events/arch/*
> 	pmu-events/arch/x86/broadwell/cache.json:        "EventName": "L2_RQSTS.DEMAND_DATA_RD_MISS",
> 	pmu-events/arch/x86/haswell/cache.json:        "EventName": "L2_RQSTS.DEMAND_DATA_RD_MISS",
> 	pmu-events/arch/x86/broadwellde/cache.json:        "EventName": "L2_RQSTS.DEMAND_DATA_RD_MISS",
> 	pmu-events/arch/x86/haswellx/cache.json:        "EventName": "L2_RQSTS.DEMAND_DATA_RD_MISS",
> 	pmu-events/arch/x86/skylake/cache.json:        "EventName": "L2_RQSTS.DEMAND_DATA_RD_MISS",
> 	pmu-events/arch/x86/skylakex/cache.json:        "EventName": "L2_RQSTS.DEMAND_DATA_RD_MISS",
> 	pmu-events/arch/x86/broadwellx/cache.json:        "EventName": "L2_RQSTS.DEMAND_DATA_RD_MISS",
>
> thanks,
> jirka

Cheers,
John

>
> .
>

^ permalink raw reply

* [PATCH v1 1/6] ARM: davinci: clean up map_io functions
From: Sekhar Nori @ 2017-12-08 15:38 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1512182054-17410-2-git-send-email-david@lechnology.com>

On Saturday 02 December 2017 08:04 AM, David Lechner wrote:
>  static int dm355leopard_mmc_get_cd(int module)
>  {
>  	if (!gpio_is_valid(leopard_mmc_gpio))
> @@ -269,7 +264,7 @@ static __init void dm355_leopard_init(void)
>  
>  MACHINE_START(DM355_LEOPARD, "DaVinci DM355 leopard")
>  	.atag_offset  = 0x100,
> -	.map_io	      = dm355_leopard_map_io,
> +	.map_io		= dm355_map_io,
>  	.init_irq     = davinci_irq_init,
>  	.init_time	= davinci_timer_init,
>  	.init_machine = dm355_leopard_init,

It seems like spaces were used in original code for indentation. Can you
please introduce a patch to fix that first since you are now touching
this part of the code?

Thanks,
Sekhar

^ permalink raw reply

* [RFC PATCH 2/5] perf jevents: add support for arch recommended events
From: John Garry @ 2017-12-08 15:38 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20171208123137.GF2799@krava>

On 08/12/2017 12:31, Jiri Olsa wrote:
> On Wed, Dec 06, 2017 at 02:40:10PM +0000, John Garry wrote:
>> On 06/12/2017 13:37, Jiri Olsa wrote:
>>> On Wed, Dec 06, 2017 at 12:13:16AM +0800, John Garry wrote:
>>>
>>> SNIP
>>>
>>>> ---
>>>>  tools/perf/pmu-events/jevents.c | 215 ++++++++++++++++++++++++++++++++++++----
>>>>  1 file changed, 198 insertions(+), 17 deletions(-)
>>>>
>>>> diff --git a/tools/perf/pmu-events/jevents.c b/tools/perf/pmu-events/jevents.c
>>>> index a0d489e..a820ed4 100644
>>>> --- a/tools/perf/pmu-events/jevents.c
>>>> +++ b/tools/perf/pmu-events/jevents.c
>>>> @@ -42,6 +42,7 @@
>>>>  #include <dirent.h>
>>>>  #include <sys/time.h>			/* getrlimit */
>>>>  #include <sys/resource.h>		/* getrlimit */
>>>> +#include <sys/queue.h>
>>>>  #include <ftw.h>
>>>>  #include <sys/stat.h>
>>>>  #include "jsmn.h"
>>>> @@ -366,6 +367,94 @@ static int print_events_table_entry(void *data, char *name, char *event,
>>>>  	return 0;
>>>>  }
>>>>
>>>> +struct event_struct {
>>>> +	char *name;
>>>> +	char *event;
>>>> +	char *desc;
>>>> +	char *long_desc;
>>>> +	char *pmu;
>>>> +	char *unit;
>>>> +	char *perpkg;
>>>> +	char *metric_expr;
>>>> +	char *metric_name;
>>>> +	char *metric_group;
>>>> +	LIST_ENTRY(event_struct) list;
>>>
>>> is there any reason you don't use the 'struct list_head' ?
>>> I dont think we want another thingie involved for lists
>>
>> Hi jirka,
>>

Hi jirka,

>> The linux kernel headers are not used for jevents tool. I would rather use
>> them if possible...
>
> should be as easy as adding  #include <linux/list.h> ;-)
>

Hi jirka,

I think the issue is that jevents is a "hostprogs", which does not use 
kernel headers.

FWIW, here is the symptom:
pmu-events/jevents.c:51:24: fatal error: linux/list.h: No such file or 
directory
  #include <linux/list.h>
                         ^
compilation terminated.
mv: cannot stat ?pmu-events/.jevents.o.tmp?: No such file or directory

perf tool build is different.

Much appreciated,
John


> it's heavily used within perf and I'm pretty sure we want
> to keep around just one way of doing lists
>
> thanks,
> jirka
>
> .
>

^ permalink raw reply

* [PATCH v1 1/6] ARM: davinci: clean up map_io functions
From: Sekhar Nori @ 2017-12-08 15:34 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <2e3b9ef7-b9ee-a6b7-bc67-e3dbd6119f48@lechnology.com>

On Thursday 07 December 2017 10:44 PM, David Lechner wrote:
> On 12/07/2017 08:52 AM, Sekhar Nori wrote:
>> On Saturday 02 December 2017 08:04 AM, David Lechner wrote:
>>> This cleans up the map_io functions in the board init files for
>>> mach-davinci.
>>>
>>> Most of the boards had a wrapper function around <board>_init(). This
>>> wrapper is removed and the function is used directly. Additionally, the
>>> <board>_init() functions are renamed to <board>_map_io() to match the
>>> field name.
>>>
>>> Signed-off-by: David Lechner <david@lechnology.com>
>>
>>> diff --git a/arch/arm/mach-davinci/board-dm646x-evm.c
>>> b/arch/arm/mach-davinci/board-dm646x-evm.c
>>> index cb0a41e..f0e2762 100644
>>> --- a/arch/arm/mach-davinci/board-dm646x-evm.c
>>> +++ b/arch/arm/mach-davinci/board-dm646x-evm.c
>>> @@ -716,16 +716,6 @@ static void __init evm_init_i2c(void)
>>> ? }
>>> ? #endif
>>> ? -#define DM6467T_EVM_REF_FREQ??????? 33000000
>>> -
>>> -static void __init davinci_map_io(void)
>>> -{
>>> -??? dm646x_init();
>>
>> The call to dm646x_init() is dropped here, but I don't see it added
>> back, at least in this patch.
> 
> dm646x_init() is renamed to dm646x_map_io(), which is used directly in
> MACHINE_START().

Ah, I missed that. But I think its a symptom of too many things going on
in the patch. How about splitting the patch to:

a) Remove trivial <board>_map_io() wrappers and use <soc>_init()
directly to initialize .map_io

b) Rename <soc>_init() to <soc>_map_io

> 
>>
>>> diff --git a/arch/arm/mach-davinci/dm646x.c
>>> b/arch/arm/mach-davinci/dm646x.c
>>> index da21353..b3be5c8 100644
>>> --- a/arch/arm/mach-davinci/dm646x.c
>>> +++ b/arch/arm/mach-davinci/dm646x.c
>>> @@ -17,6 +17,7 @@
>>> ? #include <linux/platform_data/edma.h>
>>> ? #include <linux/platform_data/gpio-davinci.h>
>>> ? +#include <asm/mach-types.h>
>>> ? #include <asm/mach/map.h>
>>> ? ? #include <mach/cputype.h>
>>> @@ -952,11 +953,16 @@ int __init dm646x_init_edma(struct
>>> edma_rsv_info *rsv)
>>> ????? return IS_ERR(edma_pdev) ? PTR_ERR(edma_pdev) : 0;
>>> ? }
>>> ? -void __init dm646x_init(void)
>>> +#define DM6467T_EVM_REF_FREQ??????? 33000000
>>> +
>>> +void __init dm646x_map_io(void)
>>> ? {
>>> ????? davinci_common_init(&davinci_soc_info_dm646x);
>>> ????? davinci_map_sysmod();
>>> ????? davinci_clk_init(davinci_soc_info_dm646x.cpu_clks);
>>> +
>>> +??? if (machine_is_davinci_dm6467tevm())
>>> +??????? davinci_set_refclk_rate(DM6467T_EVM_REF_FREQ);
>>> ? }
>>
>> I think we should leave the DM646x case out of this since there are
>> additional issues like introducing these EVM specific defines in a file
>> meant for SoC.
> 
> I agree with the sentiment. This quirk gets moved around several times
> in this series just to keep things working for a git bisect even if it
> is not the ideal place for it to be.
> 
> Currently, all boards use a common reference frequency from the common
> SoC files instead of the board file. I have not done so in this version
> of the series, but I could rework it so that this happens, which would
> remove the need for this quirk altogether. But even then, it would
> probably get shuffled around a bit before being eliminated.

We should avoid shuffling and modifying the same code repeatedly if we
can. I think, it will be easier to read if patch 2 and 1 are interchanged.

There is a lot going on and I wasn't sure how that will look so I tried
it briefly and pushed a branch.

Do have a look, but this seems better to me.

https://git.kernel.org/pub/scm/linux/kernel/git/nsekhar/linux-davinci.git/log/?h=for-davidl

Thanks,
Sekhar

^ permalink raw reply

* [PATCH 0/2] acpi, x86: Add SPCR table support
From: Jeffrey Hugo @ 2017-12-08 15:31 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <f078ada7-1e30-41cc-28dc-077ed2a5986d@redhat.com>

On 12/8/2017 7:29 AM, Prarit Bhargava wrote:
> 
> 
> On 12/08/2017 01:29 AM, Ingo Molnar wrote:
>>
>> * Prarit Bhargava <prarit@redhat.com> wrote:
>>
>>> The SPCR (Serial Port Console Redirection) Table provides information
>>> about the configuration of serial port.  This information can be used
>>> to configure the early console.
>>
>> s/about the configuration of serial port
>>   /about the configuration of the serial port
>>
>>> SPCR support was added for arm64 and is made available across all arches
>>> in this patchset.  The first patch adds a weak per-arch configuration function
>>> and moves the SPCR code into ACPI.  The second patch adds support to x86.
>>>
>>> The existing behaviour on arm64 is maintained.  If the SPCR exists the
>>> earlycon and console are automatically configured.
>>
>> s/arm64
>>   /ARM64
>>
>> which is easier to read and it's also the prevalent spelling:
>>
>>   triton:~/tip> for N in $(git grep -ih arm64 arch/arm64/ | sed 's/[[:punct:]]/ /g'); do echo $N | grep -iw arm64; done | sort | uniq -c
>>       412 arm64
>>         1 Arm64
>>       854 ARM64
>>
>>> The existing default behaviour on x86 is also maintained.  If no console or
>>> earlycon parameter is defined and the SPCR exists , the serial port is not
>>> configured.  If the earlycon parameter is used both the early console
>>> and the console are configured using the data from the SPCR.
>>
>> s/exists , the
>>   /exists, the
>>
>> But, the logic to not use the SPCR looks confusing to me.
>>
>> The SPCR is only present if the user has explicitly configured a serial console
>> for that machine, either in the firmware, or remotely via IPMI, correct? I.e. SPCR
>> will not be spuriously present by default on systems that have a serial console
>> but the user never expressed any interest for them, right?
> 
> If I disable "Serial Port Console Debug" in my BIOS I still see the SPCR configured:
> 
> [root at prarit-lab ~]# dmesg | grep SPCR
> [    0.000000] ACPI: SPCR 0x0000000069031000 000050 (v01
> 00000000      00000000)
> 
> AFAICT the SPCR is always enabled on some systems.

"Serial Port Console Debug" sounds like DBG2 to me, although I am unsure 
of the specific platform you are referencing.

> 
>>
>> If so then we should pick up that serial console configuration and activate it,
>> regardless of any kernel boot options!
> 
> I'm worried about someone who doesn't want a console on ttyS0 suddenly ending up
> with one.  The SPCR could contain incorrect data, etc.
> 
> I originally wanted this on by default, but the chances of breaking someone's
> setup seems significant doesn't it?  Maybe I'm being too cautious.  Anyone else
> want to weigh in?  I'm not ignoring your idea Ingo, I'm just worried about being
> yelled at by a user :) because I broke their default console setup.
> 

SPCR is always present on QDF2400 (ARM64 platform).  Firmware will 
automatically update the SPCR table to point to the correct console (IE 
Serial-over-LAN or SOL if configured via IPMI).  Unless a user 
specifically chooses to override the SPCR via "console=", we expect that 
a console will be present based on the data in SPCR.

-- 
Jeffrey Hugo
Qualcomm Datacenter Technologies as an affiliate of Qualcomm 
Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the
Code Aurora Forum, a Linux Foundation Collaborative Project.

^ permalink raw reply

* [PATCH] pinctrl: meson-axg: adjust spicc pin naming
From: Yixun Lan @ 2017-12-08 15:29 UTC (permalink / raw)
  To: linux-arm-kernel

According to datasheet, we should use numbers for the pin naming
instead of letters. The patch here try to fix this to keep
the consistency.

This patch should not bring any functional change.

Fixes: 83c566806a68 ("pinctrl: meson-axg: Add new pinctrl driver for Meson AXG SoC")
Suggested-by: Kevin Hilman <khilman@baylibre.com>
Signed-off-by: Yixun Lan <yixun.lan@amlogic.com>

---
The issue was raised by Kevin while review the SPI DT part patches, see [1]
[1] http://lists.infradead.org/pipermail/linux-amlogic/2017-December/005641.html

Note: the 'Fixes' is coming from pinctrl's tree 'for-next' branch
---
 drivers/pinctrl/meson/pinctrl-meson-axg.c | 86 +++++++++++++++----------------
 1 file changed, 43 insertions(+), 43 deletions(-)

diff --git a/drivers/pinctrl/meson/pinctrl-meson-axg.c b/drivers/pinctrl/meson/pinctrl-meson-axg.c
index a1a7d42afd42..1fda9d6c7ea3 100644
--- a/drivers/pinctrl/meson/pinctrl-meson-axg.c
+++ b/drivers/pinctrl/meson/pinctrl-meson-axg.c
@@ -156,25 +156,25 @@ static const unsigned int sdio_d3_pins[] = {GPIOX_3};
 static const unsigned int sdio_clk_pins[] = {GPIOX_4};
 static const unsigned int sdio_cmd_pins[] = {GPIOX_5};
 
-/* spi_a */
-static const unsigned int spi_clk_a_pins[] = {GPIOZ_0};
-static const unsigned int spi_mosi_a_pins[] = {GPIOZ_1};
-static const unsigned int spi_miso_a_pins[] = {GPIOZ_2};
-static const unsigned int spi_ss0_a_pins[] = {GPIOZ_3};
-static const unsigned int spi_ss1_a_pins[] = {GPIOZ_4};
-static const unsigned int spi_ss2_a_pins[] = {GPIOZ_5};
-
-/* spi_b */
-static const unsigned int spi_clk_b_x_pins[] = {GPIOX_19};
-static const unsigned int spi_mosi_b_x_pins[] = {GPIOX_17};
-static const unsigned int spi_miso_b_x_pins[] = {GPIOX_18};
-static const unsigned int spi_ss0_b_x_pins[] = {GPIOX_16};
-
-static const unsigned int spi_clk_b_a_pins[] = {GPIOA_4};
-static const unsigned int spi_mosi_b_a_pins[] = {GPIOA_2};
-static const unsigned int spi_miso_b_a_pins[] = {GPIOA_3};
-static const unsigned int spi_ss0_b_a_pins[] = {GPIOA_5};
-static const unsigned int spi_ss1_b_pins[] = {GPIOA_6};
+/* spi0 */
+static const unsigned int spi0_clk_pins[] = {GPIOZ_0};
+static const unsigned int spi0_mosi_pins[] = {GPIOZ_1};
+static const unsigned int spi0_miso_pins[] = {GPIOZ_2};
+static const unsigned int spi0_ss0_pins[] = {GPIOZ_3};
+static const unsigned int spi0_ss1_pins[] = {GPIOZ_4};
+static const unsigned int spi0_ss2_pins[] = {GPIOZ_5};
+
+/* spi1 */
+static const unsigned int spi1_clk_x_pins[] = {GPIOX_19};
+static const unsigned int spi1_mosi_x_pins[] = {GPIOX_17};
+static const unsigned int spi1_miso_x_pins[] = {GPIOX_18};
+static const unsigned int spi1_ss0_x_pins[] = {GPIOX_16};
+
+static const unsigned int spi1_clk_a_pins[] = {GPIOA_4};
+static const unsigned int spi1_mosi_a_pins[] = {GPIOA_2};
+static const unsigned int spi1_miso_a_pins[] = {GPIOA_3};
+static const unsigned int spi1_ss0_a_pins[] = {GPIOA_5};
+static const unsigned int spi1_ss1_pins[] = {GPIOA_6};
 
 /* i2c0 */
 static const unsigned int i2c0_sck_pins[] = {GPIOZ_6};
@@ -429,12 +429,12 @@ static struct meson_pmx_group meson_axg_periphs_groups[] = {
 	GROUP(nor_cs, 3),
 
 	/* bank GPIOZ */
-	GROUP(spi_clk_a, 1),
-	GROUP(spi_mosi_a, 1),
-	GROUP(spi_miso_a, 1),
-	GROUP(spi_ss0_a, 1),
-	GROUP(spi_ss1_a, 1),
-	GROUP(spi_ss2_a, 1),
+	GROUP(spi0_clk, 1),
+	GROUP(spi0_mosi, 1),
+	GROUP(spi0_miso, 1),
+	GROUP(spi0_ss0, 1),
+	GROUP(spi0_ss1, 1),
+	GROUP(spi0_ss2, 1),
 	GROUP(i2c0_sck, 1),
 	GROUP(i2c0_sda, 1),
 	GROUP(i2c1_sck_z, 1),
@@ -475,10 +475,10 @@ static struct meson_pmx_group meson_axg_periphs_groups[] = {
 	GROUP(jtag_tdi_x, 2),
 	GROUP(jtag_clk_x, 2),
 	GROUP(jtag_tms_x, 2),
-	GROUP(spi_clk_b_x, 4),
-	GROUP(spi_mosi_b_x, 4),
-	GROUP(spi_miso_b_x, 4),
-	GROUP(spi_ss0_b_x, 4),
+	GROUP(spi1_clk_x, 4),
+	GROUP(spi1_mosi_x, 4),
+	GROUP(spi1_miso_x, 4),
+	GROUP(spi1_ss0_x, 4),
 	GROUP(pwm_a_x18, 3),
 	GROUP(pwm_a_x20, 1),
 	GROUP(pwm_b_x, 3),
@@ -521,11 +521,11 @@ static struct meson_pmx_group meson_axg_periphs_groups[] = {
 	GROUP(spdif_in_a7, 3),
 	GROUP(spdif_in_a19, 1),
 	GROUP(spdif_in_a20, 2),
-	GROUP(spi_clk_b_a, 3),
-	GROUP(spi_mosi_b_a, 3),
-	GROUP(spi_miso_b_a, 3),
-	GROUP(spi_ss0_b_a, 3),
-	GROUP(spi_ss1_b, 3),
+	GROUP(spi1_clk_a, 3),
+	GROUP(spi1_mosi_a, 3),
+	GROUP(spi1_miso_a, 3),
+	GROUP(spi1_ss0_a, 3),
+	GROUP(spi1_ss1, 3),
 	GROUP(pwm_a_a, 3),
 	GROUP(pwm_b_a, 3),
 	GROUP(pwm_c_a, 3),
@@ -696,15 +696,15 @@ static const char * const sdio_groups[] = {
 	"sdio_cmd", "sdio_clk",
 };
 
-static const char * const spi_a_groups[] = {
-	"spi_clk_a", "spi_mosi_a", "spi_miso_a", "spi_ss0_a",
-	"spi_ss1_a", "spi_ss2_a"
+static const char * const spi0_groups[] = {
+	"spi0_clk", "spi0_mosi", "spi0_miso", "spi0_ss0",
+	"spi0_ss1", "spi0_ss2"
 };
 
-static const char * const spi_b_groups[] = {
-	"spi_clk_b_x", "spi_mosi_b_x", "spi_miso_b_x", "spi_ss0_b_x",
-	"spi_clk_b_a", "spi_mosi_b_a", "spi_miso_b_a", "spi_ss0_b_a",
-	"spi_ss1_b"
+static const char * const spi1_groups[] = {
+	"spi1_clk_x", "spi1_mosi_x", "spi1_miso_x", "spi1_ss0_x",
+	"spi1_clk_a", "spi1_mosi_a", "spi1_miso_a", "spi1_ss0_a",
+	"spi1_ss1"
 };
 
 static const char * const uart_a_groups[] = {
@@ -849,8 +849,8 @@ static struct meson_pmx_func meson_axg_periphs_functions[] = {
 	FUNCTION(gpio_periphs),
 	FUNCTION(emmc),
 	FUNCTION(nor),
-	FUNCTION(spi_a),
-	FUNCTION(spi_b),
+	FUNCTION(spi0),
+	FUNCTION(spi1),
 	FUNCTION(sdio),
 	FUNCTION(nand),
 	FUNCTION(uart_a),
-- 
2.15.1

^ permalink raw reply related

* [PATCH V7 5/7] ACPI: properties: Implement get_match_data() callback
From: Rafael J. Wysocki @ 2017-12-08 14:51 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1512681031-11343-6-git-send-email-okaya@codeaurora.org>

On Thu, Dec 7, 2017 at 10:10 PM, Sinan Kaya <okaya@codeaurora.org> wrote:
> Now that we have a get_match_data() callback as part of the firmware node,
> implement the ACPI specific piece for it.
>
> Signed-off-by: Sinan Kaya <okaya@codeaurora.org>
> Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>
> ---
>  drivers/acpi/property.c | 8 ++++++++
>  1 file changed, 8 insertions(+)
>
> diff --git a/drivers/acpi/property.c b/drivers/acpi/property.c
> index e26ea20..466d150 100644
> --- a/drivers/acpi/property.c
> +++ b/drivers/acpi/property.c
> @@ -1271,9 +1271,17 @@ static int acpi_fwnode_graph_parse_endpoint(const struct fwnode_handle *fwnode,
>         return 0;
>  }
>
> +static void *
> +acpi_fwnode_device_get_match_data(const struct fwnode_handle *fwnode,
> +                                 const struct device *dev)
> +{
> +       return acpi_get_match_data(dev);
> +}
> +
>  #define DECLARE_ACPI_FWNODE_OPS(ops) \
>         const struct fwnode_operations ops = {                          \
>                 .device_is_available = acpi_fwnode_device_is_available, \
> +               .device_get_match_data = acpi_fwnode_device_get_match_data, \
>                 .property_present = acpi_fwnode_property_present,       \
>                 .property_read_int_array =                              \
>                         acpi_fwnode_property_read_int_array,            \
> --

Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

^ permalink raw reply

* [PATCH V7 2/7] ACPI / bus: Introduce acpi_get_match_data() function
From: Rafael J. Wysocki @ 2017-12-08 14:51 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1512681031-11343-3-git-send-email-okaya@codeaurora.org>

On Thu, Dec 7, 2017 at 10:10 PM, Sinan Kaya <okaya@codeaurora.org> wrote:
> OF has of_device_get_match_data() function to extract driver specific data
> structure. Add a similar function for ACPI.
>
> Signed-off-by: Sinan Kaya <okaya@codeaurora.org>
> ---
>  drivers/acpi/bus.c   | 18 ++++++++++++++++++
>  include/linux/acpi.h |  6 ++++++
>  2 files changed, 24 insertions(+)
>
> diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
> index 4d0979e..f87ed3b 100644
> --- a/drivers/acpi/bus.c
> +++ b/drivers/acpi/bus.c
> @@ -785,6 +785,24 @@ const struct acpi_device_id *acpi_match_device(const struct acpi_device_id *ids,
>  }
>  EXPORT_SYMBOL_GPL(acpi_match_device);
>
> +void *acpi_get_match_data(const struct device *dev)
> +{
> +       const struct acpi_device_id *match;
> +
> +       if (!dev->driver)
> +               return NULL;
> +
> +       if (!dev->driver->acpi_match_table)
> +               return NULL;

You can safely check dev->driver and this in the same statement (as
long as the first check to be made is on the left).

> +
> +       match = acpi_match_device(dev->driver->acpi_match_table, dev);
> +       if (!match)
> +               return NULL;
> +
> +       return (void *)match->driver_data;
> +}
> +EXPORT_SYMBOL_GPL(acpi_get_match_data);
> +
>  int acpi_match_device_ids(struct acpi_device *device,
>                           const struct acpi_device_id *ids)
>  {
> diff --git a/include/linux/acpi.h b/include/linux/acpi.h
> index 502af53..a927260 100644
> --- a/include/linux/acpi.h
> +++ b/include/linux/acpi.h
> @@ -584,6 +584,7 @@ extern int acpi_nvs_for_each_region(int (*func)(__u64, __u64, void *),
>  const struct acpi_device_id *acpi_match_device(const struct acpi_device_id *ids,
>                                                const struct device *dev);
>
> +void *acpi_get_match_data(const struct device *dev);
>  extern bool acpi_driver_match_device(struct device *dev,
>                                      const struct device_driver *drv);
>  int acpi_device_uevent_modalias(struct device *, struct kobj_uevent_env *);
> @@ -755,6 +756,11 @@ static inline const struct acpi_device_id *acpi_match_device(
>         return NULL;
>  }
>
> +static inline void *acpi_get_match_data(const struct device *dev)
> +{
> +       return NULL;
> +}
> +
>  static inline bool acpi_driver_match_device(struct device *dev,
>                                             const struct device_driver *drv)
>  {
> --

But anyway

Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

^ permalink raw reply

* [PATCH v4 4/4] arm64: dts: meson-axg: add clock DT info for Meson AXG SoC
From: Yixun Lan @ 2017-12-08 14:50 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <7ho9nbmked.fsf@baylibre.com>

On 12/07/17 08:50, Kevin Hilman wrote:
> Yixun Lan <yixun.lan@amlogic.com> writes:
> 
>> From: Qiufang Dai <qiufang.dai@amlogic.com>
>>
>> Try to add Hiubus DT info, and also enable clock DT info
>> for the Amlogic's Meson-AXG SoC.
>>
>> Acked-by: Rob Herring <robh@kernel.org>
>> Signed-off-by: Qiufang Dai <qiufang.dai@amlogic.com>
>> Signed-off-by: Yixun Lan <yixun.lan@amlogic.com>
>> ---
>>  arch/arm64/boot/dts/amlogic/meson-axg.dtsi | 15 +++++++++++++++
>>  1 file changed, 15 insertions(+)
>>
>> diff --git a/arch/arm64/boot/dts/amlogic/meson-axg.dtsi b/arch/arm64/boot/dts/amlogic/meson-axg.dtsi
>> index b932a784b02a..36a2e98338a8 100644
>> --- a/arch/arm64/boot/dts/amlogic/meson-axg.dtsi
>> +++ b/arch/arm64/boot/dts/amlogic/meson-axg.dtsi
>> @@ -7,6 +7,7 @@
>>  #include <dt-bindings/gpio/gpio.h>
>>  #include <dt-bindings/interrupt-controller/irq.h>
>>  #include <dt-bindings/interrupt-controller/arm-gic.h>
>> +#include <dt-bindings/clock/axg-clkc.h>
> 
> This #include will cause an unnessary dependency from the amlogic tree
> to the clock tree even though this patch is not currently using any of
> the #defines from that header.  It will simplify the dependencies if you
> drop this #include from this patch.
> 
> In my comment on the cover letter, I suggested adding a patch that also
> switches the UART over to the new clock provider.  That is the patch
> that should add this #include, since it will actually need #defines from
> the header.
> 
ok, make sense
> Doing it in that order means that we could merge this patch
> independently of the clock driver, and then merge the UART switch-over
> patch only after the driver (and headers) are merged.
I was planing to add UART DT part as separately patches (including the
UARt's pinctrl part information)

but as follow your suggestion, I could split the UART's clock DT info
into separate patch, and send along with this series.

> 
> Kevin
> 
> .
> 

^ permalink raw reply

* [PATCH v7 13/13] ASoC: stm32: add DFSDM DAI support
From: Arnaud Pouliquen @ 2017-12-08 14:49 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1512744566-13233-1-git-send-email-arnaud.pouliquen@st.com>

Add driver to handle DAI interface for PDM microphones connected
to Digital Filter for Sigma Delta Modulators IP.

Signed-off-by: Arnaud Pouliquen <arnaud.pouliquen@st.com>
---
V6 to V7 updates:
- SPDX-Licensing.
- Supress workaround in stm32_adfsdm_pcm_new as issue fixed in generic code in recent kernel version.
- Fix kbuild report issue on a log parameter type.
- Suppress test in stm32_adfsdm_set_sysclk on clock direction.

 sound/soc/stm/Kconfig        |  11 ++
 sound/soc/stm/Makefile       |   3 +
 sound/soc/stm/stm32_adfsdm.c | 351 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 365 insertions(+)
 create mode 100644 sound/soc/stm/stm32_adfsdm.c

diff --git a/sound/soc/stm/Kconfig b/sound/soc/stm/Kconfig
index 3398e6c..a78f770 100644
--- a/sound/soc/stm/Kconfig
+++ b/sound/soc/stm/Kconfig
@@ -28,4 +28,15 @@ config SND_SOC_STM32_SPDIFRX
 	help
 	  Say Y if you want to enable S/PDIF capture for STM32
 
+config SND_SOC_STM32_DFSDM
+	tristate "SoC Audio support for STM32 DFSDM"
+	depends on (ARCH_STM32 && OF && STM32_DFSDM_ADC) || COMPILE_TEST
+	depends on SND_SOC
+	select SND_SOC_GENERIC_DMAENGINE_PCM
+	select SND_SOC_DMIC
+	select IIO_BUFFER_CB
+	help
+	  Select this option to enable the STM32 Digital Filter
+	  for Sigma Delta Modulators (DFSDM) driver used
+	  in various STM32 series for digital microphone capture.
 endmenu
diff --git a/sound/soc/stm/Makefile b/sound/soc/stm/Makefile
index 4ed22e6..53e90e6 100644
--- a/sound/soc/stm/Makefile
+++ b/sound/soc/stm/Makefile
@@ -12,3 +12,6 @@ obj-$(CONFIG_SND_SOC_STM32_I2S) += snd-soc-stm32-i2s.o
 # SPDIFRX
 snd-soc-stm32-spdifrx-objs := stm32_spdifrx.o
 obj-$(CONFIG_SND_SOC_STM32_SPDIFRX) += snd-soc-stm32-spdifrx.o
+
+#DFSDM
+obj-$(CONFIG_SND_SOC_STM32_DFSDM) += stm32_adfsdm.o
diff --git a/sound/soc/stm/stm32_adfsdm.c b/sound/soc/stm/stm32_adfsdm.c
new file mode 100644
index 0000000..eef725e
--- /dev/null
+++ b/sound/soc/stm/stm32_adfsdm.c
@@ -0,0 +1,351 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * This file is part of STM32 DFSDM ASoC DAI driver
+ *
+ * Copyright (C) 2017, STMicroelectronics - All Rights Reserved
+ * Authors: Arnaud Pouliquen <arnaud.pouliquen@st.com>
+ *          Olivier Moysan <olivier.moysan@st.com>
+ */
+
+#include <linux/clk.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include <linux/iio/iio.h>
+#include <linux/iio/consumer.h>
+#include <linux/iio/adc/stm32-dfsdm-adc.h>
+
+#include <sound/pcm.h>
+#include <sound/soc.h>
+
+#define STM32_ADFSDM_DRV_NAME "stm32-adfsdm"
+
+#define DFSDM_MAX_PERIOD_SIZE	(PAGE_SIZE / 2)
+#define DFSDM_MAX_PERIODS	6
+
+struct stm32_adfsdm_priv {
+	struct snd_soc_dai_driver dai_drv;
+	struct snd_pcm_substream *substream;
+	struct device *dev;
+
+	/* IIO */
+	struct iio_channel *iio_ch;
+	struct iio_cb_buffer *iio_cb;
+	bool iio_active;
+
+	/* PCM buffer */
+	unsigned char *pcm_buff;
+	unsigned int pos;
+};
+
+static const struct snd_pcm_hardware stm32_adfsdm_pcm_hw = {
+	.info = SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
+	    SNDRV_PCM_INFO_PAUSE,
+	.formats = SNDRV_PCM_FMTBIT_S32_LE,
+
+	.rate_min = 8000,
+	.rate_max = 32000,
+
+	.channels_min = 1,
+	.channels_max = 1,
+
+	.periods_min = 2,
+	.periods_max = DFSDM_MAX_PERIODS,
+
+	.period_bytes_max = DFSDM_MAX_PERIOD_SIZE,
+	.buffer_bytes_max = DFSDM_MAX_PERIODS * DFSDM_MAX_PERIOD_SIZE
+};
+
+static void stm32_adfsdm_shutdown(struct snd_pcm_substream *substream,
+				  struct snd_soc_dai *dai)
+{
+	struct stm32_adfsdm_priv *priv = snd_soc_dai_get_drvdata(dai);
+
+	if (priv->iio_active) {
+		iio_channel_stop_all_cb(priv->iio_cb);
+		priv->iio_active = false;
+	}
+}
+
+static int stm32_adfsdm_dai_prepare(struct snd_pcm_substream *substream,
+				    struct snd_soc_dai *dai)
+{
+	struct stm32_adfsdm_priv *priv = snd_soc_dai_get_drvdata(dai);
+	int ret;
+
+	ret = iio_write_channel_attribute(priv->iio_ch,
+					  substream->runtime->rate, 0,
+					  IIO_CHAN_INFO_SAMP_FREQ);
+	if (ret < 0) {
+		dev_err(dai->dev, "%s: Failed to set %d sampling rate\n",
+			__func__, substream->runtime->rate);
+		return ret;
+	}
+
+	if (!priv->iio_active) {
+		ret = iio_channel_start_all_cb(priv->iio_cb);
+		if (!ret)
+			priv->iio_active = true;
+		else
+			dev_err(dai->dev, "%s: IIO channel start failed (%d)\n",
+				__func__, ret);
+	}
+
+	return ret;
+}
+
+static int stm32_adfsdm_set_sysclk(struct snd_soc_dai *dai, int clk_id,
+				   unsigned int freq, int dir)
+{
+	struct stm32_adfsdm_priv *priv = snd_soc_dai_get_drvdata(dai);
+	ssize_t size;
+	char str_freq[10];
+
+	dev_dbg(dai->dev, "%s: Enter for freq %d\n", __func__, freq);
+
+	/* Set IIO frequency if CODEC is master as clock comes from SPI_IN*/
+
+	snprintf(str_freq, sizeof(str_freq), "%d\n", freq);
+	size = iio_write_channel_ext_info(priv->iio_ch, "spi_clk_freq",
+					  str_freq, sizeof(str_freq));
+	if (size != sizeof(str_freq)) {
+		dev_err(dai->dev, "%s: Failed to set SPI clock\n",
+			__func__);
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static const struct snd_soc_dai_ops stm32_adfsdm_dai_ops = {
+	.shutdown = stm32_adfsdm_shutdown,
+	.prepare = stm32_adfsdm_dai_prepare,
+	.set_sysclk = stm32_adfsdm_set_sysclk,
+};
+
+static const struct snd_soc_dai_driver stm32_adfsdm_dai = {
+	.capture = {
+		    .channels_min = 1,
+		    .channels_max = 1,
+		    .formats = SNDRV_PCM_FMTBIT_S32_LE,
+		    .rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |
+			      SNDRV_PCM_RATE_32000),
+		    },
+	.ops = &stm32_adfsdm_dai_ops,
+};
+
+static const struct snd_soc_component_driver stm32_adfsdm_dai_component = {
+	.name = "stm32_dfsdm_audio",
+};
+
+static int stm32_afsdm_pcm_cb(const void *data, size_t size, void *private)
+{
+	struct stm32_adfsdm_priv *priv = private;
+	struct snd_soc_pcm_runtime *rtd = priv->substream->private_data;
+	u8 *pcm_buff = priv->pcm_buff;
+	u8 *src_buff = (u8 *)data;
+	unsigned int buff_size = snd_pcm_lib_buffer_bytes(priv->substream);
+	unsigned int period_size = snd_pcm_lib_period_bytes(priv->substream);
+	unsigned int old_pos = priv->pos;
+	unsigned int cur_size = size;
+
+	dev_dbg(rtd->dev, "%s: buff_add :%p, pos = %d, size = %zu\n",
+		__func__, &pcm_buff[priv->pos], priv->pos, size);
+
+	if ((priv->pos + size) > buff_size) {
+		memcpy(&pcm_buff[priv->pos], src_buff, buff_size - priv->pos);
+		cur_size -= buff_size - priv->pos;
+		priv->pos = 0;
+	}
+
+	memcpy(&pcm_buff[priv->pos], &src_buff[size - cur_size], cur_size);
+	priv->pos = (priv->pos + cur_size) % buff_size;
+
+	if (cur_size != size || (old_pos && (old_pos % period_size < size)))
+		snd_pcm_period_elapsed(priv->substream);
+
+	return 0;
+}
+
+static int stm32_adfsdm_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct stm32_adfsdm_priv *priv =
+		snd_soc_dai_get_drvdata(rtd->cpu_dai);
+
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+	case SNDRV_PCM_TRIGGER_RESUME:
+		priv->pos = 0;
+		return stm32_dfsdm_get_buff_cb(priv->iio_ch->indio_dev,
+					       stm32_afsdm_pcm_cb, priv);
+	case SNDRV_PCM_TRIGGER_SUSPEND:
+	case SNDRV_PCM_TRIGGER_STOP:
+		return stm32_dfsdm_release_buff_cb(priv->iio_ch->indio_dev);
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int stm32_adfsdm_pcm_open(struct snd_pcm_substream *substream)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct stm32_adfsdm_priv *priv = snd_soc_dai_get_drvdata(rtd->cpu_dai);
+	int ret;
+
+	ret =  snd_soc_set_runtime_hwparams(substream, &stm32_adfsdm_pcm_hw);
+	if (!ret)
+		priv->substream = substream;
+
+	return ret;
+}
+
+static int stm32_adfsdm_pcm_close(struct snd_pcm_substream *substream)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct stm32_adfsdm_priv *priv =
+		snd_soc_dai_get_drvdata(rtd->cpu_dai);
+
+	snd_pcm_lib_free_pages(substream);
+	priv->substream = NULL;
+
+	return 0;
+}
+
+static snd_pcm_uframes_t stm32_adfsdm_pcm_pointer(
+					    struct snd_pcm_substream *substream)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct stm32_adfsdm_priv *priv =
+		snd_soc_dai_get_drvdata(rtd->cpu_dai);
+
+	return bytes_to_frames(substream->runtime, priv->pos);
+}
+
+static int stm32_adfsdm_pcm_hw_params(struct snd_pcm_substream *substream,
+				      struct snd_pcm_hw_params *params)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct stm32_adfsdm_priv *priv =
+		snd_soc_dai_get_drvdata(rtd->cpu_dai);
+	int ret;
+
+	ret =  snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params));
+	if (ret < 0)
+		return ret;
+	priv->pcm_buff = substream->runtime->dma_area;
+
+	return iio_channel_cb_set_buffer_watermark(priv->iio_cb,
+						   params_period_size(params));
+}
+
+static int stm32_adfsdm_pcm_hw_free(struct snd_pcm_substream *substream)
+{
+	snd_pcm_lib_free_pages(substream);
+
+	return 0;
+}
+
+static struct snd_pcm_ops stm32_adfsdm_pcm_ops = {
+	.open		= stm32_adfsdm_pcm_open,
+	.close		= stm32_adfsdm_pcm_close,
+	.hw_params	= stm32_adfsdm_pcm_hw_params,
+	.hw_free	= stm32_adfsdm_pcm_hw_free,
+	.trigger	= stm32_adfsdm_trigger,
+	.pointer	= stm32_adfsdm_pcm_pointer,
+};
+
+static int stm32_adfsdm_pcm_new(struct snd_soc_pcm_runtime *rtd)
+{
+	struct snd_pcm *pcm = rtd->pcm;
+	struct stm32_adfsdm_priv *priv =
+		snd_soc_dai_get_drvdata(rtd->cpu_dai);
+	unsigned int size = DFSDM_MAX_PERIODS * DFSDM_MAX_PERIOD_SIZE;
+	int ret;
+
+	ret = snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
+						    priv->dev, size, size);
+	return ret;
+}
+
+static void stm32_adfsdm_pcm_free(struct snd_pcm *pcm)
+{
+	struct snd_pcm_substream *substream;
+	struct snd_soc_pcm_runtime *rtd;
+	struct stm32_adfsdm_priv *priv;
+
+	substream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream;
+	if (substream) {
+		rtd = substream->private_data;
+		priv = snd_soc_dai_get_drvdata(rtd->cpu_dai);
+
+		snd_pcm_lib_preallocate_free_for_all(pcm);
+	}
+}
+
+static struct snd_soc_platform_driver stm32_adfsdm_soc_platform = {
+	.ops		= &stm32_adfsdm_pcm_ops,
+	.pcm_new	= stm32_adfsdm_pcm_new,
+	.pcm_free	= stm32_adfsdm_pcm_free,
+};
+
+static const struct of_device_id stm32_adfsdm_of_match[] = {
+	{.compatible = "st,stm32h7-dfsdm-dai"},
+	{}
+};
+MODULE_DEVICE_TABLE(of, stm32_adfsdm_of_match);
+
+static int stm32_adfsdm_probe(struct platform_device *pdev)
+{
+	struct stm32_adfsdm_priv *priv;
+	int ret;
+
+	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	priv->dev = &pdev->dev;
+	priv->dai_drv = stm32_adfsdm_dai;
+
+	dev_set_drvdata(&pdev->dev, priv);
+
+	ret = devm_snd_soc_register_component(&pdev->dev,
+					      &stm32_adfsdm_dai_component,
+					      &priv->dai_drv, 1);
+	if (ret < 0)
+		return ret;
+
+	/* Associate iio channel */
+	priv->iio_ch  = devm_iio_channel_get_all(&pdev->dev);
+	if (IS_ERR(priv->iio_ch))
+		return PTR_ERR(priv->iio_ch);
+
+	priv->iio_cb = iio_channel_get_all_cb(&pdev->dev, NULL, NULL);
+	if (IS_ERR(priv->iio_cb))
+		return PTR_ERR(priv->iio_ch);
+
+	ret = devm_snd_soc_register_platform(&pdev->dev,
+					     &stm32_adfsdm_soc_platform);
+	if (ret < 0)
+		dev_err(&pdev->dev, "%s: Failed to register PCM platform\n",
+			__func__);
+
+	return ret;
+}
+
+static struct platform_driver stm32_adfsdm_driver = {
+	.driver = {
+		   .name = STM32_ADFSDM_DRV_NAME,
+		   .of_match_table = stm32_adfsdm_of_match,
+		   },
+	.probe = stm32_adfsdm_probe,
+};
+
+module_platform_driver(stm32_adfsdm_driver);
+
+MODULE_DESCRIPTION("stm32 DFSDM DAI driver");
+MODULE_AUTHOR("Arnaud Pouliquen <arnaud.pouliquen@st.com>");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:" STM32_ADFSDM_DRV_NAME);
-- 
2.7.4

^ permalink raw reply related

* [PATCH v7 12/13] ASoC: add bindings for stm32 DFSDM filter
From: Arnaud Pouliquen @ 2017-12-08 14:49 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1512744566-13233-1-git-send-email-arnaud.pouliquen@st.com>

Add bindings that describes audio settings to support
Digital Filter for pulse density modulation(PDM) microphone.

Signed-off-by: Arnaud Pouliquen <arnaud.pouliquen@st.com>
Acked-by: Rob Herring <robh@kernel.org>
---
V6 to V7 update:
 - Minor update to add missing interrupt-cells in example.

 .../devicetree/bindings/sound/st,stm32-adfsdm.txt  | 63 ++++++++++++++++++++++
 1 file changed, 63 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/sound/st,stm32-adfsdm.txt

diff --git a/Documentation/devicetree/bindings/sound/st,stm32-adfsdm.txt b/Documentation/devicetree/bindings/sound/st,stm32-adfsdm.txt
new file mode 100644
index 0000000..864f5b0
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/st,stm32-adfsdm.txt
@@ -0,0 +1,63 @@
+STMicroelectronics Audio Digital Filter Sigma Delta modulators(DFSDM)
+
+The DFSDM allows PDM microphones capture through SPI interface. The Audio
+interface is seems as a sub block of the DFSDM device.
+For details on DFSDM bindings refer to ../iio/adc/st,stm32-dfsdm-adc.txt
+
+Required properties:
+  - compatible: "st,stm32h7-dfsdm-dai".
+
+  - #sound-dai-cells : Must be equal to 0
+
+  - io-channels : phandle to iio dfsdm instance node.
+
+Example of a sound card using audio DFSDM node.
+
+	sound_card {
+		compatible = "audio-graph-card";
+
+		dais = <&cpu_port>;
+	};
+
+	dfsdm: dfsdm at 40017000 {
+		compatible = "st,stm32h7-dfsdm";
+		reg = <0x40017000 0x400>;
+		clocks = <&rcc DFSDM1_CK>;
+		clock-names = "dfsdm";
+		#interrupt-cells = <1>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		dfsdm_adc0: filter at 0 {
+			compatible = "st,stm32-dfsdm-dmic";
+			reg = <0>;
+			interrupts = <110>;
+			dmas = <&dmamux1 101 0x400 0x00>;
+			dma-names = "rx";
+			st,adc-channels = <1>;
+			st,adc-channel-names = "dmic0";
+			st,adc-channel-types = "SPI_R";
+			st,adc-channel-clk-src = "CLKOUT";
+			st,filter-order = <5>;
+
+			dfsdm_dai0: dfsdm-dai {
+				compatible = "st,stm32h7-dfsdm-dai";
+				#sound-dai-cells = <0>;
+				io-channels = <&dfsdm_adc0 0>;
+				cpu_port: port {
+				dfsdm_endpoint: endpoint {
+					remote-endpoint = <&dmic0_endpoint>;
+				};
+			};
+		};
+	};
+
+	dmic0: dmic at 0 {
+		compatible = "dmic-codec";
+		#sound-dai-cells = <0>;
+		port {
+			dmic0_endpoint: endpoint {
+				remote-endpoint = <&dfsdm_endpoint>;
+			};
+		};
+	};
-- 
2.7.4

^ permalink raw reply related

* [PATCH v7 11/13] IIO: consumer: allow to set buffer sizes
From: Arnaud Pouliquen @ 2017-12-08 14:49 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1512744566-13233-1-git-send-email-arnaud.pouliquen@st.com>

Add iio consumer API to set buffer size and watermark according
to sysfs API.

Signed-off-by: Arnaud Pouliquen <arnaud.pouliquen@st.com>
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
---
 drivers/iio/buffer/industrialio-buffer-cb.c | 11 +++++++++++
 include/linux/iio/consumer.h                | 11 +++++++++++
 2 files changed, 22 insertions(+)

diff --git a/drivers/iio/buffer/industrialio-buffer-cb.c b/drivers/iio/buffer/industrialio-buffer-cb.c
index 4847534..ea63c83 100644
--- a/drivers/iio/buffer/industrialio-buffer-cb.c
+++ b/drivers/iio/buffer/industrialio-buffer-cb.c
@@ -104,6 +104,17 @@ struct iio_cb_buffer *iio_channel_get_all_cb(struct device *dev,
 }
 EXPORT_SYMBOL_GPL(iio_channel_get_all_cb);
 
+int iio_channel_cb_set_buffer_watermark(struct iio_cb_buffer *cb_buff,
+					size_t watermark)
+{
+	if (!watermark)
+		return -EINVAL;
+	cb_buff->buffer.watermark = watermark;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(iio_channel_cb_set_buffer_watermark);
+
 int iio_channel_start_all_cb(struct iio_cb_buffer *cb_buff)
 {
 	return iio_update_buffers(cb_buff->indio_dev, &cb_buff->buffer,
diff --git a/include/linux/iio/consumer.h b/include/linux/iio/consumer.h
index 2017f35..9887f4f 100644
--- a/include/linux/iio/consumer.h
+++ b/include/linux/iio/consumer.h
@@ -134,6 +134,17 @@ struct iio_cb_buffer *iio_channel_get_all_cb(struct device *dev,
 						       void *private),
 					     void *private);
 /**
+ * iio_channel_cb_set_buffer_watermark() - set the buffer watermark.
+ * @cb_buffer:		The callback buffer from whom we want the channel
+ *			information.
+ * @watermark: buffer watermark in bytes.
+ *
+ * This function allows to configure the buffer watermark.
+ */
+int iio_channel_cb_set_buffer_watermark(struct iio_cb_buffer *cb_buffer,
+					size_t watermark);
+
+/**
  * iio_channel_release_all_cb() - release and unregister the callback.
  * @cb_buffer:		The callback buffer that was allocated.
  */
-- 
2.7.4

^ permalink raw reply related

* [PATCH v7 10/13] IIO: ADC: add stm32 DFSDM support for PDM microphone
From: Arnaud Pouliquen @ 2017-12-08 14:49 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1512744566-13233-1-git-send-email-arnaud.pouliquen@st.com>

This code offers a way to handle PDM audio microphones in
ASOC framework. Audio driver should use consumer API.
A specific management is implemented for DMA, with a
callback, to allows to handle audio buffers efficiently.

Signed-off-by: Arnaud Pouliquen <arnaud.pouliquen@st.com>
---
V6 to V7 updates:
- SPDX-Licensing.
- Minor typo fixes.

 .../ABI/testing/sysfs-bus-iio-dfsdm-adc-stm32      |  16 +
 drivers/iio/adc/stm32-dfsdm-adc.c                  | 508 ++++++++++++++++++++-
 include/linux/iio/adc/stm32-dfsdm-adc.h            |  18 +
 3 files changed, 534 insertions(+), 8 deletions(-)
 create mode 100644 Documentation/ABI/testing/sysfs-bus-iio-dfsdm-adc-stm32
 create mode 100644 include/linux/iio/adc/stm32-dfsdm-adc.h

diff --git a/Documentation/ABI/testing/sysfs-bus-iio-dfsdm-adc-stm32 b/Documentation/ABI/testing/sysfs-bus-iio-dfsdm-adc-stm32
new file mode 100644
index 0000000..da98223
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-bus-iio-dfsdm-adc-stm32
@@ -0,0 +1,16 @@
+What:		/sys/bus/iio/devices/iio:deviceX/in_voltage_spi_clk_freq
+KernelVersion:	4.14
+Contact:	arnaud.pouliquen at st.com
+Description:
+		For audio purpose only.
+		Used by audio driver to set/get the spi input frequency.
+		This is mandatory if DFSDM is slave on SPI bus, to
+		provide information on the SPI clock frequency during runtime
+		Notice that the SPI frequency should be a multiple of sample
+		frequency to ensure the precision.
+		if DFSDM input is SPI master
+			Reading  SPI clkout frequency,
+			error on writing
+		If DFSDM input is SPI Slave:
+			Reading returns value previously set.
+			Writing value before starting conversions.
\ No newline at end of file
diff --git a/drivers/iio/adc/stm32-dfsdm-adc.c b/drivers/iio/adc/stm32-dfsdm-adc.c
index 68b5920..2d6aed5 100644
--- a/drivers/iio/adc/stm32-dfsdm-adc.c
+++ b/drivers/iio/adc/stm32-dfsdm-adc.c
@@ -6,19 +6,25 @@
  * Author: Arnaud Pouliquen <arnaud.pouliquen@st.com>.
  */
 
+#include <linux/dmaengine.h>
+#include <linux/dma-mapping.h>
 #include <linux/interrupt.h>
 #include <linux/iio/buffer.h>
 #include <linux/iio/hw-consumer.h>
 #include <linux/iio/iio.h>
 #include <linux/iio/sysfs.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/triggered_buffer.h>
 #include <linux/module.h>
-#include <linux/of.h>
+#include <linux/of_device.h>
 #include <linux/platform_device.h>
 #include <linux/regmap.h>
 #include <linux/slab.h>
 
 #include "stm32-dfsdm.h"
 
+#define DFSDM_DMA_BUFFER_SIZE (4 * PAGE_SIZE)
+
 /* Conversion timeout */
 #define DFSDM_TIMEOUT_US 100000
 #define DFSDM_TIMEOUT (msecs_to_jiffies(DFSDM_TIMEOUT_US / 1000))
@@ -58,6 +64,18 @@ struct stm32_dfsdm_adc {
 	struct completion completion;
 	u32 *buffer;
 
+	/* Audio specific */
+	unsigned int spi_freq;  /* SPI bus clock frequency */
+	unsigned int sample_freq; /* Sample frequency after filter decimation */
+	int (*cb)(const void *data, size_t size, void *cb_priv);
+	void *cb_priv;
+
+	/* DMA */
+	u8 *rx_buf;
+	unsigned int bufi; /* Buffer current position */
+	unsigned int buf_sz; /* Buffer size */
+	struct dma_chan	*dma_chan;
+	dma_addr_t dma_buf;
 };
 
 struct stm32_dfsdm_str2field {
@@ -351,10 +369,63 @@ int stm32_dfsdm_channel_parse_of(struct stm32_dfsdm *dfsdm,
 	return 0;
 }
 
+static ssize_t dfsdm_adc_audio_get_spiclk(struct iio_dev *indio_dev,
+					  uintptr_t priv,
+					  const struct iio_chan_spec *chan,
+					  char *buf)
+{
+	struct stm32_dfsdm_adc *adc = iio_priv(indio_dev);
+
+	return snprintf(buf, PAGE_SIZE, "%d\n", adc->spi_freq);
+}
+
+static ssize_t dfsdm_adc_audio_set_spiclk(struct iio_dev *indio_dev,
+					  uintptr_t priv,
+					  const struct iio_chan_spec *chan,
+					  const char *buf, size_t len)
+{
+	struct stm32_dfsdm_adc *adc = iio_priv(indio_dev);
+	struct stm32_dfsdm_filter *fl = &adc->dfsdm->fl_list[adc->fl_id];
+	struct stm32_dfsdm_channel *ch = &adc->dfsdm->ch_list[adc->ch_id];
+	unsigned int sample_freq = adc->sample_freq;
+	unsigned int spi_freq;
+	int ret;
+
+	dev_err(&indio_dev->dev, "enter %s\n", __func__);
+	/* If DFSDM is master on SPI, SPI freq can not be updated */
+	if (ch->src != DFSDM_CHANNEL_SPI_CLOCK_EXTERNAL)
+		return -EPERM;
+
+	ret = kstrtoint(buf, 0, &spi_freq);
+	if (ret)
+		return ret;
+
+	if (!spi_freq)
+		return -EINVAL;
+
+	if (sample_freq) {
+		if (spi_freq % sample_freq)
+			dev_warn(&indio_dev->dev,
+				 "Sampling rate not accurate (%d)\n",
+				 spi_freq / (spi_freq / sample_freq));
+
+		ret = stm32_dfsdm_set_osrs(fl, 0, (spi_freq / sample_freq));
+		if (ret < 0) {
+			dev_err(&indio_dev->dev,
+				"No filter parameters that match!\n");
+			return ret;
+		}
+	}
+	adc->spi_freq = spi_freq;
+
+	return len;
+}
+
 static int stm32_dfsdm_start_conv(struct stm32_dfsdm_adc *adc, bool dma)
 {
 	struct regmap *regmap = adc->dfsdm->regmap;
 	int ret;
+	unsigned int dma_en = 0, cont_en = 0;
 
 	ret = stm32_dfsdm_start_channel(adc->dfsdm, adc->ch_id);
 	if (ret < 0)
@@ -365,6 +436,24 @@ static int stm32_dfsdm_start_conv(struct stm32_dfsdm_adc *adc, bool dma)
 	if (ret < 0)
 		goto stop_channels;
 
+	if (dma) {
+		/* Enable DMA transfer*/
+		dma_en =  DFSDM_CR1_RDMAEN(1);
+		/* Enable conversion triggered by SPI clock*/
+		cont_en = DFSDM_CR1_RCONT(1);
+	}
+	/* Enable DMA transfer*/
+	ret = regmap_update_bits(regmap, DFSDM_CR1(adc->fl_id),
+				 DFSDM_CR1_RDMAEN_MASK, dma_en);
+	if (ret < 0)
+		goto stop_channels;
+
+	/* Enable conversion triggered by SPI clock*/
+	ret = regmap_update_bits(regmap, DFSDM_CR1(adc->fl_id),
+				 DFSDM_CR1_RCONT_MASK, cont_en);
+	if (ret < 0)
+		goto stop_channels;
+
 	ret = stm32_dfsdm_start_filter(adc->dfsdm, adc->fl_id);
 	if (ret < 0)
 		goto stop_channels;
@@ -398,6 +487,231 @@ static void stm32_dfsdm_stop_conv(struct stm32_dfsdm_adc *adc)
 	stm32_dfsdm_stop_channel(adc->dfsdm, adc->ch_id);
 }
 
+static int stm32_dfsdm_set_watermark(struct iio_dev *indio_dev,
+				     unsigned int val)
+{
+	struct stm32_dfsdm_adc *adc = iio_priv(indio_dev);
+	unsigned int watermark = DFSDM_DMA_BUFFER_SIZE / 2;
+
+	/*
+	 * DMA cyclic transfers are used, buffer is split into two periods.
+	 * There should be :
+	 * - always one buffer (period) DMA is working on
+	 * - one buffer (period) driver pushed to ASoC side.
+	 */
+	watermark = min(watermark, val * (unsigned int)(sizeof(u32)));
+	adc->buf_sz = watermark * 2;
+
+	return 0;
+}
+
+static unsigned int stm32_dfsdm_adc_dma_residue(struct stm32_dfsdm_adc *adc)
+{
+	struct dma_tx_state state;
+	enum dma_status status;
+
+	status = dmaengine_tx_status(adc->dma_chan,
+				     adc->dma_chan->cookie,
+				     &state);
+	if (status == DMA_IN_PROGRESS) {
+		/* Residue is size in bytes from end of buffer */
+		unsigned int i = adc->buf_sz - state.residue;
+		unsigned int size;
+
+		/* Return available bytes */
+		if (i >= adc->bufi)
+			size = i - adc->bufi;
+		else
+			size = adc->buf_sz + i - adc->bufi;
+
+		return size;
+	}
+
+	return 0;
+}
+
+static void stm32_dfsdm_audio_dma_buffer_done(void *data)
+{
+	struct iio_dev *indio_dev = data;
+	struct stm32_dfsdm_adc *adc = iio_priv(indio_dev);
+	int available = stm32_dfsdm_adc_dma_residue(adc);
+	size_t old_pos;
+
+	/*
+	 * FIXME: In Kernel interface does not support cyclic DMA buffer,and
+	 * offers only an interface to push data samples per samples.
+	 * For this reason IIO buffer interface is not used and interface is
+	 * bypassed using a private callback registered by ASoC.
+	 * This should be a temporary solution waiting a cyclic DMA engine
+	 * support in IIO.
+	 */
+
+	dev_dbg(&indio_dev->dev, "%s: pos = %d, available = %d\n", __func__,
+		adc->bufi, available);
+	old_pos = adc->bufi;
+
+	while (available >= indio_dev->scan_bytes) {
+		u32 *buffer = (u32 *)&adc->rx_buf[adc->bufi];
+
+		/* Mask 8 LSB that contains the channel ID */
+		*buffer = (*buffer & 0xFFFFFF00) << 8;
+		available -= indio_dev->scan_bytes;
+		adc->bufi += indio_dev->scan_bytes;
+		if (adc->bufi >= adc->buf_sz) {
+			if (adc->cb)
+				adc->cb(&adc->rx_buf[old_pos],
+					 adc->buf_sz - old_pos, adc->cb_priv);
+			adc->bufi = 0;
+			old_pos = 0;
+		}
+	}
+	if (adc->cb)
+		adc->cb(&adc->rx_buf[old_pos], adc->bufi - old_pos,
+			adc->cb_priv);
+}
+
+static int stm32_dfsdm_adc_dma_start(struct iio_dev *indio_dev)
+{
+	struct stm32_dfsdm_adc *adc = iio_priv(indio_dev);
+	struct dma_async_tx_descriptor *desc;
+	dma_cookie_t cookie;
+	int ret;
+
+	if (!adc->dma_chan)
+		return -EINVAL;
+
+	dev_dbg(&indio_dev->dev, "%s size=%d watermark=%d\n", __func__,
+		adc->buf_sz, adc->buf_sz / 2);
+
+	/* Prepare a DMA cyclic transaction */
+	desc = dmaengine_prep_dma_cyclic(adc->dma_chan,
+					 adc->dma_buf,
+					 adc->buf_sz, adc->buf_sz / 2,
+					 DMA_DEV_TO_MEM,
+					 DMA_PREP_INTERRUPT);
+	if (!desc)
+		return -EBUSY;
+
+	desc->callback = stm32_dfsdm_audio_dma_buffer_done;
+	desc->callback_param = indio_dev;
+
+	cookie = dmaengine_submit(desc);
+	ret = dma_submit_error(cookie);
+	if (ret) {
+		dmaengine_terminate_all(adc->dma_chan);
+		return ret;
+	}
+
+	/* Issue pending DMA requests */
+	dma_async_issue_pending(adc->dma_chan);
+
+	return 0;
+}
+
+static int stm32_dfsdm_postenable(struct iio_dev *indio_dev)
+{
+	struct stm32_dfsdm_adc *adc = iio_priv(indio_dev);
+	int ret;
+
+	/* Reset adc buffer index */
+	adc->bufi = 0;
+
+	ret = stm32_dfsdm_start_dfsdm(adc->dfsdm);
+	if (ret < 0)
+		return ret;
+
+	ret = stm32_dfsdm_start_conv(adc, true);
+	if (ret) {
+		dev_err(&indio_dev->dev, "Can't start conversion\n");
+		goto stop_dfsdm;
+	}
+
+	if (adc->dma_chan) {
+		ret = stm32_dfsdm_adc_dma_start(indio_dev);
+		if (ret) {
+			dev_err(&indio_dev->dev, "Can't start DMA\n");
+			goto err_stop_conv;
+		}
+	}
+
+	return 0;
+
+err_stop_conv:
+	stm32_dfsdm_stop_conv(adc);
+stop_dfsdm:
+	stm32_dfsdm_stop_dfsdm(adc->dfsdm);
+
+	return ret;
+}
+
+static int stm32_dfsdm_predisable(struct iio_dev *indio_dev)
+{
+	struct stm32_dfsdm_adc *adc = iio_priv(indio_dev);
+
+	if (adc->dma_chan)
+		dmaengine_terminate_all(adc->dma_chan);
+
+	stm32_dfsdm_stop_conv(adc);
+
+	stm32_dfsdm_stop_dfsdm(adc->dfsdm);
+
+	return 0;
+}
+
+static const struct iio_buffer_setup_ops stm32_dfsdm_buffer_setup_ops = {
+	.postenable = &stm32_dfsdm_postenable,
+	.predisable = &stm32_dfsdm_predisable,
+};
+
+/**
+ * stm32_dfsdm_get_buff_cb() - register a callback that will be called when
+ *                             DMA transfer period is achieved.
+ *
+ * @iio_dev: Handle to IIO device.
+ * @cb: Pointer to callback function:
+ *      - data: pointer to data buffer
+ *      - size: size in byte of the data buffer
+ *      - private: pointer to consumer private structure.
+ * @private: Pointer to consumer private structure.
+ */
+int stm32_dfsdm_get_buff_cb(struct iio_dev *iio_dev,
+			    int (*cb)(const void *data, size_t size,
+				      void *private),
+			    void *private)
+{
+	struct stm32_dfsdm_adc *adc;
+
+	if (!iio_dev)
+		return -EINVAL;
+	adc = iio_priv(iio_dev);
+
+	adc->cb = cb;
+	adc->cb_priv = private;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(stm32_dfsdm_get_buff_cb);
+
+/**
+ * stm32_dfsdm_release_buff_cb - unregister buffer callback
+ *
+ * @iio_dev: Handle to IIO device.
+ */
+int stm32_dfsdm_release_buff_cb(struct iio_dev *iio_dev)
+{
+	struct stm32_dfsdm_adc *adc;
+
+	if (!iio_dev)
+		return -EINVAL;
+	adc = iio_priv(iio_dev);
+
+	adc->cb = NULL;
+	adc->cb_priv = NULL;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(stm32_dfsdm_release_buff_cb);
+
 static int stm32_dfsdm_single_conv(struct iio_dev *indio_dev,
 				   const struct iio_chan_spec *chan, int *res)
 {
@@ -453,15 +767,41 @@ static int stm32_dfsdm_write_raw(struct iio_dev *indio_dev,
 {
 	struct stm32_dfsdm_adc *adc = iio_priv(indio_dev);
 	struct stm32_dfsdm_filter *fl = &adc->dfsdm->fl_list[adc->fl_id];
+	struct stm32_dfsdm_channel *ch = &adc->dfsdm->ch_list[adc->ch_id];
+	unsigned int spi_freq = adc->spi_freq;
 	int ret = -EINVAL;
 
-	if (mask == IIO_CHAN_INFO_OVERSAMPLING_RATIO) {
+	switch (mask) {
+	case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
 		ret = stm32_dfsdm_set_osrs(fl, 0, val);
 		if (!ret)
 			adc->oversamp = val;
+
+		return ret;
+
+	case IIO_CHAN_INFO_SAMP_FREQ:
+		if (!val)
+			return -EINVAL;
+		if (ch->src != DFSDM_CHANNEL_SPI_CLOCK_EXTERNAL)
+			spi_freq = adc->dfsdm->spi_master_freq;
+
+		if (spi_freq % val)
+			dev_warn(&indio_dev->dev,
+				 "Sampling rate not accurate (%d)\n",
+				 spi_freq / (spi_freq / val));
+
+		ret = stm32_dfsdm_set_osrs(fl, 0, (spi_freq / val));
+		if (ret < 0) {
+			dev_err(&indio_dev->dev,
+				"Not able to find parameter that match!\n");
+			return ret;
+		}
+		adc->sample_freq = val;
+
+		return 0;
 	}
 
-	return ret;
+	return -EINVAL;
 }
 
 static int stm32_dfsdm_read_raw(struct iio_dev *indio_dev,
@@ -494,11 +834,22 @@ static int stm32_dfsdm_read_raw(struct iio_dev *indio_dev,
 		*val = adc->oversamp;
 
 		return IIO_VAL_INT;
+
+	case IIO_CHAN_INFO_SAMP_FREQ:
+		*val = adc->sample_freq;
+
+		return IIO_VAL_INT;
 	}
 
 	return -EINVAL;
 }
 
+static const struct iio_info stm32_dfsdm_info_audio = {
+	.hwfifo_set_watermark = stm32_dfsdm_set_watermark,
+	.read_raw = stm32_dfsdm_read_raw,
+	.write_raw = stm32_dfsdm_write_raw,
+};
+
 static const struct iio_info stm32_dfsdm_info_adc = {
 	.read_raw = stm32_dfsdm_read_raw,
 	.write_raw = stm32_dfsdm_write_raw,
@@ -531,6 +882,60 @@ static irqreturn_t stm32_dfsdm_irq(int irq, void *arg)
 	return IRQ_HANDLED;
 }
 
+/*
+ * Define external info for SPI Frequency and audio sampling rate that can be
+ * configured by ASoC driver through consumer.h API
+ */
+static const struct iio_chan_spec_ext_info dfsdm_adc_audio_ext_info[] = {
+	/* spi_clk_freq : clock freq on SPI/manchester bus used by channel */
+	{
+		.name = "spi_clk_freq",
+		.shared = IIO_SHARED_BY_TYPE,
+		.read = dfsdm_adc_audio_get_spiclk,
+		.write = dfsdm_adc_audio_set_spiclk,
+	},
+	{},
+};
+
+static int stm32_dfsdm_dma_request(struct iio_dev *indio_dev)
+{
+	struct stm32_dfsdm_adc *adc = iio_priv(indio_dev);
+	struct dma_slave_config config;
+	int ret;
+
+	adc->dma_chan = dma_request_slave_channel(&indio_dev->dev, "rx");
+	if (!adc->dma_chan)
+		return -EINVAL;
+
+	adc->rx_buf = dma_alloc_coherent(adc->dma_chan->device->dev,
+					 DFSDM_DMA_BUFFER_SIZE,
+					 &adc->dma_buf, GFP_KERNEL);
+	if (!adc->rx_buf) {
+		ret = -ENOMEM;
+		goto err_release;
+	}
+
+	/* Configure DMA channel to read data register */
+	memset(&config, 0, sizeof(config));
+	config.src_addr = (dma_addr_t)adc->dfsdm->phys_base;
+	config.src_addr += DFSDM_RDATAR(adc->fl_id);
+	config.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+
+	ret = dmaengine_slave_config(adc->dma_chan, &config);
+	if (ret)
+		goto err_free;
+
+	return 0;
+
+err_free:
+	dma_free_coherent(adc->dma_chan->device->dev, DFSDM_DMA_BUFFER_SIZE,
+			  adc->rx_buf, adc->dma_buf);
+err_release:
+	dma_release_channel(adc->dma_chan);
+
+	return ret;
+}
+
 static int stm32_dfsdm_adc_chan_init_one(struct iio_dev *indio_dev,
 					 struct iio_chan_spec *ch)
 {
@@ -551,7 +956,12 @@ static int stm32_dfsdm_adc_chan_init_one(struct iio_dev *indio_dev,
 	ch->info_mask_separate = BIT(IIO_CHAN_INFO_RAW);
 	ch->info_mask_shared_by_all = BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO);
 
-	ch->scan_type.sign = 'u';
+	if (adc->dev_data->type == DFSDM_AUDIO) {
+		ch->scan_type.sign = 's';
+		ch->ext_info = dfsdm_adc_audio_ext_info;
+	} else {
+		ch->scan_type.sign = 'u';
+	}
 	ch->scan_type.realbits = 24;
 	ch->scan_type.storagebits = 32;
 	adc->ch_id = ch->channel;
@@ -560,6 +970,64 @@ static int stm32_dfsdm_adc_chan_init_one(struct iio_dev *indio_dev,
 					  &adc->dfsdm->ch_list[ch->channel]);
 }
 
+static int stm32_dfsdm_audio_init(struct iio_dev *indio_dev)
+{
+	struct iio_chan_spec *ch;
+	struct stm32_dfsdm_adc *adc = iio_priv(indio_dev);
+	struct stm32_dfsdm_channel *d_ch;
+	int ret;
+
+	ret = stm32_dfsdm_dma_request(indio_dev);
+	if (ret) {
+		dev_err(&indio_dev->dev, "DMA request failed\n");
+		return ret;
+	}
+
+	indio_dev->modes |= INDIO_BUFFER_SOFTWARE;
+
+	ret = iio_triggered_buffer_setup(indio_dev,
+					 &iio_pollfunc_store_time,
+					 NULL,
+					 &stm32_dfsdm_buffer_setup_ops);
+	if (ret) {
+		dev_err(&indio_dev->dev, "Buffer setup failed\n");
+		goto err_dma_disable;
+	}
+
+	ch = devm_kzalloc(&indio_dev->dev, sizeof(*ch), GFP_KERNEL);
+	if (!ch)
+		return -ENOMEM;
+
+	ch->scan_index = 0;
+	ret = stm32_dfsdm_adc_chan_init_one(indio_dev, ch);
+	if (ret < 0) {
+		dev_err(&indio_dev->dev, "channels init failed\n");
+		goto err_buffer_cleanup;
+	}
+	ch->info_mask_separate = BIT(IIO_CHAN_INFO_SAMP_FREQ);
+
+	d_ch = &adc->dfsdm->ch_list[adc->ch_id];
+	if (d_ch->src != DFSDM_CHANNEL_SPI_CLOCK_EXTERNAL)
+		adc->spi_freq = adc->dfsdm->spi_master_freq;
+
+	indio_dev->num_channels = 1;
+	indio_dev->channels = ch;
+
+	return 0;
+
+err_buffer_cleanup:
+	iio_triggered_buffer_cleanup(indio_dev);
+
+err_dma_disable:
+	if (adc->dma_chan) {
+		dma_free_coherent(adc->dma_chan->device->dev,
+				  DFSDM_DMA_BUFFER_SIZE,
+				  adc->rx_buf, adc->dma_buf);
+		dma_release_channel(adc->dma_chan);
+	}
+	return ret;
+}
+
 static int stm32_dfsdm_adc_init(struct iio_dev *indio_dev)
 {
 	struct iio_chan_spec *ch;
@@ -612,11 +1080,20 @@ static const struct stm32_dfsdm_dev_data stm32h7_dfsdm_adc_data = {
 	.init = stm32_dfsdm_adc_init,
 };
 
+static const struct stm32_dfsdm_dev_data stm32h7_dfsdm_audio_data = {
+	.type = DFSDM_AUDIO,
+	.init = stm32_dfsdm_audio_init,
+};
+
 static const struct of_device_id stm32_dfsdm_adc_match[] = {
 	{
 		.compatible = "st,stm32-dfsdm-adc",
 		.data = &stm32h7_dfsdm_adc_data,
 	},
+	{
+		.compatible = "st,stm32-dfsdm-dmic",
+		.data = &stm32h7_dfsdm_audio_data,
+	},
 	{}
 };
 
@@ -667,8 +1144,13 @@ static int stm32_dfsdm_adc_probe(struct platform_device *pdev)
 	name = devm_kzalloc(dev, sizeof("dfsdm-adc0"), GFP_KERNEL);
 	if (!name)
 		return -ENOMEM;
-	iio->info = &stm32_dfsdm_info_adc;
-	snprintf(name, sizeof("dfsdm-adc0"), "dfsdm-adc%d", adc->fl_id);
+	if (dev_data->type == DFSDM_AUDIO) {
+		iio->info = &stm32_dfsdm_info_audio;
+		snprintf(name, sizeof("dfsdm-pdm0"), "dfsdm-pdm%d", adc->fl_id);
+	} else {
+		iio->info = &stm32_dfsdm_info_adc;
+		snprintf(name, sizeof("dfsdm-adc0"), "dfsdm-adc%d", adc->fl_id);
+	}
 	iio->name = name;
 
 	/*
@@ -700,7 +1182,10 @@ static int stm32_dfsdm_adc_probe(struct platform_device *pdev)
 	if (ret < 0)
 		return ret;
 
-	return iio_device_register(iio);
+	iio_device_register(iio);
+	if (dev_data->type == DFSDM_AUDIO)
+		return devm_of_platform_populate(&pdev->dev);
+	return 0;
 }
 
 static int stm32_dfsdm_adc_remove(struct platform_device *pdev)
@@ -709,7 +1194,14 @@ static int stm32_dfsdm_adc_remove(struct platform_device *pdev)
 	struct iio_dev *indio_dev = iio_priv_to_dev(adc);
 
 	iio_device_unregister(indio_dev);
-
+	if (indio_dev->pollfunc)
+		iio_triggered_buffer_cleanup(indio_dev);
+	if (adc->dma_chan) {
+		dma_free_coherent(adc->dma_chan->device->dev,
+				  DFSDM_DMA_BUFFER_SIZE,
+				  adc->rx_buf, adc->dma_buf);
+		dma_release_channel(adc->dma_chan);
+	}
 	return 0;
 }
 
diff --git a/include/linux/iio/adc/stm32-dfsdm-adc.h b/include/linux/iio/adc/stm32-dfsdm-adc.h
new file mode 100644
index 0000000..e7dc7a5
--- /dev/null
+++ b/include/linux/iio/adc/stm32-dfsdm-adc.h
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * This file discribe the STM32 DFSDM IIO driver API for audio part
+ *
+ * Copyright (C) 2017, STMicroelectronics - All Rights Reserved
+ * Author(s): Arnaud Pouliquen <arnaud.pouliquen@st.com>.
+ */
+
+#ifndef STM32_DFSDM_ADC_H
+#define STM32_DFSDM_ADC_H
+
+int stm32_dfsdm_get_buff_cb(struct iio_dev *iio_dev,
+			    int (*cb)(const void *data, size_t size,
+				      void *private),
+			    void *private);
+int stm32_dfsdm_release_buff_cb(struct iio_dev *iio_dev);
+
+#endif
-- 
2.7.4

^ 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