Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 1/6] mm: hugetlb: rename some allocation functions
From: Vlastimil Babka @ 2016-11-28 13:29 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1479107259-2011-2-git-send-email-shijie.huang@arm.com>

On 11/14/2016 08:07 AM, Huang Shijie wrote:
> After a future patch, the __alloc_buddy_huge_page() will not necessarily
> use the buddy allocator.
>
> So this patch removes the "buddy" from these functions:
> 	__alloc_buddy_huge_page -> __alloc_huge_page
> 	__alloc_buddy_huge_page_no_mpol -> __alloc_huge_page_no_mpol
> 	__alloc_buddy_huge_page_with_mpol -> __alloc_huge_page_with_mpol
>
> This patch makes preparation for the later patch.
>
> Signed-off-by: Huang Shijie <shijie.huang@arm.com>
> ---
>  mm/hugetlb.c | 24 ++++++++++++++----------
>  1 file changed, 14 insertions(+), 10 deletions(-)
>
> diff --git a/mm/hugetlb.c b/mm/hugetlb.c
> index 3edb759..496b703 100644
> --- a/mm/hugetlb.c
> +++ b/mm/hugetlb.c
> @@ -1157,6 +1157,10 @@ static int alloc_fresh_gigantic_page(struct hstate *h,
>
>  static inline bool gigantic_page_supported(void) { return true; }
>  #else
> +static inline struct page *alloc_gigantic_page(int nid, unsigned int order)
> +{
> +	return NULL;
> +}

This hunk is not explained by the description. Could belong to a later 
patch?

^ permalink raw reply

* [Qemu-devel] [kvm-unit-tests PATCH v7 00/11] QEMU MTTCG Test cases
From: Peter Maydell @ 2016-11-28 13:30 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161128115824.hrofgivt2mlfk7fh@kamzik.brq.redhat.com>

On 28 November 2016 at 11:58, Andrew Jones <drjones@redhat.com> wrote:
> On Mon, Nov 28, 2016 at 11:14:48AM +0000, Peter Maydell wrote:
>> On 28 November 2016 at 11:12, Alex Benn?e <alex.bennee@linaro.org> wrote:
>> >
>> > Andrew Jones <drjones@redhat.com> writes:
>> >> I've skimmed over everything looking at it from a framwork/sytle
>> >> perspective. I didn't dig in trying to understand the tests though.
>> >> One general comment, I see many tests introduce MAX_CPUS 8. Why do
>> >> that? Why not allow all cpus by using NR_CPUS for the array sizes?
>> >
>> > Yeah - I can fix those. I wonder what the maximum is with GIC V3?
>>
>> So large that you don't want to hardcode it as an array size...
>
> 255 with the gic series, not yet merged.

I was talking about the architectural GICv3 limit, which is larger
than that by many orders of magnitude. For QEMU it looks like
MAX_CPUMASK_BITS is now 288 rather than 255.

thanks
-- PMM

^ permalink raw reply

* [PATCH v4] crypto: arm64/sha2: integrate OpenSSL implementations of SHA256/SHA512
From: Will Deacon @ 2016-11-28 13:32 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAKv+Gu-uzqR758CSPZ_sWwbeejgw1cU-zwxpLU11A=3mnvqcNg@mail.gmail.com>

On Mon, Nov 28, 2016 at 02:17:34PM +0100, Ard Biesheuvel wrote:
> On 28 November 2016 at 13:05, Will Deacon <will.deacon@arm.com> wrote:
> > On Sun, Nov 20, 2016 at 11:42:01AM +0000, Ard Biesheuvel wrote:
> >> This integrates both the accelerated scalar and the NEON implementations
> >> of SHA-224/256 as well as SHA-384/512 from the OpenSSL project.
> >>
> >> Relative performance compared to the respective generic C versions:
> >>
> >>                  |  SHA256-scalar  | SHA256-NEON* |  SHA512  |
> >>      ------------+-----------------+--------------+----------+
> >>      Cortex-A53  |      1.63x      |     1.63x    |   2.34x  |
> >>      Cortex-A57  |      1.43x      |     1.59x    |   1.95x  |
> >>      Cortex-A73  |      1.26x      |     1.56x    |     ?    |
> >>
> >> The core crypto code was authored by Andy Polyakov of the OpenSSL
> >> project, in collaboration with whom the upstream code was adapted so
> >> that this module can be built from the same version of sha512-armv8.pl.
> >>
> >> The version in this patch was taken from OpenSSL commit 32bbb62ea634
> >> ("sha/asm/sha512-armv8.pl: fix big-endian support in __KERNEL__ case.")
> >>
> >> * The core SHA algorithm is fundamentally sequential, but there is a
> >>   secondary transformation involved, called the schedule update, which
> >>   can be performed independently. The NEON version of SHA-224/SHA-256
> >>   only implements this part of the algorithm using NEON instructions,
> >>   the sequential part is always done using scalar instructions.
> >>
> >> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> >> ---
> >>  arch/arm64/crypto/Kconfig               |    8 +
> >>  arch/arm64/crypto/Makefile              |   17 +
> >>  arch/arm64/crypto/sha256-core.S_shipped | 2061 ++++++++++++++++++++
> >>  arch/arm64/crypto/sha256-glue.c         |  185 ++
> >>  arch/arm64/crypto/sha512-armv8.pl       |  778 ++++++++
> >>  arch/arm64/crypto/sha512-core.S_shipped | 1085 +++++++++++
> >>  arch/arm64/crypto/sha512-glue.c         |   94 +
> >>  7 files changed, 4228 insertions(+)
> >
> > If I build a kernel with this applied and CRYPTO_SHA{256,512}_ARM64=y,
> > then I end up with untracked .S files according to git:
> >
> > $ git status
> > Untracked files:
> >         arch/arm64/crypto/sha256-core.S
> >         arch/arm64/crypto/sha512-core.S
> >
> 
> Ah right, I forgot to add a .gitignore for these: that is required
> with .S_shipped files. I didn't spot this myself because I always
> build out of tree
> 
> Would you mind taking a separate patch for that?

I think this should all go via herbert, so I guess just send him the extra
patch.

Will

^ permalink raw reply

* [GIT PULL v2] firmware: SCPI updates for v4.10
From: Sudeep Holla @ 2016-11-28 13:32 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161118115615.GB14913@e107155-lin>

Hi,

On 18/11/16 11:56, Sudeep Holla wrote:
> Hi ARM-SoC Team,
>
> I have decoupled the platform specific binding from generic SCPI. Also
> I have renamed "arm,legacy-scpi" to "arm,scpi-pre-1.0". Since I haven't
> heard back any objections from Olof/Rob for my response, I am sending
> the pull request now.
>

Gentle ping, looks like this got missed.

-- 
Regards,
Sudeep

^ permalink raw reply

* [PATCH] crypto: arm64/sha2: add generated .S files to .gitignore
From: Ard Biesheuvel @ 2016-11-28 13:37 UTC (permalink / raw)
  To: linux-arm-kernel

Add the files that are generated by the recently merged OpenSSL
SHA-256/512 implementation to .gitignore so Git disregards them
when showing untracked files.

Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 arch/arm64/crypto/.gitignore | 2 ++
 1 file changed, 2 insertions(+)
 create mode 100644 arch/arm64/crypto/.gitignore

diff --git a/arch/arm64/crypto/.gitignore b/arch/arm64/crypto/.gitignore
new file mode 100644
index 000000000000..879df8781ed5
--- /dev/null
+++ b/arch/arm64/crypto/.gitignore
@@ -0,0 +1,2 @@
+sha256-core.S
+sha512-core.S
-- 
2.7.4

^ permalink raw reply related

* [bug report v4.8] fs/locks.c: kernel oops during posix lock stress test
From: Jeff Layton @ 2016-11-28 13:40 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CACVXFVPsHjh3CWjdUrKB_r6=hkXK=qS3wpykbacdKe1rzz1H8Q@mail.gmail.com>

On Mon, 2016-11-28 at 11:10 +0800, Ming Lei wrote:
> Hi Guys,
> 
> When I run stress-ng via the following steps on one ARM64 dual
> socket system(Cavium Thunder), the kernel oops[1] can often be
> triggered after running the stress test for several hours(sometimes
> it may take longer):
> 
> - git clone git://kernel.ubuntu.com/cking/stress-ng.git
> - apply the attachment patch which just makes the posix file
> lock stress test more aggressive
> - run the test via '~/git/stress-ng$./stress-ng --lockf 128 --aggressive'
> 
> 
> From the oops log, looks one garbage file_lock node is got
> from the linked list of 'ctx->flc_posix' when the issue happens.
> 
> BTW, the issue isn't observed on single socket Cavium Thunder yet,
> and the same issue can be seen on Ubuntu Xenial(v4.4 based kernel)
> too.
> 
> Thanks,
> Ming
> 

Some questions just for clarification:

- I assume this is being run on a local fs of some sort? ext4 or xfs or
something?

- have you seen this on any other arch, besides ARM?

The file locking code does do some lockless checking to see whether the
i_flctx is even present and whether the list is empty in
locks_remove_posix. It's possible we have some barrier problems there,
but I don't quite see how that would cause us to have a corrupt lock on
the flc_posix list.

> [1] kernel oops log
> ubuntu at ubuntu:~/git/stress-ng$ ./stress-ng --lockf 128 --aggressive
> stress-ng: info:  [63828] defaulting to a 86400 second run per stressor
> stress-ng: info:  [63828] dispatching hogs: 128 lockf
> stress-ng: info:  [63828] cache allocate: default cache size: 16384K
> [80659.799092] Unable to handle kernel NULL pointer dereference at
> virtual address 00000030
> [80659.807219] pgd = ffff81001f365800
> [80659.810683] [00000030] *pgd=000001001a290003,
> *pud=000001001a290003, *pmd=0000010fa07f0003, *pte=0000000000000000
> [80659.821029] Internal error: Oops: 96000007 [#1] SMP
> [80659.825901] Modules linked in:
> [80659.828962] CPU: 15 PID: 63848 Comm: stress-ng-lockf Tainted: G
>    W       4.8.0 #167
> [80659.837132] Hardware name: Cavium ThunderX CRB/To be filled by
> O.E.M., BIOS 5.11 12/12/2012
> [80659.845479] task: ffff81001ee78580 task.stack: ffff81001f798000
> [80659.851402] PC is at posix_locks_conflict+0x94/0xc0
> [80659.856282] LR is at posix_lock_inode+0x90/0x6b0
> [80659.860896] pc : [<ffff00000828c694>] lr : [<ffff00000828cd90>]
> pstate: a0000145
> [80659.868285] sp : ffff81001f79bca0
> [80659.871596] x29: ffff81001f79bca0 x28: ffff81001f798000
> [80659.876915] x27: ffff800fdffbc160 x26: 0000000000000000
> [80659.882234] x25: ffff800fd2da2b30 x24: ffff800fce927430
> [80659.887551] x23: ffff800fce92d8f0 x22: ffff81001f79bd30
> [80659.892869] x21: ffff800fd2da2b18 x20: fffffffffffffff8
> [80659.898187] x19: ffff800fdffbc160 x18: 0000000000001140
> [80659.903504] x17: 0000ffff8870a578 x16: ffff000008245768
> [80659.908821] x15: 0000ffff888bc000 x14: 0000000000000000
> [80659.914139] x13: 00000003e8000000 x12: 0000000000000018
> [80659.919457] x11: 00000000000e6a17 x10: 00000000ffffffd0
> [80659.924776] x9 : 0000000000000000 x8 : ffff800fce927500
> [80659.930094] x7 : 0000000000000000 x6 : 000000000000007f
> [80659.935413] x5 : 0000000000000080 x4 : ffff800fce927438
> [80659.940729] x3 : ffff800fce927458 x2 : 00000000000026b9
> [80659.946047] x1 : ffff81001f37f300 x0 : 0000000000000000
> [80659.951363]
> [80659.952851] Process stress-ng-lockf (pid: 63848, stack limit =
> 0xffff81001f798020)
> [80659.960415] Stack: (0xffff81001f79bca0 to 0xffff81001f79c000)
> [80659.966158] bca0: ffff81001f79bcc0 ffff00000828cd90
> fffffffffffffff8 ffff800fa3a66568
> [80659.973986] bcc0: ffff81001f79bd40 ffff00000828d5f0
> ffff800f8185c700 ffff800fdffbc160
> [80659.981812] bce0: 0000000000000006 0000000000000000
> ffff81001f79bdd0 0000000000000006
> [80659.989638] bd00: 0000000000000120 0000000000000019
> ffff0000088b1000 ffff81001f798000
> [80659.997465] bd20: ffff81001f79bd40 ffff000008403fec
> ffff81001f79bd30 ffff81001f79bd30
> [80660.005292] bd40: ffff81001f79bd70 ffff00000828d8bc
> ffff800f8185c700 ffff800fdffbc160
> [80660.013118] bd60: ffff800fdffbc1b8 ffff800f8185c700
> ffff81001f79bde0 ffff00000828ef10
> [80660.020944] bd80: ffff800f8185c700 0000000000000000
> ffff800fdffbc160 ffff800fa3a66568
> [80660.028770] bda0: 0000000000000006 0000000000000004
> ffff81001f79bde0 ffff00000828ee14
> [80660.036596] bdc0: ffff800f8185c700 00000000fffffff2
> ffff800fdffbc160 ffff810ff99aae80
> [80660.044423] bde0: ffff81001f79be70 ffff000008245b84
> ffff800f8185c700 ffff800f8185c700
> [80660.052249] be00: 0000000000000000 0000000000000006
> 0000ffffdad5d4b0 0000000000000004
> [80660.060087] be20: 0000000000000120 000000000000003e
> 0000000000010001 0000000000000000
> [80660.067916] be40: 0000000000000008 0000000000000000
> 0000000000010001 0000000000000000
> [80660.075742] be60: 0000000000000008 0000000000000000
> 0000000000000000 ffff0000080836f0
> [80660.083568] be80: 0000000000000000 00000000005c5000
> ffffffffffffffff 0000ffff8870a3b8
> [80660.091394] bea0: 0000000080000000 0000000000000015
> 0000000080000000 00000000005c5000
> [80660.099220] bec0: 0000000000000004 0000000000000006
> 0000ffffdad5d4b0 00000000ffffff80
> [80660.107046] bee0: 0000ffffdad5d490 0000000026c26373
> 000000000000176f 0000000000004650
> [80660.114873] bf00: 0000000000000019 0000000000006536
> 00000000ffffffd0 00000000000e6a17
> [80660.122698] bf20: 0000000000000018 00000003e8000000
> 0000000000000000 0000ffff888bc000
> [80660.130524] bf40: 000000000048a170 0000ffff8870a578
> 0000000000001140 000000000000055f
> [80660.138351] bf60: 00000000005c5000 0000000000000004
> 0000ffff879f9008 0000000000000000
> [80660.146177] bf80: 0000000000000002 000000000048b530
> 2001000800400201 0000ffffdad60758
> [80660.154004] bfa0: 000000000048b008 0000ffffdad5d390
> 0000ffff8870a518 0000ffffdad5d390
> [80660.161830] bfc0: 0000ffff8870a3b8 0000000080000000
> 0000000000000004 0000000000000019
> [80660.169656] bfe0: 0000000000000000 0000000000000000
> 0000000000000000 0000000000000000
> [80660.177481] Call trace:
> [80660.179928] Exception stack(0xffff81001f79bad0 to 0xffff81001f79bc00)
> [80660.186365] bac0:
> ffff800fdffbc160 0001000000000000
> [80660.194192] bae0: ffff81001f79bca0 ffff00000828c694
> ffff800fc0002c00 ffff81001ee78600
> [80660.202017] bb00: ffff81001f79bb70 ffff00000820b57c
> ffff800fcb2a6d88 ffff800fc0002c00
> [80660.209843] bb20: 0000000000000001 ffff810008ddbf00
> ffff81001f79bc30 ffff81001f79bc30
> [80660.217670] bb40: 0000000000000000 ffff810fa0712be8
> ffff800f81dfd680 ffff810fa0712be8
> [80660.225496] bb60: 0000000000000001 ffff810008ddbf00
> 0000000000000000 ffff81001f37f300
> [80660.233322] bb80: 00000000000026b9 ffff800fce927458
> ffff800fce927438 0000000000000080
> [80660.241148] bba0: 000000000000007f 0000000000000000
> ffff800fce927500 0000000000000000
> [80660.248974] bbc0: 00000000ffffffd0 00000000000e6a17
> 0000000000000018 00000003e8000000
> [80660.256800] bbe0: 0000000000000000 0000ffff888bc000
> ffff000008245768 0000ffff8870a578
> [80660.264636] [<ffff00000828c694>] posix_locks_conflict+0x94/0xc0
> [80660.270559] [<ffff00000828cd90>] posix_lock_inode+0x90/0x6b0
> [80660.276220] [<ffff00000828d5f0>] vfs_lock_file+0x68/0x78
> [80660.281537] [<ffff00000828d8bc>] do_lock_file_wait+0x54/0xe0
> [80660.287199] [<ffff00000828ef10>] fcntl_setlk+0x1c0/0x308
> [80660.292513] [<ffff000008245b84>] SyS_fcntl+0x41c/0x5b8
> [80660.297653] [<ffff0000080836f0>] el0_svc_naked+0x24/0x28
> [80660.302961] Code: a8c27bfd d65f03c0 d503201f f9401e61 (f9401e80)
> [80660.309188] ---[ end trace aa50050684d3a3fe ]---

-- 
Jeff Layton <jlayton@poochiereds.net>

^ permalink raw reply

* [PATCH net v2 1/1] net: macb: fix the RX queue reset in macb_rx()
From: Cyrille Pitchen @ 2016-11-28 13:40 UTC (permalink / raw)
  To: linux-arm-kernel

On macb only (not gem), when a RX queue corruption was detected from
macb_rx(), the RX queue was reset: during this process the RX ring
buffer descriptor was initialized by macb_init_rx_ring() but we forgot
to also set bp->rx_tail to 0.

Indeed, when processing the received frames, bp->rx_tail provides the
macb driver with the index in the RX ring buffer of the next buffer to
process. So when the whole ring buffer is reset we must also reset
bp->rx_tail so the driver is synchronized again with the hardware.

Since macb_init_rx_ring() is called from many locations, currently from
macb_rx() and macb_init_rings(), we'd rather add the "bp->rx_tail = 0;"
line inside macb_init_rx_ring() than add the very same line after each
call of this function.

Without this fix, the rx queue is not reset properly to recover from
queue corruption and connection drop may occur.

Signed-off-by: Cyrille Pitchen <cyrille.pitchen@atmel.com>
Fixes: 9ba723b081a2 ("net: macb: remove BUG_ON() and reset the queue to handle RX errors")
Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com>
---

ChangeLog:

v1 -> v2:
- rebase on net/master (v1 was based on net-next/master)
- add "Acked-by:" tag from Nicolas Ferre.

 drivers/net/ethernet/cadence/macb.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/cadence/macb.c b/drivers/net/ethernet/cadence/macb.c
index 533653bd7aec..3ede59c9cae0 100644
--- a/drivers/net/ethernet/cadence/macb.c
+++ b/drivers/net/ethernet/cadence/macb.c
@@ -975,6 +975,7 @@ static inline void macb_init_rx_ring(struct macb *bp)
 		addr += bp->rx_buffer_size;
 	}
 	bp->rx_ring[RX_RING_SIZE - 1].addr |= MACB_BIT(RX_WRAP);
+	bp->rx_tail = 0;
 }
 
 static int macb_rx(struct macb *bp, int budget)
@@ -1616,8 +1617,6 @@ static void macb_init_rings(struct macb *bp)
 	bp->queues[0].tx_head = 0;
 	bp->queues[0].tx_tail = 0;
 	bp->queues[0].tx_ring[TX_RING_SIZE - 1].ctrl |= MACB_BIT(TX_WRAP);
-
-	bp->rx_tail = 0;
 }
 
 static void macb_reset_hw(struct macb *bp)
-- 
2.7.4

^ permalink raw reply related

* [PATCH net-next v3 0/4] Fix OdroidC2 Gigabit Tx link issue
From: Neil Armstrong @ 2016-11-28 13:42 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1480326409-25419-1-git-send-email-jbrunet@baylibre.com>

On 11/28/2016 10:46 AM, Jerome Brunet wrote:
> This patchset fixes an issue with the OdroidC2 board (DWMAC + RTL8211F).
> The platform seems to enter LPI on the Rx path too often while performing
> relatively high TX transfer. This eventually break the link (both Tx and
> Rx), and require to bring the interface down and up again to get the Rx
> path working again.
> 
> The root cause of this issue is not fully understood yet but disabling EEE
> advertisement on the PHY prevent this feature to be negotiated.
> With this change, the link is stable and reliable, with the expected
> throughput performance.
> 
> The patchset adds options in the generic phy driver to disable EEE
> advertisement, through device tree. The way it is done is very similar
> to the handling of the max-speed property.
> 
> Changes since V2: [2]
>  - Rename "eee-advert-disable" to "eee-broken-modes" to make the intended
>    purpose of this option clear (flag broken configuration, not a
>    configuration option)
>  - Add DT bindings constants so the DT configuration is more user friendly
>  - Submit to net-next instead of net.
> 
> Changes since V1: [1]
>  - Disable the advertisement of EEE in the generic code instead of the
>    realtek driver.
> 
> [1] : http://lkml.kernel.org/r/1479220154-25851-1-git-send-email-jbrunet at baylibre.com
> [2] : http://lkml.kernel.org/r/1479742524-30222-1-git-send-email-jbrunet at baylibre.com
> 
> 
> Jerome Brunet (4):
>   net: phy: add an option to disable EEE advertisement
>   dt-bindings: net: add EEE capability constants
>   dt: bindings: add ethernet phy eee-broken-modes option documentation
>   ARM64: dts: meson: odroidc2: disable advertisement EEE for GbE.
> 
>  Documentation/devicetree/bindings/net/phy.txt      |  2 +
>  .../arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts | 16 +++++
>  drivers/net/phy/phy.c                              |  3 +
>  drivers/net/phy/phy_device.c                       | 80 +++++++++++++++++++---
>  include/dt-bindings/net/mdio.h                     | 19 +++++
>  include/linux/phy.h                                |  3 +
>  6 files changed, 114 insertions(+), 9 deletions(-)
>  create mode 100644 include/dt-bindings/net/mdio.h
> 

Tested using Nexbox A1 (S912) and Amlogic P230 (S905D) devices (DWMAC + RTL8211F).

Tested-by: Neil Armstrong <narmstrong@baylibre.com>

^ permalink raw reply

* [PATCH 1/1] net: macb: fix the RX queue reset in macb_rx()
From: Cyrille Pitchen @ 2016-11-28 13:43 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161127.202549.1887792653016840262.davem@davemloft.net>

Hi David,

Le 28/11/2016 ? 02:25, David Miller a ?crit :
> From: Cyrille Pitchen <cyrille.pitchen@atmel.com>
> Date: Fri, 25 Nov 2016 09:49:32 +0100
> 
>> On macb only (not gem), when a RX queue corruption was detected from
>> macb_rx(), the RX queue was reset: during this process the RX ring
>> buffer descriptor was initialized by macb_init_rx_ring() but we forgot
>> to also set bp->rx_tail to 0.
>>
>> Indeed, when processing the received frames, bp->rx_tail provides the
>> macb driver with the index in the RX ring buffer of the next buffer to
>> process. So when the whole ring buffer is reset we must also reset
>> bp->rx_tail so the driver is synchronized again with the hardware.
>>
>> Since macb_init_rx_ring() is called from many locations, currently from
>> macb_rx() and macb_init_rings(), we'd rather add the "bp->rx_tail = 0;"
>> line inside macb_init_rx_ring() than add the very same line after each
>> call of this function.
>>
>> Without this fix, the rx queue is not reset properly to recover from
>> queue corruption and connection drop may occur.
>>
>> Signed-off-by: Cyrille Pitchen <cyrille.pitchen@atmel.com>
>> Fixes: 9ba723b081a2 ("net: macb: remove BUG_ON() and reset the queue to handle RX errors")
> 
> This doesn't apply cleanly to the 'net' tree, where
> RX_RING_SIZE is used instead of bp->rx_ring_size. It seems
> you generated this against net-next, however you didn't say
> that either in your Subject line nor the commit message.
> 
> As a bug fix this should be targetted at 'net'.
> 

Indeed, sorry. I've just sent a v2 based on net/master.

Best regards,

Cyrille

^ permalink raw reply

* [GIT PULL]: ARM ARTPEC changes for 4.10
From: Jesper Nilsson @ 2016-11-28 13:51 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <10339600.mZlnsf0Sve@wuerfel>

On Mon, Nov 28, 2016 at 01:57:10PM +0100, Arnd Bergmann wrote:
> On Monday, November 28, 2016 1:33:31 PM CET Jesper Nilsson wrote:
> > > Hi Jesper and Niklas,
> > > 
> > > I just found the old pull request while going through my mail backlog.
> > > 
> > > A few things for you to remember for next time:
> > > 
> > > - please send pull requests "To: arm at kernel.org" so we know they
> > >   are destined for arm-soc
> > 
> > Ok, should we add that in the MAINTAINERS file so we can
> > get it automatically from get_maintainer?
> 
> No, we don't want to get every single patch that people submit to
> platform maintainers, only the consolidated pull requests that you
> send.

Right, sounds reasonable, will do.

> 	Arnd

/^JN - Jesper Nilsson
-- 
               Jesper Nilsson -- jesper.nilsson at axis.com

^ permalink raw reply

* [PATCH 1/2] bus: vexpress-config: fix device reference leak
From: Sudeep Holla @ 2016-11-28 13:57 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1479317491-7435-1-git-send-email-sudeep.holla@arm.com>



On 16/11/16 17:31, Sudeep Holla wrote:
> From: Johan Hovold <johan@kernel.org>
>
> Make sure to drop the reference to the parent device taken by
> class_find_device() after populating the bus.
>
> Fixes: 3b9334ac835b ("mfd: vexpress: Convert custom func API to regmap")
> Acked-by: Sudeep Holla <sudeep.holla@arm.com>
> Signed-off-by: Johan Hovold <johan@kernel.org>
> ---
>  drivers/bus/vexpress-config.c | 7 ++++++-
>  1 file changed, 6 insertions(+), 1 deletion(-)
>
> Hi ARM-SoC team,
>
> I am not sure if these couple of patches can be considered as fixes for
> v4.9. I will leave that to you guys.
>
> Can you pick these couple of patches directly either for v4.9 or v4.10 ?
> I am trying to avoid single patch pull requests here. Let me know if
> you prefer PR instead.
>

Gentle ping. It need not go into v4.9. Please pick them for v4.10

-- 
Regards,
Sudeep

^ permalink raw reply

* [PATCH] ARM: BCM5301X: Enable UART by default for BCM4708(1) and BCM4709(4)
From: Rafał Miłecki @ 2016-11-28 14:01 UTC (permalink / raw)
  To: linux-arm-kernel

From: Rafa? Mi?ecki <rafal@milecki.pl>

Every device tested so far got UART0 (at 0x18000300) working as serial
console. It's most likely part of reference design and all vendors use
it that way.

It seems to be easier to enable it by default and just disable it if we
ever see a device with different hardware design.

Signed-off-by: Rafa? Mi?ecki <rafal@milecki.pl>
---
 arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts  | 4 ----
 arch/arm/boot/dts/bcm4708-luxul-xap-1510.dts       | 4 ----
 arch/arm/boot/dts/bcm4708-luxul-xwc-1000.dts       | 4 ----
 arch/arm/boot/dts/bcm4708-netgear-r6250.dts        | 4 ----
 arch/arm/boot/dts/bcm4708-smartrg-sr400ac.dts      | 4 ----
 arch/arm/boot/dts/bcm4708.dtsi                     | 4 ++++
 arch/arm/boot/dts/bcm47081-buffalo-wzr-600dhp2.dts | 4 ----
 arch/arm/boot/dts/bcm47081.dtsi                    | 4 ++++
 arch/arm/boot/dts/bcm4709-netgear-r7000.dts        | 4 ----
 arch/arm/boot/dts/bcm4709-netgear-r8000.dts        | 4 ----
 arch/arm/boot/dts/bcm4709-tplink-archer-c9-v1.dts  | 4 ----
 arch/arm/boot/dts/bcm4709.dtsi                     | 1 +
 arch/arm/boot/dts/bcm47094-dlink-dir-885l.dts      | 4 ----
 arch/arm/boot/dts/bcm47094-luxul-xwr-3100.dts      | 4 ----
 arch/arm/boot/dts/bcm47094-netgear-r8500.dts       | 4 ----
 arch/arm/boot/dts/bcm47094.dtsi                    | 1 +
 16 files changed, 10 insertions(+), 48 deletions(-)

diff --git a/arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts b/arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts
index 9cb186e..d49afec0 100644
--- a/arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts
+++ b/arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts
@@ -136,10 +136,6 @@
 	};
 };
 
-&uart0 {
-	status = "okay";
-};
-
 &usb2 {
 	vcc-gpio = <&chipcommon 9 GPIO_ACTIVE_HIGH>;
 };
diff --git a/arch/arm/boot/dts/bcm4708-luxul-xap-1510.dts b/arch/arm/boot/dts/bcm4708-luxul-xap-1510.dts
index 35e6ed6..f591b0f 100644
--- a/arch/arm/boot/dts/bcm4708-luxul-xap-1510.dts
+++ b/arch/arm/boot/dts/bcm4708-luxul-xap-1510.dts
@@ -55,10 +55,6 @@
 	};
 };
 
-&uart0 {
-	status = "okay";
-};
-
 &spi_nor {
 	status = "okay";
 };
diff --git a/arch/arm/boot/dts/bcm4708-luxul-xwc-1000.dts b/arch/arm/boot/dts/bcm4708-luxul-xwc-1000.dts
index 1c7e53d..50d65d8 100644
--- a/arch/arm/boot/dts/bcm4708-luxul-xwc-1000.dts
+++ b/arch/arm/boot/dts/bcm4708-luxul-xwc-1000.dts
@@ -56,10 +56,6 @@
 	};
 };
 
-&uart0 {
-	status = "okay";
-};
-
 &spi_nor {
 	status = "okay";
 };
diff --git a/arch/arm/boot/dts/bcm4708-netgear-r6250.dts b/arch/arm/boot/dts/bcm4708-netgear-r6250.dts
index 8ce39d5..8519548 100644
--- a/arch/arm/boot/dts/bcm4708-netgear-r6250.dts
+++ b/arch/arm/boot/dts/bcm4708-netgear-r6250.dts
@@ -83,10 +83,6 @@
 	};
 };
 
-&uart0 {
-	status = "okay";
-};
-
 &usb3 {
 	vcc-gpio = <&chipcommon 0 GPIO_ACTIVE_HIGH>;
 };
diff --git a/arch/arm/boot/dts/bcm4708-smartrg-sr400ac.dts b/arch/arm/boot/dts/bcm4708-smartrg-sr400ac.dts
index 70f4bb9..74cfcd3 100644
--- a/arch/arm/boot/dts/bcm4708-smartrg-sr400ac.dts
+++ b/arch/arm/boot/dts/bcm4708-smartrg-sr400ac.dts
@@ -119,10 +119,6 @@
 	};
 };
 
-&uart0 {
-	status = "okay";
-};
-
 &spi_nor {
 	status = "okay";
 };
diff --git a/arch/arm/boot/dts/bcm4708.dtsi b/arch/arm/boot/dts/bcm4708.dtsi
index eed4dd1..d0eec09 100644
--- a/arch/arm/boot/dts/bcm4708.dtsi
+++ b/arch/arm/boot/dts/bcm4708.dtsi
@@ -34,3 +34,7 @@
 	};
 
 };
+
+&uart0 {
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/bcm47081-buffalo-wzr-600dhp2.dts b/arch/arm/boot/dts/bcm47081-buffalo-wzr-600dhp2.dts
index a9c8def..2922536 100644
--- a/arch/arm/boot/dts/bcm47081-buffalo-wzr-600dhp2.dts
+++ b/arch/arm/boot/dts/bcm47081-buffalo-wzr-600dhp2.dts
@@ -122,7 +122,3 @@
 		};
 	};
 };
-
-&uart0 {
-	status = "okay";
-};
diff --git a/arch/arm/boot/dts/bcm47081.dtsi b/arch/arm/boot/dts/bcm47081.dtsi
index f720012..c5f7619 100644
--- a/arch/arm/boot/dts/bcm47081.dtsi
+++ b/arch/arm/boot/dts/bcm47081.dtsi
@@ -24,3 +24,7 @@
 		};
 	};
 };
+
+&uart0 {
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/bcm4709-netgear-r7000.dts b/arch/arm/boot/dts/bcm4709-netgear-r7000.dts
index fd38d2a..0225d82 100644
--- a/arch/arm/boot/dts/bcm4709-netgear-r7000.dts
+++ b/arch/arm/boot/dts/bcm4709-netgear-r7000.dts
@@ -100,7 +100,3 @@
 		};
 	};
 };
-
-&uart0 {
-	status = "okay";
-};
diff --git a/arch/arm/boot/dts/bcm4709-netgear-r8000.dts b/arch/arm/boot/dts/bcm4709-netgear-r8000.dts
index 92f8a72..56d38a3 100644
--- a/arch/arm/boot/dts/bcm4709-netgear-r8000.dts
+++ b/arch/arm/boot/dts/bcm4709-netgear-r8000.dts
@@ -107,10 +107,6 @@
 	};
 };
 
-&uart0 {
-	status = "okay";
-};
-
 &usb2 {
 	vcc-gpio = <&chipcommon 0 GPIO_ACTIVE_HIGH>;
 };
diff --git a/arch/arm/boot/dts/bcm4709-tplink-archer-c9-v1.dts b/arch/arm/boot/dts/bcm4709-tplink-archer-c9-v1.dts
index 9a92c24..c67bfaa 100644
--- a/arch/arm/boot/dts/bcm4709-tplink-archer-c9-v1.dts
+++ b/arch/arm/boot/dts/bcm4709-tplink-archer-c9-v1.dts
@@ -97,10 +97,6 @@
 	};
 };
 
-&uart0 {
-	status = "okay";
-};
-
 &usb2 {
 	vcc-gpio = <&chipcommon 13 GPIO_ACTIVE_HIGH>;
 };
diff --git a/arch/arm/boot/dts/bcm4709.dtsi b/arch/arm/boot/dts/bcm4709.dtsi
index f039765..c645fea 100644
--- a/arch/arm/boot/dts/bcm4709.dtsi
+++ b/arch/arm/boot/dts/bcm4709.dtsi
@@ -8,4 +8,5 @@
 
 &uart0 {
 	clock-frequency = <125000000>;
+	status = "okay";
 };
diff --git a/arch/arm/boot/dts/bcm47094-dlink-dir-885l.dts b/arch/arm/boot/dts/bcm47094-dlink-dir-885l.dts
index 661348d..7fb9270 100644
--- a/arch/arm/boot/dts/bcm47094-dlink-dir-885l.dts
+++ b/arch/arm/boot/dts/bcm47094-dlink-dir-885l.dts
@@ -105,10 +105,6 @@
 	};
 };
 
-&uart0 {
-	status = "okay";
-};
-
 &usb3 {
 	vcc-gpio = <&chipcommon 18 GPIO_ACTIVE_HIGH>;
 };
diff --git a/arch/arm/boot/dts/bcm47094-luxul-xwr-3100.dts b/arch/arm/boot/dts/bcm47094-luxul-xwr-3100.dts
index 169b35f..2f4a651 100644
--- a/arch/arm/boot/dts/bcm47094-luxul-xwr-3100.dts
+++ b/arch/arm/boot/dts/bcm47094-luxul-xwr-3100.dts
@@ -98,10 +98,6 @@
 	};
 };
 
-&uart0 {
-	status = "okay";
-};
-
 &usb3 {
 	vcc-gpio = <&chipcommon 18 GPIO_ACTIVE_HIGH>;
 };
diff --git a/arch/arm/boot/dts/bcm47094-netgear-r8500.dts b/arch/arm/boot/dts/bcm47094-netgear-r8500.dts
index 521b415..7ecd57c 100644
--- a/arch/arm/boot/dts/bcm47094-netgear-r8500.dts
+++ b/arch/arm/boot/dts/bcm47094-netgear-r8500.dts
@@ -97,7 +97,3 @@
 		};
 	};
 };
-
-&uart0 {
-	status = "okay";
-};
diff --git a/arch/arm/boot/dts/bcm47094.dtsi b/arch/arm/boot/dts/bcm47094.dtsi
index 4f09aa0..4840a78 100644
--- a/arch/arm/boot/dts/bcm47094.dtsi
+++ b/arch/arm/boot/dts/bcm47094.dtsi
@@ -14,4 +14,5 @@
 
 &uart0 {
 	clock-frequency = <125000000>;
+	status = "okay";
 };
-- 
2.10.1

^ permalink raw reply related

* [Qemu-devel] [kvm-unit-tests PATCH v7 00/11] QEMU MTTCG Test cases
From: Andrew Jones @ 2016-11-28 14:04 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAFEAcA8-3qHnp1T4bAiUL3NT8fHWik7-8zruyQKGgfADn5xF9w@mail.gmail.com>

On Mon, Nov 28, 2016 at 01:30:54PM +0000, Peter Maydell wrote:
> On 28 November 2016 at 11:58, Andrew Jones <drjones@redhat.com> wrote:
> > On Mon, Nov 28, 2016 at 11:14:48AM +0000, Peter Maydell wrote:
> >> On 28 November 2016 at 11:12, Alex Benn?e <alex.bennee@linaro.org> wrote:
> >> >
> >> > Andrew Jones <drjones@redhat.com> writes:
> >> >> I've skimmed over everything looking at it from a framwork/sytle
> >> >> perspective. I didn't dig in trying to understand the tests though.
> >> >> One general comment, I see many tests introduce MAX_CPUS 8. Why do
> >> >> that? Why not allow all cpus by using NR_CPUS for the array sizes?
> >> >
> >> > Yeah - I can fix those. I wonder what the maximum is with GIC V3?
> >>
> >> So large that you don't want to hardcode it as an array size...
> >
> > 255 with the gic series, not yet merged.
> 
> I was talking about the architectural GICv3 limit, which is larger
> than that by many orders of magnitude. For QEMU it looks like
> MAX_CPUMASK_BITS is now 288 rather than 255.

Ah, yeah. So far we haven't considered testing limits beyond what
KVM supports, VGIC_V3_MAX_CPUS=255. However with TCG, and some
patience, we could attempt to test bigger limits. In that case,
though, we'll want to recompile kvm-unit-tests with a larger NR_CPUS
and run a specific unit test.

mach-virt still has 255 as well, mc->max_cpus = 255, so we'd have
to bump that too if we want to experiment.

Thanks,
drew

^ permalink raw reply

* [Qemu-devel] [kvm-unit-tests PATCH v7 00/11] QEMU MTTCG Test cases
From: Andrew Jones @ 2016-11-28 14:07 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161128140445.j336ksd7vqhi4ivz@kamzik.brq.redhat.com>

On Mon, Nov 28, 2016 at 03:04:45PM +0100, Andrew Jones wrote:
> On Mon, Nov 28, 2016 at 01:30:54PM +0000, Peter Maydell wrote:
> > On 28 November 2016 at 11:58, Andrew Jones <drjones@redhat.com> wrote:
> > > On Mon, Nov 28, 2016 at 11:14:48AM +0000, Peter Maydell wrote:
> > >> On 28 November 2016 at 11:12, Alex Benn?e <alex.bennee@linaro.org> wrote:
> > >> >
> > >> > Andrew Jones <drjones@redhat.com> writes:
> > >> >> I've skimmed over everything looking at it from a framwork/sytle
> > >> >> perspective. I didn't dig in trying to understand the tests though.
> > >> >> One general comment, I see many tests introduce MAX_CPUS 8. Why do
> > >> >> that? Why not allow all cpus by using NR_CPUS for the array sizes?
> > >> >
> > >> > Yeah - I can fix those. I wonder what the maximum is with GIC V3?
> > >>
> > >> So large that you don't want to hardcode it as an array size...
> > >
> > > 255 with the gic series, not yet merged.
> > 
> > I was talking about the architectural GICv3 limit, which is larger
> > than that by many orders of magnitude. For QEMU it looks like
> > MAX_CPUMASK_BITS is now 288 rather than 255.
> 
> Ah, yeah. So far we haven't considered testing limits beyond what
> KVM supports, VGIC_V3_MAX_CPUS=255. However with TCG, and some
> patience, we could attempt to test bigger limits. In that case,
> though, we'll want to recompile kvm-unit-tests with a larger NR_CPUS
> and run a specific unit test.
> 
> mach-virt still has 255 as well, mc->max_cpus = 255, so we'd have
> to bump that too if we want to experiment.

Er... actually mach-virt is 123, as we only allocate 123 redistributors.

drew

^ permalink raw reply

* [PATCH v2 1/2] arm64: dts: zx: Fix gic GICR property
From: Shawn Guo @ 2016-11-28 14:08 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <2953810.EeueujTjSC@wuerfel>

On Sat, Nov 26, 2016 at 6:03 AM, Arnd Bergmann <arnd@arndb.de> wrote:
> On Monday, October 17, 2016 1:49:19 PM CET Olof Johansson wrote:
>> On Thu, Oct 13, 2016 at 08:31:20PM +0800, Jun Nie wrote:
>> > GICR for multiple CPU can be described with start address and stride,
>> > or with multiple address. Current multiple address and stride are
>> > both used. Fix it.
>> >
>> > vmalloc patch 727a7f5a9 triggered this bug:
>> > [    0.097146] Unable to handle kernel paging request at virtual address ffff000008060008
>> > [    0.097150] pgd = ffff000008602000
>> > [    0.097160] [ffff000008060008] *pgd=000000007fffe003, *pud=000000007fffd003, *pmd=000000007fffc003, *pte=0000000000000000
>> > [    0.097165] Internal error: Oops: 96000007 [#1] PREEMPT SMP
>> > [    0.097170] Modules linked in:
>> > [    0.097177] CPU: 1 PID: 0 Comm: swapper/1 Not tainted 4.8.0+ #1474
>> > [    0.097179] Hardware name: ZTE zx296718 evaluation board (DT)
>> > [    0.097183] task: ffff80003e8c8b80 task.stack: ffff80003e8d0000
>> > [    0.097197] PC is at gic_populate_rdist+0x74/0x15c
>> > [    0.097202] LR is at gic_starting_cpu+0xc/0x20
>> > [    0.097206] pc : [<ffff0000082b1b18>] lr : [<ffff0000082b26e0>] pstate: 600001c5
>> >
>> > Signed-off-by: Jun Nie <jun.nie@linaro.org>
>>
>> A Fixes: tag would be useful on a patch like this, to tell what patch
>> introduced the problem. Please consider using them in the future.
>>
>> I've applied this one to fixes now.
>
> Hi Olof,
>
> I happened to still have this one in my todo folder as I must have
> missed your reply, and I stumbled over it while looking for things
> that may have gone missing.
>
> I don't see it in v4.9-rc6, did it get dropped accidentally?

Please help get this into v4.9 if possible, as it is required to get
v4.9 kernel boot up on ZTE ZX296718 SoC.  Thanks.

Shawn

^ permalink raw reply

* [Qemu-devel] [kvm-unit-tests PATCH v7 00/11] QEMU MTTCG Test cases
From: Peter Maydell @ 2016-11-28 14:09 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161128140705.caqpoiuvxy3mg2zk@kamzik.brq.redhat.com>

On 28 November 2016 at 14:07, Andrew Jones <drjones@redhat.com> wrote:
> Er... actually mach-virt is 123, as we only allocate 123 redistributors.

Oh yes, I'd forgotten about that limit. We'd need to add
a KVM API for allocating redistributors in non-contiguous
bits of memory if we wanted to raise that.

thanks
-- PMM

^ permalink raw reply

* [PATCH V2 fix 5/6] mm: hugetlb: add a new function to allocate a new gigantic page
From: Vlastimil Babka @ 2016-11-28 14:17 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1479279304-31379-1-git-send-email-shijie.huang@arm.com>

On 11/16/2016 07:55 AM, Huang Shijie wrote:
> There are three ways we can allocate a new gigantic page:
>
> 1. When the NUMA is not enabled, use alloc_gigantic_page() to get
>    the gigantic page.
>
> 2. The NUMA is enabled, but the vma is NULL.
>    There is no memory policy we can refer to.
>    So create a @nodes_allowed, initialize it with init_nodemask_of_mempolicy()
>    or init_nodemask_of_node(). Then use alloc_fresh_gigantic_page() to get
>    the gigantic page.
>
> 3. The NUMA is enabled, and the vma is valid.
>    We can follow the memory policy of the @vma.
>
>    Get @nodes_allowed by huge_nodemask(), and use alloc_fresh_gigantic_page()
>    to get the gigantic page.
>
> Signed-off-by: Huang Shijie <shijie.huang@arm.com>
> ---
> Since the huge_nodemask() is changed, we have to change this function a little.
>
> ---
>  mm/hugetlb.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 63 insertions(+)
>
> diff --git a/mm/hugetlb.c b/mm/hugetlb.c
> index 6995087..c33bddc 100644
> --- a/mm/hugetlb.c
> +++ b/mm/hugetlb.c
> @@ -1502,6 +1502,69 @@ int dissolve_free_huge_pages(unsigned long start_pfn, unsigned long end_pfn)
>
>  /*
>   * There are 3 ways this can get called:
> + *
> + * 1. When the NUMA is not enabled, use alloc_gigantic_page() to get
> + *    the gigantic page.
> + *
> + * 2. The NUMA is enabled, but the vma is NULL.
> + *    Create a @nodes_allowed, and use alloc_fresh_gigantic_page() to get
> + *    the gigantic page.
> + *
> + * 3. The NUMA is enabled, and the vma is valid.
> + *    Use the @vma's memory policy.
> + *    Get @nodes_allowed by huge_nodemask(), and use alloc_fresh_gigantic_page()
> + *    to get the gigantic page.
> + */
> +static struct page *__hugetlb_alloc_gigantic_page(struct hstate *h,
> +		struct vm_area_struct *vma, unsigned long addr, int nid)
> +{
> +	NODEMASK_ALLOC(nodemask_t, nodes_allowed, GFP_KERNEL | __GFP_NORETRY);

What if the allocation fails and nodes_allowed is NULL?
It might work fine now, but it's rather fragile, so I'd rather see an 
explicit check.

BTW same thing applies to __nr_hugepages_store_common().

> +	struct page *page = NULL;
> +
> +	/* Not NUMA */
> +	if (!IS_ENABLED(CONFIG_NUMA)) {
> +		if (nid == NUMA_NO_NODE)
> +			nid = numa_mem_id();
> +
> +		page = alloc_gigantic_page(nid, huge_page_order(h));
> +		if (page)
> +			prep_compound_gigantic_page(page, huge_page_order(h));
> +
> +		NODEMASK_FREE(nodes_allowed);
> +		return page;
> +	}
> +
> +	/* NUMA && !vma */
> +	if (!vma) {
> +		if (nid == NUMA_NO_NODE) {
> +			if (!init_nodemask_of_mempolicy(nodes_allowed)) {
> +				NODEMASK_FREE(nodes_allowed);
> +				nodes_allowed = &node_states[N_MEMORY];
> +			}
> +		} else if (nodes_allowed) {
> +			init_nodemask_of_node(nodes_allowed, nid);
> +		} else {
> +			nodes_allowed = &node_states[N_MEMORY];
> +		}
> +
> +		page = alloc_fresh_gigantic_page(h, nodes_allowed, true);
> +
> +		if (nodes_allowed != &node_states[N_MEMORY])
> +			NODEMASK_FREE(nodes_allowed);
> +
> +		return page;
> +	}
> +
> +	/* NUMA && vma */
> +	if (huge_nodemask(vma, addr, nodes_allowed))
> +		page = alloc_fresh_gigantic_page(h, nodes_allowed, true);
> +
> +	NODEMASK_FREE(nodes_allowed);
> +	return page;
> +}
> +
> +/*
> + * There are 3 ways this can get called:
>   * 1. With vma+addr: we use the VMA's memory policy
>   * 2. With !vma, but nid=NUMA_NO_NODE:  We try to allocate a huge
>   *    page from any node, and let the buddy allocator itself figure
>

^ permalink raw reply

* [GIT PULL] ZTE arm64 device tree updates for 4.10
From: Shawn Guo @ 2016-11-28 14:19 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Arnd, Olof,

If it's not too late, please pull this for 4.10.  It contains a single
patch which adds clock controller device nodes for zx296718.  Thanks.

Shawn


The following changes since commit 1001354ca34179f3db924eb66672442a173147dc:

  Linux 4.9-rc1 (2016-10-15 12:17:50 -0700)

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/shawnguo/linux.git tags/zte-dt64-4.10

for you to fetch changes up to 392ce382743b847eded4b40990de4e78a5eb494d:

  arm64: dts: zx: Add clock controller nodes (2016-10-24 16:54:20 +0800)

----------------------------------------------------------------
ZTE arm64 device tree update for 4.10:

Add clock controller device nodes, including one top clock controller,
two low speed clock controllers and one audio clock controller.

----------------------------------------------------------------
Jun Nie (1):
      arm64: dts: zx: Add clock controller nodes

 arch/arm64/boot/dts/zte/zx296718.dtsi | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

^ permalink raw reply

* [PATCH v2 0/6] mm: fix the "counter.sh" failure for libhugetlbfs
From: Vlastimil Babka @ 2016-11-28 14:20 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1479107259-2011-1-git-send-email-shijie.huang@arm.com>

On 11/14/2016 08:07 AM, Huang Shijie wrote:
> (1) Background
>    For the arm64, the hugetlb page size can be 32M (PMD + Contiguous bit).
>    In the 4K page environment, the max page order is 10 (max_order - 1),
>    so 32M page is the gigantic page.
>
>    The arm64 MMU supports a Contiguous bit which is a hint that the TTE
>    is one of a set of contiguous entries which can be cached in a single
>    TLB entry.  Please refer to the arm64v8 mannul :
>        DDI0487A_f_armv8_arm.pdf (in page D4-1811)
>
> (2) The bug
>    After I tested the libhugetlbfs, I found the test case "counter.sh"
>    will fail with the gigantic page (32M page in arm64 board).
>
>    This patch set adds support for gigantic surplus hugetlb pages,
>    allowing the counter.sh unit test to pass.
>
> v1 -- > v2:
>    1.) fix the compiler error in X86.
>    2.) add new patches for NUMA.
>        The patch #2 ~ #5 are new patches.
>
> Huang Shijie (6):
>   mm: hugetlb: rename some allocation functions
>   mm: hugetlb: add a new parameter for some functions
>   mm: hugetlb: change the return type for alloc_fresh_gigantic_page
>   mm: mempolicy: intruduce a helper huge_nodemask()
>   mm: hugetlb: add a new function to allocate a new gigantic page
>   mm: hugetlb: support gigantic surplus pages
>
>  include/linux/mempolicy.h |   8 +++
>  mm/hugetlb.c              | 128 ++++++++++++++++++++++++++++++++++++----------
>  mm/mempolicy.c            |  20 ++++++++
>  3 files changed, 130 insertions(+), 26 deletions(-)

Can't say I'm entirely happy with the continued direction of maze of 
functions for huge page allocation :( Feels like path of least 
resistance to basically copy/paste the missing parts here. Is there no 
way to consolidate the code more?

^ permalink raw reply

* [PATCH v7 1/8] drm: sun8i: Add a basic DRM driver for Allwinner DE2
From: Jean-Francois Moine @ 2016-11-28 14:23 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <cover.1480414715.git.moinejf@free.fr>

Allwinner's recent SoCs, as A64, A83T and H3, contain a new display
engine, DE2.
This patch adds a DRM video driver for this device.

Signed-off-by: Jean-Francois Moine <moinejf@free.fr>
---
 drivers/gpu/drm/Kconfig           |   2 +
 drivers/gpu/drm/Makefile          |   1 +
 drivers/gpu/drm/sun8i/Kconfig     |  19 +
 drivers/gpu/drm/sun8i/Makefile    |   7 +
 drivers/gpu/drm/sun8i/de2_crtc.c  | 449 +++++++++++++++++++++++
 drivers/gpu/drm/sun8i/de2_crtc.h  |  50 +++
 drivers/gpu/drm/sun8i/de2_drv.c   | 317 ++++++++++++++++
 drivers/gpu/drm/sun8i/de2_drv.h   |  48 +++
 drivers/gpu/drm/sun8i/de2_plane.c | 734 ++++++++++++++++++++++++++++++++++++++
 9 files changed, 1627 insertions(+)
 create mode 100644 drivers/gpu/drm/sun8i/Kconfig
 create mode 100644 drivers/gpu/drm/sun8i/Makefile
 create mode 100644 drivers/gpu/drm/sun8i/de2_crtc.c
 create mode 100644 drivers/gpu/drm/sun8i/de2_crtc.h
 create mode 100644 drivers/gpu/drm/sun8i/de2_drv.c
 create mode 100644 drivers/gpu/drm/sun8i/de2_drv.h
 create mode 100644 drivers/gpu/drm/sun8i/de2_plane.c

diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index 95fc041..bb1bfbc 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -202,6 +202,8 @@ source "drivers/gpu/drm/shmobile/Kconfig"
 
 source "drivers/gpu/drm/sun4i/Kconfig"
 
+source "drivers/gpu/drm/sun8i/Kconfig"
+
 source "drivers/gpu/drm/omapdrm/Kconfig"
 
 source "drivers/gpu/drm/tilcdc/Kconfig"
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index 883f3e7..3e1eaa0 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -72,6 +72,7 @@ obj-$(CONFIG_DRM_RCAR_DU) += rcar-du/
 obj-$(CONFIG_DRM_SHMOBILE) +=shmobile/
 obj-y			+= omapdrm/
 obj-$(CONFIG_DRM_SUN4I) += sun4i/
+obj-$(CONFIG_DRM_SUN8I) += sun8i/
 obj-y			+= tilcdc/
 obj-$(CONFIG_DRM_QXL) += qxl/
 obj-$(CONFIG_DRM_BOCHS) += bochs/
diff --git a/drivers/gpu/drm/sun8i/Kconfig b/drivers/gpu/drm/sun8i/Kconfig
new file mode 100644
index 0000000..6940895
--- /dev/null
+++ b/drivers/gpu/drm/sun8i/Kconfig
@@ -0,0 +1,19 @@
+#
+# Allwinner DE2 Video configuration
+#
+
+config DRM_SUN8I
+	bool
+
+config DRM_SUN8I_DE2
+	tristate "Support for Allwinner Video with DE2 interface"
+	depends on DRM && OF
+	depends on ARCH_SUNXI || COMPILE_TEST
+	select DRM_GEM_CMA_HELPER
+	select DRM_KMS_CMA_HELPER
+	select DRM_KMS_HELPER
+	select DRM_SUN8I
+	help
+	  Choose this option if your Allwinner chipset has the DE2 interface
+	  as the A64, A83T and H3. If M is selected the module will be called
+	  sun8i-de2-drm.
diff --git a/drivers/gpu/drm/sun8i/Makefile b/drivers/gpu/drm/sun8i/Makefile
new file mode 100644
index 0000000..f107919
--- /dev/null
+++ b/drivers/gpu/drm/sun8i/Makefile
@@ -0,0 +1,7 @@
+#
+# Makefile for Allwinner's sun8i DRM device driver
+#
+
+sun8i-de2-drm-objs := de2_drv.o de2_crtc.o de2_plane.o
+
+obj-$(CONFIG_DRM_SUN8I_DE2) += sun8i-de2-drm.o
diff --git a/drivers/gpu/drm/sun8i/de2_crtc.c b/drivers/gpu/drm/sun8i/de2_crtc.c
new file mode 100644
index 0000000..4e94ccc
--- /dev/null
+++ b/drivers/gpu/drm/sun8i/de2_crtc.c
@@ -0,0 +1,449 @@
+/*
+ * Allwinner DRM driver - DE2 CRTC
+ *
+ * Copyright (C) 2016 Jean-Francois Moine <moinejf@free.fr>
+ *
+ * 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/component.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_atomic_helper.h>
+#include <linux/io.h>
+#include <linux/of_irq.h>
+#include <linux/of_graph.h>
+
+#include "de2_drv.h"
+#include "de2_crtc.h"
+
+/* I/O map */
+
+#define TCON_GCTL_REG		0x00
+#define		TCON_GCTL_TCON_ENABLE BIT(31)
+#define TCON_GINT0_REG		0x04
+#define		TCON_GINT0_TCON1_Vb_Int_En BIT(30)
+#define		TCON_GINT0_TCON1_Vb_Int_Flag BIT(14)
+#define		TCON_GINT0_TCON1_Vb_Line_Int_Flag BIT(12)
+#define TCON0_CTL_REG		0x40
+#define		TCON0_CTL_TCON_ENABLE BIT(31)
+#define TCON1_CTL_REG		0x90
+#define		TCON1_CTL_TCON_ENABLE BIT(31)
+#define		TCON1_CTL_INTERLACE_ENABLE BIT(20)
+#define		TCON1_CTL_Start_Delay_SHIFT 4
+#define		TCON1_CTL_Start_Delay_MASK GENMASK(8, 4)
+#define TCON1_BASIC0_REG	0x94	/* XI/YI */
+#define TCON1_BASIC1_REG	0x98	/* LS_XO/LS_YO */
+#define TCON1_BASIC2_REG	0x9c	/* XO/YO */
+#define TCON1_BASIC3_REG	0xa0	/* HT/HBP */
+#define TCON1_BASIC4_REG	0xa4	/* VT/VBP */
+#define TCON1_BASIC5_REG	0xa8	/* HSPW/VSPW */
+#define TCON1_PS_SYNC_REG	0xb0
+#define TCON1_IO_POL_REG	0xf0
+#define		TCON1_IO_POL_IO0_inv BIT(24)
+#define		TCON1_IO_POL_IO1_inv BIT(25)
+#define		TCON1_IO_POL_IO2_inv BIT(26)
+#define TCON1_IO_TRI_REG	0xf4
+#define TCON_CEU_CTL_REG	0x100
+#define		TCON_CEU_CTL_ceu_en BIT(31)
+#define	TCON1_FILL_CTL_REG	0x300
+#define TCON1_FILL_START0_REG	0x304
+#define TCON1_FILL_END0_REG	0x308
+#define TCON1_FILL_DATA0_REG	0x30c
+
+#define XY(x, y) (((x) << 16) | (y))
+
+#define andl_relaxed(addr, val) \
+	writel_relaxed(readl_relaxed(addr) & val, addr)
+#define orl_relaxed(addr, val) \
+	writel_relaxed(readl_relaxed(addr) | val, addr)
+
+/* vertical blank functions */
+
+static void de2_atomic_flush(struct drm_crtc *crtc,
+			struct drm_crtc_state *old_state)
+{
+	struct drm_pending_vblank_event *event = crtc->state->event;
+
+	if (event) {
+		crtc->state->event = NULL;
+		spin_lock_irq(&crtc->dev->event_lock);
+		if (drm_crtc_vblank_get(crtc) == 0)
+			drm_crtc_arm_vblank_event(crtc, event);
+		else
+			drm_crtc_send_vblank_event(crtc, event);
+		spin_unlock_irq(&crtc->dev->event_lock);
+	}
+}
+
+static irqreturn_t de2_lcd_irq(int irq, void *dev_id)
+{
+	struct lcd *lcd = (struct lcd *) dev_id;
+	u32 isr;
+
+	isr = readl_relaxed(lcd->mmio + TCON_GINT0_REG);
+
+	drm_crtc_handle_vblank(&lcd->crtc);
+
+	writel_relaxed(isr &
+			~(TCON_GINT0_TCON1_Vb_Int_Flag |
+			  TCON_GINT0_TCON1_Vb_Line_Int_Flag),
+			lcd->mmio + TCON_GINT0_REG);
+
+	return IRQ_HANDLED;
+}
+
+int de2_enable_vblank(struct drm_device *drm, unsigned int crtc_ix)
+{
+	struct priv *priv = drm_to_priv(drm);
+	struct lcd *lcd = priv->lcds[crtc_ix];
+
+	orl_relaxed(lcd->mmio + TCON_GINT0_REG, TCON_GINT0_TCON1_Vb_Int_En);
+
+	return 0;
+}
+
+void de2_disable_vblank(struct drm_device *drm, unsigned int crtc_ix)
+{
+	struct priv *priv = drm_to_priv(drm);
+	struct lcd *lcd = priv->lcds[crtc_ix];
+
+	andl_relaxed(lcd->mmio + TCON_GINT0_REG, ~TCON_GINT0_TCON1_Vb_Int_En);
+}
+
+void de2_vblank_reset(struct lcd *lcd)
+{
+	drm_crtc_vblank_reset(&lcd->crtc);
+}
+
+/* frame functions */
+static int de2_crtc_set_clock(struct lcd *lcd, int rate)
+{
+	struct clk *parent_clk;
+	u32 parent_rate;
+	int ret;
+
+	/* determine and set the best rate for the parent clock (pll-video) */
+	if ((270000 * 2) % rate == 0)
+		parent_rate = 270000000;
+	else if (297000 % rate == 0)
+		parent_rate = 297000000;
+	else
+		return -EINVAL;			/* unsupported clock */
+
+	parent_clk = clk_get_parent(lcd->clk);
+
+	ret = clk_set_rate(parent_clk, parent_rate);
+	if (ret) {
+		dev_err(lcd->dev, "set parent rate failed %d\n", ret);
+		return ret;
+	}
+	ret = clk_set_rate(lcd->clk, rate * 1000);
+	if (ret) {
+		dev_err(lcd->dev, "set rate failed %d\n", ret);
+		return ret;
+	}
+
+	/* enable the clock */
+	reset_control_deassert(lcd->reset);
+	clk_prepare_enable(lcd->bus);
+	clk_prepare_enable(lcd->clk);
+
+	return ret;
+}
+
+static void de2_tcon_init(struct lcd *lcd)
+{
+	andl_relaxed(lcd->mmio + TCON0_CTL_REG, ~TCON0_CTL_TCON_ENABLE);
+	andl_relaxed(lcd->mmio + TCON1_CTL_REG, ~TCON1_CTL_TCON_ENABLE);
+	andl_relaxed(lcd->mmio + TCON_GCTL_REG, ~TCON_GCTL_TCON_ENABLE);
+
+	/* disable/ack interrupts */
+	writel_relaxed(0, lcd->mmio + TCON_GINT0_REG);
+}
+
+static void de2_tcon_enable(struct lcd *lcd)
+{
+	struct drm_crtc *crtc = &lcd->crtc;
+	const struct drm_display_mode *mode = &crtc->mode;
+	int interlace = mode->flags & DRM_MODE_FLAG_INTERLACE ? 2 : 1;
+	int start_delay;
+	u32 data;
+
+	orl_relaxed(lcd->mmio + TCON_GCTL_REG, TCON_GCTL_TCON_ENABLE);
+
+	data = XY(mode->hdisplay - 1, mode->vdisplay / interlace - 1);
+	writel_relaxed(data, lcd->mmio + TCON1_BASIC0_REG);
+	writel_relaxed(data, lcd->mmio + TCON1_BASIC1_REG);
+	writel_relaxed(data, lcd->mmio + TCON1_BASIC2_REG);
+	writel_relaxed(XY(mode->htotal - 1,
+			 mode->htotal - mode->hsync_start - 1),
+		      lcd->mmio + TCON1_BASIC3_REG);
+	writel_relaxed(XY(mode->vtotal * (3 - interlace),
+			 mode->vtotal - mode->vsync_start - 1),
+		      lcd->mmio + TCON1_BASIC4_REG);
+	writel_relaxed(XY(mode->hsync_end - mode->hsync_start - 1,
+			 mode->vsync_end - mode->vsync_start - 1),
+		      lcd->mmio + TCON1_BASIC5_REG);
+
+	data = TCON1_IO_POL_IO2_inv;
+	if (mode->flags & DRM_MODE_FLAG_PVSYNC)
+		data |= TCON1_IO_POL_IO0_inv;
+	if (mode->flags & DRM_MODE_FLAG_PHSYNC)
+		data |= TCON1_IO_POL_IO1_inv;
+	writel_relaxed(data, lcd->mmio + TCON1_IO_POL_REG);
+
+	andl_relaxed(lcd->mmio + TCON_CEU_CTL_REG, ~TCON_CEU_CTL_ceu_en);
+
+	if (interlace == 2)
+		orl_relaxed(lcd->mmio + TCON1_CTL_REG,
+			    TCON1_CTL_INTERLACE_ENABLE);
+	else
+		andl_relaxed(lcd->mmio + TCON1_CTL_REG,
+			     ~TCON1_CTL_INTERLACE_ENABLE);
+
+	writel_relaxed(0, lcd->mmio + TCON1_FILL_CTL_REG);
+	writel_relaxed(mode->vtotal + 1, lcd->mmio + TCON1_FILL_START0_REG);
+	writel_relaxed(mode->vtotal, lcd->mmio + TCON1_FILL_END0_REG);
+	writel_relaxed(0, lcd->mmio + TCON1_FILL_DATA0_REG);
+
+	start_delay = (mode->vtotal - mode->vdisplay) / interlace - 5;
+	if (start_delay > 31)
+		start_delay = 31;
+	data = readl_relaxed(lcd->mmio + TCON1_CTL_REG);
+	data &= ~TCON1_CTL_Start_Delay_MASK;
+	data |= start_delay << TCON1_CTL_Start_Delay_SHIFT;
+	writel_relaxed(data, lcd->mmio + TCON1_CTL_REG);
+
+	orl_relaxed(lcd->mmio + TCON1_CTL_REG, TCON1_CTL_TCON_ENABLE);
+}
+
+static void de2_tcon_disable(struct lcd *lcd)
+{
+	andl_relaxed(lcd->mmio + TCON1_CTL_REG, ~TCON1_CTL_TCON_ENABLE);
+	andl_relaxed(lcd->mmio + TCON_GCTL_REG, ~TCON_GCTL_TCON_ENABLE);
+}
+
+static void de2_crtc_enable(struct drm_crtc *crtc)
+{
+	struct lcd *lcd = crtc_to_lcd(crtc);
+	struct drm_display_mode *mode = &crtc->mode;
+
+	if (de2_crtc_set_clock(lcd, mode->clock) < 0)
+		return;
+	lcd->clk_enabled = true;
+
+	/* start the TCON and the DE */
+	de2_tcon_enable(lcd);
+	de2_de_enable(lcd);
+
+	/* turn on blanking interrupt */
+	drm_crtc_vblank_on(crtc);
+}
+
+static void de2_crtc_disable(struct drm_crtc *crtc,
+				struct drm_crtc_state *old_crtc_state)
+{
+	struct lcd *lcd = crtc_to_lcd(crtc);
+
+	if (!lcd->clk_enabled)
+		return;			/* already disabled */
+	lcd->clk_enabled = false;
+
+	de2_de_disable(lcd);
+
+	drm_crtc_vblank_off(crtc);
+
+	de2_tcon_disable(lcd);
+
+	clk_disable_unprepare(lcd->clk);
+	clk_disable_unprepare(lcd->bus);
+	reset_control_assert(lcd->reset);
+}
+
+static const struct drm_crtc_funcs de2_crtc_funcs = {
+	.destroy	= drm_crtc_cleanup,
+	.set_config	= drm_atomic_helper_set_config,
+	.page_flip	= drm_atomic_helper_page_flip,
+	.reset		= drm_atomic_helper_crtc_reset,
+	.atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
+	.atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
+};
+
+static const struct drm_crtc_helper_funcs de2_crtc_helper_funcs = {
+	.atomic_flush	= de2_atomic_flush,
+	.enable		= de2_crtc_enable,
+	.atomic_disable	= de2_crtc_disable,
+};
+
+/* device init */
+static int de2_lcd_bind(struct device *dev, struct device *master,
+			void *data)
+{
+	struct drm_device *drm = data;
+	struct priv *priv = drm_to_priv(drm);
+	struct lcd *lcd = dev_get_drvdata(dev);
+	struct drm_crtc *crtc = &lcd->crtc;
+	int ret, i, crtc_ix;
+
+	lcd->priv = priv;
+
+	/* set the CRTC reference */
+	crtc_ix = drm_crtc_index(crtc);
+	if (crtc_ix >= ARRAY_SIZE(priv->lcds)) {
+		dev_err(drm->dev, "Bad crtc index");
+		return -ENOENT;
+	}
+	priv->lcds[crtc_ix] = lcd;
+
+	/* and the mixer index (DT port index in the DE) */
+	for (i = 0; ; i++) {
+		struct device_node *port;
+
+		port = of_parse_phandle(drm->dev->of_node, "ports", i);
+		if (!port)
+			break;
+		if (port == lcd->crtc.port) {
+			lcd->mixer = i;
+			break;
+		}
+	}
+
+	ret = de2_plane_init(drm, lcd);
+	if (ret < 0)
+		return ret;
+
+	drm_crtc_helper_add(crtc, &de2_crtc_helper_funcs);
+
+	return drm_crtc_init_with_planes(drm, crtc,
+					 &lcd->planes[DE2_PRIMARY_PLANE],
+					 &lcd->planes[DE2_CURSOR_PLANE],
+					 &de2_crtc_funcs, NULL);
+}
+
+static void de2_lcd_unbind(struct device *dev, struct device *master,
+			   void *data)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct lcd *lcd = platform_get_drvdata(pdev);
+
+	if (lcd->priv)
+		lcd->priv->lcds[drm_crtc_index(&lcd->crtc)] = NULL;
+}
+
+static const struct component_ops de2_lcd_ops = {
+	.bind = de2_lcd_bind,
+	.unbind = de2_lcd_unbind,
+};
+
+static int de2_lcd_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *np = dev->of_node, *tmp, *parent, *port;
+	struct lcd *lcd;
+	struct resource *res;
+	int id, irq, ret;
+
+	lcd = devm_kzalloc(dev, sizeof(*lcd), GFP_KERNEL);
+	if (!lcd)
+		return -ENOMEM;
+
+	dev_set_drvdata(dev, lcd);
+	lcd->dev = dev;
+	lcd->mixer = id;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(dev, "failed to get memory resource\n");
+		return -EINVAL;
+	}
+
+	lcd->mmio = devm_ioremap_resource(dev, res);
+	if (IS_ERR(lcd->mmio)) {
+		dev_err(dev, "failed to map registers\n");
+		return PTR_ERR(lcd->mmio);
+	}
+
+	/* possible CRTC */
+	parent = np;
+	tmp = of_get_child_by_name(np, "ports");
+	if (tmp)
+		parent = tmp;
+	port = of_get_child_by_name(parent, "port");
+	of_node_put(tmp);
+	if (!port) {
+		dev_err(dev, "no port node\n");
+		return -ENXIO;
+	}
+	lcd->crtc.port = port;
+
+	lcd->bus = devm_clk_get(dev, "bus");
+	if (IS_ERR(lcd->bus)) {
+		dev_err(dev, "get bus clock err %d\n", (int) PTR_ERR(lcd->bus));
+		ret = PTR_ERR(lcd->bus);
+		goto err;
+	}
+
+	lcd->clk = devm_clk_get(dev, "clock");
+	if (IS_ERR(lcd->clk)) {
+		ret = PTR_ERR(lcd->clk);
+		dev_err(dev, "get video clock err %d\n", ret);
+		goto err;
+	}
+
+	lcd->reset = devm_reset_control_get(dev, NULL);
+	if (IS_ERR(lcd->reset)) {
+		ret = PTR_ERR(lcd->reset);
+		dev_err(dev, "get reset err %d\n", ret);
+		goto err;
+	}
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq <= 0) {
+		dev_err(dev, "unable to get irq\n");
+		ret = -EINVAL;
+		goto err;
+	}
+
+	de2_tcon_init(lcd);		/* stop TCON and avoid interrupts */
+
+	ret = devm_request_irq(dev, irq, de2_lcd_irq, 0,
+				dev_name(dev), lcd);
+	if (ret < 0) {
+		dev_err(dev, "unable to request irq %d\n", irq);
+		goto err;
+	}
+
+	return component_add(dev, &de2_lcd_ops);
+
+err:
+	of_node_put(lcd->crtc.port);
+	return ret;
+}
+
+static int de2_lcd_remove(struct platform_device *pdev)
+{
+	struct lcd *lcd = platform_get_drvdata(pdev);
+
+	component_del(&pdev->dev, &de2_lcd_ops);
+
+	of_node_put(lcd->crtc.port);
+
+	return 0;
+}
+
+static const struct of_device_id de2_lcd_ids[] = {
+	{ .compatible = "allwinner,sun8i-a83t-tcon", },
+	{ }
+};
+
+struct platform_driver de2_lcd_platform_driver = {
+	.probe = de2_lcd_probe,
+	.remove = de2_lcd_remove,
+	.driver = {
+		.name = "sun8i-de2-tcon",
+		.of_match_table = of_match_ptr(de2_lcd_ids),
+	},
+};
diff --git a/drivers/gpu/drm/sun8i/de2_crtc.h b/drivers/gpu/drm/sun8i/de2_crtc.h
new file mode 100644
index 0000000..c0d34a7
--- /dev/null
+++ b/drivers/gpu/drm/sun8i/de2_crtc.h
@@ -0,0 +1,50 @@
+#ifndef __DE2_CRTC_H__
+#define __DE2_CRTC_H__
+/*
+ * Copyright (C) 2016 Jean-Fran??ois Moine
+ *
+ * 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 <drm/drm_plane_helper.h>
+
+struct clk;
+struct reset_control;
+struct priv;
+
+/* planes */
+#define DE2_PRIMARY_PLANE 0
+#define DE2_CURSOR_PLANE 1
+#define DE2_N_PLANES 5	/* number of planes - see plane_tb[] in de2_plane.c */
+
+struct lcd {
+	void __iomem *mmio;
+
+	struct device *dev;
+	struct drm_crtc crtc;
+
+	struct priv *priv;	/* DRM/DE private data */
+
+	u8 mixer;		/* LCD (mixer) number */
+	u8 delayed;		/* bitmap of planes with delayed update */
+
+	u8 clk_enabled;		/* used for error in crtc_enable */
+
+	struct clk *clk;
+	struct clk *bus;
+	struct reset_control *reset;
+
+	struct drm_plane planes[DE2_N_PLANES];
+};
+
+#define crtc_to_lcd(x) container_of(x, struct lcd, crtc)
+
+/* in de2_plane.c */
+void de2_de_enable(struct lcd *lcd);
+void de2_de_disable(struct lcd *lcd);
+int de2_plane_init(struct drm_device *drm, struct lcd *lcd);
+
+#endif /* __DE2_CRTC_H__ */
diff --git a/drivers/gpu/drm/sun8i/de2_drv.c b/drivers/gpu/drm/sun8i/de2_drv.c
new file mode 100644
index 0000000..f96babe
--- /dev/null
+++ b/drivers/gpu/drm/sun8i/de2_drv.c
@@ -0,0 +1,317 @@
+/*
+ * Allwinner DRM driver - DE2 DRM driver
+ *
+ * Copyright (C) 2016 Jean-Francois Moine <moinejf@free.fr>
+ *
+ * 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/module.h>
+#include <linux/of_device.h>
+#include <drm/drm_of.h>
+#include <linux/component.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_gem_cma_helper.h>
+
+#include "de2_drv.h"
+
+#define DRIVER_NAME	"sun8i-de2"
+#define DRIVER_DESC	"Allwinner DRM DE2"
+#define DRIVER_DATE	"20161101"
+#define DRIVER_MAJOR	1
+#define DRIVER_MINOR	0
+
+static const struct of_device_id de2_drm_of_match[] = {
+	{ .compatible = "allwinner,sun8i-a83t-display-engine",
+				.data = (void *) SOC_A83T },
+	{ .compatible = "allwinner,sun8i-h3-display-engine",
+				.data = (void *) SOC_H3 },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, de2_drm_of_match);
+
+static void de2_fb_output_poll_changed(struct drm_device *drm)
+{
+	struct priv *priv = drm_to_priv(drm);
+
+	if (priv->fbdev)
+		drm_fbdev_cma_hotplug_event(priv->fbdev);
+}
+
+static const struct drm_mode_config_funcs de2_mode_config_funcs = {
+	.fb_create = drm_fb_cma_create,
+	.output_poll_changed = de2_fb_output_poll_changed,
+	.atomic_check = drm_atomic_helper_check,
+	.atomic_commit = drm_atomic_helper_commit,
+};
+
+/* -- DRM operations -- */
+
+static void de2_lastclose(struct drm_device *drm)
+{
+	struct priv *priv = drm_to_priv(drm);
+
+	if (priv->fbdev)
+		drm_fbdev_cma_restore_mode(priv->fbdev);
+}
+
+static const struct file_operations de2_fops = {
+	.owner		= THIS_MODULE,
+	.open		= drm_open,
+	.release	= drm_release,
+	.unlocked_ioctl	= drm_ioctl,
+	.poll		= drm_poll,
+	.read		= drm_read,
+	.llseek		= no_llseek,
+	.mmap		= drm_gem_cma_mmap,
+};
+
+static struct drm_driver de2_drm_driver = {
+	.driver_features	= DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME |
+					DRIVER_ATOMIC,
+	.lastclose		= de2_lastclose,
+	.get_vblank_counter	= drm_vblank_no_hw_counter,
+	.enable_vblank		= de2_enable_vblank,
+	.disable_vblank		= de2_disable_vblank,
+	.gem_free_object	= drm_gem_cma_free_object,
+	.gem_vm_ops		= &drm_gem_cma_vm_ops,
+	.prime_handle_to_fd	= drm_gem_prime_handle_to_fd,
+	.prime_fd_to_handle	= drm_gem_prime_fd_to_handle,
+	.gem_prime_import	= drm_gem_prime_import,
+	.gem_prime_export	= drm_gem_prime_export,
+	.gem_prime_get_sg_table	= drm_gem_cma_prime_get_sg_table,
+	.gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table,
+	.gem_prime_vmap		= drm_gem_cma_prime_vmap,
+	.gem_prime_vunmap	= drm_gem_cma_prime_vunmap,
+	.gem_prime_mmap		= drm_gem_cma_prime_mmap,
+	.dumb_create		= drm_gem_cma_dumb_create,
+	.dumb_map_offset	= drm_gem_cma_dumb_map_offset,
+	.dumb_destroy		= drm_gem_dumb_destroy,
+	.fops			= &de2_fops,
+	.name			= DRIVER_NAME,
+	.desc			= DRIVER_DESC,
+	.date			= DRIVER_DATE,
+	.major			= DRIVER_MAJOR,
+	.minor			= DRIVER_MINOR,
+};
+
+/*
+ * Platform driver
+ */
+
+static int de2_drm_bind(struct device *dev)
+{
+	struct drm_device *drm;
+	struct priv *priv;
+	struct resource *res;
+	struct lcd *lcd;
+	int i, ret;
+
+	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	drm = &priv->drm;
+	dev_set_drvdata(dev, drm);
+
+	/* get the resources */
+	priv->soc_type = (int) of_match_device(de2_drm_of_match, dev)->data;
+
+	res = platform_get_resource(to_platform_device(dev),
+				IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(dev, "failed to get memory resource\n");
+		ret = -EINVAL;
+		goto out1;
+	}
+
+	priv->mmio = devm_ioremap_resource(dev, res);
+	if (IS_ERR(priv->mmio)) {
+		ret = PTR_ERR(priv->mmio);
+		dev_err(dev, "failed to map registers %d\n", ret);
+		goto out1;
+	}
+
+	priv->gate = devm_clk_get(dev, "bus");
+	if (IS_ERR(priv->gate)) {
+		ret = PTR_ERR(priv->gate);
+		dev_err(dev, "bus gate err %d\n", ret);
+		goto out1;
+	}
+
+	priv->clk = devm_clk_get(dev, "clock");
+	if (IS_ERR(priv->clk)) {
+		ret = PTR_ERR(priv->clk);
+		dev_err(dev, "clock err %d\n", ret);
+		goto out1;
+	}
+
+	priv->reset = devm_reset_control_get(dev, NULL);
+	if (IS_ERR(priv->reset)) {
+		ret = PTR_ERR(priv->reset);
+		dev_err(dev, "reset err %d\n", ret);
+		goto out1;
+	}
+
+	mutex_init(&priv->mutex);	/* protect DE I/O accesses */
+
+	ret = drm_dev_init(drm, &de2_drm_driver, dev);
+	if (ret != 0) {
+		dev_err(dev, "dev_init failed %d\n", ret);
+		goto out1;
+	}
+
+	drm_mode_config_init(drm);
+	drm->mode_config.min_width = 32;	/* needed for cursor */
+	drm->mode_config.min_height = 32;
+	drm->mode_config.max_width = 1920;
+	drm->mode_config.max_height = 1080;
+	drm->mode_config.funcs = &de2_mode_config_funcs;
+
+	drm->irq_enabled = true;
+
+	/* start the subdevices */
+	ret = component_bind_all(dev, drm);
+	if (ret < 0)
+		goto out2;
+
+	/* initialize and disable vertical blanking on all CRTCs */
+	ret = drm_vblank_init(drm, drm->mode_config.num_crtc);
+	if (ret < 0)
+		dev_warn(dev, "vblank_init failed %d\n", ret);
+
+	for (i = 0; i < ARRAY_SIZE(priv->lcds); i++) {
+		lcd = priv->lcds[i];
+		if (lcd)
+			de2_vblank_reset(lcd);
+	}
+
+	drm_mode_config_reset(drm);
+
+	priv->fbdev = drm_fbdev_cma_init(drm,
+					 32,	/* bpp */
+					 drm->mode_config.num_crtc,
+					 drm->mode_config.num_connector);
+	if (IS_ERR(priv->fbdev)) {
+		ret = PTR_ERR(priv->fbdev);
+		priv->fbdev = NULL;
+		goto out3;
+	}
+
+	drm_kms_helper_poll_init(drm);
+
+	ret = drm_dev_register(drm, 0);
+	if (ret < 0)
+		goto out4;
+
+	return 0;
+
+out4:
+	drm_fbdev_cma_fini(priv->fbdev);
+out3:
+	component_unbind_all(dev, drm);
+out2:
+	drm_dev_unref(drm);
+out1:
+	kfree(priv);
+	return ret;
+}
+
+static void de2_drm_unbind(struct device *dev)
+{
+	struct drm_device *drm = dev_get_drvdata(dev);
+	struct priv *priv = drm_to_priv(drm);
+
+	drm_dev_unregister(drm);
+
+	drm_fbdev_cma_fini(priv->fbdev);
+	drm_kms_helper_poll_fini(drm);
+	drm_vblank_cleanup(drm);
+	drm_mode_config_cleanup(drm);
+
+	component_unbind_all(dev, drm);
+
+	kfree(priv);
+}
+
+static const struct component_master_ops de2_drm_comp_ops = {
+	.bind = de2_drm_bind,
+	.unbind = de2_drm_unbind,
+};
+
+/*
+ * drm_of_component_probe() does:
+ * - bind of the ports (lcd-controller.port)
+ * - bind of the remote nodes (hdmi, tve..)
+ */
+static int compare_of(struct device *dev, void *data)
+{
+	struct device_node *np = data;
+
+	if (of_node_cmp(np->name, "port") == 0) {
+		np = of_get_parent(np);
+		of_node_put(np);
+	}
+	return dev->of_node == np;
+}
+
+static int de2_drm_probe(struct platform_device *pdev)
+{
+	int ret;
+
+	ret = drm_of_component_probe(&pdev->dev,
+				     compare_of,
+				     &de2_drm_comp_ops);
+	if (ret == -EINVAL)
+		ret = -ENXIO;
+	return ret;
+}
+
+static int de2_drm_remove(struct platform_device *pdev)
+{
+	component_master_del(&pdev->dev, &de2_drm_comp_ops);
+
+	return 0;
+}
+
+static struct platform_driver de2_drm_platform_driver = {
+	.probe      = de2_drm_probe,
+	.remove     = de2_drm_remove,
+	.driver     = {
+		.name = DRIVER_NAME,
+		.of_match_table = de2_drm_of_match,
+	},
+};
+
+static int __init de2_drm_init(void)
+{
+	int ret;
+
+	ret = platform_driver_register(&de2_lcd_platform_driver);
+	if (ret < 0)
+		return ret;
+
+	ret = platform_driver_register(&de2_drm_platform_driver);
+	if (ret < 0)
+		platform_driver_unregister(&de2_lcd_platform_driver);
+
+	return ret;
+}
+
+static void __exit de2_drm_fini(void)
+{
+	platform_driver_unregister(&de2_lcd_platform_driver);
+	platform_driver_unregister(&de2_drm_platform_driver);
+}
+
+module_init(de2_drm_init);
+module_exit(de2_drm_fini);
+
+MODULE_AUTHOR("Jean-Francois Moine <moinejf@free.fr>");
+MODULE_DESCRIPTION("Allwinner DE2 DRM Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpu/drm/sun8i/de2_drv.h b/drivers/gpu/drm/sun8i/de2_drv.h
new file mode 100644
index 0000000..c42c30a
--- /dev/null
+++ b/drivers/gpu/drm/sun8i/de2_drv.h
@@ -0,0 +1,48 @@
+#ifndef __DE2_DRM_H__
+#define __DE2_DRM_H__
+/*
+ * Copyright (C) 2016 Jean-Fran??ois Moine
+ *
+ * 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 <drm/drmP.h>
+#include <linux/clk.h>
+#include <linux/reset.h>
+
+struct drm_fbdev_cma;
+struct lcd;
+
+#define N_LCDS 2
+
+struct priv {
+	struct drm_device drm;
+	void __iomem *mmio;
+	struct clk *clk;
+	struct clk *gate;
+	struct reset_control *reset;
+
+	struct mutex mutex;	/* protect DE I/O access */
+	u8 soc_type;
+#define SOC_A83T 0
+#define SOC_H3 1
+	u8 started;		/* bitmap of started mixers */
+	u8 clean;		/* bitmap of clean mixers */
+
+	struct drm_fbdev_cma *fbdev;
+
+	struct lcd *lcds[N_LCDS]; /* CRTCs */
+};
+
+#define drm_to_priv(x) container_of(x, struct priv, drm)
+
+/* in de2_crtc.c */
+int de2_enable_vblank(struct drm_device *drm, unsigned int crtc);
+void de2_disable_vblank(struct drm_device *drm, unsigned int crtc);
+void de2_vblank_reset(struct lcd *lcd);
+extern struct platform_driver de2_lcd_platform_driver;
+
+#endif /* __DE2_DRM_H__ */
diff --git a/drivers/gpu/drm/sun8i/de2_plane.c b/drivers/gpu/drm/sun8i/de2_plane.c
new file mode 100644
index 0000000..2fd72dc
--- /dev/null
+++ b/drivers/gpu/drm/sun8i/de2_plane.c
@@ -0,0 +1,734 @@
+/*
+ * Allwinner DRM driver - Display Engine 2
+ *
+ * Copyright (C) 2016 Jean-Francois Moine <moinejf@free.fr>
+ * Adapted from the sun8iw6 and sun8iw7 disp2 drivers
+ *	Copyright (c) 2016 Allwinnertech Co., Ltd.
+ *
+ * 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/io.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_plane_helper.h>
+
+#include "de2_drv.h"
+#include "de2_crtc.h"
+
+/* DE2 I/O map */
+
+#define DE2_MOD_REG 0x0000		/* 1 bit per LCD */
+#define DE2_GATE_REG 0x0004
+#define DE2_RESET_REG 0x0008
+#define DE2_DIV_REG 0x000c		/* 4 bits per LCD */
+#define DE2_SEL_REG 0x0010
+
+#define DE2_MIXER0_BASE 0x00100000	/* LCD 0 */
+#define DE2_MIXER1_BASE 0x00200000	/* LCD 1 */
+
+/* mixer registers (addr / mixer base) */
+#define MIXER_GLB_REGS	0x00000		/* global control */
+#define MIXER_BLD_REGS	0x01000		/* alpha blending */
+#define MIXER_CHAN_REGS 0x02000		/* VI/UI overlay channels */
+#define		MIXER_CHAN_SZ 0x1000	/* size of a channel */
+#define MIXER_VSU_REGS	0x20000		/* VSU */
+#define MIXER_GSU1_REGS 0x30000		/* GSUs */
+#define MIXER_GSU2_REGS 0x40000
+#define MIXER_GSU3_REGS 0x50000
+#define MIXER_FCE_REGS	0xa0000		/* FCE */
+#define MIXER_BWS_REGS	0xa2000		/* BWS */
+#define MIXER_LTI_REGS	0xa4000		/* LTI */
+#define MIXER_PEAK_REGS 0xa6000		/* PEAK */
+#define MIXER_ASE_REGS	0xa8000		/* ASE */
+#define MIXER_FCC_REGS	0xaa000		/* FCC */
+#define MIXER_DCSC_REGS 0xb0000		/* DCSC/SMBL */
+
+/* global control */
+#define MIXER_GLB_CTL_REG	0x00
+#define		MIXER_GLB_CTL_rt_en BIT(0)
+#define		MIXER_GLB_CTL_finish_irq_en BIT(4)
+#define		MIXER_GLB_CTL_rtwb_port BIT(12)
+#define MIXER_GLB_STATUS_REG	0x04
+#define MIXER_GLB_DBUFF_REG	0x08
+#define MIXER_GLB_SIZE_REG	0x0c
+
+/* alpha blending */
+#define MIXER_BLD_FCOLOR_CTL_REG	0x00
+#define		MIXER_BLD_FCOLOR_CTL_PEN(pipe)	(0x0100 << (pipe))
+#define	MIXER_BLD_ATTR_N 4		/* number of attribute blocks */
+#define	MIXER_BLD_ATTR_SIZE (4 * 4)	/* size of an attribute block */
+#define MIXER_BLD_ATTRx_FCOLOR(x)	(0x04 + MIXER_BLD_ATTR_SIZE * (x))
+#define MIXER_BLD_ATTRx_INSIZE(x)	(0x08 + MIXER_BLD_ATTR_SIZE * (x))
+#define MIXER_BLD_ATTRx_OFFSET(x)	(0x0c + MIXER_BLD_ATTR_SIZE * (x))
+#define MIXER_BLD_ROUTE_REG	0x80
+#define		MIXER_BLD_ROUTE(chan, pipe) ((chan) << ((pipe) * 4))
+#define MIXER_BLD_PREMULTIPLY_REG	0x84
+#define MIXER_BLD_BKCOLOR_REG	0x88
+#define MIXER_BLD_OUTPUT_SIZE_REG	0x8c
+#define MIXER_BLD_MODEx_REG(x)	(0x90 + 4 * (x))	/* x = 0..3 */
+#define		MIXER_BLD_MODE_SRCOVER	0x03010301
+#define MIXER_BLD_OUT_CTL_REG	0xfc
+
+/* VI channel (channel 0) */
+#define VI_CFG_N		4		/* number of layers */
+#define VI_CFG_SIZE		0x30		/* size of a layer */
+#define VI_CFGx_ATTR(l)		(0x00 + VI_CFG_SIZE * (l))
+#define		VI_CFG_ATTR_en BIT(0)
+#define		VI_CFG_ATTR_fcolor_en BIT(4)
+#define		VI_CFG_ATTR_fmt_SHIFT 8
+#define		VI_CFG_ATTR_fmt_MASK GENMASK(12, 8)
+#define		VI_CFG_ATTR_ui_sel BIT(15)
+#define		VI_CFG_ATTR_top_down BIT(23)
+#define VI_CFGx_SIZE(l)		(0x04 + VI_CFG_SIZE * (l))
+#define VI_CFGx_COORD(l)	(0x08 + VI_CFG_SIZE * (l))
+#define VI_N_PLANES 3
+#define VI_CFGx_PITCHy(l, p)	(0x0c + VI_CFG_SIZE * (l) + 4 * (p))
+#define VI_CFGx_TOP_LADDRy(l, p) (0x18 + VI_CFG_SIZE * (l) + 4 * (p))
+#define VI_CFGx_BOT_LADDRy(l, p) (0x24 + VI_CFG_SIZE * (l) + 4 * (p))
+#define VI_FCOLORx(l)		(0xc0 + 4 * (l))
+#define VI_TOP_HADDRx(p)	(0xd0 + 4 * (p))
+#define VI_BOT_HADDRx(p)	(0xdc + 4 * (p))
+#define VI_OVL_SIZEx(n)		(0xe8 + 4 * (n))
+#define VI_HORI_DSx(n)		(0xf0 + 4 * (n))
+#define VI_VERT_DSx(n)		(0xf8 + 4 * (n))
+#define VI_SIZE			0x100
+
+/* UI channel (channels 1..3) */
+#define UI_CFG_N		4		/* number of layers */
+#define UI_CFG_SIZE		(8 * 4)		/* size of a layer */
+#define UI_CFGx_ATTR(l)		(0x00 + UI_CFG_SIZE * (l))
+#define		UI_CFG_ATTR_en BIT(0)
+#define		UI_CFG_ATTR_alpmod_SHIFT 1
+#define		UI_CFG_ATTR_alpmod_MASK GENMASK(2, 1)
+#define		UI_CFG_ATTR_fcolor_en BIT(4)
+#define		UI_CFG_ATTR_fmt_SHIFT 8
+#define		UI_CFG_ATTR_fmt_MASK GENMASK(12, 8)
+#define		UI_CFG_ATTR_top_down BIT(23)
+#define		UI_CFG_ATTR_alpha_SHIFT 24
+#define		UI_CFG_ATTR_alpha_MASK GENMASK(31, 24)
+#define UI_CFGx_SIZE(l)		(0x04 + UI_CFG_SIZE * (l))
+#define UI_CFGx_COORD(l)	(0x08 + UI_CFG_SIZE * (l))
+#define UI_CFGx_PITCH(l)	(0x0c + UI_CFG_SIZE * (l))
+#define UI_CFGx_TOP_LADDR(l)	(0x10 + UI_CFG_SIZE * (l))
+#define UI_CFGx_BOT_LADDR(l)	(0x14 + UI_CFG_SIZE * (l))
+#define UI_CFGx_FCOLOR(l)	(0x18 + UI_CFG_SIZE * (l))
+#define UI_TOP_HADDR		0x80
+#define UI_BOT_HADDR		0x84
+#define UI_OVL_SIZE		0x88
+#define UI_SIZE			0x8c
+
+/* coordinates and sizes */
+#define XY(x, y) (((y) << 16) | (x))
+#define WH(w, h) ((((h) - 1) << 16) | ((w) - 1))
+
+/* UI video formats */
+#define DE2_FORMAT_ARGB_8888 0
+#define DE2_FORMAT_BGRA_8888 3
+#define DE2_FORMAT_XRGB_8888 4
+#define DE2_FORMAT_RGB_888 8
+#define DE2_FORMAT_BGR_888 9
+
+/* VI video formats */
+#define DE2_FORMAT_YUV422_I_YVYU 1	/* YVYU */
+#define DE2_FORMAT_YUV422_I_UYVY 2	/* UYVY */
+#define DE2_FORMAT_YUV422_I_YUYV 3	/* YUYV */
+#define DE2_FORMAT_YUV422_P 6		/* YYYY UU VV planar */
+#define DE2_FORMAT_YUV420_P 10		/* YYYY U V planar */
+
+/* plane formats */
+static const uint32_t ui_formats[] = {
+	DRM_FORMAT_ARGB8888,
+	DRM_FORMAT_BGRA8888,
+	DRM_FORMAT_XRGB8888,
+	DRM_FORMAT_RGB888,
+	DRM_FORMAT_BGR888,
+};
+
+static const uint32_t vi_formats[] = {
+	DRM_FORMAT_XRGB8888,
+	DRM_FORMAT_YUYV,
+	DRM_FORMAT_YVYU,
+	DRM_FORMAT_YUV422,
+	DRM_FORMAT_YUV420,
+	DRM_FORMAT_UYVY,
+	DRM_FORMAT_BGRA8888,
+	DRM_FORMAT_RGB888,
+	DRM_FORMAT_BGR888,
+};
+
+/*
+ * plane table
+ *
+ * The chosen channel/layer assignment of the planes respects
+ * the following constraints:
+ * - the cursor must be in a channel higher than the primary channel
+ * - there are 4 channels in the LCD 0 and only 2 channels in the LCD 1
+ */
+static const struct {
+	u8 chan;
+	u8 layer;
+	u8 pipe;
+	u8 type;			/* plane type */
+	const uint32_t *formats;
+	u8 n_formats;
+} plane_tb[] = {
+	[DE2_PRIMARY_PLANE] = {		/* primary plane: channel 0 (VI) */
+		0, 0, 0,
+		DRM_PLANE_TYPE_PRIMARY,
+		ui_formats, ARRAY_SIZE(ui_formats),
+	},
+	[DE2_CURSOR_PLANE] = {		/* cursor: channel 1 (UI) */
+		1, 0, 1,
+		DRM_PLANE_TYPE_CURSOR,
+		ui_formats, ARRAY_SIZE(ui_formats),
+	},
+	{
+		0, 1, 0,		/* 1st overlay: channel 0, layer 1 */
+		DRM_PLANE_TYPE_OVERLAY,
+		vi_formats, ARRAY_SIZE(vi_formats),
+	},
+	{
+		0, 2, 0,		/* 2nd overlay: channel 0, layer 2 */
+		DRM_PLANE_TYPE_OVERLAY,
+		vi_formats, ARRAY_SIZE(vi_formats),
+	},
+	{
+		0, 3, 0,		/* 3rd overlay: channel 0, layer 3 */
+		DRM_PLANE_TYPE_OVERLAY,
+		vi_formats, ARRAY_SIZE(vi_formats),
+	},
+};
+
+static inline void andl_relaxed(void __iomem *addr, u32 val)
+{
+	writel_relaxed(readl_relaxed(addr) & val, addr);
+}
+
+static inline void orl_relaxed(void __iomem *addr, u32 val)
+{
+	writel_relaxed(readl_relaxed(addr) | val, addr);
+}
+
+/* alert the DE processor about changes in a mixer configuration */
+static void de2_mixer_select(struct priv *priv,
+			int mixer,
+			void __iomem *mixer_io)
+{
+	/* select the mixer */
+	andl_relaxed(priv->mmio + DE2_SEL_REG, ~1);
+
+	/* double register switch */
+	writel_relaxed(1, mixer_io + MIXER_GLB_REGS + MIXER_GLB_DBUFF_REG);
+}
+
+/*
+ * cleanup a mixer
+ *
+ * This is needed only once after power on.
+ */
+static void de2_mixer_cleanup(struct priv *priv, int mixer,
+				u32 size)
+{
+	void __iomem *mixer_io = priv->mmio;
+	void __iomem *chan_io;
+	u32 data;
+	unsigned int i;
+
+	mixer_io += (mixer == 0) ? DE2_MIXER0_BASE : DE2_MIXER1_BASE;
+	chan_io = mixer_io + MIXER_CHAN_REGS;
+
+	andl_relaxed(priv->mmio + DE2_SEL_REG, ~1);
+	writel_relaxed(1, mixer_io + MIXER_GLB_REGS + MIXER_GLB_DBUFF_REG);
+
+	writel_relaxed(MIXER_GLB_CTL_rt_en,
+			mixer_io + MIXER_GLB_REGS + MIXER_GLB_CTL_REG);
+	writel_relaxed(0, mixer_io + MIXER_GLB_REGS + MIXER_GLB_STATUS_REG);
+
+	writel_relaxed(size, mixer_io + MIXER_GLB_REGS + MIXER_GLB_SIZE_REG);
+
+	/*
+	 * clear the VI/UI channels
+	 *	LCD0: 1 VI and 3 UIs
+	 *	LCD1: 1 VI and 1 UI
+	 */
+	memset_io(chan_io, 0, VI_SIZE);
+	memset_io(chan_io + MIXER_CHAN_SZ, 0, UI_SIZE);
+	if (mixer == 0) {
+		memset_io(chan_io + MIXER_CHAN_SZ * 2, 0, UI_SIZE);
+		memset_io(chan_io + MIXER_CHAN_SZ * 3, 0, UI_SIZE);
+	}
+
+	/* alpha blending */
+	writel_relaxed(0x00000001 |		/* fcolor for primary */
+			MIXER_BLD_FCOLOR_CTL_PEN(0),
+			mixer_io + MIXER_BLD_REGS + MIXER_BLD_FCOLOR_CTL_REG);
+	for (i = 0; i < MIXER_BLD_ATTR_N; i++) {
+		writel_relaxed(0xff000000,
+			mixer_io + MIXER_BLD_REGS + MIXER_BLD_ATTRx_FCOLOR(i));
+		writel_relaxed(size,
+			mixer_io + MIXER_BLD_REGS + MIXER_BLD_ATTRx_INSIZE(i));
+		writel_relaxed(0,
+			mixer_io + MIXER_BLD_REGS + MIXER_BLD_ATTRx_OFFSET(i));
+	}
+	writel_relaxed(0, mixer_io + MIXER_BLD_REGS + MIXER_BLD_OUT_CTL_REG);
+
+	/* prepare the pipe route for the planes */
+	data = 0;
+	for (i = 0; i < DE2_N_PLANES; i++)
+		data |= MIXER_BLD_ROUTE(plane_tb[i].chan, plane_tb[i].pipe);
+	writel_relaxed(data, mixer_io + MIXER_BLD_REGS + MIXER_BLD_ROUTE_REG);
+
+	writel_relaxed(0, mixer_io + MIXER_BLD_REGS +
+			MIXER_BLD_PREMULTIPLY_REG);
+	writel_relaxed(0xff000000, mixer_io + MIXER_BLD_REGS +
+			MIXER_BLD_BKCOLOR_REG);
+	writel_relaxed(size, mixer_io + MIXER_BLD_REGS +
+			MIXER_BLD_OUTPUT_SIZE_REG);
+	writel_relaxed(MIXER_BLD_MODE_SRCOVER,
+			mixer_io + MIXER_BLD_REGS + MIXER_BLD_MODEx_REG(0));
+	writel_relaxed(MIXER_BLD_MODE_SRCOVER,
+			mixer_io + MIXER_BLD_REGS + MIXER_BLD_MODEx_REG(1));
+
+	/* disable the enhancements */
+	writel_relaxed(0, mixer_io + MIXER_VSU_REGS);
+	writel_relaxed(0, mixer_io + MIXER_GSU1_REGS);
+	writel_relaxed(0, mixer_io + MIXER_GSU2_REGS);
+	writel_relaxed(0, mixer_io + MIXER_GSU3_REGS);
+	writel_relaxed(0, mixer_io + MIXER_FCE_REGS);
+	writel_relaxed(0, mixer_io + MIXER_BWS_REGS);
+	writel_relaxed(0, mixer_io + MIXER_LTI_REGS);
+	writel_relaxed(0, mixer_io + MIXER_PEAK_REGS);
+	writel_relaxed(0, mixer_io + MIXER_ASE_REGS);
+	writel_relaxed(0, mixer_io + MIXER_FCC_REGS);
+	writel_relaxed(0, mixer_io + MIXER_DCSC_REGS);
+}
+
+/* enable a mixer */
+static void de2_mixer_enable(struct lcd *lcd)
+{
+	struct priv *priv = lcd->priv;
+	void __iomem *mixer_io = priv->mmio;
+	struct drm_display_mode *mode = &lcd->crtc.mode;
+	u32 size = WH(mode->hdisplay, mode->vdisplay);
+	u32 data;
+	int mixer = lcd->mixer;
+	int i;
+
+	mixer_io += (mixer == 0) ? DE2_MIXER0_BASE : DE2_MIXER1_BASE;
+
+	/* if not done yet, start the DE processor */
+	if (!priv->started) {
+		reset_control_deassert(priv->reset);
+		clk_prepare_enable(priv->gate);
+		clk_prepare_enable(priv->clk);
+	}
+	priv->started |= 1 << mixer;
+
+	/* set the A83T clock divider (500 / 2) = 250MHz */
+	if (priv->soc_type == SOC_A83T)
+		writel_relaxed(0x00000011, /* div = 2 for both LCDs */
+				priv->mmio + DE2_DIV_REG);
+
+	/* deassert the mixer and enable its clock */
+	orl_relaxed(priv->mmio + DE2_RESET_REG, mixer == 0 ? 1 : 4);
+	data = 1 << mixer;			/* 1 bit / lcd */
+	orl_relaxed(priv->mmio + DE2_GATE_REG, data);
+	orl_relaxed(priv->mmio + DE2_MOD_REG, data);
+
+	/* if not done yet, cleanup and enable */
+	if (!(priv->clean & (1 << mixer))) {
+		priv->clean |= 1 << mixer;
+		de2_mixer_cleanup(priv, mixer, size);
+		return;
+	}
+
+	/* enable */
+	de2_mixer_select(priv, mixer, mixer_io);
+
+	writel_relaxed(MIXER_GLB_CTL_rt_en,
+			mixer_io + MIXER_GLB_REGS + MIXER_GLB_CTL_REG);
+	writel_relaxed(0, mixer_io + MIXER_GLB_REGS + MIXER_GLB_STATUS_REG);
+
+	/* set the size of the frame buffer */
+	writel_relaxed(size, mixer_io + MIXER_GLB_REGS + MIXER_GLB_SIZE_REG);
+	for (i = 0; i < MIXER_BLD_ATTR_N; i++)
+		writel_relaxed(size, mixer_io + MIXER_BLD_REGS +
+				MIXER_BLD_ATTRx_INSIZE(i));
+	writel_relaxed(size, mixer_io + MIXER_BLD_REGS +
+			MIXER_BLD_OUTPUT_SIZE_REG);
+
+	writel_relaxed(mode->flags & DRM_MODE_FLAG_INTERLACE ? 2 : 0,
+			mixer_io + MIXER_BLD_REGS + MIXER_BLD_OUT_CTL_REG);
+}
+
+/* enable a LCD (DE mixer) */
+void de2_de_enable(struct lcd *lcd)
+{
+	mutex_lock(&lcd->priv->mutex);
+
+	de2_mixer_enable(lcd);
+
+	mutex_unlock(&lcd->priv->mutex);
+}
+
+/* disable a LCD (DE mixer) */
+void de2_de_disable(struct lcd *lcd)
+{
+	struct priv *priv = lcd->priv;
+	void __iomem *mixer_io = priv->mmio;
+	int mixer = lcd->mixer;
+	u32 data;
+
+	mixer_io += (mixer == 0) ? DE2_MIXER0_BASE : DE2_MIXER1_BASE;
+
+	mutex_lock(&priv->mutex);
+
+	de2_mixer_select(priv, mixer, mixer_io);
+
+	writel_relaxed(0, mixer_io + MIXER_GLB_REGS + MIXER_GLB_CTL_REG);
+
+	data = ~(1 << mixer);
+	andl_relaxed(priv->mmio + DE2_MOD_REG, data);
+	andl_relaxed(priv->mmio + DE2_GATE_REG, data);
+	andl_relaxed(priv->mmio + DE2_RESET_REG, data);
+
+	mutex_unlock(&priv->mutex);
+
+	/* if all mixers are disabled, stop the DE */
+	priv->started &= ~(1 << mixer);
+	if (!priv->started) {
+		clk_disable_unprepare(priv->clk);
+		clk_disable_unprepare(priv->gate);
+		reset_control_assert(priv->reset);
+	}
+}
+
+static void de2_vi_update(void __iomem *chan_io,
+			  struct drm_gem_cma_object *gem,
+			  int layer,
+			  unsigned int fmt,
+			  u32 ui_sel,
+			  u32 size,
+			  u32 coord,
+			  struct drm_framebuffer *fb,
+			  u32 screen_size)
+{
+	int i;
+
+	writel_relaxed(VI_CFG_ATTR_en |
+			(fmt << VI_CFG_ATTR_fmt_SHIFT) |
+			ui_sel,
+			chan_io + VI_CFGx_ATTR(layer));
+	writel_relaxed(size, chan_io + VI_CFGx_SIZE(layer));
+	writel_relaxed(coord, chan_io + VI_CFGx_COORD(layer));
+	for (i = 0; i < VI_N_PLANES; i++) {
+		writel_relaxed(fb->pitches[i] ? fb->pitches[i] :
+						fb->pitches[0],
+				chan_io + VI_CFGx_PITCHy(layer, i));
+		writel_relaxed(gem->paddr + fb->offsets[i],
+				chan_io + VI_CFGx_TOP_LADDRy(layer, i));
+	}
+	writel_relaxed(0xff000000, chan_io + VI_FCOLORx(layer));
+	if (layer == 0) {
+		writel_relaxed(screen_size,
+				chan_io + VI_OVL_SIZEx(0));
+	}
+}
+
+static void de2_ui_update(void __iomem *chan_io,
+			  struct drm_gem_cma_object *gem,
+			  int layer,
+			  unsigned int fmt,
+			  u32 alpha_glob,
+			  u32 size,
+			  u32 coord,
+			  struct drm_framebuffer *fb,
+			  u32 screen_size)
+{
+	writel_relaxed(UI_CFG_ATTR_en |
+			(fmt << UI_CFG_ATTR_fmt_SHIFT) |
+			alpha_glob,
+			chan_io + UI_CFGx_ATTR(layer));
+	writel_relaxed(size, chan_io + UI_CFGx_SIZE(layer));
+	writel_relaxed(coord, chan_io + UI_CFGx_COORD(layer));
+	writel_relaxed(fb->pitches[0], chan_io + UI_CFGx_PITCH(layer));
+	writel_relaxed(gem->paddr + fb->offsets[0],
+			chan_io + UI_CFGx_TOP_LADDR(layer));
+	if (layer == 0)
+		writel_relaxed(screen_size, chan_io + UI_OVL_SIZE);
+}
+
+static void de2_plane_update(struct priv *priv, struct lcd *lcd,
+				int plane_num,
+				struct drm_plane_state *state,
+				struct drm_plane_state *old_state)
+{
+	void __iomem *mixer_io = priv->mmio;
+	void __iomem *chan_io;
+	struct drm_framebuffer *fb = state->fb;
+	struct drm_gem_cma_object *gem;
+	u32 size = WH(state->crtc_w, state->crtc_h);
+	u32 coord, screen_size;
+	u32 fcolor;
+	u32 ui_sel, alpha_glob;
+	int mixer = lcd->mixer;
+	int chan, layer, x, y;
+	unsigned int fmt;
+
+	chan = plane_tb[plane_num].chan;
+	layer = plane_tb[plane_num].layer;
+
+	mixer_io += (mixer == 0) ? DE2_MIXER0_BASE : DE2_MIXER1_BASE;
+	chan_io = mixer_io + MIXER_CHAN_REGS + MIXER_CHAN_SZ * chan;
+
+	x = state->crtc_x >= 0 ? state->crtc_x : 0;
+	y = state->crtc_y >= 0 ? state->crtc_y : 0;
+	coord = XY(x, y);
+
+	/* if plane update was delayed, force a full update */
+	if (priv->lcds[drm_crtc_index(&lcd->crtc)]->delayed &
+			(1 << plane_num)) {
+		priv->lcds[drm_crtc_index(&lcd->crtc)]->delayed &=
+							~(1 << plane_num);
+
+	/* handle plane move */
+	} else if (fb == old_state->fb) {
+		de2_mixer_select(priv, mixer, mixer_io);
+		if (chan == 0)
+			writel_relaxed(coord, chan_io + VI_CFGx_COORD(layer));
+		else
+			writel_relaxed(coord, chan_io + UI_CFGx_COORD(layer));
+		return;
+	}
+
+	gem = drm_fb_cma_get_gem_obj(fb, 0);
+
+	ui_sel = alpha_glob = 0;
+
+	switch (fb->pixel_format) {
+	case DRM_FORMAT_ARGB8888:
+		fmt = DE2_FORMAT_ARGB_8888;
+		ui_sel = VI_CFG_ATTR_ui_sel;
+		break;
+	case DRM_FORMAT_BGRA8888:
+		fmt = DE2_FORMAT_BGRA_8888;
+		ui_sel = VI_CFG_ATTR_ui_sel;
+		break;
+	case DRM_FORMAT_XRGB8888:
+		fmt = DE2_FORMAT_XRGB_8888;
+		ui_sel = VI_CFG_ATTR_ui_sel;
+		alpha_glob = (1 << UI_CFG_ATTR_alpmod_SHIFT) |
+				(0xff << UI_CFG_ATTR_alpha_SHIFT);
+		break;
+	case DRM_FORMAT_RGB888:
+		fmt = DE2_FORMAT_RGB_888;
+		ui_sel = VI_CFG_ATTR_ui_sel;
+		break;
+	case DRM_FORMAT_BGR888:
+		fmt = DE2_FORMAT_BGR_888;
+		ui_sel = VI_CFG_ATTR_ui_sel;
+		break;
+	case DRM_FORMAT_YUYV:
+		fmt = DE2_FORMAT_YUV422_I_YUYV;
+		break;
+	case DRM_FORMAT_YVYU:
+		fmt = DE2_FORMAT_YUV422_I_YVYU;
+		break;
+	case DRM_FORMAT_YUV422:
+		fmt = DE2_FORMAT_YUV422_P;
+		break;
+	case DRM_FORMAT_YUV420:
+		fmt = DE2_FORMAT_YUV420_P;
+		break;
+	case DRM_FORMAT_UYVY:
+		fmt = DE2_FORMAT_YUV422_I_UYVY;
+		break;
+	default:
+		pr_err("de2_plane_update: format %.4s not yet treated\n",
+			(char *) &fb->pixel_format);
+		return;
+	}
+
+	/* the overlay size is the one of the primary plane */
+	screen_size = plane_num == DE2_PRIMARY_PLANE ?
+		size :
+		readl_relaxed(mixer_io + MIXER_GLB_REGS + MIXER_GLB_SIZE_REG);
+
+	/* prepare pipe enable */
+	fcolor = readl_relaxed(mixer_io + MIXER_BLD_REGS +
+				MIXER_BLD_FCOLOR_CTL_REG);
+	fcolor |= MIXER_BLD_FCOLOR_CTL_PEN(plane_tb[plane_num].pipe);
+
+	de2_mixer_select(priv, mixer, mixer_io);
+
+	if (chan == 0)				/* VI channel */
+		de2_vi_update(chan_io, gem, layer, fmt, ui_sel, size, coord,
+				fb, screen_size);
+	else					/* UI channel */
+		de2_ui_update(chan_io, gem, layer, fmt, alpha_glob, size, coord,
+				fb, screen_size);
+	writel_relaxed(fcolor, mixer_io + MIXER_BLD_REGS +
+				MIXER_BLD_FCOLOR_CTL_REG);
+}
+
+static int vi_nb_layers(void __iomem *chan_io)
+{
+	int layer, n = 0;
+
+	for (layer = 0; layer < 4; layer++) {
+		if (readl_relaxed(chan_io + VI_CFGx_ATTR(layer)) != 0)
+			n++;
+	}
+
+	return n;
+}
+
+static int ui_nb_layers(void __iomem *chan_io)
+{
+	int layer, n = 0;
+
+	for (layer = 0; layer < 4; layer++) {
+		if (readl_relaxed(chan_io + UI_CFGx_ATTR(layer)) != 0)
+			n++;
+	}
+
+	return n;
+}
+
+static void de2_plane_disable(struct priv *priv,
+				int mixer, int plane_num)
+{
+	void __iomem *mixer_io = priv->mmio;
+	void __iomem *chan_io;
+	u32 fcolor;
+	int chan, layer, n;
+
+	chan = plane_tb[plane_num].chan;
+	layer = plane_tb[plane_num].layer;
+
+	mixer_io += (mixer == 0) ? DE2_MIXER0_BASE : DE2_MIXER1_BASE;
+	chan_io = mixer_io + MIXER_CHAN_REGS + MIXER_CHAN_SZ * chan;
+
+	if (chan == 0)
+		n = vi_nb_layers(chan_io);
+	else
+		n = ui_nb_layers(chan_io);
+
+	fcolor = readl_relaxed(mixer_io + MIXER_BLD_REGS +
+			MIXER_BLD_FCOLOR_CTL_REG);
+
+	de2_mixer_select(priv, mixer, mixer_io);
+
+	if (chan == 0)
+		writel_relaxed(0, chan_io + VI_CFGx_ATTR(layer));
+	else
+		writel_relaxed(0, chan_io + UI_CFGx_ATTR(layer));
+
+	/* disable the pipe if no more active layer */
+	if (n <= 1)
+		writel_relaxed(fcolor &
+			~MIXER_BLD_FCOLOR_CTL_PEN(plane_tb[plane_num].pipe),
+			mixer_io + MIXER_BLD_REGS + MIXER_BLD_FCOLOR_CTL_REG);
+}
+
+static void de2_drm_plane_update(struct drm_plane *plane,
+				struct drm_plane_state *old_state)
+{
+	struct drm_plane_state *state = plane->state;
+	struct drm_crtc *crtc = state->crtc;
+	struct lcd *lcd = crtc_to_lcd(crtc);
+	struct priv *priv = lcd->priv;
+	int plane_num = plane - lcd->planes;
+
+	/* if the crtc is disabled, mark update delayed */
+	if (!(priv->started & (1 << lcd->mixer))) {
+		lcd->delayed |= 1 << plane_num;
+		return;				/* mixer disabled */
+	}
+
+	mutex_lock(&priv->mutex);
+
+	de2_plane_update(priv, lcd, plane_num, state, old_state);
+
+	mutex_unlock(&priv->mutex);
+}
+
+static void de2_drm_plane_disable(struct drm_plane *plane,
+				struct drm_plane_state *old_state)
+{
+	struct drm_crtc *crtc = old_state->crtc;
+	struct lcd *lcd = crtc_to_lcd(crtc);
+	struct priv *priv = lcd->priv;
+	int plane_num = plane - lcd->planes;
+
+	if (!(priv->started & (1 << lcd->mixer)))
+		return;				/* mixer disabled */
+
+	mutex_lock(&priv->mutex);
+
+	de2_plane_disable(lcd->priv, lcd->mixer, plane_num);
+
+	mutex_unlock(&priv->mutex);
+}
+
+static const struct drm_plane_helper_funcs plane_helper_funcs = {
+	.atomic_update = de2_drm_plane_update,
+	.atomic_disable = de2_drm_plane_disable,
+};
+
+static const struct drm_plane_funcs plane_funcs = {
+	.update_plane = drm_atomic_helper_update_plane,
+	.disable_plane = drm_atomic_helper_disable_plane,
+	.destroy = drm_plane_cleanup,
+	.reset = drm_atomic_helper_plane_reset,
+	.atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
+	.atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
+};
+
+static int de2_one_plane_init(struct drm_device *drm,
+				struct drm_plane *plane,
+				int possible_crtcs,
+				int plane_num)
+{
+	int ret;
+
+	ret = drm_universal_plane_init(drm, plane, possible_crtcs,
+				&plane_funcs,
+				plane_tb[plane_num].formats,
+				plane_tb[plane_num].n_formats,
+				plane_tb[plane_num].type, NULL);
+	if (ret >= 0)
+		drm_plane_helper_add(plane, &plane_helper_funcs);
+
+	return ret;
+}
+
+/* initialize the planes */
+int de2_plane_init(struct drm_device *drm, struct lcd *lcd)
+{
+	int i, n, ret, possible_crtcs = 1 << drm_crtc_index(&lcd->crtc);
+
+	n = ARRAY_SIZE(plane_tb);
+	if (n != DE2_N_PLANES) {
+		dev_err(lcd->dev, "Bug: incorrect number of planes %d != "
+			__stringify(DE2_N_PLANES) "\n", n);
+		return -EINVAL;
+	}
+
+	for (i = 0; i < n; i++) {
+		ret = de2_one_plane_init(drm, &lcd->planes[i],
+				possible_crtcs, i);
+		if (ret < 0) {
+			dev_err(lcd->dev, "plane init failed %d\n", ret);
+			break;
+		}
+	}
+
+	return ret;
+}
-- 
2.10.2

^ permalink raw reply related

* [PATCH v9 05/11] arm/arm64: vgic: Introduce VENG0 and VENG1 fields to vmcr struct
From: Christoffer Dall @ 2016-11-28 14:28 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1479906118-15832-6-git-send-email-vijay.kilari@gmail.com>

On Wed, Nov 23, 2016 at 06:31:52PM +0530, vijay.kilari at gmail.com wrote:
> From: Vijaya Kumar K <Vijaya.Kumar@cavium.com>
> 
> ICC_VMCR_EL2 supports virtual access to ICC_IGRPEN1_EL1.Enable
> and ICC_IGRPEN0_EL1.Enable fields. Add grpen0 and grpen1 member
> variables to struct vmcr to support read and write of these fields.
> 
> Also refactor vgic_set_vmcr and vgic_get_vmcr() code.
> Drop ICH_VMCR_CTLR_SHIFT and ICH_VMCR_CTLR_MASK macros and instead
> use ICH_VMCR_EOI* and ICH_VMCR_CBPR* macros
> .
> Signed-off-by: Vijaya Kumar K <Vijaya.Kumar@cavium.com>
> ---
>  include/linux/irqchip/arm-gic-v3.h |  2 --
>  virt/kvm/arm/vgic/vgic-mmio-v2.c   | 16 ----------------
>  virt/kvm/arm/vgic/vgic-mmio.c      | 16 ++++++++++++++++
>  virt/kvm/arm/vgic/vgic-v3.c        | 22 ++++++++++++++++++++--
>  virt/kvm/arm/vgic/vgic.h           |  5 +++++
>  5 files changed, 41 insertions(+), 20 deletions(-)
> 
> diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
> index b4f8287..406fc3e 100644
> --- a/include/linux/irqchip/arm-gic-v3.h
> +++ b/include/linux/irqchip/arm-gic-v3.h
> @@ -404,8 +404,6 @@
>  #define ICH_HCR_EN			(1 << 0)
>  #define ICH_HCR_UIE			(1 << 1)
>  
> -#define ICH_VMCR_CTLR_SHIFT		0
> -#define ICH_VMCR_CTLR_MASK		(0x21f << ICH_VMCR_CTLR_SHIFT)
>  #define ICH_VMCR_CBPR_SHIFT		4
>  #define ICH_VMCR_CBPR_MASK		(1 << ICH_VMCR_CBPR_SHIFT)
>  #define ICH_VMCR_EOIM_SHIFT		9
> diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
> index 2cb04b7..ad353b5 100644
> --- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
> +++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
> @@ -212,22 +212,6 @@ static void vgic_mmio_write_sgipends(struct kvm_vcpu *vcpu,
>  	}
>  }
>  
> -static void vgic_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr)
> -{
> -	if (kvm_vgic_global_state.type == VGIC_V2)
> -		vgic_v2_set_vmcr(vcpu, vmcr);
> -	else
> -		vgic_v3_set_vmcr(vcpu, vmcr);
> -}
> -
> -static void vgic_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr)
> -{
> -	if (kvm_vgic_global_state.type == VGIC_V2)
> -		vgic_v2_get_vmcr(vcpu, vmcr);
> -	else
> -		vgic_v3_get_vmcr(vcpu, vmcr);
> -}
> -
>  #define GICC_ARCH_VERSION_V2	0x2
>  
>  /* These are for userland accesses only, there is no guest-facing emulation. */
> diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c
> index 0d1bc98..f81e0e5 100644
> --- a/virt/kvm/arm/vgic/vgic-mmio.c
> +++ b/virt/kvm/arm/vgic/vgic-mmio.c
> @@ -416,6 +416,22 @@ int vgic_validate_mmio_region_addr(struct kvm_device *dev,
>  	return -ENXIO;
>  }
>  
> +void vgic_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr)
> +{
> +	if (kvm_vgic_global_state.type == VGIC_V2)
> +		vgic_v2_set_vmcr(vcpu, vmcr);
> +	else
> +		vgic_v3_set_vmcr(vcpu, vmcr);
> +}
> +
> +void vgic_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr)
> +{
> +	if (kvm_vgic_global_state.type == VGIC_V2)
> +		vgic_v2_get_vmcr(vcpu, vmcr);
> +	else
> +		vgic_v3_get_vmcr(vcpu, vmcr);
> +}
> +
>  /*
>   * kvm_mmio_read_buf() returns a value in a format where it can be converted
>   * to a byte array and be directly observed as the guest wanted it to appear
> diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
> index 9f0dae3..a3ff04b 100644
> --- a/virt/kvm/arm/vgic/vgic-v3.c
> +++ b/virt/kvm/arm/vgic/vgic-v3.c
> @@ -175,10 +175,19 @@ void vgic_v3_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp)
>  {
>  	u32 vmcr;
>  
> -	vmcr  = (vmcrp->ctlr << ICH_VMCR_CTLR_SHIFT) & ICH_VMCR_CTLR_MASK;
> +	/*
> +	 * Ignore the FIQen bit, because GIC emulation always implies
> +	 * SRE=1 which means the vFIQEn bit is also RES1.
> +	 */
> +	vmcr = (vmcrp->ctlr & ICC_CTLR_EL1_EOImode_MASK) >>
> +		ICC_CTLR_EL1_EOImode_SHIFT;
> +	vmcr = (vmcr << ICH_VMCR_EOIM_SHIFT) & ICH_VMCR_EOIM_MASK;

Nit: I think this can be written more nicely as:
	vmcr = ((vmcrp->ctlr >> ICC_CTLR_EL1_EOImode_SHIFT)
		<< ICH_VMCR_EOIM_SHIFT) & ICH_VMCR_EOIM_MASK;

> +	vmcr |= (vmcrp->ctlr << ICH_VMCR_CBPR_SHIFT) & ICH_VMCR_CBPR_MASK;
>  	vmcr |= (vmcrp->abpr << ICH_VMCR_BPR1_SHIFT) & ICH_VMCR_BPR1_MASK;
>  	vmcr |= (vmcrp->bpr << ICH_VMCR_BPR0_SHIFT) & ICH_VMCR_BPR0_MASK;
>  	vmcr |= (vmcrp->pmr << ICH_VMCR_PMR_SHIFT) & ICH_VMCR_PMR_MASK;
> +	vmcr |= (vmcrp->grpen0 << ICH_VMCR_ENG0_SHIFT) & ICH_VMCR_ENG0_MASK;
> +	vmcr |= (vmcrp->grpen1 << ICH_VMCR_ENG1_SHIFT) & ICH_VMCR_ENG1_MASK;
>  
>  	vcpu->arch.vgic_cpu.vgic_v3.vgic_vmcr = vmcr;
>  }
> @@ -187,10 +196,19 @@ void vgic_v3_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp)
>  {
>  	u32 vmcr = vcpu->arch.vgic_cpu.vgic_v3.vgic_vmcr;
>  
> -	vmcrp->ctlr = (vmcr & ICH_VMCR_CTLR_MASK) >> ICH_VMCR_CTLR_SHIFT;
> +	/*
> +	 * Ignore the FIQen bit, because GIC emulation always implies
> +	 * SRE=1 which means the vFIQEn bit is also RES1.
> +	 */
> +	vmcrp->ctlr = (vmcr & ICH_VMCR_EOIM_MASK) >> ICH_VMCR_EOIM_SHIFT;
> +	vmcrp->ctlr = (vmcrp->ctlr << ICC_CTLR_EL1_EOImode_SHIFT) &
> +		       ICC_CTLR_EL1_EOImode_MASK;

similarly, this could be written as:
	vmcrp->ctlr = ((vmcr >> ICH_VMCR_EOIM_SHIFT) <<
			ICC_CTLR_EL1_EOImode_SHIFT) & ICC_CTLR_EL1_EOImode_MASK;

> +	vmcrp->ctlr |= (vmcr & ICH_VMCR_CBPR_MASK) >> ICH_VMCR_CBPR_SHIFT;
>  	vmcrp->abpr = (vmcr & ICH_VMCR_BPR1_MASK) >> ICH_VMCR_BPR1_SHIFT;
>  	vmcrp->bpr  = (vmcr & ICH_VMCR_BPR0_MASK) >> ICH_VMCR_BPR0_SHIFT;
>  	vmcrp->pmr  = (vmcr & ICH_VMCR_PMR_MASK) >> ICH_VMCR_PMR_SHIFT;
> +	vmcrp->grpen0 = (vmcr & ICH_VMCR_ENG0_MASK) >> ICH_VMCR_ENG0_SHIFT;
> +	vmcrp->grpen1 = (vmcr & ICH_VMCR_ENG1_MASK) >> ICH_VMCR_ENG1_SHIFT;
>  }
>  
>  #define INITIAL_PENDBASER_VALUE						  \
> diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
> index 91f58b2..9232791 100644
> --- a/virt/kvm/arm/vgic/vgic.h
> +++ b/virt/kvm/arm/vgic/vgic.h
> @@ -78,6 +78,9 @@ struct vgic_vmcr {
>  	u32	abpr;
>  	u32	bpr;
>  	u32	pmr;
> +	/* Below member variable are valid only for GICv3 */
> +	u32	grpen0;
> +	u32	grpen1;
>  };
>  
>  struct vgic_irq *vgic_get_irq(struct kvm *kvm, struct kvm_vcpu *vcpu,
> @@ -138,6 +141,8 @@ int vgic_v3_dist_uaccess(struct kvm_vcpu *vcpu, bool is_write,
>  int vgic_v3_redist_uaccess(struct kvm_vcpu *vcpu, bool is_write,
>  			 int offset, u32 *val);
>  int kvm_register_vgic_device(unsigned long type);
> +void vgic_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
> +void vgic_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
>  int vgic_lazy_init(struct kvm *kvm);
>  int vgic_init(struct kvm *kvm);
>  
> -- 
> 1.9.1
> 
My comments on style above notwithstanding:

Reviewed-by: Christoffer Dall <christoffer.dall@linaro.org>

^ permalink raw reply

* [PATCH 0/5] Meson GXL and GXM USB support
From: Neil Armstrong @ 2016-11-28 14:30 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161126145635.24488-1-martin.blumenstingl@googlemail.com>

On 11/26/2016 03:56 PM, Martin Blumenstingl wrote:
> USB support on GXL and GXM differs a lot from Meson8b and GXBB:
> The most obvious change is that GXL and GXM now have one dwc3
> controller and one dwc2 controller (instead of two dwc2 controllers).
> With that there are also new USB PHYs.
> 
> Due to lack of hardware I was only able to test this on a board with
> GXM, but as far as I understand the hardware my preparations should be
> correct (so it should also work on GXL).
> 
> dwc2 will probably stay unused on most GXM devices since it's limited
> to device mode via some dwc2 hardware configuration register.
> 
> dwc3 is probably used on all devices, even if there is more than just
> one USB port. dwc3 has a built-in USB2 hub - on GXL this hub has two
> ports enabled, while on GXM there are three ports enabled (see below
> for lsusb output). There are no USB3 ports enabled in the dwc3 hardware
> configuration, meaning that the SoC is limited to high-speed mode.
> On my GXM device the dwc3 hardware configuration forces it into "host
> only" mode.
> 
> The SoCs contain two PHY blocks: one USB3 PHY and up to four USB2 PHYs
> (on GXM there are only three enabled, but the registers should support
> up to four).
> The USB3 PHY also handles the OTG interrupts, but since dwc3's hardware
> configuration enforces "host only" mode I was not able to test this. It
> simply takes care of an interrupt and then notifies all related PHYs
> about the new mode.
> The USB2 PHY block is a bit different: I created one PHY driver which
> spans all "PHY ports" because the handling is a bit tricky. It turns
> out that for each available USB port in dwc3's hub the corresponding
> PHY must be enabled (even if there is no physical port - in my case
> port 3 is not connected to anything, but disabling the PHY breaks
> ports 1 and 2 as well).
> I decided not not pass the USB2 PHYs directly to dwc3 due to three
> reasons: 1. the USB3 PHY (which holds a reference to all relevant
> USB2 PHY ports) controls the mode of the USB2 PHY ports (since both
> are used with the same controller and thus it makes sense to keep the
> mode consistent across all ports) 2. the dwc3 driver does not support
> passing multiple USB2 PHYs (only one USB2 and one USB3 PHY can be
> passed to it) 3. it is similar to how the vendor reference driver
> manages the PHYs. Please note that this coupling is not a fixed, this
> is all configurable via devicetree (so if the third USB2 PHY has to
> be passed two the dwc2 controller then this is still possible by
> just moving on PHY reference in the .dts).
> 
> The coupling of the USB2 and USB3 PHYs is the reason why I sent the
> two drivers in one patch, even though they are handling different IP
> blocks (different registers, etc.).
> 
> Unfortunately there are no datasheets available for any of these PHYs.
> Both drivers were written by reading the reference drivers provided by
> Amlogic and analyzing the registers on the kernel that was shipped with
> my board.
> 
> As a last note: the dwc3 driver currently only explicitly enables the
> first USB port "DWC3_GUSB2PHYCFG(0)" in the internal hub. The hardware
> seems to enable the other two (DWC3_GUSB2PHYCFG(1) and
> DWC3_GUSB2PHYCFG(2)) automatically. I will ask the dwc3 maintainers if
> changes to dwc3 are desired any how these should look like, but for now
> it's working fine even without changes there.
> 
> lsusb output on GXM for the dwc3 hub:
> Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
> ...
>  Hub Port Status:
>    Port 1: 0000.0100 power
>    Port 2: 0000.0100 power
>    Port 3: 0000.0100 power
> 
> NOTE: The devicetree changes depend on my previous series:
> "[PATCH 0/2] minor GXL and GXM improvements" - see [0]
> 
> NOTE2: This series depends on an upstream dwc3/xhci-plat DMA fix
> (special thanks to Arnd Bergmann and Sriram Dash for fixing that):
> "[PATCH v5 0/6] inherit dma configuration from parent dev" - see [1]
> 
> I have a tree with all dependencies applied available at [2] if
> someone wants a quick way to test this (I don't take any responsibility
> if anything explodes though).
> 
> [0] http://lists.infradead.org/pipermail/linux-amlogic/2016-November/001665.html
> [1] http://marc.info/?l=linux-usb&m=147938307209685&w=2
> [2] https://github.com/xdarklight/linux/commits/meson-gx-integration-4.10-20161126
> 
> Martin Blumenstingl (5):
>   Documentation: dt-bindings: Add documentation for Meson GXL USB2/3
>     PHYs
>   phy: meson: add USB2 and USB3 PHY support for Meson GXL
>   arm64: dts: meson-gxl: add USB support
>   ARM64: dts: meson-gxm: add GXM specific USB configuration
>   ARM64: dts: meson-gx-p23x-q20x: enable USB on P23x and Q20x boards
> 
>  .../devicetree/bindings/phy/meson-gxl-usb2-phy.txt |  25 ++
>  .../devicetree/bindings/phy/meson-gxl-usb3-phy.txt |  27 ++
>  .../arm64/boot/dts/amlogic/meson-gx-p23x-q20x.dtsi |  12 +
>  arch/arm64/boot/dts/amlogic/meson-gxl.dtsi         |  49 +++
>  .../arm64/boot/dts/amlogic/meson-gxm-s912-q200.dts |  17 +
>  arch/arm64/boot/dts/amlogic/meson-gxm.dtsi         |  10 +
>  drivers/phy/Kconfig                                |  13 +
>  drivers/phy/Makefile                               |   2 +
>  drivers/phy/phy-meson-gxl-usb2.c                   | 374 ++++++++++++++++++++
>  drivers/phy/phy-meson-gxl-usb3.c                   | 377 +++++++++++++++++++++
>  10 files changed, 906 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/phy/meson-gxl-usb2-phy.txt
>  create mode 100644 Documentation/devicetree/bindings/phy/meson-gxl-usb3-phy.txt
>  create mode 100644 drivers/phy/phy-meson-gxl-usb2.c
>  create mode 100644 drivers/phy/phy-meson-gxl-usb3.c
> 

With the patchset in [1], tested successfully on a Nexbox A1.

On my Amlogic P230, the two USB-A ports works, the USB-OTG port work in Host mode, but does nothing connected as peripheral.
When trying to enable the DWC2 in peripheral mode, it fails by :
[   11.609586] dwc2 c9100000.usb: dwc2_core_reset() HANG! Soft Reset GRSTCTL=80000001
[   11.616962] dwc2 c9100000.usb: Specified GNPTXFDEP=1024 > 768
[   11.622643] dwc2 c9100000.usb: EPs: 7, dedicated fifos, 712 entries in SPRAM

Tested-by: Neil Armstrong <narmstrong@baylibre.com>

^ permalink raw reply

* [PATCHv2 00/11] Implement clocksource for rockchip SoC using rockchip timer
From: Alexander Kochetkov @ 2016-11-28 14:31 UTC (permalink / raw)
  To: linux-arm-kernel

Hello,

This patch series contain:
- devicetree bindings clarification for rockchip timers
- dts files fixes for rk3228-evb, rk3229-evb and rk3188
- implementation of clocksource for rockchip SoC

The clock supplying the arm-global-timer on the rk3188 is coming from the
the cpu clock itself and thus changes its rate everytime cpufreq adjusts
the cpu frequency making this timer unsuitable as a stable clocksource.
    
The rk3188, rk3288 and following socs share a separate timer block already
handled by the rockchip-timer driver. Therefore adapt this driver to also
be able to act as clocksource on rk3188.
    
In order to test clocksource you can run following commands and check
how much time it take in real. On rk3188 it take about ~45 seconds.
Such error cannot be fixed using NTP. Haven't test clocksource
on rk3288 and onwards. Guess they can also have unstable clocksource.
    
        cpufreq-set -f 1.6GHZ
        date; sleep 60; date

Regards,
Alexander.

This is try 2. Please discard all previous patches:

devicetree:
https://patchwork.ozlabs.org/patch/699019/
https://patchwork.ozlabs.org/patch/699020/

kernel:
https://patchwork.kernel.org/patch/9443975/
https://patchwork.kernel.org/patch/9443971/
https://patchwork.kernel.org/patch/9443959/
https://patchwork.kernel.org/patch/9443963/
https://patchwork.kernel.org/patch/9443979/
https://patchwork.kernel.org/patch/9443989/
https://patchwork.kernel.org/patch/9443987/
https://patchwork.kernel.org/patch/9443977/
https://patchwork.kernel.org/patch/9443991/

Old thread:
http://lists.infradead.org/pipermail/linux-rockchip/2016-November/013147.html

Alexander Kochetkov (11):
  dt-bindings: clarify compatible property for rockchip timers
  ARM: dts: rockchip: update compatible property for rk3228 timer
  ARM: dts: rockchip: update compatible property for rk3229 timer
  ARM: dts: rockchip: add timer entries to rk3188 dtsi
  clocksource/drivers/rockchip_timer: split bc_timer into rk_timer and
    rk_clock_event_device
  clocksource/drivers/rockchip_timer: low level routines take rk_timer
    as parameter
  clocksource/drivers/rockchip_timer: drop unused rk_base() and
    rk_ctrl()
  clocksource/drivers/rockchip_timer: move TIMER_INT_UNMASK out of
    rk_timer_enable()
  clocksource/drivers/rockchip_timer: implement loading 64bit value
    into timer
  clocksource/drivers/rockchip_timer: implement reading 64bit value
    from timer
  clocksource/drivers/rockchip_timer: implement clocksource timer

 .../bindings/timer/rockchip,rk-timer.txt           |   12 +-
 arch/arm/boot/dts/rk3188.dtsi                      |   16 ++
 arch/arm/boot/dts/rk3228-evb.dts                   |    4 +
 arch/arm/boot/dts/rk3229-evb.dts                   |    4 +
 drivers/clocksource/rockchip_timer.c               |  202 +++++++++++++++-----
 5 files changed, 184 insertions(+), 54 deletions(-)

-- 
1.7.9.5

^ permalink raw reply

* [PATCHv2 01/11] dt-bindings: clarify compatible property for rockchip timers
From: Alexander Kochetkov @ 2016-11-28 14:31 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1480343486-25539-1-git-send-email-al.kochet@gmail.com>

Make all properties description in form '"rockchip,<chip>-timer",
"rockchip,rk3288-timer"' for all chips found in linux kernel.

Suggested-by: Heiko St?bner <heiko@sntech.de>
Signed-off-by: Alexander Kochetkov <al.kochet@gmail.com>
---
 .../bindings/timer/rockchip,rk-timer.txt           |   12 +++++++++---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/Documentation/devicetree/bindings/timer/rockchip,rk-timer.txt b/Documentation/devicetree/bindings/timer/rockchip,rk-timer.txt
index a41b184..16a5f45 100644
--- a/Documentation/devicetree/bindings/timer/rockchip,rk-timer.txt
+++ b/Documentation/devicetree/bindings/timer/rockchip,rk-timer.txt
@@ -1,9 +1,15 @@
 Rockchip rk timer
 
 Required properties:
-- compatible: shall be one of:
-  "rockchip,rk3288-timer" - for rk3066, rk3036, rk3188, rk322x, rk3288, rk3368
-  "rockchip,rk3399-timer" - for rk3399
+- compatible: should be:
+  "rockchip,rk3036-timer", "rockchip,rk3288-timer": for Rockchip RK3036
+  "rockchip,rk3066-timer", "rockchip,rk3288-timer": for Rockchip RK3066
+  "rockchip,rk3188-timer", "rockchip,rk3288-timer": for Rockchip RK3188
+  "rockchip,rk3228-timer", "rockchip,rk3288-timer": for Rockchip RK3228
+  "rockchip,rk3229-timer", "rockchip,rk3288-timer": for Rockchip RK3229
+  "rockchip,rk3288-timer": for Rockchip RK3288
+  "rockchip,rk3368-timer", "rockchip,rk3288-timer": for Rockchip RK3368
+  "rockchip,rk3399-timer": for Rockchip RK3399
 - reg: base address of the timer register starting with TIMERS CONTROL register
 - interrupts: should contain the interrupts for Timer0
 - clocks : must contain an entry for each entry in clock-names
-- 
1.7.9.5

^ permalink raw reply related

* [PATCHv2 02/11] ARM: dts: rockchip: update compatible property for rk3228 timer
From: Alexander Kochetkov @ 2016-11-28 14:31 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1480343486-25539-1-git-send-email-al.kochet@gmail.com>

Property set to '"rockchip,rk3228-timer", "rockchip,rk3288-timer"'
to match devicetree bindings.

Signed-off-by: Alexander Kochetkov <al.kochet@gmail.com>
---
 arch/arm/boot/dts/rk3228-evb.dts |    4 ++++
 1 file changed, 4 insertions(+)

diff --git a/arch/arm/boot/dts/rk3228-evb.dts b/arch/arm/boot/dts/rk3228-evb.dts
index 904668e..38eab87 100644
--- a/arch/arm/boot/dts/rk3228-evb.dts
+++ b/arch/arm/boot/dts/rk3228-evb.dts
@@ -70,3 +70,7 @@
 &uart2 {
 	status = "okay";
 };
+
+&timer {
+	compatible = "rockchip,rk3228-timer", "rockchip,rk3288-timer";
+};
-- 
1.7.9.5

^ permalink raw reply related


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