Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Internal error: Oops: 17 [#1] ARM
From: John Tobias @ 2014-01-22 17:56 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20140122164100.GE15937@n2100.arm.linux.org.uk>

I ran the kernel in our custom board and I've seen the error after
(sometimes 10 minutes after) the reboot and sometimes my board ran for
an hour or so before it happened.
I will try the 3.13-rc8 today and will see if the said bug still exist or not.

Regards,

john

On Wed, Jan 22, 2014 at 8:41 AM, Russell King - ARM Linux
<linux@arm.linux.org.uk> wrote:
> On Wed, Jan 22, 2014 at 08:23:36AM -0800, John Tobias wrote:
>> Hello all,
>>
>> I am using 3.13-rc1 kernel on iMX6SL processor. My filesystem is in
>> eMMC running SDR50.
>> Is anyone here encountered these problem and if there's any existing
>> patch that I can get?.
>
> How reproducable is this?  I notice you're using 3.13-rc1 too, it could
> be the bug has already been fixed in a later kernel version.  -rc1
> kernels are really the "fresh after lots of new feature merging" kernels
> which should always be expected to be rather buggy.
>
> Linux kernel "release candidates" are not "we think this is going to be
> a final kernel, please test it" but -rc1 marks the end of the new
> feature merging and the beginning of the stablisation phase.
>
> --
> FTTC broadband for 0.8mile line: 5.8Mbps down 500kbps up.  Estimation
> in database were 13.1 to 19Mbit for a good line, about 7.5+ for a bad.
> Estimate before purchase was "up to 13.2Mbit".

^ permalink raw reply

* [PATCH v2 06/15] watchdog: orion: Remove unneeded BRIDGE_CAUSE clear
From: Jason Gunthorpe @ 2014-01-22 17:50 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20140122174539.GD27273@localhost>

On Wed, Jan 22, 2014 at 02:45:40PM -0300, Ezequiel Garcia wrote:
 
> Agreed. So, let's assume we can guarantee that request_irq() does the
> job of clearing the cause register (clearing pending irqs).
> 
> So, your suggestion is to put request_irq() in the watchdog start()?
> 
> Otherwise, we can ensure a watchdog full stop at probe(), before
> requesting the IRQ. Both solutions should work, uh?

Right, I would keep the request_irq in probe, just because that feels
more idiomatic..

Jason

^ permalink raw reply

* [PATCH v2 06/15] watchdog: orion: Remove unneeded BRIDGE_CAUSE clear
From: Ezequiel Garcia @ 2014-01-22 17:45 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20140122173417.GT18269@obsidianresearch.com>

On Wed, Jan 22, 2014 at 10:34:17AM -0700, Jason Gunthorpe wrote:
> On Wed, Jan 22, 2014 at 01:49:05PM -0300, Ezequiel Garcia wrote:
> > > Looking at this patch in isolation it looks to me like the clear
> > > bridge lines should be replaced with a request_irq (as that does the
> > > clear) - is the request_irq in the wrong spot?
> > 
> > First of all, it seems to me that the first item "Disable WDT" is not
> > currently true on this driver. orion_wdt_start() seem to reset the
> > counter, but doesn't clear the WDT_EN bit. Do you think we should
> > enforce a "true" disable?
> 
> I think so.
> 
> > Regarding the sequence. Let me see if I got this problem right. The
> > concern here is about the bootloader leaving the registers in a
> > weird-state, right?
> 
> It isn't just bootloaders to worry about, but also things like kexec..
> 
> > In that case, I thought that requesting the IRQ at probe time was enough
> > to ensure the BRIDGE_CAUSE would be cleared by the time the watchdog is
> > started. However, after reading through the irqchip code again, I'm no longer
> > sure this is the case.
> 
> The watchdog should ideally be fully stopped before request_irq so
> there is no possible race.
> 

Agreed. So, let's assume we can guarantee that request_irq() does the
job of clearing the cause register (clearing pending irqs).

So, your suggestion is to put request_irq() in the watchdog start()?

Otherwise, we can ensure a watchdog full stop at probe(), before
requesting the IRQ. Both solutions should work, uh?

I don't have a strong opinion. It's not like the watchdog is going to be
frequently started/stopped (right?) so we can easily do the
request_irq() in the start() without worrying.
-- 
Ezequiel Garc?a, Free Electrons
Embedded Linux, Kernel and Android Engineering
http://free-electrons.com

^ permalink raw reply

* [PATCH 2/6] arm64: Add function to create identity mappings
From: Catalin Marinas @ 2014-01-22 17:39 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1389392950-22457-3-git-send-email-msalter@redhat.com>

On Fri, Jan 10, 2014 at 10:29:06PM +0000, Mark Salter wrote:
> +void __init create_id_mapping(phys_addr_t addr, phys_addr_t size)
> +{
> +	pgd_t *pgd = &idmap_pg_dir[pgd_index(addr)];
> +
> +	if (pgd >= &idmap_pg_dir[ARRAY_SIZE(idmap_pg_dir)]) {
> +		pr_warn("BUG: not creating id mapping for 0x%016llx\n", addr);
> +		return;
> +	}

The condition above is always false since pgd_index() already ands the
index with (PTRS_PER_PGD - 1). Better check addr against something like
(PTRS_PER_PGD * PGDIR_SIZE) (for clarity, you could do other shifts,
doesn't really matter).

-- 
Catalin

^ permalink raw reply

* alloc priv buffer for s5p-mfc
From: randy @ 2014-01-22 17:37 UTC (permalink / raw)
  To: linux-arm-kernel

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Hello
When I was try v4l2-mfc-encoder from samsung, I got the problem below

In my kernel config, mfc buffer is in
                samsung,mfc-r = <0x43000000 0x800000>;
                samsung,mfc-l = <0x51000000 0x800000>;

Shall I change CONFIG_CMA_SIZE_MBYTES to bigger size?
Or I shall alloc mfc's buffer in the other place, which area of ram
can be used as a replacement?
======================logs begin==============================
root at kagami:~/v4l2-mfc-encoder# ./mfc-encode -m /dev/video1 -c h264
mfc codec encoding example application
Andrzej Hajda <a.hajda@samsung.com>
Copyright 2012 Samsung Electronics Co., Ltd.

195.444284217:args.c:parse_args:187: codec: H264
195.459693300:mfc.c:mfc_create:87: MFC device /dev/video1 opened with fd=3
195.475634300:v4l_dev.c:v4l_req_bufs:116: Succesfully requested 16
buffers for device 3:0
195.475773925:func_dev.c:func_req_bufs:42: Succesfully requested 16
buffers for device -1:1
195.475943092:func_dev.c:func_enq_buf:113: Enqueued buffer 0/16 to -1:1
195.476096592:func_dev.c:func_enq_buf:113: Enqueued buffer 1/16 to -1:1
195.476259925:func_dev.c:func_enq_buf:113: Enqueued buffer 2/16 to -1:1
195.476402425:func_dev.c:func_enq_buf:113: Enqueued buffer 3/16 to -1:1
195.476548800:func_dev.c:func_enq_buf:113: Enqueued buffer 4/16 to -1:1
195.476736300:func_dev.c:func_enq_buf:113: Enqueued buffer 5/16 to -1:1
195.476903508:func_dev.c:func_enq_buf:113: Enqueued buffer 6/16 to -1:1
195.477073675:func_dev.c:func_enq_buf:113: Enqueued buffer 7/16 to -1:1
195.477238675:func_dev.c:func_enq_buf:113: Enqueued buffer 8/16 to -1:1
195.477391550:func_dev.c:func_enq_buf:113: Enqueued buffer 9/16 to -1:1
195.477559758:func_dev.c:func_enq_buf:113: Enqueued buffer 10/16 to -1:1
195.477722842:func_dev.c:func_enq_buf:113: Enqueued buffer 11/16 to -1:1
195.477901092:func_dev.c:func_enq_buf:113: Enqueued buffer 12/16 to -1:1
195.478065717:func_dev.c:func_enq_buf:113: Enqueued buffer 13/16 to -1:1
195.478253383:func_dev.c:func_enq_buf:113: Enqueued buffer 14/16 to -1:1
195.478427675:func_dev.c:func_enq_buf:113: Enqueued buffer 15/16 to -1:1
v4l_dev.c:v4l_req_bufs:111: error: Failed to request 4 buffers for
device 3:1)

the dmesg show
[  195.525000]  (null): dma_alloc_coherent of size 2097152 failed
[  195.525000] s5p_mfc_alloc_priv_buf:43: Allocating private buffer failed
[  195.525000] s5p_mfc_alloc_codec_buffers_v5:177: Failed to allocate
Bank1 temporary buffer
[  195.525000] vidioc_reqbufs:1117: Failed to allocate encoding buffers

When I tried program which is written by me(request 16 buffers, but
eacho on is for 640*480, much bigger than mfc-encode)
I got the below in dmesg
[  230.245000]  (null): dma_alloc_coherent of size 155648 failed
[  230.245000] vidioc_querybuf:1178: error in vb2_querybuf() for E(S)
[  230.280000]  (null): dma_alloc_coherent of size 2097152 failed
[  230.285000] s5p_mfc_alloc_priv_buf:43: Allocating private buffer failed
[  230.285000] s5p_mfc_alloc_codec_buffers_v5:186: Failed to allocate
Bank2 temporary buffer
[  230.285000] vidioc_reqbufs:1117: Failed to allocate encoding buffers

Then when I was trying mfc-encode again, I got
root at kagami:~/v4l2-mfc-encoder# ./mfc-encode -m /dev/video1 -c h264
mfc codec encoding example application
Andrzej Hajda <a.hajda@samsung.com>
Copyright 2012 Samsung Electronics Co., Ltd.

265.245904000:args.c:parse_args:187: codec: H264
265.260920417:mfc.c:mfc_create:87: MFC device /dev/video1 opened with fd=3
265.276771750:v4l_dev.c:v4l_req_bufs:116: Succesfully requested 16
buffers for device 3:0
265.276913708:func_dev.c:func_req_bufs:42: Succesfully requested 16
buffers for device -1:1
265.277080750:func_dev.c:func_enq_buf:113: Enqueued buffer 0/16 to -1:1
265.277237833:func_dev.c:func_enq_buf:113: Enqueued buffer 1/16 to -1:1
265.277381833:func_dev.c:func_enq_buf:113: Enqueued buffer 2/16 to -1:1
265.277526708:func_dev.c:func_enq_buf:113: Enqueued buffer 3/16 to -1:1
265.277673000:func_dev.c:func_enq_buf:113: Enqueued buffer 4/16 to -1:1
265.277816542:func_dev.c:func_enq_buf:113: Enqueued buffer 5/16 to -1:1
265.277962375:func_dev.c:func_enq_buf:113: Enqueued buffer 6/16 to -1:1
265.278109792:func_dev.c:func_enq_buf:113: Enqueued buffer 7/16 to -1:1
265.278253917:func_dev.c:func_enq_buf:113: Enqueued buffer 8/16 to -1:1
265.278404958:func_dev.c:func_enq_buf:113: Enqueued buffer 9/16 to -1:1
265.278548417:func_dev.c:func_enq_buf:113: Enqueued buffer 10/16 to -1:1
265.278701792:func_dev.c:func_enq_buf:113: Enqueued buffer 11/16 to -1:1
265.278846542:func_dev.c:func_enq_buf:113: Enqueued buffer 12/16 to -1:1
265.278993708:func_dev.c:func_enq_buf:113: Enqueued buffer 13/16 to -1:1
265.279142042:func_dev.c:func_enq_buf:113: Enqueued buffer 14/16 to -1:1
265.279294542:func_dev.c:func_enq_buf:113: Enqueued buffer 15/16 to -1:1
265.315370875:v4l_dev.c:v4l_req_bufs:116: Succesfully requested 4
buffers for device 3:1
265.315490750:func_dev.c:func_req_bufs:42: Succesfully requested 2
buffers for device 4:0
265.315692417:v4l_dev.c:v4l_enq_buf:211: Enqueued buffer 0/2 to 3:1
265.315892667:v4l_dev.c:v4l_enq_buf:211: Enqueued buffer 1/2 to 3:1
State [enq cnt/max]: [Off 0 0/0|Rdy 16 0/250] [Off 0 0/0|Off 2 0/0]
[Off 0 0/0|Off 0 0/0]
State [enq cnt/max]: [Off 0 0/0|Rdy 16 0/250] [Off 0 0/0|Off 2 0/0]
[Off 0 0/0|Off 0 0/0]
265.316897875:func_dev.c:func_deq_buf:79: Dequeued buffer 0/16 from
- -1:1 ret=25344
v4l_dev.c:v4l_enq_buf:207: error: Error 22 enq buffer 0/16 to 3:0
265.317128125:io_dev.c:process_chain:165: pair 0:1 ret=-1

Then dmesg show that

[  265.310000]  (null): dma_alloc_coherent of size 2097152 failed
====================logs end======================================

Thank you
ayaka
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.12 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iQEcBAEBAgAGBQJS4AHBAAoJEPb4VsMIzTziGbMIAMYuuY4SNIczIn4PmmbjRjcQ
NhaeOqjtbSaeLJWfpKiPBe8yDKgSklCEuddhIcJh1Y9v1GsjpUD5BmTerObGNHWM
jWUvfMpxD7hrbjvqqrwAEWZ7U9lgyAPip2SdPLsEThkIaj0l1IreNvPzYKlXzr59
JGyP155QjIWlZiOoR5yH79s60ZOZoiQnO5d7z0ECyPyIgt3GBAXEBkqksO333O1C
PeeGxDYnZc8zB60tbP+nWIJ0NRH9fxp7J8/9ULt9OwCFcZPDLuEMXMucfszicxXo
TK/C47JdUPnBWmZ5Dz+v2siyL8ubWAzkgk89WB4qtWDejndVcRy9r264va5Z0Ng=
=odW8
-----END PGP SIGNATURE-----

^ permalink raw reply

* [PATCH v2 06/15] watchdog: orion: Remove unneeded BRIDGE_CAUSE clear
From: Jason Gunthorpe @ 2014-01-22 17:34 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20140122164904.GB27273@localhost>

On Wed, Jan 22, 2014 at 01:49:05PM -0300, Ezequiel Garcia wrote:
> > Looking at this patch in isolation it looks to me like the clear
> > bridge lines should be replaced with a request_irq (as that does the
> > clear) - is the request_irq in the wrong spot?
> 
> First of all, it seems to me that the first item "Disable WDT" is not
> currently true on this driver. orion_wdt_start() seem to reset the
> counter, but doesn't clear the WDT_EN bit. Do you think we should
> enforce a "true" disable?

I think so.

> Regarding the sequence. Let me see if I got this problem right. The
> concern here is about the bootloader leaving the registers in a
> weird-state, right?

It isn't just bootloaders to worry about, but also things like kexec..

> In that case, I thought that requesting the IRQ at probe time was enough
> to ensure the BRIDGE_CAUSE would be cleared by the time the watchdog is
> started. However, after reading through the irqchip code again, I'm no longer
> sure this is the case.

The watchdog should ideally be fully stopped before request_irq so
there is no possible race.

> It looks like the BRIDGE_CAUSE register is cleared when the interruption
> is acked (which happens in the handler if I understood the code right).
> So requesting the IRQ is useless...

IMHO, the IRQ stuff should clear out pending edge triggered interrupts
at request_irq time. It makes no sense to take an interrupt for a
stale edge event.

I had always assumed the core code did this via irq_gc_ack_clr_bit -
but I don't see an obvious path..

> Sebastian: If the above is correct, do you think we can add a cause clear to
> the orion irqchip? (supposing it's harmful) Something like this:

Hrm, irq_startup looks like the right hook to put something like this
in.

Jason

^ permalink raw reply

* [PATCH 1/6] arm64: Add macros to manage processor debug state
From: Will Deacon @ 2014-01-22 17:31 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1390401773-12100-2-git-send-email-vijay.kilari@gmail.com>

Hello,

On Wed, Jan 22, 2014 at 02:42:48PM +0000, vijay.kilari at gmail.com wrote:
> From: Vijaya Kumar K <Vijaya.Kumar@caviumnetworks.com>
> 
> Add macros to enable and disable to manage PSTATE.D
> for debugging. The macros local_dbg_save and local_dbg_restore
> are moved to irqflags.h file
> 
> KGDB boot tests fail because of PSTATE.D is masked.
> unmask it for debugging support
> 
> Signed-off-by: Vijaya Kumar K <Vijaya.Kumar@caviumnetworks.com>
> ---
>  arch/arm64/include/asm/debug-monitors.h |   18 ++----------------
>  arch/arm64/include/asm/irqflags.h       |   22 ++++++++++++++++++++++
>  arch/arm64/kernel/debug-monitors.c      |    3 ++-
>  3 files changed, 26 insertions(+), 17 deletions(-)
> 
> diff --git a/arch/arm64/include/asm/debug-monitors.h b/arch/arm64/include/asm/debug-monitors.h
> index 6231479..bc48880 100644
> --- a/arch/arm64/include/asm/debug-monitors.h
> +++ b/arch/arm64/include/asm/debug-monitors.h
> @@ -43,22 +43,8 @@ enum debug_el {
>  #ifndef __ASSEMBLY__
>  struct task_struct;
>  
> -#define local_dbg_save(flags)							\
> -	do {									\
> -		typecheck(unsigned long, flags);				\
> -		asm volatile(							\
> -		"mrs	%0, daif			// local_dbg_save\n"	\
> -		"msr	daifset, #8"						\
> -		: "=r" (flags) : : "memory");					\
> -	} while (0)
> -
> -#define local_dbg_restore(flags)						\
> -	do {									\
> -		typecheck(unsigned long, flags);				\
> -		asm volatile(							\
> -		"msr	daif, %0			// local_dbg_restore\n"	\
> -		: : "r" (flags) : "memory");					\
> -	} while (0)
> +#define local_dbg_enable()	asm("msr	daifclr, #8" : : : "memory")
> +#define local_dbg_disable()	asm("msr	daifset, #8" : : : "memory")

Any reason not to move these to irqflags.h too?

>  #define DBG_ARCH_ID_RESERVED	0	/* In case of ptrace ABI updates. */
>  
> diff --git a/arch/arm64/include/asm/irqflags.h b/arch/arm64/include/asm/irqflags.h
> index b2fcfbc..f163b11 100644
> --- a/arch/arm64/include/asm/irqflags.h
> +++ b/arch/arm64/include/asm/irqflags.h
> @@ -90,5 +90,27 @@ static inline int arch_irqs_disabled_flags(unsigned long flags)
>  	return flags & PSR_I_BIT;
>  }
>  
> +/*
> + * save and restore debug state
> + */
> +static inline unsigned long local_dbg_save(void)
> +{
> +	unsigned long flags;
> +	asm volatile(
> +		"mrs	%0, daif		// local_dbg_save"
> +		"msr	daifset, #8"
> +		: "=r" (flags) : : "memory");
> +	return flags;
> +}
> +
> +static inline void local_dbg_restore(unsigned long flags)
> +{
> +	asm volatile(
> +		"msr	daif, %0	// local_dbg_restore"
> +		:
> +		: "r" (flags)
> +		: "memory");
> +}
> +
>  #endif
>  #endif
> diff --git a/arch/arm64/kernel/debug-monitors.c b/arch/arm64/kernel/debug-monitors.c
> index 23586bd..774ad04 100644
> --- a/arch/arm64/kernel/debug-monitors.c
> +++ b/arch/arm64/kernel/debug-monitors.c
> @@ -51,7 +51,7 @@ u8 debug_monitors_arch(void)
>  static void mdscr_write(u32 mdscr)
>  {
>  	unsigned long flags;
> -	local_dbg_save(flags);
> +	flags = local_dbg_save();

Why are you changing the API? This is now pointlessly different to irqs.

Will

^ permalink raw reply

* [PATCHv14][ 4/4] ARM: dts: imx25: mbimxsd25: Add displays support.
From: Denis Carikli @ 2014-01-22 17:09 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1390410577-22073-1-git-send-email-denis@eukrea.com>

The CMO-QVGA(With backlight), DVI-VGA and DVI-SVGA displays
were added.

Cc: Eric B?nard <eric@eukrea.com>
Cc: Shawn Guo <shawn.guo@linaro.org>
Cc: Sascha Hauer <kernel@pengutronix.de>
Cc: linux-arm-kernel at lists.infradead.org
Signed-off-by: Denis Carikli <denis@eukrea.com>
---
ChangeLog v13->v14:
- Remove people not concerned by this patch from the Cc list.
- changed the fsl,pwmr lcdc property to fsl,lpccr,
  to match the previous patches in that serie.

ChangeLog v10->v13:
- This patch is the display part splitted out from the patch adding
  support for the cpuimx25(and its baseboard).
- Shawn Guo was added to the Cc list.
- The regulator part was updated to match the current style.
- The new GPIO defines are now used in the dts(i).
---
 .../imx25-eukrea-mbimxsd25-baseboard-cmo-qvga.dts  |   72 ++++++++++++++++++++
 .../imx25-eukrea-mbimxsd25-baseboard-dvi-svga.dts  |   45 ++++++++++++
 .../imx25-eukrea-mbimxsd25-baseboard-dvi-vga.dts   |   45 ++++++++++++
 3 files changed, 162 insertions(+)
 create mode 100644 arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard-cmo-qvga.dts
 create mode 100644 arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard-dvi-svga.dts
 create mode 100644 arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard-dvi-vga.dts

diff --git a/arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard-cmo-qvga.dts b/arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard-cmo-qvga.dts
new file mode 100644
index 0000000..9de68de
--- /dev/null
+++ b/arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard-cmo-qvga.dts
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2013 Eukr?a Electromatique <denis@eukrea.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include "imx25-eukrea-mbimxsd25-baseboard.dts"
+
+/ {
+	model = "Eukrea MBIMXSD25 with the CMO-QVGA Display";
+	compatible = "eukrea,mbimxsd25-baseboard-cmo-qvga", "eukrea,mbimxsd25-baseboard", "eukrea,cpuimx25", "fsl,imx25";
+
+	cmo_qvga: display {
+		model = "CMO-QVGA";
+		bits-per-pixel = <16>;
+		fsl,pcr = <0xcad08b80>;
+		bus-width = <18>;
+		native-mode = <&qvga_timings>;
+		display-timings {
+			qvga_timings: 320x240 {
+				clock-frequency = <6500000>;
+				hactive = <320>;
+				vactive = <240>;
+				hback-porch = <30>;
+				hfront-porch = <38>;
+				vback-porch = <20>;
+				vfront-porch = <3>;
+				hsync-len = <15>;
+				vsync-len = <4>;
+			};
+		};
+	};
+
+	regulators {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		reg_lcd_3v3: regulator at 0 {
+			compatible = "regulator-fixed";
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_reg_lcd_3v3>;
+			regulator-name = "lcd-3v3";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			gpio = <&gpio1 26 GPIO_ACTIVE_HIGH>;
+			enable-active-high;
+		};
+	};
+};
+
+&iomuxc {
+	imx25-eukrea-mbimxsd25-baseboard-cmo-qvga {
+		pinctrl_reg_lcd_3v3: reg_lcd_3v3 {
+			fsl,pins = <MX25_PAD_PWM__GPIO_1_26 0x80000000>;
+		};
+	};
+};
+
+&lcdc {
+	display = <&cmo_qvga>;
+	fsl,lpccr = <0x00a903ff>;
+	lcd-supply = <&reg_lcd_3v3>;
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard-dvi-svga.dts b/arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard-dvi-svga.dts
new file mode 100644
index 0000000..8eee2f6
--- /dev/null
+++ b/arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard-dvi-svga.dts
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2013 Eukr?a Electromatique <denis@eukrea.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include "imx25-eukrea-mbimxsd25-baseboard.dts"
+
+/ {
+	model = "Eukrea MBIMXSD25 with the DVI-SVGA Display";
+	compatible = "eukrea,mbimxsd25-baseboard-dvi-svga", "eukrea,mbimxsd25-baseboard", "eukrea,cpuimx25", "fsl,imx25";
+
+	dvi_svga: display {
+		model = "DVI-SVGA";
+		bits-per-pixel = <16>;
+		fsl,pcr = <0xfa208b80>;
+		bus-width = <18>;
+		native-mode = <&dvi_svga_timings>;
+		display-timings {
+			dvi_svga_timings: 800x600 {
+				clock-frequency = <40000000>;
+				hactive = <800>;
+				vactive = <600>;
+				hback-porch = <75>;
+				hfront-porch = <75>;
+				vback-porch = <7>;
+				vfront-porch = <75>;
+				hsync-len = <7>;
+				vsync-len = <7>;
+			};
+		};
+	};
+};
+
+&lcdc {
+	display = <&dvi_svga>;
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard-dvi-vga.dts b/arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard-dvi-vga.dts
new file mode 100644
index 0000000..447da62
--- /dev/null
+++ b/arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard-dvi-vga.dts
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2013 Eukr?a Electromatique <denis@eukrea.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include "imx25-eukrea-mbimxsd25-baseboard.dts"
+
+/ {
+	model = "Eukrea MBIMXSD25 with the DVI-VGA Display";
+	compatible = "eukrea,mbimxsd25-baseboard-dvi-vga", "eukrea,mbimxsd25-baseboard", "eukrea,cpuimx25", "fsl,imx25";
+
+	dvi_vga: display {
+		model = "DVI-VGA";
+		bits-per-pixel = <16>;
+		fsl,pcr = <0xfa208b80>;
+		bus-width = <18>;
+		native-mode = <&dvi_vga_timings>;
+		display-timings {
+			dvi_vga_timings: 640x480 {
+				clock-frequency = <31250000>;
+				hactive = <640>;
+				vactive = <480>;
+				hback-porch = <100>;
+				hfront-porch = <100>;
+				vback-porch = <7>;
+				vfront-porch = <100>;
+				hsync-len = <7>;
+				vsync-len = <7>;
+			};
+		};
+	};
+};
+
+&lcdc {
+	display = <&dvi_vga>;
+	status = "okay";
+};
-- 
1.7.9.5

^ permalink raw reply related

* [PATCHv14][ 3/4] video: Kconfig: Allow more broad selection of the imxfb framebuffer driver.
From: Denis Carikli @ 2014-01-22 17:09 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1390410577-22073-1-git-send-email-denis@eukrea.com>

Without that patch, a user can't select the imxfb driver when the i.MX25 and/or
  the i.MX27 device tree board are selected and that no boards that selects
  IMX_HAVE_PLATFORM_IMX_FB are compiled in.

Cc: Eric B?nard <eric@eukrea.com>
Cc: Jean-Christophe Plagniol-Villard <plagnioj@jcrosoft.com>
Cc: Sascha Hauer <kernel@pengutronix.de>
Cc: Tomi Valkeinen <tomi.valkeinen@ti.com>
Cc: linux-arm-kernel at lists.infradead.org
Cc: linux-fbdev at vger.kernel.org
Signed-off-by: Denis Carikli <denis@eukrea.com>
Acked-by: Shawn Guo <shawn.guo@linaro.org>
Acked-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
Acked-by: Sascha Hauer <s.hauer@pengutronix.de>
---
ChangeLog v11->v14:
- Remove people not concerned by this patch from the Cc list.

ChangeLog v10->v11:
- moved my signed-off-by.

ChangeLog v8->v9:
- Added Jean-Christophe PLAGNIOL-VILLARD's ACK.
---
 drivers/video/Kconfig |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 22262a3..dade5b7 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -364,7 +364,7 @@ config FB_SA1100
 
 config FB_IMX
 	tristate "Freescale i.MX1/21/25/27 LCD support"
-	depends on FB && IMX_HAVE_PLATFORM_IMX_FB
+	depends on FB && ARCH_MXC
 	select FB_CFB_FILLRECT
 	select FB_CFB_COPYAREA
 	select FB_CFB_IMAGEBLIT
-- 
1.7.9.5

^ permalink raw reply related

* [PATCHv14][ 1/4] video: imxfb: Introduce regulator support.
From: Denis Carikli @ 2014-01-22 17:09 UTC (permalink / raw)
  To: linux-arm-kernel

This commit is based on the following commit by Fabio Estevam:
  4344429 video: mxsfb: Introduce regulator support

Cc: Eric B?nard <eric@eukrea.com>
Cc: Sascha Hauer <kernel@pengutronix.de>
Cc: linux-arm-kernel at lists.infradead.org
Cc: linux-fbdev at vger.kernel.org
Signed-off-by: Denis Carikli <denis@eukrea.com>
---
ChangeLog v13->v14:
- Remove people not concerned by this patch from the Cc list.
- Simplified the regulator handling: The regulator-core now supplies
  a dummy regulator if one hasn't been hooked up explicitely.
  So we don't need to handle that case in the driver.
  The code has been updated to do that, and the error messages
  were updated accordingly.

ChangeLog v9->v10:
- Added a return 0; at the end of imxfb_disable_controller.

ChangeLog v8->v9:
- return an error if regulator_{enable,disable} fails in
  imxfb_{enable,disable}_controller, and use it.
---
 drivers/video/imxfb.c |   38 +++++++++++++++++++++++++-------------
 1 file changed, 25 insertions(+), 13 deletions(-)

diff --git a/drivers/video/imxfb.c b/drivers/video/imxfb.c
index 44ee678..dd8a35d 100644
--- a/drivers/video/imxfb.c
+++ b/drivers/video/imxfb.c
@@ -28,6 +28,7 @@
 #include <linux/cpufreq.h>
 #include <linux/clk.h>
 #include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
 #include <linux/dma-mapping.h>
 #include <linux/io.h>
 #include <linux/math64.h>
@@ -145,6 +146,7 @@ struct imxfb_info {
 	struct clk		*clk_ipg;
 	struct clk		*clk_ahb;
 	struct clk		*clk_per;
+	struct regulator	*reg_lcd;
 	enum imxfb_type		devtype;
 	bool			enabled;
 
@@ -561,14 +563,16 @@ static void imxfb_exit_backlight(struct imxfb_info *fbi)
 }
 #endif
 
-static void imxfb_enable_controller(struct imxfb_info *fbi)
+static int imxfb_enable_controller(struct imxfb_info *fbi)
 {
-
 	if (fbi->enabled)
-		return;
+		return 0;
 
 	pr_debug("Enabling LCD controller\n");
 
+	if (regulator_enable(fbi->reg_lcd))
+		dev_err(&fbi->pdev->dev, "Failed to enable regulator.\n");
+
 	writel(fbi->screen_dma, fbi->regs + LCDC_SSA);
 
 	/* panning offset 0 (0 pixel offset)        */
@@ -593,12 +597,14 @@ static void imxfb_enable_controller(struct imxfb_info *fbi)
 		fbi->backlight_power(1);
 	if (fbi->lcd_power)
 		fbi->lcd_power(1);
+
+	return 0;
 }
 
-static void imxfb_disable_controller(struct imxfb_info *fbi)
+static int imxfb_disable_controller(struct imxfb_info *fbi)
 {
 	if (!fbi->enabled)
-		return;
+		return 0;
 
 	pr_debug("Disabling LCD controller\n");
 
@@ -613,6 +619,11 @@ static void imxfb_disable_controller(struct imxfb_info *fbi)
 	fbi->enabled = false;
 
 	writel(0, fbi->regs + LCDC_RMCR);
+
+	if(regulator_disable(fbi->reg_lcd))
+		dev_err(&fbi->pdev->dev, "Failed to disable regulator.\n");
+
+	return 0;
 }
 
 static int imxfb_blank(int blank, struct fb_info *info)
@@ -626,13 +637,12 @@ static int imxfb_blank(int blank, struct fb_info *info)
 	case FB_BLANK_VSYNC_SUSPEND:
 	case FB_BLANK_HSYNC_SUSPEND:
 	case FB_BLANK_NORMAL:
-		imxfb_disable_controller(fbi);
-		break;
+		return imxfb_disable_controller(fbi);
 
 	case FB_BLANK_UNBLANK:
-		imxfb_enable_controller(fbi);
-		break;
+		return imxfb_enable_controller(fbi);
 	}
+
 	return 0;
 }
 
@@ -734,8 +744,7 @@ static int imxfb_suspend(struct platform_device *dev, pm_message_t state)
 
 	pr_debug("%s\n", __func__);
 
-	imxfb_disable_controller(fbi);
-	return 0;
+	return imxfb_disable_controller(fbi);
 }
 
 static int imxfb_resume(struct platform_device *dev)
@@ -745,8 +754,7 @@ static int imxfb_resume(struct platform_device *dev)
 
 	pr_debug("%s\n", __func__);
 
-	imxfb_enable_controller(fbi);
-	return 0;
+	return imxfb_enable_controller(fbi);
 }
 #else
 #define imxfb_suspend	NULL
@@ -1020,6 +1028,10 @@ static int imxfb_probe(struct platform_device *pdev)
 		goto failed_register;
 	}
 
+	fbi->reg_lcd = devm_regulator_get(&pdev->dev, "lcd");
+	if (IS_ERR(fbi->reg_lcd))
+		return PTR_ERR(fbi->reg_lcd);
+
 	imxfb_enable_controller(fbi);
 	fbi->pdev = pdev;
 #ifdef PWMR_BACKLIGHT_AVAILABLE
-- 
1.7.9.5

^ permalink raw reply related

* [PATCH v3 08/15] watchdog: orion: Introduce per-compatible of_device_id data
From: Ezequiel Garcia @ 2014-01-22 17:06 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20140121163547.GB3311@roeck-us.net>

On Tue, Jan 21, 2014 at 08:35:47AM -0800, Guenter Roeck wrote:
> On Tue, Jan 21, 2014 at 10:26:07AM -0300, Ezequiel Garcia wrote:
> > This commit adds an orion_watchdog_data structure to holda compatible-data
> 
> 	s/holda/hold/
> 

Yup.

> > information. This allows to remove the driver-wide definition and to
> > future add support for multiple compatible-strings.
> 
> Maybe "and to be able to add support for multiple compatible-strings in the
> future" ?
> 

Yes, sounds better.

[..]
> >  
> >  #define WDT_MAX_CYCLE_COUNT	0xffffffff
> >  #define WDT_IN_USE		0
> >  #define WDT_OK_TO_CLOSE		1
> >  
> While looking at the new defines below, I noticed that WDT_IN_USE and
> WDT_OK_TO_CLOSE are not used (anymore ?) and thus should be removed
> (separate patch, though).
> 

OK, let's clean this.

> > -#define WDT_RESET_OUT_EN	BIT(1)
> > +#define WDT_A370_RATIO_MASK(v)	((v) << 16)
> > +#define WDT_A370_RATIO_SHIFT	5
> > +#define WDT_A370_RATIO		(1 << WDT_A370_RATIO_SHIFT)
> > +
> > +#define WDT_AXP_FIXED_ENABLE_BIT BIT(10)
> >  
> Those new defines are not used. They should be introduced if and when used.
> 

Hm... maybe after dozens and dozens of rebases these macros sneaked here?

[..]
> >  
> > +	match = of_match_device(orion_wdt_of_match_table, &pdev->dev);
> > +	if (!match)
> > +		/* Default legacy match */
> > +		match = &orion_wdt_of_match_table[0];
> > +
> >  	dev->wdt.info = &orion_wdt_info;
> >  	dev->wdt.ops = &orion_wdt_ops;
> >  	dev->wdt.min_timeout = 1;
> > +	dev->data = (struct orion_watchdog_data *)match->data;
> 
> match->data is a void *, so the typecast should not be needed here.
> You might want to declare 'data' to be of type
> 'const struct orion_watchdog_data *' because otherwise you loose the
> 'const' attribute of match->data (which may be the reason for the typecast ?).
> 

Done.

Thanks a lot for reviewing!
-- 
Ezequiel Garc?a, Free Electrons
Embedded Linux, Kernel and Android Engineering
http://free-electrons.com

^ permalink raw reply

* [PATCH v2] dma: Add Xilinx AXI Video Direct Memory Access Engine driver support
From: Srikanth Thokala @ 2014-01-22 16:52 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1390409565-4200-1-git-send-email-sthokal@xilinx.com>

This is the driver for the AXI Video Direct Memory Access (AXI
VDMA) core, which is a soft Xilinx IP core that provides high-
bandwidth direct memory access between memory and AXI4-Stream
type video target peripherals. The core provides efficient two
dimensional DMA operations with independent asynchronous read
and write channel operation.

This module works on Zynq (ARM Based SoC) and Microblaze platforms.

Signed-off-by: Srikanth Thokala <sthokal@xilinx.com>
---
NOTE:
1. Created a separate directory 'dma/xilinx' as Xilinx has two more
   DMA IPs and we are also planning to upstream these drivers soon.
2. Rebased on v3.13.0-rc8

Changes in v2:
- Removed DMA Test client module from the patchset as suggested
  by Andy Shevchenko
- Removed device-id DT property, as suggested by Arnd Bergmann
- Properly documented DT bindings as suggested by Arnd Bergmann
- Returning with error, if registration of DMA to node fails
- Fixed typo errors
- Used BIT() macro at applicable places
- Added missing header file to the patchset
- Changed copyright year to include 2014
---
 .../devicetree/bindings/dma/xilinx/xilinx_vdma.txt |   75 +
 drivers/dma/Kconfig                                |   14 +
 drivers/dma/Makefile                               |    1 +
 drivers/dma/xilinx/Makefile                        |    1 +
 drivers/dma/xilinx/xilinx_vdma.c                   | 1486 ++++++++++++++++++++
 include/linux/amba/xilinx_dma.h                    |   50 +
 6 files changed, 1627 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/dma/xilinx/xilinx_vdma.txt
 create mode 100644 drivers/dma/xilinx/Makefile
 create mode 100644 drivers/dma/xilinx/xilinx_vdma.c
 create mode 100644 include/linux/amba/xilinx_dma.h

diff --git a/Documentation/devicetree/bindings/dma/xilinx/xilinx_vdma.txt b/Documentation/devicetree/bindings/dma/xilinx/xilinx_vdma.txt
new file mode 100644
index 0000000..ab8be1a
--- /dev/null
+++ b/Documentation/devicetree/bindings/dma/xilinx/xilinx_vdma.txt
@@ -0,0 +1,75 @@
+Xilinx AXI VDMA engine, it does transfers between memory and video devices.
+It can be configured to have one channel or two channels. If configured
+as two channels, one is to transmit to the video device and another is
+to receive from the video device.
+
+Required properties:
+- compatible: Should be "xlnx,axi-vdma-1.00.a"
+- #dma-cells: Should be <1>, see "dmas" property below
+- reg: Should contain VDMA registers location and length.
+- xlnx,num-fstores: Should be the number of framebuffers as configured in h/w.
+- dma-channel child node: Should have atleast one channel and can have upto
+	two channels per device. This node specifies the properties of each
+	DMA channel (see child node properties below).
+
+Optional properties:
+- xlnx,include-sg: Tells whether configured for Scatter-mode in
+	the hardware.
+- xlnx,flush-fsync: Tells whether which channel to Flush on Frame sync.
+	It takes following values:
+	{1}, flush both channels
+	{2}, flush mm2s channel
+	{3}, flush s2mm channel
+
+Required child node properties:
+- compatible: It should be either "xlnx,axi-vdma-mm2s-channel" or
+	"xlnx,axi-vdma-s2mm-channel".
+- interrupts: Should contain per channel VDMA interrupts.
+- xlnx,data-width: Should contain the stream data width, take values
+	{32,64...1024}.
+
+Option child node properties:
+- xlnx,include-dre: Tells whether hardware is configured for Data
+	Realignment Engine.
+- xlnx,genlock-mode: Tells whether Genlock synchronization is
+	enabled/disabled in hardware.
+
+Example:
+++++++++
+
+axi_vdma_0: axivdma at 40030000 {
+	compatible = "xlnx,axi-vdma-1.00.a";
+	#dma_cells = <1>;
+	reg = < 0x40030000 0x10000 >;
+	xlnx,num-fstores = <0x8>;
+	xlnx,flush-fsync = <0x1>;
+	dma-channel at 40030000 {
+		compatible = "xlnx,axi-vdma-mm2s-channel";
+		interrupts = < 0 54 4 >;
+		xlnx,datawidth = <0x40>;
+	} ;
+	dma-channel at 40030030 {
+		compatible = "xlnx,axi-vdma-s2mm-channel";
+		interrupts = < 0 53 4 >;
+		xlnx,datawidth = <0x40>;
+	} ;
+} ;
+
+
+* DMA client
+
+Required properties:
+- dmas: a list of <[Video DMA device phandle] [Channel ID]> pairs,
+	where Channel ID is '0' for write/tx and '1' for read/rx
+	channel.
+- dma-names: a list of DMA channel names, one per "dmas" entry
+
+Example:
+++++++++
+
+vdmatest_0: vdmatest at 0 {
+	compatible ="xlnx,axi-vdma-test-1.00.a";
+	dmas = <&axi_vdma_0 0
+		&axi_vdma_0 1>;
+	dma-names = "vdma0", "vdma1";
+} ;
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index c823daa..2a74651 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -334,6 +334,20 @@ config K3_DMA
 	  Support the DMA engine for Hisilicon K3 platform
 	  devices.
 
+config XILINX_VDMA
+	tristate "Xilinx AXI VDMA Engine"
+	depends on (ARCH_ZYNQ || MICROBLAZE)
+	select DMA_ENGINE
+	help
+	  Enable support for Xilinx AXI VDMA Soft IP.
+
+	  This engine provides high-bandwidth direct memory access
+	  between memory and AXI4-Stream video type target
+	  peripherals including peripherals which support AXI4-
+	  Stream Video Protocol.  It has two stream interfaces/
+	  channels, Memory Mapped to Stream (MM2S) and Stream to
+	  Memory Mapped (S2MM) for the data transfers.
+
 config DMA_ENGINE
 	bool
 
diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile
index 0ce2da9..d84130b 100644
--- a/drivers/dma/Makefile
+++ b/drivers/dma/Makefile
@@ -42,3 +42,4 @@ obj-$(CONFIG_MMP_PDMA) += mmp_pdma.o
 obj-$(CONFIG_DMA_JZ4740) += dma-jz4740.o
 obj-$(CONFIG_TI_CPPI41) += cppi41.o
 obj-$(CONFIG_K3_DMA) += k3dma.o
+obj-y += xilinx/
diff --git a/drivers/dma/xilinx/Makefile b/drivers/dma/xilinx/Makefile
new file mode 100644
index 0000000..3c4e9f2
--- /dev/null
+++ b/drivers/dma/xilinx/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_XILINX_VDMA) += xilinx_vdma.o
diff --git a/drivers/dma/xilinx/xilinx_vdma.c b/drivers/dma/xilinx/xilinx_vdma.c
new file mode 100644
index 0000000..4c0d04c
--- /dev/null
+++ b/drivers/dma/xilinx/xilinx_vdma.c
@@ -0,0 +1,1486 @@
+/*
+ * DMA driver for Xilinx Video DMA Engine
+ *
+ * Copyright (C) 2010-2014 Xilinx, Inc. All rights reserved.
+ *
+ * Based on the Freescale DMA driver.
+ *
+ * Description:
+ * The AXI Video Direct Memory Access (AXI VDMA) core is a soft Xilinx IP
+ * core that provides high-bandwidth direct memory access between memory
+ * and AXI4-Stream type video target peripherals. The core provides efficient
+ * two dimensional DMA operations with independent asynchronous read (S2MM)
+ * and write (MM2S) channel operation. It can be configured to have either
+ * one channel or two channels. If configured as two channels, one is to
+ * transmit to the video device (MM2S) and another is to receive from the
+ * video device (S2MM). Initialization, status, interrupt and management
+ * registers are accessed through an AXI4-Lite slave interface.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/amba/xilinx_dma.h>
+#include <linux/bitops.h>
+#include <linux/dmapool.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/of_dma.h>
+#include <linux/of_platform.h>
+#include <linux/of_irq.h>
+#include <linux/slab.h>
+
+/* Register/Descriptor Offsets */
+#define XILINX_VDMA_MM2S_CTRL_OFFSET		0x0000
+#define XILINX_VDMA_S2MM_CTRL_OFFSET		0x0030
+#define XILINX_VDMA_MM2S_DESC_OFFSET		0x0050
+#define XILINX_VDMA_S2MM_DESC_OFFSET		0x00a0
+
+/* Control Registers */
+#define XILINX_VDMA_REG_DMACR			0x0000
+#define XILINX_VDMA_DMACR_DELAY_MAX		0xff
+#define XILINX_VDMA_DMACR_DELAY_SHIFT		24
+#define XILINX_VDMA_DMACR_FRAME_COUNT_MAX	0xff
+#define XILINX_VDMA_DMACR_FRAME_COUNT_SHIFT	16
+#define XILINX_VDMA_DMACR_ERR_IRQ		BIT(14)
+#define XILINX_VDMA_DMACR_DLY_CNT_IRQ		BIT(13)
+#define XILINX_VDMA_DMACR_FRM_CNT_IRQ		BIT(12)
+#define XILINX_VDMA_DMACR_MASTER_SHIFT		8
+#define XILINX_VDMA_DMACR_FSYNCSRC_SHIFT	5
+#define XILINX_VDMA_DMACR_FRAMECNT_EN		BIT(4)
+#define XILINX_VDMA_DMACR_GENLOCK_EN		BIT(3)
+#define XILINX_VDMA_DMACR_RESET			BIT(2)
+#define XILINX_VDMA_DMACR_CIRC_EN		BIT(1)
+#define XILINX_VDMA_DMACR_RUNSTOP		BIT(0)
+#define XILINX_VDMA_DMACR_DELAY_MASK		\
+				(XILINX_VDMA_DMACR_DELAY_MAX << \
+				XILINX_VDMA_DMACR_DELAY_SHIFT)
+#define XILINX_VDMA_DMACR_FRAME_COUNT_MASK	\
+				(XILINX_VDMA_DMACR_FRAME_COUNT_MAX << \
+				XILINX_VDMA_DMACR_FRAME_COUNT_SHIFT)
+#define XILINX_VDMA_DMACR_MASTER_MASK		\
+				(0xf << XILINX_VDMA_DMACR_MASTER_SHIFT)
+#define XILINX_VDMA_DMACR_FSYNCSRC_MASK		\
+				(3 << XILINX_VDMA_DMACR_FSYNCSRC_SHIFT)
+
+#define XILINX_VDMA_REG_DMASR			0x0004
+#define XILINX_VDMA_DMASR_DELAY_SHIFT		24
+#define XILINX_VDMA_DMASR_FRAME_COUNT_SHIFT	16
+#define XILINX_VDMA_DMASR_EOL_LATE_ERR		BIT(15)
+#define XILINX_VDMA_DMASR_ERR_IRQ		BIT(14)
+#define XILINX_VDMA_DMASR_DLY_CNT_IRQ		BIT(13)
+#define XILINX_VDMA_DMASR_FRM_CNT_IRQ		BIT(12)
+#define XILINX_VDMA_DMASR_SOF_LATE_ERR		BIT(11)
+#define XILINX_VDMA_DMASR_SG_DEC_ERR		BIT(10)
+#define XILINX_VDMA_DMASR_SG_SLV_ERR		BIT(9)
+#define XILINX_VDMA_DMASR_EOF_EARLY_ERR		BIT(8)
+#define XILINX_VDMA_DMASR_SOF_EARLY_ERR		BIT(7)
+#define XILINX_VDMA_DMASR_DMA_DEC_ERR		BIT(6)
+#define XILINX_VDMA_DMASR_DMA_SLAVE_ERR		BIT(5)
+#define XILINX_VDMA_DMASR_DMA_INT_ERR		BIT(4)
+#define XILINX_VDMA_DMASR_IDLE			BIT(1)
+#define XILINX_VDMA_DMASR_HALTED		BIT(0)
+
+#define XILINX_VDMA_DMASR_DELAY_MASK		\
+				(0xff << XILINX_VDMA_DMASR_DELAY_SHIFT)
+#define XILINX_VDMA_DMASR_FRAME_COUNT_MASK	\
+				(0xff << XILINX_VDMA_DMASR_FRAME_COUNT_SHIFT)
+
+#define XILINX_VDMA_REG_CURDESC			0x0008
+#define XILINX_VDMA_REG_TAILDESC		0x0010
+#define XILINX_VDMA_REG_REG_INDEX		0x0014
+#define XILINX_VDMA_REG_FRMSTORE		0x0018
+#define XILINX_VDMA_REG_THRESHOLD		0x001c
+#define XILINX_VDMA_REG_FRMPTR_STS		0x0024
+#define XILINX_VDMA_REG_PARK_PTR		0x0028
+#define XILINX_VDMA_PARK_PTR_WR_REF_SHIFT	8
+#define XILINX_VDMA_PARK_PTR_RD_REF_SHIFT	0
+#define XILINX_VDMA_REG_VDMA_VERSION		0x002c
+
+/* Register Direct Mode Registers */
+#define XILINX_VDMA_REG_VSIZE			0x0000
+#define XILINX_VDMA_REG_HSIZE			0x0004
+
+#define XILINX_VDMA_REG_FRMDLY_STRIDE		0x0008
+#define XILINX_VDMA_FRMDLY_STRIDE_FRMDLY_SHIFT	24
+#define XILINX_VDMA_FRMDLY_STRIDE_STRIDE_SHIFT	0
+#define XILINX_VDMA_FRMDLY_STRIDE_FRMDLY_MASK	\
+				(0x1f <<	\
+				XILINX_VDMA_FRMDLY_STRIDE_FRMDLY_SHIFT)
+#define XILINX_VDMA_FRMDLY_STRIDE_STRIDE_MASK	\
+				(0xffff <<	\
+				XILINX_VDMA_FRMDLY_STRIDE_STRIDE_MASK)
+
+#define XILINX_VDMA_REG_START_ADDRESS(n)	(0x000c + 4 * (n))
+
+/* Hw specific definitions */
+#define XILINX_VDMA_MAX_CHANS_PER_DEVICE	0x2
+
+#define XILINX_VDMA_DMAXR_ALL_IRQ_MASK	(XILINX_VDMA_DMASR_FRM_CNT_IRQ | \
+					 XILINX_VDMA_DMASR_DLY_CNT_IRQ | \
+					 XILINX_VDMA_DMASR_ERR_IRQ)
+
+#define XILINX_VDMA_DMASR_ALL_ERR_MASK	(XILINX_VDMA_DMASR_EOL_LATE_ERR | \
+					 XILINX_VDMA_DMASR_SOF_LATE_ERR | \
+					 XILINX_VDMA_DMASR_SG_DEC_ERR | \
+					 XILINX_VDMA_DMASR_SG_SLV_ERR | \
+					 XILINX_VDMA_DMASR_EOF_EARLY_ERR | \
+					 XILINX_VDMA_DMASR_SOF_EARLY_ERR | \
+					 XILINX_VDMA_DMASR_DMA_DEC_ERR | \
+					 XILINX_VDMA_DMASR_DMA_SLAVE_ERR | \
+					 XILINX_VDMA_DMASR_DMA_INT_ERR)
+
+/*
+ * Recoverable errors are DMA Internal error, SOF Early, EOF Early and SOF Late.
+ * They are only recoverable when C_FLUSH_ON_FSYNC is enabled in the h/w system.
+ */
+#define XILINX_VDMA_DMASR_ERR_RECOVER_MASK	\
+					(XILINX_VDMA_DMASR_SOF_LATE_ERR | \
+					 XILINX_VDMA_DMASR_EOF_EARLY_ERR | \
+					 XILINX_VDMA_DMASR_SOF_EARLY_ERR | \
+					 XILINX_VDMA_DMASR_DMA_INT_ERR)
+
+/* Axi VDMA Flush on Fsync bits */
+#define XILINX_VDMA_FLUSH_S2MM			3
+#define XILINX_VDMA_FLUSH_MM2S			2
+#define XILINX_VDMA_FLUSH_BOTH			1
+
+/* Delay loop counter to prevent hardware failure */
+#define XILINX_VDMA_LOOP_COUNT			1000000
+
+/**
+ * struct xilinx_vdma_desc_hw - Hardware Descriptor
+ * @next_desc: Next Descriptor Pointer @0x00
+ * @pad1: Reserved @0x04
+ * @buf_addr: Buffer address @0x08
+ * @pad2: Reserved @0x0C
+ * @vsize: Vertical Size @0x10
+ * @hsize: Horizontal Size @0x14
+ * @stride: Number of bytes between the first
+ *	    pixels of each horizontal line @0x18
+ */
+struct xilinx_vdma_desc_hw {
+	u32 next_desc;
+	u32 pad1;
+	u32 buf_addr;
+	u32 pad2;
+	u32 vsize;
+	u32 hsize;
+	u32 stride;
+} __aligned(64);
+
+/**
+ * struct xilinx_vdma_tx_segment - Descriptor segment
+ * @hw: Hardware descriptor
+ * @node: Node in the descriptor segments list
+ * @cookie: Segment cookie
+ * @phys: Physical address of segment
+ */
+struct xilinx_vdma_tx_segment {
+	struct xilinx_vdma_desc_hw hw;
+	struct list_head node;
+	dma_cookie_t cookie;
+	dma_addr_t phys;
+} __aligned(64);
+
+/**
+ * struct xilinx_vdma_tx_descriptor - Per Transaction structure
+ * @async_tx: Async transaction descriptor
+ * @segments: TX segments list
+ * @node: Node in the channel descriptors list
+ */
+struct xilinx_vdma_tx_descriptor {
+	struct dma_async_tx_descriptor async_tx;
+	struct list_head segments;
+	struct list_head node;
+};
+
+#define to_vdma_tx_descriptor(tx) \
+	container_of(tx, struct xilinx_vdma_tx_descriptor, async_tx)
+
+/**
+ * struct xilinx_vdma_chan - Driver specific VDMA channel structure
+ * @xdev: Driver specific device structure
+ * @ctrl_offset: Control registers offset
+ * @desc_offset: TX descriptor registers offset
+ * @completed_cookie: Maximum cookie completed
+ * @cookie: The current cookie
+ * @lock: Descriptor operation lock
+ * @pending_list: Descriptors waiting
+ * @active_desc: Active descriptor
+ * @done_list: Complete descriptors
+ * @common: DMA common channel
+ * @desc_pool: Descriptors pool
+ * @dev: The dma device
+ * @irq: Channel IRQ
+ * @id: Channel ID
+ * @direction: Transfer direction
+ * @num_frms: Number of frames
+ * @has_sg: Support scatter transfers
+ * @genlock: Support genlock mode
+ * @err: Channel has errors
+ * @tasklet: Cleanup work after irq
+ * @config: Device configuration info
+ * @flush_on_fsync: Flush on Frame sync
+ */
+struct xilinx_vdma_chan {
+	struct xilinx_vdma_device *xdev;
+	u32 ctrl_offset;
+	u32 desc_offset;
+	dma_cookie_t completed_cookie;
+	dma_cookie_t cookie;
+	spinlock_t lock;
+	struct list_head pending_list;
+	struct xilinx_vdma_tx_descriptor *active_desc;
+	struct list_head done_list;
+	struct dma_chan common;
+	struct dma_pool *desc_pool;
+	struct device *dev;
+	int irq;
+	int id;
+	enum dma_transfer_direction direction;
+	int num_frms;
+	bool has_sg;
+	bool genlock;
+	bool err;
+	struct tasklet_struct tasklet;
+	struct xilinx_vdma_config config;
+	bool flush_on_fsync;
+};
+
+/**
+ * struct xilinx_vdma_device - VDMA device structure
+ * @regs: I/O mapped base address
+ * @dev: Device Structure
+ * @common: DMA device structure
+ * @chan: Driver specific VDMA channel
+ * @has_sg: Specifies whether Scatter-Gather is present or not
+ * @flush_on_fsync: Flush on frame sync
+ */
+struct xilinx_vdma_device {
+	void __iomem *regs;
+	struct device *dev;
+	struct dma_device common;
+	struct xilinx_vdma_chan *chan[XILINX_VDMA_MAX_CHANS_PER_DEVICE];
+	bool has_sg;
+	u32 flush_on_fsync;
+};
+
+#define to_xilinx_chan(chan) \
+			container_of(chan, struct xilinx_vdma_chan, common)
+
+/* IO accessors */
+static inline u32 vdma_read(struct xilinx_vdma_chan *chan, u32 reg)
+{
+	return ioread32(chan->xdev->regs + reg);
+}
+
+static inline void vdma_write(struct xilinx_vdma_chan *chan, u32 reg, u32 value)
+{
+	iowrite32(value, chan->xdev->regs + reg);
+}
+
+static inline void vdma_desc_write(struct xilinx_vdma_chan *chan, u32 reg,
+				   u32 value)
+{
+	vdma_write(chan, chan->desc_offset + reg, value);
+}
+
+static inline u32 vdma_ctrl_read(struct xilinx_vdma_chan *chan, u32 reg)
+{
+	return vdma_read(chan, chan->ctrl_offset + reg);
+}
+
+static inline void vdma_ctrl_write(struct xilinx_vdma_chan *chan, u32 reg,
+				   u32 value)
+{
+	vdma_write(chan, chan->ctrl_offset + reg, value);
+}
+
+static inline void vdma_ctrl_clr(struct xilinx_vdma_chan *chan, u32 reg,
+				 u32 clr)
+{
+	vdma_ctrl_write(chan, reg, vdma_ctrl_read(chan, reg) & ~clr);
+}
+
+static inline void vdma_ctrl_set(struct xilinx_vdma_chan *chan, u32 reg,
+				 u32 set)
+{
+	vdma_ctrl_write(chan, reg, vdma_ctrl_read(chan, reg) | set);
+}
+
+/* -----------------------------------------------------------------------------
+ * Descriptors and segments alloc and free
+ */
+
+/**
+ * xilinx_vdma_alloc_tx_segment - Allocate transaction segment
+ * @chan: Driver specific VDMA channel
+ *
+ * Return: The allocated segment on success and NULL on failure.
+ */
+static struct xilinx_vdma_tx_segment *
+xilinx_vdma_alloc_tx_segment(struct xilinx_vdma_chan *chan)
+{
+	struct xilinx_vdma_tx_segment *segment;
+	dma_addr_t phys;
+
+	segment = dma_pool_alloc(chan->desc_pool, GFP_ATOMIC, &phys);
+	if (!segment)
+		return NULL;
+
+	memset(segment, 0, sizeof(*segment));
+	segment->phys = phys;
+
+	return segment;
+}
+
+/**
+ * xilinx_vdma_free_tx_segment - Free transaction segment
+ * @chan: Driver specific VDMA channel
+ * @segment: VDMA transaction segment
+ */
+static void xilinx_vdma_free_tx_segment(struct xilinx_vdma_chan *chan,
+					struct xilinx_vdma_tx_segment *segment)
+{
+	dma_pool_free(chan->desc_pool, segment, segment->phys);
+}
+
+/**
+ * xilinx_vdma_tx_descriptor - Allocate transaction descriptor
+ * @chan: Driver specific VDMA channel
+ *
+ * Return: The allocated descriptor on success and NULL on failure.
+ */
+static struct xilinx_vdma_tx_descriptor *
+xilinx_vdma_alloc_tx_descriptor(struct xilinx_vdma_chan *chan)
+{
+	struct xilinx_vdma_tx_descriptor *desc;
+
+	desc = kzalloc(sizeof(*desc), GFP_KERNEL);
+	if (!desc)
+		return NULL;
+
+	INIT_LIST_HEAD(&desc->segments);
+
+	return desc;
+}
+
+/**
+ * xilinx_vdma_free_tx_descriptor - Free transaction descriptor
+ * @chan: Driver specific VDMA channel
+ * @desc: VDMA transaction descriptor
+ */
+static void
+xilinx_vdma_free_tx_descriptor(struct xilinx_vdma_chan *chan,
+			       struct xilinx_vdma_tx_descriptor *desc)
+{
+	struct xilinx_vdma_tx_segment *segment, *next;
+
+	if (!desc)
+		return;
+
+	list_for_each_entry_safe(segment, next, &desc->segments, node) {
+		list_del(&segment->node);
+		xilinx_vdma_free_tx_segment(chan, segment);
+	}
+
+	kfree(desc);
+}
+
+/* Required functions */
+
+/**
+ * xilinx_vdma_free_descriptors - Free descriptors list
+ * @chan: Driver specific VDMA channel
+ * @list: List to parse and delete the descriptor
+ */
+static void xilinx_vdma_free_desc_list(struct xilinx_vdma_chan *chan,
+					struct list_head *list)
+{
+	struct xilinx_vdma_tx_descriptor *desc, *next;
+
+	list_for_each_entry_safe(desc, next, list, node) {
+		list_del(&desc->node);
+		xilinx_vdma_free_tx_descriptor(chan, desc);
+	}
+}
+
+/**
+ * xilinx_vdma_free_descriptors - Free channel descriptors
+ * @chan: Driver specific VDMA channel
+ */
+static void xilinx_vdma_free_descriptors(struct xilinx_vdma_chan *chan)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&chan->lock, flags);
+
+	xilinx_vdma_free_desc_list(chan, &chan->pending_list);
+	xilinx_vdma_free_desc_list(chan, &chan->done_list);
+
+	xilinx_vdma_free_tx_descriptor(chan, chan->active_desc);
+	chan->active_desc = NULL;
+
+	spin_unlock_irqrestore(&chan->lock, flags);
+}
+
+/**
+ * xilinx_vdma_free_chan_resources - Free channel resources
+ * @dchan: DMA channel
+ */
+static void xilinx_vdma_free_chan_resources(struct dma_chan *dchan)
+{
+	struct xilinx_vdma_chan *chan = to_xilinx_chan(dchan);
+
+	dev_dbg(chan->dev, "Free all channel resources.\n");
+
+	tasklet_kill(&chan->tasklet);
+	xilinx_vdma_free_descriptors(chan);
+	dma_pool_destroy(chan->desc_pool);
+	chan->desc_pool = NULL;
+}
+
+/**
+ * xilinx_vdma_chan_desc_cleanup - Clean channel descriptors
+ * @chan: Driver specific VDMA channel
+ */
+static void xilinx_vdma_chan_desc_cleanup(struct xilinx_vdma_chan *chan)
+{
+	struct xilinx_vdma_tx_descriptor *desc, *next;
+	unsigned long flags;
+
+	spin_lock_irqsave(&chan->lock, flags);
+
+	list_for_each_entry_safe(desc, next, &chan->done_list, node) {
+		dma_async_tx_callback callback;
+		void *callback_param;
+
+		/* Remove from the list of running transactions */
+		list_del(&desc->node);
+
+		/* Run the link descriptor callback function */
+		callback = desc->async_tx.callback;
+		callback_param = desc->async_tx.callback_param;
+		if (callback) {
+			spin_unlock_irqrestore(&chan->lock, flags);
+			callback(callback_param);
+			spin_lock_irqsave(&chan->lock, flags);
+		}
+
+		/* Run any dependencies, then free the descriptor */
+		dma_run_dependencies(&desc->async_tx);
+		xilinx_vdma_free_tx_descriptor(chan, desc);
+	}
+
+	spin_unlock_irqrestore(&chan->lock, flags);
+}
+
+/**
+ * xilinx_vdma_do_tasklet - Schedule completion tasklet
+ * @data: Pointer to the Xilinx VDMA channel structure
+ */
+static void xilinx_vdma_do_tasklet(unsigned long data)
+{
+	struct xilinx_vdma_chan *chan = (struct xilinx_vdma_chan *)data;
+
+	xilinx_vdma_chan_desc_cleanup(chan);
+}
+
+/**
+ * xilinx_vdma_alloc_chan_resources - Allocate channel resources
+ * @dchan: DMA channel
+ *
+ * Return: '1' on success and failure value on error
+ */
+static int xilinx_vdma_alloc_chan_resources(struct dma_chan *dchan)
+{
+	struct xilinx_vdma_chan *chan = to_xilinx_chan(dchan);
+
+	/* Has this channel already been allocated? */
+	if (chan->desc_pool)
+		return 1;
+
+	/*
+	 * We need the descriptor to be aligned to 64bytes
+	 * for meeting Xilinx VDMA specification requirement.
+	 */
+	chan->desc_pool = dma_pool_create("xilinx_vdma_desc_pool",
+				chan->dev,
+				sizeof(struct xilinx_vdma_tx_segment),
+				__alignof__(struct xilinx_vdma_tx_segment), 0);
+	if (!chan->desc_pool) {
+		dev_err(chan->dev,
+			"unable to allocate channel %d descriptor pool\n",
+			chan->id);
+		return -ENOMEM;
+	}
+
+	tasklet_init(&chan->tasklet, xilinx_vdma_do_tasklet,
+			(unsigned long)chan);
+
+	chan->completed_cookie = DMA_MIN_COOKIE;
+	chan->cookie = DMA_MIN_COOKIE;
+
+	/* There is at least one descriptor free to be allocated */
+	return 1;
+}
+
+/**
+ * xilinx_vdma_tx_status - Get VDMA transaction status
+ * @dchan: DMA channel
+ * @cookie: Transaction identifier
+ * @txstate: Transaction state
+ *
+ * Return: DMA transaction status
+ */
+static enum dma_status xilinx_vdma_tx_status(struct dma_chan *dchan,
+					dma_cookie_t cookie,
+					struct dma_tx_state *txstate)
+{
+	struct xilinx_vdma_chan *chan = to_xilinx_chan(dchan);
+	dma_cookie_t last_used;
+	dma_cookie_t last_complete;
+
+	xilinx_vdma_chan_desc_cleanup(chan);
+
+	last_used = dchan->cookie;
+	last_complete = chan->completed_cookie;
+
+	dma_set_tx_state(txstate, last_complete, last_used, 0);
+
+	return dma_async_is_complete(cookie, last_complete, last_used);
+}
+
+/**
+ * xilinx_vdma_is_running - Check if VDMA channel is running
+ * @chan: Driver specific VDMA channel
+ *
+ * Return: '1' if running, '0' if not.
+ */
+static int xilinx_vdma_is_running(struct xilinx_vdma_chan *chan)
+{
+	return !(vdma_ctrl_read(chan, XILINX_VDMA_REG_DMASR) &
+		 XILINX_VDMA_DMASR_HALTED) &&
+		(vdma_ctrl_read(chan, XILINX_VDMA_REG_DMACR) &
+		 XILINX_VDMA_DMACR_RUNSTOP);
+}
+
+/**
+ * xilinx_vdma_is_idle - Check if VDMA channel is idle
+ * @chan: Driver specific VDMA channel
+ *
+ * Return: '1' if idle, '0' if not.
+ */
+static int xilinx_vdma_is_idle(struct xilinx_vdma_chan *chan)
+{
+	return vdma_ctrl_read(chan, XILINX_VDMA_REG_DMASR) &
+		XILINX_VDMA_DMASR_IDLE;
+}
+
+/**
+ * xilinx_vdma_halt - Halt VDMA channel
+ * @chan: Driver specific VDMA channel
+ */
+static void xilinx_vdma_halt(struct xilinx_vdma_chan *chan)
+{
+	int loop = XILINX_VDMA_LOOP_COUNT + 1;
+
+	vdma_ctrl_clr(chan, XILINX_VDMA_REG_DMACR, XILINX_VDMA_DMACR_RUNSTOP);
+
+	/* Wait for the hardware to halt */
+	while (loop--)
+		if (vdma_ctrl_read(chan, XILINX_VDMA_REG_DMASR) &
+		    XILINX_VDMA_DMASR_HALTED)
+			break;
+
+	if (!loop) {
+		dev_err(chan->dev, "Cannot stop channel %p: %x\n",
+			chan, vdma_ctrl_read(chan, XILINX_VDMA_REG_DMASR));
+		chan->err = true;
+	}
+
+	return;
+}
+
+/**
+ * xilinx_vdma_start - Start VDMA channel
+ * @chan: Driver specific VDMA channel
+ */
+static void xilinx_vdma_start(struct xilinx_vdma_chan *chan)
+{
+	int loop = XILINX_VDMA_LOOP_COUNT + 1;
+
+	vdma_ctrl_set(chan, XILINX_VDMA_REG_DMACR, XILINX_VDMA_DMACR_RUNSTOP);
+
+	/* Wait for the hardware to start */
+	while (loop--)
+		if (!(vdma_ctrl_read(chan, XILINX_VDMA_REG_DMASR) &
+		      XILINX_VDMA_DMASR_HALTED))
+			break;
+
+	if (!loop) {
+		dev_err(chan->dev, "Cannot start channel %p: %x\n",
+			chan, vdma_ctrl_read(chan, XILINX_VDMA_REG_DMASR));
+
+		chan->err = true;
+	}
+
+	return;
+}
+
+/**
+ * xilinx_vdma_start_transfer - Starts VDMA transfer
+ * @chan: Driver specific channel struct pointer
+ */
+static void xilinx_vdma_start_transfer(struct xilinx_vdma_chan *chan)
+{
+	struct xilinx_vdma_config *config = &chan->config;
+	struct xilinx_vdma_tx_descriptor *desc;
+	unsigned long flags;
+	u32 reg;
+	struct xilinx_vdma_tx_segment *head, *tail = NULL;
+
+	if (chan->err)
+		return;
+
+	spin_lock_irqsave(&chan->lock, flags);
+
+	/* There's already an active descriptor, bail out. */
+	if (chan->active_desc)
+		goto out_unlock;
+
+	if (list_empty(&chan->pending_list))
+		goto out_unlock;
+
+	desc = list_first_entry(&chan->pending_list,
+				struct xilinx_vdma_tx_descriptor, node);
+
+	/* If it is SG mode and hardware is busy, cannot submit */
+	if (chan->has_sg && xilinx_vdma_is_running(chan) &&
+	    !xilinx_vdma_is_idle(chan)) {
+		dev_dbg(chan->dev, "DMA controller still busy\n");
+		goto out_unlock;
+	}
+
+	if (chan->err)
+		goto out_unlock;
+
+	/*
+	 * If hardware is idle, then all descriptors on the running lists are
+	 * done, start new transfers
+	 */
+	if (chan->has_sg) {
+		head = list_first_entry(&desc->segments,
+					struct xilinx_vdma_tx_segment, node);
+		tail = list_entry(desc->segments.prev,
+				  struct xilinx_vdma_tx_segment, node);
+
+		vdma_ctrl_write(chan, XILINX_VDMA_REG_CURDESC, head->phys);
+	}
+
+	/* Configure the hardware using info in the config structure */
+	reg = vdma_ctrl_read(chan, XILINX_VDMA_REG_DMACR);
+
+	if (config->frm_cnt_en)
+		reg |= XILINX_VDMA_DMACR_FRAMECNT_EN;
+	else
+		reg &= ~XILINX_VDMA_DMACR_FRAMECNT_EN;
+
+	/*
+	 * With SG, start with circular mode, so that BDs can be fetched.
+	 * In direct register mode, if not parking, enable circular mode
+	 */
+	if (chan->has_sg || !config->park)
+		reg |= XILINX_VDMA_DMACR_CIRC_EN;
+
+	if (config->park)
+		reg &= ~XILINX_VDMA_DMACR_CIRC_EN;
+
+	vdma_ctrl_write(chan, XILINX_VDMA_REG_DMACR, reg);
+
+	if (config->park && (config->park_frm >= 0) &&
+			(config->park_frm < chan->num_frms)) {
+		if (chan->direction == DMA_MEM_TO_DEV)
+			vdma_write(chan, XILINX_VDMA_REG_PARK_PTR,
+				config->park_frm <<
+					XILINX_VDMA_PARK_PTR_RD_REF_SHIFT);
+		else
+			vdma_write(chan, XILINX_VDMA_REG_PARK_PTR,
+				config->park_frm <<
+					XILINX_VDMA_PARK_PTR_WR_REF_SHIFT);
+	}
+
+	/* Start the hardware */
+	xilinx_vdma_start(chan);
+
+	if (chan->err)
+		goto out_unlock;
+
+	/* Start the transfer */
+	if (chan->has_sg) {
+		vdma_ctrl_write(chan, XILINX_VDMA_REG_TAILDESC, tail->phys);
+	} else {
+		struct xilinx_vdma_tx_segment *segment;
+		int i = 0;
+
+		list_for_each_entry(segment, &desc->segments, node)
+			vdma_desc_write(chan,
+					XILINX_VDMA_REG_START_ADDRESS(i++),
+					segment->hw.buf_addr);
+
+		vdma_desc_write(chan, XILINX_VDMA_REG_HSIZE, config->hsize);
+		vdma_desc_write(chan, XILINX_VDMA_REG_FRMDLY_STRIDE,
+				(config->frm_dly <<
+				 XILINX_VDMA_FRMDLY_STRIDE_FRMDLY_SHIFT) |
+				(config->stride <<
+				 XILINX_VDMA_FRMDLY_STRIDE_STRIDE_SHIFT));
+		vdma_desc_write(chan, XILINX_VDMA_REG_VSIZE, config->vsize);
+	}
+
+	list_del(&desc->node);
+	chan->active_desc = desc;
+
+out_unlock:
+	spin_unlock_irqrestore(&chan->lock, flags);
+}
+
+/**
+ * xilinx_vdma_issue_pending - Issue pending transactions
+ * @dchan: DMA channel
+ */
+static void xilinx_vdma_issue_pending(struct dma_chan *dchan)
+{
+	struct xilinx_vdma_chan *chan = to_xilinx_chan(dchan);
+
+	xilinx_vdma_start_transfer(chan);
+}
+
+/**
+ * xilinx_vdma_complete_descriptor - Mark the active descriptor as complete
+ * @chan : xilinx DMA channel
+ *
+ * CONTEXT: hardirq
+ */
+static void xilinx_vdma_complete_descriptor(struct xilinx_vdma_chan *chan)
+{
+	struct xilinx_vdma_tx_descriptor *desc;
+	unsigned long flags;
+
+	spin_lock_irqsave(&chan->lock, flags);
+
+	desc = chan->active_desc;
+	if (!desc) {
+		dev_dbg(chan->dev, "no running descriptors\n");
+		goto out_unlock;
+	}
+
+	list_add_tail(&desc->node, &chan->done_list);
+
+	/* Update the completed cookie and reset the active descriptor. */
+	chan->completed_cookie = desc->async_tx.cookie;
+	chan->active_desc = NULL;
+
+out_unlock:
+	spin_unlock_irqrestore(&chan->lock, flags);
+}
+
+/**
+ * xilinx_vdma_reset - Reset VDMA channel
+ * @chan: Driver specific VDMA channel
+ *
+ * Return: '0' on success and failure value on error
+ */
+static int xilinx_vdma_reset(struct xilinx_vdma_chan *chan)
+{
+	int loop = XILINX_VDMA_LOOP_COUNT + 1;
+	u32 tmp;
+
+	vdma_ctrl_set(chan, XILINX_VDMA_REG_DMACR, XILINX_VDMA_DMACR_RESET);
+
+	tmp = vdma_ctrl_read(chan, XILINX_VDMA_REG_DMACR) &
+		XILINX_VDMA_DMACR_RESET;
+
+	/* Wait for the hardware to finish reset */
+	while (loop-- && tmp)
+		tmp = vdma_ctrl_read(chan, XILINX_VDMA_REG_DMACR) &
+			XILINX_VDMA_DMACR_RESET;
+
+	if (!loop) {
+		dev_err(chan->dev, "reset timeout, cr %x, sr %x\n",
+			vdma_ctrl_read(chan, XILINX_VDMA_REG_DMACR),
+			vdma_ctrl_read(chan, XILINX_VDMA_REG_DMASR));
+		return -ETIMEDOUT;
+	}
+
+	chan->err = false;
+
+	return 0;
+}
+
+/**
+ * xilinx_vdma_chan_reset - Reset VDMA channel and enable interrupts
+ * @chan: Driver specific VDMA channel
+ *
+ * Return: '0' on success and failure value on error
+ */
+static int xilinx_vdma_chan_reset(struct xilinx_vdma_chan *chan)
+{
+	int err;
+
+	/* Reset VDMA */
+	err = xilinx_vdma_reset(chan);
+	if (err)
+		return err;
+
+	/* Enable interrupts */
+	vdma_ctrl_set(chan, XILINX_VDMA_REG_DMACR,
+		      XILINX_VDMA_DMAXR_ALL_IRQ_MASK);
+
+	return 0;
+}
+
+/**
+ * xilinx_vdma_irq_handler - VDMA Interrupt handler
+ * @irq: IRQ number
+ * @data: Pointer to the Xilinx VDMA channel structure
+ *
+ * Return: IRQ_HANDLED/IRQ_NONE
+ */
+static irqreturn_t xilinx_vdma_irq_handler(int irq, void *data)
+{
+	struct xilinx_vdma_chan *chan = data;
+	u32 status;
+
+	/* Read the status and ack the interrupts. */
+	status = vdma_ctrl_read(chan, XILINX_VDMA_REG_DMASR);
+	if (!(status & XILINX_VDMA_DMAXR_ALL_IRQ_MASK))
+		return IRQ_NONE;
+
+	vdma_ctrl_write(chan, XILINX_VDMA_REG_DMASR,
+			status & XILINX_VDMA_DMAXR_ALL_IRQ_MASK);
+
+	if (status & XILINX_VDMA_DMASR_ERR_IRQ) {
+		/*
+		 * An error occurred. If C_FLUSH_ON_FSYNC is enabled and the
+		 * error is recoverable, ignore it. Otherwise flag the error.
+		 *
+		 * Only recoverable errors can be cleared in the DMASR register,
+		 * make sure not to write to other error bits to 1.
+		 */
+		u32 errors = status & XILINX_VDMA_DMASR_ALL_ERR_MASK;
+		vdma_ctrl_write(chan, XILINX_VDMA_REG_DMASR,
+				errors & XILINX_VDMA_DMASR_ERR_RECOVER_MASK);
+
+		if (!chan->flush_on_fsync ||
+		    (errors & ~XILINX_VDMA_DMASR_ERR_RECOVER_MASK)) {
+			dev_err(chan->dev,
+				"Channel %p has errors %x, cdr %x tdr %x\n",
+				chan, errors,
+				vdma_ctrl_read(chan, XILINX_VDMA_REG_CURDESC),
+				vdma_ctrl_read(chan, XILINX_VDMA_REG_TAILDESC));
+			chan->err = true;
+		}
+	}
+
+	if (status & XILINX_VDMA_DMASR_DLY_CNT_IRQ) {
+		/*
+		 * Device takes too long to do the transfer when user requires
+		 * responsiveness.
+		 */
+		dev_dbg(chan->dev, "Inter-packet latency too long\n");
+	}
+
+	if (status & XILINX_VDMA_DMASR_FRM_CNT_IRQ) {
+		xilinx_vdma_complete_descriptor(chan);
+		xilinx_vdma_start_transfer(chan);
+	}
+
+	tasklet_schedule(&chan->tasklet);
+	return IRQ_HANDLED;
+}
+
+/**
+ * xilinx_vdma_tx_submit - Submit DMA transaction
+ * @tx: Async transaction descriptor
+ *
+ * Return: cookie value on success and failure value on error
+ */
+static dma_cookie_t xilinx_vdma_tx_submit(struct dma_async_tx_descriptor *tx)
+{
+	struct xilinx_vdma_tx_descriptor *desc = to_vdma_tx_descriptor(tx);
+	struct xilinx_vdma_chan *chan = to_xilinx_chan(tx->chan);
+	struct xilinx_vdma_tx_segment *segment;
+	dma_cookie_t cookie;
+	unsigned long flags;
+	int err;
+
+	if (chan->err) {
+		/*
+		 * If reset fails, need to hard reset the system.
+		 * Channel is no longer functional
+		 */
+		err = xilinx_vdma_chan_reset(chan);
+		if (err < 0)
+			return err;
+	}
+
+	spin_lock_irqsave(&chan->lock, flags);
+
+	/* Assign cookies to all of the segments that make up this transaction.
+	 * Use the cookie of the last segment as the transaction cookie.
+	 */
+	cookie = chan->cookie;
+
+	list_for_each_entry(segment, &desc->segments, node) {
+		if (cookie < DMA_MAX_COOKIE)
+			cookie++;
+		else
+			cookie = DMA_MIN_COOKIE;
+
+		segment->cookie = cookie;
+	}
+
+	tx->cookie = cookie;
+	chan->cookie = cookie;
+
+	/* Append the transaction to the pending transactions queue. */
+	list_add_tail(&desc->node, &chan->pending_list);
+
+	spin_unlock_irqrestore(&chan->lock, flags);
+
+	return cookie;
+}
+
+/**
+ * xilinx_vdma_prep_slave_sg - prepare a descriptor for a DMA_SLAVE transaction
+ * @dchan: DMA channel
+ * @sgl: scatterlist to transfer to/from
+ * @sg_len: number of entries in @sgl
+ * @dir: DMA direction
+ * @flags: transfer ack flags
+ * @context: unused
+ *
+ * Return: Async transaction descriptor on success and NULL on failure
+ */
+static struct dma_async_tx_descriptor *
+xilinx_vdma_prep_slave_sg(struct dma_chan *dchan, struct scatterlist *sgl,
+			  unsigned int sg_len, enum dma_transfer_direction dir,
+			  unsigned long flags, void *context)
+{
+	struct xilinx_vdma_chan *chan = to_xilinx_chan(dchan);
+	struct xilinx_vdma_tx_descriptor *desc;
+	struct xilinx_vdma_tx_segment *segment;
+	struct xilinx_vdma_tx_segment *prev = NULL;
+	struct scatterlist *sg;
+	int i;
+
+	if (chan->direction != dir || sg_len == 0)
+		return NULL;
+
+	/* Enforce one sg entry for one frame. */
+	if (sg_len != chan->num_frms) {
+		dev_err(chan->dev,
+		"number of entries %d not the same as num stores %d\n",
+			sg_len, chan->num_frms);
+		return NULL;
+	}
+
+	/* Allocate a transaction descriptor. */
+	desc = xilinx_vdma_alloc_tx_descriptor(chan);
+	if (!desc)
+		return NULL;
+
+	dma_async_tx_descriptor_init(&desc->async_tx, &chan->common);
+	desc->async_tx.tx_submit = xilinx_vdma_tx_submit;
+	desc->async_tx.cookie = 0;
+	async_tx_ack(&desc->async_tx);
+
+	/* Build the list of transaction segments. */
+	for_each_sg(sgl, sg, sg_len, i) {
+		struct xilinx_vdma_desc_hw *hw;
+
+		/* Allocate the link descriptor from DMA pool */
+		segment = xilinx_vdma_alloc_tx_segment(chan);
+		if (!segment)
+			goto error;
+
+		/* Fill in the hardware descriptor */
+		hw = &segment->hw;
+		hw->buf_addr = sg_dma_address(sg);
+		hw->vsize = chan->config.vsize;
+		hw->hsize = chan->config.hsize;
+		hw->stride = (chan->config.frm_dly <<
+			      XILINX_VDMA_FRMDLY_STRIDE_FRMDLY_SHIFT) |
+			     (chan->config.stride <<
+			      XILINX_VDMA_FRMDLY_STRIDE_STRIDE_SHIFT);
+		if (prev)
+			prev->hw.next_desc = segment->phys;
+
+		/* Insert the segment into the descriptor segments list. */
+		list_add_tail(&segment->node, &desc->segments);
+
+		prev = segment;
+	}
+
+	/* Link the last hardware descriptor with the first. */
+	segment = list_first_entry(&desc->segments,
+				   struct xilinx_vdma_tx_segment, node);
+	prev->hw.next_desc = segment->phys;
+
+	return &desc->async_tx;
+
+error:
+	xilinx_vdma_free_tx_descriptor(chan, desc);
+	return NULL;
+}
+
+/**
+ * xilinx_vdma_terminate_all - Halt the channel and free descriptors
+ * @chan: Driver specific VDMA Channel pointer
+ */
+static void xilinx_vdma_terminate_all(struct xilinx_vdma_chan *chan)
+{
+	/* Halt the DMA engine */
+	xilinx_vdma_halt(chan);
+
+	/* Remove and free all of the descriptors in the lists */
+	xilinx_vdma_free_descriptors(chan);
+}
+
+/**
+ * xilinx_vdma_slave_config - Configure VDMA channel
+ * Run-time configuration for Axi VDMA, supports:
+ * . halt the channel
+ * . configure interrupt coalescing and inter-packet delay threshold
+ * . start/stop parking
+ * . enable genlock
+ * . set transfer information using config struct
+ *
+ * @chan: Driver specific VDMA Channel pointer
+ * @cfg: Channel configuration pointer
+ *
+ * Return: '0' on success and failure value on error
+ */
+static int xilinx_vdma_slave_config(struct xilinx_vdma_chan *chan,
+				    struct xilinx_vdma_config *cfg)
+{
+	u32 dmacr;
+
+	if (cfg->reset)
+		return xilinx_vdma_chan_reset(chan);
+
+	dmacr = vdma_ctrl_read(chan, XILINX_VDMA_REG_DMACR);
+
+	/* If vsize is -1, it is park-related operations */
+	if (cfg->vsize == -1) {
+		if (cfg->park)
+			dmacr &= ~XILINX_VDMA_DMACR_CIRC_EN;
+		else
+			dmacr |= XILINX_VDMA_DMACR_CIRC_EN;
+
+		vdma_ctrl_write(chan, XILINX_VDMA_REG_DMACR, dmacr);
+		return 0;
+	}
+
+	/* If hsize is -1, it is interrupt threshold settings */
+	if (cfg->hsize == -1) {
+		if (cfg->coalesc <= XILINX_VDMA_DMACR_FRAME_COUNT_MAX) {
+			dmacr &= ~XILINX_VDMA_DMACR_FRAME_COUNT_MASK;
+			dmacr |= cfg->coalesc <<
+				 XILINX_VDMA_DMACR_FRAME_COUNT_SHIFT;
+			chan->config.coalesc = cfg->coalesc;
+		}
+
+		if (cfg->delay <= XILINX_VDMA_DMACR_DELAY_MAX) {
+			dmacr &= ~XILINX_VDMA_DMACR_DELAY_MASK;
+			dmacr |= cfg->delay << XILINX_VDMA_DMACR_DELAY_SHIFT;
+			chan->config.delay = cfg->delay;
+		}
+
+		vdma_ctrl_write(chan, XILINX_VDMA_REG_DMACR, dmacr);
+		return 0;
+	}
+
+	/* Transfer information */
+	chan->config.vsize = cfg->vsize;
+	chan->config.hsize = cfg->hsize;
+	chan->config.stride = cfg->stride;
+	chan->config.frm_dly = cfg->frm_dly;
+	chan->config.park = cfg->park;
+
+	/* genlock settings */
+	chan->config.gen_lock = cfg->gen_lock;
+	chan->config.master = cfg->master;
+
+	if (cfg->gen_lock && chan->genlock) {
+		dmacr |= XILINX_VDMA_DMACR_GENLOCK_EN;
+		dmacr |= cfg->master << XILINX_VDMA_DMACR_MASTER_SHIFT;
+	}
+
+	chan->config.frm_cnt_en = cfg->frm_cnt_en;
+	if (cfg->park)
+		chan->config.park_frm = cfg->park_frm;
+	else
+		chan->config.park_frm = -1;
+
+	chan->config.coalesc = cfg->coalesc;
+	chan->config.delay = cfg->delay;
+	if (cfg->coalesc <= XILINX_VDMA_DMACR_FRAME_COUNT_MAX) {
+		dmacr |= cfg->coalesc << XILINX_VDMA_DMACR_FRAME_COUNT_SHIFT;
+		chan->config.coalesc = cfg->coalesc;
+	}
+
+	if (cfg->delay <= XILINX_VDMA_DMACR_DELAY_MAX) {
+		dmacr |= cfg->delay << XILINX_VDMA_DMACR_DELAY_SHIFT;
+		chan->config.delay = cfg->delay;
+	}
+
+	/* FSync Source selection */
+	dmacr &= ~XILINX_VDMA_DMACR_FSYNCSRC_MASK;
+	dmacr |= cfg->ext_fsync << XILINX_VDMA_DMACR_FSYNCSRC_SHIFT;
+
+	vdma_ctrl_write(chan, XILINX_VDMA_REG_DMACR, dmacr);
+	return 0;
+}
+
+/**
+ * xilinx_vdma_device_control - Configure DMA channel of the device
+ * @dchan: DMA Channel pointer
+ * @cmd: DMA control command
+ * @arg: Channel configuration
+ *
+ * Return: '0' on success and failure value on error
+ */
+static int xilinx_vdma_device_control(struct dma_chan *dchan,
+				      enum dma_ctrl_cmd cmd, unsigned long arg)
+{
+	struct xilinx_vdma_chan *chan = to_xilinx_chan(dchan);
+
+	switch (cmd) {
+	case DMA_TERMINATE_ALL:
+		xilinx_vdma_terminate_all(chan);
+		return 0;
+	case DMA_SLAVE_CONFIG:
+		return xilinx_vdma_slave_config(chan,
+					(struct xilinx_vdma_config *)arg);
+	default:
+		return -ENXIO;
+	}
+}
+
+/* -----------------------------------------------------------------------------
+ * Probe and remove
+ */
+
+/**
+ * xilinx_vdma_chan_remove - Per Channel remove function
+ * @chan: Driver specific VDMA channel
+ */
+static void xilinx_vdma_chan_remove(struct xilinx_vdma_chan *chan)
+{
+	/* Disable all interrupts */
+	vdma_ctrl_clr(chan, XILINX_VDMA_REG_DMACR,
+		      XILINX_VDMA_DMAXR_ALL_IRQ_MASK);
+
+	list_del(&chan->common.device_node);
+}
+
+/**
+ * xilinx_vdma_chan_probe - Per Channel Probing
+ * It get channel features from the device tree entry and
+ * initialize special channel handling routines
+ *
+ * @xdev: Driver specific device structure
+ * @node: Device node
+ *
+ * Return: '0' on success and failure value on error
+ */
+static int xilinx_vdma_chan_probe(struct xilinx_vdma_device *xdev,
+				  struct device_node *node)
+{
+	struct xilinx_vdma_chan *chan;
+	bool has_dre = false;
+	u32 value;
+	int err;
+
+	/* Allocate and initialize the channel structure */
+	chan = devm_kzalloc(xdev->dev, sizeof(*chan), GFP_KERNEL);
+	if (!chan)
+		return -ENOMEM;
+
+	chan->dev = xdev->dev;
+	chan->xdev = xdev;
+	chan->has_sg = xdev->has_sg;
+
+	spin_lock_init(&chan->lock);
+	INIT_LIST_HEAD(&chan->pending_list);
+	INIT_LIST_HEAD(&chan->done_list);
+
+	/* Retrieve the channel properties from the device tree */
+	has_dre = of_property_read_bool(node, "xlnx,include-dre");
+
+	chan->genlock = of_property_read_bool(node, "xlnx,genlock-mode");
+
+	err = of_property_read_u32(node, "xlnx,datawidth", &value);
+	if (!err) {
+		u32 width = value >> 3; /* Convert bits to bytes */
+
+		/* If data width is greater than 8 bytes, DRE is not in hw */
+		if (width > 8)
+			has_dre = false;
+
+		if (!has_dre)
+			xdev->common.copy_align = fls(width - 1);
+	} else {
+		dev_err(xdev->dev, "missing xlnx,datawidth property\n");
+		return err;
+	}
+
+	if (of_device_is_compatible(node, "xlnx,axi-vdma-mm2s-channel")) {
+		chan->direction = DMA_MEM_TO_DEV;
+		chan->id = 0;
+
+		chan->ctrl_offset = XILINX_VDMA_MM2S_CTRL_OFFSET;
+		chan->desc_offset = XILINX_VDMA_MM2S_DESC_OFFSET;
+
+		if (xdev->flush_on_fsync == XILINX_VDMA_FLUSH_BOTH ||
+		    xdev->flush_on_fsync == XILINX_VDMA_FLUSH_MM2S)
+			chan->flush_on_fsync = true;
+	} else if (of_device_is_compatible(node,
+					    "xlnx,axi-vdma-s2mm-channel")) {
+		chan->direction = DMA_DEV_TO_MEM;
+		chan->id = 1;
+
+		chan->ctrl_offset = XILINX_VDMA_S2MM_CTRL_OFFSET;
+		chan->desc_offset = XILINX_VDMA_S2MM_DESC_OFFSET;
+
+		if (xdev->flush_on_fsync == XILINX_VDMA_FLUSH_BOTH ||
+		    xdev->flush_on_fsync == XILINX_VDMA_FLUSH_S2MM)
+			chan->flush_on_fsync = true;
+	} else {
+		dev_err(xdev->dev, "Invalid channel compatible node\n");
+		return -EINVAL;
+	}
+
+	/* Request the interrupt */
+	chan->irq = irq_of_parse_and_map(node, 0);
+	err = devm_request_irq(xdev->dev, chan->irq, xilinx_vdma_irq_handler,
+			       IRQF_SHARED, "xilinx-vdma-controller", chan);
+	if (err) {
+		dev_err(xdev->dev, "unable to request IRQ\n");
+		return err;
+	}
+
+	/* Initialize the DMA channel and add it to the DMA engine channels
+	 * list.
+	 */
+	chan->common.device = &xdev->common;
+
+	list_add_tail(&chan->common.device_node, &xdev->common.channels);
+	xdev->chan[chan->id] = chan;
+
+	/* Reset the channel */
+	err = xilinx_vdma_chan_reset(chan);
+	if (err < 0) {
+		dev_err(xdev->dev, "Reset channel failed\n");
+		return err;
+	}
+
+	return 0;
+}
+
+/**
+ * struct of_dma_filter_xilinx_args - Channel filter args
+ * @dev: DMA device structure
+ * @chan_id: Channel id
+ */
+struct of_dma_filter_xilinx_args {
+	struct dma_device *dev;
+	u32 chan_id;
+};
+
+/**
+ * xilinx_vdma_dt_filter - VDMA channel filter function
+ * @chan: DMA channel pointer
+ * @param: Filter match value
+ *
+ * Return: true/false based on the result
+ */
+static bool xilinx_vdma_dt_filter(struct dma_chan *chan, void *param)
+{
+	struct of_dma_filter_xilinx_args *args = param;
+
+	return chan->device == args->dev && chan->chan_id == args->chan_id;
+}
+
+/**
+ * of_dma_xilinx_xlate - Translation function
+ * @dma_spec: Pointer to DMA specifier as found in the device tree
+ * @ofdma: Pointer to DMA controller data
+ *
+ * Return: DMA channel pointer on success and NULL on error
+ */
+static struct dma_chan *of_dma_xilinx_xlate(struct of_phandle_args *dma_spec,
+						struct of_dma *ofdma)
+{
+	struct of_dma_filter_xilinx_args args;
+	dma_cap_mask_t cap;
+
+	args.dev = ofdma->of_dma_data;
+	if (!args.dev)
+		return NULL;
+
+	if (dma_spec->args_count != 1)
+		return NULL;
+
+	dma_cap_zero(cap);
+	dma_cap_set(DMA_SLAVE, cap);
+
+	args.chan_id = dma_spec->args[0];
+
+	return dma_request_channel(cap, xilinx_vdma_dt_filter, &args);
+}
+
+/**
+ * xilinx_vdma_probe - Driver probe function
+ * @pdev: Pointer to the platform_device structure
+ *
+ * Return: '0' on success and failure value on error
+ */
+static int xilinx_vdma_probe(struct platform_device *pdev)
+{
+	struct device_node *node = pdev->dev.of_node;
+	struct xilinx_vdma_device *xdev;
+	struct device_node *child;
+	struct resource *io;
+	u32 num_frames;
+	int i, err;
+
+	dev_info(&pdev->dev, "Probing xilinx axi vdma engine\n");
+
+	/* Allocate and initialize the DMA engine structure */
+	xdev = devm_kzalloc(&pdev->dev, sizeof(*xdev), GFP_KERNEL);
+	if (!xdev)
+		return -ENOMEM;
+
+	xdev->dev = &pdev->dev;
+
+	/* Request and map I/O memory */
+	io = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	xdev->regs = devm_ioremap_resource(&pdev->dev, io);
+	if (IS_ERR(xdev->regs))
+		return PTR_ERR(xdev->regs);
+
+	/* Retrieve the DMA engine properties from the device tree */
+	xdev->has_sg = of_property_read_bool(node, "xlnx,include-sg");
+
+	err = of_property_read_u32(node, "xlnx,num-fstores", &num_frames);
+	if (err < 0) {
+		dev_err(xdev->dev, "missing xlnx,num-fstores property\n");
+		return err;
+	}
+
+	of_property_read_u32(node, "xlnx,flush-fsync", &xdev->flush_on_fsync);
+
+	/* Initialize the DMA engine */
+	xdev->common.dev = &pdev->dev;
+
+	INIT_LIST_HEAD(&xdev->common.channels);
+	dma_cap_set(DMA_SLAVE, xdev->common.cap_mask);
+	dma_cap_set(DMA_PRIVATE, xdev->common.cap_mask);
+
+	xdev->common.device_alloc_chan_resources =
+				xilinx_vdma_alloc_chan_resources;
+	xdev->common.device_free_chan_resources =
+				xilinx_vdma_free_chan_resources;
+	xdev->common.device_prep_slave_sg = xilinx_vdma_prep_slave_sg;
+	xdev->common.device_control = xilinx_vdma_device_control;
+	xdev->common.device_tx_status = xilinx_vdma_tx_status;
+	xdev->common.device_issue_pending = xilinx_vdma_issue_pending;
+
+	platform_set_drvdata(pdev, xdev);
+
+	/* Initialize the channels */
+	for_each_child_of_node(node, child) {
+		err = xilinx_vdma_chan_probe(xdev, child);
+		if (err < 0)
+			goto error;
+	}
+
+	for (i = 0; i < XILINX_VDMA_MAX_CHANS_PER_DEVICE; i++) {
+		if (xdev->chan[i])
+			xdev->chan[i]->num_frms = num_frames;
+	}
+
+	/* Register the DMA engine with the core */
+	dma_async_device_register(&xdev->common);
+
+	err = of_dma_controller_register(node, of_dma_xilinx_xlate,
+					 &xdev->common);
+	if (err < 0) {
+		dev_err(&pdev->dev, "Unable to register DMA to DT\n");
+		dma_async_device_unregister(&xdev->common);
+		goto error;
+	}
+
+	return 0;
+
+error:
+	for (i = 0; i < XILINX_VDMA_MAX_CHANS_PER_DEVICE; i++) {
+		if (xdev->chan[i])
+			xilinx_vdma_chan_remove(xdev->chan[i]);
+	}
+
+	return err;
+}
+
+/**
+ * xilinx_vdma_remove - Driver remove function
+ * @pdev: Pointer to the platform_device structure
+ *
+ * Return: Always '0'
+ */
+static int xilinx_vdma_remove(struct platform_device *pdev)
+{
+	struct xilinx_vdma_device *xdev;
+	int i;
+
+	of_dma_controller_free(pdev->dev.of_node);
+
+	xdev = platform_get_drvdata(pdev);
+	dma_async_device_unregister(&xdev->common);
+
+	for (i = 0; i < XILINX_VDMA_MAX_CHANS_PER_DEVICE; i++) {
+		if (xdev->chan[i])
+			xilinx_vdma_chan_remove(xdev->chan[i]);
+	}
+
+	return 0;
+}
+
+static const struct of_device_id xilinx_vdma_of_ids[] = {
+	{ .compatible = "xlnx,axi-vdma-1.00.a",},
+	{}
+};
+
+static struct platform_driver xilinx_vdma_driver = {
+	.driver = {
+		.name = "xilinx-vdma",
+		.owner = THIS_MODULE,
+		.of_match_table = xilinx_vdma_of_ids,
+	},
+	.probe = xilinx_vdma_probe,
+	.remove = xilinx_vdma_remove,
+};
+
+module_platform_driver(xilinx_vdma_driver);
+
+MODULE_AUTHOR("Xilinx, Inc.");
+MODULE_DESCRIPTION("Xilinx VDMA driver");
+MODULE_LICENSE("GPL v2");
diff --git a/include/linux/amba/xilinx_dma.h b/include/linux/amba/xilinx_dma.h
new file mode 100644
index 0000000..48a8c8b
--- /dev/null
+++ b/include/linux/amba/xilinx_dma.h
@@ -0,0 +1,50 @@
+/*
+ * Xilinx DMA Engine drivers support header file
+ *
+ * Copyright (C) 2010-2014 Xilinx, Inc. All rights reserved.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __DMA_XILINX_DMA_H
+#define __DMA_XILINX_DMA_H
+
+#include <linux/dma-mapping.h>
+#include <linux/dmaengine.h>
+
+/**
+ * struct xilinx_vdma_config - VDMA Configuration structure
+ * @vsize: Vertical size
+ * @hsize: Horizontal size
+ * @stride: Stride
+ * @frm_dly: Frame delay
+ * @gen_lock: Whether in gen-lock mode
+ * @master: Master that it syncs to
+ * @frm_cnt_en: Enable frame count enable
+ * @park: Whether wants to park
+ * @park_frm: Frame to park on
+ * @coalesc: Interrupt coalescing threshold
+ * @delay: Delay counter
+ * @reset: Reset Channel
+ * @ext_fsync: External Frame Sync source
+ */
+struct xilinx_vdma_config {
+	int vsize;
+	int hsize;
+	int stride;
+	int frm_dly;
+	int gen_lock;
+	int master;
+	int frm_cnt_en;
+	int park;
+	int park_frm;
+	int coalesc;
+	int delay;
+	int reset;
+	int ext_fsync;
+};
+
+#endif
-- 
1.7.9.5

^ permalink raw reply related

* [PATCH v2] Add Xilinx AXI Video DMA Engine driver
From: Srikanth Thokala @ 2014-01-22 16:52 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

This is the driver for Xilinx AXI Video Direct Memory Access Engine.
It is a soft IP core, which provides high-bandwidth direct memory
access between memory and AXI4-Stream video type target peripherals
including peripherals which support AXI4-Stream Video Protocol. The
core provides efficient two dimensional DMA operations with independent
asynchronous read and write channel operation.

For more information on the IP, please refer to
http://www.xilinx.com/support/documentation/ip_documentation/axi_vdma/v6_1/pg020_axi_vdma.pdf

Use cases:
++++++++++
1. Xilinx Video Targeted Reference design
   http://www.wiki.xilinx.com/Zynq+Base+TRD+14.5
2. Common Display Framework
   http://events.linuxfoundation.org/sites/events/files/slides/20131024-elce.pdf

Regards,
Srikanth 

Srikanth Thokala (1):
  dma: Add Xilinx AXI Video Direct Memory Access Engine driver support

 .../devicetree/bindings/dma/xilinx/xilinx_vdma.txt |   75 +
 drivers/dma/Kconfig                                |   14 +
 drivers/dma/Makefile                               |    1 +
 drivers/dma/xilinx/Makefile                        |    1 +
 drivers/dma/xilinx/xilinx_vdma.c                   | 1486 ++++++++++++++++++++
 include/linux/amba/xilinx_dma.h                    |   50 +
 6 files changed, 1627 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/dma/xilinx/xilinx_vdma.txt
 create mode 100644 drivers/dma/xilinx/Makefile
 create mode 100644 drivers/dma/xilinx/xilinx_vdma.c
 create mode 100644 include/linux/amba/xilinx_dma.h

-- 
1.7.9.5

^ permalink raw reply

* [PATCH v2 06/15] watchdog: orion: Remove unneeded BRIDGE_CAUSE clear
From: Ezequiel Garcia @ 2014-01-22 16:49 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20140121233537.GS18269@obsidianresearch.com>

On Tue, Jan 21, 2014 at 04:35:37PM -0700, Jason Gunthorpe wrote:
> On Tue, Jan 21, 2014 at 06:12:32AM -0300, Ezequiel Garcia wrote:
> > After adding the IRQ request, the BRIDGE_CAUSE bit should be cleared by the
> > bridge interrupt controller. There's no longer a need to do it in the watchdog
> > driver, so we can simply remove it.
> 
> When we talked about this before I pointed out that sequence here is
> important:
> 
> - Disable WDT
> - Clear bridge
> - Enable WDT
> 

Sure, I wrote this series with that in mind and made some tests to
ensure that no spurious trigger was possible.

> Looking at this patch in isolation it looks to me like the clear
> bridge lines should be replaced with a request_irq (as that does the
> clear) - is the request_irq in the wrong spot?
> 

First of all, it seems to me that the first item "Disable WDT" is not
currently true on this driver. orion_wdt_start() seem to reset the
counter, but doesn't clear the WDT_EN bit. Do you think we should
enforce a "true" disable?

As an example, s3c2410wdt calls stop() from start(). Maybe we should
do something like it?

Regarding the sequence. Let me see if I got this problem right. The
concern here is about the bootloader leaving the registers in a
weird-state, right?

In that case, I thought that requesting the IRQ at probe time was enough
to ensure the BRIDGE_CAUSE would be cleared by the time the watchdog is
started. However, after reading through the irqchip code again, I'm no longer
sure this is the case.

It looks like the BRIDGE_CAUSE register is cleared when the interruption
is acked (which happens in the handler if I understood the code right).
So requesting the IRQ is useless...

I'll trace the code to confirm this.

Sebastian: If the above is correct, do you think we can add a cause clear to
the orion irqchip? (supposing it's harmful) Something like this:

diff --git a/drivers/irqchip/irq-orion.c b/drivers/irqchip/irq-orion.c
index e51d400..fef9171 100644
--- a/drivers/irqchip/irq-orion.c
+++ b/drivers/irqchip/irq-orion.c
@@ -180,6 +180,9 @@ static int __init orion_bridge_irq_init(struct device_node *np,
 	gc->chip_types[0].chip.irq_mask = irq_gc_mask_clr_bit;
 	gc->chip_types[0].chip.irq_unmask = irq_gc_mask_set_bit;
 
+	/* clear pending interrupts */
+	writel(0, gc->reg_base + ORION_BRIDGE_IRQ_CAUSE);
+
 	/* mask all interrupts */
 	writel(0, gc->reg_base + ORION_BRIDGE_IRQ_MASK);
 
-- 
Ezequiel Garc?a, Free Electrons
Embedded Linux, Kernel and Android Engineering
http://free-electrons.com

^ permalink raw reply related

* Internal error: Oops: 17 [#1] ARM
From: Russell King - ARM Linux @ 2014-01-22 16:41 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CACUGKYPXficVuqDgy6_Tnh9b-VOXDNK=+nqb6U5O6NpcZOGGpQ@mail.gmail.com>

On Wed, Jan 22, 2014 at 08:23:36AM -0800, John Tobias wrote:
> Hello all,
> 
> I am using 3.13-rc1 kernel on iMX6SL processor. My filesystem is in
> eMMC running SDR50.
> Is anyone here encountered these problem and if there's any existing
> patch that I can get?.

How reproducable is this?  I notice you're using 3.13-rc1 too, it could
be the bug has already been fixed in a later kernel version.  -rc1
kernels are really the "fresh after lots of new feature merging" kernels
which should always be expected to be rather buggy.

Linux kernel "release candidates" are not "we think this is going to be
a final kernel, please test it" but -rc1 marks the end of the new
feature merging and the beginning of the stablisation phase.

-- 
FTTC broadband for 0.8mile line: 5.8Mbps down 500kbps up.  Estimation
in database were 13.1 to 19Mbit for a good line, about 7.5+ for a bad.
Estimate before purchase was "up to 13.2Mbit".

^ permalink raw reply

* [PATCH RFC v2 2/2] Documentation: arm: define DT C-states bindings
From: Lorenzo Pieralisi @ 2014-01-22 16:33 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20140122114232.GB20247@sirena.org.uk>

On Wed, Jan 22, 2014 at 11:42:32AM +0000, Mark Brown wrote:
> On Tue, Jan 21, 2014 at 01:31:48PM +0000, Lorenzo Pieralisi wrote:
> > On Tue, Jan 21, 2014 at 11:16:46AM +0000, Vincent Guittot wrote:
> 
> > > > +       - psci-power-state
> > > > +               Usage: Required if entry-method property value is set to
> > > > +                      "psci".
> > > > +               Value type: <u32>
> > > > +               Definition: power_state parameter to pass to the PSCI
> > > > +                           suspend call to enter the C-state.
> 
> > > Why psci has got a dedicated field and not vendor methods ? can't you
> > > make that more generic ?
> 
> > If anyone provides me with an example usage why not, for now I know I
> > need that parameter for PSCI, I can call it differently, define it for PSCI
> > and leave it as optional for other methods.
> 
> Would it not be sensible to define a PSCI binding that extends this and
> other bindings - ISTR some other properties getting scattered into
> bindings for it?

You mean adding the properties in the PSCI bindings instead of defining
them here ? Let me think about this, I really reckon these are C-state
specific properties that belong in here (but actually I have to add
a statement related to PSCI - ie bindings require a PSCI node to be
present and valid), I will look into this.

Thank you,
Lorenzo

^ permalink raw reply

* Internal error: Oops: 17 [#1] ARM
From: John Tobias @ 2014-01-22 16:23 UTC (permalink / raw)
  To: linux-arm-kernel

Hello all,

I am using 3.13-rc1 kernel on iMX6SL processor. My filesystem is in
eMMC running SDR50.
Is anyone here encountered these problem and if there's any existing
patch that I can get?.

Regards,

john

[ 1552.394899] Unable to handle kernel NULL pointer dereference at
virtual address 00000037
[ 1552.403034] pgd = beef4000
[ 1552.405855] [00000037] *pgd=bef60831, *pte=00000000, *ppte=00000000
[ 1552.412245] Internal error: Oops: 17 [#1] ARM
[ 1552.416627] Modules linked in: bt8xxx(O) sd8xxx(O) mlan(O)
[ 1552.422249] CPU: 0 PID: 232 Comm: commsd Tainted: G           O 3.13.0-rc1 #7
[ 1552.429409] task: bfbc7500 ti: bec96000 task.ti: bec96000
[ 1552.434844] PC is at lookup_fast+0x5c/0x318
[ 1552.439067] LR is at mark_held_locks+0x78/0x13c
[ 1552.443622] pc : [<80101184>]    lr : [<80056e48>]    psr: a00f0013
[ 1552.443622] sp : bec97d88  ip : 00666e6f  fp : bec97ddc
[ 1552.455124] r10: 00000000  r9 : bec97e08  r8 : 80102d94
[ 1552.460370] r7 : bec97e60  r6 : bf133ac8  r5 : bec97e60  r4 : bec97e00
[ 1552.466918] r3 : bee4f01d  r2 : 00000000  r1 : ffffffff  r0 : ffffffff
[ 1552.473471] Flags: NzCv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment user
[ 1552.480629] Control: 10c53c7d  Table: beef4059  DAC: 00000015
[ 1552.486397] Process commsd (pid: 232, stack limit = 0xbec96238)
[ 1552.492341] Stack: (0xbec97d88 to 0xbec98000)
[ 1552.496728] 7d80:                   80102b94 80057108 bfb95310
bf133ac8 bf15f4e8 bfb95310
[ 1552.504936] 7da0: c08bb14d ffffffff bee4f015 00000008 bfbc7500
bec97e08 00000000 00000041
[ 1552.513142] 7dc0: bec97e60 bec96020 bec96000 00000000 bec97e3c
bec97de0 80102d94 80101134
[ 1552.521347] 7de0: bec97df8 00000000 800d982c bec96018 00000010
bec97e00 00000000 bec97e08
[ 1552.529553] 7e00: 8026e25c 800d97e8 bee4f000 00000ff0 80d4e3a4
00000001 bee4f000 bec97e60
[ 1552.537758] 7e20: ffffff9c ffffff9c bec96000 00000000 bec97e5c
bec97e40 801033bc 80102c70
[ 1552.545964] 7e40: bee4f000 00000001 bec97e60 bec97f00 bec97ee4
bec97e60 80105dc0 80103398
[ 1552.554170] 7e60: bfb95310 bf133ac8 c08bb14d 0000000b bee4f015
8005992c bfb95310 bf133398
[ 1552.562375] 7e80: bf15f4e8 00000041 00000002 0000008a 00000000
00000000 600f0013 bec96000
[ 1552.570581] 7ea0: ffffffea bf8c1840 807b4430 80115444 801156e4
8011563c 00000008 00000000
[ 1552.578786] 7ec0: bec97f04 733fe4e0 00000001 ffffff9c 757e3810
bec97f40 bec97efc bec97ee8
[ 1552.586991] 7ee0: 80105e0c 80105d68 00000000 bc950fe0 bec97f2c
bec97f00 800faf64 80105df4
[ 1552.595196] 7f00: 801156e4 80115420 bec97f54 733fe4e0 733ff8f0
733fe61c 000000c3 8000f504
[ 1552.603402] 7f20: bec97f3c bec97f30 800fafe0 800faf1c bec97fa4
bec97f40 800fb71c 800fafc4
[ 1552.611608] 7f40: 8000f310 bfbc7500 733fe550 8000f458 733fe61c
000000c3 bec97f84 bec97f68
[ 1552.619813] 7f60: 80056f28 800a0270 733fe550 733ff8f0 733fe61c
000000c3 bec97f94 bec97f88
[ 1552.628019] 7f80: 80057110 80056f18 00000000 bec97f98 8000f458
733fe550 00000000 bec97fa8
[ 1552.636226] 7fa0: 8000f280 800fb704 733fe550 733ff8f0 757e3810
733fe4e0 733fe550 00000003
[ 1552.644431] 7fc0: 733fe550 733ff8f0 733fe61c 000000c3 00000000
00000002 733fe92c 00000200
[ 1552.652636] 7fe0: 000000c3 733fe4d8 7579b7e5 7572e276 200f0030
757e3810 bfffd821 bfffdc21
[ 1552.660828] Backtrace:
[ 1552.663343] [<80101128>] (lookup_fast+0x0/0x318) from [<80102d94>]
(path_lookupat+0x130/0x728)
[ 1552.671994] [<80102c64>] (path_lookupat+0x0/0x728) from
[<801033bc>] (filename_lookup.isra.40+0x30/0x70)
[ 1552.681515] [<8010338c>] (filename_lookup.isra.40+0x0/0x70) from
[<80105dc0>] (user_path_at_empty+0x64/0x8c)
[ 1552.691361]  r7:bec97f00 r6:bec97e60 r5:00000001 r4:bee4f000
[ 1552.697163] [<80105d5c>] (user_path_at_empty+0x0/0x8c) from
[<80105e0c>] (user_path_at+0x24/0x2c)
[ 1552.706053]  r8:bec97f40 r7:757e3810 r6:ffffff9c r5:00000001 r4:733fe4e0
[ 1552.712927] [<80105de8>] (user_path_at+0x0/0x2c) from [<800faf64>]
(vfs_fstatat+0x54/0xa8)
[ 1552.721232] [<800faf10>] (vfs_fstatat+0x0/0xa8) from [<800fafe0>]
(vfs_stat+0x28/0x2c)
[ 1552.729167]  r8:8000f504 r7:000000c3 r6:733fe61c r5:733ff8f0 r4:733fe4e0
[ 1552.736031] [<800fafb8>] (vfs_stat+0x0/0x2c) from [<800fb71c>]
(SyS_stat64+0x24/0x40)
[ 1552.743902] [<800fb6f8>] (SyS_stat64+0x0/0x40) from [<8000f280>]
(ret_fast_syscall+0x0/0x48)
[ 1552.752359]  r4:733fe550
[ 1552.754946] Code: eb00352d e3500000 e50b0038 0a000080 (e5903038)
[ 1552.761270] ---[ end trace 02679086a39365e8 ]---
[ 1552.765968] Kernel panic - not syncing: Fatal exception

^ permalink raw reply

* [PATCH RFC v2 2/2] Documentation: arm: define DT C-states bindings
From: Lorenzo Pieralisi @ 2014-01-22 16:23 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20140122115214.GG17314@sirena.org.uk>

Hi Mark,

On Wed, Jan 22, 2014 at 11:52:14AM +0000, Mark Brown wrote:
> On Tue, Jan 21, 2014 at 03:23:59PM +0000, Lorenzo Pieralisi wrote:
> > On Tue, Jan 21, 2014 at 02:35:11PM +0000, Amit Kucheria wrote:
> 
> > > DT-newbie here. What would happen if a vendor does not characterise
> > > the latency at each OPP? IOW, the table only contains latency values
> > > for a subset of the OPPs.
> 
> > The bindings are explicit, so the kernel will barf. Adding a LUT to map
> > latencies to OPPs make me cringe, so I would not change the current
> > bindings.
> 
> Actually looking at the OPP binding I do wonder if it might not be
> better to have a v2/rich binding for them which is extensible - the fact
> that it's not possible to add additional information seems like an
> issue, this can't be the only thing anyone might want to add and lining
> up multiple tables is never fun.

On one hand OPP bindings need improvement and that's on the cards. I am not
really following what you mean by "extensible", I only want to make sure
that the C-state bindings do not become too complex.

Do you mean extending OPP bindings to add eg C-state information there
(or whatever piece of information that is OPP dependent) ?
It seems a bit of a stretch but I can think about that.

I think that C-state properties are better defined in the C-state bindings
that was the idea but I am open to suggestions.

Thank you !
Lorenzo

^ permalink raw reply

* [PATCH v2 05/15] watchdog: orion: Make RSTOUT register a separate resource
From: Ezequiel Garcia @ 2014-01-22 16:21 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <3176358.2QFcJHj0fv@wuerfel>

Jason, Arnd:

On Wed, Jan 22, 2014 at 10:48:37AM +0100, Arnd Bergmann wrote:
> On Tuesday 21 January 2014 16:33:21 Jason Gunthorpe wrote:
> > On Tue, Jan 21, 2014 at 06:12:31AM -0300, Ezequiel Garcia wrote:
> > > In order to support other SoC, it's required to distinguish
> > > the 'control' timer register, from the 'rstout' register
> > > that enables system reset on watchdog expiration.
> > 
> > > +     res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
> > > +     if (!res)
> > > +             return -ENODEV;
> >            ^^^^^^^^^^^^^^^^^^^^^^
> > 
> > This change seems to break compatibility with existing DT files that
> > have only a single entry in reg?
> > 
> > Can the value be defaulted some how if missing?
> 
> I think this is a direct consequence of the attempt to remove the
> header file dependency, since the RSTOUTn_MASK macro is defined
> in mach/bridge-regs.h.
> 

Exactly. Just for the record, I warned about this a while back:

http://www.spinics.net/lists/arm-kernel/msg270163.html

That said, it truly sucks to break compatibility so finding a way to
keep backwards compatibility would be certainly desirable.

> I don't see a good way out that would preserve backwards compatibility,
> other than hardcoding the physical address in the driver, which seems
> just as bad as breaking compatibility. That said, it is always the
> same constant (0xf1000000 + 0x20000 + 0x0108) on Dove, Kirkwood and
> Orion5x (not on mv78xx0, but that doesn't use the wdt), so hardcoding
> a fallback would technically work, but we should print a fat warning at
> boot time if we actually fall back to that.
> 

Yes, I was thinking just about this. Namely:

If the second resource is missing *and* the compatible-string is
"orion-watchdog" (or it's not DT-registered), then use a hardcoded
RSTOUTn_MASK address. And pr_warn() something.

Thanks for the feedback,
-- 
Ezequiel Garc?a, Free Electrons
Embedded Linux, Kernel and Android Engineering
http://free-electrons.com

^ permalink raw reply

* [PATCH v7 5/6] misc: debug: remove compilation warnings
From: Catalin Marinas @ 2014-01-22 16:11 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1390401773-12100-6-git-send-email-vijay.kilari@gmail.com>

On Wed, Jan 22, 2014 at 02:42:52PM +0000, vijay.kilari at gmail.com wrote:
> From: Vijaya Kumar K <Vijaya.Kumar@caviumnetworks.com>
> 
> Resolve following compiler warnings
> warning: format '%lx' expects argument of type 'long unsigned int',
> but argument 2 has type 'u64' [-Wformat]
> 
> tested for warnings on arm32 & arm64
> 
> Signed-off-by: Vijaya Kumar K <Vijaya.Kumar@caviumnetworks.com>
> ---
>  drivers/misc/kgdbts.c |   12 ++++++------
>  1 file changed, 6 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/misc/kgdbts.c b/drivers/misc/kgdbts.c
> index 36f5d52..78e10b2 100644
> --- a/drivers/misc/kgdbts.c
> +++ b/drivers/misc/kgdbts.c
> @@ -350,8 +350,8 @@ static int check_single_step(char *put_str, char *arg)
>  	kgdb_hex2mem(&put_str[1], (char *)kgdbts_gdb_regs,
>  		 NUMREGBYTES);
>  	gdb_regs_to_pt_regs(kgdbts_gdb_regs, &kgdbts_regs);
> -	v2printk("Singlestep stopped at IP: %lx\n",
> -		   instruction_pointer(&kgdbts_regs));
> +	v2printk("Singlestep stopped at IP: %llx\n",
> +		   (unsigned long long)instruction_pointer(&kgdbts_regs));
>  
>  	if (sstep_thread_id != cont_thread_id) {
>  		/*
> @@ -376,8 +376,8 @@ static int check_single_step(char *put_str, char *arg)
>  continue_test:
>  	matched_id = 0;
>  	if (instruction_pointer(&kgdbts_regs) == addr) {
> -		eprintk("kgdbts: SingleStep failed at %lx\n",
> -			   instruction_pointer(&kgdbts_regs));
> +		eprintk("kgdbts: SingleStep failed at %llx\n",
> +			(unsigned long long)instruction_pointer(&kgdbts_regs));

I think we could simply add the cast to the definition of
instruction_pointer() on arm64. Even the generic instruction_pointer()
definition returns unsigned long.

-- 
Catalin

^ permalink raw reply

* [PATCH 11/11] arm: dma-mapping: Add support to extend DMA IOMMU mappings
From: Will Deacon @ 2014-01-22 16:10 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1389876263-25759-12-git-send-email-andreas.herrmann@calxeda.com>

On Thu, Jan 16, 2014 at 12:44:23PM +0000, Andreas Herrmann wrote:
> Instead of using just one bitmap to keep track of IO virtual addresses
> (handed out for IOMMU use) introduce a list of iova_ranges (each
> having its own bitmap). This allows us to extend existing mappings
> when running out of iova space for a mapping.
> 
> If there is not enough space in the mapping to service an IO virtual
> address allocation request, __alloc_iova() tries to extend the mapping
> -- by allocating another bitmap -- and makes another allocation
> attempt using the freshly allocated bitmap.
> 
> This allows arm iommu drivers to start with a decent initial size when
> an dma_iommu_mapping is created and still to avoid running out of IO
> virtual addresses for the mapping.
> 
> Tests were done on Calxeda ECX-2000 with smmu for sata and xgmac.
> I've used SZ_512K both for initial mapping size and grow_size.

Aha, I thought grow_size was the *maximum* size, rather than the incremental
size. In which case, you probably want to pick the maximum supported IOMMU
page size that satisfies a fixed limit on the bitmap size.

> +static int extend_iommu_mapping(struct dma_iommu_mapping *mapping)
> +{
> +	struct dma_iommu_iova_range *iovar;
> +	unsigned int count = mapping->grow_size >> (PAGE_SHIFT + mapping->order);
> +	unsigned int bitmap_size = BITS_TO_LONGS(count) * sizeof(long);
> +
> +	if (!mapping->grow_size ||
> +		(mapping->size + mapping->grow_size) >= mapping->max_size)
> +		return -EINVAL;
> +
> +	iovar = kzalloc(sizeof(struct dma_iommu_iova_range), GFP_ATOMIC);
> +	if (!iovar)
> +		return -ENOMEM;
> +
> +	iovar->bitmap = kzalloc(bitmap_size, GFP_ATOMIC);

Do these allocation really need to be atomic? I worry that's going to have
severe restrictions on our ability to allocate large address spaces.

Will

^ permalink raw reply

* [PATCH RESEND] cpufreq: exynos: Fix build error of no type of module_init
From: Krzysztof Kozlowski @ 2014-01-22 16:10 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <52DFE7D9.5050001@windriver.com>

On Wed, 2014-01-22 at 10:46 -0500, Paul Gortmaker wrote:
> On 14-01-22 10:37 AM, Krzysztof Kozlowski wrote:
> > 
> >>
> >> Hi,
> >>
> >> A little more explanation from my side: the build error actually happens
> >> only on next/master, not Linus' tree.
> >>
> >> Mentioned commit which changes the driver to platform driver is in
> >> mainline since 3.12-rc2 so it seems this is not the cause of the build
> >> error. I think I need to find first the real cause of this build error.
> >>
> >> Best regards,
> >> Krzysztof
> > 
> > After bisecting, the real commit for build error is:
> > caa7dcde7c424cdc81698a6e4e48072eb67ec67e
> >     module: relocate module_init from init.h to module.h
> 
> Yep, even though I fixed a crap-tonne of implicit includes, and
> built all the arm configs, some were bound to sneak through.
> 
> I'll push a fix shortly to the init cleanup queue:
> 
>    http://git.kernel.org/cgit/linux/kernel/git/paulg/init.git/
> 
> so it will be fine for the next linux-next tree.

Thanks, the same issue applies to drivers/cpufreq/exynos-cpufreq.c.

Best regards,
Krzysztof

^ permalink raw reply

* [PATCH 10/11] arm: dma-mapping: Add additional parameters to arm_iommu_create_mapping
From: Will Deacon @ 2014-01-22 16:01 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1389876263-25759-11-git-send-email-andreas.herrmann@calxeda.com>

On Thu, Jan 16, 2014 at 12:44:22PM +0000, Andreas Herrmann wrote:
> The new parameters are
> 
>   dma_addr_t grow_size
> 
>          Specifies the size by which the mapping will be extended in
>          case that no sufficient space is left in the mapping to
>          handle an iova allocation request. If a grow_size of 0 is
>          specified the mapping is not extended.

How can an IOMMU know what a sensible value is for grow size? I can only
think of two cases:

  (1) Growing is not permitted at all (0 in your current API)
  (2) Growing is permitted up to the maximum input address size of the
      IOMMU.

Maybe the latter should be probable, rather than waiting to get -ERANGE from
iommu_map? Actually, if we assume that the DMA master can't master a wider
address range the its IOMMU, then we could construct the grow_size from the
base and the dma mask already.

Will

^ permalink raw reply

* [PATCH 10/20] ARM64 / ACPI: Enumerate possible/present CPU set and map logical cpu id to APIC id
From: Lorenzo Pieralisi @ 2014-01-22 15:53 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1389961514-13562-11-git-send-email-hanjun.guo@linaro.org>

On Fri, Jan 17, 2014 at 12:25:04PM +0000, Hanjun Guo wrote:

[...]

> +/* map logic cpu id to physical GIC id */
> +extern int arm_cpu_to_apicid[NR_CPUS];
> +#define cpu_physical_id(cpu) arm_cpu_to_apicid[cpu]

Sudeep already commented on this, please update it accordingly.

> +
>  #else	/* !CONFIG_ACPI */
>  #define acpi_disabled 1		/* ACPI sometimes enabled on ARM */
>  #define acpi_noirq 1		/* ACPI sometimes enabled on ARM */
> diff --git a/drivers/acpi/plat/arm-core.c b/drivers/acpi/plat/arm-core.c
> index 8ba3e6f..1d9b789 100644
> --- a/drivers/acpi/plat/arm-core.c
> +++ b/drivers/acpi/plat/arm-core.c
> @@ -31,6 +31,7 @@
>  #include <linux/smp.h>
>  
>  #include <asm/pgtable.h>
> +#include <asm/cputype.h>
>  
>  /*
>   * We never plan to use RSDT on arm/arm64 as its deprecated in spec but this
> @@ -52,6 +53,13 @@ EXPORT_SYMBOL(acpi_pci_disabled);
>   */
>  static u64 acpi_lapic_addr __initdata;

Is this variable actually needed ?

>  
> +/* available_cpus here means enabled cpu in MADT */
> +static int available_cpus;

Ditto.

> +
> +/* Map logic cpu id to physical GIC id (physical CPU id). */
> +int arm_cpu_to_apicid[NR_CPUS] = { [0 ... NR_CPUS-1] = -1 };
> +static int boot_cpu_apic_id = -1;

Do we need all these variables ? I think we should reuse cpu_logical_map
data structures for that, it looks suspiciously familiar.

>  #define BAD_MADT_ENTRY(entry, end) (					\
>  	(!entry) || (unsigned long)entry + sizeof(*entry) > end ||	\
>  	((struct acpi_subtable_header *)entry)->length < sizeof(*entry))
> @@ -132,6 +140,55 @@ static int __init acpi_parse_madt(struct acpi_table_header *table)
>   * Please refer to chapter5.2.12.14/15 of ACPI 5.0
>   */
>  
> +/**
> + * acpi_register_gic_cpu_interface - register a gic cpu interface and
> + * generates a logic cpu number
> + * @id: gic cpu interface id to register
> + * @enabled: this cpu is enabled or not
> + *
> + * Returns the logic cpu number which maps to the gic cpu interface
> + */
> +static int acpi_register_gic_cpu_interface(int id, u8 enabled)
> +{
> +	int cpu;
> +
> +	if (id >= MAX_GIC_CPU_INTERFACE) {
> +		pr_info(PREFIX "skipped apicid that is too big\n");
> +		return -EINVAL;
> +	}
> +
> +	total_cpus++;
> +	if (!enabled)
> +		return -EINVAL;
> +
> +	if (available_cpus >=  NR_CPUS) {
> +		pr_warn(PREFIX "NR_CPUS limit of %d reached,"
> +		" Processor %d/0x%x ignored.\n", NR_CPUS, total_cpus, id);
> +		return -EINVAL;
> +	}

Hmm...what if you are missing the boot CPU ? It is a worthy check.
Have a look at smp_init_cpus(), it does not bail out on cpu>= NR_CPUS
because you do want to make sure that the DT contains the boot CPU
node. Same logic applies.

> +
> +	available_cpus++;
> +

Is available_cpus != num_possible_cpus() ? It does not look like hence
available_cpus can go.

> +	/* allocate a logic cpu id for the new comer */
> +	if (boot_cpu_apic_id == id) {
> +		/*
> +		 * boot_cpu_init() already hold bit 0 in cpu_present_mask
> +		 * for BSP, no need to allocte again.
> +		 */
> +		cpu = 0;
> +	} else {
> +		cpu = cpumask_next_zero(-1, cpu_present_mask);
> +	}
> +
> +	/* map the logic cpu id to APIC id */
> +	arm_cpu_to_apicid[cpu] = id;
> +
> +	set_cpu_present(cpu, true);
> +	set_cpu_possible(cpu, true);

This is getting nasty. Before adding this patch and previous ones we
need to put in place a method for the kernel to make a definite choice between
ACPI and DT and stick to that. We can't initialize the logical map twice
(which will happen if your DT has valid cpu nodes and a chosen node pointing
to proper ACPI tables) or even having some entries initialized from DT and
others by ACPI. It is a big fat no-no, please update the series accordingly.

> +
> +	return cpu;
> +}
> +
>  static int __init
>  acpi_parse_gic(struct acpi_subtable_header *header, const unsigned long end)
>  {
> @@ -144,6 +201,16 @@ acpi_parse_gic(struct acpi_subtable_header *header, const unsigned long end)
>  
>  	acpi_table_print_madt_entry(header);
>  
> +	/*
> +	 * We need to register disabled CPU as well to permit
> +	 * counting disabled CPUs. This allows us to size
> +	 * cpus_possible_map more accurately, to permit
> +	 * to not preallocating memory for all NR_CPUS
> +	 * when we use CPU hotplug.
> +	 */
> +	acpi_register_gic_cpu_interface(processor->gic_id,
> +			processor->flags & ACPI_MADT_ENABLED);
> +
>  	return 0;
>  }
>  
> @@ -186,6 +253,19 @@ static int __init acpi_parse_madt_gic_entries(void)
>  		return count;
>  	}
>  
> +#ifdef CONFIG_SMP
> +	if (available_cpus == 0) {
> +		pr_info(PREFIX "Found 0 CPUs; assuming 1\n");
> +		arm_cpu_to_apicid[available_cpus] =
> +			read_cpuid_mpidr() & MPIDR_HWID_BITMASK;
> +		available_cpus = 1;	/* We've got at least one of these */
> +	}

I'd rather check the MADT for at least the boot cpu to present, if it is
not ACPI tables are horribly buggy and the kernel should barf on that.

> +#endif
> +
> +	/* Make boot-up look pretty */
> +	pr_info("%d CPUs available, %d CPUs total\n", available_cpus,
> +		total_cpus);

Ok, now, how can we use the "disabled" CPUs == (total_cpus - available_cpus) ?

Are we keeping track of them in the kernel at all ? It does not look
like, so I wonder whether we need this bit of info. I do not see why it
is pretty to know that there are disabled, aka unusable CPUs.

>  	return 0;
>  }
>  
> @@ -321,6 +401,9 @@ int __init early_acpi_boot_init(void)
>  	if (acpi_disabled)
>  		return -ENODEV;
>  
> +	/* Get the boot CPU's GIC cpu interface id before MADT parsing */
> +	boot_cpu_apic_id = read_cpuid_mpidr() & MPIDR_HWID_BITMASK;

See Sudeep's comment.

Thanks,
Lorenzo

^ permalink raw reply

* [PATCH 05/11] iommu/arm-smmu: Check for duplicate stream IDs when registering master devices
From: Will Deacon @ 2014-01-22 15:53 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1389876263-25759-6-git-send-email-andreas.herrmann@calxeda.com>

On Thu, Jan 16, 2014 at 12:44:17PM +0000, Andreas Herrmann wrote:
> Cc: Andreas Herrmann <herrmann.der.user@googlemail.com>
> Signed-off-by: Andreas Herrmann <andreas.herrmann@calxeda.com>
> ---
>  drivers/iommu/arm-smmu.c |   25 ++++++++++++++++++++++---
>  1 file changed, 22 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
> index 02a871e..a4e0c93 100644
> --- a/drivers/iommu/arm-smmu.c
> +++ b/drivers/iommu/arm-smmu.c
> @@ -56,6 +56,9 @@
>  /* Maximum number of stream IDs assigned to a single device */
>  #define MAX_MASTER_STREAMIDS		8
>  
> +/* Maximum stream ID */
> +#define ARM_SMMU_MAX_STREAMID		(SZ_64K - 1)
> +
>  /* Maximum number of context banks per SMMU */
>  #define ARM_SMMU_MAX_CBS		128
>  
> @@ -386,6 +389,8 @@ struct arm_smmu_device {
>  	u32				smr_mask_mask;
>  	u32				smr_id_mask;
>  
> +	unsigned long			*sids;

DECLARE_BITMAP instead? However, that's an 8k bitmap just for sanity
checking, which I'm not too fond of. Given that the motivation for the
checking was your smr allocator, perhaps it's sufficient just to do the
checking on a per-master basis, which we can do with the exhaustive search
each time.

Will

^ permalink raw reply


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